iobroker.sun2000 0.11.0 → 0.12.1

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
@@ -63,6 +63,14 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
63
63
  Placeholder for the next version (at the beginning of the line):
64
64
  ### **WORK IN PROGRESS**
65
65
  -->
66
+ ### 0.12.1 (2024-09-29)
67
+ * no warning from check the valid number during standby: "no irradiation"
68
+
69
+ ### 0.12.0 (2024-09-23)
70
+ * Requirements from ioBroker Check and Service Bot #104
71
+ * added battery packs #85
72
+ * added config panel `Further Register`
73
+
66
74
  ### 0.11.0 (2024-06-27)
67
75
  * added a donation link in the adapter settings
68
76
  * dependency updated
@@ -78,7 +86,6 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
78
86
  * modbus device remains active in standby on the inverter M2,M3
79
87
 
80
88
  ### 0.8.0 (2024-04-19)
81
-
82
89
  * Check numerical values for plausibility #75
83
90
  * realization the "limit the power fed to grid" (Export control)
84
91
  * realization the "forcible Charge or Discharge Power"
@@ -127,6 +127,30 @@
127
127
  }
128
128
  }
129
129
  },
130
+ "tab7": {
131
+ "type": "panel",
132
+ "label": "Further Register",
133
+ "items": {
134
+ "mainHdr1": {
135
+ "newLine": true,
136
+ "type": "header",
137
+ "text": "Further battery register data",
138
+ "size": 2
139
+ },
140
+ "ds_bu": {
141
+ "type": "checkbox",
142
+ "label": "battery units",
143
+ "newLine": true,
144
+ "help": "This register data is stored in the opject path “sun2000.x.inverter.x.battery.unit”"
145
+ },
146
+ "ds_bp": {
147
+ "type": "checkbox",
148
+ "label": "battery packs",
149
+ "newLine": true,
150
+ "help": "This register data is stored in the opject path “sun2000.x.inverter.x.battery.unit.x.pack”"
151
+ }
152
+ }
153
+ },
130
154
  "tab3": {
131
155
  "type": "panel",
132
156
  "label": "Energy control",
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sun2000",
4
- "version": "0.11.0",
4
+ "version": "0.12.1",
5
5
  "news": {
6
+ "0.12.1": {
7
+ "en": "no warning from check the valid number during standby: \"no irradiation\"",
8
+ "de": "keine warnung vor der prüfung der gültigen nummer im standby: \"keine bestrahlung\"",
9
+ "ru": "не предупредить проверить действительный номер во время ожидания: «без облучения»",
10
+ "pt": "sem aviso de verificar o número válido durante o standby: \"nenhuma irradiação\"",
11
+ "nl": "geen waarschuwing van controle van het geldige nummer tijdens standby: \"geen bestraling\"",
12
+ "fr": "aucun avertissement de vérifier le nombre valide en attente: \"pas d'irradiation\"",
13
+ "it": "nessun avviso da controllare il numero valido durante la standby: \"nessuna irradiazione\"",
14
+ "es": "no hay advertencia de comprobar el número válido durante la espera: \"no irradiación\"",
15
+ "pl": "brak ostrzeżenia z sprawdzenia poprawnego numeru podczas czuwania: \"brak napromieniowania\"",
16
+ "uk": "без попередження про перевірку дійсного числа під час очікування: \"не опромінення\"",
17
+ "zh-cn": "在待命时不检查有效号码的警告 : “ 不辐射 ”"
18
+ },
19
+ "0.12.0": {
20
+ "en": "Requirements from ioBroker Check and Service Bot #104\nadded battery packs #85\nadded config panel `Further Register`",
21
+ "de": "Anforderungen an ioBroker Check und Service Bot #104\nakkupacks #85\nhinzufügen config panel `Weiter registrieren `",
22
+ "ru": "Требования от ioBroker Check and Service Bot #104\n#85\nдобавленная панель конфигурации `Further Register \"",
23
+ "pt": "Requisitos de ioBroker Check e Service Bot #104\npacotes de bateria adicionados #85\nadicionado painel de configuração `Further Register \"",
24
+ "nl": "Vereisten van ioBroker Check and Service Bot #104\ntoegevoegde batterijpakketten #85\ntoegevoegd config paneel \"Verder registreren\" Wat",
25
+ "fr": "Exigences de ioBroker Check and Service Bot #104\npacks de batterie supplémentaires #85\najouté panneau de configuration `Plus grand registre \"",
26
+ "it": "Requisiti da ioBroker Check and Service Bot #104\nbatterie aggiunte #85\naggiunto pannello di configurazione `Further Register #",
27
+ "es": "Requisitos de ioBroker Check and Service Bot #104\nañadir paquetes de batería #85\npanel de configuración añadido `Más registro `",
28
+ "pl": "Wymagania dotyczące kontroli ioBroker i serwisu Bot # 104\ndodany zestaw baterii # 85\ndodany panel konfiguracyjny \"Dalszy rejestr '",
29
+ "uk": "Вимоги до ioBroker Check and Service Bot #104\nдоданий акумуляторний пакет #85\nдодано панель налаштувань `Further Реєстр й",
30
+ "zh-cn": "ioBroker检查和服务瓶的所需经费#104\n添加电池包# 85\n添加配置面板“ 进一步登记” `"
31
+ },
6
32
  "0.11.0": {
7
33
  "en": "added a donation link in the adapter settings\ndependency updated",
8
34
  "de": "einen spendenlink in den adaptereinstellungen hinzugefügt\naktualisierte abhängigkeit",
@@ -67,32 +93,6 @@
67
93
  "pl": "inverter model nazwa zbyt wiele znaków # 73",
68
94
  "uk": "ім'я інвертора занадто багато символів #73",
69
95
  "zh-cn": "翻转模型名称过多字符 # 73"
70
- },
71
- "0.7.0": {
72
- "en": "breaking changes\nNode.js 18.x or higher required\nioBroker host (js-controller) 5.x or higher",
73
- "de": "änderungen\nNode.js 18.x oder höher erforderlich\nioBroker Host (js-controller) 5.x oder höher",
74
- "ru": "изменения\nNode.js 18.x или выше требуется\nioBroker host (js-controller) 5.x или выше",
75
- "pt": "alterações de ruptura\nNode.js 18.x ou superior requerido\nhospedeiro ioBroker (js-controller) 5.x ou superior",
76
- "nl": "wijzigingen breken\nNode.js 18.x of hoger vereist\nioBroker host (js-controller) 5.x of hoger",
77
- "fr": "casser les changements\nNode.js 18.x ou plus requis\nioBroker host (js-controller) 5.x ou plus",
78
- "it": "cambiamenti di rottura\nNode.js 18.x o superiore richiesto\nioBroker host (js-controller) 5.x o superiore",
79
- "es": "cambios de ruptura\nNode.js 18.x o superior requerido\nioBroker host (js-controller) 5.x o superior",
80
- "pl": "łamanie zmian\nNode.js 18,x lub wyższa wymagana\njoBroker host (kontroler js-) 5.x lub wyższy",
81
- "uk": "поломка змін\nNode.js 18.x або вище потрібно\nioBroker host (js-controller) 5.x або вище",
82
- "zh-cn": "断开更改\n所需节点.js 18.x或更高\nioBroker 主机(js-controller) 5.x或更高"
83
- },
84
- "0.6.2": {
85
- "en": "standby detection adjusted\nImprovement of logs",
86
- "de": "standby-erkennung angepasst\nVerbesserung der Protokolle",
87
- "ru": "резервное обнаружение с поправкой\nСовершенствование журналов",
88
- "pt": "detecção de espera ajustada\nMelhoria dos logs",
89
- "nl": "stand-by detectie aangepast\nVerbetering van de logs",
90
- "fr": "réglage de la détection en attente\nAmélioration des registres",
91
- "it": "rilevamento standby regolato\nMiglioramento dei registri",
92
- "es": "detección de reserva ajustada\nMejora de los registros",
93
- "pl": "korekta detekcji czuwania\nPoprawa dzienników",
94
- "uk": "автономне виявлення\nУдосконалення колод",
95
- "zh-cn": "经调整的备用检测\n改进日志"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -246,7 +246,8 @@
246
246
  "ms_port": 502,
247
247
  "ms_log": false,
248
248
  "sl_active": false,
249
- "sl_meterId": 11
249
+ "sl_meterId": 11,
250
+ "ds_bu": true
250
251
  },
251
252
  "objects": [],
252
253
  "instanceObjects": [
@@ -180,9 +180,10 @@ class DriverBase {
180
180
  if (!this.modbusAllowed && reg.standby !== true) continue; //standby - v0.6.2
181
181
  if (!dataRefreshRate.compare(refreshRate,reg.refresh)) continue; //refreshrate unequal
182
182
  if (reg.type == deviceType.meter && !this.deviceInfo?.meter) continue; //meter
183
- if (reg.type == deviceType.battery && this.deviceInfo?.numberBatteryUnits == 0) continue; //battery
184
- if (reg.type == deviceType.batteryUnit2 && this.deviceInfo?.numberBatteryUnits < 2) continue; //battery Unit2
185
183
  if (reg.type == deviceType.gridPowerControl && !this.deviceInfo?.meter) continue; //Grid Power Control - v0.8.x
184
+
185
+ if (reg.checkIfActive && !reg.checkIfActive(this._getStatePath(reg.type))) continue; //NEW, PATH
186
+
186
187
  //refresh rate low or empty
187
188
  const lastread = reg.lastread;
188
189
  if ( refreshRate !== dataRefreshRate.high) {
@@ -133,7 +133,7 @@ class InverterSun2000 extends DriverBase{
133
133
  {
134
134
  state: {id: 'info.ratedPower', name: 'Rated power', type: 'number', unit: 'kW', role: 'value.power', desc: 'reg:30073, len:2'},
135
135
  register: {reg: 30073, type: dataType.int32, gain:1000}
136
- }],
136
+ }]
137
137
  },
138
138
  {
139
139
  address : 32080,
@@ -156,7 +156,9 @@ class InverterSun2000 extends DriverBase{
156
156
  states : [{
157
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
158
  register: {reg: 37765, type: dataType.int32, gain:1000}
159
- }]
159
+ }],
160
+ //Check if the address field is active
161
+ checkIfActive: (path) => this._batteryExists(path)
160
162
  },
161
163
  {
162
164
  address : 32064,
@@ -199,7 +201,6 @@ class InverterSun2000 extends DriverBase{
199
201
  info : 'meter activePower',
200
202
  refresh : dataRefreshRate.high,
201
203
  type : deviceType.meter,
202
- //standby : true,
203
204
  states: [{
204
205
  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.)' },
205
206
  register: { reg: 37113, type: dataType.int32, gain:1000 }
@@ -208,7 +209,7 @@ class InverterSun2000 extends DriverBase{
208
209
  {
209
210
  address : 37052,
210
211
  length : 10,
211
- info : 'battery unit1 indicator',
212
+ info : 'battery unit1 (indicator)',
212
213
  states: [
213
214
  {
214
215
  state: { id: 'battery.unit.1.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
@@ -221,10 +222,186 @@ class InverterSun2000 extends DriverBase{
221
222
  if(err.modbusCode === 2) {
222
223
  reg.lastread = this._newNowTime(); //try it once
223
224
  this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.1.SN', '', { stored : true });
224
- return true; //self handle
225
+ return true; //error self handle
225
226
  }
226
227
  }
227
228
  },
229
+ //--
230
+ {
231
+ address : 38200,
232
+ length : 10,
233
+ info : 'battery unit1 Pack1 (indicator)',
234
+ states: [
235
+ {
236
+ state: { id: 'battery.unit.1.batteryPack.1.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
237
+ register: { reg: 38200, type: dataType.string, length: 6},
238
+ store: storeType.never
239
+ },
240
+ ],
241
+ readErrorHook: (err,reg) => {
242
+ //modbus Error 2 - illegal address
243
+ if(err.modbusCode === 2) {
244
+ reg.lastread = this._newNowTime(); //try it once
245
+ this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.1.batteryPack.1.SN', '', { stored : true });
246
+ return true; //error self handle
247
+ }
248
+ }
249
+ },
250
+ {
251
+ address : 38242,
252
+ length : 10,
253
+ info : 'battery unit1 Pack2 (indicator)',
254
+ states: [
255
+ {
256
+ state: { id: 'battery.unit.1.batteryPack.2.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
257
+ register: { reg: 38242, type: dataType.string, length: 6},
258
+ store: storeType.never
259
+ },
260
+ ],
261
+ readErrorHook: (err,reg) => {
262
+ //modbus Error 2 - illegal address
263
+ if(err.modbusCode === 2) {
264
+ reg.lastread = this._newNowTime(); //try it once
265
+ this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.1.batteryPack.2.SN', '', { stored : true });
266
+ return true; //error self handle
267
+ }
268
+ }
269
+ },
270
+ {
271
+ address : 38284,
272
+ length : 10,
273
+ info : 'battery unit1 Pack3 (indicator)',
274
+ states: [
275
+ {
276
+ state: { id: 'battery.unit.1.batteryPack.3.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
277
+ register: { reg: 38284, type: dataType.string, length: 6},
278
+ store: storeType.never
279
+ },
280
+ ],
281
+ readErrorHook: (err,reg) => {
282
+ //modbus Error 2 - illegal address
283
+ if(err.modbusCode === 2) {
284
+ reg.lastread = this._newNowTime(); //try it once
285
+ this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.1.batteryPack.3.SN', '', { stored : true });
286
+ return true; //error self handle
287
+ }
288
+ }
289
+ },
290
+ {
291
+ address : 38229,
292
+ length : 13,
293
+ info : 'battery Pack 1 information',
294
+ refresh : dataRefreshRate.low,
295
+ type : deviceType.battery,
296
+ states: [
297
+ {
298
+ state: {id: 'battery.unit.1.batteryPack.1.SOC', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:38229 len:1'},
299
+ register: {reg: 38229, type: dataType.uint16, gain: 10}
300
+ },
301
+ {
302
+ state: {id: 'battery.unit.1.batteryPack.1.totalCharge', name: 'Total Charge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38238, len:2'},
303
+ register: {reg: 38238, type: dataType.uint32, gain: 100}
304
+ },
305
+ {
306
+ state: {id: 'battery.unit.1.batteryPack.1.totalDischarge', name: 'Total Discharge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38240, len:2'},
307
+ register: {reg: 38240, type: dataType.uint32, gain: 100}
308
+ }
309
+ ],
310
+ checkIfActive: (path) => this._batteryExists(path,1,1)
311
+ },
312
+ {
313
+ address : 38271,
314
+ length : 13,
315
+ info : 'battery Pack 2 information',
316
+ refresh : dataRefreshRate.low,
317
+ type : deviceType.battery,
318
+ states: [
319
+ {
320
+ state: {id: 'battery.unit.1.batteryPack.2.SOC', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:38271, len:1'},
321
+ register: {reg: 38271, type: dataType.uint16, gain: 10}
322
+ },
323
+ {
324
+ state: {id: 'battery.unit.1.batteryPack.2.totalCharge', name: 'Total Charge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38280, len:2'},
325
+ register: {reg: 38280, type: dataType.uint32, gain: 100}
326
+ },
327
+ {
328
+ state: {id: 'battery.unit.1.batteryPack.2.totalDischarge', name: 'Total Discharge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38282, len:2'},
329
+ register: {reg: 38282, type: dataType.uint32, gain: 100}
330
+ }
331
+ ],
332
+ checkIfActive: (path) => this._batteryExists(path,1,2)
333
+ },
334
+ {
335
+ address : 38313,
336
+ length : 13,
337
+ info : 'battery Pack 3 information',
338
+ refresh : dataRefreshRate.low,
339
+ type : deviceType.battery,
340
+ states: [
341
+ {
342
+ state: {id: 'battery.unit.1.batteryPack.3.SOC', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:38313, len:1'},
343
+ register: {reg: 38313, type: dataType.uint16, gain: 10}
344
+ },
345
+ {
346
+ state: {id: 'battery.unit.1.batteryPack.3.totalCharge', name: 'Total Charge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38322, len:2'},
347
+ register: {reg: 38322, type: dataType.uint32, gain: 100}
348
+ },
349
+ {
350
+ state: {id: 'battery.unit.1.batteryPack.3.totalDischarge', name: 'Total Discharge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38324, len:2'},
351
+ register: {reg: 38324, type: dataType.uint32, gain: 100}
352
+ }
353
+ ],
354
+ checkIfActive: (path) => this._batteryExists(path,1,3)
355
+ },
356
+ {
357
+ address : 38233,
358
+ length : 3,
359
+ info : 'Battery Pack 1 Charge And Discharge Power',
360
+ refresh : dataRefreshRate.high,
361
+ type : deviceType.battery,
362
+ states : [{
363
+ state: {id: 'battery.unit.1.batteryPack.1.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:38233, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
364
+ register: {reg: 38233, type: dataType.int32, gain:1000}
365
+ },
366
+ {
367
+ state: {id: 'battery.unit.1.batteryPack.1.voltage', name: 'Voltage', type: 'number', unit: 'V', role: 'value.voltage', desc: 'reg:38235, len:1'},
368
+ register: {reg: 38235, type: dataType.uint16, gain: 10},
369
+ }],
370
+ checkIfActive: (path) => this._batteryExists(path,1,1)
371
+ },
372
+ {
373
+ address : 38275,
374
+ length : 3,
375
+ info : 'Battery Pack 2 Charge And Discharge Power',
376
+ refresh : dataRefreshRate.high,
377
+ type : deviceType.battery,
378
+ states : [{
379
+ state: {id: 'battery.unit.1.batteryPack.2.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:38275, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
380
+ register: {reg: 38275, type: dataType.int32, gain:1000}
381
+ },
382
+ {
383
+ state: {id: 'battery.unit.1.batteryPack.2.voltage', name: 'Voltage', type: 'number', unit: 'V', role: 'value.voltage', desc: 'reg:38277, len:1'},
384
+ register: {reg: 38277, type: dataType.uint16, gain: 10},
385
+ }],
386
+ checkIfActive: (path) => this._batteryExists(path,1,2)
387
+ },
388
+ {
389
+ address : 38317,
390
+ length : 3,
391
+ info : 'Battery Pack 3Charge And Discharge Power',
392
+ refresh : dataRefreshRate.high,
393
+ type : deviceType.battery,
394
+ states : [{
395
+ state: {id: 'battery.unit.1.batteryPack.3.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:38317, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
396
+ register: {reg: 38317, type: dataType.int32, gain:1000}
397
+ },
398
+ {
399
+ state: {id: 'battery.unit.1.batteryPack.3.voltage', name: 'Voltage', type: 'number', unit: 'V', role: 'value.voltage', desc: 'reg:38319, len:1'},
400
+ register: {reg: 38319, type: dataType.uint16, gain: 10},
401
+ }],
402
+ checkIfActive: (path) => this._batteryExists(path,1,3)
403
+ },
404
+ //++
228
405
  {
229
406
  address : 37000,
230
407
  length : 50,
@@ -241,6 +418,14 @@ class InverterSun2000 extends DriverBase{
241
418
  state: {id: 'battery.unit.1.batterySOC', name: 'battery SOC', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:37004, len:1'},
242
419
  register: {reg: 37004, type: dataType.uint16, gain:10}
243
420
  },
421
+ {
422
+ state: {id: 'battery.unit.1.RatedChargePower', name: 'rated charge power', type: 'number', unit: 'W', role: 'value.power', desc: 'reg:37007, len:2'},
423
+ register: {reg: 37007, type: dataType.uint32}
424
+ },
425
+ {
426
+ state: {id: 'battery.unit.1.RatedDischargePower', name: 'rated discharge power', type: 'number', unit: 'W', role: 'value.power', desc: 'reg:37009, len:2'},
427
+ register: {reg: 37009, type: dataType.uint32}
428
+ },
244
429
  {
245
430
  state: {id: 'battery.unit.1.batteryTemperature', name: 'battery temperature', type: 'number', unit: '°C', role: 'value.temperature', desc: 'reg:37022, len:1'},
246
431
  register: {reg: 37022, type: dataType.uint16, gain:10},
@@ -254,7 +439,8 @@ class InverterSun2000 extends DriverBase{
254
439
  state: { id: 'battery.maximumDischargePower', name: 'MaximumDischargePower', type: 'number', unit: 'W', role: 'value.power', desc: 'reg:37048, len:2'},
255
440
  register: { reg: 37048, type: dataType.uint32}
256
441
  }
257
- ]
442
+ ],
443
+ checkIfActive: (path) => this._batteryExists(path)
258
444
  },
259
445
  { //for NRGKick
260
446
  address : 47000,
@@ -266,7 +452,8 @@ class InverterSun2000 extends DriverBase{
266
452
  state: { id: 'battery.unit.1.productMode', name: 'Product Mode', type: 'number', unit: '', role: 'value', desc: 'reg:47000, len:1'},
267
453
  register: { reg: 47000, type: dataType.uint16}
268
454
  },
269
- ]
455
+ ],
456
+ checkIfActive: (path) => this._batteryExists(path)
270
457
  },
271
458
  {
272
459
  address : 47081,
@@ -299,7 +486,8 @@ class InverterSun2000 extends DriverBase{
299
486
  state: {id: 'battery.gridChargeCutoffSOC', name: 'Grid Charge Cutoff SOC', type: 'number', unit: '%', role: 'value', desc: 'reg:47088, len:1'},
300
487
  register: {reg: 47088, type: dataType.uint16, gain: 10}
301
488
  }
302
- ]
489
+ ],
490
+ checkIfActive: (path) => this._batteryExists(path)
303
491
  },
304
492
  {
305
493
  address : 47101,
@@ -317,10 +505,11 @@ class InverterSun2000 extends DriverBase{
317
505
  register: {reg: 47102, type: dataType.uint16, gain: 10}
318
506
  },
319
507
  {
320
- state: { id: 'battery.productModel', name: 'Product Model', type: 'number', unit: '', role: 'value', desc: 'reg: 47089 , len: 1'},
508
+ state: { id: 'battery.productModel', name: 'Product Model', type: 'number', unit: '', role: 'value', desc: 'reg: 47106 , len: 1'},
321
509
  register: {reg: 47106, type: dataType.uint16}
322
510
  }
323
- ]
511
+ ],
512
+ checkIfActive: (path) => this._batteryExists(path)
324
513
  },
325
514
  {
326
515
  address : 32000,
@@ -671,7 +860,8 @@ class InverterSun2000 extends DriverBase{
671
860
  state: {id: 'battery.currentDayDischargeCapacity', name: 'Current Day Discharge Capacity', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:37786, len:2' },
672
861
  register: { reg: 37786, type: dataType.uint32, gain: 100 }
673
862
  }
674
- ]
863
+ ],
864
+ checkIfActive: (path) => this._batteryExists(path)
675
865
  },
676
866
  {
677
867
  //https://photomate.zendesk.com/hc/en-gb/articles/5701625507485-Export-limitation-for-SUN2000-inverters-via-FusionSolar-App
@@ -726,12 +916,6 @@ class InverterSun2000 extends DriverBase{
726
916
 
727
917
  if (inputYield < 0 || isNaN(inputYield)) inputYield = 0;
728
918
  this.stateCache.set(path+'derived.dailyInputYield', inputYield, {type: 'number'});
729
-
730
- //Battery Indicator
731
- let state = this.stateCache.get(path+'battery.unit.1.SN');
732
- if (state && state?.value !== '') this.deviceInfo.numberBatteryUnits = 1;
733
- state = this.stateCache.get(path+'battery.unit.2.SN');
734
- if (state && state?.value !== '') this.deviceInfo.numberBatteryUnits = 2;
735
919
  }
736
920
  },
737
921
  {
@@ -752,12 +936,33 @@ class InverterSun2000 extends DriverBase{
752
936
  if (value >= from && value <= until) {
753
937
  return value;
754
938
  }
755
- this.log.warn('_checkValidNumber '+value+' from: '+from+' until: '+until);
939
+ this.log.debug('_checkValidNumber '+value+' from: '+from+' until: '+until);
756
940
  return substWith;
757
941
  }
758
942
  return value;
759
943
  }
760
944
 
945
+ //V0.12
946
+ _batteryExists(path,unit=0,pack=0) {
947
+ if (unit === 0) {
948
+ if (!this.adapter.settings.ds.batteryUnits) return false;
949
+ const state1 = this.stateCache.get(path+'battery.unit.1.SN');
950
+ const state2 = this.stateCache.get(path+'battery.unit.2.SN');
951
+ return (state1 && state1.value) || (state2 && state2.value);
952
+ } else {
953
+ if (pack === 0) {
954
+ const state = this.stateCache.get(`${path}battery.unit.${unit}.SN`);
955
+ return this.adapter.settings.ds.batteryUnits && state && state.value;
956
+ //return (state && 'test');
957
+ } else {
958
+ const state = this.stateCache.get(`${path}battery.unit.${unit}.batteryPack.${pack}.SN`);
959
+ return this.adapter.settings.ds.batteryPacks && state && state.value;
960
+ //return state && state.value;
961
+ //return (state && 'test');
962
+ }
963
+ }
964
+ }
965
+
761
966
  //overload
762
967
  get modbusAllowed () {
763
968
  //if the modbus-device offline we cannot read or write anythink!
@@ -831,10 +1036,9 @@ class InverterSun2000_M1 extends InverterSun2000{
831
1036
  }]
832
1037
  },
833
1038
  {
834
-
835
1039
  address : 37700,
836
1040
  length : 10,
837
- info : 'battery unit2 indicator',
1041
+ info : 'battery unit2 (indicator)',
838
1042
  states: [
839
1043
  {
840
1044
  state: { id: 'battery.unit.2.SN', name: 'serial number', type: 'string', unit: '', role: 'value', desc: 'reg:37700, len:10'},
@@ -851,12 +1055,72 @@ class InverterSun2000_M1 extends InverterSun2000{
851
1055
  }
852
1056
  }
853
1057
  },
1058
+ {
1059
+ address : 38326,
1060
+ length : 10,
1061
+ info : 'battery unit2 Pack1 (indicator)',
1062
+ states: [
1063
+ {
1064
+ state: { id: 'battery.unit.2.batteryPack.1.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
1065
+ register: { reg: 38326, type: dataType.string, length: 6},
1066
+ store: storeType.never
1067
+ },
1068
+ ],
1069
+ readErrorHook: (err,reg) => {
1070
+ //modbus Error 2 - illegal address
1071
+ if(err.modbusCode === 2) {
1072
+ reg.lastread = this._newNowTime(); //try it once
1073
+ this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.2.batteryPack.1.SN', '', { stored : true });
1074
+ return true; //error self handle
1075
+ }
1076
+ }
1077
+ },
1078
+ {
1079
+ address : 38368,
1080
+ length : 10,
1081
+ info : 'battery unit2 Pack2 (indicator)',
1082
+ states: [
1083
+ {
1084
+ state: { id: 'battery.unit.2.batteryPack.2.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
1085
+ register: { reg: 38368, type: dataType.string, length: 6},
1086
+ store: storeType.never
1087
+ },
1088
+ ],
1089
+ readErrorHook: (err,reg) => {
1090
+ //modbus Error 2 - illegal address
1091
+ if(err.modbusCode === 2) {
1092
+ reg.lastread = this._newNowTime(); //try it once
1093
+ this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.2.batteryPack.2.SN', '', { stored : true });
1094
+ return true; //error self handle
1095
+ }
1096
+ }
1097
+ },
1098
+ {
1099
+ address : 38410,
1100
+ length : 10,
1101
+ info : 'battery unit1 Pack3 (indicator)',
1102
+ states: [
1103
+ {
1104
+ state: { id: 'battery.unit.1.batteryPack.3.SN', name: 'serial number', type: 'string', unit: '', role: 'value'},
1105
+ register: { reg: 38410, type: dataType.string, length: 6},
1106
+ store: storeType.never
1107
+ },
1108
+ ],
1109
+ readErrorHook: (err,reg) => {
1110
+ //modbus Error 2 - illegal address
1111
+ if(err.modbusCode === 2) {
1112
+ reg.lastread = this._newNowTime(); //try it once
1113
+ this.stateCache.set(this._getStatePath(reg.type)+'battery.unit.1.batteryPack.3.SN', '', { stored : true });
1114
+ return true; //error self handle
1115
+ }
1116
+ }
1117
+ },
854
1118
  {
855
1119
  address : 37738,
856
1120
  length : 15,
857
1121
  info : 'battery unit2 information',
858
1122
  refresh : dataRefreshRate.low,
859
- type : deviceType.batteryUnit2,
1123
+ type : deviceType.battery,
860
1124
  states: [
861
1125
  {
862
1126
  state: {id: 'battery.unit.2.batterySOC', name: 'battery SOC', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:37738, len:1'},
@@ -872,20 +1136,138 @@ class InverterSun2000_M1 extends InverterSun2000{
872
1136
  register: {reg: 37752, type: dataType.uint16, gain:10},
873
1137
  mapper: value => Promise.resolve(this._checkValidNumber(value,-100,100))
874
1138
  }
875
- ]
1139
+ ],
1140
+ checkIfActive: (path) => this._batteryExists(path,2)
876
1141
  },
877
1142
  { //for NRGKick
878
1143
  address : 47089,
879
1144
  length : 1,
880
1145
  info : 'battery unit2 (static)',
881
- type : deviceType.batteryUnit2,
1146
+ type : deviceType.battery,
882
1147
  states: [
883
1148
  {
884
1149
  state: { id: 'battery.unit.2.productMode', name: 'Product Mode', type: 'number', unit: '', role: 'value', desc: 'reg:37089, len:1'},
885
1150
  register: { reg: 47089, type: dataType.uint16}
886
1151
  },
887
- ]
1152
+ ],
1153
+ checkIfActive: (path) => this._batteryExists(path,2)
1154
+ },
1155
+ //--V0.12
1156
+ {
1157
+ address : 38355,
1158
+ length : 13,
1159
+ info : 'battery Pack 1 information',
1160
+ refresh : dataRefreshRate.low,
1161
+ type : deviceType.battery,
1162
+ states: [
1163
+ {
1164
+ state: {id: 'battery.unit.2.batteryPack.1.SOC', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:38355, len:1'},
1165
+ register: {reg: 38355, type: dataType.uint16, gain: 10}
1166
+ },
1167
+ {
1168
+ state: {id: 'battery.unit.2.batteryPack.1.totalCharge', name: 'Total Charge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38364, len:2'},
1169
+ register: {reg: 38364, type: dataType.uint32, gain: 100}
1170
+ },
1171
+ {
1172
+ state: {id: 'battery.unit.2.batteryPack.1.totalDischarge', name: 'Total Discharge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38366, len:2'},
1173
+ register: {reg: 38366, type: dataType.uint32, gain: 100}
1174
+ }
1175
+ ],
1176
+ checkIfActive: (path) => this._batteryExists(path,2,1)
1177
+ },
1178
+ {
1179
+ address : 38397,
1180
+ length : 13,
1181
+ info : 'battery Pack 2 information',
1182
+ refresh : dataRefreshRate.low,
1183
+ type : deviceType.battery,
1184
+ states: [
1185
+ {
1186
+ state: {id: 'battery.unit.2.batteryPack.2.SOC', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:38397, len:1'},
1187
+ register: {reg: 38397, type: dataType.uint16, gain: 10}
1188
+ },
1189
+ {
1190
+ state: {id: 'battery.unit.2.batteryPack.2.totalCharge', name: 'Total Charge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38406, len:2'},
1191
+ register: {reg: 38406, type: dataType.uint32, gain: 100}
1192
+ },
1193
+ {
1194
+ state: {id: 'battery.unit.2.batteryPack.2.totalDischarge', name: 'Total Discharge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38408, len:2'},
1195
+ register: {reg: 38408, type: dataType.uint32, gain: 100}
1196
+ }
1197
+ ],
1198
+ checkIfActive: (path) => this._batteryExists(path,2,2)
1199
+ },
1200
+ {
1201
+ address : 38439,
1202
+ length : 13,
1203
+ info : 'battery Pack 3 information',
1204
+ refresh : dataRefreshRate.low,
1205
+ type : deviceType.battery,
1206
+ states: [
1207
+ {
1208
+ state: {id: 'battery.unit.2.batteryPack.3.SOC', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'reg:38439, len:1'},
1209
+ register: {reg: 38439, type: dataType.uint16, gain: 10}
1210
+ },
1211
+ {
1212
+ state: {id: 'battery.unit.2.batteryPack.3.totalCharge', name: 'Total Charge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38448, len:2'},
1213
+ register: {reg: 38448, type: dataType.uint32, gain: 100}
1214
+ },
1215
+ {
1216
+ state: {id: 'battery.unit.2.batteryPack.3.totalDischarge', name: 'Total Discharge', type: 'number', unit: 'kWh', role: 'value.power.consumption', desc: 'reg:38450, len:2'},
1217
+ register: {reg: 38450, type: dataType.uint32, gain: 100}
1218
+ }
1219
+ ],
1220
+ checkIfActive: (path) => this._batteryExists(path,2,3)
1221
+ },
1222
+ {
1223
+ address : 38359,
1224
+ length : 3,
1225
+ info : 'Battery Pack 1 Charge And Discharge Power',
1226
+ refresh : dataRefreshRate.high,
1227
+ type : deviceType.battery,
1228
+ states : [{
1229
+ state: {id: 'battery.unit.2.batteryPack.1.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:38359, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
1230
+ register: {reg: 38359, type: dataType.int32, gain:1000}
1231
+ },
1232
+ {
1233
+ state: {id: 'battery.unit.2.batteryPack.1.voltage', name: 'Voltage', type: 'number', unit: 'V', role: 'value.voltage', desc: 'reg:38361, len:1'},
1234
+ register: {reg: 38361, type: dataType.uint16, gain: 10},
1235
+ }],
1236
+ checkIfActive: (path) => this._batteryExists(path,2,1)
1237
+ },
1238
+ {
1239
+ address : 38401,
1240
+ length : 3,
1241
+ info : 'Battery Pack 2 Charge And Discharge Power',
1242
+ refresh : dataRefreshRate.high,
1243
+ type : deviceType.battery,
1244
+ states : [{
1245
+ state: {id: 'battery.unit.2.batteryPack.2.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:38401, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
1246
+ register: {reg: 38401, type: dataType.int32, gain:1000}
1247
+ },
1248
+ {
1249
+ state: {id: 'battery.unit.2.batteryPack.2.voltage', name: 'Voltage', type: 'number', unit: 'V', role: 'value.voltage', desc: 'reg:38403, len:1'},
1250
+ register: {reg: 38403, type: dataType.uint16, gain: 10},
1251
+ }],
1252
+ checkIfActive: (path) => this._batteryExists(path,2,2)
1253
+ },
1254
+ {
1255
+ address : 38443,
1256
+ length : 3,
1257
+ info : 'Battery Pack 3 Charge And Discharge Power',
1258
+ refresh : dataRefreshRate.high,
1259
+ type : deviceType.battery,
1260
+ states : [{
1261
+ state: {id: 'battery.unit.2.batteryPack.3.chargeDischargePower', name: 'Charge/Discharge power', desc: 'reg:38443, len:2 (>0 charging, <0 discharging)', type: 'number', unit: 'kW', role: 'value.power'},
1262
+ register: {reg: 38443, type: dataType.int32, gain:1000}
1263
+ },
1264
+ {
1265
+ state: {id: 'battery.unit.2.batteryPack.3.voltage', name: 'Voltage', type: 'number', unit: 'V', role: 'value.voltage', desc: 'reg:38445, len:1'},
1266
+ register: {reg: 38445, type: dataType.uint16, gain: 10},
1267
+ }],
1268
+ checkIfActive: (path) => this._batteryExists(path,2,3)
888
1269
  }
1270
+ //++
889
1271
  ];
890
1272
  this.registerFields.push.apply(this.registerFields,newFields);
891
1273
  }
package/lib/register.js CHANGED
@@ -218,8 +218,15 @@ class Registers {
218
218
  for (const [i, reg] of device.instance.registerFields.entries()) {
219
219
  if (!device.instance.modbusAllowed) continue; //standby
220
220
  if (reg.type == deviceType.meter && !device?.meter) continue; //not meter
221
+ /*
221
222
  if (reg.type == deviceType.battery && device?.numberBatteryUnits == 0) continue; //battery
222
223
  if (reg.type == deviceType.batteryUnit2 && device?.numberBatteryUnits < 2) continue; //battery Unit2
224
+
225
+ if (reg.type == deviceType.battery && device?.battery.unit1.exist === false && device?.battery.unit2.exist === false) continue; //battery exist
226
+ if (reg.type == deviceType.batteryUnit2 && device?.battery.unit2.exist === false) continue; //battery Unit2
227
+ */
228
+ if (reg.checkIfActive && !reg.checkIfActive(device.instance._getStatePath(reg.type))) continue; //NEW, PATH
229
+
223
230
  if (reg.type == deviceType.gridPowerControl && !device?.meter) continue; //power control v0.8.x
224
231
  if (reg.states && reg.refresh) {
225
232
  const lastread = reg.lastread;
package/lib/tools.js CHANGED
@@ -27,6 +27,11 @@ class Logging {
27
27
  else this.adapter.log.info(msg);
28
28
  }
29
29
 
30
+ silly(msg) {
31
+ if (this._quiet) this.debug('Warn: '+msg);
32
+ else this.adapter.log.silly(msg);
33
+ }
34
+
30
35
  warn(msg) {
31
36
  if (this._quiet) this.debug('Warn: '+msg);
32
37
  else this.adapter.log.warn(msg);
package/lib/types.js CHANGED
@@ -61,14 +61,8 @@ const dataRefreshRate = {
61
61
  medium: 'medium',
62
62
  high : 'high',
63
63
  compare (refresh,fieldRefresh) {
64
- //v0.4.0
65
64
  if (refresh === this.high) return (fieldRefresh === this.high);
66
65
  else return (fieldRefresh !== this.high);
67
- /*
68
- if (refresh !== this.high && fieldRefresh === undefined) return true;
69
- if (fieldRefresh === this.medium && refresh === this.low) return true;
70
- return (fieldRefresh === refresh );
71
- */
72
66
  }
73
67
  };
74
68
 
@@ -76,7 +70,6 @@ const deviceType = {
76
70
  inverter : 'inverter', //default
77
71
  meter : 'meter',
78
72
  battery : 'battery',
79
- batteryUnit2 : 'batteryUnit2',
80
73
  gridPowerControl : 'gridPowerControl' //v8.0.x
81
74
  };
82
75
 
package/main.js CHANGED
@@ -59,6 +59,10 @@ class Sun2000 extends utils.Adapter {
59
59
  },
60
60
  cb: {
61
61
  tou : false
62
+ },
63
+ ds: {
64
+ batteryUnits : true,
65
+ batterPacks : false
62
66
  }
63
67
  };
64
68
 
@@ -339,6 +343,10 @@ class Sun2000 extends utils.Adapter {
339
343
  this.settings.sl.meterId = this.config.sl_meterId;
340
344
  //battery charge control
341
345
  this.settings.cb.tou = this.config.cb_tou;
346
+ //data scope
347
+ this.settings.ds.batteryUnits = this.config.ds_bu;
348
+ this.settings.ds.batteryPacks = this.config.ds_bp;
349
+
342
350
 
343
351
  if (this.settings.modbusAdjust) {
344
352
  await this.setState('info.JSONhealth', {val: '{message: "Adjust modbus settings"}', ack: true});
@@ -354,8 +362,7 @@ class Sun2000 extends utils.Adapter {
354
362
  duration: 5000,
355
363
  modbusId: id,
356
364
  driverClass: driverClasses.inverter,
357
- meter: (i==0 && !this.settings.sl.active),
358
- numberBatteryUnits : 0
365
+ meter: (i==0 && !this.settings.sl.active)
359
366
  });
360
367
  }
361
368
  //SmartLogger
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.sun2000",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "sun2000",
5
5
  "author": {
6
6
  "name": "bolliy",
@@ -10,9 +10,14 @@
10
10
  "license": "MIT",
11
11
  "keywords": [
12
12
  "ioBroker",
13
- "template",
14
13
  "Smart Home",
15
- "home automation"
14
+ "home automation",
15
+ "inverter",
16
+ "sun2000",
17
+ "modbus",
18
+ "modbus-proxy",
19
+ "smartlogger",
20
+ "huawei"
16
21
  ],
17
22
  "repository": {
18
23
  "type": "git",
@@ -28,24 +33,24 @@
28
33
  "tcp-port-used": "^1.0.2"
29
34
  },
30
35
  "devDependencies": {
31
- "@alcalzone/release-script": "^3.7.0",
36
+ "@alcalzone/release-script": "^3.8.0",
32
37
  "@alcalzone/release-script-plugin-iobroker": "^3.7.2",
33
38
  "@alcalzone/release-script-plugin-license": "^3.7.0",
34
39
  "@alcalzone/release-script-plugin-manual-review": "^3.7.0",
35
40
  "@iobroker/adapter-dev": "^1.3.0",
36
41
  "@iobroker/testing": "^4.1.3",
37
42
  "@tsconfig/node16": "^16.1.3",
38
- "@types/chai": "^4.3.16",
43
+ "@types/chai": "^4.3.19",
39
44
  "@types/chai-as-promised": "^7.1.8",
40
45
  "@types/mocha": "^10.0.7",
41
- "@types/node": "^20.14.9",
46
+ "@types/node": "^22.5.5",
42
47
  "@types/proxyquire": "^1.3.31",
43
48
  "@types/sinon": "^17.0.3",
44
49
  "@types/sinon-chai": "^3.2.12",
45
- "chai": "^4.4.1",
50
+ "chai": "^4.5.0",
46
51
  "chai-as-promised": "^7.1.2",
47
52
  "eslint": "^8.57.0",
48
- "mocha": "^10.5.2",
53
+ "mocha": "^10.7.3",
49
54
  "proxyquire": "^2.1.3",
50
55
  "sinon": "^18.0.0",
51
56
  "sinon-chai": "^3.7.0",