iobroker.sun2000 2.1.1 → 2.2.1-alpha.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
@@ -30,7 +30,7 @@ Feel free to follow the discussions in the german [iobroker forum](https://forum
30
30
  ## Requirements
31
31
  * Node.js 20 or higher
32
32
  * ioBroker host (js-controller) 6.0.11 or higher
33
- * ioBroker admin 7.4.10 or higher
33
+ * ioBroker admin 7.6.17 or higher
34
34
 
35
35
  ## Documentation
36
36
 
@@ -65,6 +65,20 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
65
65
  Placeholder for the next version (at the beginning of the line):
66
66
  ### **WORK IN PROGRESS**
67
67
  -->
68
+ ### 2.2.1-alpha.0 (2025-10-21)
69
+ * inverter control: add same state for startup and shutdown an inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)
70
+ * fix: Device status name has been corrected [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)
71
+ * add undocumented device status `Shutdown: End of the ESS discharge process`
72
+ * 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)
73
+ * if an Emma is installed, some control states of the inverter are deactivated (read only). Mainly for the grid settings.
74
+ * deprecated control states have been removed.
75
+ * a workaround for issue [#582](https://github.com/yaacov/node-modbus-serial/issues/582) of node-modbus-serial has been implemented.
76
+
77
+ ### 2.2.0 (2025-10-05)
78
+ * dependency and configuration updates
79
+ * new state `meter.derived.signConventionForPowerFeed-in` sign of meter.activePower that is currently being fed into the power grid
80
+ * new state `meter.derived.feed-inPower` electric power that is supplied to a grid ("fed in")
81
+
68
82
  ### 2.1.1 (2025-09-24)
69
83
  * dependency and configuration updates
70
84
  * fix: adjust event value limits based on usableSurplus parameters
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sun2000",
4
- "version": "2.1.1",
4
+ "version": "2.2.1-alpha.0",
5
5
  "news": {
6
+ "2.2.1-alpha.0": {
7
+ "en": "inverter control: add same state for startup and shutdown an inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfix: Device status name has been corrected [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\nadd undocumented device status `Shutdown: End of the ESS discharge process` \nemma control: new state ` emma.control.battery.ESSControlMode`. You can now configure EMMA with TOU-mode (Time of Use) to charge the battery from grid. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nif an Emma is installed, some control states of the inverter are deactivated (read only). Mainly for the grid settings.\ndeprecated control states have been removed.\na workaround for issue [#582](https://github.com/yaacov/node-modbus-serial/issues/582) of node-modbus-serial has been implemented.",
8
+ "de": "inverter-Steuerung: Fügen Sie den gleichen Zustand für Start und Abschaltung eines Inverters [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199) hinzu\nbehoben: Gerätestatusname wurde korrigiert [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\n`Shutdown: Ende des ESS-Entladungsvorgangs`\nemma control: new state ` emma.control.battery.ESSControlMode`. Sie können nun EMMA mit TOU-Modus (Time of Use) konfigurieren, um den Akku aus dem Netz zu laden. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nwenn eine Emma installiert ist, werden einige Steuerzustände des Wechselrichters deaktiviert (nur lesen). Hauptsächlich für die Netzeinstellungen.\ndeprekierte steuerzustände wurden entfernt.\nein workaround für ausgabe [#582](https://github.com/yaacov/node-modbus-serial/issues/582) von node-modbus-serial wurde implementiert.",
9
+ "ru": "инверторное управление: добавьте то же состояние для запуска и отключения инвертора [#199] (https://github.com/bolliy/ioBroker.sun2000/issues/199)\nисправление: имя статуса устройства было исправлено [#202] (https://github.com/bolliy/ioBroker.sun2000/pull/202)\nдобавить незарегистрированный статус устройства «Shutdown: End of the ESS discharge process»\nemma control: emma.control.battery.ESSControlMode. Теперь вы можете настроить EMMA с режимом TOU (Время использования) для зарядки батареи из сетки. [#200] (https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nесли установлена Эмма, некоторые контрольные состояния инвертора деактивируются (только чтение). В основном для настроек сетки.\nустаревшие контрольные штаты были удалены.\nбыл реализован обходной путь для выпуска [#582] (https://github.com/yaacov/node-modbus-serial/issues/582) node-modbus-serial.",
10
+ "pt": "controle do inversor: adicione o mesmo estado para iniciar e desligar um inversor [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\ncorreção: o nome do estado do dispositivo foi corrigido [#202] (https://github.com/bolliy/ioBroker.sun2000/pull/202)\nadicionar status do dispositivo não documentado `Shutdown: Fim do processo de descarga do ESS'\nemma control: novo estado `emma.control.battery.ESSControlMode`. Agora você pode configurar o EMMA com o modo TOU (Time of Use) para carregar a bateria da grade. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nse uma Emma estiver instalada, alguns estados de controle do inversor são desativados (apenas lidos). Principalmente para as configurações da grade.\nos estados de controlo desactualizados foram removidos.\numa solução alternativa para o problema [#582](https://github.com/yaacov/node-modbus-serial/issues/582) do nó-modbus-serial foi implementada.",
11
+ "nl": "inverter control: voeg dezelfde status toe voor het opstarten en afsluiten van een inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfix: De status van het apparaat is gecorrigeerd [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\nstatus van niet-gedocumenteerd apparaat toevoegen: Afsluiten: Einde van het ESS-ontladingsproces\nemma control: nieuwe staat U kunt nu EMMA configureren met de TOU-modus (Time of Use) om de batterij op te laden van het net. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nals een Emma is geïnstalleerd, worden sommige controletoestanden van de omvormer gedeactiveerd (alleen lezen). Vooral voor de rasterinstellingen.\nverouderde controlestaten zijn verwijderd.\ner is een oplossing gevonden voor nummer [#582](https://github.com/yaacov/node-modbus-serial/issues/582) van node-modbus-serial.",
12
+ "fr": "contrôle de l'onduleur: ajouter le même état pour le démarrage et l'arrêt d'un onduleur [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\ncorrection : le nom de l'état du périphérique a été corrigé [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\najouter l'état de l'appareil sans papiers `Shutdown: Fin du processus de décharge ESS'\ncontrôle emma: nouvel état ` emma.control.battery.ESSControlMode`. Vous pouvez maintenant configurer EMMA en mode TOU (Time of Use) pour charger la batterie à partir de la grille. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nsi une Emma est installée, certains états de contrôle de l'onduleur sont désactivés (lisez seulement). Principalement pour les paramètres de la grille.\nles états de contrôle dépréciés ont été supprimés.\nune solution de rechange pour l'émission [#582](https://github.com/yaacov/node-modbus-serial/issues/582) de nœud-modbus-serial a été mise en œuvre.",
13
+ "it": "controllo inverter: aggiungere lo stesso stato per l'avvio e l'arresto di un inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfix: Il nome dello stato del dispositivo è stato corretto [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\naggiungere lo stato del dispositivo non documentato `Shutdown: Fine del processo di scarico ESS`\ncontrollo emma: nuovo stato ` emma.control.battery.ESSControlMode`. È ora possibile configurare EMMA con TOU-mode (Time of Use) per caricare la batteria dalla rete. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nse viene installata una Emma, alcuni stati di controllo dell'inverter sono disattivati (leggi solo). Principalmente per le impostazioni della griglia.\nstati di controllo deprecati sono stati rimossi.\nè stato implementato un workaround per il numero [#582](https://github.com/yaacov/node-modbus-serial/issues/582) di node-modbus-serial.",
14
+ "es": "control inverter: añadir el mismo estado para iniciar y cerrar un inverter [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nfijado: Se ha corregido el nombre del estado de los dispositivos [#202](https://github.com/bolliy/ioBroker.sun2000/pull/202)\nañadir estado de dispositivo no documentado `Shutdown: Final del proceso de descarga ESS`\nemma control: nuevo estado ` emma.control.battery.ESSControlMode`. Ahora puede configurar EMMA con TOU-mode (Time of Use) para cargar la batería de la red. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nsi se instala una Emma, se desactivan algunos estados de control del inversor (sólo lectura). Principalmente para la configuración de la red.\nestados de control deprecatados han sido eliminados.\na workaround for issue [#582](https://github.com/yaacov/node-modbus-serial/issues/582) of node-modbus-serial has been implemented.",
15
+ "pl": "inverter control: add same state for startup and shutdown an inverter [# 199] (https: / / github.com / bolliy / ioBroker.sun2000 / issues / 199)\nfix: Nazwa statusu urządzenia została poprawiona [# 202] (https: / / github.com / bolliy / ioBroker.sun2000 / pull / 202)\ndodać nieudokumentowany status urządzenia \"Wyłączenie: koniec procesu rozładowania ESS\"\nemma control: New state 'emma.control.battery.ESSControlMode'. Można teraz skonfigurować EMMA z TOU- mode (Time of Use), aby naładować baterię z siatki. [# 200] (https: / / github.com / bolliy / ioBroker.sun2000 / discussions / 200)\njeśli zainstalowana jest Emma, niektóre stany sterujące inwertera są wyłączone (tylko do odczytu). Głównie dla ustawień siatki.\nusunięto zdepregatowane stany kontrolne.\na workaround for issue [# 582] (https: / / github.com / yaacov / node- modbus- serial / issues / 582) of node- modbus- serial został wdrożony.",
16
+ "uk": "контроль інвертора: додати однаковий стан для запуску та відключення інвертора [#199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\nвиправлено: Назва стану пристрою було виправлено [#202] (https://github.com/bolliy/ioBroker.sun2000/pull/202)\nдодати недокументований статус пристрою `Пошук: кінець процесу розряду ESS\nемма управління: новий стан ` emma.control.battery.ESSControlMode`. Ви можете налаштувати EMMA з TOU-mode (Time of Use) для зарядки акумулятора з сітки. [#200](https://github.com/bolliy/ioBroker.sun2000/discussions/200)\nякщо встановлений Емма, деактивуються деякі стани управління інвертором (прочитати тільки). В основному для налаштування сітки.\nвилучені стани керування.\n[#582](https://github.com/yaacov/node-modbus-serial/issues/582) вузла-modbus-serial.",
17
+ "zh-cn": "反转器控制:为启动和关闭添加相同状态的反转器[199](https://github.com/bolliy/ioBroker.sun2000/issues/199)\n固定: 设备状态名称已更正 [# 202] (https://github.com/bolliy/ioBroker.sun2000/pul/202)\n添加无文件设备状态“关闭:ESS放电过程结束”\nemma控制:新状态`emma.control.battery.ESS Control Mode'. 您现在可以用 TOU- mode( 使用时间) 配置 EMMA 从电网中充电 。 [# 200] (https://github.com/bolliy/ioBroker.sun2000/discussions/200)\n如果安装了Emma,反转器的某些控制状态就会失效(只读). 主要用于网格设置.\n贬值的控制状态已被取消.\n已落实了节点-modbus-serial[#582](https://github.com/yaacov/node-modbus-serial/issues/582)的工作."
18
+ },
19
+ "2.2.0": {
20
+ "en": "dependency and configuration updates\nnew state `meter.derived.signConventionForPowerFeed-in` sign of meter.activePower that is currently being fed into the power grid\nnew state `meter.derived.feed-inPower` electric power that is supplied to a grid (\"fed in\")",
21
+ "de": "abhängigkeits- und konfigurationsupdates\nneuer Zustand `meter.derived.signConventionForPowerFeed-in` Zeichen von meter.active Strom, der derzeit in das Stromnetz eingespeist wird\nneue Zustand `meter.derived.feed-inPower` elektrische Leistung, die einem Netz zugeführt wird (\"fed in\")",
22
+ "ru": "обновления зависимостей и конфигурации\nновый государственный знак «meter.derived.signConventionForPowerFeed-in» Мощность, которая в настоящее время подается в электросеть\nэлектрическая мощность нового состояния «meter.derived.feed-inPower», которая подается в сеть («питается в»)",
23
+ "pt": "atualizações de dependência e configuração\nnovo estado `meter.derived.signConventionForPowerFeed-in` sinal do medidor.active Energia que está sendo alimentada na rede de energia\nnovo estado `meter.derived.feed-inPower` energia elétrica que é fornecida a uma grade (\"feed in\")",
24
+ "nl": "afhankelijkheid en configuratie-updates\nnieuwe staat Energie die momenteel wordt gevoed in het elektriciteitsnet\nnieuwe toestand ",
25
+ "fr": "mises à jour de la dépendance et de la configuration\nnouvel état `meter.derived.signConventionForPowerFeed-in` signe de meter.active Puissance qui est actuellement introduite dans le réseau électrique\nnouvel état `meter.derived.feed-inPower` électricité qui est fourni à un réseau (\"feed in\")",
26
+ "it": "aggiornamenti di dipendenza e configurazione\nnuovo stato `meter.derived.signConventionForPowerFeed-in` segno di metro.active Potenza che sta attualmente alimentando nella rete elettrica\nnuovo stato `meter.derived.feed-inPower` potere elettrico che viene fornito a una griglia (\"fed in\")",
27
+ "es": "actualizaciones de dependencia y configuración\nnuevo estado `meter.derived.signConventionForPowerFeed-in` signo de medidor.active Potencia que actualmente está siendo alimentada en la red eléctrica\nnuevo estado `meter.derived.feed-inPower` energía eléctrica que se suministra a una red (\"fed in\")",
28
+ "pl": "aktualizacje zależności i konfiguracji\nnowy stan 'meter.derived.signConventionForPowerFeed- in' znak meter.active Energia zasilana obecnie do sieci energetycznej\nnowy stan 'meter.derived.feed-inPower' energia elektryczna, która jest dostarczana do sieci (\"karmiona w\")",
29
+ "uk": "оновлення залежності та конфігурації\nновий стан `meter.derived.signConventionForPowerFeed-in` знак лічильника.active Потужність, яка в даний час вдається в електромережу\nновий стан `meter.derived.feed-inPower` електрична потужність, яка подається в сітку (\"fed in\")",
30
+ "zh-cn": "依赖和配置更新\n新的状态“ 公尺” 。 生成。 签署 Convention ForPowerFeed- in' sign of meter. 活动 目前输入电网的电力\n新状态“ met. entered. feed-inpower” 供电给电网(“ feeded in”)"
31
+ },
6
32
  "2.1.1": {
7
33
  "en": "dependency and configuration updates\nfix: adjust event value limits based on usableSurplus parameters\nfix: swap register values for power consumption in Emma driver #190\nemma: improve power calculation with exponential moving average in EmmaCharger\nupdate surplus power state definitions and deprecate old identifiers",
8
34
  "de": "abhängigkeits- und konfigurationsupdates\nfix: Event-Wert-Grenze basierend auf nutzbar Überschüssige Parameter\nfix: Swap-Registerwerte für den Stromverbrauch in Emma Treiber #190\nemma: Leistungsberechnung mit exponentiellem Bewegungsmittel in EmmaCharger verbessern\naktualisierung der überschussstrom-zustandsdefinitionen und abschreibung alter kennungen",
@@ -67,32 +93,6 @@
67
93
  "pl": "control: nowy stan kontroli 'sun2000.0.control.externalPower' # 76\nstała emisja wykryta przez kontroler repozytorium # 166",
68
94
  "uk": "контроль: новий стан управління `sun2000.0.control.externalPower` #76\nвиправлено проблему, виявлену репозиторійною перевіркою #166",
69
95
  "zh-cn": "控制:新的控制状态`sun 2000.0.control.external Power ' 76号\n仓库检查器检测到的固定问题 # 166"
70
- },
71
- "1.3.0": {
72
- "en": "usableSurplusPower: new control state `sun2000.0.control.usableSurplus.allowNegativeValue`",
73
- "de": "usableSurplusPower: neuer Steuerzustand `sun2000.0.control.usableSurplus.allowNegativeValue `",
74
- "ru": "usableSurplusPower: новое состояние управления 'sun2000.0.control.usableSurplus.allowНегативная ценность пункт",
75
- "pt": "usableSurplusPower: novo estado de controle `sun2000.0.control.usableSurplus.allowValue negativo \"",
76
- "nl": "bruikbareSurplusPower: nieuwe controlestatus Wat",
77
- "fr": "utilisableSurplusPower: nouvel état de contrôle `sun2000.0.control.usableSurplus.allowNegativeValue \"",
78
- "it": "usableSurplusPower: nuovo stato di controllo `sun2000.0.control.usableSurplus.allowValore negativo #",
79
- "es": "usableSurplusPower: nuevo estado de control `sun2000.0.control.usableSurplus.allowNegativeValue `",
80
- "pl": "usableSurplusPower: nowy stan kontroli 'Sun2000.0.control.usableSurplus.allowNegativeValue'",
81
- "uk": "english, Українська, Français... й",
82
- "zh-cn": "可用SurpusPower: 新的控制状态 `sun 2000.control.usurplus.allow NegativeValue ' `"
83
- },
84
- "1.2.2": {
85
- "en": "deploy 1.2",
86
- "de": "bereitstellung 1.2",
87
- "ru": "развернуть 1.2",
88
- "pt": "implementação 1.2",
89
- "nl": "1.2 inzetten",
90
- "fr": "déploiement 1,2",
91
- "it": "distribuzione 1.2",
92
- "es": "despliegue 1.2",
93
- "pl": "rozmieszczenie 1.2",
94
- "uk": "розгортання 1.2",
95
- "zh-cn": "部署"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -0,0 +1,304 @@
1
+ 'use strict';
2
+ const { deviceType, dataType } = require(`${__dirname}/../types.js`);
3
+ class ServiceQueueMap {
4
+ constructor(adapterInstance, emma) {
5
+ this.adapter = adapterInstance;
6
+ this.log = this.adapter.logger;
7
+ this.inverterInfo = emma;
8
+ this._modbusClient = null;
9
+ this._serviceMap = new Map();
10
+ this._eventMap = new Map();
11
+ this._initialized = false;
12
+ this._name = 'emma control';
13
+
14
+ this.serviceFields = [
15
+ {
16
+ state: { id: 'battery.ESSControlMode', name: 'ESS control mode', type: 'number', unit: '', role: 'level', desc: 'reg:40000, len:1' },
17
+ type: deviceType.battery,
18
+ fn: async event => {
19
+ let ret = false;
20
+ if (event.value > 6) {
21
+ event.value = 2;
22
+ }
23
+ if (event.value < 2 || event.value === 3) {
24
+ event.value = 2;
25
+ }
26
+ if (this.isTestMode()) {
27
+ this.log.info(`${this._name}: the test mode is active, so the ESS control mode is always written to register 47086`);
28
+ ret = await this._writeRegisters(47086, dataType.numToArray(event.value, dataType.uint16));
29
+ } else {
30
+ ret = await this._writeRegisters(40000, dataType.numToArray(event.value, dataType.uint16));
31
+ /*
32
+ if (ret) {
33
+ this.inverterInfo.instance.stateCache.set(`emma.${event.id}`, event.value, { type: 'number' });
34
+ }
35
+ */
36
+ }
37
+ return ret;
38
+ },
39
+ },
40
+ {
41
+ state: {
42
+ id: 'battery.tou.preferredUseOfSurplusPvPower',
43
+ name: '[Time of Use mode] Preferred use of surplus PV power',
44
+ type: 'boolean',
45
+ unit: '',
46
+ role: 'switch.enable',
47
+ desc: 'reg: 40001, len: 1',
48
+ },
49
+ type: deviceType.battery,
50
+ fn: async event => {
51
+ let ret = false;
52
+
53
+ if (this.isTestMode()) {
54
+ this.log.info(`${this._name}: the test mode is active, so the maximum power for charging batteries from grid not transferred`);
55
+ ret = true;
56
+ } else {
57
+ ret = await this._writeRegisters(40001, event.value === true ? [1] : [0]);
58
+ }
59
+ /*
60
+ if (ret) {
61
+ this.inverterInfo.instance.stateCache.set(`emma.${event.id}`, event.value);
62
+ }
63
+ */
64
+ return ret;
65
+ },
66
+ },
67
+ {
68
+ state: {
69
+ id: 'battery.tou.maximumPowerForChargingFromGrid',
70
+ name: '[Time of Use mode] Maximum power for charging batteries from grid',
71
+ type: 'number',
72
+ unit: 'kW',
73
+ role: 'level.power',
74
+ desc: 'reg: 40002, len: 2',
75
+ },
76
+ type: deviceType.battery,
77
+ fn: async event => {
78
+ let ret = false;
79
+ if (event.value > 50) {
80
+ event.value = 50;
81
+ }
82
+ if (event.value < 0) {
83
+ event.value = 0;
84
+ }
85
+ if (this.isTestMode()) {
86
+ this.log.info(`${this._name}: the test mode is active, so the maximum power for charging batteries from grid not transferred`);
87
+ ret = true;
88
+ } else {
89
+ ret = await this._writeRegisters(40002, dataType.numToArray(event.value * 1000, dataType.uint32));
90
+ }
91
+ /*
92
+ if (ret) {
93
+ this.inverterInfo.instance.stateCache.set(`emma.${event.id}`, event.value, { type: 'number' });
94
+ }
95
+ */
96
+ return ret;
97
+ },
98
+ },
99
+ ];
100
+ }
101
+
102
+ async _init() {
103
+ if (this.inverterInfo.instance) {
104
+ for (const item of this.serviceFields) {
105
+ if (item?.state) {
106
+ this._serviceMap.set(item.state.id, item);
107
+ }
108
+ }
109
+
110
+ for (const entry of this._serviceMap.values()) {
111
+ //await this._initState('emma.control.',entry.state);
112
+ const path = `emma.control.`;
113
+ await this._initState(path, entry.state);
114
+ const state = await this.adapter.getState(path + entry.state.id);
115
+ if (state && state.ack === false) {
116
+ this.set(entry.state.id, state);
117
+ }
118
+ }
119
+ //subscribe all control states
120
+ this.adapter.subscribeStates(`emma.control*`);
121
+ this._initialized = true;
122
+
123
+ if (this.adapter.settings?.cb.tou && !this.isTestMode()) {
124
+ const essControlMode = await this._readHoldingRegisters(40000, 1);
125
+ //const tou = await this._readHoldingRegisters(40004,43); //first periode
126
+ if (essControlMode && essControlMode[0] !== 5) {
127
+ /*
128
+ 127 - Working mode settings
129
+ 2 : Maximise self consumptions (default)
130
+ 5 : Time Of Use(Luna) - hilfreich bei dynamischem Stromtarif (z.B Tibber)
131
+
132
+ Time of Using charging and discharging periodes (siehe Table 5-6)
133
+ tCDP[3] = 127 - Working mode settings - load from grid (charge)
134
+ tCDP[3] = 383 - Working mode settings - self-consumption (discharge)
135
+ */
136
+ const tCDP = [
137
+ 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,
138
+ ];
139
+ if (await this._writeRegisters(40004, tCDP)) {
140
+ this.inverterInfo.instance.addHoldingRegisters((40004, tCDP));
141
+ this.log.info(`${this._name}: The default TOU setting are transferred`);
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ if (this._initialized) {
148
+ this.log.info(`${this._name}: service queue initialized`);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Checks if the device is in test mode
154
+ * @returns {boolean} True if the device is in test mode, false otherwise
155
+ */
156
+ isTestMode() {
157
+ return this.inverterInfo.instance?.isTestMode() || false;
158
+ }
159
+
160
+ /**
161
+ * @description Check if the value of the event is a number and optionally round it to the nearest integer.
162
+ * @param {object} event The event object
163
+ * @param {boolean} [round] If true, the value is rounded to the nearest integer
164
+ * @returns {boolean} True if the value is a number, false otherwise
165
+ */
166
+ isNumber(event, round = true) {
167
+ if (isNaN(event.value)) {
168
+ return false;
169
+ }
170
+ if (round) event.value = Math.round(event.value);
171
+ return true;
172
+ }
173
+
174
+ get(id) {
175
+ return this._eventMap.get(id);
176
+ }
177
+
178
+ set(id, state) {
179
+ const service = this._serviceMap.get(id);
180
+ if (state && service) {
181
+ if (state.val !== null && !state.ack) {
182
+ this.log.info(`${this._name}: Event - state: emma.control.${id} changed: ${state.val} ack: ${state.ack}`);
183
+ const event = this._eventMap.get(id);
184
+ if (event) {
185
+ event.value = state.val;
186
+ event.ack = false;
187
+ } else {
188
+ this._eventMap.set(id, { id: id, value: state.val, ack: false });
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Processes pending events in the service queue and attempts to execute their associated functions.
196
+ *
197
+ * @async
198
+ * @param {object} modbusClient - The modbus client instance used for communication.
199
+ *
200
+ * @description This function iterates over the events in the service queue, checking whether each event
201
+ * can be processed. It verifies conditions such as battery presence and running status, and checks if the
202
+ * event value is a number when required. If the event is successfully processed, it acknowledges the event
203
+ * by setting its state in the adapter and removes it from the event map. If the event cannot be processed
204
+ * after multiple attempts, it is discarded. The function initializes the service queue if it is not already
205
+ * initialized and the adapter is connected.
206
+ */
207
+
208
+ async process(modbusClient) {
209
+ this._modbusClient = modbusClient;
210
+
211
+ if (this._initialized) {
212
+ let count = 0;
213
+ for (const event of this._eventMap.values()) {
214
+ if (event.ack) {
215
+ continue;
216
+ } //allready done
217
+ const service = this._serviceMap.get(event.id);
218
+ if (!service.errorCount) {
219
+ service.errorCount = 0;
220
+ }
221
+ if (event.value !== null && service.fn) {
222
+ //check if battery is present and running
223
+ if (service.state.type === 'number') {
224
+ if (!this.isNumber(event)) {
225
+ this.log.warn(
226
+ `${this._name}: Event is discarded because the value ${event.value} is not a number. State: emma.control.${event.id}`,
227
+ );
228
+ this._eventMap.delete(event.id); //forget the event
229
+ continue;
230
+ }
231
+ }
232
+ count++;
233
+ if (await service.fn(event)) {
234
+ service.errorCount = 0;
235
+ try {
236
+ event.ack = true;
237
+ await this.adapter.setState(`emma.control.${event.id}`, { val: event.value, ack: true });
238
+ this._eventMap.delete(event.id);
239
+ this.log.info(`${this._name}: write state emma.control.${event.id} : ${event.value} ack: true`);
240
+ } catch {
241
+ this.log.warn(`${this._name}: Can not write state emma.control.${event.id}`);
242
+ }
243
+ } else {
244
+ service.errorCount++;
245
+ if (service.errorCount > 1) {
246
+ this._eventMap.delete(event.id); //forget it
247
+ this.log.info(`${this._name}: Event is discarded because it could not be processed. State: emma.control.${event.id}`);
248
+ }
249
+ }
250
+ }
251
+ if (count > 1) {
252
+ break;
253
+ } //max 2 Events
254
+ }
255
+ }
256
+ if (!this._initialized && this.adapter.isConnected) {
257
+ await this._init();
258
+ }
259
+ }
260
+
261
+ async _writeRegisters(address, data) {
262
+ try {
263
+ this.log.debug(`Try to write data to id/address/length ${this._modbusClient.id}/${address}/${data.length}`);
264
+ await this._modbusClient.writeRegisters(address, data);
265
+ this.inverterInfo.instance.addHoldingRegisters(address, data); //write also to the modbus read cache
266
+ return true;
267
+ } catch (err) {
268
+ this.log.warn(
269
+ `Error while writing to ${this._modbusClient.ipAddress} [Reg: ${address}, Len: ${data.length}, modbusID: ${this._modbusClient.id}] with: ${err.message}`,
270
+ );
271
+ }
272
+ }
273
+
274
+ async _readHoldingRegisters(address, length) {
275
+ try {
276
+ this.log.debug(`Try to read data to id/address/length ${this._modbusClient.id}/${address}/${length}`);
277
+ const data = await this._modbusClient.readHoldingRegisters(address, length);
278
+ return data;
279
+ } catch (err) {
280
+ this.log.warn(
281
+ `Error while reading from ${this._modbusClient.ipAddress} [Reg: ${address}, Len: ${length}, modbusID: ${this._modbusClient.id}] with: ${err.message}`,
282
+ );
283
+ }
284
+ }
285
+
286
+ //state
287
+ async _initState(path, state) {
288
+ await this.adapter.extendObject(path + state.id, {
289
+ type: 'state',
290
+ common: {
291
+ name: state.name,
292
+ type: state.type,
293
+ role: state.role,
294
+ unit: state.unit,
295
+ desc: state.desc,
296
+ read: true,
297
+ write: true,
298
+ },
299
+ native: {},
300
+ });
301
+ }
302
+ }
303
+
304
+ module.exports = ServiceQueueMap;