iobroker.alpha-ess 1.2.1 → 1.3.0-beta.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
@@ -57,12 +57,21 @@ How to find SN and Check code for registration is described here: https://github
57
57
  - **Interval to read charging settings:** Unit: minutes.
58
58
  - **Interval to read discharging settings:** Unit: minutes.
59
59
  - **Interval to read summary data:** Unit: minutes.
60
+ - **Interval to read wallbox data:** Unit: minutes. Caution: Currently only one Wallbox is supported.
60
61
 
61
62
  ## Disclaimer
62
63
 
63
64
  **All product and company names or logos are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them or any associated subsidiaries! This personal project is maintained in spare time and has no business goal.**
64
65
 
65
66
  ## Changelog
67
+ ### 1.3.0-beta.1 (2023-11-21)
68
+
69
+ - (Gaspode) Start and stop charging of wallbox with Open API
70
+
71
+ ### 1.3.0-beta.0 (2023-11-18)
72
+
73
+ - (Gaspode) Support wallbox with Open API
74
+
66
75
  ### 1.2.1 (2023-11-11)
67
76
 
68
77
  - (Gaspode) Fixed severe error in ClosedAPI
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Persönliches Application Secret",
14
14
  "Interval to read charging settings": "Intervall zum Lesen der Ladeeinstellungen [min]",
15
15
  "Interval to read discharging settings": "Intervall zum Lesen der Entladeeinstellungen [min]",
16
+ "Interval to read wallbox data": "Intervall zum Auslesen der Wallbox-Daten [min]",
16
17
  "Sorry. Closed API currently not supported!": "Entschuldigung. Closed API wird aufgrund von Änderungen durch Alpha-ESS derzeit nicht unterstützt!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Personal Application Secret",
14
14
  "Interval to read charging settings": "Interval to read charging settings [min]",
15
15
  "Interval to read discharging settings": "Interval to read discharging settings [min]",
16
+ "Interval to read wallbox data": "Interval to read wallbox data [min]",
16
17
  "Sorry. Closed API currently not supported!": "Sorry. Closed API currently not supported due to changes by Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Secreto de aplicación personal",
14
14
  "Interval to read charging settings": "Intervalo para leer la configuración de carga",
15
15
  "Interval to read discharging settings": "Intervalo para leer la configuración de descarga",
16
+ "Interval to read wallbox data": "Intervalo para leer los datos del wallbox [min]",
16
17
  "Sorry. Closed API currently not supported!": "Lo siento. ¡La API cerrada actualmente no es compatible debido a cambios realizados por Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Secret d'application personnel",
14
14
  "Interval to read charging settings": "Intervalle pour lire les paramètres de charge",
15
15
  "Interval to read discharging settings": "Intervalle pour lire les paramètres de décharge",
16
+ "Interval to read wallbox data": "Intervalle de lecture des données de la wallbox [min]",
16
17
  "Sorry. Closed API currently not supported!": "Désolé. API fermée actuellement non prise en charge en raison de modifications apportées par Alpha-ESS !"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Segreto dell'applicazione personale",
14
14
  "Interval to read charging settings": "Intervallo per leggere le impostazioni di ricarica",
15
15
  "Interval to read discharging settings": "Intervallo per leggere le impostazioni di scarica",
16
+ "Interval to read wallbox data": "Intervallo per leggere i dati della Wallbox [min]",
16
17
  "Sorry. Closed API currently not supported!": "Scusa. API chiusa attualmente non supportata a causa di modifiche apportate da Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Persoonlijk toepassingsgeheim",
14
14
  "Interval to read charging settings": "Interval om laadinstellingen te lezen",
15
15
  "Interval to read discharging settings": "Interval om ontlaadinstellingen te lezen",
16
+ "Interval to read wallbox data": "Interval voor het lezen van wallbox-gegevens [min]",
16
17
  "Sorry. Closed API currently not supported!": "Sorry. Gesloten API momenteel niet ondersteund vanwege wijzigingen door Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Tajny wniosek osobisty",
14
14
  "Interval to read charging settings": "Interwał odczytu ustawień ładowania",
15
15
  "Interval to read discharging settings": "Interwał odczytu ustawień rozładowania",
16
+ "Interval to read wallbox data": "Interwał odczytu danych wallboxa [min]",
16
17
  "Sorry. Closed API currently not supported!": "Przepraszam. Zamknięte API obecnie nie jest obsługiwane ze względu na zmiany wprowadzone przez Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Segredo de aplicativo pessoal",
14
14
  "Interval to read charging settings": "Intervalo para ler as configurações de carregamento",
15
15
  "Interval to read discharging settings": "Intervalo para ler as configurações de descarga",
16
+ "Interval to read wallbox data": "Intervalo para leitura dos dados da Wallbox [min]",
16
17
  "Sorry. Closed API currently not supported!": "Desculpe. API fechada atualmente não suportada devido a alterações do Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Секрет личного приложения",
14
14
  "Interval to read charging settings": "Интервал чтения настроек зарядки",
15
15
  "Interval to read discharging settings": "Интервал чтения настроек разрядки",
16
+ "Interval to read wallbox data": "Интервал чтения данных Wallbox [мин]",
16
17
  "Sorry. Closed API currently not supported!": "Извини. Закрытый API в настоящее время не поддерживается из-за изменений Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "Особистий секрет програми",
14
14
  "Interval to read charging settings": "Інтервал зчитування параметрів заряджання",
15
15
  "Interval to read discharging settings": "Інтервал зчитування параметрів розрядки",
16
+ "Interval to read wallbox data": "Інтервал зчитування даних Wallbox [хв]",
16
17
  "Sorry. Closed API currently not supported!": "вибач Закритий API наразі не підтримується через зміни Alpha-ESS!"
17
18
  }
@@ -13,5 +13,6 @@
13
13
  "Personal APP Secret": "个人申请秘诀",
14
14
  "Interval to read charging settings": "读取充电设置的间隔",
15
15
  "Interval to read discharging settings": "读取放电设置的间隔",
16
+ "Interval to read wallbox data": "读取 Wallbox 数据的时间间隔 [min]",
16
17
  "Sorry. Closed API currently not supported!": "对不起。由于 Alpha-ESS 的更改,目前不支持封闭 API!"
17
18
  }
@@ -155,6 +155,20 @@
155
155
  "disabled": "!data.enableSummarydata",
156
156
  "hidden": "data.apiType == 1 || data.apiType == 3"
157
157
  },
158
+ "enableWallbox": {
159
+ "type": "checkbox",
160
+ "newLine": true,
161
+ "hidden": "true"
162
+ },
163
+ "intervalWallboxMins": {
164
+ "sm": 5,
165
+ "min": 1,
166
+ "type": "number",
167
+ "label": "Interval to read wallbox data",
168
+ "newLine": false,
169
+ "disabled": "!data.oAEnableWallbox",
170
+ "hidden": "true"
171
+ },
158
172
  "oAEnableRealtime": {
159
173
  "type": "checkbox",
160
174
  "newLine": true,
@@ -253,6 +267,20 @@
253
267
  "disabled": "!data.oAEnableSummary",
254
268
  "hidden": "data.apiType == 0"
255
269
  },
