iobroker.alpha-ess 1.1.1 → 1.2.0-beta.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
@@ -27,8 +27,6 @@ Staring with version 1.0.0-alpha.5, the quality attribute of each state is set a
27
27
 
28
28
  ## Settings:
29
29
 
30
- <span style="color:red">CAUTION: Currently only Open API is supported because the Closed API was changed by Apha-ESS and cannot be used by third party applications at the moment.</span>
31
-
32
30
  **Used API:** Choose between the inofficial "Closed" API and the official "Open" API
33
31
  Depending on the selected API there are different settings available.
34
32
 
@@ -65,6 +63,10 @@ How to find SN and Check code for registration is described here: https://github
65
63
  **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.**
66
64
 
67
65
  ## Changelog
66
+ ### 1.2.0-beta.0 (2023-11-10)
67
+
68
+ - (Gaspode) Added additional realtime attributes for OpenAPI
69
+
68
70
  ### 1.1.1 (2023-11-04)
69
71
 
70
72
  - (Gaspode) Closed API adapted to latest Alpha-ESS changes and enabled again
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "alpha-ess",
4
- "version": "1.1.1",
4
+ "version": "1.2.0-beta.0",
5
5
  "news": {
6
+ "1.2.0-beta.0": {
7
+ "en": "Added additional realtime attributes for OpenAPI",
8
+ "de": "Zusätzliche Echtzeit-Attribute für OpenAPI hinzugefügt",
9
+ "ru": "Добавлены дополнительные атрибуты в реальном времени для OpenAPI",
10
+ "pt": "Adicionado atributos em tempo real adicionais para OpenAPI",
11
+ "nl": "Toegevoegd aanvullingen voor OpenAPI",
12
+ "fr": "Ajout d'autres attributs en temps réel pour OpenAPI",
13
+ "it": "Aggiunto attributi in tempo reale aggiuntivi per OpenAPI",
14
+ "es": "Atributos adicionales en tiempo real para OpenAPI",
15
+ "pl": "Dodać dodatkowe atrybuty dla OpenAPI",
16
+ "uk": "Додано додаткові атрибути в режимі реального часу для OpenAPI",
17
+ "zh-cn": "增加开放协会实时归属"
18
+ },
6
19
  "1.1.1": {
7
20
  "en": "Closed API adapted to latest Alpha-ESS changes and enabled again",
8
21
  "de": "Closed API angepasst an neueste Alpha-ESS-Änderungen und wieder aktiviert",
@@ -80,19 +93,6 @@
80
93
  "pl": "Zmienił odstępy dla OpenAPI zgodnie z nowymi specjami Alpha-ESS\nUstalono jakość państwa zgodnie z statusem danych",
81
94
  "uk": "Змінено дозволені інтервали для OpenAPI відповідно до нових специфікацій Альфа-ESS\nВстановити якість держави відповідно до стану даних",
82
95
  "zh-cn": "根据Alpha-ESS的新投机,修改后允许有时间开放性倾向。\n相应地确定数据状况的国家质量"
83
- },
84
- "1.0.0-alpha.4": {
85
- "en": "Writing settings implemented for 'Closed API'",
86
- "de": "Schreiben von Settings für 'Closed API' implementiert",
87
- "ru": "Настройки написания, реализованные для 'Closed API'",
88
- "pt": "Definições de escrita implementadas para ' API fechada'",
89
- "nl": "Schrijf instellingen voor 'Closed API'",
90
- "fr": "Paramètres de rédaction mis en œuvre pour 'API perdue'",
91
- "it": "Impostazioni di scrittura implementate per 'Closed API'",
92
- "es": "Configuración de escritura implementada para 'Closed API'",
93
- "pl": "Scenariusze zaimplementowali \"zniszczone\" API",
94
- "uk": "Написання параметрів, реалізованих для \"Closed API\"",
95
- "zh-cn": "A. 落实的封闭环境"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/main.js CHANGED
@@ -46,6 +46,51 @@ class OpenAPI {
46
46
  , type: 'number'
47
47
  , unit: 'W'
48
48
  },
49
+ {
50
+ alphaAttrName: 'ppv1'
51
+ , role: 'value.power'
52
+ , id: 'PV_power_string_1'
53
+ , name: 'PV power string 1'
54
+ , type: 'number'
55
+ , unit: 'W'
56
+ , dayIndex: false
57
+ },
58
+ {
59
+ alphaAttrName: 'ppv2'
60
+ , role: 'value.power'
61
+ , id: 'PV_power_string_2'
62
+ , name: 'PV power string 2'
63
+ , type: 'number'
64
+ , unit: 'W'
65
+ , dayIndex: false
66
+ },
67
+ {
68
+ alphaAttrName: 'ppv3'
69
+ , role: 'value.power'
70
+ , id: 'PV_power_string_3'
71
+ , name: 'PV power string 3'
72
+ , type: 'number'
73
+ , unit: 'W'
74
+ , dayIndex: false
75
+ },
76
+ {
77
+ alphaAttrName: 'ppv4'
78
+ , role: 'value.power'
79
+ , id: 'PV_power_string_4'
80
+ , name: 'PV power string 4'
81
+ , type: 'number'
82
+ , unit: 'W'
83
+ , dayIndex: false
84
+ },
85
+ {
86
+ alphaAttrName: 'pmeterDc'
87
+ , role: 'value.power'
88
+ , id: 'PV_power_meter'
89
+ , name: 'PV power meter'
90
+ , type: 'number'
91
+ , unit: 'W'
92
+ , dayIndex: false
93
+ },
49
94
  {
50
95
  alphaAttrName: 'pload'
51
96
  , role: 'value.power'
@@ -62,6 +107,30 @@ class OpenAPI {
62
107
  , type: 'number'
63
108
  , unit: '%'
64
109
  },
110
+ {
111
+ alphaAttrName: 'pmeterL1'
112
+ , role: 'value.power'
113
+ , id: 'Grid_power_L1'
114
+ , name: 'Grid power L1'
115
+ , type: 'number'
116
+ , unit: 'W'
117
+ },
118
+ {
119
+ alphaAttrName: 'pmeterL2'
120
+ , role: 'value.power'
121
+ , id: 'Grid_power_L2'
122
+ , name: 'Grid power L2'
123
+ , type: 'number'
124
+ , unit: 'W'
125
+ },
126
+ {
127
+ alphaAttrName: 'pmeterL3'
128
+ , role: 'value.power'
129
+ , id: 'Grid_power_L3'
130
+ , name: 'Grid power L3'
131
+ , type: 'number'
132
+ , unit: 'W'
133
+ },
65
134
  {
66
135
  alphaAttrName: 'pgrid'
67
136
  , role: 'value.power'
@@ -81,10 +150,73 @@ class OpenAPI {
81
150
  {
82
151
  alphaAttrName: 'pev'
83
152
  , role: 'value.power'
84
- , id: 'Charging_pile_total'
85
- , name: 'Charging pile (Wallbox) total'
153
+ , id: 'Charging_pile_power_total'
154
+ , name: 'Charging pile (Wallbox) power total'
155
+ , type: 'number'
156
+ , unit: 'W'
157
+ },
158
+ {
159
+ alphaAttrName: 'prealL1'
160
+ , role: 'value.power'
161
+ , id: 'Inverter_power_L1'
162
+ , name: 'Inverter power L1'
163
+ , type: 'number'
164
+ , unit: 'W'
165
+ , dayIndex: false
166
+ },
167
+ {
168
+ alphaAttrName: 'prealL2'
169
+ , role: 'value.power'
170
+ , id: 'Inverter_power_L2'
171
+ , name: 'Inverter power L2'
172
+ , type: 'number'
173
+ , unit: 'W'
174
+ , dayIndex: false
175
+ },
176
+ {
177
+ alphaAttrName: 'prealL3'
178
+ , role: 'value.power'
179
+ , id: 'Inverter_power_L3'
180
+ , name: 'Inverter power L3'
181
+ , type: 'number'
182
+ , unit: 'W'
183
+ , dayIndex: false
184
+ },
185
+ {
186
+ alphaAttrName: 'ev1Power'
187
+ , role: 'value.power'
188
+ , id: 'Charging_pile_power_1'
189
+ , name: 'Charging pile (Wallbox) power 1'
190
+ , type: 'number'
191
+ , unit: 'W'
192
+ , dayIndex: false
193
+ },
194
+ {
195
+ alphaAttrName: 'ev2Power'
196
+ , role: 'value.power'
197
+ , id: 'Charging_pile_power_2'
198
+ , name: 'Charging pile (Wallbox) power 2'
86
199
  , type: 'number'
87
200
  , unit: 'W'
201
+ , dayIndex: false
202
+ },
203
+ {
204
+ alphaAttrName: 'ev3Power'
205
+ , role: 'value.power'
206
+ , id: 'Charging_pile_power_3'
207
+ , name: 'Charging pile (Wallbox) power 3'
208
+ , type: 'number'
209
+ , unit: 'W'
210
+ , dayIndex: false
211
+ },
212
+ {
213
+ alphaAttrName: 'ev4Power'
214
+ , role: 'value.power'
215
+ , id: 'Charging_pile_power_4'
216
+ , name: 'Charging pile (Wallbox) power 4'
217
+ , type: 'number'
218
+ , unit: 'W'
219
+ , dayIndex: false
88
220
  }]
89
221
  },
90
222
  {
@@ -2289,34 +2421,15 @@ class AlphaEss extends utils.Adapter {
2289
2421
  // Create all states for received elements
2290
2422
  for (const [alphaAttrName, rawValue] of Object.entries(data)) {
2291
2423
  const stateInfo = this.getStateInfoByAlphaAttrName(group, alphaAttrName);
2292
- if (stateInfo) {
2293
- // The type checker has a problem with type: stateInfo.type. I have no clue why.
2294
- // All possible types are correct and valid. To get rid of the type checker error, we check for valid types:
2295
- if (stateInfo.type == 'string' || stateInfo.type == 'boolean' || stateInfo.type == 'number') {
2296
- await setObjectFunc(group + '.' + this.osn(stateInfo.id), {
2297
- type: 'state',
2298
- common: {
2299
- name: stateInfo.name + ' [' + stateInfo.alphaAttrName + ']'
2300
- , type: stateInfo.type
2301
- , role: stateInfo.role
2302
- , read: true
2303
- , write: stateInfo.writeable ? stateInfo.writeable : false
2304
- , unit: stateInfo.unit === '{money_type}' ? data['money_type'] : stateInfo.unit === '{moneyType}' ? data['moneyType'] : stateInfo.unit
2305
- , desc: stateInfo.alphaAttrName
2306
- },
2307
- native: {},
2308
- });
2309
- if (stateInfo.writeable) {
2310
- await this.subscribeStatesAsync(`${group}.${stateInfo.id}`);
2311
- this.log.debug(`Subscribed State: ${group}.${stateInfo.id}`);
2312
- }
2313
- }
2314
- else {
2315
- this.log.error('Internal error: Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue + ' because of invalid type definition!');
2316
- }
2424
+ if (typeof data[alphaAttrName] !== 'object') {
2425
+ this.createStateForAttribute(group, data, rawValue, alphaAttrName, stateInfo, setObjectFunc);
2317
2426
  }
2318
2427
  else {
2319
- this.log.debug('Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue);
2428
+ // Look for subvalues:
2429
+ for (const [alphaAttrName2, rawValue2] of Object.entries(data[alphaAttrName])) {
2430
+ const stateInfo2 = this.getStateInfoByAlphaAttrName(group, alphaAttrName2);
2431
+ this.createStateForAttribute(group, data[alphaAttrName], rawValue2, alphaAttrName2, stateInfo2, setObjectFunc);
2432
+ }
2320
2433
  }
2321
2434
  }
2322
2435
  this.log.info('Initialized states for : ' + group);
@@ -2326,48 +2439,15 @@ class AlphaEss extends utils.Adapter {
2326
2439
  // Set values for received states
2327
2440
  for (const [alphaAttrName, rawValue] of Object.entries(data)) {
2328
2441
  const stateInfo = this.getStateInfoByAlphaAttrName(group, alphaAttrName);
2329
- if (stateInfo) {
2330
- let value = '';
2331
- if (stateInfo.dayIndex) {
2332
- value = rawValue[idx];
2333
- }
2334
- else {
2335
- value = rawValue;
2336
- }
2337
- this.log.silly(group + '.' + this.osn(stateInfo.id) + ':' + value);
2338
- let tvalue;
2339
- switch (stateInfo.type) {
2340
- case 'number':
2341
- tvalue = Number.parseFloat(value);
2342
- if (stateInfo.factor) {
2343
- tvalue *= stateInfo.factor;
2344
- }
2345
- if (stateInfo.round) {
2346
- tvalue = (Math.round(tvalue * (10 ** stateInfo.round))) / (10 ** stateInfo.round);
2347
- }
2348
- break;
2349
- case 'boolean':
2350
- if (value.toString().toLowerCase() === 'true') {
2351
- tvalue = true;
2352
- }
2353
- else if (value.toString().toLowerCase() === 'false') {
2354
- tvalue = false;
2355
- }
2356
- else {
2357
- tvalue = Number.parseInt(value) != 0;
2358
- }
2359
- break;
2360
- default:
2361
- tvalue = value;
2362
- }
2363
- if (this.config.updateUnchangedStates) {
2364
- await this.setStateAsync(group + '.' + this.osn(stateInfo.id), { val: tvalue, q: 0 }, true);
2365
- }
2366
- else {
2367
- await this.setStateChangedAsync(group + '.' + this.osn(stateInfo.id), { val: tvalue, q: 0 }, true);
2442
+ if (typeof data[alphaAttrName] !== 'object') {
2443
+ this.setValueForAttribute(group, rawValue, stateInfo, idx);
2444
+ }
2445
+ else {
2446
+ // Look for subvalues:
2447
+ for (const [alphaAttrName2, rawValue2] of Object.entries(data[alphaAttrName])) {
2448
+ const stateInfo2 = this.getStateInfoByAlphaAttrName(group, alphaAttrName2);
2449
+ this.setValueForAttribute(group, rawValue2, stateInfo2, idx);
2368
2450
  }
2369
- stateInfo.lastUpdateTs = Date.now();
2370
- this.log.debug('Received object ' + group + '.' + this.osn(stateInfo.alphaAttrName) + ' with value ' + rawValue);
2371
2451
  }
2372
2452
  }
2373
2453
  }
@@ -2377,6 +2457,101 @@ class AlphaEss extends utils.Adapter {
2377
2457
  }
2378
2458
  }
2379
2459
 
2460
+ /**
2461
+ *
2462
+ * create the state for the received element
2463
+ * @param {string} group
2464
+ * @param {{[x: string]: any;}} data
2465
+ * @param {string} rawValue
2466
+ * @param {string} alphaAttrName
2467
+ */
2468
+ async createStateForAttribute(group, data, rawValue, alphaAttrName, stateInfo, setObjectFunc) {
2469
+ if (stateInfo) {
2470
+ // The type checker has a problem with type: stateInfo.type. I have no clue why.
2471
+ // All possible types are correct and valid. To get rid of the type checker error, we check for valid types:
2472
+ if (stateInfo.type == 'string' || stateInfo.type == 'boolean' || stateInfo.type == 'number') {
2473
+ await setObjectFunc(group + '.' + this.osn(stateInfo.id), {
2474
+ type: 'state',
2475
+ common: {
2476
+ name: stateInfo.name + ' [' + stateInfo.alphaAttrName + ']'
2477
+ , type: stateInfo.type
2478
+ , role: stateInfo.role
2479
+ , read: true
2480
+ , write: stateInfo.writeable ? stateInfo.writeable : false
2481
+ , unit: stateInfo.unit === '{money_type}' ? data['money_type'] : stateInfo.unit === '{moneyType}' ? data['moneyType'] : stateInfo.unit
2482
+ , desc: stateInfo.alphaAttrName
2483
+ },
2484
+ native: {},
2485
+ });
2486
+ if (stateInfo.writeable) {
2487
+ await this.subscribeStatesAsync(`${group}.${stateInfo.id}`);
2488
+ this.log.debug(`Subscribed State: ${group}.${stateInfo.id}`);
2489
+ }
2490
+ }
2491
+ else {
2492
+ this.log.error('Internal error: Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue + ' because of invalid type definition!');
2493
+ }
2494
+ }
2495
+ else {
2496
+ if (alphaAttrName == 'sysSn' || alphaAttrName == 'theDate') {
2497
+ this.log.debug('Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue);
2498
+ }
2499
+ else {
2500
+ this.log.warn('Skipped object ' + group + '.' + alphaAttrName + ' with value ' + rawValue);
2501
+ }
2502
+ }
2503
+ }
2504
+
2505
+ /**
2506
+ * @param {string} group
2507
+ * @param {string} rawValue
2508
+ */
2509
+ async setValueForAttribute(group, rawValue, stateInfo, idx) {
2510
+ if (stateInfo) {
2511
+ let value = '';
2512
+ if (stateInfo.dayIndex) {
2513
+ value = rawValue[idx];
2514
+ }
2515
+ else {
2516
+ value = rawValue;
2517
+ }
2518
+ this.log.silly(group + '.' + this.osn(stateInfo.id) + ':' + value);
2519
+ let tvalue;
2520
+ switch (stateInfo.type) {
2521
+ case 'number':
2522
+ tvalue = Number.parseFloat(value);
2523
+ if (stateInfo.factor) {
2524
+ tvalue *= stateInfo.factor;
2525
+ }
2526
+ if (stateInfo.round) {
2527
+ tvalue = (Math.round(tvalue * (10 ** stateInfo.round))) / (10 ** stateInfo.round);
2528
+ }
2529
+ break;
2530
+ case 'boolean':
2531
+ if (value.toString().toLowerCase() === 'true') {
2532
+ tvalue = true;
2533
+ }
2534
+ else if (value.toString().toLowerCase() === 'false') {
2535
+ tvalue = false;
2536
+ }
2537
+ else {
2538
+ tvalue = Number.parseInt(value) != 0;
2539
+ }
2540
+ break;
2541
+ default:
2542
+ tvalue = value;
2543
+ }
2544
+ if (this.config.updateUnchangedStates) {
2545
+ await this.setStateAsync(group + '.' + this.osn(stateInfo.id), { val: tvalue, q: 0 }, true);
2546
+ }
2547
+ else {
2548
+ await this.setStateChangedAsync(group + '.' + this.osn(stateInfo.id), { val: tvalue, q: 0 }, true);
2549
+ }
2550
+ stateInfo.lastUpdateTs = Date.now();
2551
+ this.log.debug('Received object ' + group + '.' + this.osn(stateInfo.alphaAttrName) + ' with value ' + rawValue);
2552
+ }
2553
+ }
2554
+
2380
2555
  /**
2381
2556
  * Answer the state description object for a given group and alpha-ess attribute name
2382
2557
  * @param {string} Group
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.alpha-ess",
3
- "version": "1.1.1",
3
+ "version": "1.2.0-beta.0",
4
4
  "description": "Read and write data from and to Alpha ESS systems.",
5
5
  "author": {
6
6
  "name": "Gaspode",