iobroker.sun2000 0.6.1 → 0.7.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 CHANGED
@@ -6,6 +6,9 @@
6
6
  ![Number of Installations](https://iobroker.live/badges/sun2000-installed.svg)
7
7
  ![Current version in stable repository](https://iobroker.live/badges/sun2000-stable.svg)
8
8
  [![Documentation](https://img.shields.io/badge/Documentation-2D963D?logo=read-the-docs&logoColor=white)](./docs/README.md)
9
+ [![Donate](https://img.shields.io/badge/paypal-donate%20|%20spenden-blue.svg)](https://www.paypal.com/donate/?hosted_button_id=ZTX3VP9LZBDCG)
10
+ [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/bolliy)
11
+
9
12
 
10
13
  [![NPM](https://nodei.co/npm/iobroker.sun2000.png?downloads=true)](https://nodei.co/npm/iobroker.sun2000/)
11
14
 
@@ -17,12 +20,16 @@ Sentry reporting is used starting with js-controller 3.0.
17
20
 
18
21
  ## sun2000 adapter for ioBroker
19
22
 
20
- Read register data from Huawei SUN2000 inverter and LUNA2000 battery using Modbus TCP.
23
+ Read and write register data from Huawei SUN2000 inverter and LUNA2000 battery using Modbus TCP. Third-party devices can be integrated via the modbus proxy. Even a Huawei SmartLogger can be integrated.
21
24
 
22
25
  [Huawei product information](https://solar.huawei.com/en/professionals/all-products?residential-smart-pv)
23
26
 
24
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)
25
28
 
29
+ ## Required
30
+ * Node.js 18.x or higher
31
+ * ioBroker host (js-controller) 5.x or higher
32
+
26
33
  ## Documentation
27
34
 
28
35
  See the [documentation page](./docs/README.md) or
@@ -52,6 +59,15 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
52
59
  Placeholder for the next version (at the beginning of the line):
53
60
  ### **WORK IN PROGRESS**
54
61
  -->
62
+ ### 0.7.0 (2024-04-03)
63
+ * breaking changes
64
+ - Node.js 18.x or higher required
65
+ - ioBroker host (js-controller) 5.x or higher
66
+
67
+ ### 0.6.2 (2024-03-31)
68
+ * standby detection adjusted
69
+ * improvement of logs
70
+
55
71
  ### 0.6.1 (2024-03-23)
56
72
  * Battery control: After the second failed attempt, the control event is discarded
57
73
  * Battery control: Adjust the battery maxCharge and Discharge to the actual values
@@ -61,7 +77,7 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
61
77
  * fix the standby detection #60
62
78
 
63
79
  ### 0.5.1 (2024-03-11)
64
- * Config page restructured
80
+ * config page restructured
65
81
  * read only the required string data
66
82
  * fix interval medium
67
83
 
package/admin/sun2000.png CHANGED
Binary file
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sun2000",
4
- "version": "0.6.1",
4
+ "version": "0.7.0",
5
5
  "news": {
6
+ "0.7.0": {
7
+ "en": "breaking changes\nNode.js 18.x or higher required\nioBroker host (js-controller) 5.x or higher",
8
+ "de": "änderungen\nNode.js 18.x oder höher erforderlich\nioBroker Host (js-controller) 5.x oder höher",
9
+ "ru": "изменения\nNode.js 18.x или выше требуется\nioBroker host (js-controller) 5.x или выше",
10
+ "pt": "alterações de ruptura\nNode.js 18.x ou superior requerido\nhospedeiro ioBroker (js-controller) 5.x ou superior",
11
+ "nl": "wijzigingen breken\nNode.js 18.x of hoger vereist\nioBroker host (js-controller) 5.x of hoger",
12
+ "fr": "casser les changements\nNode.js 18.x ou plus requis\nioBroker host (js-controller) 5.x ou plus",
13
+ "it": "cambiamenti di rottura\nNode.js 18.x o superiore richiesto\nioBroker host (js-controller) 5.x o superiore",
14
+ "es": "cambios de ruptura\nNode.js 18.x o superior requerido\nioBroker host (js-controller) 5.x o superior",
15
+ "pl": "łamanie zmian\nNode.js 18,x lub wyższa wymagana\njoBroker host (kontroler js-) 5.x lub wyższy",
16
+ "uk": "поломка змін\nNode.js 18.x або вище потрібно\nioBroker host (js-controller) 5.x або вище",
17
+ "zh-cn": "断开更改\n所需节点.js 18.x或更高\nioBroker 主机(js-controller) 5.x或更高"
18
+ },
19
+ "0.6.2": {
20
+ "en": "standby detection adjusted\nImprovement of logs",
21
+ "de": "standby-erkennung angepasst\nVerbesserung der Protokolle",
22
+ "ru": "резервное обнаружение с поправкой\nСовершенствование журналов",
23
+ "pt": "detecção de espera ajustada\nMelhoria dos logs",
24
+ "nl": "stand-by detectie aangepast\nVerbetering van de logs",
25
+ "fr": "réglage de la détection en attente\nAmélioration des registres",
26
+ "it": "rilevamento standby regolato\nMiglioramento dei registri",
27
+ "es": "detección de reserva ajustada\nMejora de los registros",
28
+ "pl": "korekta detekcji czuwania\nPoprawa dzienników",
29
+ "uk": "автономне виявлення\nУдосконалення колод",
30
+ "zh-cn": "经调整的备用检测\n改进日志"
31
+ },
6
32
  "0.6.1": {
7
33
  "en": "Battery control: After the second failed attempt, the control event is discarded\nBattery control: Adjust the battery maxCharge and Discharge to the actual values",
8
34
  "de": "Batteriesteuerung: Nach dem zweiten gescheiterten Versuch wird das Kontrollereignis verworfen\nBatteriesteuerung: Einstellen der Batterie maxCharge und Entladen auf die tatsächlichen Werte",
@@ -67,32 +93,6 @@
67
93
  "pl": "odczyt danych strun fotowoltaicznych wolniej (interwał średni)",
68
94
  "uk": "читати повільніші дані ПВ (середній інтервал)",
69
95
  "zh-cn": "读取较慢的光电字符串数据( 中间隔)"
70
- },
71
- "0.4.0": {
72
- "en": "detect standby mode of inverters (#34)\ndevices in standby often give incorrect values. These are assigned \"0\" (#40)\nthe modbus register and the length are stored in the description of the states\nimplemented modbus-proxy (read-only cache)\nread register data from SDongleA \nadditional loop interval medium (SDongle data)\nIntegration of [NRGkick Wallbox](https://www.nrgkick.com)\nread string data faster (high interval)",
73
- "de": "standby-modus von wechselrichtern erkennen (#34)\ngeräte im Standby geben oft falsche Werte. Diese werden \"0\" zugeordnet (#40)\ndas modbusregister und die länge werden in der beschreibung der zustände gespeichert\nimplementiert modbus-proxy (nur lesen cache)\nregisterdaten von SDongleA lesen\nzusätzliches Loop-Intervallmedium (SDongle-Daten)\nIntegration von [NRGkick Wallbox](https://www.nrgkick.com)\nstringdaten schneller lesen (hohes intervall)",
74
- "ru": "#34\nустройства в режиме ожидания часто дают неправильные значения. Назначены \"0\" (#40)\nрегистр modbus и длина хранятся в описании состояний\nреализованный modbus-proxy (только для чтения)\nчитать данные реестра SDongleA\nдополнительная интерактивная среда (данные SDongle)\nИнтеграция [NRGkick Wallbox] (https://www.nrgkick.com)\nчитать строковые данные быстрее (высокий интервал)",
75
- "pt": "detectar modo de espera de inversores (#34)\ndispositivos em espera muitas vezes dão valores incorretos. Estes são atribuídos \"0\" (#40)\no registro do modbus e o comprimento são armazenados na descrição dos estados\nimplementado modbus-proxy (apenas leitura cache)\nler dados de registro de SDongleA\nmeio de intervalo de loop adicional (dados de SDongle)\nIntegração de [NRGkick Wallbox](https://www.nrgkick.com)\nler dados de cadeia mais rápido (alto intervalo)",
76
- "nl": "de standbymodus van de inverters detecteren (#34)\napparaten in stand-by geven vaak onjuiste waarden. Deze worden toegewezen aan \"0\" (#40)\nde modbus register en de lengte worden opgeslagen in de beschrijving van de staten\ngeïmplementeerd modbus-proxy (alleen-lezen cache)\nlees registergegevens van SDongleA\nextra loopintervalmedium (SDongle-gegevens)\nIntegratie van [NRGkick Wallbox](https://www.nrgkick.com)\nlees tekstgegevens sneller (hoog interval)",
77
- "fr": "détecter le mode veille des onduleurs (#34)\nles dispositifs en attente donnent souvent des valeurs incorrectes. Ils sont assignés « 0 » (#40)\nle registre modbus et la longueur sont stockés dans la description des états\nmis en œuvre modbus-proxy (cache de lecture seule)\nlire les données du registre de SDongleA\nmilieu d'intervalle de boucle supplémentaire (données SDongle)\nIntégration de [NRGkick Wallbox](https://www.nrgkick.com)\nlire les données de chaîne plus rapidement (intervalle élevé)",
78
- "it": "rilevare modalità standby di inverter (#34)\ni dispositivi in standby spesso danno valori errati. Questi sono assegnati \"0\" (#40)\nil registro modbus e la lunghezza sono memorizzate nella descrizione degli stati\nimplementato modbus-proxy ( cache di sola lettura)\nleggere i dati del registro da SDongleA\nintervallo di loop aggiuntivo medio (dati del triangolo)\nIntegrazione [NRGkick Wallbox](https://www.nrgkick.com)\nleggere i dati della stringa più velocemente (alto intervallo)",
79
- "es": "detectar el modo de espera de los inversores (#34)\ndispositivos en standby a menudo dan valores incorrectos. Estos son asignados \"0\" (#40)\nel registro del modbus y la longitud se almacenan en la descripción de los estados\naplicado modbus-proxy (caché de sólo lectura)\nread register data from SDongleA\nintervalo de bucle adicional medio (datos de SDongle)\nIntegración de [NRGkick Wallbox](https://www.nrgkick.com)\nleer datos de cadena más rápido (intervalo alto)",
80
- "pl": "wykrywanie trybu czuwania inwerterów (# 34)\nurządzenia w trybie czuwania często dają nieprawidłowe wartości. Są one przypisane \"0\" (# 40)\nrejestr modbus i długość są przechowywane w opisie stanów\nzaimplementowany modbus- proxy (tylko read- cache)\nczytaj dane rejestru z SDongleA\ndodatkowe medium interwałowe pętli (dane SDongle)\nW związku z tym Komisja uznała, że nie ma podstaw, aby stwierdzić, że w odniesieniu do niektórych rodzajów działalności, które nie są objęte zakresem rozporządzenia (WE) nr 659 / 1999, nie można uznać, że działalność ta nie jest zgodna z rynkiem wewnętrznym\nodczyt danych łańcuchowych szybciej (wysoki interwał)",
81
- "uk": "виявити режим очікування інверторів (#34)\nпристрої в режимі очікування часто дають неправильні значення. Присвоюється \"0\" (#40)\nреєстр модбусів і довжина зберігаються в описі станів\nреалізований модбус-проксі (тільки кеш)\nчитати реєстраційні дані з SDongleA\nдодатковий інтервал петлі середній (SDongle data)\nІнтеграція [NRGkick Wallbox](https://www.nrgkick.com)\nчитати дані рядка швидше (високий інтервал)",
82
- "zh-cn": "检测反转器的备用模式 (# 34)\n正在待命的设备往往给出错误的值。 这些被分配为\"0\" (# 40)\nmodbus 寄存器和长度存储在状态描述中\n已执行的 modbus- 代理( 只读缓存)\n从 SDongleA 读取寄存器数据\n额外的循环间隔介质( SDongle 数据)\n整合[NRGkick Wallbox](https://www.nrgkick.com)\n更快地读取字符串数据( 高间隔)"
83
- },
84
- "0.3.1": {
85
- "en": "state `sun2000.0.collected.chargeDischargePowercharge` is not always refreshed #47",
86
- "de": "state `sun2000.0.collected.chargeDischargePowercharge` ist nicht immer erfrischt #47",
87
- "ru": "состояние `sun2000.0.collected.chargeDischargePowercharge' не всегда обновляется #47",
88
- "pt": "estado `sun2000.0.collected.chargeDischargePowercharge` nem sempre é atualizado #47",
89
- "nl": "staat ",
90
- "fr": "état `sun2000.0.collected.chargeDéchargePowercharge` n'est pas toujours rafraîchi #47",
91
- "it": "stato `sun2000.0.colletto.chargeDischargePowercharge` non è sempre aggiornato #47",
92
- "es": "estado `sun2000.0.collected.chargeDischargePowercharge` no siempre se actualiza #47",
93
- "pl": "state 'sun2000.0.0 collected.chargeDischargePowercharge' nie zawsze jest odświeżona # 47",
94
- "uk": "#47",
95
- "zh-cn": "state `sun 2000.00.colled. 充电电源 ' 并不总是刷新47"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -109,17 +109,17 @@
109
109
  "zh-cn": "Huawei sun2000 inverter"
110
110
  },
111
111
  "desc": {
112
- "en": "Read data from up to 5 Huawei SUN2000 inverters and LUNA2000 batteries using Modbus TCP.\nThird-party devices can be integrated via the modbus proxy.\n",
113
- "de": "Daten von bis zu 5 Huawei SUN2000 Wechselrichtern und LUNA2000 Batterien können über Modbus TCP ausgelesen werden.\nMit dem integrierten Modbus-Proxy können Geräte von Drittanbietern eingebunden werden.",
114
- "ru": "Считывайте данные с пяти инверторов Huawei SUN2000 и аккумуляторов LUNA2000 с помощью Modbus TCP.\nУстройства сторонних производителей можно интегрировать через прокси-сервер Modbus.",
115
- "pt": "Leia dados de até 5 inversores Huawei SUN2000 e baterias LUNA2000 usando Modbus TCP.\nDispositivos de terceiros podem ser integrados através do proxy modbus.",
116
- "nl": "Lees gegevens van maximaal 5 Huawei SUN2000-omvormers en LUNA2000-batterijen met behulp van Modbus TCP.\nApparaten van derden kunnen via de modbus-proxy worden geïntegreerd.",
117
- "fr": "Lisez les données de jusqu'à 5 onduleurs Huawei SUN2000 et batteries LUNA2000 à l'aide de Modbus TCP.\nDes appareils tiers peuvent être intégrés via le proxy Modbus.",
118
- "it": "Leggi i dati da un massimo di 5 inverter Huawei SUN2000 e batterie LUNA2000 utilizzando Modbus TCP.\nI dispositivi di terze parti possono essere integrati tramite il proxy Modbus.",
119
- "es": "Lea datos de hasta 5 inversores Huawei SUN2000 y baterías LUNA2000 mediante Modbus TCP.\nSe pueden integrar dispositivos de terceros a través del proxy modbus.",
120
- "pl": "Odczyt danych z maksymalnie 5 inwerterów Huawei SUN2000 i akumulatorów LUNA2000 za pomocą protokołu Modbus TCP.\nUrządzenia innych firm można zintegrować za pośrednictwem serwera proxy Modbus.",
121
- "uk": "Зчитування даних до 5 інверторів Huawei SUN2000 і акумуляторів LUNA2000 за допомогою Modbus TCP.\nПристрої сторонніх виробників можна інтегрувати через проксі-сервер Modbus.",
122
- "zh-cn": "使用Modbus TCP读取最多5台华为SUN2000逆变器和LUNA2000电池的数据。\n第三方设备可以通过modbus代理集成。"
112
+ "en": "To read and write data from up to 5 Huawei SUN2000 inverters and LUNA2000 batteries via Modbus TCP. Third-party devices can be integrated via the modbus proxy.",
113
+ "de": "Zum Lesen und Schreiben von Daten von bis zu 5 Huawei SUN2000 Wechselrichtern und LUNA2000 Batterien über Modbus TCP. Drittgeräte können über den Modbus Proxy integriert werden.",
114
+ "ru": "Прочитать и писать данные до 5 инверторов Huawei SUN2000 и батарей LUNA2000 через Modbus TCP. Сторонние устройства могут быть интегрированы через modbus proxy.",
115
+ "pt": "Para ler e escrever dados de até 5 inversores Huawei SUN2000 e baterias LUNA2000 via Modbus TCP. Dispositivos de terceiros podem ser integrados através do proxy modbus.",
116
+ "nl": "Gegevens lezen en schrijven van maximaal 5 Huawei SUN2000 omvormers en LUNA2000 batterijen via Modbus TCP. De apparaten van derden kunnen worden geïntegreerd via de modbus proxy.",
117
+ "fr": "Pour lire et écrire des données de jusqu'à 5 onduleurs Huawei SUN2000 et batteries LUNA2000 via Modbus TCP. Les périphériques tiers peuvent être intégrés via le proxy modbus.",
118
+ "it": "Per leggere e scrivere dati da un massimo di 5 inverter Huawei SUN2000 e batterie LUNA2000 tramite Modbus TCP. I dispositivi di terze parti possono essere integrati tramite il proxy modbus.",
119
+ "es": "Para leer y escribir datos de hasta 5 inversores Huawei SUN2000 y baterías LUNA2000 a través de Modbus TCP. Los dispositivos de terceros se pueden integrar a través del modbus proxy.",
120
+ "pl": "Do odczytu i zapisu danych z do 5 Huawei SUN2000 inwerterów i akumulatorów LUNA2000 za pośrednictwem Modbus TCP. Urządzenia trójstronne mogą być zintegrowane za pośrednictwem proxy modbus.",
121
+ "uk": "Щоб читати та писати дані від 5 інверторів Huawei SUN2000 та батарей LUNA2000 через Modbus TCP. Сторонні пристрої можуть бути інтегровані через проксі модбуса.",
122
+ "zh-cn": "通过Modbus TCP读取和写入最多5个Huawei SUN2000反转器和LUNA2000电池的数据。 第三方设备可以通过modbus代理集成."
123
123
  },
124
124
  "authors": [
125
125
  "bolliy <stephan@mante.info>"
@@ -130,7 +130,7 @@
130
130
  "sun2000",
131
131
  "luna2000",
132
132
  "inverter",
133
- "charger",
133
+ "smartcharger",
134
134
  "sdongle"
135
135
  ],
136
136
  "tier": 2,
@@ -154,9 +154,60 @@
154
154
  "adminUI": {
155
155
  "config": "json"
156
156
  },
157
+ "docs": {
158
+ "en": [
159
+ "docs/README.md"
160
+ ]
161
+ },
162
+ "messages": [
163
+ {
164
+ "condition": {
165
+ "operand": "and",
166
+ "rules": [
167
+ "oldVersion<=0.6.2",
168
+ "newVersion>0.6.2"
169
+ ]
170
+ },
171
+ "title": {
172
+ "en": "node.js 18.x or higher required",
173
+ "de": "node.js 18.x oder höher erforderlich",
174
+ "ru": "node.js 18.x или выше требуется",
175
+ "pt": "node.js 18.x ou superior requerido",
176
+ "nl": "node.js 18.x of hoger vereist",
177
+ "fr": "node.js 18.x ou plus requis",
178
+ "it": "node.js 18.x o superiore richiesto",
179
+ "es": "node.js 18.x o superior requerido",
180
+ "pl": "node.js 18,x lub wyższa wymagana",
181
+ "uk": "node.js 18.x або вище потрібно",
182
+ "zh-cn": "节点.js 18.x或更高"
183
+ },
184
+ "text": {
185
+ "en": "Please try to stay current with your Node.js version because the support is limited in time. As of now all Node.js versions below 18.x are no longer supported. (End Of Life).",
186
+ "de": "Bitte versuchen Sie die Node.js-Version aktuell zu halten, da die Unterstützung zeitlich begrenzt ist. Ab sofort werden alle Node.js Versionen unter 18.x nicht mehr unterstützt. (End Of Life).",
187
+ "ru": "Пожалуйста, попытайтесь оставаться в курсе своей версии Node.js, потому что поддержка ограничена во времени. На данный момент все версии Node.js ниже 18.x больше не поддерживаются. (Конец жизни).",
188
+ "pt": "Por favor, tente manter-se atual com sua versão Node.js porque o suporte é limitado a tempo. A partir de agora todas as versões do Node.js abaixo de 18.x não são mais suportadas. (End Of Life).",
189
+ "nl": "Probeer om actueel te blijven met uw Node.js-versie omdat de ondersteuning beperkt is in de tijd. Vanaf nu worden alle Node.js versies onder 18.x niet meer ondersteund. (Einde van het leven).",
190
+ "fr": "Veuillez essayer de rester à jour avec votre version Node.js car le support est limité dans le temps. Toutes les versions de Node.js sous 18.x ne sont plus prises en charge. (Fin de vie).",
191
+ "it": "Si prega di cercare di rimanere corrente con la versione Node.js perché il supporto è limitato nel tempo. A partire da ora tutte le versioni Node.js inferiori a 18.x non sono più supportate. (End Of Life).",
192
+ "es": "Por favor, trate de mantenerse actualizado con su versión Node.js porque el soporte es limitado en el tiempo. A partir de ahora todas las versiones Node.js debajo de 18.x ya no están soportadas. (End Of Life).",
193
+ "pl": "Proszę spróbować pozostać na bieżąco z wersją Node.js ponieważ wsparcie jest ograniczone w czasie. Od teraz wszystkie wersje Node.js poniżej 18.x nie są już obsługiwane. (Koniec życia).",
194
+ "uk": "Будь-ласка, будь ласка, намагайтеся постійно триматися з версією Node.js, оскільки підтримка обмежена в часі. Зараз всі версії Node.js нижче 18.x не підтримуються. (Для життя).",
195
+ "zh-cn": "请尝试保留您的 Node.js 版本, 因为支持时间有限 。 到目前为止,18x以下的所有Node.js版本不再被支持. (寿终."
196
+ },
197
+ "level": "info",
198
+ "buttons": [
199
+ "agree",
200
+ "cancel"
201
+ ],
202
+ "link": "https://github.com/bolliy/ioBroker.sun2000/wiki/Update-node.js",
203
+ "linkText": {
204
+ "en": "The node.js update procedure is described here."
205
+ }
206
+ }
207
+ ],
157
208
  "dependencies": [
158
209
  {
159
- "js-controller": ">=3.3.22"
210
+ "js-controller": ">=5.0.0"
160
211
  }
161
212
  ],
162
213
  "globalDependencies": [
@@ -253,7 +304,7 @@
253
304
  "role": "indicator.port",
254
305
  "read": true,
255
306
  "write": false,
256
- "desc": " Device modbus port"
307
+ "desc": "Device modbus port"
257
308
  }
258
309
  },
259
310
  {
@@ -268,7 +319,7 @@
268
319
  "role": "indicator.id",
269
320
  "read": true,
270
321
  "write": false,
271
- "desc": "deevice modbus IDs"
322
+ "desc": "device modbus IDs"
272
323
  }
273
324
  },
274
325
  {
@@ -106,7 +106,6 @@ class ServiceQueueMap {
106
106
  if (item.type == deviceType.battery && this.inverterInfo?.numberBatteryUnits == 0) continue;
107
107
 
108
108
  if (item?.state) {
109
- //this._map.set(item.state.id, { field : item , value : null, ack : false });
110
109
  this._serviceMap.set(item.state.id, item);
111
110
  }
112
111
  }
@@ -134,7 +133,7 @@ class ServiceQueueMap {
134
133
  tCDP[3] = 383 - Working mode settings - self-consumption (discharge)
135
134
  */
136
135
  const tCDP = [1,0,1440,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
137
- if (await this._writeRegisters(47255,tCDP)) this.adapter.logger.info('Control: The default TOU settings are stored.');
136
+ if (await this._writeRegisters(47255,tCDP)) this.adapter.logger.info('Control: The default TOU setting are transferred');
138
137
  }
139
138
  }
140
139
  }
@@ -191,7 +190,7 @@ class ServiceQueueMap {
191
190
  service.errorCount ++;
192
191
  if (service.errorCount > 1) {
193
192
  this._eventMap.delete(event.id); //forget it
194
- this.log.warn('Control: Event is discarded because it could not be processed.'+this.inverterInfo.path+'.control.'+event.id);
193
+ this.log.info('Control: Event is discarded because it could not be processed. '+this.inverterInfo.path+'.control.'+event.id);
195
194
  }
196
195
  }
197
196
  }
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const {deviceType,storeType,dataRefreshRate,dataType} = require(__dirname + '/../types.js');
4
- const {Logging,RegisterMap,isSunshine} = require(__dirname + '/../tools.js');
4
+ const {Logging,RegisterMap} = require(__dirname + '/../tools.js');
5
5
 
6
6
  class DriverBase {
7
7
  constructor(stateInstance,device, options) {
@@ -17,12 +17,13 @@ class DriverBase {
17
17
  this._driverClass = options?.driverClass,
18
18
  this._name = options?.name;
19
19
 
20
+ this._errorCount = 0;
20
21
  this._modbusAllowed = true; //modbus request is allowed
21
22
  this._deviceStatus = -1; //device shutdown or standby
22
23
  this._regMap = new RegisterMap();
23
24
 
24
25
  //v0.6.x
25
- this.control = undefined; //Battery Charge control
26
+ this.control = null; //Battery Charge control
26
27
  this.log = new Logging(this.adapter); //my own Logger
27
28
 
28
29
  this.registerFields = [];
@@ -46,8 +47,6 @@ class DriverBase {
46
47
  }
47
48
 
48
49
  get modbusAllowed () {
49
- //v0.6.0
50
- if (!this._modbusAllowed) this._modbusAllowed = isSunshine(this.adapter);
51
50
  return this._modbusAllowed;
52
51
  }
53
52
 
@@ -92,8 +91,6 @@ class DriverBase {
92
91
  if (reg.states) {
93
92
  for(const field of reg.states) {
94
93
  const state = field.state;
95
- //v0.4.0
96
- //if (field.store !== storeType.never && !reg.initState) {
97
94
  if (field.store !== storeType.never && !state.initState) {
98
95
  await this.state.initState(path,state);
99
96
  state.initState = true;
@@ -107,10 +104,13 @@ class DriverBase {
107
104
  if (field.mapper) {
108
105
  value = await field.mapper(value);
109
106
  }
107
+
110
108
  this.stateCache.set(path+state.id, value, {
111
109
  renew : field?.store === storeType.always,
112
110
  stored : field?.store === storeType.never
113
- });
111
+ }
112
+
113
+ );
114
114
  }
115
115
  }
116
116
  }
@@ -124,7 +124,7 @@ class DriverBase {
124
124
  async updateStates(modbusClient,refreshRate,duration) {
125
125
  //if the device is down or standby we cannot read or write anythink?!
126
126
  //new since 0.4.x
127
- if (!this.modbusAllowed) return 0;
127
+ //if (!this.modbusAllowed) return 0;
128
128
  if (this._modbusId >= 0) modbusClient.setID(this._modbusId);
129
129
 
130
130
  const start = this._newNowTime();
@@ -142,10 +142,7 @@ class DriverBase {
142
142
  break;
143
143
  }
144
144
  }
145
- //v0.4.x
146
- //it is ok, because needs data for new modbus server!
147
- //if (!reg.states || reg.states.length == 0) continue; //no states ?!
148
-
145
+ if (!this.modbusAllowed && reg.standby !== true) continue; //standby - v0.6.x
149
146
  if (!dataRefreshRate.compare(refreshRate,reg.refresh)) continue; //refreshrate unequal
150
147
  if (reg.type == deviceType.meter && this.deviceInfo?.meter == false) continue; //meter
151
148
  if (reg.type == deviceType.battery && this.deviceInfo?.numberBatteryUnits == 0) continue; //battery
@@ -170,12 +167,15 @@ class DriverBase {
170
167
  reg.lastread = this._newNowTime();
171
168
  await this._processRegister(reg,data);
172
169
  readRegisters++;
170
+ this._errorCount = 0;
173
171
  } catch (err) {
172
+ if (err.modbusCode === undefined) this._errorCount ++;
174
173
  if (!reg.readErrorHook || !reg.readErrorHook(err,reg)) {
175
174
  this.log.warn(`Error while reading from ${modbusClient.ipAddress} [Reg: ${reg.address}, Len: ${reg.length}, modbusID: ${modbusClient.id}] with: ${err.message}`);
176
175
  if (err.code == 'EHOSTUNREACH' || err.modbusCode == 6) break; // modbus is busy : 6
177
176
  }
178
177
  }
178
+
179
179
  }
180
180
  //Einschubfunktionen
181
181
  await this._runPostUpdateHooks(refreshRate);
@@ -11,8 +11,7 @@ class InverterInfo extends DriverBase {
11
11
  super(stateInstance,device,{
12
12
  name: 'Huawei DriverInfo'
13
13
  });
14
- this._newInstance = undefined;
15
- this._errorCount = 0;
14
+ this._newInstance = null;
16
15
 
17
16
  //https://github.com/ioBroker/ioBroker.docs/blob/master/docs/en/dev/stateroles.md
18
17
  const newFields = [
@@ -33,32 +32,16 @@ class InverterInfo extends DriverBase {
33
32
  state: {id: 'info.modelID', name: 'Model ID', type: 'number', role: 'info.hardware', desc: 'reg:30070, len:1' },
34
33
  register: {reg: 30070, type: dataType.uint16}
35
34
  }],
36
- readErrorHook: (err,reg) => {
37
- //modbus Error 2 - illegal address
38
- if(err.modbusCode === 2) {
39
- reg.lastread = this._newNowTime(); //try it once
40
- this.log.error('Modbus Error 2: Huawei inverter could not be identified for modbus ID '+this._modbusId+'!');
41
- return true; //self handle
42
- }
43
-
44
- this.log.warn('Can not connect to Huawei inverter for modbus ID '+this._modbusId+'!');
45
- if (err.modbusCode === undefined) {
46
- if (!isSunshine(this.adapter)) {
47
- this._errorCount ++;
48
- if (this._errorCount > 2) {
49
- this.log.warn('It will be tried again when the sun rises :-)');
50
- this._modbusAllowed = false;
51
- return true;
52
- //this.log.beQuiet(!sunShine);
53
- }
54
- }
55
- } else {
56
- this._errorCount = 0;
57
- }
35
+ readErrorHook: () => { //err,reg
36
+ this.log.error('Can not connect to Huawei inverter for modbus ID '+this._modbusId+'!');
37
+ //reg.lastread = this._newNowTime(); //try it once
38
+ //return true;
58
39
  },
59
40
  postHook: (path) => {
60
41
  const detectedModelId = this.stateCache.get(path+'info.modelID')?.value;
61
42
  if (detectedModelId) {
43
+ const model = this.stateCache.get(path+'info.model')?.value;
44
+ this.log.info('Identified a Huawei '+model+' model '+detectedModelId+' for modbus ID '+this._modbusId);
62
45
  const model_sun2000M1 = [424,425,426,427,428,429,463,142];
63
46
  if(model_sun2000M1.includes(detectedModelId) || detectedModelId >= 430) {
64
47
  this._newInstance = new InverterSun2000_M1(this.state,device, { modelId : detectedModelId });
@@ -73,29 +56,27 @@ class InverterInfo extends DriverBase {
73
56
  ];
74
57
 
75
58
  this.registerFields.push.apply(this.registerFields,newFields);
76
-
77
- /*
78
- const newHooks = [
79
- {
80
- fn : () => {
81
- if (!this._newInstance) {
82
- this.log.error('Can not connect to Huawei inverter for modbus ID '+this._modbusId+'!');
83
- if (!isSunshine(this.adapter)) {
84
- this.log.info('Try again when the sun is shining.');
85
- this._modbusAllowed = false;
86
- //this.log.beQuiet(!sunShine);
87
- }
88
- }
89
- }
90
- }
91
- ];
92
- this.postUpdateHooks.push.apply(this.postUpdateHooks,newHooks);
93
- */
94
59
  }
95
60
 
96
61
  get newInstance () {
97
62
  return this._newInstance;
98
63
  }
64
+
65
+ //overload
66
+ get modbusAllowed () {
67
+ if (isSunshine(this.adapter)) {
68
+ if (!this._modbusAllowed) {
69
+ this._modbusAllowed = true;
70
+ this._errorCount = 0;
71
+ }
72
+ } else {
73
+ if (this._errorCount > 3 && this._modbusAllowed) {
74
+ this.log.warn('It will try again when the sun rises for modbus id '+this._modbusId+' :-)');
75
+ this._modbusAllowed = false;
76
+ }
77
+ }
78
+ return this._modbusAllowed;
79
+ }
99
80
  }
100
81
 
101
82
 
@@ -107,11 +88,14 @@ class InverterSun2000 extends DriverBase{
107
88
  driverClass : driverClasses.inverter,
108
89
  ...options,
109
90
  });
91
+ //TestMode
92
+ this._testMode = this.adapter.settings.address === '192.168.2.54';
93
+ this.log.debug('### TestMode (#60) '+this._testMode+ ' '+this.adapter.settings.address);
94
+ this._testMode = false;
110
95
 
111
96
  this.solarSum = new RiemannSum();
112
- //v0.6.0
113
97
  this.adapter.getState(this.deviceInfo.path+'.derived.dailySolarYield',(err, state) => {
114
- if (state && !err) this.solarSum.setStart(state.val,state.ts);
98
+ if (!err && state) this.solarSum.setStart(state.val,state.ts);
115
99
  });
116
100
 
117
101
  this.control = new ServiceQueueMap(this.adapter,this.deviceInfo);
@@ -151,17 +135,6 @@ class InverterSun2000 extends DriverBase{
151
135
  register: {reg: 30073, type: dataType.int32, gain:1000}
152
136
  }],
153
137
  },
154
- {
155
- address : 37765,
156
- length : 2,
157
- info : 'Battery Charge And Discharge Power',
158
- refresh : dataRefreshRate.high,
159
- type : deviceType.battery,
160
- states : [{
161
- state: {id: 'battery.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:37765, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
162
- register: {reg: 37765, type: dataType.int32, gain:1000}
163
- }]
164
- },
165
138
  {
166
139
  address : 32080,
167
140
  length : 2,
@@ -174,6 +147,17 @@ class InverterSun2000 extends DriverBase{
174
147
  store : storeType.always
175
148
  }]
176
149
  },
150
+ {
151
+ address : 37765,
152
+ length : 2,
153
+ info : 'Battery Charge And Discharge Power',
154
+ refresh : dataRefreshRate.high,
155
+ type : deviceType.battery,
156
+ states : [{
157
+ state: {id: 'battery.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:37765, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
158
+ register: {reg: 37765, type: dataType.int32, gain:1000}
159
+ }]
160
+ },
177
161
  {
178
162
  address : 32064,
179
163
  length : 2,
@@ -215,11 +199,11 @@ class InverterSun2000 extends DriverBase{
215
199
  info : 'meter activePower',
216
200
  refresh : dataRefreshRate.high,
217
201
  type : deviceType.meter,
202
+ //standby : true,
218
203
  states: [{
219
204
  state: {id: 'meter.activePower', name: 'ActivePower', type: 'number', unit: 'kW', role: 'value.power.active', desc: 'reg:37113, len:2 (>0: feed-in to grid. <0: supply from grid.)' },
220
205
  register: { reg: 37113, type: dataType.int32, gain:1000 }
221
- }
222
- ]
206
+ }]
223
207
  },
224
208
  {
225
209
  address : 37052,
@@ -400,6 +384,41 @@ class InverterSun2000 extends DriverBase{
400
384
  }
401
385
  }
402
386
  },
387
+ {
388
+ //read also standby
389
+ address : 32089,
390
+ length : 1,
391
+ info : 'inverter deviceStatus',
392
+ refresh : dataRefreshRate.low,
393
+ standby : true,
394
+ type : deviceType.inverter,
395
+ states: [{
396
+ state: {id: 'deviceStatus', name: 'Device Status', type: 'number', unit: '', role: 'value', desc: 'reg:32089, len:1'},
397
+ register: {reg: 32089, type: dataType.uint16},
398
+ mapper: async value => {
399
+ if (this._testMode) {
400
+ this.log.info('testMode: Die Sonne scheint? '+isSunshine(this.adapter));
401
+ if (!isSunshine(this.adapter)) return 2;
402
+ //return 2;
403
+ }
404
+ return value;
405
+ },
406
+ },{
407
+ state: {id: 'derived.deviceStatus', name: 'Device Status Information', type: 'string', unit: '', role: 'value'}
408
+ }
409
+ ],
410
+ readErrorHook: (err,reg) => { //(err,reg)
411
+ if (err.modbusCode === undefined) {
412
+ reg.lastread = this._newNowTime();
413
+ //return true; //Error has been handled
414
+ }
415
+ },
416
+ postHook: (path) => {
417
+ //DeviceStatus
418
+ const deviceStatus = this.stateCache.get(path+'deviceStatus')?.value;
419
+ this.stateCache.set(path+'derived.deviceStatus',getDeviceStatusInfo(deviceStatus));
420
+ }
421
+ },
403
422
  {
404
423
  address : 32066,
405
424
  length : 50,
@@ -473,13 +492,6 @@ class InverterSun2000 extends DriverBase{
473
492
  state: {id: 'isulationResistance', name: 'Isulation Resistance', type: 'number', unit: 'MOhm', role: 'value', desc: 'reg:32088, len:1'},
474
493
  register: {reg: 32088, type: dataType.uint16, gain: 1000}
475
494
  },
476
- {
477
- state: {id: 'deviceStatus', name: 'Device Status', type: 'number', unit: '', role: 'value', desc: 'reg:32089, len:1'},
478
- register: {reg: 32089, type: dataType.uint16}
479
- },
480
- {
481
- state: {id: 'derived.deviceStatus', name: 'Device Status Information', type: 'string', unit: '', role: 'value'}
482
- },
483
495
  {
484
496
  state: {id: 'faultCode', name: 'Fault Code', type: 'number', unit: '', role: 'value', desc: 'reg:32090, len:1'},
485
497
  register: {reg: 32090, type: dataType.uint16}
@@ -500,14 +512,7 @@ class InverterSun2000 extends DriverBase{
500
512
  state: {id: 'dailyEnergyYield', name: 'Daily Energy Yield', type: 'number', unit: 'kWh', role: 'value.power.produced', desc: 'reg:32114, len:2'},
501
513
  register: {reg: 32114, type: dataType.uint32, gain: 100}
502
514
  }
503
-
504
- ],
505
- postHook: (path) => {
506
- //DeviceStatus
507
- const deviceStatus = this.stateCache.get(path+'deviceStatus')?.value;
508
- //this.deviceInfo.deviceStatus = deviceStatus;
509
- this.stateCache.set(path+'derived.deviceStatus',getDeviceStatusInfo(deviceStatus));
510
- }
515
+ ]
511
516
  },
512
517
  {
513
518
  address : 37100,
@@ -703,39 +708,45 @@ class InverterSun2000 extends DriverBase{
703
708
  //overload
704
709
  get modbusAllowed () {
705
710
  //if the modbus-device offline we cannot read or write anythink!
706
- /*
707
- const timeAfterSunrise = this._newNowTime() - this.adapter.settings.sunrise?.getTime();
708
- const timeAfterSunrise = 1000;
709
- const allow = timeAfterSunrise > 0 && timeAfterSunrise < 60*60*1000; //60 Minutes after sunrise
710
- this.adapter.log.debug('### modbusAllowed '+allow+' deviceStatus: '+this.deviceStatus);
711
- */
712
-
713
- if (this.deviceStatus == 0x0002) { //detecting irradiation
714
- if (this.adapter.settings.sunrise) {
715
- const timeAfterSunrise = this._newNowTime() - this.adapter.settings.sunrise?.getTime();
716
- this._modbusAllowed = timeAfterSunrise > 0 && timeAfterSunrise < 60*60*1000; //60 Minutes after sunrise
717
- } else {
718
- //im Zweifel immer wake up
719
- this._modbusAllowed = true;
711
+ let modbusAllowed = true;
712
+ if (this.deviceInfo.index > 0) { //I am a slave inverter
713
+ if (this.adapter.devices[0].driverClass === driverClasses.inverter && this.adapter.devices[0].instance) {
714
+ modbusAllowed = this.adapter.devices[0].instance.modbusAllowed; //first ask the master
720
715
  }
721
- } else {
722
- this._modbusAllowed = true;
723
716
  }
717
+ if (modbusAllowed) {
718
+ modbusAllowed = this.deviceStatus !== 0x0002;
719
+ if (this._errorCount > 3) modbusAllowed = false;
720
+ }
721
+
722
+ if (!modbusAllowed && !this.log.quiet) {
723
+ this.log.info(`The inverter with modbus ID ${this._modbusId} is no longer accessible. That is why the logs are minimized.`);
724
+ this.log.beQuiet(true);
725
+ }
726
+ if (modbusAllowed && this.log.quiet) {
727
+ this.log.beQuiet(false);
728
+ this.log.info(`The inverter with modbus ID ${this._modbusId} is accessible again.`);
729
+ this._errorCount = 0;
730
+ }
731
+ this._modbusAllowed = modbusAllowed;
724
732
  return this._modbusAllowed;
725
733
  }
726
734
 
727
735
  //overload
728
736
  get deviceStatus() {
729
- const status = this.stateCache.get(this.deviceInfo.path+'.deviceStatus')?.value;
737
+ const status = this.stateCache.get(this._getStatePath()+'deviceStatus')?.value;
730
738
  if (status) {
731
- //this.adapter.log.debug('### deviceStatus '+status);
732
739
  if (status !== this._deviceStatus && this._deviceStatus >= 0) {
733
- this.log.info(`The Inverter ${this.deviceInfo.index} switches to ${this.stateCache.get(this.deviceInfo.path+'.derived.deviceStatus')?.value} mode.`);
740
+ this.log.info(`The Inverter with modbus ID ${this._modbusId} switches to ${this.stateCache.get(this.deviceInfo.path+'.derived.deviceStatus')?.value} mode.`);
734
741
  }
735
742
  this._deviceStatus = status;
736
743
  }
737
744
  return this._deviceStatus;
738
745
  }
746
+
747
+ async mitnightProcess() {
748
+ this.solarSum.reset();
749
+ }
739
750
  }
740
751
 
741
752
  class InverterSun2000_M1 extends InverterSun2000{
@@ -1,5 +1,5 @@
1
1
  const {driverClasses,dataRefreshRate,dataType} = require(__dirname + '/../types.js');
2
- const {isSunshine} = require(__dirname + '/../tools.js');
2
+ //const {isSunshine} = require(__dirname + '/../tools.js');
3
3
  const DriverBase = require(__dirname + '/driver_base.js');
4
4
 
5
5
  class Sdongle extends DriverBase{
@@ -11,8 +11,6 @@ class Sdongle extends DriverBase{
11
11
  ...options,
12
12
  });
13
13
 
14
- this._errorCount = 0;
15
-
16
14
  const newFields = [
17
15
  {
18
16
  address : 30015,
@@ -29,27 +27,7 @@ class Sdongle extends DriverBase{
29
27
  {
30
28
  state: {id: 'sdongle.protokolVersion', name: 'Protokol Version', type: 'number', unit: '', role: 'value',desc: 'reg:30068, len:2'},
31
29
  register: {reg: 30068, type: dataType.uint32}
32
- }],
33
- readErrorHook: (err) => {
34
- /*
35
- if (err.code == 'EHOSTUNREACH') {
36
- this._modbusAllowed = isSunshine(this.adapter);
37
- }
38
- */
39
- if (err.modbusCode === undefined) {
40
- if (!isSunshine(this.adapter)) {
41
- this._errorCount ++;
42
- if (this._errorCount > 2) {
43
- this._modbusAllowed = false;
44
- }
45
- }
46
- } else {
47
- this._errorCount = 0;
48
- }
49
- },
50
- postHook: () => {
51
- this._errorCount = 0;
52
- }
30
+ }]
53
31
  },
54
32
  {
55
33
  address : 37410,
@@ -102,20 +80,15 @@ class Sdongle extends DriverBase{
102
80
 
103
81
  this.registerFields.push.apply(this.registerFields,newFields);
104
82
 
105
- /*
106
- const newHooks = [
107
- {
108
- fn : (path) => {
109
- if (!this.stateCache.get(path+'sdongle.sn')?.value) {
110
- const sunShine = isSunshine(this.adapter);
111
- if (!sunShine) this.log.info('Try again when the sun is shining.');
112
- this.log.beQuiet(!sunShine);
113
- }
114
- }
115
- }
116
- ];
117
- this.postUpdateHooks.push.apply(this.postUpdateHooks,newHooks);
118
- */
83
+ }
84
+
85
+ //overload
86
+ get modbusAllowed () {
87
+ // the first device is the master
88
+ if (this.adapter.devices[0].driverClass === driverClasses.inverter && this.adapter.devices[0].instance) {
89
+ return this.adapter.devices[0].instance.modbusAllowed; //ask the master
90
+ }
91
+ return false;
119
92
  }
120
93
  }
121
94
 
@@ -64,8 +64,8 @@ class SmartLoggerMeter extends DriverBase{
64
64
  ...options,
65
65
  });
66
66
 
67
- this._testMode = (this._modbusId == 1);
68
- //this._testMode = false;
67
+ //this._testMode = (this._modbusId == 1);
68
+ this._testMode = false;
69
69
 
70
70
  //https://github.com/ioBroker/ioBroker.docs/blob/master/docs/en/dev/stateroles.md
71
71
  const newFields = [
@@ -153,10 +153,6 @@ class ModbusConnect extends DeviceInterface {
153
153
  this._adjustDelay(err,false);
154
154
  await this._create();
155
155
  }
156
- /*
157
- if (err.modbusCode === 6 ) this._adjustDelay(err,false); //Slave device busy
158
- if (err.modbusCode === 5 ) await this._create();
159
- */
160
156
  }
161
157
  }
162
158
 
package/lib/register.js CHANGED
@@ -151,15 +151,17 @@ class Registers {
151
151
 
152
152
  async storeStates() {
153
153
  for (const stateEntry of this.stateCache.values()) {
154
+ //if (stateEntry?.storeType === storeType.never) continue;
154
155
  if (stateEntry.stored) continue;
156
+ //if (stateEntry?.storeType !== storeType.always && stateEntry.stored) continue;
155
157
  if (stateEntry.value !== null) {
156
158
  try {
157
159
  stateEntry.stored = true;
158
160
  await this.adapter.setStateAsync(stateEntry.id, {val: stateEntry.value , ack: true});
159
- //this.adapter.log.debug(`Fetched ${stateEntry.id}, val=${stateEntry.value}`);
161
+ this.adapter.logger.debug(`Fetched ${stateEntry.id}, val=${stateEntry.value}`);
160
162
  } catch (err) {
161
163
  stateEntry.stored = false;
162
- this.adapter.log.warn(`Error while fetching ${stateEntry.id}, val=${stateEntry.value} err=${err.message}`);
164
+ this.adapter.logger.warn(`Error while fetching ${stateEntry.id}, val=${stateEntry.value} err=${err.message}`);
163
165
  }
164
166
  }
165
167
  }
@@ -170,17 +172,14 @@ class Registers {
170
172
  async updateStates(device,modbusClient,refreshRate,duration) {
171
173
  //this.adapter.log.debug('### DeviceInfo: '+device.index+' '+JSON.stringify(device.instance.info));
172
174
  if (device.instance) {
173
- //const buff = device.instance.getHoldingRegisters(37115,2);
174
- //this.adapter.log.debug('### buff '+buff);
175
- //new Instance?
176
175
  if (device.instance.newInstance) {
177
- this.adapter.log.debug('DeviceInfo: '+device.index+' '+JSON.stringify(device.instance.info));
176
+ this.adapter.logger.debug('DeviceInfo: '+device.index+' '+JSON.stringify(device.instance.info));
178
177
  device.instance = device.instance.newInstance;
179
- this.adapter.log.debug('Device: '+device.index+' '+JSON.stringify(device.instance.info));
178
+ this.adapter.logger.debug('Device: '+device.index+' '+JSON.stringify(device.instance.info));
180
179
  }
181
180
  return device.instance.updateStates(modbusClient,refreshRate,duration);
182
181
  } else {
183
- this.adapter.log.error('No device instance has been initialized!');
182
+ this.adapter.logger.error('No device instance has been initialized!');
184
183
  return 0;
185
184
  }
186
185
  }
@@ -210,22 +209,14 @@ class Registers {
210
209
  this.stateCache.set('collected.gridImportStart',state?.val, {type : 'number', stored : true });
211
210
  state = await this.adapter.getStateAsync('collected.consumptionStart');
212
211
  this.stateCache.set('collected.consumptionStart',state?.val, {type : 'number', stored : true });
213
- //v0.6.0
214
- /*
215
- for (const device of this.adapter.devices) {
216
- state = await this.adapter.getStateAsync(device.path+'.derived.dailySolarYield');
217
- state?.val && device.instance.solarSum && device.instance.solarSum.setStart(state.val,state.ts);
218
- }
219
- */
220
212
  }
221
213
 
222
214
  //state
223
215
  CheckReadError(timeShift) {
224
216
  const now = new Date();
225
217
  for (const device of this.adapter.devices) {
226
- //v0.4.x
227
- if (!device.instance.info.online) continue;
228
218
  for (const [i, reg] of device.instance.registerFields.entries()) {
219
+ if (!device.instance.modbusAllowed) continue; //standby
229
220
  if (reg.type == deviceType.meter && device.meter == false) continue; //not meter
230
221
  if (reg.type == deviceType.battery && device?.numberBatteryUnits == 0) continue; //battery
231
222
  if (reg.type == deviceType.batteryUnit2 && device?.numberBatteryUnits < 2) continue; //battery Unit2
@@ -270,6 +261,9 @@ class Registers {
270
261
  this.stateCache.set('collected.gridImportStart',this.stateCache.get('meter.reverseActiveEnergy')?.value, {type : 'number'});
271
262
  // copy consumption Sum to Start for the next day
272
263
  this.stateCache.set('collected.consumptionStart',this.stateCache.get('collected.consumptionSum')?.value, {type : 'number'});
264
+ for (const device of this.adapter.devices) {
265
+ if (device.instance.mitnightProcess) await device.instance.mitnightProcess();
266
+ }
273
267
  this.storeStates(); //fire and forget
274
268
  }
275
269
 
package/lib/tools.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
+
2
3
  const suncalc = require('suncalc2');
4
+ //const {storeType} = require(__dirname + '/types.js');
3
5
 
4
6
 
5
7
  class Logging {
@@ -51,13 +53,29 @@ class StateMap {
51
53
  if (options?.type == 'number') {
52
54
  value = Math.round((value + Number.EPSILON) * 1000) / 1000; //3rd behind
53
55
  }
54
- if (options?.renew || this.get(id)?.value !== value) {
56
+
57
+ const existing = this.get(id); //existing entry
58
+
59
+ const mapOptions = {
60
+ id: id,
61
+ value: value,
62
+ stored : existing?.stored ? existing.stored : false
63
+ };
64
+ if (options?.renew || existing?.value !== value) mapOptions.stored = false;
65
+ if (options?.stored) mapOptions.stored = options.stored;
66
+
67
+ this.stateMap.set(id, mapOptions);
68
+
69
+ /* the old code
70
+ if (options?.renew || existing?.value !== value) {
55
71
  if (options?.stored ) {
56
72
  this.stateMap.set(id, {id: id, value: value, stored: options.stored});
57
73
  } else {
58
74
  this.stateMap.set(id, {id: id, value: value});
59
75
  }
60
76
  }
77
+ */
78
+
61
79
  }
62
80
  }
63
81
 
@@ -210,7 +228,25 @@ function getAstroDate (adapter,pattern, date, offsetMinutes) {
210
228
  function isSunshine(adapter) {
211
229
  if (adapter.settings.sunrise && adapter.settings.sunset) {
212
230
  const now = new Date();
213
- return (now > adapter.settings.sunrise && now < adapter.settings.sunset);
231
+ /*
232
+ const sunrise = new Date(
233
+ now.getFullYear(),
234
+ now.getMonth(),
235
+ now.getDate(), // today, ...
236
+ 14, 18, 0 // ...at 00:00:00 hours
237
+ );
238
+
239
+ const sunset = new Date(
240
+ now.getFullYear(),
241
+ now.getMonth(),
242
+ now.getDate(), // today, ...
243
+ 14, 16, 0 // ...at 00:00:00 hours
244
+ );
245
+
246
+ return (now.getTime() > sunrise.getTime() || now.getTime() < sunset.getTime());
247
+ */
248
+
249
+ return (now.getTime() > adapter.settings.sunrise.getTime() && now.getTime() < adapter.settings.sunset.getTime());
214
250
  }
215
251
  return true;
216
252
  }
package/main.js CHANGED
@@ -185,9 +185,15 @@ class Sun2000 extends utils.Adapter {
185
185
  await this.initPath();
186
186
  this.state = new Registers(this);
187
187
  await this.atMidnight();
188
+ /*
189
+ if (!this.settings.sunrise || !this.settings.sunset) {
190
+ this.adapterDisable('*** Adapter deactivated, Latitude and longitude must be set! ***');
191
+ return;
192
+ }
193
+ */
188
194
  if (this.settings.modbusAdjust) {
189
195
  this.settings.modbusAdjust = isSunshine(this);
190
- this.logger.debug('Sunshine: '+this.settings.modbusAdjust);
196
+ //this.logger.debug('Sunshine: '+this.settings.modbusAdjust);
191
197
  }
192
198
  this.modbusClient = new ModbusConnect(this,this.settings);
193
199
  this.modbusClient.setCallback(this.endOfmodbusAdjust.bind(this));
@@ -351,7 +357,7 @@ class Sun2000 extends utils.Adapter {
351
357
  numberBatteryUnits : 0
352
358
  });
353
359
  }
354
- //v0.5.0
360
+ //SmartLogger
355
361
  if (this.settings.sl.active) {
356
362
  this.devices.push({
357
363
  index: 0,
@@ -381,12 +387,10 @@ class Sun2000 extends utils.Adapter {
381
387
  await this.adjustInverval();
382
388
  await this.StartProcess();
383
389
  } else {
384
- this.logger.error('*** Adapter deactivated, can\'t parse modbusIds! ***');
385
- this.setForeignState('system.adapter.' + this.namespace + '.alive', false);
390
+ this.adapterDisable('*** Adapter deactivated, can\'t parse modbusIds! ***');
386
391
  }
387
392
  } else {
388
- this.logger.error('*** Adapter deactivated, Adapter Settings incomplete! ***');
389
- this.setForeignState('system.adapter.' + this.namespace + '.alive', false);
393
+ this.adapterDisable('*** Adapter deactivated, Adapter Settings incomplete! ***');
390
394
  }
391
395
  }
392
396
 
@@ -400,7 +404,7 @@ class Sun2000 extends utils.Adapter {
400
404
  const start = new Date().getTime();
401
405
  this.logger.debug('### DataPolling START '+ Math.round((start-this.lastTimeUpdated)/1000)+' sec ###');
402
406
  if (this.lastTimeUpdated > 0 && (start-this.lastTimeUpdated)/1000 > this.settings.highInterval/1000 + 1) {
403
- this.logger.info('Interval '+(start-this.lastTimeUpdated)/1000+' sec');
407
+ this.logger.debug('Interval '+(start-this.lastTimeUpdated)/1000+' sec');
404
408
  }
405
409
  this.lastTimeUpdated = start;
406
410
  const nextLoop = this.settings.highInterval - start % (this.settings.highInterval) + start;
@@ -471,6 +475,11 @@ class Sun2000 extends utils.Adapter {
471
475
  },this.settings.lowInterval);
472
476
  }
473
477
 
478
+ adapterDisable(errMsg) {
479
+ this.logger.error(errMsg);
480
+ this.setForeignState('system.adapter.' + this.namespace + '.alive', false);
481
+ }
482
+
474
483
  /**
475
484
  * Is called when adapter shuts down - callback has to be called under any circumstances!
476
485
  * @param {() => void} callback
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.sun2000",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "sun2000",
5
5
  "author": {
6
6
  "name": "bolliy",
@@ -19,28 +19,28 @@
19
19
  "url": "https://github.com/bolliy/ioBroker.sun2000.git"
20
20
  },
21
21
  "engines": {
22
- "node": ">= 16"
22
+ "node": ">= 18"
23
23
  },
24
24
  "dependencies": {
25
- "@iobroker/adapter-core": "^3.0.4",
26
- "suncalc2": "^1.8.1",
25
+ "@iobroker/adapter-core": "^3.0.6",
27
26
  "modbus-serial": "^8.0.16",
27
+ "suncalc2": "^1.8.1",
28
28
  "tcp-port-used": "^1.0.2"
29
29
  },
30
30
  "devDependencies": {
31
- "@alcalzone/release-script": "^3.6.0",
32
- "@alcalzone/release-script-plugin-iobroker": "^3.6.0",
33
- "@alcalzone/release-script-plugin-license": "^3.5.9",
34
- "@alcalzone/release-script-plugin-manual-review": "^3.5.9",
35
- "@iobroker/adapter-dev": "^1.2.0",
36
- "@iobroker/testing": "^4.1.0",
37
- "@tsconfig/node16": "^16.1.1",
38
- "@types/chai": "^4.3.10",
31
+ "@alcalzone/release-script": "^3.7.0",
32
+ "@alcalzone/release-script-plugin-iobroker": "^3.7.0",
33
+ "@alcalzone/release-script-plugin-license": "^3.7.0",
34
+ "@alcalzone/release-script-plugin-manual-review": "^3.7.0",
35
+ "@iobroker/adapter-dev": "^1.3.0",
36
+ "@iobroker/testing": "^4.1.1",
37
+ "@tsconfig/node16": "^16.1.3",
38
+ "@types/chai": "^4.3.14",
39
39
  "@types/chai-as-promised": "^7.1.8",
40
40
  "@types/mocha": "^10.0.4",
41
- "@types/node": "^20.11.24",
41
+ "@types/node": "^20.12.2",
42
42
  "@types/proxyquire": "^1.3.31",
43
- "@types/sinon": "^17.0.1",
43
+ "@types/sinon": "^17.0.3",
44
44
  "@types/sinon-chai": "^3.2.12",
45
45
  "chai": "^4.3.10",
46
46
  "chai-as-promised": "^7.1.1",
@@ -49,7 +49,7 @@
49
49
  "proxyquire": "^2.1.3",
50
50
  "sinon": "^17.0.1",
51
51
  "sinon-chai": "^3.7.0",
52
- "typescript": "~5.3.3"
52
+ "typescript": "~5.4.3"
53
53
  },
54
54
  "main": "main.js",
55
55
  "files": [