270
+ "oAEnableWallbox": {
271
+ "type": "checkbox",
272
+ "newLine": true,
273
+ "hidden": "data.apiType == 0"
274
+ },
275
+ "oAIntervalWallboxMins": {
276
+ "sm": 5,
277
+ "min": 1,
278
+ "type": "number",
279
+ "label": "Interval to read wallbox data",
280
+ "newLine": false,
281
+ "disabled": "!data.oAEnableWallbox",
282
+ "hidden": "data.apiType == 0"
283
+ },
256
284
  "updateUnchangedStates": {
257
285
  "type": "checkbox",
258
286
  "label": "Update unchanged states",
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "alpha-ess",
4
- "version": "1.2.1",
4
+ "version": "1.3.0-beta.1",
5
5
  "news": {
6
+ "1.3.0-beta.1": {
7
+ "en": "Start and stop charging of wallbox with Open API",
8
+ "de": "Starten und stoppen des Ladevorgangs der Wallbox mit Open API",
9
+ "ru": "Начните и остановите зарядку настенного ящика с Open API",
10
+ "pt": "Iniciar e parar de carregar de wallbox com API aberta",
11
+ "nl": "Begin en stop met het inladen van een muurkist met open API",
12
+ "fr": "Démarrer et arrêter le chargement de la boîte murale avec Open API",
13
+ "it": "Avviare e interrompere la ricarica di wallbox con Open API",
14
+ "es": "Comience y deje de cargar Wallbox con Open API",
15
+ "pl": "Start i zatrzymanie ładowania skrzynki z Open API",
16
+ "uk": "Старт і зупинка зарядки стінок з відкритим API",
17
+ "zh-cn": "A. 开端和停止向开放的阿联酋投掷石箱"
18
+ },
19
+ "1.3.0-beta.0": {
20
+ "en": "Support wallbox with Open API",
21
+ "de": "Wallbox Unterstützung mit Open API",
22
+ "ru": "Поддержка настенного ящика с Open API",
23
+ "pt": "Suporte wallbox com API aberta",
24
+ "nl": "Steun muur met open API",
25
+ "fr": "Porte-monnaie support avec Open API",
26
+ "it": "Supporto wallbox con Open API",
27
+ "es": "Soporte de pared con Open API",
28
+ "pl": "Współdzielnia z API Open",
29
+ "uk": "Підтримка настінної коробки з відкритим API",
30
+ "zh-cn": "A. 开放式API的支助墙箱"
31
+ },
6
32
  "1.2.1": {
7
33
  "en": "Fixed severe error in ClosedAPI",
8
34
  "de": "Schweren Fehler in ClosedAPI behoben",
@@ -67,32 +93,6 @@
67
93
  "pl": "Wymagana wersja węzła do 16 lub nowa",
68
94
  "uk": "Оновлено необхідну версію вершини до 16 або нових",
69
95
  "zh-cn": "A. 最新要求的无误版本到16个或新成员"
70
- },
71
- "1.0.1": {
72
- "en": "Adapted fetching energy values using 'Closed API' to latest API changes by Alpha-ESS",
73
- "de": "Closed API: Energiewerte an neueste API-Änderungen von Alpha-ESS angepasst",
74
- "ru": "Адаптированные выкачивание энергетических ценностей с помощью 'Closed API' для последних изменений API от Alpha-ESS",
75
- "pt": "Valores de energia de busca adaptados usando ' API fechada' para as últimas alterações de API por Alpha-ESS",
76
- "nl": "API verandert door Alpha-ESSS",
77
- "fr": "Récupération des valeurs d'énergie à l'aide de 'API fermée' aux dernières modifications de l'API par Alpha-ESS",
78
- "it": "Adattato l'ottenimento di valori energetici utilizzando 'API archiviate' alle ultime modifiche API di Alpha-ESS",
79
- "es": "Valores de energía adaptados de búsqueda usando 'Closed API' para los últimos cambios de API por Alpha-ESS",
80
- "pl": "Adapted fetching energy values używając 'Closed API' do najnowszych zmian API przez Alpha-ESS",
81
- "uk": "Адаптивовані коефіцієнти відтікання енергії за допомогою 'Closed API' для останніх змін API від Alpha-ESS",
82
- "zh-cn": "利用“无能”的能源价值降低到Alpha-ESS新生动的改变"
83
- },
84
- "1.0.0": {
85
- "en": "Support also the new official OpenAPI provided by Alpha-ESS\nSet state quality accordingly to status of data\nWriting charging and discharging settings implemented for 'Closed API' and OpenAPI\nRemove no more supported states at startup automatically",
86
- "de": "Unterstützung der neuen offiziellen OpenAPI von Alpha-ESS\nQuality von States wird jetzt entsprechend des Zustands der Daten gesetzt\nSchreiben von Lade- und Entladeeinstellungen für 'Closed API' und OpenAPI implementiert\nNicht mehr unterstützte States werden bei Adapter-Neustart automatisch gelöscht",
87
- "ru": "Поддержка также новый официальный OpenAPI, предоставленный Alpha-ESS\nУстановите государственное качество в соответствии с статусом данных\nНаписание зарядки и разгрузки настроек, реализованных для 'Closed API' и OpenAPI\nУдалить больше не поддерживаемых состояний при запуске автоматически",
88
- "pt": "Suporte também o novo OpenAPI oficial fornecido pela Alpha-ESS\nDefina a qualidade do estado de acordo com o status dos dados\nEscrevendo as configurações de carregamento e descarregamento implementadas para ' API fechada' e OpenAPI\nRemover estados não mais suportados na inicialização automaticamente",
89
- "nl": "Vertaling:\nZet de staatskwaliteit in aanmerking van gegevens\nSchrijven en ontladen opstellingen voor 'Closed API' en OpenAPI'\nVerwijder geen ondersteunende staten bij start-up automatisch",
90
- "fr": "Soutien également le nouveau OpenAPI officiel fourni par Alpha-ESS\nDéfinir la qualité de l'état en conséquence à l'état des données\nRédaction des paramètres de chargement et de déchargement mis en œuvre pour 'API perdu' et OpenAPI\nEnlever plus d'états supportés au démarrage automatiquement",
91
- "it": "Supporto anche il nuovo OpenAPI ufficiale fornito da Alpha-ESS\nImpostare la qualità dello stato di conseguenza allo stato dei dati\nScrivere le impostazioni di ricarica e discarica implementate per 'Closed API' e OpenAPI\nNon rimuovere più stati supportati all'avvio automaticamente",
92
- "es": "Apoyar también el nuevo OpenAPI oficial proporcionado por Alpha-ESS\nEstablecer la calidad del estado en consecuencia al estado de los datos\nEscribir ajustes de carga y descarga implementados para 'Closed API' y OpenAPI\nEliminar no más estados compatibles en el inicio automáticamente",
93
- "pl": "Wspiera również nowy oficjalny interfejs OpenAPI zapewniany przez Alpha-ESS\nUstalono jakość państwa zgodnie z statusem danych\nPisanie ładowania i rozładowania wdrożonych ustawień API oraz OpenAPI\nRemove nie będzie więcej wspieranych państw",
94
- "uk": "Підтримка також нових офіційних OpenAPI, що надається Альфа-ESS\nВстановити якість держави відповідно до стану даних\nНаписання параметрів зарядки та відключення, що реалізовані для \"Closed API\" та OpenAPI\nВидаліть не більше підтримуваних держав при запуску автоматично",
95
- "zh-cn": "还支持阿尔法-萨斯新官方开放协会\n相应地确定数据状况的国家质量\n确定和履行执行的消费和开放的消费者协会和开放协会环境\n自动取消不再支持的开办国家"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -182,6 +182,8 @@
182
182
  "intervalStatisticalTodaydataMins": 5,
183
183
  "enableSummarydata": false,
184
184
  "intervalSummarydataMins": 5,
185
+ "enableWallbox": false,
186
+ "intervalWallboxMins": 5,
185
187
  "updateUnchangedStates": false,
186
188
  "appID": "",
187
189
  "appSecret": "",
@@ -199,7 +201,9 @@
199
201
  "oAEnableStatisticsToday": false,
200
202
  "oAIntervalStatisticsTodayMins": 5,
201
203
  "oAEnableSummary": true,
202
- "oAIntervalSummaryMins": 5
204
+ "oAIntervalSummaryMins": 5,
205
+ "oAEnableWallbox": false,
206
+ "oAIntervalWallboxMins": 5
203
207
  },
204
208
  "objects": [],
205
209
  "instanceObjects": [
package/main.js CHANGED
@@ -17,7 +17,6 @@ const CA_AUTHSUFFIX = 'ui893ed';
17
17
  const CA_BaseURI = 'https://www.alphaess-cloud.com/';
18
18
  const OA_BaseURI = 'https://openapi.alphaess.com/api';
19
19
 
20
- const WriteTimeoutIntervalInS = 5;
21
20
  const ReadAfterWriteTimeoutIntervalInS = 2;
22
21
 
23
22
  const REQUEST_TIMEOUT = 10000;
@@ -305,6 +304,7 @@ class OpenAPI {
305
304
  Group: 'Settings_Charge'
306
305
  , fnct: this.getChargeConfigInfo.bind(this)
307
306
  , writeFnct: this.writeConfigInfo.bind(this)
307
+ , writeTimeoutIntervalInS: 5
308
308
  , requestName: 'updateChargeConfigInfo'
309
309
  , enabledName: 'oAEnableSettingsCharge'
310
310
  , intervalName: 'oAIntervalSettingsChargeMins'
@@ -369,6 +369,7 @@ class OpenAPI {
369
369
  Group: 'Settings_Discharge'
370
370
  , fnct: this.getDisChargeConfigInfo.bind(this)
371
371
  , writeFnct: this.writeConfigInfo.bind(this)
372
+ , writeTimeoutIntervalInS: 5
372
373
  , requestName: 'updateDisChargeConfigInfo'
373
374
  , enabledName: 'oAEnableSettingsDischarge'
374
375
  , intervalName: 'oAIntervalSettingsDischargeMins'
@@ -558,7 +559,79 @@ class OpenAPI {
558
559
  , type: 'number'
559
560
  , unit: 'kWh'
560
561
  }]
562
+ },
563
+ {
564
+ Group: 'Wallbox'
565
+ , fnct: this.getWallboxData.bind(this)
566
+ , writeFnct: this.writeWallboxChargerControl.bind(this)
567
+ , writeTimeoutIntervalInS: 0
568
+ , requestName: 'remoteControlEvCharger'
569
+ , enabledName: 'oAEnableWallbox'
570
+ , intervalName: 'oAIntervalWallboxMins'
571
+ , intervalFactor: 60
572
+ , states: [
573
+ {
574
+ alphaAttrName: 'evchargerSn'
575
+ , role: 'value'
576
+ , id: 'SN'
577
+ , name: 'Wallbox serial number'
578
+ , type: 'string'
579
+ , unit: ''
580
+ , isStatic: true
581
+ },
582
+ {
583
+ alphaAttrName: 'evchargerModel'
584
+ , role: 'value'
585
+ , id: 'Model'
586
+ , name: 'Wallbox model'
587
+ , type: 'string'
588
+ , unit: ''
589
+ , isStatic: true
590
+ },
591
+ {
592
+ alphaAttrName: 'remoteControlEvChargerStart'
593
+ , role: 'button.start'
594
+ , id: 'Charging_Start'
595
+ , name: 'Charging Start'
596
+ , type: 'boolean'
597
+ , unit: ''
598
+ , isStatic: true
599
+ , writeable: true
600
+ , readable: false
601
+ },
602
+ {
603
+ alphaAttrName: 'remoteControlEvChargerStop'
604
+ , role: 'button.stop'
605
+ , id: 'Charging_Stop'
606
+ , name: 'Charging Stop'
607
+ , type: 'boolean'
608
+ , unit: ''
609
+ , isStatic: true
610
+ , writeable: true
611
+ , readable: false
612
+ },
613
+ {
614
+ alphaAttrName: 'evchargerStatus'
615
+ , role: 'value'
616
+ , id: 'Status'
617
+ , name: 'Wallbox status'
618
+ , type: 'number'
619
+ , unit: ''
620
+ , states: {
621
+ 0: '0 - Unknown',
622
+ 1: '1 - Available state (not plugged in)',
623
+ 2: '2 - Preparing state of insertion (plugged in and not activated)',
624
+ 3: '3 - Charging state (charging with power output)',
625
+ 4: '4 - SuspendedEVSE pile Suspended at the terminal (already started but no available power)',
626
+ 5: '5 - SuspendedEV Suspended at the vehicle end (with available power, waiting for the car to respond)',
627
+ 6: '6 - Finishing The charging end state (actively swiping the card to stop or EMS stop control)',
628
+ 7: '7 - Unknown',
629
+ 8: '8 - Unknown',
630
+ 9: '9 - Faulted fault state (pile failure)'
631
+ }
632
+ }]
561
633
  }];
634
+
562
635
  this.adapter = adapter;
563
636
  this.emptyBody = { data: null };
564
637
  }
@@ -648,7 +721,7 @@ class OpenAPI {
648
721
  }
649
722
  }
