iobroker.sun2000 2.3.1 → 2.3.3

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
@@ -65,6 +65,14 @@ 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.3 (2025-10-31)
69
+ * Improved verification of the adapter configuration
70
+ * new state `inverter.x.derived.dailyActiveEnergy` Inverter daily active energy, which is determined via the Riemann sum of `inverter.x.activePower`
71
+ * state `collected.dailyInputYield` was redisigned based on inverter.[0..n-1].derived.dailyActiveEnergy
72
+
73
+ ### 2.3.2 (2025-10-24)
74
+ * allows again `control.battery.chargeFromGridFunction` when using the Emma
75
+
68
76
  ### 2.3.1 (2025-10-21)
69
77
  * fix: handle potential null values in set method of RegisterMap
70
78
 
@@ -75,7 +83,7 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
75
83
  * inverter control: add same state for startup and shutdown an inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)
76
84
  * fix: Device status name has been corrected [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)
77
85
  * add undocumented device status `Shutdown: End of the ESS discharge process`
78
- * emma 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)
86
+ * emma 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)
79
87
  * if an Emma is installed, some control states of the inverter are deactivated (read only). Mainly for the grid settings.
80
88
  * deprecated control states have been removed.
81
89
  * a workaround for issue [#582](https://github.com/yaacov/node-modbus-serial/issues/582) of node-modbus-serial has been implemented.
@@ -263,8 +263,20 @@
263
263
  },
264
264
  "chipsTxt1": {
265
265
  "type": "staticText",
266
- "text": "This control is set in the opject path `sun2000.0.inverter.x.control.battery`",
266
+ "text": "This control states are set in the object path `sun2000.0.inverter.x.control.battery`",
267
+ "newLine": true,
268
+ "hidden": "data.integration === 2",
269
+ "xs": 12,
270
+ "sm": 12,
271
+ "md": 6,
272
+ "lg": 4,
273
+ "xl": 4
274
+ },
275
+ "chipsTxt1_1": {
276
+ "type": "staticText",
277
+ "text": "This control states are set in the object path `sun2000.0.emma.control.battery`",
267
278
  "newLine": true,
279
+ "hidden": "data.integration !== 2",
268
280
  "xs": 12,
269
281
  "sm": 12,
270
282
  "md": 6,
@@ -275,7 +287,7 @@
275
287
  "type": "checkbox",
276
288
  "label": "Create default TOU setting",
277
289
  "newLine": true,
278
- "help": "The `default TOU settings` is interesting for the `force battery charging from the grid` function, which is required for variable energy prices.",
290
+ "help": "The `default TOU settings` is interesting for the `charge from the grid` function, which is required for variable energy prices.",
279
291
  "xs": 12,
280
292
  "sm": 12,
281
293
  "md": 6,
@@ -287,6 +299,7 @@
287
299
  "text": "Description with examples",
288
300
  "href": "https://github.com/bolliy/ioBroker.sun2000/wiki/Battery-control",
289
301
  "button": true,
302
+ "hidden": "data.integration === 2",
290
303
  "icon": "info",
291
304
  "newLine": true,
292
305
  "xs": 12,
@@ -295,6 +308,20 @@
295
308
  "lg": 3,
296
309
  "xl": 3
297
310
  },
311
+ "staticLink1_1": {
312
+ "type": "staticLink",
313
+ "text": "Description with examples",
314
+ "href": "https://github.com/bolliy/ioBroker.sun2000/wiki/Emma:-Battery-control",
315
+ "button": true,
316
+ "hidden": "data.integration !== 2",
317
+ "icon": "info",
318
+ "newLine": true,
319
+ "xs": 12,
320
+ "sm": 12,
321
+ "md": 6,
322
+ "lg": 3,
323
+ "xl": 3
324
+ },
298
325
  "mainHdr2": {
299
326
  "newLine": true,
300
327
  "type": "header",
@@ -328,12 +355,14 @@
328
355
  "newLine": true,
329
356
  "type": "header",
330
357
  "text": "Export control",
358
+ "hidden": "data.integration === 2",
331
359
  "size": 2
332
360
  },
