iobroker.sun2000 2.4.4 → 2.5.0
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.md +10 -8
- package/admin/jsonConfig.json5 +33 -0
- package/io-package.json +29 -28
- package/lib/drivers/driver_emma.js +6 -6
- package/lib/drivers/driver_inverter.js +67 -23
- package/lib/json_helper.js +126 -0
- package/lib/modbus/modbus_server.js +1 -1
- package/lib/register.js +174 -26
- package/lib/statistics/breakdownChartHelper.js +131 -0
- package/lib/statistics/consumptionBreakdown.js +304 -0
- package/lib/statistics/statistics.js +1453 -0
- package/lib/tools.js +15 -3
- package/main.js +12 -0
- package/package.json +9 -10
- package/lib/statistics.js +0 -1477
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Read and write register data from Huawei SUN2000 inverter and LUNA2000 battery u
|
|
|
27
27
|
Feel free to follow the discussions in the german [iobroker forum](https://forum.iobroker.net/topic/71768/test-adapter-sun2000-v0-1-x-huawei-wechselrichter)
|
|
28
28
|
|
|
29
29
|
## Requirements
|
|
30
|
-
* Node.js
|
|
30
|
+
* Node.js 22 or higher
|
|
31
31
|
* ioBroker host (js-controller) 6.0.11 or higher
|
|
32
32
|
* ioBroker admin 7.6.20 or higher
|
|
33
33
|
|
|
@@ -69,6 +69,14 @@ The sun2000 adapter calculates how much of your self-generated solar energy is a
|
|
|
69
69
|
Placeholder for the next version (at the beginning of the line):
|
|
70
70
|
### **WORK IN PROGRESS**
|
|
71
71
|
-->
|
|
72
|
+
### 2.5.0 (2026-06-09)
|
|
73
|
+
* statistics: added live power chart (statistics.jsonLive)
|
|
74
|
+
|
|
75
|
+
### 2.4.5 (2026-05-14)
|
|
76
|
+
* statistics fix: return weekly range up to current Monday
|
|
77
|
+
* statistics: added support for generating statistics templates directly from built-in charts
|
|
78
|
+
* statistics: improved tooltip formatter - tooltip units are now provided explicitly via tooltip.valueFormatter
|
|
79
|
+
|
|
72
80
|
### 2.4.4 (2026-05-04)
|
|
73
81
|
* statistics fix: add error handling for waitForValue function
|
|
74
82
|
|
|
@@ -86,13 +94,7 @@ The sun2000 adapter calculates how much of your self-generated solar energy is a
|
|
|
86
94
|
* statistics: data placeholders (`%%solarYield%%`, `%%gridExport%%` etc.) allow complete chart layout control via template states
|
|
87
95
|
* statistics: chart output states (`statistics.flexCharts.jsonOutput.hourly` etc.) updated automatically each hour
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
* fix: the order of bit assignment corrected of alarmsJSON
|
|
91
|
-
* new state `inverter.x.emma.activeAlarmSN` and `inverter.x.emma.HistoricalAlarmSN` : emma alarms [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)
|
|
92
|
-
* statistics: Aggregates historical collected datapoints into time-based summaries (e.g. hourly, daily, monthly, yearly). The data is stored in the path `statistics` as JSON.
|
|
93
|
-
|
|
94
|
-
### 2.3.7 (2026-02-01)
|
|
95
|
-
* deleted deprecated state `collected.usableSurplusPower`
|
|
97
|
+
[Older changelogs can be found there](CHANGELOG_OLD.md)
|
|
96
98
|
|
|
97
99
|
## License
|
|
98
100
|
MIT License
|
package/admin/jsonConfig.json5
CHANGED
|
@@ -385,6 +385,39 @@
|
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
},
|
|
388
|
+
"tab8": {
|
|
389
|
+
"type": "panel",
|
|
390
|
+
"label": "Statistics",
|
|
391
|
+
"items": {
|
|
392
|
+
"staticLink1": {
|
|
393
|
+
"type": "staticLink",
|
|
394
|
+
"text": "Information and settings regarding the statistics explained in the wiki",
|
|
395
|
+
"href": "https://github.com/bolliy/ioBroker.sun2000/wiki/Statistk-(statistics)",
|
|
396
|
+
"button": true,
|
|
397
|
+
"icon": "info",
|
|
398
|
+
"newLine": true,
|
|
399
|
+
"xs": 12,
|
|
400
|
+
"sm": 12,
|
|
401
|
+
"md": 6,
|
|
402
|
+
"lg": 3,
|
|
403
|
+
"xl": 3
|
|
404
|
+
},
|
|
405
|
+
"stat_liveInterval": {
|
|
406
|
+
"type": "number",
|
|
407
|
+
"label": "Live chart interval (min)",
|
|
408
|
+
"min" : 1,
|
|
409
|
+
"max" : 15,
|
|
410
|
+
"newLine": true,
|
|
411
|
+
"tooltip": "Live chart update interval in minutes",
|
|
412
|
+
"xs": 12,
|
|
413
|
+
"sm": 12,
|
|
414
|
+
"md": 6,
|
|
415
|
+
"lg": 4,
|
|
416
|
+
"xl": 4
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
},
|
|
388
421
|
"tab7": {
|
|
389
422
|
"type": "panel",
|
|
390
423
|
"label": "Further Register",
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "sun2000",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.5.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.5.0": {
|
|
7
|
+
"en": "statistics: added live power chart (statistics.jsonLive)\nrequires node.js >= 22",
|
|
8
|
+
"de": "statistiken: Live Power Chart hinzugefügt (statistics.jsonLive)\nrequires node.js >= 22",
|
|
9
|
+
"ru": "статистика: добавлена живая диаграмма мощности (statistics.jsonLive)\nrequires node.js >= 22",
|
|
10
|
+
"pt": "estatísticas: gráfico de potência ao vivo adicionado (statistics.jsonLive)\nrequires node.js >= 22",
|
|
11
|
+
"nl": "statistieken: toegevoegde live power chart (statistics.jsonLive)",
|
|
12
|
+
"fr": "statistiques: tableau de puissance en direct ajouté (statistiques.jsonLive)\nrequires node.js >= 22",
|
|
13
|
+
"it": "statistiche: aggiunto live power chart (statistics.jsonLive)\nrequires node.js >= 22",
|
|
14
|
+
"es": "estadística: añadido gráfico de potencia en vivo (statistics.jsonLive)\nrequires node.js >= 22",
|
|
15
|
+
"pl": "statystyki: dodany live power chart (statistics.jsonLive)\nrequires node.js >= 22",
|
|
16
|
+
"uk": "статистика: додано графік живої потужності (statistics.jsonLive)\nrequires node.js >= 22",
|
|
17
|
+
"zh-cn": "统计:增加的实电图(统计学.jsonLive)"
|
|
18
|
+
},
|
|
19
|
+
"2.4.5": {
|
|
20
|
+
"en": "statistics fix: return weekly range up to current Monday\nstatistics: added support for generating statistics templates directly from built-in charts\nstatistics: improved tooltip formatter - tooltip units are now provided explicitly via tooltip.valueFormatter",
|
|
21
|
+
"de": "statistik fix: wöchentliche Rückgabe bis zum aktuellen Montag\nstatistik: unterstützung für die erstellung von statistiken vorlagen direkt aus integrierten diagrammen\nstatistiken: verbesserter Tooltip-Formater - Tooltip-Einheiten werden nun explizit über tooltip.valueFormatter bereitgestellt",
|
|
22
|
+
"ru": "исправление статистики: еженедельный диапазон возврата до текущего понедельника\nстатистика: добавлена поддержка для создания шаблонов статистики непосредственно из встроенных диаграмм\nстатистика: улучшенный инструментальный формататор - инструментальные блоки теперь предоставляются явно через tooltip.value",
|
|
23
|
+
"pt": "estatística correção: retorno semanal intervalo até a segunda-feira atual\nestatística: suporte adicionado para gerar modelos estatísticos diretamente de gráficos embutidos\nestatísticas: a dica de formatação melhorada - as unidades de dica são agora fornecidas explicitamente via tooltip.valueFormatter",
|
|
24
|
+
"nl": "statistieken fix: retour wekelijkse bereik tot de huidige maandag\nstatistieken: extra ondersteuning voor het genereren van statistieken templates rechtstreeks uit ingebouwde grafieken\nstatistieken: verbeterde tooltip formatter - tooltip-eenheden worden nu expliciet geleverd via tooltip.valueFormatter",
|
|
25
|
+
"fr": "correction statistique: retour hebdomadaire jusqu'à lundi actuel\nstatistiques: appui supplémentaire à la production de modèles de statistiques directement à partir de graphiques intégrés\nstatistiques: amélioration de l'outil pour la matière - les unités d'outil sont désormais fournies explicitement via tooltip.valueFormatter",
|
|
26
|
+
"it": "statistiche fix: rientro settimanale fino al lunedì corrente\nstatistiche: aggiunto il supporto per la generazione di modelli di statistiche direttamente da grafici incorporati\nstatistiche: migliorato tooltip formatter - le unità tooltip sono ora fornite esplicitamente tramite tooltip.valueFormatter",
|
|
27
|
+
"es": "solucion de estadísticas: retorno semanal hasta el lunes actual\nestadística: apoyo añadido para generar plantillas de estadísticas directamente desde gráficos incorporados\nestadística: mejorada herramienta formatter - unidades de punta de herramientas se proporcionan ahora explícitamente a través de tooltip.valueFormatter",
|
|
28
|
+
"pl": "statystyki naprawić: wrócić tygodniowy zakres do bieżącego poniedziałku\nstatystyki: dodano wsparcie dla tworzenia szablonów statystycznych bezpośrednio z wykresów built- in\nstatystyki: ulepszone formatowanie podpowiedzi narzędziowej - jednostki podpowiedzi są teraz wyraźnie dostarczane za pośrednictwem tooltip.valueFormatter",
|
|
29
|
+
"uk": "статистика виправити: повернути щотижневий діапазон до поточного понеділка\nстатистика: додана підтримка створення шаблонів статистики безпосередньо з вбудованих діаграм\nстатистика: поліпшений форматувальник інструментів - блоки інструментів тепер забезпечують явно через tooltip.valueFormatter",
|
|
30
|
+
"zh-cn": "统计修补:截至本星期一的每周返回范围\n统计:为直接从内建图表生成统计模板提供更多支持\n统计:改进后的工具提示用于物质-工具提示单位现在通过工具提示明确提供. valueFormatter"
|
|
31
|
+
},
|
|
6
32
|
"2.4.4": {
|
|
7
33
|
"en": "statistics fix: add error handling for waitForValue function",
|
|
8
34
|
"de": "statistik fix: Fehlerbehandlung für waitForValue-Funktion hinzufügen",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "usunięty stan zdepregatowany \"collected.usableSurplusPower '",
|
|
68
94
|
"uk": "вилучена депресована держава `collected.usableSurplusPower й",
|
|
69
95
|
"zh-cn": "删除已贬值状态“ 已收集。 可使用 SurplusPower `"
|
|
70
|
-
},
|
|
71
|
-
"2.3.6": {
|
|
72
|
-
"en": "dependency and configuration updates\nnew state `inverter.x.derived.alarmsJSON` : json array with intverter alarms (id, name, level) [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nadd ChargeDischargePower for Battery units [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\nadd minimum and maximum temperature for battery packs [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
73
|
-
"de": "abhängigkeits- und konfigurationsupdates\nneuer Zustand `inverter.x.derived.alarmsJSON`: json array with intverter alarms (id, name, level) [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nadd ChargeDischargePower for Battery Units [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\nmindest- und Höchsttemperatur für Akkupacks [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
74
|
-
"ru": "обновления зависимостей и конфигурации\njson array with intverter alarms (id, name, level) [#226] (https://github.com/bolliy/ioBroker.sun2000/issues/226)\nдобавить ChargeDischargePower для батарейных блоков [#234] (https://github.com/bolliy/ioBroker.sun2000/issues/234)\nдобавить минимальную и максимальную температуру для аккумуляторных батарей [#236] (https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
75
|
-
"pt": "atualizações de dependência e configuração\nnovo estado `inverter.x.derived.alarmsJSON` : json array com alarmes de inversor (id, name, level) [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nadicionar ChargeDischargePower for Battery units [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\nadicionar temperatura mínima e máxima para pacotes de bateria [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
76
|
-
"nl": "afhankelijkheid en configuratie-updates\nnieuwe staat \nchargeDischargePower for Battery units [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\nminimum- en maximumtemperatuur toevoegen voor batterijpakketten [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
77
|
-
"fr": "mises à jour de la dépendance et de la configuration\nnouvel état `inverter.x.derived.alarmsJSON` : tableau json avec alarmes d'intverter (id, nom, niveau) [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\najouter ChargeDischargePower pour les unités de batterie [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\najouter la température minimale et maximale pour les batteries [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
78
|
-
"it": "aggiornamenti di dipendenza e configurazione\nnuovo stato `inverter.x.derived.alarmsJSON` : json array con allarme intverter (id, nome, livello) [#226](https://github.com/bolliy/ioBroker.sun2000/problems/226)\naggiungi ChargeDischargePower per batterie [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\naggiungere la temperatura minima e massima per le batterie [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
79
|
-
"es": "actualizaciones de dependencia y configuración\nnuevo estado `inverter.x.derived.alarmsJSON` : json array with intverter alarms (id, name, level) [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nañadir ChargeDischargePower for Battery units [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\nañadir la temperatura mínima y máxima para los paquetes de baterías [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)",
|
|
80
|
-
"pl": "aktualizacje zależności i konfiguracji\nnowość \"inverter.x.derived.alarmsJSON\": tablica json z alarmami intverter (id, name, level) [# 226] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 226)\ndata umieszczenia w wykazie\ndodać minimalną i maksymalną temperaturę dla baterii [# 236] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 236)",
|
|
81
|
-
"uk": "оновлення залежності та конфігурації\nновий стан `inverter.x.derived.alarmsJSON` : json array with intverter тривоги (id, назва, рівень) [#226](https://github.com/bolliy/ioBroker.sun2000/products/226)\nadd ChargeDischargePower для батарей [#234](https://github.com/bolliy/ioBroker.sun2000/products/234)\nдодайте мінімальну і максимальну температуру для акумуляторних пакетів [#236](https://github.com/bolliy/ioBroker.sun2000/products/236)",
|
|
82
|
-
"zh-cn": "依赖和配置更新\nnew state `inverter.x. inducted.alarmsJSON ' : json 数组带内置式警报器(id, name, level) [# 226] (https://github.com/bolliy/ioBroker.sun2000/issues/226) (中文(简体) )\n添加电池单位充电放电器[#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)\n增加电池包的最低和最高温度[第236号](https://github.com/bolliy/ioBroker.sun2000/issues/236)"
|
|
83
|
-
},
|
|
84
|
-
"2.3.5": {
|
|
85
|
-
"en": "dependency and configuration updates\nBattery status check was suspended in inverter control [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\nEmma: dynamic detection of sun2000 inverters and integration of devices such as sun2000\nallow Modbus ID 0 when using the sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
86
|
-
"de": "abhängigkeits- und konfigurationsupdates\nDie Batteriestatusprüfung wurde in der Wechselrichtersteuerung [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220) ausgesetzt\nEmma: dynamische Erkennung von Wechselrichtern von Sun2000 und Integration von Geräten wie sun2000\nerlauben Sie Modbus ID 0 bei Verwendung des sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
87
|
-
"ru": "обновления зависимостей и конфигурации\nПроверка состояния батареи была приостановлена в инверторном управлении [#220] (https://github.com/bolliy/ioBroker.sun2000/issues/220)\nЭмма: динамическое обнаружение инверторов Sun2000 и интеграция таких устройств, как Sun2000\nразрешить Modbus ID 0 при использовании sDongle [#218] (https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
88
|
-
"pt": "atualizações de dependência e configuração\nA verificação do estado da bateria foi suspensa no controle do inversor [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\nEmma: detecção dinâmica de inversores sun2000 e integração de dispositivos como sun2000\npermitir Modbus ID 0 ao usar o sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
89
|
-
"nl": "afhankelijkheid en configuratie-updates\nDe controle van de status van de batterij werd opgeschort bij controle van de inverter [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\nEmma: dynamische detectie van zonne2000 omvormers en integratie van apparaten zoals sun2000\nmodbus ID 0 toestaan bij gebruik van sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
90
|
-
"fr": "mises à jour de la dépendance et de la configuration\nLe contrôle de l'état de la batterie a été suspendu dans le contrôle de l'onduleur [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\nEmma : détection dynamique des onduleurs Sun2000 et intégration de dispositifs tels que Sun2000\npermettre Modbus ID 0 lors de l'utilisation de sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
91
|
-
"it": "aggiornamenti di dipendenza e configurazione\nIl controllo dello stato della batteria è stato sospeso nel controllo dell'inverter [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\nEmma: rilevazione dinamica degli inverter Sun2000 e integrazione di dispositivi come sun2000\nconsentire Modbus ID 0 quando si utilizza lo sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
92
|
-
"es": "actualizaciones de dependencia y configuración\nSe suspendió el control del estado de la batería [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\nEmma: detección dinámica de inversores de sol2000 e integración de dispositivos como el sol2000\npermitir Modbus ID 0 al utilizar el sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
93
|
-
"pl": "aktualizacje zależności i konfiguracji\nKontrola stanu baterii została zawieszona w kontrolach inwertera [# 220] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 220)\nEmma: dynamiczna detekcja inwerterów sun2000 i integracja urządzeń takich jak sun2000\nw przypadku stosowania sDongle [# 218] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 118)",
|
|
94
|
-
"uk": "оновлення залежності та конфігурації\nПеревірка стану акумулятора була припинена в інверторному режимі [#220] (https://github.com/bolliy/ioBroker.sun2000/issues/220)\nЕмма: динамічне виявлення інверторів сонця2000 та інтеграції пристроїв, таких як сонце2000\nдозволити Modbus ID 0 при використанні sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/118)",
|
|
95
|
-
"zh-cn": "依赖和配置更新\n在反转控制中暂停了电池状态检查[#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)\n艾玛:对太阳2000反转器的动态检测和太阳2000等设备的集成\n允许在使用 sDongle [# 218] 时使用 Modbus ID (https:// github.com/ bolliy/ioBroker.sun2000/issues/118) "
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
|
@@ -251,7 +251,8 @@
|
|
|
251
251
|
"ds_bu": true,
|
|
252
252
|
"ds_bp": false,
|
|
253
253
|
"cb_tou": false,
|
|
254
|
-
"integration": 0
|
|
254
|
+
"integration": 0,
|
|
255
|
+
"stat_liveInterval": 5
|
|
255
256
|
},
|
|
256
257
|
"objects": [],
|
|
257
258
|
"instanceObjects": [
|
|
@@ -707,9 +707,9 @@ class Emma extends DriverBase {
|
|
|
707
707
|
type: 'number',
|
|
708
708
|
unit: 'kW',
|
|
709
709
|
role: 'value.power',
|
|
710
|
-
desc: 'reg:
|
|
710
|
+
desc: 'reg:31665, len:2',
|
|
711
711
|
},
|
|
712
|
-
register: { reg:
|
|
712
|
+
register: { reg: 31665, type: dataType.int32, gain: 1000 },
|
|
713
713
|
},
|
|
714
714
|
{
|
|
715
715
|
state: {
|
|
@@ -718,9 +718,9 @@ class Emma extends DriverBase {
|
|
|
718
718
|
type: 'number',
|
|
719
719
|
unit: 'kW',
|
|
720
720
|
role: 'value.power',
|
|
721
|
-
desc: 'reg:
|
|
721
|
+
desc: 'reg:31667, len:2',
|
|
722
722
|
},
|
|
723
|
-
register: { reg:
|
|
723
|
+
register: { reg: 31667, type: dataType.int32, gain: 1000 },
|
|
724
724
|
},
|
|
725
725
|
{
|
|
726
726
|
state: {
|
|
@@ -729,9 +729,9 @@ class Emma extends DriverBase {
|
|
|
729
729
|
type: 'number',
|
|
730
730
|
unit: 'kW',
|
|
731
731
|
role: 'value.power',
|
|
732
|
-
desc: 'reg:
|
|
732
|
+
desc: 'reg:31669, len:2',
|
|
733
733
|
},
|
|
734
|
-
register: { reg:
|
|
734
|
+
register: { reg: 31669, type: dataType.int32, gain: 1000 },
|
|
735
735
|
},
|
|
736
736
|
{
|
|
737
737
|
state: {
|
|
@@ -104,6 +104,19 @@ class InverterSun2000 extends DriverBase {
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
+
this.chargeSumHelper = new RiemannSum();
|
|
108
|
+
this.adapter.getState(`${this.deviceInfo.path}.battery.currentDayChargeCapacity`, (err, state) => {
|
|
109
|
+
if (!err && state) {
|
|
110
|
+
this.chargeSumHelper.setStart(state?.val, state?.ts, false);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
this.dischargeSumHelper = new RiemannSum();
|
|
114
|
+
this.adapter.getState(`${this.deviceInfo.path}.battery.currentDayDischargeCapacity`, (err, state) => {
|
|
115
|
+
if (!err && state) {
|
|
116
|
+
this.dischargeSumHelper.setStart(state?.val, state?.ts, false);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
107
120
|
this.control = new ServiceQueueMap(this.adapter, this.deviceInfo);
|
|
108
121
|
|
|
109
122
|
//https://github.com/ioBroker/ioBroker.docs/blob/master/docs/en/dev/stateroles.md
|
|
@@ -222,6 +235,35 @@ class InverterSun2000 extends DriverBase {
|
|
|
222
235
|
],
|
|
223
236
|
//Check if the address field is active
|
|
224
237
|
checkIfActive: () => this._batteryExists(),
|
|
238
|
+
postHook: path => {
|
|
239
|
+
//calculate daily charge and discharge capacity
|
|
240
|
+
const chargeDischargePower = this.stateCache.get(`${path}battery.chargeDischargePower`)?.value ?? 0;
|
|
241
|
+
if (chargeDischargePower > 0) this.chargeSumHelper.add(chargeDischargePower); //riemann Sum for charge power
|
|
242
|
+
if (chargeDischargePower < 0) this.dischargeSumHelper.add(-chargeDischargePower); //riemann Sum for discharge power
|
|
243
|
+
|
|
244
|
+
const now = new Date();
|
|
245
|
+
const minute = now.getMinutes();
|
|
246
|
+
const hour = now.getHours();
|
|
247
|
+
//reset at 00:00 - until 00:05 if the inverter is a bit late with the update
|
|
248
|
+
if (hour !== 0 || minute > 5) {
|
|
249
|
+
const currentDayChargeCapacity = this.stateCache.get(`${path}battery.currentDayChargeCapacity`)?.value;
|
|
250
|
+
if (currentDayChargeCapacity !== undefined) {
|
|
251
|
+
if (!this.chargeSumHelper.startInitialized || currentDayChargeCapacity > this.chargeSumHelper.sum) {
|
|
252
|
+
this.chargeSumHelper.setStart(currentDayChargeCapacity);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const currentDayDischargeCapacity = this.stateCache.get(`${path}battery.currentDayDischargeCapacity`)?.value;
|
|
257
|
+
if (currentDayDischargeCapacity !== undefined) {
|
|
258
|
+
if (!this.dischargeSumHelper.startInitialized || currentDayDischargeCapacity > this.dischargeSumHelper.sum) {
|
|
259
|
+
this.dischargeSumHelper.setStart(currentDayDischargeCapacity);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
this.stateCache.set(`${path}battery.statistics.currentDayChargeCapacity`, this.chargeSumHelper.sum, { type: 'number', stored: true }); //stored for statistics
|
|
265
|
+
this.stateCache.set(`${path}battery.statistics.currentDayDischargeCapacity`, this.dischargeSumHelper.sum, { type: 'number', stored: true }); //stored for statistics
|
|
266
|
+
},
|
|
225
267
|
},
|
|
226
268
|
{
|
|
227
269
|
address: 32064,
|
|
@@ -236,7 +278,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
236
278
|
name: 'Input power',
|
|
237
279
|
type: 'number',
|
|
238
280
|
unit: 'kW',
|
|
239
|
-
role: 'value.power
|
|
281
|
+
role: 'value.power',
|
|
240
282
|
desc: 'reg:32064, len:2, Power from solar',
|
|
241
283
|
},
|
|
242
284
|
register: { reg: 32064, type: dataType.int32, gain: 1000 },
|
|
@@ -465,7 +507,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
465
507
|
name: 'Total charge',
|
|
466
508
|
type: 'number',
|
|
467
509
|
unit: 'kWh',
|
|
468
|
-
role: 'value.power.
|
|
510
|
+
role: 'value.power.consumed',
|
|
469
511
|
desc: 'reg:38238, len:2',
|
|
470
512
|
},
|
|
471
513
|
register: { reg: 38238, type: dataType.uint32, gain: 100 },
|
|
@@ -476,7 +518,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
476
518
|
name: 'Total discharge',
|
|
477
519
|
type: 'number',
|
|
478
520
|
unit: 'kWh',
|
|
479
|
-
role: 'value.power.
|
|
521
|
+
role: 'value.power.produced',
|
|
480
522
|
desc: 'reg:38240, len:2',
|
|
481
523
|
},
|
|
482
524
|
register: { reg: 38240, type: dataType.uint32, gain: 100 },
|
|
@@ -508,7 +550,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
508
550
|
name: 'Total charge',
|
|
509
551
|
type: 'number',
|
|
510
552
|
unit: 'kWh',
|
|
511
|
-
role: 'value.power.
|
|
553
|
+
role: 'value.power.consumed',
|
|
512
554
|
desc: 'reg:38280, len:2',
|
|
513
555
|
},
|
|
514
556
|
register: { reg: 38280, type: dataType.uint32, gain: 100 },
|
|
@@ -519,7 +561,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
519
561
|
name: 'Total discharge',
|
|
520
562
|
type: 'number',
|
|
521
563
|
unit: 'kWh',
|
|
522
|
-
role: 'value.power.
|
|
564
|
+
role: 'value.power.produced',
|
|
523
565
|
desc: 'reg:38282, len:2',
|
|
524
566
|
},
|
|
525
567
|
register: { reg: 38282, type: dataType.uint32, gain: 100 },
|
|
@@ -551,7 +593,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
551
593
|
name: 'Total charge',
|
|
552
594
|
type: 'number',
|
|
553
595
|
unit: 'kWh',
|
|
554
|
-
role: 'value.power.
|
|
596
|
+
role: 'value.power.consumed',
|
|
555
597
|
desc: 'reg:38322, len:2',
|
|
556
598
|
},
|
|
557
599
|
register: { reg: 38322, type: dataType.uint32, gain: 100 },
|
|
@@ -562,7 +604,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
562
604
|
name: 'Total discharge',
|
|
563
605
|
type: 'number',
|
|
564
606
|
unit: 'kWh',
|
|
565
|
-
role: 'value.power.
|
|
607
|
+
role: 'value.power.produced',
|
|
566
608
|
desc: 'reg:38324, len:2',
|
|
567
609
|
},
|
|
568
610
|
register: { reg: 38324, type: dataType.uint32, gain: 100 },
|
|
@@ -843,7 +885,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
843
885
|
name: 'Total charge',
|
|
844
886
|
type: 'number',
|
|
845
887
|
unit: 'kWh',
|
|
846
|
-
role: 'value.power.
|
|
888
|
+
role: 'value.power.consumed',
|
|
847
889
|
desc: 'reg:37780, len:2',
|
|
848
890
|
},
|
|
849
891
|
register: { reg: 37780, type: dataType.uint32, gain: 100 },
|
|
@@ -854,7 +896,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
854
896
|
name: 'Total discharge',
|
|
855
897
|
type: 'number',
|
|
856
898
|
unit: 'kWh',
|
|
857
|
-
role: 'value.power.
|
|
899
|
+
role: 'value.power.produced',
|
|
858
900
|
desc: 'reg:37782, len:2',
|
|
859
901
|
},
|
|
860
902
|
register: { reg: 37782, type: dataType.uint32, gain: 100 },
|
|
@@ -865,10 +907,11 @@ class InverterSun2000 extends DriverBase {
|
|
|
865
907
|
name: 'Current day charge capacity',
|
|
866
908
|
type: 'number',
|
|
867
909
|
unit: 'kWh',
|
|
868
|
-
role: 'value.power.
|
|
910
|
+
role: 'value.power.consumed',
|
|
869
911
|
desc: 'reg:37784, len:2',
|
|
870
912
|
},
|
|
871
913
|
register: { reg: 37784, type: dataType.uint32, gain: 100 },
|
|
914
|
+
//store: storeType.never,
|
|
872
915
|
},
|
|
873
916
|
{
|
|
874
917
|
state: {
|
|
@@ -876,10 +919,11 @@ class InverterSun2000 extends DriverBase {
|
|
|
876
919
|
name: 'Current day discharge capacity',
|
|
877
920
|
type: 'number',
|
|
878
921
|
unit: 'kWh',
|
|
879
|
-
role: 'value.power.
|
|
922
|
+
role: 'value.power.produced',
|
|
880
923
|
desc: 'reg:37786, len:2',
|
|
881
924
|
},
|
|
882
925
|
register: { reg: 37786, type: dataType.uint32, gain: 100 },
|
|
926
|
+
//store: storeType.never,
|
|
883
927
|
},
|
|
884
928
|
],
|
|
885
929
|
checkIfActive: () => this._batteryExists(),
|
|
@@ -1466,7 +1510,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
1466
1510
|
name: 'Positive active energy',
|
|
1467
1511
|
type: 'number',
|
|
1468
1512
|
unit: 'kWh',
|
|
1469
|
-
role: 'value.power.
|
|
1513
|
+
role: 'value.power.produced',
|
|
1470
1514
|
desc: 'reg:37119, len:2',
|
|
1471
1515
|
},
|
|
1472
1516
|
register: { reg: 37119, type: dataType.int32, gain: 100 },
|
|
@@ -1477,7 +1521,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
1477
1521
|
name: 'Reverse active energy',
|
|
1478
1522
|
type: 'number',
|
|
1479
1523
|
unit: 'kWh',
|
|
1480
|
-
role: 'value.power.
|
|
1524
|
+
role: 'value.power.consumed',
|
|
1481
1525
|
desc: 'reg:37121, len:2',
|
|
1482
1526
|
},
|
|
1483
1527
|
register: { reg: 37121, type: dataType.int32, gain: 100 },
|
|
@@ -1488,7 +1532,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
1488
1532
|
name: 'Accumulated reactive power',
|
|
1489
1533
|
type: 'number',
|
|
1490
1534
|
unit: 'kVarh',
|
|
1491
|
-
role: 'value.power.reactive.
|
|
1535
|
+
role: 'value.power.reactive.consumed',
|
|
1492
1536
|
desc: 'reg:37123, len:2',
|
|
1493
1537
|
},
|
|
1494
1538
|
register: { reg: 37123, type: dataType.int32, gain: 100 },
|
|
@@ -1643,7 +1687,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
1643
1687
|
name: 'Portal yield today',
|
|
1644
1688
|
type: 'number',
|
|
1645
1689
|
unit: 'kWh',
|
|
1646
|
-
role: 'value.power.
|
|
1690
|
+
role: 'value.power.produced',
|
|
1647
1691
|
desc: 'yield from the portal',
|
|
1648
1692
|
},
|
|
1649
1693
|
fn: path => {
|
|
@@ -1666,7 +1710,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
1666
1710
|
name: 'Solar yield today',
|
|
1667
1711
|
type: 'number',
|
|
1668
1712
|
unit: 'kWh',
|
|
1669
|
-
role: 'value.power.
|
|
1713
|
+
role: 'value.power.produced',
|
|
1670
1714
|
desc: 'Riemann sum of input power with efficiency loss',
|
|
1671
1715
|
},
|
|
1672
1716
|
fn: path => {
|
|
@@ -1680,7 +1724,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
1680
1724
|
name: 'Active Energy today',
|
|
1681
1725
|
type: 'number',
|
|
1682
1726
|
unit: 'kWh',
|
|
1683
|
-
role: 'value.power.
|
|
1727
|
+
role: 'value.power.produced',
|
|
1684
1728
|
desc: 'Amount of Riemann sum of sum of active power',
|
|
1685
1729
|
},
|
|
1686
1730
|
fn: path => {
|
|
@@ -2104,7 +2148,7 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
2104
2148
|
name: 'Total charge',
|
|
2105
2149
|
type: 'number',
|
|
2106
2150
|
unit: 'kWh',
|
|
2107
|
-
role: 'value.power.
|
|
2151
|
+
role: 'value.power.consumed',
|
|
2108
2152
|
desc: 'reg:38364, len:2',
|
|
2109
2153
|
},
|
|
2110
2154
|
register: { reg: 38364, type: dataType.uint32, gain: 100 },
|
|
@@ -2115,7 +2159,7 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
2115
2159
|
name: 'Total discharge',
|
|
2116
2160
|
type: 'number',
|
|
2117
2161
|
unit: 'kWh',
|
|
2118
|
-
role: 'value.power.
|
|
2162
|
+
role: 'value.power.produced',
|
|
2119
2163
|
desc: 'reg:38366, len:2',
|
|
2120
2164
|
},
|
|
2121
2165
|
register: { reg: 38366, type: dataType.uint32, gain: 100 },
|
|
@@ -2147,7 +2191,7 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
2147
2191
|
name: 'Total charge',
|
|
2148
2192
|
type: 'number',
|
|
2149
2193
|
unit: 'kWh',
|
|
2150
|
-
role: 'value.power.
|
|
2194
|
+
role: 'value.power.consumed',
|
|
2151
2195
|
desc: 'reg:38406, len:2',
|
|
2152
2196
|
},
|
|
2153
2197
|
register: { reg: 38406, type: dataType.uint32, gain: 100 },
|
|
@@ -2158,7 +2202,7 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
2158
2202
|
name: 'Total discharge',
|
|
2159
2203
|
type: 'number',
|
|
2160
2204
|
unit: 'kWh',
|
|
2161
|
-
role: 'value.power.
|
|
2205
|
+
role: 'value.power.produced',
|
|
2162
2206
|
desc: 'reg:38408, len:2',
|
|
2163
2207
|
},
|
|
2164
2208
|
register: { reg: 38408, type: dataType.uint32, gain: 100 },
|
|
@@ -2190,7 +2234,7 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
2190
2234
|
name: 'Total charge',
|
|
2191
2235
|
type: 'number',
|
|
2192
2236
|
unit: 'kWh',
|
|
2193
|
-
role: 'value.power.
|
|
2237
|
+
role: 'value.power.consumed',
|
|
2194
2238
|
desc: 'reg:38448, len:2',
|
|
2195
2239
|
},
|
|
2196
2240
|
register: { reg: 38448, type: dataType.uint32, gain: 100 },
|
|
@@ -2201,7 +2245,7 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
2201
2245
|
name: 'Total discharge',
|
|
2202
2246
|
type: 'number',
|
|
2203
2247
|
unit: 'kWh',
|
|
2204
|
-
role: 'value.power.
|
|
2248
|
+
role: 'value.power.produced',
|
|
2205
2249
|
desc: 'reg:38450, len:2',
|
|
2206
2250
|
},
|
|
2207
2251
|
register: { reg: 38450, type: dataType.uint32, gain: 100 },
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Serializes an object to JSON, converting functions to their string representation.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} obj - The object to serialize.
|
|
7
|
+
* @returns {string} JSON string where functions are represented as strings.
|
|
8
|
+
*/
|
|
9
|
+
function stringifyWithFunctions(obj) {
|
|
10
|
+
return JSON.stringify(
|
|
11
|
+
obj,
|
|
12
|
+
(key, value) => {
|
|
13
|
+
if (typeof value === 'function') {
|
|
14
|
+
return value.toString();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (value === undefined) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
},
|
|
22
|
+
2,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const FUNCTION_KEYS = ['formatter', 'parser', 'render', 'labelFormatter', 'valueFormatter', 'position', 'interval'];
|
|
27
|
+
|
|
28
|
+
function reviveFunctions(obj, key = '') {
|
|
29
|
+
if (typeof obj === 'string' && FUNCTION_KEYS.includes(key)) {
|
|
30
|
+
const str = obj.trim();
|
|
31
|
+
|
|
32
|
+
// Arrow Function erkennen
|
|
33
|
+
if (str.includes('=>')) {
|
|
34
|
+
try {
|
|
35
|
+
return new Function(`return (${str})`)();
|
|
36
|
+
} catch {
|
|
37
|
+
return obj;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// klassische function() {} erkennen
|
|
42
|
+
if (str.startsWith('function')) {
|
|
43
|
+
try {
|
|
44
|
+
return new Function(`return (${str})`)();
|
|
45
|
+
} catch {
|
|
46
|
+
return obj;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
52
|
+
for (const key in obj) {
|
|
53
|
+
obj[key] = reviveFunctions(obj[key], key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return obj;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Deeply merges source object properties into the target object.
|
|
62
|
+
*
|
|
63
|
+
* @param {object} target - The target object to merge into.
|
|
64
|
+
* @param {object} source - The source object whose properties are merged.
|
|
65
|
+
* @returns {object} The merged target object.
|
|
66
|
+
*/
|
|
67
|
+
function deepMerge(target, source) {
|
|
68
|
+
for (const key of Object.keys(source)) {
|
|
69
|
+
if (
|
|
70
|
+
source[key] !== null &&
|
|
71
|
+
typeof source[key] === 'object' &&
|
|
72
|
+
!Array.isArray(source[key]) &&
|
|
73
|
+
target[key] !== null &&
|
|
74
|
+
typeof target[key] === 'object' &&
|
|
75
|
+
!Array.isArray(target[key])
|
|
76
|
+
) {
|
|
77
|
+
deepMerge(target[key], source[key]);
|
|
78
|
+
} else {
|
|
79
|
+
target[key] = source[key];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return target;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Sets a value on an object using a dot‑separated path, creating intermediate objects as needed.
|
|
87
|
+
*
|
|
88
|
+
* @param {object} obj - The object to modify.
|
|
89
|
+
* @param {string} path - Dot‑separated path (e.g., "a.b.c").
|
|
90
|
+
* @param {string} value - The value to set at the specified path.
|
|
91
|
+
*/
|
|
92
|
+
function setByPath(obj, path, value) {
|
|
93
|
+
const keys = path.split('.');
|
|
94
|
+
let current = obj;
|
|
95
|
+
|
|
96
|
+
while (keys.length > 1) {
|
|
97
|
+
const key = keys.shift();
|
|
98
|
+
|
|
99
|
+
if (!(key in current)) {
|
|
100
|
+
current[key] = {};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
current = current[key];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
current[keys[0]] = value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Applies a set of overrides to a target object based on dot‑separated paths.
|
|
111
|
+
*
|
|
112
|
+
* @param {object} target - The target object to which overrides are applied.
|
|
113
|
+
* @param {object} overrides - An object whose keys are dot‑separated paths and values are the overrides.
|
|
114
|
+
*/
|
|
115
|
+
function applyOverrides(target, overrides) {
|
|
116
|
+
for (const path in overrides) {
|
|
117
|
+
setByPath(target, path, overrides[path]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
stringifyWithFunctions,
|
|
123
|
+
reviveFunctions,
|
|
124
|
+
deepMerge,
|
|
125
|
+
applyOverrides,
|
|
126
|
+
};
|
|
@@ -194,7 +194,7 @@ class ModbusServer {
|
|
|
194
194
|
* @param {number} startAddr The start address of the register.
|
|
195
195
|
* @param {number} length The length of the register.
|
|
196
196
|
* @param {number} unitId The modbus unitId.
|
|
197
|
-
* @param {
|
|
197
|
+
* @param {callback} callback The callback function.
|
|
198
198
|
* @returns {Promise<void>}
|
|
199
199
|
*/
|
|
200
200
|
|