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 +8 -0
- package/io-package.json +27 -27
- package/main.js +111 -55
- package/package.json +4 -4
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.
|
|
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
|
|
658
|
-
if (this.config[
|
|
659
|
-
await
|
|
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(
|
|
663
|
-
await this.
|
|
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.
|
|
733
|
+
this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
|
|
704
734
|
} else {
|
|
705
735
|
// The state was deleted
|
|
706
|
-
this.log.
|
|
736
|
+
this.log.debug(`state ${id} deleted`);
|
|
707
737
|
}
|
|
708
738
|
}
|
|
709
739
|
|
|
710
740
|
/**
|
|
711
|
-
*
|
|
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}
|
|
1007
|
+
* @param {string} group
|
|
984
1008
|
* @param {{ [s: string]: any; }} data
|
|
985
1009
|
*/
|
|
986
|
-
async createAndUpdateStates(
|
|
1010
|
+
async createAndUpdateStates(group, data) {
|
|
987
1011
|
try {
|
|
988
1012
|
if (data) {
|
|
989
1013
|
const idx = new Date().getDate() - 1;
|
|
990
1014
|
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
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(
|
|
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(
|
|
1110
|
+
await this.setStateAsync(group + '.' + this.osn(stateInfo.id), tvalue, true);
|
|
1046
1111
|
}
|
|
1047
1112
|
else {
|
|
1048
|
-
await this.setStateChangedAsync(
|
|
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
|
+
"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.
|
|
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.
|
|
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.
|
|
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",
|