333
361
  "chipsTxt3": {
334
362
  "type": "staticText",
335
363
  "text": "This control is set in the opject path `sun2000.0.inverter.0.control.grid`",
336
364
  "newLine": true,
365
+ "hidden": "data.integration === 2",
337
366
  "xs": 12,
338
367
  "sm": 12,
339
368
  "md": 6,
@@ -344,6 +373,7 @@
344
373
  "type": "staticLink",
345
374
  "text": "Description with examples",
346
375
  "href": "https://github.com/bolliy/ioBroker.sun2000/wiki/Begrenzung-Netzeinspeisung-(Export-Control)",
376
+ "hidden": "data.integration === 2",
347
377
  "button": true,
348
378
  "icon": "info",
349
379
  "newLine": true,
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sun2000",
4
- "version": "2.3.1",
4
+ "version": "2.3.3",
5
5
  "news": {
6
+ "2.3.3": {
7
+ "en": "Improved verification of the adapter configuration\nnew state `inverter.x.derived.dailyActiveEnergy` Inverter daily active energy, which is determined via the Riemann sum of `inverter.x.activePower`\nstate `collected.dailyInputYield` was redisigned based on inverter.[0..n-1].derived.dailyActiveEnergy",
8
+ "de": "Verbesserte Überprüfung der Adapterkonfiguration\n`inverter.x.derived.dailyActiveEnergy` Inverter tägliche aktive Energie, die über die Riemann Summe von `inverter.x.activePower bestimmt wird `\nstate `collected.dailyInputYield` wurde basierend auf Inverter zurückgeteilt. [0.n-1].derived.dailyActiveEnergy",
9
+ "ru": "Улучшенная проверка конфигурации адаптера\nновое состояние «inverter.x.derived.dailyActiveEnergy» Инверторная ежедневная активная энергия, которая определяется через сумму Римана 'inverter.x.activePower пункт\nstate 'collected.dailyInputYield' была переопределена на основе инвертора. [0..n-1].derived.dailyActiveEnergy",
10
+ "pt": "Verificação melhorada da configuração do adaptador\nnovo estado «inverter.x.derived.dailyActiveEnergy» Energia ativa diária do inversor, que é determinada através da soma Riemann de `inverter.x.activePower `\nestado `colleted.dailyInputYield` foi reassinado com base no inversor. [0..n-1].derivado.diárioAtividadeEnergia",
11
+ "nl": "Verbeterde verificatie van de configuratie van de adapter\nnieuwe staat Inverter dagelijkse actieve energie, die wordt bepaald via de Riemann som van Wat\nstaat [0..n-1].afgeleid.dailyActiveEnergy",
12
+ "fr": "Amélioration de la vérification de la configuration de l'adaptateur\nnouvel état `inverter.x.derived.dailyActiveEnergy` Inverter l'énergie active quotidienne, qui est déterminée par la somme Riemann de `inverter.x.activePower \"\nl'état `collected.dailyInputYield` a été résigné sur la base de l'onduleur. Énergie active",
13
+ "it": "Verifica migliorata della configurazione dell'adattatore\nnuovo stato `inverter.x.derived.dailyActiveEnergy` Inverter energia attiva quotidiana, che è determinata tramite la somma Riemann di `inverter.x.activePower #\nstato `collect.dailyInputYield` è stato ridisegnato sulla base di inverter. [0.n-1]",
14
+ "es": "Mejor verificación de la configuración del adaptador\nnuevo estado `inverter.x.derived.dailyActiveEnergy` Inverter energía activa diaria, que se determina a través de la suma Riemann de `inverter.x.activePower `\nestado `colected.dailyInputYield` fue redisigned basado en inverter. [0.n-1].derived.dailyActiveEnergy",
15
+ "pl": "Ulepszona weryfikacja konfiguracji adaptera\nnowy stan 'inverter.x.derived.dailyActiveEnergy' Inwerter dzienna aktywna energia, która jest określana za pomocą sumy Riemann 'inverter.x.activePower'\nstan 'collected.dailyInputYield' został wycofany na podstawie inwertera. [0.. n-1] .derived.dailyActiveEnergy",
16
+ "uk": "Покращена перевірка конфігурації адаптера\nновий стан `inverter.x.derived.dailyActiveEnergy` Інверторна щоденна активна енергія, яка визначається за рахунок `inverter.x.activePower й\n`collected.dailyInputYield` був перерахований на основі інвертора. [0..n-1].derived.dailyActiveEnergy",
17
+ "zh-cn": "改进适配器配置的核查\n新州`反转器.x.衍生的每日能源 ' 每日反转活性能量,通过`反转器.x.activePower的Riemann总和确定 `\ndaily InputYield)根据反差重新签名。 [0.n-1]. 衍生的每日能源"
18
+ },
19
+ "2.3.2": {
20
+ "en": "allows again `control.battery.chargeFromGridFunction` when using the Emma",
21
+ "de": "erlaubt wieder `control.battery.chargeFromGridFunction` bei Verwendung der Emma",
22
+ "ru": "позволяет снова «control.battery.chargeFromGridFunction» при использовании Emma",
23
+ "pt": "permite novamente `control.battery.chargeFromGridFunction` ao usar a Emma",
24
+ "nl": "maakt het mogelijk opnieuw te controleren.battery.chargeFromGridFunction",
25
+ "fr": "permet de nouveau `control.battery.chargeFromGridFunction` lors de l'utilisation de l'Emma",
26
+ "it": "permette di nuovo `control.battery.chargeFromGridFunction` quando si utilizza Emma",
27
+ "es": "permite de nuevo 'control.battery.chargeDesdeGridFunction' al utilizar Emma",
28
+ "pl": "pozwala ponownie 'control.battery.chargeFromGridFunction' podczas korzystania z Emmy",
29
+ "uk": "дозволяє знову `control.battery.chargeЗ альбомуGridFunction` при використанні Емма",
30
+ "zh-cn": "允许在使用 Emma 时再次使用 \" control.battery. charge from GridFunction \" "
31
+ },
6
32
  "2.3.1": {
7
33
  "en": "fix: handle potential null values in set method of RegisterMap",
8
34
  "de": "fix: griff potenzielle Nullwerte in der eingestellten Methode des Registrierens Landkarte",
@@ -67,32 +93,6 @@
67
93
  "pl": "aktualizacje zależności i konfiguracji\nfix: dostosować wartości graniczne dla zdarzeń w oparciu o wartość użytkową Parametry nadwyżki\nfix: wartości rejestru swap dla zużycia energii w sterowniku Emma # 190\nemma: ulepszenie obliczania mocy przy zastosowaniu wykładniczej średniej ruchomej w EmmaCharger\naktualizacja definicji nadwyżek energii elektrycznej i deprecjacja starych identyfikatorów",
68
94
  "uk": "оновлення залежності та конфігурації\nвиправити: регулювати ліміти значення події на основі Параметри Surplus\nвиправити: значення swap для споживання енергії в машині Емма #190\nемма: поліпшення розрахунку потужності з постійним рухомим середнім в ЕммаКхаргер\nоновлення надлишок визначення стану живлення та депресувати старі ідентифікатори",
69
95
  "zh-cn": "依赖和配置更新\n固定:根据可用值调整事件值限制 盈余参数\n修补: Emma 驱动器中用电量的交换记录值 # 190\nemma: 改进电量计算, 以 Emmacourer 中的指数移动平均值\n更新剩余电源状态定义并折旧旧标识符"
70
- },
71
- "2.1.0": {
72
- "en": "emma: system time is being determined [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\ncontrol: add grid power scheduling functionality to inverter driver [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
73
- "de": "emma: Die Systemzeit wird bestimmt [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\nsteuerung: Netz-Leistungs-Scheduling-Funktionalität zum Wechselrichtertreiber hinzufügen [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
74
- "ru": "emma: системное время определяется [#179] (https://github.com/bolliy/ioBroker.sun2000/issues/179)\nуправление: добавьте функцию планирования мощности сети к драйверу инвертора [#176] (https://github.com/bolliy/ioBroker.sun2000/issues/176)",
75
- "pt": "emma: tempo do sistema está sendo determinado [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\ncontrol: add grid power screaming functionality to inverter driver [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
76
- "nl": "emma: de systeemtijd wordt bepaald [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\ncontrole: voeg net stroom planning functionaliteit aan omvormer driver [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
77
- "fr": "emma: le temps du système est déterminé [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\ncontrôle: ajouter la fonctionnalité de programmation du réseau au pilote d'onduleur [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
78
- "it": "emma: il tempo di sistema viene determinato [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\ncontrollo: aggiungere funzionalità di programmazione della griglia al driver inverter [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
79
- "es": "emma: El tiempo del sistema se determina [#179](https://github.com/bolliy/ioBroker.sun2000/issues/179)\ncontrol: añadir funcionalidad de programación de energía de red al controlador inverter [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
80
- "pl": "emma: ustala się czas systemowy [# 179] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 179)\ncontrol: add grid Power Scheduling Functional to inverter driver [# 176] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 176)",
81
- "uk": "emma: час системи визначається [#179](https://github.com/bolliy/ioBroker.sun2000/products/179)\ncontrol: add power scheduling features to inverter драйвер [#176](https://github.com/bolliy/ioBroker.sun2000/issues/176)",
82
- "zh-cn": "emma:系统时间正在确定 [# 179] (https://github.com/bolliy/ioBroker.sun2000/issues/179)\n控制:向反向驱动器添加电网电源调度功能[#176](https://github.com/bolliy/ioBroker.sun2000/issues/1976)"
83
- },
84
- "2.0.0": {
85
- "en": "add support for chargers via Emma and save the data in the charger path #171\nEstablish data consistency between meter.activePower and the power of the meter phases #174\nallows `control.battery.chargeFromGridFunction` when using the Emma\nbreaking change: \nthe value `sun2000.x.inverter.x.battery.runningStatus` is saved as a number. The translated value (such as STANDBY, RUNNING etc.) is stored in the path sun2000.x.inverter.x.battery.derived",
86
- "de": "unterstützung für Ladegeräte über Emma hinzufügen und die Daten im Ladepfad #171 speichern\nDatenkonsistenz zwischen meter.activePower und der Leistung der Zählerphasen #174 einstellen\nerlaubt `control.battery.chargeFromGridFunction` bei Verwendung der Emma\nänderung:\nder Wert `sun2000.x.inverter.x.battery.runningStatus` wird als Nummer gespeichert. Der übersetzte Wert (wie STANDBY, RUNNING etc.) wird im Pfad sun2000.x.inverter.x.battery.derived gespeichert",
87
- "ru": "добавьте поддержку зарядных устройств через Emma и сохраните данные в пути зарядного устройства #171\nУстановить согласованность данных между meter.activePower и мощностью фаз счетчика #174\nпозволяет «control.battery.chargeFromGridFunction» при использовании Emma\nпреодоление изменений:\nзначение 'sun2000.x.inverter.x.battery.runningStatus' сохраняется в виде числа. Переведенное значение (например, STANDBY, RUNNING и т.д.) сохраняется в пути sun2000.x.inverter.x.battery.derived",
88
- "pt": "adicionar suporte para carregadores via Emma e salvar os dados no caminho do carregador #171\nEstabelecer a consistência dos dados entre a potência do medidor e a potência das fases do medidor #174\npermite `control.battery.chargeFromGridFunction` ao usar a Emma\nalteração de quebra:\no valor `sun2000.x.inverter.x.battery.runningStatus` é salvo como um número. O valor traduzido (como STADBY, RUNNING etc.) é armazenado no caminho sun2000.x.inverter.x.battery.derived",
89
- "nl": "ondersteuning voor opladers toevoegen via Emma en de gegevens opslaan in het opladerpad #171\nVaststelling van gegevens consistentie tussen meter.activePower en het vermogen van de meter fasen #174\nstaat control.battery.chargeFromGridFunction\nbreek verandering:\nde waarde De vertaalde waarde (zoals STANDBY, RUNNING etc.) wordt opgeslagen in het pad sun2000.x.inverter.x.battery. afgeleide",
90
- "fr": "ajouter le support pour les chargeurs via Emma et enregistrer les données dans le chemin de chargeur #171\nÉtablir la cohérence des données entre le compteur.activePower et la puissance des phases du compteur #174\npermet `control.battery.chargeFromGridFunction` lors de l'utilisation de l'Emma\nrupture du changement:\nla valeur `sun2000.x.inverter.x.battery.runningStatus` est enregistrée en nombre. La valeur traduite (comme STANDBY, RUNNING, etc.) est stockée dans le chemin sun2000.x.inverter.x.battery.derived",
91
- "it": "aggiungere supporto per i caricatori tramite Emma e salvare i dati nel percorso del caricabatterie #171\nStabilire la consistenza dei dati tra metro.activePower e la potenza delle fasi metro #174\npermette `control.battery.chargeFromGridFunction` quando si utilizza Emma\ncambiamento di rottura:\nil valore `sun2000.x.inverter.x.battery.runningStatus` viene salvato come numero. Il valore tradotto (come STANDBY, RUNNING ecc.) è memorizzato nel percorso sun2000.x.inverter.x.battery.derived",
92
- "es": "añadir soporte para los cargadores a través de Emma y guardar los datos en la ruta del cargador #171\nEstablecer la coherencia de los datos entre el medidor.activePower y la potencia de las fases del medidor #174\npermite 'control.battery.chargeDesdeGridFunction' al usar Emma\ncambio de ruptura:\nel valor `sun2000.x.inverter.x.battery.runningStatus` se guarda como un número. El valor traducido (como STANDBY, RUNNING etc.) se almacena en el camino sun2000.x.inverter.x.battery.derived",
93
- "pl": "dodaj obsługę ładowarek przez Emmę i zapisz dane w ścieżce ładowarki # 171\nUstanowienie spójności danych między miernikiem. ActivePower i mocą faz miernika # 174\npozwala 'control.battery.chargeFromGridFunction' przy użyciu Emmy\nzmiana\nwartość 'sun2000.x.inverter.x.battery.runningStatus' jest zapisywana jako liczba. Wartość przetłumaczona (taka jak STANDBY, RUNNING itp.) jest przechowywana w ścieżce Sun2000.x.inverter.x.battery.deriver",
94
- "uk": "додати підтримку зарядних пристроїв через Емма і зберегти дані в шляху зарядного пристрою #171\nВстановити консистенцію даних між лічильником.activePower і потужністю метрових фаз #174\nдозволяє `control.battery.chargeЗ альбомуGridFunction` при використанні Емма\nзміна розриву:\nзначення `sun2000.x.inverter.x.battery.runningStatus` зберігається як номер. Перекладено значення (наприклад, STANDBY, RUNNING тощо) зберігається в шляху сонце2000.x.inverter.x.battery.derived",
95
- "zh-cn": "通过 Emma 添加对充电器的支持, 并保存充电器路径 # 171 中的数据\n在 meter.activePower和meter阶段的功率之间建立数据一致性 #174\n在使用 Emma 时允许“ control. battery. force from GridFunction ”\n断开更改 :\n将“sun2000.x.inverter.x.battery.running Status”作为数字保存。 翻译值( 如 STANDBY, RUNNING 等) 存储在路径 sun2000.x.inverter.x.battery. 衍生"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -55,8 +55,10 @@ class ServiceQueueMap {
55
55
  },
56
56
  {
57
57
  state: { id: 'battery.chargeFromGridFunction', name: 'Charge from grid', type: 'boolean', role: 'switch.enable', desc: 'reg: 47087, len: 1' },
58
- type: deviceType.battery,
59
- deactiveIfEmmaAvailable: true,
58
+ //type: deviceType.gridPowerControl,
59
+ //deactiveIfEmmaAvailable: true,
60
+ //It is currently unknown whether the ChargeFromGrid(AC) does not work when using the Emma.
61
+ type: deviceType.inverter, //
60
62
  fn: async event => {
61
63
  const ret = await this._writeRegisters(47087, event.value === true ? [1] : [0]);
62
64
  if (ret) {
@@ -570,7 +570,7 @@ class Emma extends DriverBase {
570
570
  this.log.debug('### PostHook for Emma - identify Subdevices charger');
571
571
  this.identifySubdevices('charger', this.modbusId)
572
572
  .then(ret => {
573
- this.log.debug(`### PostHook for Emma - ret: ${JSON.stringify(ret)}`);
573
+ this.log.debug(`### PostHook identification for Emmachargers - ret: ${JSON.stringify(ret)}`);
574
574
  for (const [i, charger] of ret.entries()) {
575
575
  const device = {
576
576
  index: i,
@@ -587,9 +587,9 @@ class Emma extends DriverBase {
587
587
  });
588
588
  this.identifySubdevices('sun2000', this.modbusId)
589
589
  .then(ret => {
590
- this.log.debug(`### PostHook for InverterSun2000 - ret: ${JSON.stringify(ret)}`);
591
- for (const [i, inverter] of ret.entries()) {
592
- this.log.info(`inverter ${i} sun2000 found - modbus id: ${inverter.slave_id}`);
590
+ this.log.debug(`### PostHook indentification for Inverter Sun2000 - ret: ${JSON.stringify(ret)}`);
591
+ for (const [, inverter] of ret.entries()) {
592
+ this.log.info(`${this._name} identify subdevice an inverter sun2000: OID=${inverter.obj_id}, modbus id: ${inverter.slave_id}`);
593
593
  }
594
594
  })
595
595
  .catch(err => {
@@ -100,6 +100,14 @@ class InverterSun2000 extends DriverBase {
100
100
  }
101
101
  });
102
102
 
103
+ //
104
+ this.activePowerSum = new RiemannSum();
105
+ this.adapter.getState(`${this.deviceInfo.path}.derived.dailyActiveEnergy`, (err, state) => {
106
+ if (!err && state) {
107
+ this.activePowerSum.setStart(state.val, state.ts);
108
+ }
109
+ });
110
+
103
111
  this.control = new ServiceQueueMap(this.adapter, this.deviceInfo);
104
112
 
105
113
  //https://github.com/ioBroker/ioBroker.docs/blob/master/docs/en/dev/stateroles.md
@@ -149,15 +157,16 @@ class InverterSun2000 extends DriverBase {
149
157
  postHook: () => {
150
158
  if (!this._testMode) return;
151
159
 
152
- this.log.debug('### PostHook for InverterSun2000');
160
+ this.log.debug('### TEST MODE - PostHook for InverterSun2000 ####');
153
161
  this.identifySubdevices('sun2000', this.modbusId)
154
162
  .then(ret => {
155
163
  this.log.debug(`### PostHook for InverterSun2000 - ret: ${JSON.stringify(ret)}`);
156
- for (const [i, charger] of ret.entries()) {
164
+ for (const [i, inverter] of ret.entries()) {
165
+ this.log.info(`${this._name} identifies an inverter sun2000: OID=${inverter.obj_id}, modbus id: ${inverter.slave_id}`);
157
166
  const device = {
158
167
  index: i,
159
168
  duration: 0,
160
- modbusId: charger.slave_id,
169
+ modbusId: inverter.slave_id,
161
170
  driverClass: driverClasses.emmaCharger,
162
171
  };
163
172
  this.adapter.devices.push(device);
@@ -189,6 +198,11 @@ class InverterSun2000 extends DriverBase {
189
198
  store: storeType.always,
190
199
  },
191
200
  ],
201
+ postHook: path => {
202
+ //calculate daily active energy
203
+ const activePower = this.stateCache.get(`${path}activePower`)?.value ?? 0;
204
+ this.activePowerSum.add(activePower); //riemann Sum
205
+ },
192
206
  },
193
207
  {
194
208
  address: 37765,
@@ -1488,14 +1502,7 @@ class InverterSun2000 extends DriverBase {
1488
1502
  const activePower = this.stateCache.get(`${path}activePower`)?.value ?? 0;
1489
1503
  if (Math.abs(activePower - inputPower + chargePower) > 0) {
1490
1504
  this.log.debug(`activePower ${activePower} !== inputPower ${inputPower}-chargePower ${chargePower}`);
1491
- this.stateCache.set(`${path}activePower`, inputPower - chargePower, { type: 'number' });
1492
- /*
1493
- if (chargePower === 0) {
1494
- this.stateCache.set(`${path}activePower`, inputPower - chargePower, { type: 'number' });
1495
- } else {
1496
- this.stateCache.set(`${path}battery.chargeDischargePower`, inputPower - activePower, { type: 'number' });
1497
- }
1498
- */
1505
+ //this.stateCache.set(`${path}activePower`, inputPower - chargePower, { type: 'number' });
1499
1506
  }
1500
1507
  },
1501
1508
  },
@@ -1507,17 +1514,18 @@ class InverterSun2000 extends DriverBase {
1507
1514
  type: 'number',
1508
1515
  unit: 'kWh',
1509
1516
  role: 'value.power.consumption',
1510
- desc: 'Try to recreate the yield from the portal',
1517
+ desc: 'yield from the portal',
1511
1518
  },
1512
1519
  fn: path => {
1513
- const disCharge = this.stateCache.get(`${path}battery.currentDayDischargeCapacity`)?.value;
1514
- const charge = this.stateCache.get(`${path}battery.currentDayChargeCapacity`)?.value;
1515
- let inputYield = this.stateCache.get(`${path}dailyEnergyYield`)?.value * 0.97 + charge - disCharge;
1516
-
1517
- if (inputYield < 0 || isNaN(inputYield)) {
1518
- inputYield = 0;
1520
+ const disCharge = this.stateCache.get(`${path}battery.currentDayDischargeCapacity`)?.value ?? 0;
1521
+ const charge = this.stateCache.get(`${path}battery.currentDayChargeCapacity`)?.value ?? 0;
1522
+ //let inputYield = this.stateCache.get(`${path}dailyEnergyYield`)?.value ?? 0 * 0.97 + charge - disCharge;
1523
+ const activeEnergy = this.stateCache.get(`${path}derived.dailyActiveEnergy`)?.value ?? 0;
1524
+ let inYield = activeEnergy + (charge - disCharge) * 0.97; //efficiency loss of battery 3%
1525
+ if (inYield < 0) {
1526
+ inYield = 0;
1519
1527
  }
1520
- this.stateCache.set(`${path}derived.dailyInputYield`, inputYield, { type: 'number' });
1528
+ this.stateCache.set(`${path}derived.dailyInputYield`, inYield, { type: 'number' });
1521
1529
  },
1522
1530
  },
1523
1531
  {
@@ -1534,6 +1542,20 @@ class InverterSun2000 extends DriverBase {
1534
1542
  this.stateCache.set(`${path}derived.dailySolarYield`, this.solarSum.sum, { type: 'number' });
1535
1543
  },
1536
1544
  },
1545
+ {
1546
+ refresh: dataRefreshRate.low,
1547
+ state: {
1548
+ id: 'derived.dailyActiveEnergy',
1549
+ name: 'Active Energy today',
1550
+ type: 'number',
1551
+ unit: 'kWh',
1552
+ role: 'value.power.consumption',
1553
+ desc: 'Amount of Riemann sum of sum of active power',
1554
+ },
1555
+ fn: path => {
1556
+ this.stateCache.set(`${path}derived.dailyActiveEnergy`, this.activePowerSum.sum, { type: 'number' });
1557
+ },
1558
+ },
1537
1559
  ];
1538
1560
  this.postUpdateHooks.push.apply(this.postUpdateHooks, newHooks);
1539
1561
  }
@@ -1637,6 +1659,7 @@ class InverterSun2000 extends DriverBase {
1637
1659
 
1638
1660
  async mitnightProcess() {
1639
1661
  this.solarSum.reset();
1662
+ this.activePowerSum.reset();
1640
1663
  }
1641
1664
  }
1642
1665
 
package/lib/register.js CHANGED
@@ -31,7 +31,7 @@ class Registers {
31
31
  type: 'number',
32
32
  unit: 'kW',
33
33
  role: 'value.power',
34
- desc: '',
34
+ desc: 'Power from solar with efficiency loss',
35
35
  },
36
36
  {
37
37
  id: 'collected.chargeDischargePower',
@@ -66,7 +66,6 @@ class Registers {
66
66
  desc: 'Power from solar minus house consumption and usable battery power',
67
67
  },
68
68
  { id: 'collected.externalPower', name: 'external power', type: 'number', unit: 'kW', role: 'value.power' },
69
- //{ id: 'collected.ratedPower', name: 'rated power', type: 'number', unit: 'kW', role: 'value.power' },
70
69
  ],
71
70
  fn: inverters => {
72
71
  let actPower = 0;
@@ -80,7 +79,7 @@ class Registers {
80
79
  let usableSurplusPower = 0;
81
80
 
82
81
  if (this.adapter.control) {
83
- surplusPower += feedinPower;
82
+ surplusPower = feedinPower;
84
83
 
85
84
  const minSoc = this.adapter.control.get('usableSurplus.minSoc')?.value ?? 0;
86
85
  let bufferSoc = this.adapter.control.get('usableSurplus.bufferSoc')?.value ?? 0;
@@ -88,13 +87,21 @@ class Registers {
88
87
  const soc = this.stateCache.get('collected.SOC')?.value ?? 0;
89
88
  const allowNegativeValue = this.adapter.control.get('usableSurplus.allowNegativeValue')?.value ?? false;
90
89
  const hysterese = this.adapter.control.get('usableSurplus.bufferHysteresis')?.value ?? 0;
91
- // chargeDischarge
90
+ // discharge power is negative
92
91
  if (chargeDischarge < 0) {
93
92
  surplusPower += chargeDischarge;
94
93
  }
95
- if (soc >= minSoc) {
94
+
95
+ let threshold = hysterese / 2;
96
+ if (this.bufferOn) {
97
+ threshold = -threshold;
98
+ }
99
+
100
+ if (soc > minSoc) {
101
+ // charge power is positive - Battery is charging
96
102
  if (chargeDischarge > 0) surplusPower += chargeDischarge;
97
- if (bufferSoc === 0 || soc < bufferSoc) {
103
+
104
+ if (bufferSoc === 0 || soc < bufferSoc + threshold) {
98
105
  surplusPower -= residualPower / 1000;
99
106
  }
100
107
  }
@@ -102,11 +109,6 @@ class Registers {
102
109
  usableSurplusPower = surplusPower;
103
110
 
104
111
  if (bufferSoc > 0) {
105
- let threshold = hysterese / 2;
106
-
107
- if (this.bufferOn) {
108
- threshold = -threshold;
109
- }
110
112
  if (soc > minSoc && soc >= bufferSoc + threshold) {
111
113
  this.bufferOn = true;
112
114
  const bufferPower = this.adapter.control.get('usableSurplus.bufferPower')?.value ?? 0;
@@ -146,13 +148,11 @@ class Registers {
146
148
  inPowerEff += this.stateCache.get(`${inverter.path}.derived.inputPowerWithEfficiencyLoss`)?.value ?? 0;
147
149
  chargeDischarge += this.stateCache.get(`${inverter.path}.battery.chargeDischargePower`)?.value ?? 0;
148
150
  ratedPower += this.stateCache.get(`${inverter.path}.info.ratedPower`)?.value ?? 0;
149
- //maxChargePower = this.stateCache.get(`${inverter.path}.battery.maximumChargingPower`)?.value ?? 0;
150
151
  }
151
152
 
152
153
  const feedinPower = this.stateCache.get('meter.derived.feed-inPower')?.value ?? 0;
153
154
 
154
155
  const extPower = this.adapter.control.get('externalPower')?.value ?? 0;
155
- //extPower = extPower / 1000;
156
156
 
157
157
  //Zu geringe Erzeugerenegie
158
158
  let houseConsum = actPower - feedinPower + extPower;
@@ -165,7 +165,6 @@ class Registers {
165
165
  this.stateCache.set('collected.inputPower', inPower, { type: 'number', renew: true });
166
166
  this.stateCache.set('collected.inputPowerWithEfficiencyLoss', inPowerEff, { type: 'number' });
167
167
  this.stateCache.set('collected.activePower', actPower, { type: 'number', renew: true });
168
- //this.stateCache.set('collected.feed-inPower', feedinPower, { type: 'number' }); //positive -> power to grid
169
168
  this.stateCache.set('collected.houseConsumption', houseConsum, { type: 'number' });
170
169
  this.stateCache.set('collected.chargeDischargePower', chargeDischarge, { type: 'number' });
171
170
  this.stateCache.set('collected.usableSurplusPower', surplusArray[1], {
@@ -190,15 +189,15 @@ class Registers {
190
189
  type: 'number',
191
190
  unit: 'kWh',
192
191
  role: 'value.power.consumption',
193
- desc: 'daily output yield of the inverters',
192
+ desc: 'daily energy yield of the inverters',
194
193
  },
195
194
  {
196
195
  id: 'collected.dailyInputYield',
197
- name: 'Daily portal yield',
196
+ name: 'Daily input yield',
198
197
  type: 'number',
199
198
  unit: 'kWh',
200
199
  role: 'value.power.consumption',
201
- desc: 'Try to recreate the yield from the portal',
200
+ desc: 'yield from the portal',
202
201
  },
203
202
  {
204
203
  id: 'collected.dailySolarYield',
@@ -235,12 +234,23 @@ class Registers {
235
234
  },
236
235
  { id: 'collected.SOC', name: 'State of battery capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'SOC' },
237
236
  { id: 'collected.ratedCapacity', name: 'Rated of battery capacity', type: 'number', unit: 'Wh', role: 'value.capacity' },
237
+ /*
238
+ {
239
+ id: 'collected.dailyActiveEnergy',
240
+ name: 'Active Energy today',
241
+ type: 'number',
242
+ unit: 'kWh',
243
+ role: 'value.power.consumption',
244
+ desc: 'Amount of Riemann sum of sum of active power',
245
+ },
246
+ */
238
247
  ],
239
248
  fn: inverters => {
240
249
  let inYield = 0;
241
250
  let solarYield = 0;
242
251
  let outYield = 0;
243
252
  let enYield = 0;
253
+ let activeEnergy = 0;
244
254
  let charge = 0;
245
255
  let disCharge = 0;
246
256
  let totalDisCharge = 0;
@@ -254,10 +264,11 @@ class Registers {
254
264
  if (inverter.driverClass != driverClasses.inverter) {
255
265
  continue;
256
266
  }
257
- outYield += this.stateCache.get(`${inverter.path}.dailyEnergyYield`)?.value;
267
+ outYield += this.stateCache.get(`${inverter.path}.dailyEnergyYield`)?.value ?? 0;
258
268
  inYield += this.stateCache.get(`${inverter.path}.derived.dailyInputYield`)?.value;
259
269
  solarYield += this.stateCache.get(`${inverter.path}.derived.dailySolarYield`)?.value;
260
270
  enYield += this.stateCache.get(`${inverter.path}.accumulatedEnergyYield`)?.value;
271
+ activeEnergy += this.stateCache.get(`${inverter.path}.derived.dailyActiveEnergy`)?.value ?? 0;
261
272
  if (this.stateCache.get(`${inverter.path}.battery.ratedCapacity`)?.value > 0) {
262
273
  charge += this.stateCache.get(`${inverter.path}.battery.currentDayChargeCapacity`)?.value ?? 0;
263
274
  disCharge += this.stateCache.get(`${inverter.path}.battery.currentDayDischargeCapacity`)?.value ?? 0;
@@ -269,7 +280,7 @@ class Registers {
269
280
  ratedCap += this.stateCache.get(`${inverter.path}.battery.ratedCapacity`)?.value;
270
281
  }
271
282
  }
272
-
283
+ //this.stateCache.set('collected.dailyActiveEnergy', activeEnergy, { type: 'number' });
273
284
  this.stateCache.set('collected.dailyEnergyYield', outYield, { type: 'number' });
274
285
  this.stateCache.set('collected.dailyInputYield', inYield, { type: 'number' }); //deprecated
275
286
  this.stateCache.set('collected.dailySolarYield', solarYield, { type: 'number' });
@@ -284,6 +295,7 @@ class Registers {
284
295
  feedinEnergy = this.stateCache.get('meter.positiveActiveEnergy')?.value ?? 0;
285
296
  supplyFromGrid = this.stateCache.get('meter.reverseActiveEnergy')?.value ?? 0;
286
297
  }
298
+ //stimmt leider nicht genau - bleibt aber erstmal bestehen
287
299
  const conSum = enYield + supplyFromGrid - feedinEnergy;
288
300
  this.stateCache.set('collected.consumptionSum', conSum, { type: 'number' });
289
301
  // compute export and import today
@@ -293,11 +305,19 @@ class Registers {
293
305
  this.stateCache.set('collected.gridImportToday', supplyFromGrid - this.stateCache.get('collected.gridImportStart')?.value, {
294
306
  type: 'number',
295
307
  });
308
+ /* old computation of consumption today
296
309
  this.stateCache.set(
297
310
  'collected.consumptionToday',
298
311
  this.stateCache.get('collected.consumptionSum')?.value - this.stateCache.get('collected.consumptionStart')?.value,
299
312
  { type: 'number' },
300
313
  );
314
+ */
315
+ //new computation of consumption today
316
+ this.stateCache.set(
317
+ 'collected.consumptionToday',
318
+ activeEnergy + this.stateCache.get('collected.gridImportToday')?.value - this.stateCache.get('collected.gridExportToday')?.value,
319
+ { type: 'number' },
320
+ );
301
321
  //compute battery
302
322
  this.stateCache.set('collected.totalCharge', totalCharge, { type: 'number' });
303
323
  this.stateCache.set('collected.totalDischarge', totalDisCharge, { type: 'number' });
@@ -413,6 +433,7 @@ class Registers {
413
433
  this.stateCache.set('collected.gridImportStart', state?.val, { type: 'number', stored: true });
414
434
  state = await this.adapter.getState('collected.consumptionStart');
415
435
  this.stateCache.set('collected.consumptionStart', state?.val, { type: 'number', stored: true });
436
+ //this.stateCache.set('collected.consumptionStart', 100000, { type: 'number', stored: true });
416
437
  }
417
438
 
418
439
  //state
package/main.js CHANGED
@@ -379,7 +379,7 @@ class Sun2000 extends utils.Adapter {
379
379
  await this.setState('info.modbusDelay', { val: this.config.delay, ack: true });
380
380
  await this.setState('info.modbusTcpServer', { val: this.config.ms_active, ack: true });
381
381
  // Load user settings
382
- if (this.config.address != '' && this.config.port > 0 && this.config.modbusIds != '' && this.config.updateInterval > 0) {
382
+ if (this.config.address != '' && this.config.port > 0 && this.config.updateInterval > 0) {
383
383
  this.settings.address = this.config.address;
384
384
  this.settings.port = this.config.port;
385
385
  this.settings.modbusTimeout = this.config.timeout; //ms
@@ -421,67 +421,72 @@ class Sun2000 extends utils.Adapter {
421
421
  } else {
422
422
  await this.setState('info.JSONhealth', { val: '{message : "Information is collected"}', ack: true });
423
423
  }
424
-
425
- if (this.settings.modbusIds.length > 0 && this.settings.modbusIds.length < 6) {
426
- //ES6 use a for (const [index, item] of array.entries()) of loop
427
- for (const [i, id] of this.settings.modbusIds.entries()) {
428
- this.devices.push({
429
- index: i,
430
- duration: 5000,
431
- modbusId: id,
432
- driverClass: driverClasses.inverter,
433
- meter: i == 0 && this.settings.integration === 0,
434
- });
435
- }
436
-
437
- //SDongle
438
- if (this.settings.integration === 0 && this.settings.sd.active) {
439
- this.devices.push({
440
- index: 0,
441
- duration: 0,
442
- modbusId: this.settings.sd.sDongleId,
443
- driverClass: driverClasses.sdongle,
444
- });
424
+ //future: if (this.settings.integration !== 2 && (this.settings.modbusIds.length === 0 || this.settings.modbusIds.length > 5)) {
425
+ if (this.settings.modbusIds.length === 0 || this.settings.modbusIds.length > 5) {
426
+ this.adapterDisable(`*** Adapter deactivated, inverter modbus Ids is invalid! ***`);
427
+ return;
428
+ }
429
+ //ES6 use a for (const [index, item] of array.entries()) of loop
430
+ for (const [i, id] of this.settings.modbusIds.entries()) {
431
+ //Inverter
432
+ if (id < 1 || id >= 250) {
433
+ this.adapterDisable(`*** Adapter deactivated, inverter modbus Id ${id} is not permitted! ***`);
434
+ return;
445
435
  }
436
+ this.devices.push({
437
+ index: i,
438
+ duration: 5000,
439
+ modbusId: id,
440
+ driverClass: driverClasses.inverter,
441
+ meter: i == 0 && this.settings.integration === 0,
442
+ });
443
+ }
446
444
 
447
- //SmartLogger
448
- if (this.settings.integration === 1) {
449
- this.devices.push({
450
- index: 0,
451
- duration: 0,
452
- modbusId: 0,
453
- driverClass: driverClasses.logger,
454
- });
455
- if (this.settings.sl.meterId > 0) {
456
- this.devices.push({
457
- index: 0,
458
- duration: 0,
459
- meter: true,
460
- modbusId: this.settings.sl.meterId,
461
- driverClass: driverClasses.loggerMeter,
462
- });
463
- }
464
- }
445
+ //SDongle
446
+ if (this.settings.integration === 0 && this.settings.sd.active) {
447
+ this.devices.push({
448
+ index: 0,
449
+ duration: 0,
450
+ modbusId: this.settings.sd.sDongleId,
451
+ driverClass: driverClasses.sdongle,
452
+ });
453
+ }
465
454
 
466
- //EMMA
467
- if (this.settings.integration === 2) {
455
+ //SmartLogger
456
+ if (this.settings.integration === 1) {
457
+ this.devices.push({
458
+ index: 0,
459
+ duration: 0,
460
+ modbusId: 0,
461
+ driverClass: driverClasses.logger,
462
+ });
463
+ if (this.settings.sl.meterId > 0) {
468
464
  this.devices.push({
469
465
  index: 0,
470
466
  duration: 0,
471
- //modbusId: 1, --> testMode
472
- modbusId: 0,
473
467
  meter: true,
474
- driverClass: driverClasses.emma,
468
+ modbusId: this.settings.sl.meterId,
469
+ driverClass: driverClasses.loggerMeter,
475
470
  });
476
471
  }
472
+ }
477
473
 
478
- await this.adjustInverval();
479
- await this.StartProcess();
480
- } else {
481
- this.adapterDisable("*** Adapter deactivated, can't parse modbusIds! ***");
474
+ //EMMA with TestMode
475
+ if (this.settings.integration === 2) {
476
+ this.devices.push({
477
+ index: 0,
478
+ duration: 0,
479
+ //modbusId: 1, --> testMode
480
+ modbusId: 0,
481
+ meter: true,
482
+ driverClass: driverClasses.emma,
483
+ });
482
484
  }
485
+
486
+ await this.adjustInverval();
487
+ await this.StartProcess();
483
488
  } else {
484
- this.adapterDisable('*** Adapter deactivated, Adapter Settings incomplete! ***');
489
+ this.adapterDisable(`*** Adapter deactivated, Adapter Settings incomplete! ***`);
485
490
  }
486
491
  }
487
492
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.sun2000",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "sun2000",
5
5
  "author": {
6
6
  "name": "bolliy",