iobroker.senec 1.3.10 → 1.4.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
@@ -366,53 +366,15 @@ This channel contains calculated values. Currently these are day/week/month/year
366
366
  *Read-only number, which designates the number of wallbox [0..3]. This is only available on systems with configured wallboxes.*
367
367
 
368
368
  ## Changelog
369
+ ### 1.4.0 (NoBl)
370
+ * Added object caching along with some minor code updates. Due to the amount of objects we deal with caching is about mandatory.
371
+
369
372
  ### 1.3.10 (NoBl)
370
373
  * Fixed wrong Unit for STATISTIC.LIVE_WB_ENERGY
371
374
  * Updated to json Admin UI
372
375
  * Technical Updates
373
376
  * Added more state_attr definitions
374
377
 
375
- ### 1.3.9 (Nobl)
376
- * Added (some) Wallbox Datapoints to high-prio polling
377
- * Added more state definitions
378
-
379
- ### 1.3.8 (NoBl)
380
- * Removed (unnecessary) admin tab
381
-
382
- ### 1.3.7 (NoBl, noffycws, git-ZeR0)
383
- * Updates to state translations (new values when SENEC turned off appliances)
384
- * Added state definitions
385
- * Added high priority datapoints: temperatures, voltages, ... to better monitor safety relevant data
386
-
387
- ### 1.3.6 (NoBl)
388
- * Fixed log.warning error
389
-
390
- ### 1.3.5 (NoBl)
391
- * Added more state attributes (if you have updated descriptions or anything, please open an issue!)
392
- * Workaround in case SENEC reports bogus request data
393
-
394
- ### 1.3.4 (NoBl)
395
- * Moved from request to axios
396
- * Added more state attributes (if you have updated descriptions or anything, please open an issue!)
397
-
398
- ### 1.3.3 (NoBl)
399
- * Updated to current template.
400
-
401
- ### 1.3.2 (NoBl)
402
- * Autarky without decimal places (again). They are causing more updates than we really need.
403
- * Autarky values won't reset to 0 at change of timeframe (day, week, ...) anymore. They are calculated based on reference values anyways.
404
- * Ensuring that only values meant to be changeable by user are defined so (attribute changes upon the next update of value)
405
-
406
- ### 1.3.1 (NoBl) 20210513
407
- * Added calculation of autarky for day/week/month/year
408
-
409
- ### 1.3.0 (NoBl) 20210509
410
- * Rewrote translations handling
411
- * Added translations for wallbox status.
412
- * Translated status get an extra datapoint with _Text as postfix. Former translations that didn't add an extra dp will now revert to their numeric representation and add the _Text DP.
413
- * Translations are now handled via lib/state_trans.js for all 3 languages available in the senec system (german, english, italian).
414
- * Language used is decided by the language of the SENEC appliance.
415
-
416
378
  ### [Former Updates](CHANGELOG_old.md)
417
379
 
