iobroker.sun2000 2.3.5 → 2.3.7
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/LICENSE +1 -1
- package/README.md +11 -2
- package/io-package.json +27 -27
- package/lib/alarms.js +91 -0
- package/lib/drivers/driver_base.js +4 -2
- package/lib/drivers/driver_emma.js +5 -2
- package/lib/drivers/driver_inverter.js +241 -17
- package/lib/modbus/modbus_connect.js +6 -0
- package/lib/register.js +28 -13
- package/main.js +12 -22
- package/package.json +3 -3
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 bolliy <stephan@mante.info>
|
|
3
|
+
Copyright (c) 2025-2026 bolliy <stephan@mante.info>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -65,11 +65,20 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
|
|
|
65
65
|
Placeholder for the next version (at the beginning of the line):
|
|
66
66
|
### **WORK IN PROGRESS**
|
|
67
67
|
-->
|
|
68
|
+
### 2.3.7 (2026-02-01)
|
|
69
|
+
* deleted deprecated state `collected.usableSurplusPower`
|
|
70
|
+
|
|
71
|
+
### 2.3.6 (2026-01-29)
|
|
72
|
+
* dependency and configuration updates
|
|
73
|
+
* new state `inverter.x.derived.alarmsJSON` : json array with intverter alarms (id, name, level) [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)
|
|
74
|
+
* add ChargeDischargePower for Battery units [#234](https://github.com/bolliy/ioBroker.sun2000/issues/234)
|
|
75
|
+
* add minimum and maximum temperature for battery packs [#236](https://github.com/bolliy/ioBroker.sun2000/issues/236)
|
|
76
|
+
|
|
68
77
|
### 2.3.5 (2025-11-17)
|
|
69
78
|
* dependency and configuration updates
|
|
70
79
|
* Battery status check was suspended in inverter control [#220](https://github.com/bolliy/ioBroker.sun2000/issues/220)
|
|
71
80
|
* Emma: dynamic detection of sun2000 inverters and integration of devices such as sun2000
|
|
72
|
-
* allow Modbus ID 0 when using the sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/
|
|
81
|
+
* allow Modbus ID 0 when using the sDongle [#218](https://github.com/bolliy/ioBroker.sun2000/issues/218)
|
|
73
82
|
|
|
74
83
|
### 2.3.4 (2025-11-01)
|
|
75
84
|
* dependency and configuration updates
|
|
@@ -325,7 +334,7 @@ initial release
|
|
|
325
334
|
## License
|
|
326
335
|
MIT License
|
|
327
336
|
|
|
328
|
-
Copyright (c) 2025 bolliy <stephan@mante.info>
|
|
337
|
+
Copyright (c) 2025-2026 bolliy <stephan@mante.info>
|
|
329
338
|
|
|
330
339
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
331
340
|
of this software and associated documentation files (the "Software"), to deal
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "sun2000",
|
|
4
|
-
"version": "2.3.
|
|
4
|
+
"version": "2.3.7",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.3.7": {
|
|
7
|
+
"en": "deleted deprecated state `collected.usableSurplusPower`",
|
|
8
|
+
"de": "gelöschter deprecated state `collect.usableSurplusPower `",
|
|
9
|
+
"ru": "удаленное устаревшее состояние 'collected.usableSurplusPower пункт",
|
|
10
|
+
"pt": "estado desactualizado excluído `colected.usableSurplusPower `",
|
|
11
|
+
"nl": "verwijderde verouderde staat Wat",
|
|
12
|
+
"fr": "état obsolète supprimé `collected.usableSurplusPower \"",
|
|
13
|
+
"it": "cancellato stato deprecato `colletto.usableSurplusPower #",
|
|
14
|
+
"es": "borrado estado deprecatado `collected.usableSurplusPower `",
|
|
15
|
+
"pl": "usunięty stan zdepregatowany \"collected.usableSurplusPower '",
|
|
16
|
+
"uk": "вилучена депресована держава `collected.usableSurplusPower й",
|
|
17
|
+
"zh-cn": "删除已贬值状态“ 已收集。 可使用 SurplusPower `"
|
|
18
|
+
},
|
|
19
|
+
"2.3.6": {
|
|
20
|
+
"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)",
|
|
21
|
+
"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)",
|
|
22
|
+
"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)",
|
|
23
|
+
"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)",
|
|
24
|
+
"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)",
|
|
25
|
+
"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)",
|
|
26
|
+
"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)",
|
|
27
|
+
"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)",
|
|
28
|
+
"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)",
|
|
29
|
+
"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)",
|
|
30
|
+
"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)"
|
|
31
|
+
},
|
|
6
32
|
"2.3.5": {
|
|
7
33
|
"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)",
|
|
8
34
|
"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)",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "fix: obsługi potencjalnych wartości null w ustawieniu metody rejestru Mapa",
|
|
68
94
|
"uk": "виправити: обробляти потенціал null значення в встановленому методі Реєстру Мапа",
|
|
69
95
|
"zh-cn": "固定值:在设定的登记方法中处理潜在的无效值 地图"
|
|
70
|
-
},
|
|
71
|
-
"2.3.0": {
|
|
72
|
-
"en": "new release for npm migrates to Trusted Publishing",
|
|
73
|
-
"de": "neue Veröffentlichung für npm migriert Trusted Publishing",
|
|
74
|
-
"ru": "новый релиз для npm перенесен в Trusted Publishing",
|
|
75
|
-
"pt": "nova versão para npm migra para a publicação confiável",
|
|
76
|
-
"nl": "nieuwe release voor npm-migraties naar Trusted Publishing",
|
|
77
|
-
"fr": "nouvelle version pour npm migre vers Trusted Publishing",
|
|
78
|
-
"it": "nuovo rilascio per npm migra a Trusted Publishing",
|
|
79
|
-
"es": "nueva versión para npm migrates a Trusted Publishing",
|
|
80
|
-
"pl": "nowa wersja dla migratów npm do zaufanej publikacji",
|
|
81
|
-
"uk": "новий реліз для npm migrats для Trusted Publishing",
|
|
82
|
-
"zh-cn": "npm 的新版本迁移到信任出版"
|
|
83
|
-
},
|
|
84
|
-
"2.2.1-alpha.0": {
|
|
85
|
-
"en": "inverter control: add same state for startup and shutdown an inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfix: Device status name has been corrected [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\nadd undocumented device status `Shutdown: End of the ESS discharge process` \nemma control: new state ` emma.control.battery.ESSControlMode`. You can now configure EMMA with TOU-mode (Time of Use) to charge the battery from grid. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nif an Emma is installed, some control states of the inverter are deactivated (read only). Mainly for the grid settings.\ndeprecated control states have been removed.\na workaround for issue [#582](https://github.com/yaacov/node-modbus-serial/issues/582) of node-modbus-serial has been implemented.",
|
|
86
|
-
"de": "inverter-Steuerung: Fügen Sie den gleichen Zustand für Start und Abschaltung eines Inverters [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199) hinzu\nbehoben: Gerätestatusname wurde korrigiert [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\n`Shutdown: Ende des ESS-Entladungsvorgangs`\nemma control: new state ` emma.control.battery.ESSControlMode`. Sie können nun EMMA mit TOU-Modus (Time of Use) konfigurieren, um den Akku aus dem Netz zu laden. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nwenn eine Emma installiert ist, werden einige Steuerzustände des Wechselrichters deaktiviert (nur lesen). Hauptsächlich für die Netzeinstellungen.\ndeprekierte steuerzustände wurden entfernt.\nein workaround für ausgabe [#582](https://github.com/yaacov/node-modbus-serial/issues/582) von node-modbus-serial wurde implementiert.",
|
|
87
|
-
"ru": "инверторное управление: добавьте то же состояние для запуска и отключения инвертора [#199] (https://github.com/bolliy/ioBroker.sun2000/issues/199)\nисправление: имя статуса устройства было исправлено [#202] (https://github.com/bolliy/ioBroker.sun2000/pull/202)\nдобавить незарегистрированный статус устройства «Shutdown: End of the ESS discharge process»\nemma control: emma.control.battery.ESSControlMode. Теперь вы можете настроить EMMA с режимом TOU (Время использования) для зарядки батареи из сетки. [#200] (https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nесли установлена Эмма, некоторые контрольные состояния инвертора деактивируются (только чтение). В основном для настроек сетки.\nустаревшие контрольные штаты были удалены.\nбыл реализован обходной путь для выпуска [#582] (https://github.com/yaacov/node-modbus-serial/issues/582) node-modbus-serial.",
|
|
88
|
-
"pt": "controle do inversor: adicione o mesmo estado para iniciar e desligar um inversor [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\ncorreção: o nome do estado do dispositivo foi corrigido [#202] (https://github.com/bolliy/ioBroker.sun2000/pull/202)\nadicionar status do dispositivo não documentado `Shutdown: Fim do processo de descarga do ESS'\nemma control: novo estado `emma.control.battery.ESSControlMode`. Agora você pode configurar o EMMA com o modo TOU (Time of Use) para carregar a bateria da grade. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nse uma Emma estiver instalada, alguns estados de controle do inversor são desativados (apenas lidos). Principalmente para as configurações da grade.\nos estados de controlo desactualizados foram removidos.\numa solução alternativa para o problema [#582](https://github.com/yaacov/node-modbus-serial/issues/582) do nó-modbus-serial foi implementada.",
|
|
89
|
-
"nl": "inverter control: voeg dezelfde status toe voor het opstarten en afsluiten van een inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfix: De status van het apparaat is gecorrigeerd [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\nstatus van niet-gedocumenteerd apparaat toevoegen: Afsluiten: Einde van het ESS-ontladingsproces\nemma control: nieuwe staat U kunt nu EMMA configureren met de TOU-modus (Time of Use) om de batterij op te laden van het net. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nals een Emma is geïnstalleerd, worden sommige controletoestanden van de omvormer gedeactiveerd (alleen lezen). Vooral voor de rasterinstellingen.\nverouderde controlestaten zijn verwijderd.\ner is een oplossing gevonden voor nummer [#582](https://github.com/yaacov/node-modbus-serial/issues/582) van node-modbus-serial.",
|
|
90
|
-
"fr": "contrôle de l'onduleur: ajouter le même état pour le démarrage et l'arrêt d'un onduleur [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\ncorrection : le nom de l'état du périphérique a été corrigé [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\najouter l'état de l'appareil sans papiers `Shutdown: Fin du processus de décharge ESS'\ncontrôle emma: nouvel état ` emma.control.battery.ESSControlMode`. Vous pouvez maintenant configurer EMMA en mode TOU (Time of Use) pour charger la batterie à partir de la grille. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nsi une Emma est installée, certains états de contrôle de l'onduleur sont désactivés (lisez seulement). Principalement pour les paramètres de la grille.\nles états de contrôle dépréciés ont été supprimés.\nune solution de rechange pour l'émission [#582](https://github.com/yaacov/node-modbus-serial/issues/582) de nœud-modbus-serial a été mise en œuvre.",
|
|
91
|
-
"it": "controllo inverter: aggiungere lo stesso stato per l'avvio e l'arresto di un inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfix: Il nome dello stato del dispositivo è stato corretto [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\naggiungere lo stato del dispositivo non documentato `Shutdown: Fine del processo di scarico ESS`\ncontrollo emma: nuovo stato ` emma.control.battery.ESSControlMode`. È ora possibile configurare EMMA con TOU-mode (Time of Use) per caricare la batteria dalla rete. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nse viene installata una Emma, alcuni stati di controllo dell'inverter sono disattivati (leggi solo). Principalmente per le impostazioni della griglia.\nstati di controllo deprecati sono stati rimossi.\nè stato implementato un workaround per il numero [#582](https://github.com/yaacov/node-modbus-serial/issues/582) di node-modbus-serial.",
|
|
92
|
-
"es": "control inverter: añadir el mismo estado para iniciar y cerrar un inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfijado: Se ha corregido el nombre del estado de los dispositivos [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\nañadir estado de dispositivo no documentado `Shutdown: Final del proceso de descarga ESS`\nemma control: nuevo estado ` emma.control.battery.ESSControlMode`. Ahora puede configurar EMMA con TOU-mode (Time of Use) para cargar la batería de la red. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nsi se instala una Emma, se desactivan algunos estados de control del inversor (sólo lectura). Principalmente para la configuración de la red.\nestados de control deprecatados han sido eliminados.\na workaround for issue [#582](https://github.com/yaacov/node-modbus-serial/issues/582) of node-modbus-serial has been implemented.",
|
|
93
|
-
"pl": "inverter control: add same state for startup and shutdown an inverter [# 199] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 199)\nfix: Nazwa statusu urządzenia została poprawiona [# 202] (https: / / github.com / bolliy / ioBroker.sun2000 / pull / 202)\ndodać nieudokumentowany status urządzenia \"Wyłączenie: koniec procesu rozładowania ESS\"\nemma control: New state 'emma.control.battery.ESSControlMode'. Można teraz skonfigurować EMMA z TOU- mode (Time of Use), aby naładować baterię z siatki. [# 200] (https: / / github.com / bolliy / ioBroker.sun2000 / discussions / 200)\njeśli zainstalowana jest Emma, niektóre stany sterujące inwertera są wyłączone (tylko do odczytu). Głównie dla ustawień siatki.\nusunięto zdepregatowane stany kontrolne.\na workaround for issue [# 582] (https: / / github.com / yaacov / node- modbus- serial / issues / 582) of node- modbus- serial został wdrożony.",
|
|
94
|
-
"uk": "контроль інвертора: додати однаковий стан для запуску та відключення інвертора [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nвиправлено: Назва стану пристрою було виправлено [#202] (https://github.com/bolliy/ioBroker.sun2000/pull/202)\nдодати недокументований статус пристрою `Пошук: кінець процесу розряду ESS\nемма управління: новий стан ` emma.control.battery.ESSControlMode`. Ви можете налаштувати EMMA з TOU-mode (Time of Use) для зарядки акумулятора з сітки. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nякщо встановлений Емма, деактивуються деякі стани управління інвертором (прочитати тільки). В основному для налаштування сітки.\nвилучені стани керування.\n[#582](https://github.com/yaacov/node-modbus-serial/issues/582) вузла-modbus-serial.",
|
|
95
|
-
"zh-cn": "反转器控制:为启动和关闭添加相同状态的反转器[199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\n固定: 设备状态名称已更正 [# 202] (https://github.com/bolliy/ioBroker.sun2000/pul/202)\n添加无文件设备状态“关闭:ESS放电过程结束”\nemma控制:新状态`emma.control.battery.ESS Control Mode'. 您现在可以用 TOU- mode( 使用时间) 配置 EMMA 从电网中充电 。 [# 200] (https://github.com/bolliy/ioBroker.sun2000/discussions/200)\n如果安装了Emma,反转器的某些控制状态就会失效(只读). 主要用于网格设置.\n贬值的控制状态已被取消.\n已落实了节点-modbus-serial[#582](https://github.com/yaacov/node-modbus-serial/issues/582)的工作."
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
package/lib/alarms.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const alarmLevel = {
|
|
2
|
+
Major: 'major',
|
|
3
|
+
Minor: 'minor',
|
|
4
|
+
Warning: 'warning',
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const inverterAlarms1 = new Map()
|
|
8
|
+
.set('0', { id: 2001, name: 'High String Input Voltage', level: alarmLevel.Major })
|
|
9
|
+
.set('1', { id: 2002, name: 'DC Arc Fault', level: alarmLevel.Major })
|
|
10
|
+
.set('2', { id: 2011, name: 'String Reverse Connection', level: alarmLevel.Major })
|
|
11
|
+
.set('3', { id: 2012, name: 'String Current Backfeed', level: alarmLevel.Warning })
|
|
12
|
+
.set('4', { id: 2913, name: 'Abnormal String Power', level: alarmLevel.Warning })
|
|
13
|
+
.set('5', { id: 2021, name: 'AFCI Self-Check Fail', level: alarmLevel.Major })
|
|
14
|
+
.set('6', { id: 2031, name: 'Phase Wire Short-Circuited to PE', level: alarmLevel.Major })
|
|
15
|
+
.set('7', { id: 2032, name: 'Grid Loss', level: alarmLevel.Major })
|
|
16
|
+
.set('8', { id: 2033, name: 'Grid Undervoltage', level: alarmLevel.Major })
|
|
17
|
+
.set('9', { id: 2034, name: 'Grid Overvoltage', level: alarmLevel.Major })
|
|
18
|
+
.set('10', { id: 2035, name: 'Grid Volt. Imbalance', level: alarmLevel.Major })
|
|
19
|
+
.set('11', { id: 2036, name: 'Grid Overfrequency', level: alarmLevel.Major })
|
|
20
|
+
.set('12', { id: 2037, name: 'Grid Underfrequency', level: alarmLevel.Major })
|
|
21
|
+
.set('13', { id: 2038, name: 'Unstable Grid Frequency', level: alarmLevel.Major })
|
|
22
|
+
.set('14', { id: 2039, name: 'Output Overcurrent', level: alarmLevel.Major })
|
|
23
|
+
.set('15', { id: 2040, name: 'Output DC Component Overhigh', level: alarmLevel.Major });
|
|
24
|
+
|
|
25
|
+
const inverterAlarms2 = new Map()
|
|
26
|
+
.set('0', { id: 2051, name: 'Abnormal Residual Current', level: alarmLevel.Major })
|
|
27
|
+
.set('1', { id: 2061, name: 'Abnormal Grounding', level: alarmLevel.Major })
|
|
28
|
+
.set('2', { id: 2062, name: 'Low Insulation Resistance', level: alarmLevel.Major })
|
|
29
|
+
.set('3', { id: 2063, name: 'Overtemperature', level: alarmLevel.Minor })
|
|
30
|
+
.set('4', { id: 2064, name: 'Device Fault', level: alarmLevel.Major })
|
|
31
|
+
.set('5', { id: 2065, name: 'Upgrade Failed or Version Mismatch', level: alarmLevel.Minor })
|
|
32
|
+
.set('6', { id: 2066, name: 'License Expired', level: alarmLevel.Warning })
|
|
33
|
+
.set('7', { id: 61440, name: 'Faulty Monitoring Unit', level: alarmLevel.Minor })
|
|
34
|
+
.set('8', { id: 2067, name: 'Faulty Power Collector', level: alarmLevel.Major })
|
|
35
|
+
.set('9', { id: 2068, name: 'Battery abnormal', level: alarmLevel.Minor })
|
|
36
|
+
.set('10', { id: 2070, name: 'Active Islanding', level: alarmLevel.Major })
|
|
37
|
+
.set('11', { id: 2071, name: 'Passive Islanding', level: alarmLevel.Major })
|
|
38
|
+
.set('12', { id: 2072, name: 'Transient AC Overvoltage', level: alarmLevel.Major })
|
|
39
|
+
.set('13', { id: 2075, name: 'Peripheral port short circuit', level: alarmLevel.Warning })
|
|
40
|
+
.set('14', { id: 2077, name: 'Churn output overload', level: alarmLevel.Major })
|
|
41
|
+
.set('15', { id: 2080, name: 'Abnormal PV module configuration', level: alarmLevel.Major });
|
|
42
|
+
|
|
43
|
+
const inverterAlarms3 = new Map()
|
|
44
|
+
.set('0', { id: 2081, name: 'Optimizer fault', level: alarmLevel.Warning })
|
|
45
|
+
.set('1', { id: 2085, name: 'Built-in PID operation abnormal', level: alarmLevel.Minor })
|
|
46
|
+
.set('2', { id: 2014, name: 'High input string voltage to ground', level: alarmLevel.Major })
|
|
47
|
+
.set('3', { id: 2086, name: 'External Fan Abnormal', level: alarmLevel.Major })
|
|
48
|
+
.set('4', { id: 2069, name: 'Battery Reverse Connection', level: alarmLevel.Major })
|
|
49
|
+
.set('5', { id: 2082, name: 'On-grid /Off-grid controller abnormal', level: alarmLevel.Major })
|
|
50
|
+
.set('6', { id: 2015, name: 'PV String Loss', level: alarmLevel.Warning })
|
|
51
|
+
.set('7', { id: 2087, name: 'Internal Fan Abnormal', level: alarmLevel.Major })
|
|
52
|
+
.set('8', { id: 2088, name: 'DC Protection Unit Abnormal', level: alarmLevel.Major })
|
|
53
|
+
.set('9', { id: 2089, name: 'EL Unit Abnormal', level: alarmLevel.Minor })
|
|
54
|
+
.set('10', { id: 2090, name: 'Active Adjustment Instruction Abnormal', level: alarmLevel.Major })
|
|
55
|
+
.set('11', { id: 2091, name: 'Reactive Adjustment Instruction Abnormal', level: alarmLevel.Major })
|
|
56
|
+
.set('12', { id: 2092, name: 'CT Wiring Abnormal', level: alarmLevel.Major })
|
|
57
|
+
.set('13', { id: 2003, name: 'DC Arc Fault(ADMC Alarm to be clear manually)', level: alarmLevel.Major })
|
|
58
|
+
.set('14', { id: 2093, name: 'DC Switch Abnormal', level: alarmLevel.Minor })
|
|
59
|
+
.set('15', { id: 2094, name: 'Allowable discharge capacity of the battery is low', level: alarmLevel.Warning });
|
|
60
|
+
|
|
61
|
+
function fromBitfield(alarmString, lot) {
|
|
62
|
+
const result = [];
|
|
63
|
+
for (let i = 0; i < alarmString.length; i++) {
|
|
64
|
+
if (alarmString[alarmString.length - 1 - i] === '1') {
|
|
65
|
+
const alarmText = lot.get(String(i));
|
|
66
|
+
if (alarmText) {
|
|
67
|
+
result.push(alarmText);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getAlarmInfo(alarmCode, alarmNo) {
|
|
75
|
+
if (alarmCode !== null) {
|
|
76
|
+
const alarmString = (alarmCode >>> 0).toString(2).padStart(16, '0');
|
|
77
|
+
switch (alarmNo) {
|
|
78
|
+
case 1:
|
|
79
|
+
return fromBitfield(alarmString, inverterAlarms1);
|
|
80
|
+
case 2:
|
|
81
|
+
return fromBitfield(alarmString, inverterAlarms2);
|
|
82
|
+
case 3:
|
|
83
|
+
return fromBitfield(alarmString, inverterAlarms3);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
getAlarmInfo,
|
|
91
|
+
};
|
|
@@ -154,6 +154,10 @@ class DriverBase {
|
|
|
154
154
|
}
|
|
155
155
|
if (reg.states) {
|
|
156
156
|
for (const field of reg.states) {
|
|
157
|
+
//typeof field.register.checkIfActive === 'function'
|
|
158
|
+
if (field.checkIfActive && !field.checkIfActive()) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
157
161
|
const state = field.state;
|
|
158
162
|
if (field.store !== storeType.never && !state.initState) {
|
|
159
163
|
await this.state.initState(path, state);
|
|
@@ -162,11 +166,9 @@ class DriverBase {
|
|
|
162
166
|
if (field.register) {
|
|
163
167
|
let value = this._fromArray(data, reg.address, field);
|
|
164
168
|
if (value !== null) {
|
|
165
|
-
//v0.8.x
|
|
166
169
|
if (field.register.type) {
|
|
167
170
|
value = this._checkValidValueRange(value, field.register);
|
|
168
171
|
}
|
|
169
|
-
|
|
170
172
|
if (field.register.gain) {
|
|
171
173
|
value /= field.register.gain;
|
|
172
174
|
}
|
|
@@ -586,7 +586,7 @@ class Emma extends DriverBase {
|
|
|
586
586
|
this.log.warn(`PostHook for identification EmmaChargers - err: ${err}`);
|
|
587
587
|
});
|
|
588
588
|
this.identifySubdevices('sun2000', this.modbusId)
|
|
589
|
-
.then(ret => {
|
|
589
|
+
.then(async ret => {
|
|
590
590
|
this.log.debug(`### PostHook indentification for Inverter Sun2000 - ret: ${JSON.stringify(ret)}`);
|
|
591
591
|
//check if inverter sun2000 already exists
|
|
592
592
|
const inverterExist = this.adapter.devices.findIndex(x => x.driverClass === driverClasses.inverter);
|
|
@@ -602,10 +602,13 @@ class Emma extends DriverBase {
|
|
|
602
602
|
meter: false,
|
|
603
603
|
};
|
|
604
604
|
this.adapter.devices.push(device);
|
|
605
|
-
this.adapter.initDevicePath(device);
|
|
605
|
+
await this.adapter.initDevicePath(device);
|
|
606
606
|
this.log.info(`Inverter sun2000 with modbus id ${inverter.slave_id} added.`);
|
|
607
607
|
}
|
|
608
608
|
}
|
|
609
|
+
if (inverterExist === -1) {
|
|
610
|
+
await this.adapter.adjustInverval();
|
|
611
|
+
}
|
|
609
612
|
})
|
|
610
613
|
.catch(err => {
|
|
611
614
|
this.log.warn(`### PostHook for identification Sun2000 - err: ${err}`);
|
|
@@ -4,6 +4,7 @@ const { deviceType, driverClasses, storeType, getDeviceStatusInfo, batteryStatus
|
|
|
4
4
|
const { RiemannSum, isSunshine } = require(`${__dirname}/../tools.js`);
|
|
5
5
|
const DriverBase = require(`${__dirname}/driver_base.js`);
|
|
6
6
|
const ServiceQueueMap = require(`${__dirname}/../controls/inverter_service_queue.js`);
|
|
7
|
+
const { getAlarmInfo } = require(`${__dirname}/../alarms.js`);
|
|
7
8
|
|
|
8
9
|
class InverterInfo extends DriverBase {
|
|
9
10
|
constructor(stateInstance, device) {
|
|
@@ -88,10 +89,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
88
89
|
driverClass: driverClasses.inverter,
|
|
89
90
|
...options,
|
|
90
91
|
});
|
|
91
|
-
//TestMode
|
|
92
|
-
//this._testMode = this.adapter.settings.address === '192.168.2.54';
|
|
93
|
-
this._testMode = false;
|
|
94
|
-
this.log.debug(`### TestMode (#60) ${this._testMode} ${this.adapter.settings.address}`);
|
|
92
|
+
this._testMode = false; //TestMode
|
|
95
93
|
|
|
96
94
|
this.solarSum = new RiemannSum();
|
|
97
95
|
this.adapter.getState(`${this.deviceInfo.path}.derived.dailySolarYield`, (err, state) => {
|
|
@@ -157,7 +155,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
157
155
|
|
|
158
156
|
this.log.debug('### TEST MODE - PostHook for InverterSun2000 ####');
|
|
159
157
|
this.identifySubdevices('sun2000', this.modbusId)
|
|
160
|
-
.then(ret => {
|
|
158
|
+
.then(async ret => {
|
|
161
159
|
this.log.debug(`### PostHook for InverterSun2000 - ret: ${JSON.stringify(ret)}`);
|
|
162
160
|
for (const [i, inverter] of ret.entries()) {
|
|
163
161
|
this.log.info(`${this._name} identifies an inverter sun2000: OID=${inverter.obj_id}, modbus id: ${inverter.slave_id}`);
|
|
@@ -168,8 +166,9 @@ class InverterSun2000 extends DriverBase {
|
|
|
168
166
|
driverClass: driverClasses.emmaCharger,
|
|
169
167
|
};
|
|
170
168
|
this.adapter.devices.push(device);
|
|
171
|
-
this.adapter.initDevicePath(device);
|
|
169
|
+
await this.adapter.initDevicePath(device);
|
|
172
170
|
}
|
|
171
|
+
await this.adapter.adjustInverval();
|
|
173
172
|
})
|
|
174
173
|
.catch(err => {
|
|
175
174
|
this.log.warn(`### PostHook for InverterSun2000 - err: ${err}`);
|
|
@@ -212,7 +211,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
212
211
|
{
|
|
213
212
|
state: {
|
|
214
213
|
id: 'battery.chargeDischargePower',
|
|
215
|
-
name: 'Charge/
|
|
214
|
+
name: 'Charge/discharge power',
|
|
216
215
|
desc: 'reg:37765, len:2 (>0 charging, <0 discharging)',
|
|
217
216
|
type: 'number',
|
|
218
217
|
unit: 'kW',
|
|
@@ -355,6 +354,93 @@ class InverterSun2000 extends DriverBase {
|
|
|
355
354
|
}
|
|
356
355
|
},
|
|
357
356
|
},
|
|
357
|
+
{
|
|
358
|
+
//NEU!!
|
|
359
|
+
address: 38452,
|
|
360
|
+
length: 6,
|
|
361
|
+
info: 'battery Pack max/min Temperature of unit 1',
|
|
362
|
+
refresh: dataRefreshRate.low,
|
|
363
|
+
type: deviceType.battery,
|
|
364
|
+
states: [
|
|
365
|
+
{
|
|
366
|
+
state: {
|
|
367
|
+
id: 'battery.unit.1.batteryPack.1.maximumTemperature',
|
|
368
|
+
name: 'Max. temperature',
|
|
369
|
+
type: 'number',
|
|
370
|
+
unit: '°C',
|
|
371
|
+
role: 'value.temperature',
|
|
372
|
+
desc: 'reg:38452, len:1',
|
|
373
|
+
},
|
|
374
|
+
register: { reg: 38452, type: dataType.int16, gain: 10 },
|
|
375
|
+
checkIfActive: () => this._batteryExists(1, 1),
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
state: {
|
|
379
|
+
id: 'battery.unit.1.batteryPack.1.minimumTemperature',
|
|
380
|
+
name: 'Min. temperature',
|
|
381
|
+
type: 'number',
|
|
382
|
+
unit: '°C',
|
|
383
|
+
role: 'value.temperature',
|
|
384
|
+
desc: 'reg:38453, len:1',
|
|
385
|
+
},
|
|
386
|
+
register: { reg: 38453, type: dataType.int16, gain: 10 },
|
|
387
|
+
checkIfActive: () => this._batteryExists(1, 1),
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
// 38454
|
|
391
|
+
state: {
|
|
392
|
+
id: 'battery.unit.1.batteryPack.2.maximumTemperature',
|
|
393
|
+
name: 'Max. temperature',
|
|
394
|
+
type: 'number',
|
|
395
|
+
unit: '°C',
|
|
396
|
+
role: 'value.temperature',
|
|
397
|
+
desc: 'reg:38454, len:1',
|
|
398
|
+
},
|
|
399
|
+
register: { reg: 38454, type: dataType.int16, gain: 10 },
|
|
400
|
+
checkIfActive: () => this._batteryExists(1, 2),
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
// 38455
|
|
404
|
+
state: {
|
|
405
|
+
id: 'battery.unit.1.batteryPack.2.minimumTemperature',
|
|
406
|
+
name: 'Min. temperature',
|
|
407
|
+
type: 'number',
|
|
408
|
+
unit: '°C',
|
|
409
|
+
role: 'value.temperature',
|
|
410
|
+
desc: 'reg:38455, len:1',
|
|
411
|
+
},
|
|
412
|
+
register: { reg: 38455, type: dataType.int16, gain: 10 },
|
|
413
|
+
checkIfActive: () => this._batteryExists(1, 2),
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
// 38456
|
|
417
|
+
state: {
|
|
418
|
+
id: 'battery.unit.1.batteryPack.3.maximumTemperature',
|
|
419
|
+
name: 'Max. temperature',
|
|
420
|
+
type: 'number',
|
|
421
|
+
unit: '°C',
|
|
422
|
+
role: 'value.temperature',
|
|
423
|
+
desc: 'reg:38456, len:1',
|
|
424
|
+
},
|
|
425
|
+
register: { reg: 38456, type: dataType.int16, gain: 10 },
|
|
426
|
+
checkIfActive: () => this._batteryExists(1, 3),
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
// 38457
|
|
430
|
+
state: {
|
|
431
|
+
id: 'battery.unit.1.batteryPack.3.minimumTemperature',
|
|
432
|
+
name: 'Min. temperature',
|
|
433
|
+
type: 'number',
|
|
434
|
+
unit: '°C',
|
|
435
|
+
role: 'value.temperature',
|
|
436
|
+
desc: 'reg:38457, len:1',
|
|
437
|
+
},
|
|
438
|
+
register: { reg: 38457, type: dataType.int16, gain: 10 },
|
|
439
|
+
checkIfActive: () => this._batteryExists(1, 3),
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
checkIfActive: () => this._batteryExists(1),
|
|
443
|
+
},
|
|
358
444
|
{
|
|
359
445
|
address: 38229,
|
|
360
446
|
length: 13,
|
|
@@ -494,7 +580,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
494
580
|
{
|
|
495
581
|
state: {
|
|
496
582
|
id: 'battery.unit.1.batteryPack.1.chargeDischargePower',
|
|
497
|
-
name: 'Charge/
|
|
583
|
+
name: 'Charge/discharge power',
|
|
498
584
|
desc: 'reg:38233, len:2 (>0 charging, <0 discharging)',
|
|
499
585
|
type: 'number',
|
|
500
586
|
unit: 'kW',
|
|
@@ -526,7 +612,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
526
612
|
{
|
|
527
613
|
state: {
|
|
528
614
|
id: 'battery.unit.1.batteryPack.2.chargeDischargePower',
|
|
529
|
-
name: 'Charge/
|
|
615
|
+
name: 'Charge/discharge power',
|
|
530
616
|
desc: 'reg:38275, len:2 (>0 charging, <0 discharging)',
|
|
531
617
|
type: 'number',
|
|
532
618
|
unit: 'kW',
|
|
@@ -558,7 +644,7 @@ class InverterSun2000 extends DriverBase {
|
|
|
558
644
|
{
|
|
559
645
|
state: {
|
|
560
646
|
id: 'battery.unit.1.batteryPack.3.chargeDischargePower',
|
|
561
|
-
name: 'Charge/
|
|
647
|
+
name: 'Charge/discharge power',
|
|
562
648
|
desc: 'reg:38317, len:2 (>0 charging, <0 discharging)',
|
|
563
649
|
type: 'number',
|
|
564
650
|
unit: 'kW',
|
|
@@ -580,12 +666,35 @@ class InverterSun2000 extends DriverBase {
|
|
|
580
666
|
],
|
|
581
667
|
checkIfActive: () => this._batteryExists(1, 3),
|
|
582
668
|
},
|
|
583
|
-
|
|
669
|
+
/*
|
|
670
|
+
//TESTS FOR BATTERY UNIT 2
|
|
671
|
+
{
|
|
672
|
+
address: 37001,
|
|
673
|
+
length: 2,
|
|
674
|
+
info: 'battery Unit1 chargeDischargePower',
|
|
675
|
+
refresh: dataRefreshRate.high,
|
|
676
|
+
type: deviceType.battery,
|
|
677
|
+
states: [
|
|
678
|
+
{
|
|
679
|
+
state: {
|
|
680
|
+
id: 'battery.unit.1.chargeDischargePower2',
|
|
681
|
+
name: 'Charge/discharge power',
|
|
682
|
+
type: 'number',
|
|
683
|
+
unit: 'W',
|
|
684
|
+
role: 'value.power',
|
|
685
|
+
desc: 'reg:37001, len:2 (>0 charging, <0 discharging)',
|
|
686
|
+
},
|
|
687
|
+
register: { reg: 37001, type: dataType.int32 },
|
|
688
|
+
},
|
|
689
|
+
],
|
|
690
|
+
checkIfActive: () => this._batteryExists(1),
|
|
691
|
+
},
|
|
692
|
+
*/
|
|
584
693
|
{
|
|
585
694
|
address: 37000,
|
|
586
695
|
length: 23,
|
|
587
696
|
info: 'battery Unit1 information',
|
|
588
|
-
refresh: dataRefreshRate.
|
|
697
|
+
refresh: dataRefreshRate.high,
|
|
589
698
|
type: deviceType.battery,
|
|
590
699
|
states: [
|
|
591
700
|
{
|
|
@@ -598,7 +707,17 @@ class InverterSun2000 extends DriverBase {
|
|
|
598
707
|
desc: 'reg:37000, len:1',
|
|
599
708
|
},
|
|
600
709
|
register: { reg: 37000, type: dataType.uint16 },
|
|
601
|
-
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
state: {
|
|
713
|
+
id: 'battery.unit.1.chargeDischargePower',
|
|
714
|
+
name: 'Charge/discharge power',
|
|
715
|
+
type: 'number',
|
|
716
|
+
unit: 'W',
|
|
717
|
+
role: 'value.power',
|
|
718
|
+
desc: 'reg:37001, len:2 (>0 charging, <0 discharging)',
|
|
719
|
+
},
|
|
720
|
+
register: { reg: 37001, type: dataType.int32 },
|
|
602
721
|
},
|
|
603
722
|
{
|
|
604
723
|
state: {
|
|
@@ -770,7 +889,6 @@ class InverterSun2000 extends DriverBase {
|
|
|
770
889
|
},
|
|
771
890
|
},
|
|
772
891
|
{
|
|
773
|
-
//for NRGKick
|
|
774
892
|
address: 47000,
|
|
775
893
|
length: 1,
|
|
776
894
|
info: 'battery unit1 (static)',
|
|
@@ -933,7 +1051,21 @@ class InverterSun2000 extends DriverBase {
|
|
|
933
1051
|
state: { id: 'alarm3', name: 'Alarm 3', type: 'number', unit: '', role: 'value', desc: 'reg:32010, len:1' },
|
|
934
1052
|
register: { reg: 32010, type: dataType.uint16 },
|
|
935
1053
|
},
|
|
1054
|
+
{
|
|
1055
|
+
state: { id: 'derived.alarmJSON', name: 'alarms as json string', type: 'string', unit: '', role: 'value' },
|
|
1056
|
+
},
|
|
936
1057
|
],
|
|
1058
|
+
postHook: path => {
|
|
1059
|
+
const alarm1Info = getAlarmInfo(this.stateCache.get(`${path}alarm1`)?.value, 1);
|
|
1060
|
+
//const alarm1Info = getAlarmInfo(128, 1);
|
|
1061
|
+
const alarm2Info = getAlarmInfo(this.stateCache.get(`${path}alarm2`)?.value, 2);
|
|
1062
|
+
//const alarm3Info = getAlarmInfo(32, 3);
|
|
1063
|
+
const alarm3Info = getAlarmInfo(this.stateCache.get(`${path}alarm3`)?.value, 3);
|
|
1064
|
+
const alarmInfos = alarm1Info.concat(alarm2Info, alarm3Info);
|
|
1065
|
+
|
|
1066
|
+
this.adapter.log.silly(`Inverter alarms '${alarmInfos}'`);
|
|
1067
|
+
this.stateCache.set(`${path}derived.alarmJSON`, JSON.stringify(alarmInfos), { type: 'string' });
|
|
1068
|
+
},
|
|
937
1069
|
},
|
|
938
1070
|
{
|
|
939
1071
|
address: 32016,
|
|
@@ -1792,11 +1924,94 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
1792
1924
|
}
|
|
1793
1925
|
},
|
|
1794
1926
|
},
|
|
1927
|
+
{
|
|
1928
|
+
//NEU!!
|
|
1929
|
+
address: 38458,
|
|
1930
|
+
length: 6,
|
|
1931
|
+
info: 'battery Packs max/min Temperature of unit 2',
|
|
1932
|
+
refresh: dataRefreshRate.low,
|
|
1933
|
+
type: deviceType.battery,
|
|
1934
|
+
states: [
|
|
1935
|
+
{
|
|
1936
|
+
state: {
|
|
1937
|
+
id: 'battery.unit.2.batteryPack.1.maximumTemperature',
|
|
1938
|
+
name: 'Max. temperature',
|
|
1939
|
+
type: 'number',
|
|
1940
|
+
unit: '°C',
|
|
1941
|
+
role: 'value.temperature',
|
|
1942
|
+
desc: 'reg:38458, len:1',
|
|
1943
|
+
},
|
|
1944
|
+
register: { reg: 38458, type: dataType.int16, gain: 10 },
|
|
1945
|
+
checkIfActive: () => this._batteryExists(2, 1),
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
state: {
|
|
1949
|
+
id: 'battery.unit.2.batteryPack.1.minimumTemperature',
|
|
1950
|
+
name: 'Min. temperature',
|
|
1951
|
+
type: 'number',
|
|
1952
|
+
unit: '°C',
|
|
1953
|
+
role: 'value.temperature',
|
|
1954
|
+
desc: 'reg:38459, len:1',
|
|
1955
|
+
},
|
|
1956
|
+
register: { reg: 38459, type: dataType.int16, gain: 10 },
|
|
1957
|
+
checkIfActive: () => this._batteryExists(2, 1),
|
|
1958
|
+
},
|
|
1959
|
+
{
|
|
1960
|
+
state: {
|
|
1961
|
+
id: 'battery.unit.2.batteryPack.2.maximumTemperature',
|
|
1962
|
+
name: 'Max. temperature',
|
|
1963
|
+
type: 'number',
|
|
1964
|
+
unit: '°C',
|
|
1965
|
+
role: 'value.temperature',
|
|
1966
|
+
desc: 'reg:38460, len:1',
|
|
1967
|
+
},
|
|
1968
|
+
register: { reg: 38460, type: dataType.int16, gain: 10 },
|
|
1969
|
+
checkIfActive: () => this._batteryExists(2, 2),
|
|
1970
|
+
},
|
|
1971
|
+
{
|
|
1972
|
+
state: {
|
|
1973
|
+
id: 'battery.unit.2.batteryPack.2.minimumTemperature',
|
|
1974
|
+
name: 'Min. temperature',
|
|
1975
|
+
type: 'number',
|
|
1976
|
+
unit: '°C',
|
|
1977
|
+
role: 'value.temperature',
|
|
1978
|
+
desc: 'reg:38461, len:1',
|
|
1979
|
+
},
|
|
1980
|
+
register: { reg: 38461, type: dataType.int16, gain: 10 },
|
|
1981
|
+
checkIfActive: () => this._batteryExists(2, 2),
|
|
1982
|
+
},
|
|
1983
|
+
{
|
|
1984
|
+
state: {
|
|
1985
|
+
id: 'battery.unit.2.batteryPack.3.maximumTemperature',
|
|
1986
|
+
name: 'Max. temperature',
|
|
1987
|
+
type: 'number',
|
|
1988
|
+
unit: '°C',
|
|
1989
|
+
role: 'value.temperature',
|
|
1990
|
+
desc: 'reg:38462, len:1',
|
|
1991
|
+
},
|
|
1992
|
+
register: { reg: 38462, type: dataType.int16, gain: 10 },
|
|
1993
|
+
checkIfActive: () => this._batteryExists(2, 3),
|
|
1994
|
+
},
|
|
1995
|
+
{
|
|
1996
|
+
state: {
|
|
1997
|
+
id: 'battery.unit.2.batteryPack.3.minimumTemperature',
|
|
1998
|
+
name: 'Min. temperature',
|
|
1999
|
+
type: 'number',
|
|
2000
|
+
unit: '°C',
|
|
2001
|
+
role: 'value.temperature',
|
|
2002
|
+
desc: 'reg:38463, len:1',
|
|
2003
|
+
},
|
|
2004
|
+
register: { reg: 38463, type: dataType.int16, gain: 10 },
|
|
2005
|
+
checkIfActive: () => this._batteryExists(2, 3),
|
|
2006
|
+
},
|
|
2007
|
+
],
|
|
2008
|
+
checkIfActive: () => this._batteryExists(2),
|
|
2009
|
+
},
|
|
1795
2010
|
{
|
|
1796
2011
|
address: 37738,
|
|
1797
2012
|
length: 15,
|
|
1798
2013
|
info: 'battery unit2 information',
|
|
1799
|
-
refresh: dataRefreshRate.
|
|
2014
|
+
refresh: dataRefreshRate.high,
|
|
1800
2015
|
type: deviceType.battery,
|
|
1801
2016
|
states: [
|
|
1802
2017
|
{
|
|
@@ -1820,7 +2035,17 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
1820
2035
|
desc: 'reg:37741, len:1',
|
|
1821
2036
|
},
|
|
1822
2037
|
register: { reg: 37741, type: dataType.uint16 },
|
|
1823
|
-
|
|
2038
|
+
},
|
|
2039
|
+
{
|
|
2040
|
+
state: {
|
|
2041
|
+
id: 'battery.unit.2.chargeDischargePower',
|
|
2042
|
+
name: 'Charge/discharge power',
|
|
2043
|
+
type: 'number',
|
|
2044
|
+
unit: 'W',
|
|
2045
|
+
role: 'value.power',
|
|
2046
|
+
desc: 'reg:37743, len:2 (>0 charging, <0 discharging)',
|
|
2047
|
+
},
|
|
2048
|
+
register: { reg: 37743, type: dataType.int32 },
|
|
1824
2049
|
},
|
|
1825
2050
|
{
|
|
1826
2051
|
state: {
|
|
@@ -1851,7 +2076,6 @@ class InverterSun2000_M1 extends InverterSun2000 {
|
|
|
1851
2076
|
],
|
|
1852
2077
|
checkIfActive: () => this._batteryExists(2),
|
|
1853
2078
|
},
|
|
1854
|
-
//--V0.12
|
|
1855
2079
|
{
|
|
1856
2080
|
address: 38355,
|
|
1857
2081
|
length: 13,
|
|
@@ -154,6 +154,12 @@ class ModbusConnect extends DeviceInterface {
|
|
|
154
154
|
await this.close();
|
|
155
155
|
await this._create();
|
|
156
156
|
if (err.errno === 'ECONNREFUSED') {
|
|
157
|
+
this.log.warn('Connection Refused!');
|
|
158
|
+
this.log.warn(
|
|
159
|
+
'Either the Modbus TCP service is not enabled, the wrong IP address or port is being used, or a firewall is blocking the connection.',
|
|
160
|
+
);
|
|
161
|
+
} else if (err.errno === 'ECONNRESET') {
|
|
162
|
+
this.log.warn('Connection Reset!');
|
|
157
163
|
this.log.warn('Has another device interrupted the modbus connection?');
|
|
158
164
|
this.log.warn('Consider that only 1 client is allowed to connect to modbus at the same time!');
|
|
159
165
|
}
|
package/lib/register.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { deviceType, driverClasses, dataRefreshRate } = require(`${__dirname}/types.js`);
|
|
4
4
|
const { RiemannSum, StateMap } = require(`${__dirname}/tools.js`);
|
|
5
5
|
const getDriverHandler = require(`${__dirname}/drivers/index.js`);
|
|
6
|
+
const tools = require(`${__dirname}/tools.js`);
|
|
6
7
|
|
|
7
8
|
class Registers {
|
|
8
9
|
constructor(adapterInstance) {
|
|
@@ -18,6 +19,18 @@ class Registers {
|
|
|
18
19
|
device.instance = new handler(this, device);
|
|
19
20
|
}
|
|
20
21
|
}
|
|
22
|
+
//deleted deprecated states
|
|
23
|
+
if (
|
|
24
|
+
tools.existsState(this.adapter, `collected.usableSurplusPower`, (err, exists) => {
|
|
25
|
+
if (!err && exists) {
|
|
26
|
+
tools.deleteState(this.adapter, `collected.usableSurplusPower`, (err, deleted) => {
|
|
27
|
+
if (!err && deleted) {
|
|
28
|
+
this.adapter.logger.debug('Deleted deprecated state collected.usableSurplusPower');
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
);
|
|
21
34
|
|
|
22
35
|
this.postProcessHooks = [];
|
|
23
36
|
this.inverterPostProcessHooks = [
|
|
@@ -43,6 +56,7 @@ class Registers {
|
|
|
43
56
|
unit: 'kW',
|
|
44
57
|
role: 'value.power',
|
|
45
58
|
},
|
|
59
|
+
/*
|
|
46
60
|
{
|
|
47
61
|
id: 'collected.usableSurplusPower',
|
|
48
62
|
name: 'usable surplus power',
|
|
@@ -51,6 +65,7 @@ class Registers {
|
|
|
51
65
|
role: 'value.power',
|
|
52
66
|
desc: 'depreciated: Please use collected.surplus.usablePower instead',
|
|
53
67
|
},
|
|
68
|
+
*/
|
|
54
69
|
{
|
|
55
70
|
id: 'collected.surplus.power',
|
|
56
71
|
name: 'surplus power',
|
|
@@ -75,6 +90,7 @@ class Registers {
|
|
|
75
90
|
let inPowerEff = 0;
|
|
76
91
|
let chargeDischarge = 0;
|
|
77
92
|
let ratedPower = 0;
|
|
93
|
+
let maxDischargingPower = 0;
|
|
78
94
|
|
|
79
95
|
function calcUsableSurplus() {
|
|
80
96
|
let surplusPower = 0;
|
|
@@ -109,11 +125,14 @@ class Registers {
|
|
|
109
125
|
}
|
|
110
126
|
|
|
111
127
|
usableSurplusPower = surplusPower;
|
|
112
|
-
|
|
128
|
+
// Using battery power to calculate usable surplus power
|
|
113
129
|
if (bufferSoc > 0) {
|
|
114
130
|
if (soc > minSoc && soc >= bufferSoc + threshold) {
|
|
115
131
|
this.bufferOn = true;
|
|
116
|
-
|
|
132
|
+
let bufferPower = this.adapter.control.get('usableSurplus.bufferPower')?.value ?? 0;
|
|
133
|
+
if (bufferPower > maxDischargingPower) {
|
|
134
|
+
bufferPower = maxDischargingPower;
|
|
135
|
+
}
|
|
117
136
|
usableSurplusPower += bufferPower / 1000;
|
|
118
137
|
} else {
|
|
119
138
|
this.bufferOn = false;
|
|
@@ -130,11 +149,11 @@ class Registers {
|
|
|
130
149
|
usableSurplusPower = ratedPower;
|
|
131
150
|
}
|
|
132
151
|
if (!allowNegativeValue) {
|
|
133
|
-
if (surplusPower < 0.
|
|
134
|
-
if (usableSurplusPower < 0.
|
|
152
|
+
if (surplusPower < 0.01) surplusPower = 0;
|
|
153
|
+
if (usableSurplusPower < 0.01) usableSurplusPower = 0;
|
|
135
154
|
}
|
|
136
155
|
|
|
137
|
-
this.adapter.
|
|
156
|
+
this.adapter.logger.debug(
|
|
138
157
|
`### Caculate usableSurplus power ${surplusPower} bufferOn ${this.bufferOn} soc ${soc} minSoc ${minSoc} bufferSoc ${bufferSoc} threshold ${hysterese / 2}`,
|
|
139
158
|
);
|
|
140
159
|
}
|
|
@@ -150,6 +169,7 @@ class Registers {
|
|
|
150
169
|
inPowerEff += this.stateCache.get(`${inverter.path}.derived.inputPowerWithEfficiencyLoss`)?.value ?? 0;
|
|
151
170
|
chargeDischarge += this.stateCache.get(`${inverter.path}.battery.chargeDischargePower`)?.value ?? 0;
|
|
152
171
|
ratedPower += this.stateCache.get(`${inverter.path}.info.ratedPower`)?.value ?? 0;
|
|
172
|
+
maxDischargingPower += this.stateCache.get(`${inverter.path}.battery.maximumDischargingPower`)?.value ?? 0;
|
|
153
173
|
}
|
|
154
174
|
|
|
155
175
|
const feedinPower = this.stateCache.get('meter.derived.feed-inPower')?.value ?? 0;
|
|
@@ -170,9 +190,11 @@ class Registers {
|
|
|
170
190
|
this.stateCache.set('collected.activePower', actPower, { type: 'number', renew: true });
|
|
171
191
|
this.stateCache.set('collected.houseConsumption', houseConsum, { type: 'number' });
|
|
172
192
|
this.stateCache.set('collected.chargeDischargePower', chargeDischarge, { type: 'number' });
|
|
193
|
+
/*
|
|
173
194
|
this.stateCache.set('collected.usableSurplusPower', surplusArray[1], {
|
|
174
195
|
type: 'number',
|
|
175
196
|
});
|
|
197
|
+
*/
|
|
176
198
|
this.stateCache.set('collected.surplus.power', surplusArray[0], {
|
|
177
199
|
type: 'number',
|
|
178
200
|
});
|
|
@@ -317,14 +339,7 @@ class Registers {
|
|
|
317
339
|
this.stateCache.set('collected.gridImportToday', supplyFromGrid - this.stateCache.get('collected.gridImportStart')?.value, {
|
|
318
340
|
type: 'number',
|
|
319
341
|
});
|
|
320
|
-
|
|
321
|
-
this.stateCache.set(
|
|
322
|
-
'collected.consumptionToday',
|
|
323
|
-
this.stateCache.get('collected.consumptionSum')?.value - this.stateCache.get('collected.consumptionStart')?.value,
|
|
324
|
-
{ type: 'number' },
|
|
325
|
-
);
|
|
326
|
-
*/
|
|
327
|
-
//new computation of consumption today
|
|
342
|
+
//consumption today
|
|
328
343
|
this.stateCache.set(
|
|
329
344
|
'collected.consumptionToday',
|
|
330
345
|
activeEnergy +
|
package/main.js
CHANGED
|
@@ -103,15 +103,7 @@ class Sun2000 extends utils.Adapter {
|
|
|
103
103
|
},
|
|
104
104
|
native: {},
|
|
105
105
|
});
|
|
106
|
-
|
|
107
|
-
await this.extendObject(path+'.battery', {
|
|
108
|
-
type: 'channel',
|
|
109
|
-
common: {
|
|
110
|
-
name: 'channel battery'
|
|
111
|
-
},
|
|
112
|
-
native: {}
|
|
113
|
-
});
|
|
114
|
-
*/
|
|
106
|
+
|
|
115
107
|
await this.extendObject(`${path}.string`, {
|
|
116
108
|
type: 'channel',
|
|
117
109
|
common: {
|
|
@@ -325,17 +317,16 @@ class Sun2000 extends utils.Adapter {
|
|
|
325
317
|
if (this.settings.modbusAdjust) {
|
|
326
318
|
this.settings.highInterval = 10000 * this.settings.modbusIds.length;
|
|
327
319
|
} else {
|
|
320
|
+
this.settings.highInterval = this.config.updateInterval * 1000; //ms
|
|
328
321
|
let minInterval = this.settings.modbusIds.length * this.settings.modbusDelay * 2.5; //len*5*delay/2
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
} else {
|
|
333
|
-
for (const device of this.devices) {
|
|
334
|
-
if (device.duration) {
|
|
335
|
-
minInterval += device.duration;
|
|
336
|
-
}
|
|
322
|
+
for (const device of this.devices) {
|
|
323
|
+
if (device.duration) {
|
|
324
|
+
minInterval += device.duration;
|
|
337
325
|
}
|
|
338
326
|
}
|
|
327
|
+
if (minInterval < 5000) {
|
|
328
|
+
minInterval = 5000;
|
|
329
|
+
}
|
|
339
330
|
if (minInterval > this.settings.highInterval) {
|
|
340
331
|
this.settings.highInterval = Math.round(minInterval);
|
|
341
332
|
}
|
|
@@ -348,8 +339,8 @@ class Sun2000 extends utils.Adapter {
|
|
|
348
339
|
const newHighInterval = Math.round(this.settings.highInterval / 1000);
|
|
349
340
|
if (!this.settings.modbusAdjust) {
|
|
350
341
|
if (this.config.updateInterval < newHighInterval) {
|
|
351
|
-
this.logger.
|
|
352
|
-
this.logger.warn('Please check your configuration!');
|
|
342
|
+
this.logger.info(`The interval is too small. The value has been changed on ${newHighInterval} sec.`);
|
|
343
|
+
//this.logger.warn('Please check your configuration!');
|
|
353
344
|
}
|
|
354
345
|
}
|
|
355
346
|
await this.setState('info.modbusUpdateInterval', { val: newHighInterval, ack: true });
|
|
@@ -400,7 +391,7 @@ class Sun2000 extends utils.Adapter {
|
|
|
400
391
|
if (this.settings.sd.sDongleId < 0 || this.settings.sd.sDongleId >= 255) {
|
|
401
392
|
this.settings.sd.active = false;
|
|
402
393
|
}
|
|
403
|
-
this.settings.highInterval = this.config.updateInterval * 1000; //ms
|
|
394
|
+
//this.settings.highInterval = this.config.updateInterval * 1000; //ms
|
|
404
395
|
//Modbus-Proxy
|
|
405
396
|
this.settings.ms.address = this.config.ms_address;
|
|
406
397
|
this.settings.ms.port = this.config.ms_port;
|
|
@@ -477,7 +468,7 @@ class Sun2000 extends utils.Adapter {
|
|
|
477
468
|
}
|
|
478
469
|
}
|
|
479
470
|
|
|
480
|
-
//EMMA
|
|
471
|
+
//EMMA
|
|
481
472
|
if (this.settings.integration === 2) {
|
|
482
473
|
this.devices.push({
|
|
483
474
|
index: 0,
|
|
@@ -548,7 +539,6 @@ class Sun2000 extends utils.Adapter {
|
|
|
548
539
|
const sinceLastUpdate = new Date().getTime() - this.lastTimeUpdated; //ms
|
|
549
540
|
this.logger.debug(`### Watchdog: time since last update ${sinceLastUpdate / 1000} sec`);
|
|
550
541
|
const lastIsConnected = this.isConnected;
|
|
551
|
-
//this.isConnected = this.lastStateUpdatedHigh > 0 && sinceLastUpdate < this.settings.highInterval*3;
|
|
552
542
|
this.isConnected = this.lastStateUpdatedHigh > 0 || this.lastStateUpdatedLow > 0;
|
|
553
543
|
|
|
554
544
|
if (this.isConnected !== lastIsConnected) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.sun2000",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.7",
|
|
4
4
|
"description": "sun2000",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "bolliy",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"@iobroker/adapter-dev": "^1.5.0",
|
|
41
41
|
"@iobroker/eslint-config": "^2.2.0",
|
|
42
42
|
"@iobroker/testing": "^5.2.2",
|
|
43
|
-
"@tsconfig/node20": "^20.1.
|
|
44
|
-
"@types/node": "^
|
|
43
|
+
"@tsconfig/node20": "^20.1.8",
|
|
44
|
+
"@types/node": "^25.0.10",
|
|
45
45
|
"globals": "^16.5.0",
|
|
46
46
|
"typescript": "~5.9.3"
|
|
47
47
|
},
|