650
723
  catch (e) {
651
- this.adapter.log.error('Reading data for group ' + group + ': Exception occurred: ' + e);
724
+ this.adapter.log.error('Fetching data for group ' + group + ': Exception occurred: ' + e);
652
725
  await this.handleError(this.emptyBody, group);
653
726
  }
654
727
  await this.startGroupTimeout(group);
@@ -674,7 +747,7 @@ class OpenAPI {
674
747
  }
675
748
  }
676
749
  catch (e) {
677
- this.adapter.log.error('Reading data for group ' + group + ': Exception occurred: ' + e);
750
+ this.adapter.log.error('Fetching data for group ' + group + ': Exception occurred: ' + e);
678
751
  await this.handleError(this.emptyBody, group);
679
752
  }
680
753
  await this.startGroupTimeout(group);
@@ -712,7 +785,7 @@ class OpenAPI {
712
785
  }
713
786
  }
714
787
  catch (e) {
715
- this.adapter.log.error('Reading data for group ' + group + ': Exception occurred: ' + e);
788
+ this.adapter.log.error('Fetching data for group ' + group + ': Exception occurred: ' + e);
716
789
  await this.handleError(this.emptyBody, group);
717
790
  }
718
791
  await this.startGroupTimeout(group);
@@ -736,7 +809,7 @@ class OpenAPI {
736
809
  }