418
380
  ## License
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "senec",
4
- "version": "1.3.10",
4
+ "version": "1.4.0",
5
5
  "news": {
6
+ "1.4.0": {
7
+ "en": "Added object caching and minor code updates. Due to the amount of objects we deal with caching is about mandatory.",
8
+ "de": "Objekt-Caching und kleinere Code-Updates hinzugefügt. Aufgrund der Menge an Objekten, die der Adapter bearbeitet, ist Caching zwingend notwendig.",
9
+ "ru": "Добавлена кэшировка объекта и незначительные обновления кода. В связи с количеством объектов, с которыми мы занимаемся кэшированием, является обязательным.",
10
+ "pt": "Adicionado cache de objeto e pequenas atualizações de código. Devido à quantidade de objetos que lidamos com caching é sobre obrigatória.",
11
+ "nl": "Toegevoegd voorwerp caching en kleine code updates. Gezien de hoeveelheid objecten die we met caching hebben, gaat het over verplichting.",
12
+ "fr": "Ajout de cache d'objet et de mises à jour de code mineur. En raison de la quantité d'objets que nous traitons avec le cache est environ obligatoire.",
13
+ "it": "Aggiunti caching oggetto e aggiornamenti di codice minori. A causa della quantità di oggetti che abbiamo a che fare con il caching è circa obbligatorio.",
14
+ "es": "Añadido objeto caching y actualizaciones de código menor. Debido a la cantidad de objetos que tratamos con el caché es sobre obligatorio.",
15
+ "pl": "Dodany obiekt caching i drobnych aktualizacji kodu. Ze względu na ilość przedmiotów, które traktują z cachingiem, dotyczy obowiązkowych.",
16
+ "uk": "Додано кешування об'єкта та оновлення коду неповного розміру. У зв'язку з кількістю об'єктів, які ми маємо справу з кешуванням, є обов'язковим.",
17
+ "zh-cn": "添加了目标包和小法典的更新。 由于我们所处理的物品数量是强制性的。."
18
+ },
6
19
  "1.3.10": {
7
20
  "en": "Fixed wrong Unit for STATISTIC.LIVE_WB_ENERGY, added more state_attr. Moved to json admin UI and other technical updates.",
8
21
  "de": "Fehler behoben Einheit für STATISTIC.LIVE_WB_ENERGY, hinzugefügt mehr state_attr. Umgezogen zu json admin UI und anderen technischen Updates.",
package/main.js CHANGED
@@ -1,13 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  const utils = require('@iobroker/adapter-core');
4
- const axios = require('axios');
4
+ const axios = require('axios').default;
5
5
  const state_attr = require(__dirname + '/lib/state_attr.js');
6
6
  const state_trans = require(__dirname + '/lib/state_trans.js');
7
7
 
8
8
  let retry = 0; // retry-counter
9
9
  let retryLowPrio = 0; // retry-counter
10
10
 
11
+ let unloaded = false;
12
+
13
+ const knownObjects = {};
14
+
11
15
  class Senec extends utils.Adapter {
12
16
 
13
17
  /**
@@ -47,6 +51,7 @@ class Senec extends utils.Adapter {
47
51
  */
48
52
  onUnload(callback) {
49
53
  try {
54
+ unloaded = true;
50
55
  if (this.timer) {
51
56
  clearTimeout(this.timer);
52
57
  }
@@ -114,7 +119,7 @@ class Senec extends utils.Adapter {
114
119
  * @param url to read from
115
120
  * @param form to post
116
121
  */
117
- async doGet(pUrl, pForm, caller, pollingTimeout) {
122
+ doGet(pUrl, pForm, caller, pollingTimeout) {
118
123
  return new Promise(function (resolve, reject) {
119
124
  axios({
120
125
  method: 'post',
@@ -187,6 +192,7 @@ class Senec extends utils.Adapter {
187
192
  await this.evalPoll(obj);
188
193
 
189
194
  retry = 0;
195
+ if (unloaded) return;
190
196
  this.timer = setTimeout(() => this.readSenecV21(), this.config.interval * 1000);
191
197
  } catch (error) {
192
198
  if ((retry == this.config.retries) && this.config.retries < 999) {
@@ -224,6 +230,7 @@ class Senec extends utils.Adapter {
224
230
  await this.evalPoll(obj);
225
231
 
226
232
  retryLowPrio = 0;
233
+ if (unloaded) return;
227
234
  this.timerLowPrio = setTimeout(() => this.readSenecV21LowPrio(), this.config.intervalLow * 1000 * 60);
228
235
  } catch (error) {
229
236
  if ((retryLowPrio == this.config.retries) && this.config.retries < 999) {
@@ -247,51 +254,51 @@ class Senec extends utils.Adapter {
247
254
  return;
248
255
  }
249
256
  this.log.silly('(doState) Update: ' + name + ': ' + value);
250
- await this.setObjectNotExistsAsync(name, {
251
- type: 'state',
252
- common: {
253
- name: description,
254
- type: typeof(value),
255
- role: 'value',
256
- unit: unit,
257
- read: true,
258
- write: write
259
- },
260
- native: {}
261
- });
262
-
257
+
258
+ const valueType = value !== null && value !== undefined ? typeof value : "mixed";
259
+
263
260
  // Check object for changes:
264
- var obj = await this.getObjectAsync(name);
265
- if (obj.common.name != description) {
266
- this.log.debug("(doState) Updating object: " + name + " (desc): " + obj.common.name + " -> " + description);
267
- await this.extendObject(name, {common: {name: description}});
268
- }
269
- if (obj.common.type != typeof(value)) {
270
- this.log.debug("(doState) Updating object: " + name + " (type): " + obj.common.type + " -> " + typeof(value));
271
- await this.extendObject(name, {common: {type: typeof(value)}});
272
- }
273
- if (obj.common.unit != unit) {
274
- this.log.debug("(doState) Updating object: " + name + " (unit): " + obj.common.unit + " -> " + unit);
275
- await this.extendObject(name, {common: {unit: unit}});
276
- }
277
- if (obj.common.write != write) {
278
- this.log.debug("(doState) Updating object: " + name + " (write): " + obj.common.write + " -> " + write);
279
- await this.extendObject(name, {common: {write: write}});
280
- }
281
-
282
- var oldState = await this.getStateAsync(name);
283
- if (oldState) {
284
- if (oldState.val === value) {
285
- await this.checkUpdateSelfStat(name);
286
- return;
261
+ const obj = knownObjects[name] ? knownObjects[name] : await this.getObjectAsync(name);
262
+ if (obj) {
263
+ const newCommon = {};
264
+ if (obj.common.name !== description) {
265
+ this.log.debug("(doState) Updating object: " + name + " (desc): " + obj.common.name + " -> " + description);
266
+ newCommon.name = description;
287
267
  }
288
- this.log.debug('(doState) Update: ' + name + ': ' + oldState.val + ' -> ' + value);
289
- }
290
- await this.setStateAsync(name, {
291
- val: value,
292
- ack: true
293
- });
294
- await this.checkUpdateSelfStat(name);
268
+ if (obj.common.type !== valueType) {
269
+ this.log.debug("(doState) Updating object: " + name + " (type): " + obj.common.type + " -> " + typeof value);
270
+ newCommon.type = valueType;
271
+ }
272
+ if (obj.common.unit !== unit) {
273
+ this.log.debug("(doState) Updating object: " + name + " (unit): " + obj.common.unit + " -> " + unit);
274
+ newCommon.unit = unit;
275
+ }
276
+ if (obj.common.write !== write) {
277
+ this.log.debug("(doState) Updating object: " + name + " (write): " + obj.common.write + " -> " + write);
278
+ newCommon.write = write;
279
+ }
280
+ if (Object.keys(newCommon).length > 0) {
281
+ await this.extendObjectAsync(name, { common: newCommon });
282
+ }
283
+ } else {
284
+ knownObjects[name] = {
285
+ type: "state",
286
+ common: {
287
+ name: description,
288
+ type: valueType,
289
+ role: "value",
290
+ unit: unit,
291
+ read: true,
292
+ write: write
293
+ },
294
+ native: {}
295
+ };
296
+ await this.setObjectNotExistsAsync(name, knownObjects[name]);
297
+ }
298
+ await this.setStateChangedAsync(name, {
299
+ val: value,
300
+ ack: true
301
+ });
295
302
  await this.doDecode(name, value);
296
303
  }
297
304
 
@@ -332,8 +339,9 @@ class Senec extends utils.Adapter {
332
339
  * creates / updates the state.
333
340
  */
334
341
  async evalPoll(obj) {
335
- for (let[key1, value1]of Object.entries(obj)) {
336
- for (let[key2, value2]of Object.entries(value1)) {
342
+ if (unloaded) return;
343
+ for (const[key1, value1] of Object.entries(obj)) {
344
+ for (const[key2, value2] of Object.entries(value1)) {
337
345
  if (value2 !== "VARIABLE_NOT_FOUND" && key2 !== "OBJECT_NOT_FOUND") {
338
346
  const key = key1 + '.' + key2;
339
347
  if (state_attr[key] === undefined) {
@@ -474,7 +482,7 @@ const ValueTyping = (key, value) => {
474
482
  } else if (isIP) {
475
483
  return DecToIP(value);
476
484
  } else if (multiply !== 1) {
477
- return (value *= multiply).toFixed(2);
485
+ return parseFloat((value * multiply).toFixed(2));
478
486
  } else {
479
487
  return value;
480
488
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.senec",
3
- "version": "1.3.10",
3
+ "version": "1.4.0",
4
4
  "description": "Senec Home",
5
5
  "author": {
6
6
  "name": "NoBl",