Releases: bueste/ioBroker.goodwe-sems
Release list
Release v1.0.11
Docs only, no functional changes.
Release v1.0.10
- Added contact email to copyright lines (README.md, LICENSE,
package.json author, io-package.json authors). - Bumped @iobroker/adapter-core, @iobroker/testing, and
@alcalzone/release-script-plugin-license to current recommended
versions. - Bumped ioBroker/testing-action-check to v2 (was v1, flagged W3028).
- Raised required admin version to >=7.8.23.
- Fixed a real bug in .github/dependabot.yml: the cooldown block used
the property name "default" instead of the correct "default-days".
GitHub Dependabot silently ignores unrecognised keys, so the
cooldown setting had zero effect despite being present in the file
since it was first added - confirmed against the official GitHub
Dependabot options reference. The two sibling adapters
(zeptrion, husqvarna-automower-connect) already had the correct
key; only this one had the typo. - Expanded the common.news translations for versions 1.0.3-1.0.9 (and
this 1.0.10 entry itself) in all 8 languages that were significantly
shorter than the English original into proper full translations,
verified via word-count ratio against English for every entry.
No functional code changes. 47 unit tests + 60 package-consistency
tests pass. Lockfile synced.
Release v1.0.9
_applyMonitorDetail() unconditionally created a top-level "Battery"
channel on every poll cycle, but it has held no states at all since
v1.0.8 moved battery data to per-inverter states
(Inverters..Battery.*). Reported by a tester after updating to
v1.0.8: an empty, orphaned "Battery" folder remained in the object
tree.
Stopped creating the channel, and added a startup migration
(_migrateRemoveEmptyBatteryChannel) that removes it from already-
running installations - but only after confirming via
getObjectListAsync() that it genuinely has no child objects, as a
safety check against removing anything unexpected.
47 unit tests + 57 package-consistency tests pass unchanged. Lockfile
synced.
Release v1.0.8
A tester (thanks!) reported missing battery data despite the SEMS portal
showing SOC/voltage/etc for their GW8K-ET + LX battery system, and
provided a HAR capture of the portal web UI to help diagnose it.
Confirmed via the raw gateway response (info.rawResponse): the
GetMonitorDetailByPowerstationId-equivalent gateway endpoint this
adapter uses never returns battery data at all, structurally, even
for battery-equipped plants - not a field-naming bug.
Reverse-engineered the alternative, undocumented API GoodWes own web
portal (semsplus.goodwe.com) uses instead, and verified every piece
against real captured browser traffic:
- cross-login: pwd = base64(md5(password)), matching an existing
_hashPasswordForNewLogin() helper already in this codebase - x-signature header: base64(sha256() +
"@" + ts) - verified byte-for-byte against two independent real
requests (login and an authenticated relatedDevices call) - device discovery: relatedDevices() per inverter returns any
attached BAT_SYS device with a separate "VD..."-prefixed ID
(stations/device/all-status, already used for inverter discovery,
does NOT surface battery devices) - battery data: BAT_SYS telemetry() returns soc/pBat/voltage/a/
batSysTemp/aMaxChar/aMaxDischar - verified 7/7 fields against the
testers own portal screenshot
New "Fetch battery data" instance option (off by default) enables
this second, independently-authenticated flow using the SAME SEMS
credentials already configured. Creates
Inverters..Battery.SOC/Power/Voltage/Current/Temperature/
MaxChargeCurrent/MaxDischargeCurrent per inverter with an attached
battery. Fully isolated in try/catch per inverter - a failure here
never affects core PV monitoring.
Also fixes the previous top-level Battery.SOC/Status states (always
empty - read from detail.soc.power, a field the gateway never
populated) and the per-inverter battery field guesses
(vbattery1/ibattery1/soc) that never matched any real API shape.
No migration needed: these states were never actually created due
to the bug (push() skips undefined values).
47 unit tests (2 new: battery on/off, 2 updated to the corrected
field names) + 57 package-consistency tests pass. Lockfile synced,
npm pack verified complete.
Release v1.0.7
value.gps is reserved for a combined longitude;latitude string
(e.g. 5.56;43.45 per the official state roles reference) and does
not support common.type number. Switched to value.gps.latitude /
value.gps.longitude, which are designed for separate numeric
coordinate values.
Added an explicit startup migration: these states are created via
setObjectNotExistsAsync (see _ensureState), which never updates an
existing object, so already-running installations would otherwise
keep the incompatible role forever.
Verified against a live object dump: both Station.Latitude and
Station.Longitude currently show role=value.gps and would be
corrected by the new migration.
Release v1.0.6
- Added "default": "en" to the notificationLanguage select in
admin/jsonConfig.json and a matching default in native config -
was blank on fresh installs, though the code already fell back to
English correctly (non-blocking finding). - Added pushoverUserKey to encryptedNative/protectedNative alongside
pushoverApiToken, consistent with how the API token is already
handled - the Pushover user key is personal account data and
warrants encryption at rest (must-fix finding).
No code changes needed: js-controller already auto-decrypts
encryptedNative fields into this.config at adapter startup (the same
mechanism pushoverApiToken already relies on), so existing plain-text
values from installations upgrading from <=1.0.5 are handled by the
standard js-controller encryption migration on the next config save.
Release v1.0.5
The checker text-scans source files for bare setTimeout()/setInterval()
calls (via a comment-stripped but NOT string-literal-stripped regex).
A log message explaining why the poll interval was capped happened to
contain the literal substring "setTimeout(" as plain English text
("Node.js setTimeout() would otherwise wrap..."), which matched the
same detection regex as real code.
Verified the actual codebase has zero bare setTimeout()/setInterval()
calls: the only real call (main.js _schedulePoll) already uses the
adapter-managed this.setTimeout(). Confirmed by running the checkers
exact regex (?<![.\w])setTimeout\s*( against every source file
after the fix - no matches anywhere.
Reworded the log message to remove the literal substring without
changing its meaning. No functional changes.
Release v1.0.4
The per-inverter AC_L1-3, PV1-4 and Battery sub-groups (e.g.
Inverters..AC_L1.Voltage) were only ever created as leaf states,
without the required intermediate channel object for the AC_L1/PV1/...
grouping level itself - 26 E3009 errors in the automated Object
Structure Check.
_applyMonitorDetail() now ensures a channel for each sub-group that
actually has at least one mapped state for that inverter, mirroring
the presence-driven pattern already used for the top-level EVCharger
channel.
No migration needed: these are new objects, not changed properties of
existing ones, and _applyMonitorDetail() runs on every poll cycle (not
just on first start), so already-running installations self-heal on
their very next poll after upgrading.
Verified against a live daytime API response with 2 inverters
(AC_L1-3 + PV1-2 populated for both): 0 missing intermediate objects,
was 26.
Release v1.0.3
Verified against a live daytime GetMonitorDetailByPowerstationId response:
the info object has no time field, and the kpi object only ever contains
pac/power/total_power - never month_generation/day_income/total_income/
currency. Station.PortalTimestamp and the KPI income/currency/month-
generation states are therefore permanently absent for every account,
regardless of time of day - not a symptom of an incomplete nighttime
dump, as previously assumed during review. Battery/PowerFlow states are
correctly created only when the portal actually reports that data
(e.g. no powerflow key at all for battery-less plants).
No code changes, README.md and README.de.md only.
Release v1.0.2
- 6 previously missed German log messages in lib/semsApi.js translated
(used this.log(level, message) call syntax instead of this.log.(),
which the earlier translation pass had not searched for) - second duplicate German SemsAuthError message translated
- _maskAccount() now always returns English "(not set)" (flows into an
English log line) - proper multi-language support for Pushover notification text: new
notificationLanguage config option (English/German, default English)
selects EN/DE templates for all 4 notification categories - hard ceiling (86400s) on the poll interval to prevent a setTimeout()
integer overflow if an extreme value were ever set outside the admin
UIs existing 60-3600s range - info.activePollInterval unit corrected from "s" to "sec" as required
by the value.interval role (the role itself, and value.battery for
Battery.SOC, are both officially documented and were not changed) - added an explicit startup migration for the unit fix, since js-controller
does not reliably re-sync instanceObjects common properties on adapter
update across all versions in the field
(see ioBroker/ioBroker.js-controller#769) - already-running installations
get corrected, not just fresh installs
No functional regressions. 45 unit tests + 57 package-consistency tests
pass unchanged, plus a standalone verification of the poll-interval
clamping logic against 7 boundary cases.