iobroker.alpha-ess 0.3.0 → 0.5.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
@@ -37,6 +37,14 @@ The password is stored encrypted and must therefore be entered manually: demo
37
37
  **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.**
38
38
 
39
39
  ## Changelog
40
+ ### 0.5.0 (2023-03-05)
41
+ * (Gaspode) Remove no more supported states at startup automatically
42
+ * (Gaspode) Prepared data migration for future versions
43
+
44
+ ### 0.4.0 (2023-02-16)
45
+ * (Gaspode) Optimized deletion of group states
46
+ * (Gaspode) Added new Realtime state for pmeter_dc
47
+
40
48
  ### 0.3.0 (2023-02-11)
41
49
  * (Gaspode) Rearranged statistical data and added more values. Many thanks to [Thorsten](https://github.com/ThorstenBoettler) for his valuable contribution in testing the early alpha versions of this release and providing informative suggestions and recommendations for new data points.
42
50
  * (Gaspode) Added Summary data
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "alpha-ess",
4
- "version": "0.3.0",
4
+ "version": "0.5.0",
5
5
  "news": {
6
+ "0.5.0": {
7
+ "en": "Remove no more supported states at startup automatically\nPrepared data migration for future versions",
8
+ "de": "Entfernen Sie keine unterstützten Zustände beim Start automatisch\nVorbereitete Datenmigration für zukünftige Versionen",
9
+ "ru": "Удалить больше не поддерживаемых состояний при запуске автоматически\nПодготовленная миграция данных для будущих версий",
10
+ "pt": "Remover estados não mais suportados na inicialização automaticamente\nMigração de dados preparada para versões futuras",
11
+ "nl": "Verwijder geen ondersteunende staten bij start-up automatisch\nVertaling:",
12
+ "fr": "Enlever plus d'états supportés au démarrage automatiquement\nMigration de données préparée pour les versions futures",
13
+ "it": "Non rimuovere più stati supportati all'avvio automaticamente\nMigrazione dei dati preparata per le versioni future",
14
+ "es": "Eliminar no más estados compatibles en el inicio automáticamente\nMigración de datos preparada para futuras versiones",
15
+ "pl": "Remove nie będzie więcej wspieranych państw\nWstępna migracja danych do przyszłych wersji",
16
+ "uk": "Видаліть не більше підтримуваних держав при запуску автоматично\nПідготовка міграції даних для майбутніх версій",
17
+ "zh-cn": "自动取消不再支持的开办国家\n今后版本的准备数据迁移"
18
+ },
19
+ "0.4.0": {
20
+ "en": "Optimized deletion of group states\nAdded new Realtime state for pmeter_dc",
21
+ "de": "Optimiertes Löschen von Gruppenzuständen\nNeuer Realtime-Zustand für pmeter_dc hinzugefügt",
22
+ "ru": "Оптимизированное удаление групповых государств\nДобавлено новое состояние в режиме реального времени для pmeter_dc",
23
+ "pt": "Eliminação otimizada de estados de grupo\nAdicionado novo estado em tempo real para pmeter_dc",
24
+ "nl": "Optimaal deletie van de groepsstaat\nVoegde nieuwe Realtime staat toe voor begraafplaats",
25
+ "fr": "Suppression optimisée des états de groupe\nAjout d'un nouvel état en temps réel pour pmeter_dc",
26
+ "it": "Eliminazione ottimizzata degli stati di gruppo\nAggiunto nuovo stato in tempo reale per pmeter_dc",
27
+ "es": "Eliminación optimizada de estados de grupo\nNuevo estado en tiempo real añadido para pmeter_dc",
28
+ "pl": "Ostateczne delecje grupowych stanów\nNowy stan rzeczywisty",
29
+ "uk": "Оптимальне видалення групових станів\nДодано новий стан в режимі реального часу для pmeter_dc",
30
+ "zh-cn": "删除集团国家\n添加新实时状态"
31
+ },
6
32
  "0.3.0": {
7
33
  "en": "Rearranged statistical data and added more values. Many thanks to [Thorsten](https://github.com/ThorstenBoettler) for his valuable contribution in testing the early alpha versions of this release and providing informative suggestions and recommendations for new data points.\nAdded Summary data \nRefactored complete implementation\nChanged the unit of settings for all intervals, except of realtime data, to minutes (Caution: settings are reset to defaults)\nRemove disabled states at adapter startup\nRemoved no more supported value 'createtime' (state ID Realtime.Last_update). \nOptimized rounding for selected values",
8
34
  "de": "Rearrangierte statistische Daten und fügte weitere Werte hinzu. Vielen Dank an [Thorsten](https://github.com/ThorstenBoettler) für seinen wertvollen Beitrag bei der Prüfung der frühen Alpha-Versionen dieser Veröffentlichung und Bereitstellung informativer Vorschläge und Empfehlungen für neue Datenpunkte.\nZusammenfassung Daten\nRefactored complete Implementation\nÄnderte die Einheit der Einstellungen für alle Intervalle, mit Ausnahme von Echtzeitdaten, in Minuten (Vorsicht: Einstellungen werden auf Standardeinstellungen zurückgesetzt)\nEntfernen von deaktivierten Zuständen bei Adapter-Start\nKeine unterstützte Wert-Erstellung entfernt (state ID Realtime.Last_update).\nOptimierte Rundung für ausgewählte Werte",
@@ -67,32 +93,6 @@
67
93
  "pl": "Zmniejszenie żądań dotyczących trwałych błędów",
68
94
  "uk": "Повільні запити у разі постійних помилок",
69
95
  "zh-cn": "长期错误请求下降"
70
- },
71
- "0.0.6-beta.4": {
72
- "en": "Changed adapter type from metering to energy",
73
- "de": "Geänderter Adaptertyp von der Dosierung bis zur Energie",
74
- "ru": "Измененный тип адаптера от измерения до энергии",
75
- "pt": "Tipo de adaptador alterado de medição para energia",
76
- "nl": "Veranderde adapter type van meting naar energie",
77
- "fr": "Type d'adaptateur modifié de mesure à énergie",
78
- "it": "Tipo di adattatore modificato dalla misurazione all'energia",
79
- "es": "Tipo de adaptador cambiado de medición a energía",
80
- "pl": "Zmienił adapter typu z metrowania do energii",
81
- "uk": "Змінений тип адаптера від вимірювальної енергії",
82
- "zh-cn": "能源参数的变量"
83
- },
84
- "0.0.6-beta.3": {
85
- "en": "Correction for NPM",
86
- "de": "Korrektur für NPM",
87
- "ru": "Коррекция для NPM",
88
- "pt": "Correção para NPM",
89
- "nl": "Correctie voor NPM",
90
- "fr": "Correction pour les mécanismes nationaux de prévention",
91
- "it": "Correzione per NPM",
92
- "es": "Corrección para el mecanismo nacional de prevención",
93
- "pl": "Poprawka dla NPM",
94
- "uk": "Корекція для NPM",
95
- "zh-cn": "国家防范机制的纠正"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/main.js CHANGED
@@ -107,6 +107,15 @@ class AlphaEss extends utils.Adapter {
107
107
  , unit: 'W'
108
108
  , dayIndex: false
109
109
  }
110
+ , {
111
+ alphaAttrName: 'pmeter_dc'
112
+ , role: 'value.power'
113
+ , id: 'PV_meter_power'
114
+ , name: 'PV meter power'
115
+ , type: 'number'
116
+ , unit: 'W'
117
+ , dayIndex: false
118
+ }
110
119
  , {
111
120
  alphaAttrName: 'preal_l1'
112
121
  , role: 'value.power'
@@ -617,6 +626,9 @@ class AlphaEss extends utils.Adapter {
617
626
  RefreshToken: ''
618
627
  };
619
628
 
629
+ this.setObjectNormalAsync = this.setObjectNotExistsAsync.bind(this);
630
+ this.setObjectMigrationAsync = this.setObjectAsync.bind(this);
631
+
620
632
  this.createdStates = [];
621
633
 
622
634
  this.errorCount = 0;
@@ -649,24 +661,42 @@ class AlphaEss extends utils.Adapter {
649
661
  this.log.debug('config updateUnchangedStates: ' + this.config.updateUnchangedStates);
650
662
  this.wrongCredentials = false;
651
663
 
664
+ await this.setObjectNotExistsAsync('info.version', {
665
+ type: 'state',
666
+ common: {
667
+ name: 'Adapter Version'
668
+ , type: 'string'
669
+ , role: 'value'
670
+ , read: true
671
+ , write: false
672
+ },
673
+ native: {},
674
+ });
675
+
676
+ if (await this.isMigrationNecessary()) {
677
+ this.log.info('States will be migrated.');
678
+ }
679
+
652
680
  await this.resetAuth();
653
681
 
654
682
  if (this.config.password && this.config.username && this.config.systemId) {
655
683
 
656
684
  for (const gidx of Object.keys(this.stateInfoList)) {
657
- const group = this.stateInfoList[gidx];
658
- if (this.config[group.enabledName]) {
659
- await group.fnct(group.Group);
685
+ const groupInfo = this.stateInfoList[gidx];
686
+ if (this.config[groupInfo.enabledName]) {
687
+ await groupInfo.fnct(groupInfo.Group);
660
688
  }
661
689
  else {
662
- this.log.info(group.Group + ' data disabled! Adapter won\'t fetch ' + group.Group + ' data. According states deleted.');
663
- await this.deleteStatesForGroup(group.Group);
690
+ this.log.info(groupInfo.Group + ' data disabled! Adapter won\'t fetch ' + groupInfo.Group + ' data. According states deleted.');
691
+ await this.delObjectAsync(groupInfo.Group, { recursive: true });
664
692
  }
665
693
  }
666
694
  }
667
695
  else {
668
696
  this.log.error('No username, password and/or system ID set! Adapter won\'t fetch any data.');
669
697
  }
698
+
699
+ await this.setStateAsync('info.version', this.version, true);
670
700
  }
671
701
  catch (e) {
672
702
  this.log.error('onReady Exception occurred: ' + e);
@@ -700,41 +730,15 @@ class AlphaEss extends utils.Adapter {
700
730
  onStateChange(id, state) {
701
731
  if (state) {
702
732
  // The state was changed
703
- this.log.info(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
733
+ this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
704
734
  } else {
705
735
  // The state was deleted
706
- this.log.info(`state ${id} deleted`);
736
+ this.log.debug(`state ${id} deleted`);
707
737
  }
708
738
  }
709
739
 
710
740
  /**
711
- * Delete all states for a given group (async, so it can be used in a Promise)
712
- * @param {string} group
713
- */
714
- async deleteStatesForGroupAsync(group) {
715
- const states = await this.getStatesAsync(group + '.*');
716
- for (const id in states) {
717
- this.log.info(id + ': ' + JSON.stringify(states[id]));
718
- await this.delObjectAsync(id);
719
- }
720
- }
721
-
722
- /**
723
- * Delete all states for a given group
724
- * @param {string} group
725
- */
726
- deleteStatesForGroup(group) {
727
- return new Promise((resolve) => {
728
- this.deleteStatesForGroupAsync(group).then(() => {
729
- resolve(true);
730
- }).catch(e => {
731
- this.log.warn('Error: ' + e + '. Deletion of group ' + group + ' failed!');
732
- resolve(false);
733
- });
734
- });
735
- }
736
-
737
- /** Stop a timer for a given group
741
+ * Stop a timer for a given group
738
742
  *
739
743
  * @param {string} group
740
744
  */
@@ -978,21 +982,71 @@ class AlphaEss extends utils.Adapter {
978
982
  }
979
983
  }
980
984
 
985
+ /**
986
+ * Answer if the states shall be migrated, i.e. overwritten.
987
+ * This is called a view times at startup only.
988
+ */
989
+ async isMigrationNecessary() {
990
+ const oldVersionState = await this.getStateAsync('info.version');
991
+ if (oldVersionState) {
992
+ const oldVersion = '' + oldVersionState.val;
993
+ const vParts = oldVersion.split('.');
994
+ if (vParts.length >= 3) {
995
+ const major = Number.parseInt(vParts[0]);
996
+ const minor = Number.parseInt(vParts[1]);
997
+ if (major == 0 && minor > 4 || major > 0) {
998
+ return false;
999
+ }
1000
+ }
1001
+ }
1002
+ return true;
1003
+ }
1004
+
981
1005
  /**
982
1006
  * Create states when called the first time, update state values in each call
983
- * @param {string} groupName
1007
+ * @param {string} group
984
1008
  * @param {{ [s: string]: any; }} data
985
1009
  */
986
- async createAndUpdateStates(groupName, data) {
1010
+ async createAndUpdateStates(group, data) {
987
1011
  try {
988
1012
  if (data) {
989
1013
  const idx = new Date().getDate() - 1;
990
1014
 
991
- for (const [alphaAttrName, rawValue] of Object.entries(data)) {
992
- const stateInfo = this.getStateInfo(groupName, alphaAttrName);
993
- if (stateInfo) {
994
- if (!this.createdStates[groupName]) {
995
- await this.setObjectNotExistsAsync(groupName + '.' + this.osn(stateInfo.id), {
1015
+ if (!this.createdStates[group]) {
1016
+
1017
+ // Delete no longer supported states for this group
1018
+ const gidx = this.stateInfoList.findIndex(i => i.Group == group);
1019
+ if (gidx >= 0) {
1020
+ const groupStateList = this.stateInfoList[gidx].states;
1021
+ const states = await this.getStatesAsync(group + '.*');
1022
+ for (const sid in states) {
1023
+ const parts = sid.split('.');
1024
+ const id = parts[parts.length - 1];
1025
+ if (groupStateList.findIndex(i => i.id == id) == -1) {
1026
+ this.log.info('State ' + group + '.' + id + ' removed, no longer supported.');
1027
+ await this.delObjectAsync(group + '.' + id);
1028
+ }
1029
+ }
1030
+ }
1031
+
1032
+ const setObjectFunc = await this.isMigrationNecessary() ? this.setObjectMigrationAsync : this.setObjectNormalAsync;
1033
+
1034
+ // Create the folder for this group
1035
+ await setObjectFunc(group, {
1036
+ type: 'folder',
1037
+ common: {
1038
+ name: group
1039
+ , read: true
1040
+ , write: false
1041
+ },
1042
+ native: {}
1043
+ });
1044
+
1045
+ // Create all states for received elements
1046
+ for (const [alphaAttrName, rawValue] of Object.entries(data)) {
1047
+ const stateInfo = this.getStateInfo(group, alphaAttrName);
1048
+ if (stateInfo) {
1049
+ await setObjectFunc(group + '.' + this.osn(stateInfo.id), {
996
1050
  type: 'state',
997
1051
  common: {
998
1052
  name: stateInfo.name + ' [' + stateInfo.alphaAttrName + ']'
@@ -1007,6 +1061,18 @@ class AlphaEss extends utils.Adapter {
1007
1061
  native: {},
1008
1062
  });
1009
1063
  }
1064
+ else {
1065
+ this.log.debug('Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue);
1066
+ }
1067
+ }
1068
+ this.log.info('Initialized states for : ' + group);
1069
+ this.createdStates[group] = true;
1070
+ }
1071
+
1072
+ // Set values for received states
1073
+ for (const [alphaAttrName, rawValue] of Object.entries(data)) {
1074
+ const stateInfo = this.getStateInfo(group, alphaAttrName);
1075
+ if (stateInfo) {
1010
1076
  let value = '';
1011
1077
  if (stateInfo.dayIndex) {
1012
1078
  value = rawValue[idx];
@@ -1014,7 +1080,7 @@ class AlphaEss extends utils.Adapter {
1014
1080
  else {
1015
1081
  value = rawValue;
1016
1082
  }
1017
- this.log.silly(groupName + '.' + this.osn(stateInfo.id) + ':' + value);
1083
+ this.log.silly(group + '.' + this.osn(stateInfo.id) + ':' + value);
1018
1084
  let tvalue;
1019
1085
  switch (stateInfo.type) {
1020
1086
  case 'number':
@@ -1040,25 +1106,15 @@ class AlphaEss extends utils.Adapter {
1040
1106
  default:
1041
1107
  tvalue = value;
1042
1108
  }
1043
-
1044
1109
  if (this.config.updateUnchangedStates) {
1045
- await this.setStateAsync(groupName + '.' + this.osn(stateInfo.id), tvalue, true);
1110
+ await this.setStateAsync(group + '.' + this.osn(stateInfo.id), tvalue, true);
1046
1111
  }
1047
1112
  else {
1048
- await this.setStateChangedAsync(groupName + '.' + this.osn(stateInfo.id), tvalue, true);
1049
- }
1050
- this.log.debug('Received object ' + groupName + '.' + this.osn(stateInfo.alphaAttrName) + ' with value ' + rawValue);
1051
- }
1052
- else {
1053
- if (!this.createdStates[groupName]) {
1054
- this.log.info('Skipped object ' + groupName + '.' + alphaAttrName + ' with value ' + rawValue);
1113
+ await this.setStateChangedAsync(group + '.' + this.osn(stateInfo.id), tvalue, true);
1055
1114
  }
1115
+ this.log.debug('Received object ' + group + '.' + this.osn(stateInfo.alphaAttrName) + ' with value ' + rawValue);
1056
1116
  }
1057
1117
  }
1058
- if (!this.createdStates[groupName]) {
1059
- this.log.info('Created states for : ' + groupName);
1060
- this.createdStates[groupName] = true;
1061
- }
1062
1118
  }
1063
1119
  }
1064
1120
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.alpha-ess",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Read and write data from and to Alpha ESS systems.",
5
5
  "author": {
6
6
  "name": "Gaspode",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@iobroker/adapter-core": "^2.6.7",
23
- "axios": "^1.3.0"
23
+ "axios": "^1.3.4"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@alcalzone/release-script": "^3.5.9",
@@ -33,13 +33,13 @@
33
33
  "@types/chai": "^4.3.4",
34
34
  "@types/chai-as-promised": "^7.1.5",
35
35
  "@types/mocha": "^10.0.1",
36
- "@types/node": "^18.11.18",
36
+ "@types/node": "^18.14.2",
37
37
  "@types/proxyquire": "^1.3.28",
38
38
  "@types/sinon": "^10.0.13",
39
39
  "@types/sinon-chai": "^3.2.9",
40
40
  "chai": "^4.3.7",
41
41
  "chai-as-promised": "^7.1.1",
42
- "eslint": "^8.33.0",
42
+ "eslint": "^8.35.0",
43
43
  "eslint-config-prettier": "^8.5.0",
44
44
  "eslint-plugin-prettier": "^4.2.1",
45
45
  "mocha": "^10.2.0",