iobroker.goodwe-sems 0.1.13 → 0.1.15

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 CHANGED
@@ -151,6 +151,18 @@ Pull Requests willkommen, insbesondere um zusätzliche, vom Portal gelieferte Fe
151
151
  -->
152
152
  ### **WORK IN PROGRESS**
153
153
 
154
+ ### 0.1.15 (2026-07-19)
155
+
156
+ - (Stefan Bühler) Fix: Der v3→v2-Fallback aus 0.1.14 für `GetMonitorDetailByPowerstationId` reichte nicht aus - bei einem echten Konto lieferte das Legacy-Login-Backend `404 Route Not Found` für **beide** Pfade, `v2` und `v3`. Community-Referenzen widersprechen sich, welche Version korrekt ist (pygoodwe verwendet fest `v2`, ein separater Artikel von 2023 nutzt `v1`, unsere eigene Traffic-Analyse beobachtete `v3`) - `getMonitorDetail()` probiert jetzt alle drei Versionen der Reihe nach durch (`v3` → `v2` → `v1`) und nutzt die erste, die keinen 404 liefert
157
+ - (Stefan Bühler) Diagnose: Debug-Logs enthalten jetzt die vollständige Request-URL (inkl. aufgelöster API-Basis) statt nur des relativen Pfads, und der Login-Erfolgs-Log gibt jetzt ebenfalls die aufgelöste API-Basis aus - so lässt sich genau erkennen, welche Host+Pfad-Kombination fehlschlägt
158
+ - (Stefan Bühler) 2 aktualisierte/neue Regressionstests (45 Unit-Tests insgesamt) für den dreistufigen Versions-Fallback und den Fall, dass alle drei Pfade fehlschlagen
159
+
160
+ ### 0.1.14 (2026-07-19)
161
+
162
+ - (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
163
+ - (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)
164
+ - (Stefan Bühler) 2 neue Regressionstests (44 Unit-Tests gesamt) für den v3→v2-Fallback sowie den Fall, dass beide Pfade fehlschlagen
165
+
154
166
  ### 0.1.13 (2026-07-19)
155
167
 
156
168
  - (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,18 @@ 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.15 (2026-07-19)
155
+
156
+ - (Stefan Bühler) fix: 0.1.14's v3→v2 fallback for `GetMonitorDetailByPowerstationId` was insufficient - a real-world account's legacy-login backend returned `404 Route Not Found` for **both** the `v2` and `v3` paths. Community references disagree on which version is correct (pygoodwe hardcodes `v2`, a separate 2023 write-up uses `v1`, our own traffic inspection observed `v3`), so `getMonitorDetail()` now tries all three versions in sequence (`v3` → `v2` → `v1`) and uses whichever one doesn't 404
157
+ - (Stefan Bühler) diagnostics: debug logs now include the full request URL (including the resolved API base) instead of just the relative path, and the login success log now also prints the resolved API base, making it possible to see exactly which host+path combination is failing
158
+ - (Stefan Bühler) 2 updated/new regression tests (45 unit tests in total) covering the three-way version fallback and the case where all three paths fail
159
+
160
+ ### 0.1.14 (2026-07-19)
161
+
162
+ - (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
163
+ - (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)
164
+ - (Stefan Bühler) 2 new regression tests (44 unit tests in total) covering the v3→v2 fallback and the case where both paths fail
165
+
154
166
  ### 0.1.13 (2026-07-19)
155
167
 
156
168
  - (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,298 +1,298 @@
1
1
  {
2
- "common": {
3
- "name": "goodwe-sems",
4
- "version": "0.1.13",
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
- "0.1.7": {
20
- "en": "branding: replace placeholder icon with the official GoodWe logo (used with permission from GoodWe)",
21
- "de": "Branding: Platzhalter-Icon durch das offizielle GoodWe-Logo ersetzt (mit Genehmigung von GoodWe verwendet)",
22
- "ru": "брендинг: заменена иконка-заполнитель на официальный логотип GoodWe (используется с разрешения GoodWe)",
23
- "pt": "marca: ícone substituído pelo logótipo oficial da GoodWe (usado com autorização da GoodWe)",
24
- "nl": "branding: placeholder-icoon vervangen door het officiële GoodWe-logo (gebruikt met toestemming van GoodWe)",
25
- "fr": "image de marque : icône remplacée par le logo officiel GoodWe (utilisé avec l autorisation de GoodWe)",
26
- "it": "branding: icona sostituita con il logo ufficiale GoodWe (utilizzato con l autorizzazione di GoodWe)",
27
- "es": "marca: icono sustituido por el logotipo oficial de GoodWe (utilizado con permiso de GoodWe)",
28
- "pl": "branding: zastąpiono ikonę zastępczą oficjalnym logo GoodWe (używane za zgodą GoodWe)",
29
- "uk": "брендинг: замінено іконку-заповнювач на офіційний логотип GoodWe (використовується з дозволу GoodWe)",
30
- "zh-cn": "品牌:将占位图标替换为 GoodWe 官方标志(经 GoodWe 许可使用)"
31
- },
32
- "0.1.8": {
33
- "en": "address ioBroker adapter-check findings: remove news entries for versions that were never actually published to npm (0.1.1, 0.1.2), remove deprecated common.title/common.main fields, update @iobroker/adapter-core to ^3.2.2",
34
- "de": "ioBroker-Adapter-Check-Befunde behoben: News-Einträge für nie tatsächlich auf npm veröffentlichte Versionen entfernt (0.1.1, 0.1.2), veraltete Felder common.title/common.main entfernt, @iobroker/adapter-core auf ^3.2.2 aktualisiert",
35
- "ru": "устранены замечания adapter-check: удалены записи news для версий, никогда не публиковавшихся в npm (0.1.1, 0.1.2), удалены устаревшие поля common.title/common.main, обновлён @iobroker/adapter-core до ^3.2.2",
36
- "pt": "resolvidas as constatações do adapter-check: removidas entradas de news de versões nunca publicadas no npm (0.1.1, 0.1.2), removidos campos obsoletos common.title/common.main, @iobroker/adapter-core atualizado para ^3.2.2",
37
- "nl": "adapter-check bevindingen opgelost: news-items voor nooit op npm gepubliceerde versies verwijderd (0.1.1, 0.1.2), verouderde velden common.title/common.main verwijderd, @iobroker/adapter-core bijgewerkt naar ^3.2.2",
38
- "fr": "corrections des remarques adapter-check : suppression des entrées news pour des versions jamais publiées sur npm (0.1.1, 0.1.2), suppression des champs obsolètes common.title/common.main, mise à jour de @iobroker/adapter-core vers ^3.2.2",
39
- "it": "risolti i rilievi di adapter-check: rimosse le voci news per versioni mai pubblicate su npm (0.1.1, 0.1.2), rimossi i campi deprecati common.title/common.main, aggiornato @iobroker/adapter-core a ^3.2.2",
40
- "es": "se resolvieron los hallazgos de adapter-check: se eliminaron entradas de news de versiones nunca publicadas en npm (0.1.1, 0.1.2), se eliminaron los campos obsoletos common.title/common.main, se actualizó @iobroker/adapter-core a ^3.2.2",
41
- "pl": "rozwiązano uwagi adapter-check: usunięto wpisy news dla wersji nigdy niepublikowanych na npm (0.1.1, 0.1.2), usunięto przestarzałe pola common.title/common.main, zaktualizowano @iobroker/adapter-core do ^3.2.2",
42
- "uk": "усунено зауваження adapter-check: видалено записи news для версій, які ніколи не публікувалися в npm (0.1.1, 0.1.2), видалено застарілі поля common.title/common.main, оновлено @iobroker/adapter-core до ^3.2.2",
43
- "zh-cn": "解决 adapter-check 发现的问题:移除从未真正发布到 npm 的版本的 news 条目(0.1.1、0.1.2),移除已弃用的 common.title/common.main 字段,将 @iobroker/adapter-core 更新至 ^3.2.2"
44
- },
45
- "0.1.9": {
46
- "en": "address stricter ioBroker.repositories PR check: move encryptedNative/protectedNative to io-package.json root, update deps (adapter-core, testing, adapter-dev, admin, js-controller), rewrite CI workflow (check-and-lint/adapter-tests/deploy jobs, concurrency, full OS+Node matrix), use adapter-managed timers, node:crypto, fix jsonConfig responsive sizes + i18n key, translate README to English (required), add CHANGELOG_OLD.md",
47
- "de": "strengere ioBroker.repositories-PR-Prüfung behoben: encryptedNative/protectedNative auf io-package.json-Root verschoben, Abhängigkeiten aktualisiert (adapter-core, testing, adapter-dev, admin, js-controller), CI-Workflow neu geschrieben (check-and-lint/adapter-tests/deploy Jobs, Concurrency, volle OS+Node-Matrix), adapter-verwaltete Timer, node:crypto, jsonConfig Responsive-Größen + i18n-Key behoben, README auf Englisch übersetzt (Pflicht), CHANGELOG_OLD.md ergänzt",
48
- "ru": "устранены более строгие проверки PR ioBroker.repositories: encryptedNative/protectedNative перемещены в корень io-package.json, обновлены зависимости, переписан CI, README переведён на английский (обязательно)",
49
- "pt": "corrigidas verificações mais rigorosas do PR do ioBroker.repositories: encryptedNative/protectedNative movidos para a raiz do io-package.json, dependências atualizadas, CI reescrito, README traduzido para inglês (obrigatório)",
50
- "nl": "strengere ioBroker.repositories-PR-controles opgelost: encryptedNative/protectedNative naar de root van io-package.json verplaatst, dependencies bijgewerkt, CI herschreven, README naar het Engels vertaald (verplicht)",
51
- "fr": "correction des vérifications plus strictes du PR ioBroker.repositories : encryptedNative/protectedNative déplacés à la racine de io-package.json, dépendances mises à jour, CI réécrit, README traduit en anglais (obligatoire)",
52
- "it": "risolti controlli più severi del PR ioBroker.repositories: encryptedNative/protectedNative spostati alla radice di io-package.json, dipendenze aggiornate, CI riscritta, README tradotto in inglese (obbligatorio)",
53
- "es": "se resolvieron comprobaciones más estrictas del PR de ioBroker.repositories: encryptedNative/protectedNative movidos a la raíz de io-package.json, dependencias actualizadas, CI reescrita, README traducido al inglés (obligatorio)",
54
- "pl": "rozwiązano bardziej rygorystyczne kontrole PR ioBroker.repositories: encryptedNative/protectedNative przeniesiono do katalogu głównego io-package.json, zaktualizowano zależności, przepisano CI, README przetłumaczono na angielski (wymagane)",
55
- "uk": "усунено суворіші перевірки PR ioBroker.repositories: encryptedNative/protectedNative перенесено в корінь io-package.json, оновлено залежності, переписано CI, README перекладено англійською (обов'язково)",
56
- "zh-cn": "解决更严格的 ioBroker.repositories PR 检查:将 encryptedNative/protectedNative 移至 io-package.json 根目录,更新依赖项,重写 CI,将 README 翻译为英文(必需)"
57
- },
58
- "0.1.11": {
59
- "en": "fix broken CI: remove Node.js 20.x from the adapter-tests matrix - it is incompatible with engines.node >=22 (introduced in 0.1.10) under the official action's engine-strict npm ci, which crashed that matrix job and cancelled all others",
60
- "de": "defekte CI behoben: Node.js 20.x aus der adapter-tests-Matrix entfernt - inkompatibel mit engines.node >=22 (seit 0.1.10) unter dem engine-strict npm ci der offiziellen Action, wodurch dieser Matrix-Job abstürzte und alle anderen abgebrochen wurden",
61
- "ru": "исправлен неработающий CI: Node.js 20.x удалён из матрицы adapter-tests - несовместим с engines.node >=22 (введено в 0.1.10)",
62
- "pt": "corrigido o CI quebrado: Node.js 20.x removido da matriz adapter-tests - incompatível com engines.node >=22 (introduzido em 0.1.10)",
63
- "nl": "defecte CI opgelost: Node.js 20.x verwijderd uit de adapter-tests-matrix - incompatibel met engines.node >=22 (geïntroduceerd in 0.1.10)",
64
- "fr": "correction du CI cassé : Node.js 20.x retiré de la matrice adapter-tests - incompatible avec engines.node >=22 (introduit en 0.1.10)",
65
- "it": "risolto il CI non funzionante: rimosso Node.js 20.x dalla matrice adapter-tests - incompatibile con engines.node >=22 (introdotto in 0.1.10)",
66
- "es": "se corrigió el CI roto: se eliminó Node.js 20.x de la matriz adapter-tests - incompatible con engines.node >=22 (introducido en 0.1.10)",
67
- "pl": "naprawiono uszkodzone CI: usunięto Node.js 20.x z macierzy adapter-tests - niekompatybilne z engines.node >=22 (wprowadzone w 0.1.10)",
68
- "uk": "виправлено зламаний CI: видалено Node.js 20.x з матриці adapter-tests - несумісний з engines.node >=22 (введено в 0.1.10)",
69
- "zh-cn": "修复损坏的 CI:从 adapter-tests 矩阵中移除 Node.js 20.x - 与 engines.node >=22(0.1.10 中引入)不兼容"
70
- },
71
- "0.1.12": {
72
- "en": "further recheck fixes: remove news entry for 0.1.10 (never published to npm - its CI failed before the deploy step), declare \"needs: check-and-lint\" on the adapter-tests job, pin @types/node to \"^22\" (was open-ended \">=22\"), fix .vscode/settings.json schema fileMatch patterns (drop leading slash, add jsonCustom.json/jsonTab.json), add dependabot auto-merge workflow + config",
73
- "de": "weitere Recheck-Fixes: News-Eintrag fuer 0.1.10 entfernt (nie auf npm veroeffentlicht - CI schlug vor dem Deploy-Schritt fehl), \"needs: check-and-lint\" beim adapter-tests-Job ergaenzt, @types/node auf \"^22\" fixiert (war offenes \">=22\"), Schema-fileMatch in .vscode/settings.json korrigiert (kein fuehrender Slash, jsonCustom.json/jsonTab.json ergaenzt), Dependabot-Automerge-Workflow + Konfiguration ergaenzt",
74
- "ru": "дальнейшие исправления: удалена запись news для 0.1.10 (никогда не публиковалась в npm), needs: check-and-lint для adapter-tests, @types/node зафиксирован на ^22, исправлены схемы в .vscode/settings.json, добавлен automerge для dependabot",
75
- "pt": "mais correcoes: removida a entrada de news para 0.1.10 (nunca publicada no npm), needs: check-and-lint no job adapter-tests, @types/node fixado em ^22, esquemas corrigidos em .vscode/settings.json, automerge do dependabot adicionado",
76
- "nl": "verdere fixes: news-item voor 0.1.10 verwijderd (nooit op npm gepubliceerd), needs: check-and-lint toegevoegd aan adapter-tests, @types/node vastgezet op ^22, schema's in .vscode/settings.json gecorrigeerd, dependabot automerge toegevoegd",
77
- "fr": "autres corrections : entree news pour 0.1.10 supprimee (jamais publiee sur npm), needs: check-and-lint ajoute au job adapter-tests, @types/node fixe a ^22, schemas corriges dans .vscode/settings.json, automerge dependabot ajoute",
78
- "it": "ulteriori correzioni: rimossa la voce news per 0.1.10 (mai pubblicata su npm), aggiunto needs: check-and-lint al job adapter-tests, @types/node fissato a ^22, schemi corretti in .vscode/settings.json, aggiunto automerge per dependabot",
79
- "es": "mas correcciones: se elimino la entrada de news para 0.1.10 (nunca publicada en npm), se agrego needs: check-and-lint al job adapter-tests, @types/node fijado en ^22, esquemas corregidos en .vscode/settings.json, se agrego automerge de dependabot",
80
- "pl": "kolejne poprawki: usunieto wpis news dla 0.1.10 (nigdy nie opublikowano na npm), dodano needs: check-and-lint do zadania adapter-tests, @types/node ustalono na ^22, poprawiono schematy w .vscode/settings.json, dodano automerge dependabot",
81
- "uk": "подальші виправлення: видалено запис news для 0.1.10 (ніколи не публікувався на npm), додано needs: check-and-lint для adapter-tests, @types/node зафіксовано на ^22, виправлено схеми в .vscode/settings.json, додано automerge для dependabot",
82
- "zh-cn": "进一步修复:移除 0.1.10 news 条目(从未发布到 npm),为 adapter-tests 任务添加 needs: check-and-lint,将 @types/node 固定为 ^22,修复 .vscode/settings.json 中的 schema 匹配,添加 dependabot 自动合并"
83
- },
84
- "0.1.13": {
85
- "en": "diagnostics: log the raw JSON envelope of every SEMS API call at debug level (not just the monitor-detail call). This helps pinpoint reports like \"unbekannter Fehler (code=undefined)\" on GetPowerStationIdByOwner, where the actual success/error convention used by that endpoint differs from what earlier testing assumed",
86
- "de": "Diagnose: rohe JSON-Antwort jedes SEMS-API-Aufrufs wird jetzt auf Debug-Level geloggt (nicht mehr nur beim Monitor-Detail-Aufruf). Hilft, Meldungen wie \"unbekannter Fehler (code=undefined)\" bei GetPowerStationIdByOwner einzugrenzen, wenn die tatsächliche Erfolgs-/Fehler-Konvention dieses Endpunkts von den bisherigen Annahmen abweicht",
87
- "ru": "диагностика: сырой JSON-ответ каждого вызова SEMS API теперь логируется на уровне debug",
88
- "pt": "diagnóstico: a resposta JSON bruta de cada chamada à API SEMS agora é registada ao nível de debug",
89
- "nl": "diagnostiek: de ruwe JSON-respons van elke SEMS API-aanroep wordt nu op debug-niveau gelogd",
90
- "fr": "diagnostic : la reponse JSON brute de chaque appel a l'API SEMS est desormais journalisee au niveau debug",
91
- "it": "diagnostica: la risposta JSON grezza di ogni chiamata all'API SEMS viene ora registrata a livello debug",
92
- "es": "diagnostico: la respuesta JSON en bruto de cada llamada a la API de SEMS ahora se registra en el nivel debug",
93
- "pl": "diagnostyka: surowa odpowiedz JSON kazdego wywolania API SEMS jest teraz logowana na poziomie debug",
94
- "uk": "діагностика: сирий JSON-вiдповiдь кожного виклику SEMS API тепер логується на рiвнi debug",
95
- "zh-cn": "诊断:每次 SEMS API 调用的原始 JSON 响应现在都会在 debug 级别记录"
96
- }
2
+ "common": {
3
+ "name": "goodwe-sems",
4
+ "version": "0.1.15",
5
+ "news": {
6
+ "0.1.15": {
7
+ "de": "Weiterer Fix für die GoodWe-API-Versionierung: getMonitorDetail() probiert jetzt v3, v2 UND v1 der Reihe nach durch (statt nur v3->v2), da GoodWe je nach Konto/Backend unterschiedliche API-Versionen für denselben Endpunkt verwendet. Zusätzlich vollständige Request-URL im Debug-Log für einfachere Diagnose.",
8
+ "en": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
9
+ "ru": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
10
+ "pt": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
11
+ "nl": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
12
+ "fr": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
13
+ "it": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
14
+ "es": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
15
+ "pl": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
16
+ "zh-cn": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis.",
17
+ "uk": "Further fix for GoodWe API versioning: getMonitorDetail() now tries v3, v2 AND v1 in sequence (not just v3->v2), since GoodWe uses different API versions for the same endpoint depending on account/backend. Also logs the full request URL in debug mode for easier diagnosis."
18
+ },
19
+ "0.1.14": {
20
+ "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\"",
21
+ "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\"",
22
+ "ru": "исправление: GetMonitorDetailByPowerstationId возвращал 404 для учётных записей с резервным входом через устаревший API - теперь используется путь v2",
23
+ "pt": "correcao: GetMonitorDetailByPowerstationId retornava 404 para contas com login de reserva na API legada - agora usa o caminho v2",
24
+ "nl": "fix: GetMonitorDetailByPowerstationId gaf 404 voor accounts met fallback-login op de legacy API - gebruikt nu het v2-pad",
25
+ "fr": "correction : GetMonitorDetailByPowerstationId renvoyait une 404 pour les comptes utilisant la connexion de secours a l'API historique - utilise desormais le chemin v2",
26
+ "it": "correzione: GetMonitorDetailByPowerstationId restituiva 404 per gli account con login di fallback sull'API legacy - ora usa il percorso v2",
27
+ "es": "correccion: GetMonitorDetailByPowerstationId devolvia 404 para cuentas con inicio de sesion de respaldo en la API heredada - ahora usa la ruta v2",
28
+ "pl": "poprawka: GetMonitorDetailByPowerstationId zwracal 404 dla kont z zapasowym logowaniem do starszego API - teraz uzywana jest sciezka v2",
29
+ "uk": "виправлення: GetMonitorDetailByPowerstationId повертав 404 для облікових записів із резервним входом через застарілий API - тепер використовується шлях v2",
30
+ "zh-cn": "修复:对于回退到旧版登录 API 的账户,GetMonitorDetailByPowerstationId 返回 404 - 现在改用 v2 路径"
31
+ },
32
+ "0.1.13": {
33
+ "en": "diagnostics: log the raw JSON envelope of every SEMS API call at debug level (not just the monitor-detail call). This helps pinpoint reports like \"unbekannter Fehler (code=undefined)\" on GetPowerStationIdByOwner, where the actual success/error convention used by that endpoint differs from what earlier testing assumed",
34
+ "de": "Diagnose: rohe JSON-Antwort jedes SEMS-API-Aufrufs wird jetzt auf Debug-Level geloggt (nicht mehr nur beim Monitor-Detail-Aufruf). Hilft, Meldungen wie \"unbekannter Fehler (code=undefined)\" bei GetPowerStationIdByOwner einzugrenzen, wenn die tatsächliche Erfolgs-/Fehler-Konvention dieses Endpunkts von den bisherigen Annahmen abweicht",
35
+ "ru": "диагностика: сырой JSON-ответ каждого вызова SEMS API теперь логируется на уровне debug",
36
+ "pt": "diagnóstico: a resposta JSON bruta de cada chamada à API SEMS agora é registada ao nível de debug",
37
+ "nl": "diagnostiek: de ruwe JSON-respons van elke SEMS API-aanroep wordt nu op debug-niveau gelogd",
38
+ "fr": "diagnostic : la reponse JSON brute de chaque appel a l'API SEMS est desormais journalisee au niveau debug",
39
+ "it": "diagnostica: la risposta JSON grezza di ogni chiamata all'API SEMS viene ora registrata a livello debug",
40
+ "es": "diagnostico: la respuesta JSON en bruto de cada llamada a la API de SEMS ahora se registra en el nivel debug",
41
+ "pl": "diagnostyka: surowa odpowiedz JSON kazdego wywolania API SEMS jest teraz logowana na poziomie debug",
42
+ "uk": "діагностика: сирий JSON-вiдповiдь кожного виклику SEMS API тепер логується на рiвнi debug",
43
+ "zh-cn": "诊断:每次 SEMS API 调用的原始 JSON 响应现在都会在 debug 级别记录"
44
+ },
45
+ "0.1.12": {
46
+ "en": "further recheck fixes: remove news entry for 0.1.10 (never published to npm - its CI failed before the deploy step), declare \"needs: check-and-lint\" on the adapter-tests job, pin @types/node to \"^22\" (was open-ended \">=22\"), fix .vscode/settings.json schema fileMatch patterns (drop leading slash, add jsonCustom.json/jsonTab.json), add dependabot auto-merge workflow + config",
47
+ "de": "weitere Recheck-Fixes: News-Eintrag fuer 0.1.10 entfernt (nie auf npm veroeffentlicht - CI schlug vor dem Deploy-Schritt fehl), \"needs: check-and-lint\" beim adapter-tests-Job ergaenzt, @types/node auf \"^22\" fixiert (war offenes \">=22\"), Schema-fileMatch in .vscode/settings.json korrigiert (kein fuehrender Slash, jsonCustom.json/jsonTab.json ergaenzt), Dependabot-Automerge-Workflow + Konfiguration ergaenzt",
48
+ "ru": "дальнейшие исправления: удалена запись news для 0.1.10 (никогда не публиковалась в npm), needs: check-and-lint для adapter-tests, @types/node зафиксирован на ^22, исправлены схемы в .vscode/settings.json, добавлен automerge для dependabot",
49
+ "pt": "mais correcoes: removida a entrada de news para 0.1.10 (nunca publicada no npm), needs: check-and-lint no job adapter-tests, @types/node fixado em ^22, esquemas corrigidos em .vscode/settings.json, automerge do dependabot adicionado",
50
+ "nl": "verdere fixes: news-item voor 0.1.10 verwijderd (nooit op npm gepubliceerd), needs: check-and-lint toegevoegd aan adapter-tests, @types/node vastgezet op ^22, schema's in .vscode/settings.json gecorrigeerd, dependabot automerge toegevoegd",
51
+ "fr": "autres corrections : entree news pour 0.1.10 supprimee (jamais publiee sur npm), needs: check-and-lint ajoute au job adapter-tests, @types/node fixe a ^22, schemas corriges dans .vscode/settings.json, automerge dependabot ajoute",
52
+ "it": "ulteriori correzioni: rimossa la voce news per 0.1.10 (mai pubblicata su npm), aggiunto needs: check-and-lint al job adapter-tests, @types/node fissato a ^22, schemi corretti in .vscode/settings.json, aggiunto automerge per dependabot",
53
+ "es": "mas correcciones: se elimino la entrada de news para 0.1.10 (nunca publicada en npm), se agrego needs: check-and-lint al job adapter-tests, @types/node fijado en ^22, esquemas corregidos en .vscode/settings.json, se agrego automerge de dependabot",
54
+ "pl": "kolejne poprawki: usunieto wpis news dla 0.1.10 (nigdy nie opublikowano na npm), dodano needs: check-and-lint do zadania adapter-tests, @types/node ustalono na ^22, poprawiono schematy w .vscode/settings.json, dodano automerge dependabot",
55
+ "uk": "подальші виправлення: видалено запис news для 0.1.10 (ніколи не публікувався на npm), додано needs: check-and-lint для adapter-tests, @types/node зафіксовано на ^22, виправлено схеми в .vscode/settings.json, додано automerge для dependabot",
56
+ "zh-cn": "进一步修复:移除 0.1.10 news 条目(从未发布到 npm),为 adapter-tests 任务添加 needs: check-and-lint,将 @types/node 固定为 ^22,修复 .vscode/settings.json 中的 schema 匹配,添加 dependabot 自动合并"
57
+ },
58
+ "0.1.11": {
59
+ "en": "fix broken CI: remove Node.js 20.x from the adapter-tests matrix - it is incompatible with engines.node >=22 (introduced in 0.1.10) under the official action's engine-strict npm ci, which crashed that matrix job and cancelled all others",
60
+ "de": "defekte CI behoben: Node.js 20.x aus der adapter-tests-Matrix entfernt - inkompatibel mit engines.node >=22 (seit 0.1.10) unter dem engine-strict npm ci der offiziellen Action, wodurch dieser Matrix-Job abstürzte und alle anderen abgebrochen wurden",
61
+ "ru": "исправлен неработающий CI: Node.js 20.x удалён из матрицы adapter-tests - несовместим с engines.node >=22 (введено в 0.1.10)",
62
+ "pt": "corrigido o CI quebrado: Node.js 20.x removido da matriz adapter-tests - incompatível com engines.node >=22 (introduzido em 0.1.10)",
63
+ "nl": "defecte CI opgelost: Node.js 20.x verwijderd uit de adapter-tests-matrix - incompatibel met engines.node >=22 (geïntroduceerd in 0.1.10)",
64
+ "fr": "correction du CI cassé : Node.js 20.x retiré de la matrice adapter-tests - incompatible avec engines.node >=22 (introduit en 0.1.10)",
65
+ "it": "risolto il CI non funzionante: rimosso Node.js 20.x dalla matrice adapter-tests - incompatibile con engines.node >=22 (introdotto in 0.1.10)",
66
+ "es": "se corrigió el CI roto: se eliminó Node.js 20.x de la matriz adapter-tests - incompatible con engines.node >=22 (introducido en 0.1.10)",
67
+ "pl": "naprawiono uszkodzone CI: usunięto Node.js 20.x z macierzy adapter-tests - niekompatybilne z engines.node >=22 (wprowadzone w 0.1.10)",
68
+ "uk": "виправлено зламаний CI: видалено Node.js 20.x з матриці adapter-tests - несумісний з engines.node >=22 (введено в 0.1.10)",
69
+ "zh-cn": "修复损坏的 CI:从 adapter-tests 矩阵中移除 Node.js 20.x - 与 engines.node >=22(0.1.10 中引入)不兼容"
70
+ },
71
+ "0.1.9": {
72
+ "en": "address stricter ioBroker.repositories PR check: move encryptedNative/protectedNative to io-package.json root, update deps (adapter-core, testing, adapter-dev, admin, js-controller), rewrite CI workflow (check-and-lint/adapter-tests/deploy jobs, concurrency, full OS+Node matrix), use adapter-managed timers, node:crypto, fix jsonConfig responsive sizes + i18n key, translate README to English (required), add CHANGELOG_OLD.md",
73
+ "de": "strengere ioBroker.repositories-PR-Prüfung behoben: encryptedNative/protectedNative auf io-package.json-Root verschoben, Abhängigkeiten aktualisiert (adapter-core, testing, adapter-dev, admin, js-controller), CI-Workflow neu geschrieben (check-and-lint/adapter-tests/deploy Jobs, Concurrency, volle OS+Node-Matrix), adapter-verwaltete Timer, node:crypto, jsonConfig Responsive-Größen + i18n-Key behoben, README auf Englisch übersetzt (Pflicht), CHANGELOG_OLD.md ergänzt",
74
+ "ru": "устранены более строгие проверки PR ioBroker.repositories: encryptedNative/protectedNative перемещены в корень io-package.json, обновлены зависимости, переписан CI, README переведён на английский (обязательно)",
75
+ "pt": "corrigidas verificações mais rigorosas do PR do ioBroker.repositories: encryptedNative/protectedNative movidos para a raiz do io-package.json, dependências atualizadas, CI reescrito, README traduzido para inglês (obrigatório)",
76
+ "nl": "strengere ioBroker.repositories-PR-controles opgelost: encryptedNative/protectedNative naar de root van io-package.json verplaatst, dependencies bijgewerkt, CI herschreven, README naar het Engels vertaald (verplicht)",
77
+ "fr": "correction des vérifications plus strictes du PR ioBroker.repositories : encryptedNative/protectedNative déplacés à la racine de io-package.json, dépendances mises à jour, CI réécrit, README traduit en anglais (obligatoire)",
78
+ "it": "risolti controlli più severi del PR ioBroker.repositories: encryptedNative/protectedNative spostati alla radice di io-package.json, dipendenze aggiornate, CI riscritta, README tradotto in inglese (obbligatorio)",
79
+ "es": "se resolvieron comprobaciones más estrictas del PR de ioBroker.repositories: encryptedNative/protectedNative movidos a la raíz de io-package.json, dependencias actualizadas, CI reescrita, README traducido al inglés (obligatorio)",
80
+ "pl": "rozwiązano bardziej rygorystyczne kontrole PR ioBroker.repositories: encryptedNative/protectedNative przeniesiono do katalogu głównego io-package.json, zaktualizowano zależności, przepisano CI, README przetłumaczono na angielski (wymagane)",
81
+ "uk": "усунено суворіші перевірки PR ioBroker.repositories: encryptedNative/protectedNative перенесено в корінь io-package.json, оновлено залежності, переписано CI, README перекладено англійською (обов'язково)",
82
+ "zh-cn": "解决更严格的 ioBroker.repositories PR 检查:将 encryptedNative/protectedNative 移至 io-package.json 根目录,更新依赖项,重写 CI,将 README 翻译为英文(必需)"
83
+ },
84
+ "0.1.8": {
85
+ "en": "address ioBroker adapter-check findings: remove news entries for versions that were never actually published to npm (0.1.1, 0.1.2), remove deprecated common.title/common.main fields, update @iobroker/adapter-core to ^3.2.2",
86
+ "de": "ioBroker-Adapter-Check-Befunde behoben: News-Einträge für nie tatsächlich auf npm veröffentlichte Versionen entfernt (0.1.1, 0.1.2), veraltete Felder common.title/common.main entfernt, @iobroker/adapter-core auf ^3.2.2 aktualisiert",
87
+ "ru": "устранены замечания adapter-check: удалены записи news для версий, никогда не публиковавшихся в npm (0.1.1, 0.1.2), удалены устаревшие поля common.title/common.main, обновлён @iobroker/adapter-core до ^3.2.2",
88
+ "pt": "resolvidas as constatações do adapter-check: removidas entradas de news de versões nunca publicadas no npm (0.1.1, 0.1.2), removidos campos obsoletos common.title/common.main, @iobroker/adapter-core atualizado para ^3.2.2",
89
+ "nl": "adapter-check bevindingen opgelost: news-items voor nooit op npm gepubliceerde versies verwijderd (0.1.1, 0.1.2), verouderde velden common.title/common.main verwijderd, @iobroker/adapter-core bijgewerkt naar ^3.2.2",
90
+ "fr": "corrections des remarques adapter-check : suppression des entrées news pour des versions jamais publiées sur npm (0.1.1, 0.1.2), suppression des champs obsolètes common.title/common.main, mise à jour de @iobroker/adapter-core vers ^3.2.2",
91
+ "it": "risolti i rilievi di adapter-check: rimosse le voci news per versioni mai pubblicate su npm (0.1.1, 0.1.2), rimossi i campi deprecati common.title/common.main, aggiornato @iobroker/adapter-core a ^3.2.2",
92
+ "es": "se resolvieron los hallazgos de adapter-check: se eliminaron entradas de news de versiones nunca publicadas en npm (0.1.1, 0.1.2), se eliminaron los campos obsoletos common.title/common.main, se actualizó @iobroker/adapter-core a ^3.2.2",
93
+ "pl": "rozwiązano uwagi adapter-check: usunięto wpisy news dla wersji nigdy niepublikowanych na npm (0.1.1, 0.1.2), usunięto przestarzałe pola common.title/common.main, zaktualizowano @iobroker/adapter-core do ^3.2.2",
94
+ "uk": "усунено зауваження adapter-check: видалено записи news для версій, які ніколи не публікувалися в npm (0.1.1, 0.1.2), видалено застарілі поля common.title/common.main, оновлено @iobroker/adapter-core до ^3.2.2",
95
+ "zh-cn": "解决 adapter-check 发现的问题:移除从未真正发布到 npm 的版本的 news 条目(0.1.1、0.1.2),移除已弃用的 common.title/common.main 字段,将 @iobroker/adapter-core 更新至 ^3.2.2"
96
+ }
97
+ },
98
+ "titleLang": {
99
+ "en": "GoodWe SEMS Portal",
100
+ "de": "GoodWe SEMS Portal",
101
+ "ru": "GoodWe SEMS Portal",
102
+ "pt": "GoodWe SEMS Portal",
103
+ "nl": "GoodWe SEMS Portal",
104
+ "fr": "GoodWe SEMS Portal",
105
+ "it": "GoodWe SEMS Portal",
106
+ "es": "GoodWe SEMS Portal",
107
+ "pl": "GoodWe SEMS Portal",
108
+ "uk": "GoodWe SEMS Portal",
109
+ "zh-cn": "GoodWe SEMS 门户"
110
+ },
111
+ "desc": {
112
+ "en": "Reads inverter, battery and power-flow data from the GoodWe SEMS Portal cloud for installations that have no local/LAN access to the inverter.",
113
+ "de": "Liest Wechselrichter-, Batterie- und Energiefluss-Daten aus dem GoodWe-SEMS-Portal (Cloud) für Anlagen ohne lokalen/LAN-Zugriff auf den Wechselrichter.",
114
+ "ru": "Считывает данные инвертора, батареи и потоков энергии из облачного портала GoodWe SEMS для установок без локального доступа к инвертору.",
115
+ "pt": "Lê dados do inversor, bateria e fluxo de energia do portal SEMS da GoodWe na nuvem para instalações sem acesso local/LAN ao inversor.",
116
+ "nl": "Leest omvormer-, batterij- en energiestroomgegevens uit het GoodWe SEMS-portaal (cloud) voor installaties zonder lokale/LAN-toegang tot de omvormer.",
117
+ "fr": "Lit les données de l'onduleur, de la batterie et des flux d'énergie depuis le portail cloud GoodWe SEMS pour les installations sans accès local/LAN à l'onduleur.",
118
+ "it": "Legge i dati dell'inverter, della batteria e del flusso di energia dal portale cloud GoodWe SEMS per impianti senza accesso locale/LAN all'inverter.",
119
+ "es": "Lee datos del inversor, la batería y el flujo de energía desde el portal en la nube GoodWe SEMS para instalaciones sin acceso local/LAN al inversor.",
120
+ "pl": "Odczytuje dane falownika, baterii i przepływu energii z chmury portalu GoodWe SEMS dla instalacji bez lokalnego dostępu do falownika.",
121
+ "uk": "Зчитує дані інвертора, батареї та потоків енергії з хмарного порталу GoodWe SEMS для установок без локального доступу до інвертора.",
122
+ "zh-cn": "为无法本地访问逆变器的装置从 GoodWe SEMS 云端门户读取逆变器、电池和功率流数据。"
123
+ },
124
+ "authors": [
125
+ "bueste <bueste@users.noreply.github.com>"
126
+ ],
127
+ "keywords": [
128
+ "goodwe",
129
+ "sems",
130
+ "semsportal",
131
+ "inverter",
132
+ "solar",
133
+ "pv",
134
+ "photovoltaik",
135
+ "battery"
136
+ ],
137
+ "licenseInformation": {
138
+ "type": "free",
139
+ "license": "MIT"
140
+ },
141
+ "platform": "Javascript/Node.js",
142
+ "icon": "goodwe-sems.png",
143
+ "enabled": true,
144
+ "extIcon": "https://raw.githubusercontent.com/bueste/ioBroker.goodwe-sems/main/admin/goodwe-sems.png",
145
+ "readme": "https://github.com/bueste/ioBroker.goodwe-sems/blob/main/README.md",
146
+ "loglevel": "info",
147
+ "mode": "daemon",
148
+ "type": "energy",
149
+ "compact": true,
150
+ "connectionType": "cloud",
151
+ "dataSource": "poll",
152
+ "tier": 3,
153
+ "adminUI": {
154
+ "config": "json"
155
+ },
156
+ "dependencies": [
157
+ {
158
+ "js-controller": ">=6.0.11"
159
+ }
160
+ ],
161
+ "globalDependencies": [
162
+ {
163
+ "admin": ">=7.6.20"
164
+ }
165
+ ]
97
166
  },
98
- "titleLang": {
99
- "en": "GoodWe SEMS Portal",
100
- "de": "GoodWe SEMS Portal",
101
- "ru": "GoodWe SEMS Portal",
102
- "pt": "GoodWe SEMS Portal",
103
- "nl": "GoodWe SEMS Portal",
104
- "fr": "GoodWe SEMS Portal",
105
- "it": "GoodWe SEMS Portal",
106
- "es": "GoodWe SEMS Portal",
107
- "pl": "GoodWe SEMS Portal",
108
- "uk": "GoodWe SEMS Portal",
109
- "zh-cn": "GoodWe SEMS 门户"
167
+ "native": {
168
+ "account": "",
169
+ "password": "",
170
+ "powerStationId": "",
171
+ "pollInterval": 300,
172
+ "requestTimeout": 15,
173
+ "maxConsecutiveErrors": 3,
174
+ "pushoverMode": "none",
175
+ "pushoverInstance": "pushover.0",
176
+ "pushoverUserKey": "",
177
+ "pushoverApiToken": "",
178
+ "pushoverPriority": 0,
179
+ "notifyOnLoginFailure": true,
180
+ "notifyOnRateLimit": true,
181
+ "notifyOnStationOffline": true,
182
+ "notifyOnAdapterError": true,
183
+ "stationOfflineMinutes": 30,
184
+ "debugRawResponse": false
110
185
  },
111
- "desc": {
112
- "en": "Reads inverter, battery and power-flow data from the GoodWe SEMS Portal cloud for installations that have no local/LAN access to the inverter.",
113
- "de": "Liest Wechselrichter-, Batterie- und Energiefluss-Daten aus dem GoodWe-SEMS-Portal (Cloud) für Anlagen ohne lokalen/LAN-Zugriff auf den Wechselrichter.",
114
- "ru": "Считывает данные инвертора, батареи и потоков энергии из облачного портала GoodWe SEMS для установок без локального доступа к инвертору.",
115
- "pt": "Lê dados do inversor, bateria e fluxo de energia do portal SEMS da GoodWe na nuvem para instalações sem acesso local/LAN ao inversor.",
116
- "nl": "Leest omvormer-, batterij- en energiestroomgegevens uit het GoodWe SEMS-portaal (cloud) voor installaties zonder lokale/LAN-toegang tot de omvormer.",
117
- "fr": "Lit les données de l'onduleur, de la batterie et des flux d'énergie depuis le portail cloud GoodWe SEMS pour les installations sans accès local/LAN à l'onduleur.",
118
- "it": "Legge i dati dell'inverter, della batteria e del flusso di energia dal portale cloud GoodWe SEMS per impianti senza accesso locale/LAN all'inverter.",
119
- "es": "Lee datos del inversor, la batería y el flujo de energía desde el portal en la nube GoodWe SEMS para instalaciones sin acceso local/LAN al inversor.",
120
- "pl": "Odczytuje dane falownika, baterii i przepływu energii z chmury portalu GoodWe SEMS dla instalacji bez lokalnego dostępu do falownika.",
121
- "uk": "Зчитує дані інвертора, батареї та потоків енергії з хмарного порталу GoodWe SEMS для установок без локального доступу до інвертора.",
122
- "zh-cn": "为无法本地访问逆变器的装置从 GoodWe SEMS 云端门户读取逆变器、电池和功率流数据。"
123
- },
124
- "authors": [
125
- "bueste <bueste@users.noreply.github.com>"
126
- ],
127
- "keywords": [
128
- "goodwe",
129
- "sems",
130
- "semsportal",
131
- "inverter",
132
- "solar",
133
- "pv",
134
- "photovoltaik",
135
- "battery"
186
+ "encryptedNative": [
187
+ "password",
188
+ "pushoverApiToken"
136
189
  ],
137
- "licenseInformation": {
138
- "type": "free",
139
- "license": "MIT"
140
- },
141
- "platform": "Javascript/Node.js",
142
- "icon": "goodwe-sems.png",
143
- "enabled": true,
144
- "extIcon": "https://raw.githubusercontent.com/bueste/ioBroker.goodwe-sems/main/admin/goodwe-sems.png",
145
- "readme": "https://github.com/bueste/ioBroker.goodwe-sems/blob/main/README.md",
146
- "loglevel": "info",
147
- "mode": "daemon",
148
- "type": "energy",
149
- "compact": true,
150
- "connectionType": "cloud",
151
- "dataSource": "poll",
152
- "tier": 3,
153
- "adminUI": {
154
- "config": "json"
155
- },
156
- "dependencies": [
157
- {
158
- "js-controller": ">=6.0.11"
159
- }
190
+ "protectedNative": [
191
+ "password",
192
+ "pushoverApiToken"
160
193
  ],
161
- "globalDependencies": [
162
- {
163
- "admin": ">=7.6.20"
164
- }
194
+ "objects": [],
195
+ "instanceObjects": [
196
+ {
197
+ "_id": "info",
198
+ "type": "channel",
199
+ "common": {
200
+ "name": "Information"
201
+ },
202
+ "native": {}
203
+ },
204
+ {
205
+ "_id": "info.connection",
206
+ "type": "state",
207
+ "common": {
208
+ "role": "indicator.connected",
209
+ "name": "SEMS Portal reachable",
210
+ "type": "boolean",
211
+ "read": true,
212
+ "write": false,
213
+ "def": false
214
+ },
215
+ "native": {}
216
+ },
217
+ {
218
+ "_id": "info.lastSuccess",
219
+ "type": "state",
220
+ "common": {
221
+ "role": "value.time",
222
+ "name": "Timestamp of last successful poll",
223
+ "type": "number",
224
+ "read": true,
225
+ "write": false,
226
+ "def": 0
227
+ },
228
+ "native": {}
229
+ },
230
+ {
231
+ "_id": "info.lastError",
232
+ "type": "state",
233
+ "common": {
234
+ "role": "text",
235
+ "name": "Last error message",
236
+ "type": "string",
237
+ "read": true,
238
+ "write": false,
239
+ "def": ""
240
+ },
241
+ "native": {}
242
+ },
243
+ {
244
+ "_id": "info.consecutiveErrors",
245
+ "type": "state",
246
+ "common": {
247
+ "role": "value",
248
+ "name": "Number of consecutive failed polls",
249
+ "type": "number",
250
+ "read": true,
251
+ "write": false,
252
+ "def": 0
253
+ },
254
+ "native": {}
255
+ },
256
+ {
257
+ "_id": "info.rateLimited",
258
+ "type": "state",
259
+ "common": {
260
+ "role": "indicator",
261
+ "name": "SEMS Portal is currently rate-limiting this account",
262
+ "type": "boolean",
263
+ "read": true,
264
+ "write": false,
265
+ "def": false
266
+ },
267
+ "native": {}
268
+ },
269
+ {
270
+ "_id": "info.activePollInterval",
271
+ "type": "state",
272
+ "common": {
273
+ "role": "value.interval",
274
+ "name": "Currently active poll interval (seconds, incl. backoff)",
275
+ "type": "number",
276
+ "unit": "s",
277
+ "read": true,
278
+ "write": false,
279
+ "def": 300
280
+ },
281
+ "native": {}
282
+ },
283
+ {
284
+ "_id": "info.rawResponse",
285
+ "type": "state",
286
+ "common": {
287
+ "role": "json",
288
+ "name": "Raw last SEMS API response (debug, disabled by default)",
289
+ "type": "string",
290
+ "read": true,
291
+ "write": false,
292
+ "def": "",
293
+ "expert": true
294
+ },
295
+ "native": {}
296
+ }
165
297
  ]
166
- },
167
- "native": {
168
- "account": "",
169
- "password": "",
170
- "powerStationId": "",
171
- "pollInterval": 300,
172
- "requestTimeout": 15,
173
- "maxConsecutiveErrors": 3,
174
- "pushoverMode": "none",
175
- "pushoverInstance": "pushover.0",
176
- "pushoverUserKey": "",
177
- "pushoverApiToken": "",
178
- "pushoverPriority": 0,
179
- "notifyOnLoginFailure": true,
180
- "notifyOnRateLimit": true,
181
- "notifyOnStationOffline": true,
182
- "notifyOnAdapterError": true,
183
- "stationOfflineMinutes": 30,
184
- "debugRawResponse": false
185
- },
186
- "encryptedNative": [
187
- "password",
188
- "pushoverApiToken"
189
- ],
190
- "protectedNative": [
191
- "password",
192
- "pushoverApiToken"
193
- ],
194
- "objects": [],
195
- "instanceObjects": [
196
- {
197
- "_id": "info",
198
- "type": "channel",
199
- "common": {
200
- "name": "Information"
201
- },
202
- "native": {}
203
- },
204
- {
205
- "_id": "info.connection",
206
- "type": "state",
207
- "common": {
208
- "role": "indicator.connected",
209
- "name": "SEMS Portal reachable",
210
- "type": "boolean",
211
- "read": true,
212
- "write": false,
213
- "def": false
214
- },
215
- "native": {}
216
- },
217
- {
218
- "_id": "info.lastSuccess",
219
- "type": "state",
220
- "common": {
221
- "role": "value.time",
222
- "name": "Timestamp of last successful poll",
223
- "type": "number",
224
- "read": true,
225
- "write": false,
226
- "def": 0
227
- },
228
- "native": {}
229
- },
230
- {
231
- "_id": "info.lastError",
232
- "type": "state",
233
- "common": {
234
- "role": "text",
235
- "name": "Last error message",
236
- "type": "string",
237
- "read": true,
238
- "write": false,
239
- "def": ""
240
- },
241
- "native": {}
242
- },
243
- {
244
- "_id": "info.consecutiveErrors",
245
- "type": "state",
246
- "common": {
247
- "role": "value",
248
- "name": "Number of consecutive failed polls",
249
- "type": "number",
250
- "read": true,
251
- "write": false,
252
- "def": 0
253
- },
254
- "native": {}
255
- },
256
- {
257
- "_id": "info.rateLimited",
258
- "type": "state",
259
- "common": {
260
- "role": "indicator",
261
- "name": "SEMS Portal is currently rate-limiting this account",
262
- "type": "boolean",
263
- "read": true,
264
- "write": false,
265
- "def": false
266
- },
267
- "native": {}
268
- },
269
- {
270
- "_id": "info.activePollInterval",
271
- "type": "state",
272
- "common": {
273
- "role": "value.interval",
274
- "name": "Currently active poll interval (seconds, incl. backoff)",
275
- "type": "number",
276
- "unit": "s",
277
- "read": true,
278
- "write": false,
279
- "def": 300
280
- },
281
- "native": {}
282
- },
283
- {
284
- "_id": "info.rawResponse",
285
- "type": "state",
286
- "common": {
287
- "role": "json",
288
- "name": "Raw last SEMS API response (debug, disabled by default)",
289
- "type": "string",
290
- "read": true,
291
- "write": false,
292
- "def": "",
293
- "expert": true
294
- },
295
- "native": {}
296
- }
297
- ]
298
298
  }
package/lib/semsApi.js CHANGED
@@ -41,7 +41,19 @@ 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
- const MONITOR_DETAIL_PATH = "/v3/PowerStation/GetMonitorDetailByPowerstationId";
44
+ // GoodWe backends have been observed to expose GetMonitorDetailByPowerstationId
45
+ // under different API versions depending on account/region/backend generation.
46
+ // Community references disagree: pygoodwe (github.com/yaleman/pygoodwe) hardcodes
47
+ // "v2", a 2023 write-up (binodmx.medium.com) uses "v1", and our own traffic
48
+ // inspection against a SEMS+ account observed "v3". A real-world legacy-login
49
+ // account (SEMS+ login rejected with code=C0602) 404'd on BOTH v3 and v2, so
50
+ // none of the single hardcoded versions are reliable - we try all three,
51
+ // newest first, and use whichever one doesn't 404.
52
+ const MONITOR_DETAIL_PATHS = [
53
+ "/v3/PowerStation/GetMonitorDetailByPowerstationId",
54
+ "/v2/PowerStation/GetMonitorDetailByPowerstationId",
55
+ "/v1/PowerStation/GetMonitorDetailByPowerstationId",
56
+ ];
45
57
 
46
58
  // Observed rate-limit response code. GoodWe does not document a retry-after
47
59
  // value, community projects settled on a 5 minute cool-down.
@@ -166,7 +178,7 @@ class SemsApi {
166
178
  async login() {
167
179
  try {
168
180
  const session = await this._loginNew();
169
- this.log("debug", "SEMS-Login über SEMS+ (neue API) erfolgreich.");
181
+ this.log("debug", `SEMS-Login über SEMS+ (neue API) erfolgreich. API-Basis: ${session.api}`);
170
182
  this.session = session;
171
183
  return session;
172
184
  } catch (newLoginError) {
@@ -177,7 +189,7 @@ class SemsApi {
177
189
  }
178
190
 
179
191
  const session = await this._loginLegacy();
180
- this.log("debug", "SEMS-Login über Legacy-API erfolgreich.");
192
+ this.log("debug", `SEMS-Login über Legacy-API erfolgreich. API-Basis: ${session.api}`);
181
193
  this.session = session;
182
194
  return session;
183
195
  }
@@ -228,7 +240,7 @@ class SemsApi {
228
240
  _extractSession(json, fallbackApi, variantName) {
229
241
  const code = json && json.code;
230
242
  if (!SUCCESS_CODES.has(code) && !(json && SUCCESS_MESSAGES.has(String(json.msg).toLowerCase()))) {
231
- const msg = (json && (json.msg || json.message)) || "unbekannter Fehler";
243
+ const msg = (json && (json.msg || json.message || json.error_msg)) || "unbekannter Fehler";
232
244
  throw new SemsAuthError(`SEMS-${variantName}-Login abgelehnt: ${msg} (code=${code})`);
233
245
  }
234
246
 
@@ -308,12 +320,13 @@ class SemsApi {
308
320
  this._timerFns,
309
321
  );
310
322
 
311
- // Always log the raw envelope at debug level (not just on error) - some SEMS
312
- // endpoints use success/error conventions that differ from the ones this
313
- // adapter was originally built and tested against, so this is the fastest way
314
- // to diagnose "unbekannter Fehler (code=undefined)"-style reports from real
315
- // accounts without needing access to the account's credentials.
316
- this.log("debug", `SEMS-API-Antwort ${path}: ${JSON.stringify(json)}`);
323
+ // Always log the raw envelope (with the full request URL, not just the relative
324
+ // path) at debug level - not just on error. Some SEMS endpoints use success/error
325
+ // conventions, or even entirely different API bases/paths, that differ from the
326
+ // ones this adapter was originally built and tested against, so this is the
327
+ // fastest way to diagnose reports from real accounts without needing access to
328
+ // the account's credentials.
329
+ this.log("debug", `SEMS-API-Antwort ${url}: ${JSON.stringify(json)}`);
317
330
 
318
331
  const code = json && json.code;
319
332
 
@@ -337,7 +350,7 @@ class SemsApi {
337
350
  }
338
351
 
339
352
  if (!SUCCESS_CODES.has(code) && !(json && SUCCESS_MESSAGES.has(String(json.msg).toLowerCase()))) {
340
- const msg = (json && (json.msg || json.message)) || "unbekannter Fehler";
353
+ const msg = (json && (json.msg || json.message || json.error_msg)) || "unbekannter Fehler";
341
354
  throw new SemsProtocolError(`SEMS-API-Aufruf ${path} fehlgeschlagen: ${msg} (code=${code})`);
342
355
  }
343
356
 
@@ -383,7 +396,27 @@ class SemsApi {
383
396
  if (!powerStationId) {
384
397
  throw new SemsProtocolError("getMonitorDetail() ohne powerStationId aufgerufen.");
385
398
  }
386
- return this._authenticatedPost(MONITOR_DETAIL_PATH, { powerStationId });
399
+ let lastError;
400
+ for (let i = 0; i < MONITOR_DETAIL_PATHS.length; i++) {
401
+ const path = MONITOR_DETAIL_PATHS[i];
402
+ try {
403
+ return await this._authenticatedPost(path, { powerStationId });
404
+ } catch (error) {
405
+ lastError = error;
406
+ const is404 = error instanceof SemsProtocolError && /404|route not found/i.test(error.message);
407
+ if (!is404) {
408
+ throw error;
409
+ }
410
+ const nextPath = MONITOR_DETAIL_PATHS[i + 1];
411
+ if (nextPath) {
412
+ this.log(
413
+ "debug",
414
+ `${path} nicht gefunden (404) - versuche ${nextPath} als Fallback (API-Version unterschiedlich je nach Konto/Backend).`,
415
+ );
416
+ }
417
+ }
418
+ }
419
+ throw lastError;
387
420
  }
388
421
  }
389
422
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.goodwe-sems",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
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",