iobroker.goodwe-sems 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +6 -0
- package/README.md +6 -0
- package/io-package.json +14 -14
- package/lib/semsApi.js +24 -4
- package/package.json +1 -1
package/README.de.md
CHANGED
|
@@ -151,6 +151,12 @@ Pull Requests willkommen, insbesondere um zusätzliche, vom Portal gelieferte Fe
|
|
|
151
151
|
-->
|
|
152
152
|
### **WORK IN PROGRESS**
|
|
153
153
|
|
|
154
|
+
### 0.1.14 (2026-07-19)
|
|
155
|
+
|
|
156
|
+
- (Stefan Bühler) Fix: `GetMonitorDetailByPowerstationId` lieferte `404 Route Not Found` für Konten, deren SEMS+-Login abgelehnt wird (beobachtet: `code=C0602`) und die auf die Legacy-CrossLogin-API zurückfallen - dieses Backend stellt den Endpunkt unter dem `v2`-API-Pfad bereit, nicht `v3`. Root Cause gefunden anhand des Debug-Logs eines echten Kontos sowie der Referenzimplementierung [pygoodwe](https://github.com/yaleman/pygoodwe), deren rein-legacy-Client den `v2`-Pfad fest verdrahtet. `getMonitorDetail()` versucht jetzt zuerst `v3` und wiederholt bei erkanntem 404 automatisch einmal mit `v2` - beide Backend-Varianten funktionieren damit ohne jede Konfigurationsänderung durch den Nutzer
|
|
157
|
+
- (Stefan Bühler) Fix: Fehlermeldungen zeigen jetzt auch das `error_msg`-Feld der API an (wurde bisher stillschweigend verworfen, was selbst bei aussagekräftiger Fehlerbeschreibung in der Antwort nur zu einem nichtssagenden „unbekannter Fehler" führte)
|
|
158
|
+
- (Stefan Bühler) 2 neue Regressionstests (44 Unit-Tests gesamt) für den v3→v2-Fallback sowie den Fall, dass beide Pfade fehlschlagen
|
|
159
|
+
|
|
154
160
|
### 0.1.13 (2026-07-19)
|
|
155
161
|
|
|
156
162
|
- (Stefan Bühler) Diagnose: rohe JSON-Antwort jedes SEMS-API-Aufrufs wird jetzt auf Debug-Level geloggt, nicht mehr nur beim Monitor-Detail-Aufruf. Tests mit einem echten Konto zeigten eine Meldung `SEMS-API-Fehler: ... GetPowerStationIdByOwner ... unbekannter Fehler (code=undefined)` - die vom Adapter angenommene Erfolgs-/Fehler-Code-Konvention (`code: 0`/`"0"`/`"00000"`) wurde bisher nur gegen selbst geschriebene Testfixtures geprüft, nicht gegen diesen konkreten Endpunkt auf einem echten Konto. Dieses Logging ist der schnellste Weg, die tatsächliche Antwortstruktur zu sehen und den echten Fehler zu beheben, ohne dass Zugangsdaten von irgendjemandem benötigt werden
|
package/README.md
CHANGED
|
@@ -151,6 +151,12 @@ Pull requests are welcome, especially to add further fields delivered by the por
|
|
|
151
151
|
-->
|
|
152
152
|
### **WORK IN PROGRESS**
|
|
153
153
|
|
|
154
|
+
### 0.1.14 (2026-07-19)
|
|
155
|
+
|
|
156
|
+
- (Stefan Bühler) fix: `GetMonitorDetailByPowerstationId` returned `404 Route Not Found` for accounts whose SEMS+ login is rejected (observed: `code=C0602`) and that fall back to the legacy CrossLogin API - that backend serves the endpoint under the `v2` API path, not `v3`. Root cause found via a real account's debug log plus the community reference implementation [pygoodwe](https://github.com/yaleman/pygoodwe), whose legacy-only client hardcodes the `v2` path. `getMonitorDetail()` now tries `v3` first and automatically retries once with `v2` on a detected 404, so both backend variants work without any user-facing configuration change
|
|
157
|
+
- (Stefan Bühler) fix: error messages now also surface the API's `error_msg` field (previously silently dropped, resulting in an uninformative "unbekannter Fehler" even when the response body contained a clear error description)
|
|
158
|
+
- (Stefan Bühler) 2 new regression tests (44 unit tests in total) covering the v3→v2 fallback and the case where both paths fail
|
|
159
|
+
|
|
154
160
|
### 0.1.13 (2026-07-19)
|
|
155
161
|
|
|
156
162
|
- (Stefan Bühler) diagnostics: log the raw JSON envelope of every SEMS API call at debug level, not just the monitor-detail call. Real-account testing surfaced a `SEMS-API-Fehler: ... GetPowerStationIdByOwner ... unbekannter Fehler (code=undefined)` report - the success/error code convention this adapter assumes (`code: 0`/`"0"`/`"00000"`) was only ever validated against test fixtures, not this specific endpoint on a live account. This logging is the fastest way to see the actual response shape and fix the real bug without needing access to anyone's SEMS credentials
|
package/io-package.json
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "goodwe-sems",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.14",
|
|
5
5
|
"news": {
|
|
6
|
-
"0.1.6": {
|
|
7
|
-
"en": "security/quality audit: sanitize inverter serials used in state IDs, survive broken inverter array entries, validate server-provided API base URL (HTTPS + GoodWe domains only), fix scientific-notation number parsing, reject invalid portal timestamps, filter stations without id",
|
|
8
|
-
"de": "Sicherheits-/Qualitätsaudit: Wechselrichter-Seriennummern für State-IDs bereinigt, defekte Einträge im Inverter-Array abgefangen, vom Server gelieferte API-Basis-URL validiert (nur HTTPS + GoodWe-Domains), Zahlen-Parsing für Exponentialschreibweise korrigiert, ungültige Portal-Zeitstempel verworfen, Anlagen ohne ID gefiltert",
|
|
9
|
-
"ru": "аудит безопасности/качества: очистка серийных номеров инверторов в ID состояний, устойчивость к повреждённым записям, проверка базового URL API, исправлен разбор чисел, отклонение неверных меток времени",
|
|
10
|
-
"pt": "auditoria de segurança/qualidade: sanitização de números de série, tolerância a entradas corrompidas, validação da URL base da API, correção do parsing numérico, rejeição de timestamps inválidos",
|
|
11
|
-
"nl": "beveiligings-/kwaliteitsaudit: serienummers gesaneerd voor state-IDs, bestand tegen kapotte inverter-items, API-basis-URL gevalideerd, wetenschappelijke notatie gecorrigeerd, ongeldige tijdstempels afgewezen",
|
|
12
|
-
"fr": "audit sécurité/qualité : assainissement des numéros de série, tolérance aux entrées corrompues, validation de l URL de base de l API, correction de l analyse numérique, rejet des horodatages invalides",
|
|
13
|
-
"it": "audit di sicurezza/qualità: sanificazione dei numeri di serie, tolleranza a voci corrotte, validazione dell URL base API, correzione del parsing numerico, rifiuto di timestamp non validi",
|
|
14
|
-
"es": "auditoría de seguridad/calidad: saneamiento de números de serie, tolerancia a entradas corruptas, validación de la URL base de la API, corrección del análisis numérico, rechazo de marcas de tiempo inválidas",
|
|
15
|
-
"pl": "audyt bezpieczeństwa/jakości: sanityzacja numerów seryjnych, odporność na uszkodzone wpisy, walidacja bazowego URL API, poprawka parsowania liczb, odrzucanie nieprawidłowych znaczników czasu",
|
|
16
|
-
"uk": "аудит безпеки/якості: очищення серійних номерів, стійкість до пошкоджених записів, перевірка базової URL API, виправлення розбору чисел, відхилення недійсних міток часу",
|
|
17
|
-
"zh-cn": "安全/质量审计:清理用于状态ID的逆变器序列号、容忍损坏的数组条目、验证服务器提供的API基础URL、修复科学计数法解析、拒绝无效时间戳、过滤无ID电站"
|
|
18
|
-
},
|
|
19
6
|
"0.1.7": {
|
|
20
7
|
"en": "branding: replace placeholder icon with the official GoodWe logo (used with permission from GoodWe)",
|
|
21
8
|
"de": "Branding: Platzhalter-Icon durch das offizielle GoodWe-Logo ersetzt (mit Genehmigung von GoodWe verwendet)",
|
|
@@ -93,6 +80,19 @@
|
|
|
93
80
|
"pl": "diagnostyka: surowa odpowiedz JSON kazdego wywolania API SEMS jest teraz logowana na poziomie debug",
|
|
94
81
|
"uk": "діагностика: сирий JSON-вiдповiдь кожного виклику SEMS API тепер логується на рiвнi debug",
|
|
95
82
|
"zh-cn": "诊断:每次 SEMS API 调用的原始 JSON 响应现在都会在 debug 级别记录"
|
|
83
|
+
},
|
|
84
|
+
"0.1.14": {
|
|
85
|
+
"en": "fix: GetMonitorDetailByPowerstationId returned 404 (\"Route Not Found\") for accounts whose SEMS+ login is rejected and falls back to the legacy CrossLogin API - that backend uses the \"v2\" API path instead of \"v3\". The adapter now automatically retries with the v2 path on a detected 404, and error messages now surface the actual error_msg field instead of \"unbekannter Fehler\"",
|
|
86
|
+
"de": "Fix: GetMonitorDetailByPowerstationId lieferte 404 (\"Route Not Found\") fuer Konten, deren SEMS+-Login abgelehnt wird und die auf die Legacy-CrossLogin-API zurueckfallen - dieses Backend nutzt den \"v2\"-API-Pfad statt \"v3\". Der Adapter versucht bei erkanntem 404 jetzt automatisch den v2-Pfad, und Fehlermeldungen zeigen jetzt das tatsaechliche error_msg-Feld statt \"unbekannter Fehler\"",
|
|
87
|
+
"ru": "исправление: GetMonitorDetailByPowerstationId возвращал 404 для учётных записей с резервным входом через устаревший API - теперь используется путь v2",
|
|
88
|
+
"pt": "correcao: GetMonitorDetailByPowerstationId retornava 404 para contas com login de reserva na API legada - agora usa o caminho v2",
|
|
89
|
+
"nl": "fix: GetMonitorDetailByPowerstationId gaf 404 voor accounts met fallback-login op de legacy API - gebruikt nu het v2-pad",
|
|
90
|
+
"fr": "correction : GetMonitorDetailByPowerstationId renvoyait une 404 pour les comptes utilisant la connexion de secours a l'API historique - utilise desormais le chemin v2",
|
|
91
|
+
"it": "correzione: GetMonitorDetailByPowerstationId restituiva 404 per gli account con login di fallback sull'API legacy - ora usa il percorso v2",
|
|
92
|
+
"es": "correccion: GetMonitorDetailByPowerstationId devolvia 404 para cuentas con inicio de sesion de respaldo en la API heredada - ahora usa la ruta v2",
|
|
93
|
+
"pl": "poprawka: GetMonitorDetailByPowerstationId zwracal 404 dla kont z zapasowym logowaniem do starszego API - teraz uzywana jest sciezka v2",
|
|
94
|
+
"uk": "виправлення: GetMonitorDetailByPowerstationId повертав 404 для облікових записів із резервним входом через застарілий API - тепер використовується шлях v2",
|
|
95
|
+
"zh-cn": "修复:对于回退到旧版登录 API 的账户,GetMonitorDetailByPowerstationId 返回 404 - 现在改用 v2 路径"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
package/lib/semsApi.js
CHANGED
|
@@ -41,7 +41,16 @@ const NEW_LOGIN_FALLBACK_API = "https://eu-gateway.semsportal.com/web/sems";
|
|
|
41
41
|
const LEGACY_LOGIN_FALLBACK_API = "https://eu.semsportal.com/api";
|
|
42
42
|
|
|
43
43
|
const STATION_LIST_PATH = "/PowerStation/GetPowerStationIdByOwner";
|
|
44
|
-
|
|
44
|
+
// GoodWe backends have been observed to expose GetMonitorDetailByPowerstationId
|
|
45
|
+
// under different API versions depending on which login variant the account
|
|
46
|
+
// ends up using (confirmed against a real account whose SEMS+ login is
|
|
47
|
+
// rejected with code=C0602, falling back to the legacy CrossLogin API): the
|
|
48
|
+
// "v3" path works for SEMS+ sessions, but 404s ("Route Not Found") on a
|
|
49
|
+
// legacy-login session, which instead needs "v2" - matching the community
|
|
50
|
+
// reference implementation pygoodwe (github.com/yaleman/pygoodwe), whose
|
|
51
|
+
// legacy-only client hardcodes "v2/PowerStation/GetMonitorDetailByPowerstationId".
|
|
52
|
+
const MONITOR_DETAIL_PATH_V3 = "/v3/PowerStation/GetMonitorDetailByPowerstationId";
|
|
53
|
+
const MONITOR_DETAIL_PATH_V2 = "/v2/PowerStation/GetMonitorDetailByPowerstationId";
|
|
45
54
|
|
|
46
55
|
// Observed rate-limit response code. GoodWe does not document a retry-after
|
|
47
56
|
// value, community projects settled on a 5 minute cool-down.
|
|
@@ -228,7 +237,7 @@ class SemsApi {
|
|
|
228
237
|
_extractSession(json, fallbackApi, variantName) {
|
|
229
238
|
const code = json && json.code;
|
|
230
239
|
if (!SUCCESS_CODES.has(code) && !(json && SUCCESS_MESSAGES.has(String(json.msg).toLowerCase()))) {
|
|
231
|
-
const msg = (json && (json.msg || json.message)) || "unbekannter Fehler";
|
|
240
|
+
const msg = (json && (json.msg || json.message || json.error_msg)) || "unbekannter Fehler";
|
|
232
241
|
throw new SemsAuthError(`SEMS-${variantName}-Login abgelehnt: ${msg} (code=${code})`);
|
|
233
242
|
}
|
|
234
243
|
|
|
@@ -337,7 +346,7 @@ class SemsApi {
|
|
|
337
346
|
}
|
|
338
347
|
|
|
339
348
|
if (!SUCCESS_CODES.has(code) && !(json && SUCCESS_MESSAGES.has(String(json.msg).toLowerCase()))) {
|
|
340
|
-
const msg = (json && (json.msg || json.message)) || "unbekannter Fehler";
|
|
349
|
+
const msg = (json && (json.msg || json.message || json.error_msg)) || "unbekannter Fehler";
|
|
341
350
|
throw new SemsProtocolError(`SEMS-API-Aufruf ${path} fehlgeschlagen: ${msg} (code=${code})`);
|
|
342
351
|
}
|
|
343
352
|
|
|
@@ -383,7 +392,18 @@ class SemsApi {
|
|
|
383
392
|
if (!powerStationId) {
|
|
384
393
|
throw new SemsProtocolError("getMonitorDetail() ohne powerStationId aufgerufen.");
|
|
385
394
|
}
|
|
386
|
-
|
|
395
|
+
try {
|
|
396
|
+
return await this._authenticatedPost(MONITOR_DETAIL_PATH_V3, { powerStationId });
|
|
397
|
+
} catch (error) {
|
|
398
|
+
if (error instanceof SemsProtocolError && /404|route not found/i.test(error.message)) {
|
|
399
|
+
this.log(
|
|
400
|
+
"debug",
|
|
401
|
+
`${MONITOR_DETAIL_PATH_V3} nicht gefunden (404) - versuche ${MONITOR_DETAIL_PATH_V2} als Fallback (vermutlich Legacy-API-Backend).`,
|
|
402
|
+
);
|
|
403
|
+
return this._authenticatedPost(MONITOR_DETAIL_PATH_V2, { powerStationId });
|
|
404
|
+
}
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
387
407
|
}
|
|
388
408
|
}
|
|
389
409
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.goodwe-sems",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "ioBroker adapter to read GoodWe inverter data from the SEMS Portal cloud API (for installations without local/LAN access to the inverter).",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "bueste",
|