737
810
  }
738
811
  catch (e) {
739
- this.adapter.log.error('Reading data for group ' + group + ': Exception occurred: ' + e);
812
+ this.adapter.log.error('Fetching data for group ' + group + ': Exception occurred: ' + e);
740
813
  await this.handleError(this.emptyBody, group);
741
814
  }
742
815
  await this.startGroupTimeout(group);
@@ -762,7 +835,45 @@ class OpenAPI {
762
835
  }
763
836
  }
764
837
  catch (e) {
765
- this.adapter.log.error('Reading data for group ' + group + ': Exception occurred: ' + e);
838
+ this.adapter.log.error('Fetching data for group ' + group + ': Exception occurred: ' + e);
839
+ await this.handleError(this.emptyBody, group);
840
+ }
841
+ await this.startGroupTimeout(group);
842
+ }
843
+
844
+ /**
845
+ * @param {string} group
846
+ */
847
+ async getWallboxData(group) {
848
+ try {
849
+ this.adapter.stopGroupTimeout(group);
850
+
851
+ this.adapter.log.debug('Fetching ' + group + ' data...');
852
+ // First we need to get SN if not already done:
853
+ let snState = await this.adapter.getStateAsync(`${group}.SN`);
854
+ if (!snState || typeof snState.val === 'string' && snState.val.length == 0) {
855
+ await this.getWallboxSn(group);
856
+ snState = await this.adapter.getStateAsync(`${group}.SN`);
857
+ // In this special case we reset the created indicator because more states must be created for this group in the next step
858
+ this.adapter.createdStates[group] = false;
859
+ }
860
+
861
+ if (snState && typeof snState.val === 'string' && snState.val.length > 0) {
862
+ this.adapter.log.debug(`Using Wallbox SN: ${snState.val}`);
863
+ const res = await this.getRequest(`getEvChargerStatusBySn?sysSn=${this.adapter.config.systemId}&evchargerSn=${snState.val}`, {});
864
+ if (res && res['status'] == 200 && res.data && res.data.data) {
865
+ await this.adapter.createAndUpdateStates(group, res.data.data);
866
+ }
867
+ else {
868
+ await this.handleError(res, group);
869
+ }
870
+ }
871
+ else {
872
+ this.adapter.log.error('No wallbox SN could be found!');
873
+ }
874
+ }
875
+ catch (e) {
876
+ this.adapter.log.error('Fetching data for group ' + group + ': Exception occurred: ' + e);
766
877
  await this.handleError(this.emptyBody, group);
767
878
  }
768
879
  await this.startGroupTimeout(group);
@@ -771,7 +882,32 @@ class OpenAPI {
771
882
  /**
772
883
  * @param {string} group
773
884
  */
774
- async writeConfigInfo(group) {
885
+ async getWallboxSn(group) {
886
+ try {
887
+ this.adapter.log.debug('Fetching Wallbox SN ...');
888
+
889
+ const res = await this.getRequest(`getEvChargerConfigList?sysSn=${this.adapter.config.systemId}`, {});
890
+ if (res && res['status'] == 200 && res.data && res.data.data) {
891
+
892
+ if (res.data.data.length > 1) {
893
+ this.adapter.log.warn('More than one wallbox found! Only the first wallbox is currently supported by this adapter!');
894
+ }
895
+ await this.adapter.createAndUpdateStates(group, res.data.data[0]);
896
+ }
897
+ else {
898
+ await this.handleError(res, group);
899
+ }
900
+ }
901
+ catch (e) {
902
+ this.adapter.log.error('Fetching Wallbox SN: Exception occurred: ' + e);
903
+ await this.handleError(this.emptyBody, group);
904
+ }
905
+ }
906
+
907
+ /**
908
+ * @param {string} group
909
+ */
910
+ async writeConfigInfo(group, _updState, _updStateInfo) {
775
911
  const nextReadTimeout = ReadAfterWriteTimeoutIntervalInS;
776
912
  try {
777
913
  this.adapter.stopGroupWriteTimeout(group);
@@ -820,6 +956,60 @@ class OpenAPI {
820
956
  this.adapter.startGroupTimeout(nextReadTimeout, group);
821
957
  }
822
958
 
959
+ /**
960
+ * @param {string} group
961
+ * @param {ioBroker.State} updState
962
+ * @param {any} updStateInfo
963
+ */
964
+ async writeWallboxChargerControl(group, updState, updStateInfo) {
965
+ try {
966
+ this.adapter.stopGroupWriteTimeout(group);
967
+ this.adapter.stopGroupTimeout(group);
968
+
969
+ this.adapter.log.debug('Writing ' + group + ' data...');
970
+
971
+ const gidx = this.stateInfoList.findIndex((/** @type {{ Group: string; }} */ i) => i.Group == group);
972
+ if (gidx >= 0) {
973
+
974
+ const chargerSnState = await this.adapter.getStateAsync(group + '.SN');
975
+
976
+ if (chargerSnState) {
977
+ this.adapter.log.debug(`Using Wallbox SN: ${chargerSnState.val}`);
978
+
979
+ const body = {};
980
+
981
+ if (updStateInfo.role == 'button.start') {
982
+ body['controlMode'] = 1;
983
+ }
984
+ else {
985
+ body['controlMode'] = 0;
986
+ }
987
+
988
+ body['sysSn'] = this.adapter.config.systemId;
989
+ body['evchargerSn'] = chargerSnState.val;
990
+
991
+ this.adapter.log.debug(`Write group ${group}: ${JSON.stringify(body)}`);
992
+
993
+ const res = await this.postRequest(this.adapter.getStateInfoList()[gidx].requestName, body, {});
994
+ if (res && res['status'] == 200 && res.data) {
995
+ this.adapter.log.info('Written values fror group ' + group);
996
+ }
997
+ else {
998
+ await this.handleError(res, group);
999
+ }
1000
+ }
1001
+ else {
1002
+ this.adapter.log.error('State ' + group + '.evchargerSn not found!');
1003
+ }
1004
+ }
1005
+ }
1006
+ catch (e) {
1007
+ this.adapter.log.error('Writing data for group ' + group + ': Exception occurred: ' + e);
1008
+ await this.handleError(this.emptyBody, group);
1009
+ }
1010
+ this.adapter.startGroupTimeout(ReadAfterWriteTimeoutIntervalInS, group);
1011
+ }
1012
+
823
1013
  /**
824
1014
  * @param {string} group
825
1015
  */
@@ -848,24 +1038,28 @@ class OpenAPI {
848
1038
  await this.adapter.setStateChangedAsync('info.connection', false, true);
849
1039
  this.adapter.errorCount++;
850
1040
  if (res.data && res.data.code && res.data.code != 0) {
851
- this.adapter.log.error('Alpha ESS Api returns an error!');
1041
+ this.adapter.log.error(`Alpha ESS Api returns an error! Group: ${group}`);
852
1042
  switch (res.data.code) {
853
- case 6001: this.adapter.log.error(`Error: ${res.data.code} - Parameter error (#${this.adapter.errorCount})`); break;
854
- case 6002: this.adapter.log.error(`Error: ${res.data.code} - The SN is not bound to the user (#${this.adapter.errorCount})`); break;
855
- case 6003: this.adapter.log.error(`Error: ${res.data.code} - You have bound this SN (#${this.adapter.errorCount})`); break;
856
- case 6004: this.adapter.log.error(`Error: ${res.data.code} - CheckCode error (#${this.adapter.errorCount})`); break;
857
- case 6005: this.adapter.log.error(`Error: ${res.data.code} - This appId is not bound to the SN (#${this.adapter.errorCount})`); break;
858
- case 6006: this.adapter.log.error(`Error: ${res.data.code} - Timestamp error (#${this.adapter.errorCount})`); break;
859
- case 6007: this.adapter.log.error(`Error: ${res.data.code} - Sign verification error (#${this.adapter.errorCount})`); break;
860
- case 6008: this.adapter.log.error(`Error: ${res.data.code} - Set failed (#${this.adapter.errorCount})`); break;
861
- case 6009: this.adapter.log.error(`Error: ${res.data.code} - Whitelist verification failed (#${this.adapter.errorCount})`); break;
862
- case 6010: this.adapter.log.error(`Error: ${res.data.code} - Sign is empty (#${this.adapter.errorCount})`); break;
863
- case 6011: this.adapter.log.error(`Error: ${res.data.code} - timestamp is empty (#${this.adapter.errorCount})`); break;
864
- case 6012: this.adapter.log.error(`Error: ${res.data.code} - AppId is empty (#${this.adapter.errorCount})`); break;
865
- case 6026: this.adapter.log.error(`Error: ${res.data.code} - Internal Error (#${this.adapter.errorCount})`); break;
866
- case 6046: this.adapter.log.error(`Error: ${res.data.code} - Verification code error (#${this.adapter.errorCount})`); break;
867
- case 6053: this.adapter.log.error(`Error: ${res.data.code} - The request was too fast, please try again later (#${this.adapter.errorCount})`); break;
868
- default: this.adapter.log.error(`Error: ${res.data.code} - Unknown error (#${this.adapter.errorCount})`);
1043
+ case 6001: this.adapter.log.info(`Error code: ${res.data.code} - Parameter error (#${this.adapter.errorCount})`); break;
1044
+ case 6002: this.adapter.log.info(`Error code: ${res.data.code} - The SN is not bound to the user (#${this.adapter.errorCount})`); break;
1045
+ case 6003: this.adapter.log.info(`Error code: ${res.data.code} - You have bound this SN (#${this.adapter.errorCount})`); break;
1046
+ case 6004: this.adapter.log.info(`Error code: ${res.data.code} - CheckCode error (#${this.adapter.errorCount})`); break;
1047
+ case 6005: this.adapter.log.info(`Error code: ${res.data.code} - This appId is not bound to the SN (#${this.adapter.errorCount})`); break;
1048
+ case 6006: this.adapter.log.info(`Error code: ${res.data.code} - Timestamp error (#${this.adapter.errorCount})`); break;
1049
+ case 6007: this.adapter.log.info(`Error code: ${res.data.code} - Sign verification error (#${this.adapter.errorCount})`); break;
1050
+ case 6008: this.adapter.log.info(`Error code: ${res.data.code} - Set failed (#${this.adapter.errorCount})`); break;
1051
+ case 6009: this.adapter.log.info(`Error code: ${res.data.code} - Whitelist verification failed (#${this.adapter.errorCount})`); break;
1052
+ case 6010: this.adapter.log.info(`Error code: ${res.data.code} - Sign is empty (#${this.adapter.errorCount})`); break;
1053
+ case 6011: this.adapter.log.info(`Error code: ${res.data.code} - timestamp is empty (#${this.adapter.errorCount})`); break;
1054
+ case 6012: this.adapter.log.info(`Error code: ${res.data.code} - AppId is empty (#${this.adapter.errorCount})`); break;
1055
+ case 6016: this.adapter.log.info(`Error code: ${res.data.code} - Data does not exist or has been deleted (#${this.adapter.errorCount})`); break;
1056
+ case 6026: this.adapter.log.info(`Error code: ${res.data.code} - Internal Error (#${this.adapter.errorCount})`); break;
1057
+ case 6029: this.adapter.log.info(`Error code: ${res.data.code} - operation failed (#${this.adapter.errorCount})`); break;
1058
+ case 6038: this.adapter.log.info(`Error code: ${res.data.code} - system sn does not exist (#${this.adapter.errorCount})`); break;
1059
+ case 6042: this.adapter.log.info(`Error code: ${res.data.code} - system offline (#${this.adapter.errorCount})`); break;
1060
+ case 6046: this.adapter.log.info(`Error code: ${res.data.code} - Verification code error (#${this.adapter.errorCount})`); break;
1061
+ case 6053: this.adapter.log.info(`Error code: ${res.data.code} - The request was too fast, please try again later (#${this.adapter.errorCount})`); break;
1062
+ default: this.adapter.log.info(`Error code: ${res.data.code} - Unknown error (#${this.adapter.errorCount})`);
869
1063
  }
870
1064
  if (res.data.code == 6002 ||
871
1065
  res.data.code == 6003 ||
@@ -880,7 +1074,7 @@ class OpenAPI {
880
1074
  }
881
1075
  }
882
1076
  else {
883
- this.adapter.log.error(`Unknown error occurred: ${JSON.stringify(res.data)} (#${this.adapter.errorCount})`);
1077
+ this.adapter.log.error(`Unknown error occurred: ${JSON.stringify(res.data)} (#${this.adapter.errorCount}) Group:${group}`);
884
1078
  }
885
1079
  await this.adapter.setQualityForGroup(group, 0x44);
886
1080
  }
@@ -1059,6 +1253,7 @@ class ClosedAPI {
1059
1253
  Group: 'Settings'
1060
1254
  , fnct: this.fetchSettingsData.bind(this)
1061
1255
  , writeFnct: this.writeSettingsData.bind(this)
1256
+ , writeTimeoutIntervalInS: 5
1062
1257
  , enabledName: 'enableSettingsdata'
1063
1258
  , intervalName: 'intervalSettingsdataMins'
1064
1259
  , intervalFactor: 60
@@ -1521,6 +1716,15 @@ class ClosedAPI {
1521
1716
  , unit: ''
1522
1717
  , dayIndex: false
1523
1718
  }]
1719
+ },
1720
+ {
1721
+ // Just a dummy to ensure that this group is deleted
1722
+ Group: 'Wallbox'
1723
+ , fnct: this.fetchWallboxDataDummy.bind(this)
1724
+ , enabledName: 'enableWallbox'
1725
+ , intervalName: 'intervalWallboxMins'
1726
+ , intervalFactor: 60
1727
+ , states: []
1524
1728
  }];
1525
1729
 
1526
1730
  this.Auth =
@@ -1796,6 +2000,13 @@ class ClosedAPI {
1796
2000
  this.adapter.log.warn(`Internal error (group ${group}): function fetchSettingsDischargeDataDummy should never be called.`);
1797
2001
  }
1798
2002
 
2003
+ /**
2004
+ * @param {string} group
2005
+ */
2006
+ async fetchWallboxDataDummy(group) {
2007
+ this.adapter.log.warn(`Internal error (group ${group}): function fetchWallboxDataDummy should never be called.`);
2008
+ }
2009
+
1799
2010
  /**
1800
2011
  * Get realtime data from alpha-ess and start timer for next execution
1801
2012
  * @param {string} group
@@ -1916,7 +2127,7 @@ class ClosedAPI {
1916
2127
  /**
1917
2128
  * @param {string} group
1918
2129
  */
1919
- async writeSettingsData(group) {
2130
+ async writeSettingsData(group, _updState, _updStateInfo) {
1920
2131
  try {
1921
2132
  this.adapter.stopGroupWriteTimeout(group);
1922
2133
  this.adapter.stopGroupTimeout(group);
@@ -2072,12 +2283,14 @@ class AlphaEss extends utils.Adapter {
2072
2283
  this.log.debug('config oAIntervalSettingsChargeMins ' + this.config.oAIntervalSettingsChargeMins);
2073
2284
  this.log.debug('config oAIntervalSettingsDischargeMins ' + this.config.oAIntervalSettingsDischargeMins);
2074
2285
  this.log.debug('config oAIntervalSummaryMins: ' + this.config.oAIntervalSummaryMins);
2075
- this.log.debug('config enableRealtimedata: ' + this.config.oAEnableRealtime);
2076
- this.log.debug('config enableEnergydata: ' + this.config.oAEnableEnergy);
2077
- this.log.debug('config enableSettingsdata: ' + this.config.oAEnableSettingsCharge);
2078
- this.log.debug('config enableStatisticalTodaydata: ' + this.config.oAEnableSettingsDischarge);
2079
- this.log.debug('config enableSummarydata: ' + this.config.oAEnableSettingsDischarge);
2080
- this.log.debug('config enableSummarydata: ' + this.config.oAEnableSummary);
2286
+ this.log.debug('config oAIntervalWallboxMins: ' + this.config.oAIntervalWallboxMins);
2287
+ this.log.debug('config oAEnableRealtime: ' + this.config.oAEnableRealtime);
2288
+ this.log.debug('config oAEnableEnergy: ' + this.config.oAEnableEnergy);
2289
+ this.log.debug('config oAEnableSettingsCharge: ' + this.config.oAEnableSettingsCharge);
2290
+ this.log.debug('config oAEnableSettingsCharge: ' + this.config.oAEnableSettingsCharge);
2291
+ this.log.debug('config oAEnableSettingsDischarge: ' + this.config.oAEnableSettingsDischarge);
2292
+ this.log.debug('config oAEnableSummary: ' + this.config.oAEnableSummary);
2293
+ this.log.debug('config oAEnableWallbox: ' + this.config.oAEnableWallbox);
2081
2294
  this.log.debug('config updateUnchangedStates: ' + this.config.updateUnchangedStates);
2082
2295
  }
2083
2296
 
@@ -2203,7 +2416,12 @@ class AlphaEss extends utils.Adapter {
2203
2416
 
2204
2417
  this.verifyValue(state.val, group, stateInfo);
2205
2418
 
2206
- this.startGroupWriteTimeout(WriteTimeoutIntervalInS, group);
2419
+ const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == group);
2420
+
2421
+ if (gidx >= 0) {
2422
+ const writeTimeOut = this.getStateInfoList()[gidx].writeTimeoutIntervalInS;
2423
+ this.startGroupWriteTimeout(writeTimeOut ? writeTimeOut : 0, group, state, stateInfo);
2424
+ }
2207
2425
  }
2208
2426
  else {
2209
2427
  this.log.debug(`Validation already in progress: ${id}`);
@@ -2338,15 +2556,17 @@ class AlphaEss extends utils.Adapter {
2338
2556
  * Start a timer for a given group
2339
2557
  * @param {number} intervalInS
2340
2558
  * @param {string} group
2559
+ * @param {ioBroker.State} updState
2560
+ * @param {{ alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; dayIndex?: undefined; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; dayIndex: boolean; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; writeable: boolean; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; round: number; factor?: undefined; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; factor: number; round: number; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; round?: undefined; factor?: undefined; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; isStatic: boolean; writeable?: undefined; readable?: undefined; states?: undefined; } | { alphaAttrName: string; role: string; id: string; name: string; type: string; unit: string; states: { 0: string; 1: string; 2: string; 3: string; 4: string; 5: string; 6: string; 7: string; 8: string; 9: string; }; isStatic?: undefined; writeable?: undefined; readable?: undefined; }} updStateInfo
2341
2561
  */
2342
- startGroupWriteTimeout(intervalInS, group) {
2562
+ startGroupWriteTimeout(intervalInS, group, updState, updStateInfo) {
2343
2563
  const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == group);
2344
2564
  if (!this.getStateInfoList()[gidx].writeTimeoutHandle) {
2345
2565
  const interval = intervalInS * 1000;
2346
2566
  this.log.debug('Write Timeout with interval ' + interval + ' ms started for group ' + group);
2347
2567
  const wf = this.getStateInfoList()[gidx].writeFnct;
2348
2568
  if (wf) {
2349
- this.getStateInfoList()[gidx].writeTimeoutHandle = this.setTimeout(() => { wf(group); }, interval);
2569
+ this.getStateInfoList()[gidx].writeTimeoutHandle = this.setTimeout(() => { wf(group, updState, updStateInfo); }, interval);
2350
2570
  }
2351
2571
  }
2352
2572
  }
@@ -2378,10 +2598,11 @@ class AlphaEss extends utils.Adapter {
2378
2598
  /**
2379
2599
  * Create states when called the first time, update state values in each call
2380
2600
  * @param {string} group
2381
- * @param {{ [s: string]: any; }} data
2601
+ * @param {{ [s: string]: any; } | null} data
2382
2602
  */
2383
2603
  async createAndUpdateStates(group, data) {
2384
2604
  try {
2605
+
2385
2606
  if (data) {
2386
2607
  await this.setStateChangedAsync('info.connection', true, true);
2387
2608
  this.errorCount = 0;
@@ -2390,6 +2611,8 @@ class AlphaEss extends utils.Adapter {
2390
2611
 
2391
2612
  if (!this.createdStates[group]) {
2392
2613
 
2614
+ const setObjectFunc = await this.isMigrationNecessary() ? this.setObjectMigrationAsync : this.setObjectNormalAsync;
2615
+
2393
2616
  // Delete no longer supported states for this group
2394
2617
  const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == group);
2395
2618
  if (gidx >= 0) {
@@ -2405,8 +2628,6 @@ class AlphaEss extends utils.Adapter {
2405
2628
  }
2406
2629
  }
2407
2630
 
2408
- const setObjectFunc = await this.isMigrationNecessary() ? this.setObjectMigrationAsync : this.setObjectNormalAsync;
2409
-
2410
2631
  // Create the folder for this group
2411
2632
  await setObjectFunc(group, {
2412
2633
  type: 'folder',
@@ -2418,38 +2639,50 @@ class AlphaEss extends utils.Adapter {
2418
2639
  native: {}
2419
2640
  });
2420
2641
 
2642
+ // Create all static states:
2643
+ const groupStateList = this.getStateInfoList()[gidx].states;
2644
+ if (!this.createdStates[group]) {
2645
+ for (const stateInfo of groupStateList) {
2646
+ if (stateInfo.isStatic) {
2647
+ await this.createStateForAttribute(group, data, stateInfo.alphaAttrName, stateInfo, setObjectFunc);
2648
+
2649
+ }
2650
+ }
2651
+ }
2652
+
2421
2653
  // Create all states for received elements
2422
- for (const [alphaAttrName, rawValue] of Object.entries(data)) {
2423
- const stateInfo = this.getStateInfoByAlphaAttrName(group, alphaAttrName);
2654
+ for (const [alphaAttrName] of Object.entries(data)) {
2655
+ const stateInfo = await this.getStateInfoByAlphaAttrName(group, alphaAttrName);
2424
2656
  if (typeof data[alphaAttrName] !== 'object') {
2425
- this.createStateForAttribute(group, data, rawValue, alphaAttrName, stateInfo, setObjectFunc);
2657
+ await this.createStateForAttribute(group, data, alphaAttrName, stateInfo, setObjectFunc);
2426
2658
  }
2427
2659
  else {
2428
2660
  // Look for subvalues:
2429
2661
  if (data[alphaAttrName]) {
2430
- for (const [alphaAttrName2, rawValue2] of Object.entries(data[alphaAttrName])) {
2431
- const stateInfo2 = this.getStateInfoByAlphaAttrName(group, alphaAttrName2);
2432
- this.createStateForAttribute(group, data[alphaAttrName], rawValue2, alphaAttrName2, stateInfo2, setObjectFunc);
2662
+ for (const [alphaAttrName2] of Object.entries(data[alphaAttrName])) {
2663
+ const stateInfo2 = await this.getStateInfoByAlphaAttrName(group, alphaAttrName2);
2664
+ await this.createStateForAttribute(group, data[alphaAttrName], alphaAttrName2, stateInfo2, setObjectFunc);
2433
2665
  }
2434
2666
  }
2435
2667
  }
2436
2668
  }
2669
+
2437
2670
  this.log.info('Initialized states for : ' + group);
2438
2671
  this.createdStates[group] = true;
2439
2672
  }
2440
2673
 
2441
2674
  // Set values for received states
2442
2675
  for (const [alphaAttrName, rawValue] of Object.entries(data)) {
2443
- const stateInfo = this.getStateInfoByAlphaAttrName(group, alphaAttrName);
2676
+ const stateInfo = await this.getStateInfoByAlphaAttrName(group, alphaAttrName);
2444
2677
  if (typeof data[alphaAttrName] !== 'object') {
2445
- this.setValueForAttribute(group, rawValue, stateInfo, idx);
2678
+ await this.setValueForAttribute(group, rawValue, stateInfo, idx);
2446
2679
  }
2447
2680
  else {
2448
2681
  // Look for subvalues:
2449
2682
  if (data[alphaAttrName]) {
2450
2683
  for (const [alphaAttrName2, rawValue2] of Object.entries(data[alphaAttrName])) {
2451
- const stateInfo2 = this.getStateInfoByAlphaAttrName(group, alphaAttrName2);
2452
- this.setValueForAttribute(group, rawValue2, stateInfo2, idx);
2684
+ const stateInfo2 = await this.getStateInfoByAlphaAttrName(group, alphaAttrName2);
2685
+ await this.setValueForAttribute(group, rawValue2, stateInfo2, idx);
2453
2686
  }
2454
2687
  }
2455
2688
  }
@@ -2465,11 +2698,10 @@ class AlphaEss extends utils.Adapter {
2465
2698
  *
2466
2699
  * create the state for the received element
2467
2700
  * @param {string} group
2468
- * @param {{[x: string]: any;}} data
2469
- * @param {string} rawValue
2701
+ * @param {{[x: string]: any;} | null} data
2470
2702
  * @param {string} alphaAttrName
2471
2703
  */
2472
- async createStateForAttribute(group, data, rawValue, alphaAttrName, stateInfo, setObjectFunc) {
2704
+ async createStateForAttribute(group, data, alphaAttrName, stateInfo, setObjectFunc) {
2473
2705
  if (stateInfo) {
2474
2706
  // The type checker has a problem with type: stateInfo.type. I have no clue why.
2475
2707
  // All possible types are correct and valid. To get rid of the type checker error, we check for valid types:
@@ -2480,28 +2712,30 @@ class AlphaEss extends utils.Adapter {
2480
2712
  name: stateInfo.name + ' [' + stateInfo.alphaAttrName + ']'
2481
2713
  , type: stateInfo.type
2482
2714
  , role: stateInfo.role
2483
- , read: true
2715
+ , read: stateInfo.readable != null ? stateInfo.readable : true
2484
2716
  , write: stateInfo.writeable ? stateInfo.writeable : false
2485
- , unit: stateInfo.unit === '{money_type}' ? data['money_type'] : stateInfo.unit === '{moneyType}' ? data['moneyType'] : stateInfo.unit
2717
+ , unit: stateInfo.unit === '{money_type}' && data ? data['money_type'] : stateInfo.unit === '{moneyType}' && data ? data['moneyType'] : stateInfo.unit
2486
2718
  , desc: stateInfo.alphaAttrName
2719
+ , states: stateInfo.states
2487
2720
  },
2488
2721
  native: {},
2489
2722
  });
2723
+ this.log.debug('Created object ' + group + '.' + this.osn(stateInfo.alphaAttrName));
2490
2724
  if (stateInfo.writeable) {
2491
2725
  await this.subscribeStatesAsync(`${group}.${stateInfo.id}`);
2492
2726
  this.log.debug(`Subscribed State: ${group}.${stateInfo.id}`);
2493
2727
  }
2494
2728
  }
2495
2729
  else {
2496
- this.log.error('Internal error: Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue + ' because of invalid type definition!');
2730
+ this.log.error('Internal error: Skipped object ' + group + '.' + alphaAttrName + ' because of invalid type definition!');
2497
2731
  }
2498
2732
  }
2499
2733
  else {
2500
2734
  if (alphaAttrName == 'sysSn' || alphaAttrName == 'theDate') {
2501
- this.log.debug('Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue);
2735
+ this.log.debug('Skipped object ' + group + '.' + alphaAttrName);
2502
2736
  }
2503
2737
  else {
2504
- this.log.warn('Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue);
2738
+ this.log.warn('Skipped object ' + group + '.' + alphaAttrName);
2505
2739
  }
2506
2740
  }
2507
2741
  }
@@ -2561,7 +2795,7 @@ class AlphaEss extends utils.Adapter {
2561
2795
  * @param {string} Group
2562
2796
  * @param {string} alphaAttrName
2563
2797
  */
2564
- getStateInfoByAlphaAttrName(Group, alphaAttrName) {
2798
+ async getStateInfoByAlphaAttrName(Group, alphaAttrName) {
2565
2799
  try {
2566
2800
  const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == Group);
2567
2801
  if (gidx >= 0) {
@@ -2583,12 +2817,12 @@ class AlphaEss extends utils.Adapter {
2583
2817
 
2584
2818
  /**
2585
2819
  * Answer the state description object for a given group and id
2586
- * @param {string} Group
2820
+ * @param {string} group
2587
2821
  * @param {string} id
2588
2822
  */
2589
- getStateInfoById(Group, id) {
2823
+ getStateInfoById(group, id) {
2590
2824
  try {
2591
- const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == Group);
2825
+ const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == group);
2592
2826
  if (gidx >= 0) {
2593
2827
  const currentList = this.getStateInfoList()[gidx].states;
2594
2828
  const sidx = currentList.findIndex((/** @type {{ id: string; }} */ i) => i.id == id);
@@ -2600,7 +2834,7 @@ class AlphaEss extends utils.Adapter {
2600
2834
  }
2601
2835
  catch (e) {
2602
2836
  this.log.error('getStateInfo Exception occurred: ' + e);
2603
- this.log.info('Group: ' + Group);
2837
+ this.log.info('Group: ' + group);
2604
2838
  this.log.info('alphaAttrName: ' + id);
2605
2839
  return null;
2606
2840
  }
@@ -2613,16 +2847,29 @@ class AlphaEss extends utils.Adapter {
2613
2847
  */
2614
2848
  async setQualityForGroup(group, q) {
2615
2849
  try {
2616
- const states = await this.getStatesAsync(group + '.*');
2617
- for (const sid in states) {
2618
- const newState = states[sid];
2619
- if (newState.ack) {
2620
- newState.q = q;
2621
- this.log.debug(`Set state ${sid} to val: ${newState.val}; q: ${newState.q}; ack: ${newState.ack}`);
2622
- await this.setStateAsync(sid, newState, true);
2623
- }
2624
- else {
2625
- this.log.debug(`Set state ${sid} NOT to val: ${newState.val}; q: ${newState.q} because ack of this state is ${newState.ack}`);
2850
+ const gidx = this.getStateInfoList().findIndex((/** @type {{ Group: string; }} */ i) => i.Group == group);
2851
+ if (gidx >= 0) {
2852
+ const groupInfo = this.getStateInfoList()[gidx];
2853
+ const groupStates = groupInfo.states;
2854
+ for (let i = 0; i < groupStates.length; i++) {
2855
+ if (!groupStates[i].isStatic) {
2856
+ const newState = await this.getStateAsync(`${groupInfo.Group}.${groupStates[i].id}`);
2857
+ if (newState) {
2858
+ if (newState.q != q && newState.ack) {
2859
+ newState.q = q;
2860
+ this.log.debug(`Set state ${groupInfo.Group}.${groupStates[i].id} to val: ${newState.val}; q: ${newState.q}; ack: ${newState.ack}`);
2861
+ await this.setStateAsync(`${groupInfo.Group}.${groupStates[i].id}`, newState, true);
2862
+ }
2863
+ else {
2864
+ if (!newState.ack) {
2865
+ this.log.silly(`Set state ${groupInfo.Group}.${groupStates[i].id} NOT to val: ${newState.val}; q: ${newState.q} because ack of this state is ${newState.ack}`);
2866
+ }
2867
+ else {
2868
+ this.log.silly(`Set state ${groupInfo.Group}.${groupStates[i].id} NOT to val: ${newState.val}; q: ${newState.q} because quality is unchanged ${newState.q}`);
2869
+ }
2870
+ }
2871
+ }
2872
+ }
2626
2873
  }
2627
2874
  }
2628
2875
  }
@@ -2643,11 +2890,11 @@ class AlphaEss extends utils.Adapter {
2643
2890
  const groupInfo = this.getStateInfoList()[gidx];
2644
2891
  const groupStates = groupInfo.states;
2645
2892
  for (let i = 0; i < groupStates.length; i++) {
2646
- if (groupStates[i].lastUpdateTs) {
2893
+ if (groupStates[i].lastUpdateTs && !groupStates[i].isStatic) {
2647
2894
  if (Date.now() - groupStates[i].lastUpdateTs > (groupInfo.interval * 1000 + REQUEST_TIMEOUT)) {
2648
2895
  const newState = await this.getStateAsync(`${groupInfo.Group}.${groupStates[i].id}`);
2649
2896
  if (newState) {
2650
- if (newState.q != 0 && newState.ack) {
2897
+ if (newState.q == 0 && newState.ack) {
2651
2898
  // Change quality only if it was OK before
2652
2899
  newState.q = 0x01;
2653
2900
  this.log.warn(`Watchdog: State ${groupInfo.Group}.${groupStates[i].id} not updated for ${Date.now() - groupStates[i].lastUpdateTs} ms`);
@@ -2655,7 +2902,12 @@ class AlphaEss extends utils.Adapter {
2655
2902
  await this.setStateAsync(`${groupInfo.Group}.${groupStates[i].id}`, newState, true);
2656
2903
  }
2657
2904
  else {
2658
- this.log.silly(`Watchdog: Quality of state ${groupInfo.Group}.${groupStates[i].id} not changed, was already set to ${newState.q} and ack is ${newState.ack}!`);
2905
+ if (!newState.ack) {
2906
+ this.log.silly(`Set state ${groupInfo.Group}.${groupStates[i].id} NOT to val: ${newState.val}; q: ${newState.q} because ack of this state is ${newState.ack}`);
2907
+ }
2908
+ else {
2909
+ this.log.silly(`Set state ${groupInfo.Group}.${groupStates[i].id} NOT to val: ${newState.val}; q: ${newState.q} because quality is already not OK: ${newState.q}`);
2910
+ }
2659
2911
  }
2660
2912
  }
2661
2913
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.alpha-ess",
3
- "version": "1.2.1",
3
+ "version": "1.3.0-beta.1",
4
4
  "description": "Read and write data from and to Alpha ESS systems.",
5
5
  "author": {
6
6
  "name": "Gaspode",
@@ -46,7 +46,7 @@
46
46
  "mocha": "^10.2.0",
47
47
  "prettier": "^2.8.7",
48
48
  "proxyquire": "^2.1.3",
49
- "sinon": "^15.2.0",
49
+ "sinon": "^17.0.0",
50
50
  "sinon-chai": "^3.7.0",
51
51
  "typescript": "~5.2.2"
52
52
  },