iobroker.senec 1.6.4 → 1.6.5
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 +4 -0
- package/admin/jsonConfig.json +35 -1
- package/io-package.json +17 -3
- package/main.js +102 -18
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -366,6 +366,10 @@ 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.6.5 (NoBl)
|
|
370
|
+
* Added AllTime Statistics (trigger initial calculations in adapter settings)
|
|
371
|
+
* https is now default for new instances
|
|
372
|
+
|
|
369
373
|
### 1.6.4 (NoBl)
|
|
370
374
|
* Bugfix (numbers are numbers again)
|
|
371
375
|
|
package/admin/jsonConfig.json
CHANGED
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"uk": "Чи потрібен HTTPS для підключення до SENEC? Тільки перевірте, чи підтримує SENEC HTTPS вже!",
|
|
84
84
|
"zh-cn": "是否需要与ENEC联系? 只有检查有无国界协会支持已经!"
|
|
85
85
|
},
|
|
86
|
-
"default":
|
|
86
|
+
"default": true,
|
|
87
87
|
"newLine": false
|
|
88
88
|
},
|
|
89
89
|
"interval": {
|
|
@@ -1242,6 +1242,40 @@
|
|
|
1242
1242
|
"max": 1440,
|
|
1243
1243
|
"newLine": true
|
|
1244
1244
|
},
|
|
1245
|
+
"api_alltimeRebuild": {
|
|
1246
|
+
"type": "checkbox",
|
|
1247
|
+
"sm": 12,
|
|
1248
|
+
"md": 6,
|
|
1249
|
+
"lg": 6,
|
|
1250
|
+
"label": {
|
|
1251
|
+
"en": "Rebuild AllTime history (one-time)",
|
|
1252
|
+
"de": "Gesamthistorie neu berechnen (einmalig)",
|
|
1253
|
+
"ru": "Восстановление истории AllTime (один раз)",
|
|
1254
|
+
"pt": "Reconstruir história AllTime (um tempo)",
|
|
1255
|
+
"nl": "Herbouw AllTime geschiedenis (1-time)",
|
|
1256
|
+
"fr": "Rebuild AllTime history (une fois)",
|
|
1257
|
+
"it": "Ricostruire la storia di AllTime (una volta)",
|
|
1258
|
+
"es": "Recuperar historia de AllTime (una sola vez)",
|
|
1259
|
+
"pl": "Rebuild All Time history (ang.)",
|
|
1260
|
+
"uk": "Історія (один раз)",
|
|
1261
|
+
"zh-cn": "废除所有制度的历史(一次性)"
|
|
1262
|
+
},
|
|
1263
|
+
"help": {
|
|
1264
|
+
"en": "Check this if you want the adapter to rebuild history values back to date of installation.",
|
|
1265
|
+
"de": "Aktivieren, falls der Adapter die Historienwerte seit Installation neu berechnen soll.",
|
|
1266
|
+
"ru": "Проверьте это, если вы хотите, чтобы адаптер восстановить значения истории обратно к дате установки.",
|
|
1267
|
+
"pt": "Verifique se deseja que o adaptador reconstrua os valores do histórico de volta à data da instalação.",
|
|
1268
|
+
"nl": "Controleer dit als je wilt dat de adapter de geschiedeniswaarden herbouwt tot datum van installatie.",
|
|
1269
|
+
"fr": "Vérifiez ceci si vous voulez que l'adaptateur reconstruise les valeurs d'histoire à la date d'installation.",
|
|
1270
|
+
"it": "Controllare questo se si desidera che l'adattatore per ricostruire i valori storici fino alla data di installazione.",
|
|
1271
|
+
"es": "Revise esto si desea que el adaptador reconstruya los valores de historia hasta la fecha de instalación.",
|
|
1272
|
+
"pl": "Umożliwia to, czy chcesz adapterowi odbudować wartości historyczne do daty instalacji.",
|
|
1273
|
+
"uk": "Перевірте це, якщо ви хочете перебудувати значення історії назад до дати установки.",
|
|
1274
|
+
"zh-cn": "如果你想适应者重建历史价值,那么我们就会感到惊讶。."
|
|
1275
|
+
},
|
|
1276
|
+
"default": false,
|
|
1277
|
+
"newLine": true
|
|
1278
|
+
},
|
|
1245
1279
|
}
|
|
1246
1280
|
}
|
|
1247
1281
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "senec",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.5",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.6.5": {
|
|
7
|
+
"en": "Added AllTime Statistics (trigger initial calculations in adapter settings), https is now default for new instances.",
|
|
8
|
+
"de": "AllTime Statistiken hinzugefügt (initiale Berechnung bitte in den Adapter-Einstellungen aktivieren), https ist jetzt Standard für neue Instanzen.",
|
|
9
|
+
"ru": "Добавлена статистика AllTime (trigger начальные расчеты в настройках адаптера), https теперь по умолчанию для новых инстанций.",
|
|
10
|
+
"pt": "Adicionado AllTime Statistics ( cálculos iniciais de gatilho em configurações de adaptador), https agora é padrão para novas instâncias.",
|
|
11
|
+
"nl": "Toegevoegd AllTime Statistieken (trigger initialen berekeningen in adapter settings\" \"htps is nu default voor nieuwe instanties.",
|
|
12
|
+
"fr": "Ajout de AllTime Statistics (trigger initial calculations in adapt settings), https est maintenant par défaut pour de nouveaux cas.",
|
|
13
|
+
"it": "Aggiunta AllTime Statistics (configurazioni iniziali del trigger nelle impostazioni dell'adattatore), https è ora predefinito per nuove istanze.",
|
|
14
|
+
"es": "Añadido AllTime Statistics (trigger inicial calculations in adapter settings), https ahora es predeterminado para nuevas instancias.",
|
|
15
|
+
"pl": "Added AllTime Statistics (trigger początkowych obliczeń w ustawieniach adapterów), https jest obecnie domyślny do nowych instancji.",
|
|
16
|
+
"uk": "Додано AllTime Статистика (тригер початкових обчислень в налаштуваннях адаптера), HTTPS тепер за замовчуванням для нових екземплярів.",
|
|
17
|
+
"zh-cn": "加上《所有制度统计》(在适应环境中的过份初步计算),目前,新情况目前有缺陷。."
|
|
18
|
+
},
|
|
6
19
|
"1.6.4": {
|
|
7
20
|
"en": "Numbers are numbers again",
|
|
8
21
|
"de": "Zahlen sind wieder Zahlen",
|
|
@@ -205,7 +218,7 @@
|
|
|
205
218
|
"pollingTimeout": 5000,
|
|
206
219
|
"retries": 10,
|
|
207
220
|
"retrymultiplier": 2,
|
|
208
|
-
"useHttps":
|
|
221
|
+
"useHttps": true,
|
|
209
222
|
"disclaimer": false,
|
|
210
223
|
"highPrio_BMS": "",
|
|
211
224
|
"highPrio_BMS_active": false,
|
|
@@ -236,7 +249,8 @@
|
|
|
236
249
|
"highPrio_TEMPMEASURE": "",
|
|
237
250
|
"highPrio_TEMPMEASURE_active": false,
|
|
238
251
|
"api_use": false,
|
|
239
|
-
"api_interval": 5
|
|
252
|
+
"api_interval": 5,
|
|
253
|
+
"api_alltimeRebuild": false
|
|
240
254
|
},
|
|
241
255
|
"nativeEncrypted": {
|
|
242
256
|
"api_mail": "",
|
package/main.js
CHANGED
|
@@ -292,12 +292,12 @@ class Senec extends utils.Adapter {
|
|
|
292
292
|
apiKnownSystems.push(systemId);
|
|
293
293
|
for (const[key2, value2] of Object.entries(value)) {
|
|
294
294
|
if (typeof value2 === "object")
|
|
295
|
-
this.doState(pfx + systemId + "." + key2, JSON.stringify(value2), "", "", false);
|
|
295
|
+
await this.doState(pfx + systemId + "." + key2, JSON.stringify(value2), "", "", false);
|
|
296
296
|
else
|
|
297
|
-
this.doState(pfx + systemId + "." + key2, value2, "", "", false);
|
|
297
|
+
await this.doState(pfx + systemId + "." + key2, value2, "", "", false);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
-
this.doState(pfx + 'IDs', JSON.stringify(apiKnownSystems), "Anlagen IDs", "", false);
|
|
300
|
+
await this.doState(pfx + 'IDs', JSON.stringify(apiKnownSystems), "Anlagen IDs", "", false);
|
|
301
301
|
} catch (error) {
|
|
302
302
|
throw new Error("Error reading Systems Information from Senec AppAPI. (" + error + ").");
|
|
303
303
|
}
|
|
@@ -409,7 +409,7 @@ class Senec extends utils.Adapter {
|
|
|
409
409
|
var body = "";
|
|
410
410
|
try {
|
|
411
411
|
for (let i = 0; i < apiKnownSystems.length; i++) {
|
|
412
|
-
const baseUrl = apiSystemsUrl + "/" + apiKnownSystems[i]
|
|
412
|
+
const baseUrl = apiSystemsUrl + "/" + apiKnownSystems[i];
|
|
413
413
|
var url = "";
|
|
414
414
|
const tzObj = await this.getStateAsync("_api.Anlagen." + apiKnownSystems[i] + ".zeitzone");
|
|
415
415
|
const tz = tzObj ? encodeURIComponent(tzObj.val) : encodeURIComponent("Europe/Berlin");
|
|
@@ -420,17 +420,14 @@ class Senec extends utils.Adapter {
|
|
|
420
420
|
await this.decodeDashboard(apiKnownSystems[i], JSON.parse(body));
|
|
421
421
|
|
|
422
422
|
for (let[key, value] of dates.entries()) {
|
|
423
|
-
// statistik
|
|
423
|
+
// statistik for period
|
|
424
424
|
url = baseUrl + "/statistik?periode=" + api_trans[key].api + "&datum=" + value + "&locale=de_DE&timezone=" + tz;
|
|
425
425
|
body = await this.doGet(url, "", this, this.config.pollingTimeout, false);
|
|
426
426
|
await this.decodeStatistik(apiKnownSystems[i], JSON.parse(body), api_trans[key].dp);
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
//body = await this.doGet(url, "", this, this.config.pollingTimeout, false);
|
|
432
|
-
//this.log.info("Abilities: " + body);
|
|
433
|
-
//await this.decodeWallbox(apiKnownSystems[i], JSON.parse(body));
|
|
429
|
+
if (this.config.api_alltimeRebuild) await this.rebuildAllTimeHistory(apiKnownSystems[i]);
|
|
430
|
+
|
|
434
431
|
}
|
|
435
432
|
retry = 0;
|
|
436
433
|
if (unloaded) return;
|
|
@@ -447,16 +444,19 @@ class Senec extends utils.Adapter {
|
|
|
447
444
|
}
|
|
448
445
|
}
|
|
449
446
|
|
|
447
|
+
/**
|
|
448
|
+
* Decodes Dashboard information from SENEC App API
|
|
449
|
+
*/
|
|
450
450
|
async decodeDashboard(system, obj) {
|
|
451
451
|
const pfx = "_api.Anlagen." + system + ".Dashboard.";
|
|
452
452
|
for (const[key, value] of Object.entries(obj)) {
|
|
453
453
|
if (key == "zeitstempel" || key == "electricVehicleConnected") {
|
|
454
|
-
this.doState(pfx + key, value, "", "", false);
|
|
454
|
+
await this.doState(pfx + key, value, "", "", false);
|
|
455
455
|
} else {
|
|
456
456
|
for (const[key2, value2] of Object.entries(value)) {
|
|
457
|
-
this.doState(pfx + key + "." + key2, Number((value2.wert).toFixed(2)), "", value2.einheit, false);
|
|
457
|
+
await this.doState(pfx + key + "." + key2, Number((value2.wert).toFixed(2)), "", value2.einheit, false);
|
|
458
458
|
if (kiloList.includes(value2.einheit)) {
|
|
459
|
-
this.doState(pfx + key + "." + key2 + " (k" + value2.einheit + ")", Number((value2.wert / 1000).toFixed(2)), "", "k" + value2.einheit, false);
|
|
459
|
+
await this.doState(pfx + key + "." + key2 + " (k" + value2.einheit + ")", Number((value2.wert / 1000).toFixed(2)), "", "k" + value2.einheit, false);
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
462
|
}
|
|
@@ -464,21 +464,105 @@ class Senec extends utils.Adapter {
|
|
|
464
464
|
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Decodes Statistik information from SENEC App API
|
|
469
|
+
*/
|
|
467
470
|
async decodeStatistik(system, obj, period) {
|
|
468
471
|
const pfx = "_api.Anlagen." + system + ".Statistik." + period + ".";
|
|
469
472
|
for (const[key, value] of Object.entries(obj.aggregation)) {
|
|
470
473
|
// only reading 'aggregation' - no interest in fine granular information
|
|
471
474
|
if (key == "startzeitpunkt") {
|
|
472
|
-
this.doState(pfx + key, value, "", "", false);
|
|
475
|
+
await this.doState(pfx + key, value, "", "", false);
|
|
473
476
|
} else {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
+
if (!this.config.api_alltimeRebuild) { // don't update DPs if we are AllTime-Rebuild-Process
|
|
478
|
+
await this.doState(pfx + key, Number((value.wert).toFixed(2)), "", value.einheit, false);
|
|
479
|
+
if (kiloList.includes(value.einheit)) {
|
|
480
|
+
await this.doState(pfx + key + " (k"+ value.einheit + ")", Number((value.wert / 1000).toFixed(2)), "", "k" + value.einheit, false);
|
|
481
|
+
}
|
|
477
482
|
}
|
|
483
|
+
if (period == api_trans["THIS_YEAR"].dp) await this.insertAllTimeHistory(system, key, new Date(obj.aggregation.startzeitpunkt).getFullYear(), Number((value.wert).toFixed(0)), value.einheit);
|
|
478
484
|
}
|
|
479
485
|
}
|
|
480
486
|
const autarky = Number((((obj.aggregation.stromerzeugung.wert - obj.aggregation.netzeinspeisung.wert - obj.aggregation.speicherbeladung.wert + obj.aggregation.speicherentnahme.wert) / obj.aggregation.stromverbrauch.wert) * 100).toFixed(2));
|
|
481
|
-
this.doState(pfx + "Autarkie", autarky, "", "%", false);
|
|
487
|
+
await this.doState(pfx + "Autarkie", autarky, "", "%", false);
|
|
488
|
+
await this.updateAllTimeHistory(system);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* inserts a value for a given key and year into AllTimeValueStore
|
|
493
|
+
*/
|
|
494
|
+
async insertAllTimeHistory(system, key, year, value, einheit) {
|
|
495
|
+
const pfx = "_api.Anlagen." + system + ".Statistik.AllTime.";
|
|
496
|
+
const valueStore = pfx + "valueStore";
|
|
497
|
+
const statsObj = await this.getStateAsync(valueStore);
|
|
498
|
+
const stats = statsObj ? JSON.parse(statsObj.val) : {};
|
|
499
|
+
if (!stats[key]) stats[key] = {};
|
|
500
|
+
if (!stats[key][year]) stats[key][year] = {};
|
|
501
|
+
stats[key][year] = value;
|
|
502
|
+
stats[key]["einheit"] = einheit;
|
|
503
|
+
await this.doState(valueStore, JSON.stringify(stats), "", "", false);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Updated AllTimeHistory based on what we have in our AllTimeValueStore
|
|
508
|
+
*/
|
|
509
|
+
async updateAllTimeHistory(system) {
|
|
510
|
+
const pfx = "_api.Anlagen." + system + ".Statistik.AllTime.";
|
|
511
|
+
const valueStore = pfx + "valueStore";
|
|
512
|
+
const statsObj = await this.getStateAsync(valueStore);
|
|
513
|
+
const stats = statsObj ? JSON.parse(statsObj.val) : {};
|
|
514
|
+
const sums = {};
|
|
515
|
+
for (const[key, value] of Object.entries(stats)) {
|
|
516
|
+
var einheit = "";
|
|
517
|
+
var sum = 0.0;
|
|
518
|
+
for (const[key2, value2] of Object.entries(value)) {
|
|
519
|
+
if (key2 == "einheit") {
|
|
520
|
+
einheit = value2;
|
|
521
|
+
} else {
|
|
522
|
+
sum += value2;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
sums[key] = sum;
|
|
526
|
+
if (kiloList.includes(einheit)) {
|
|
527
|
+
await this.doState(pfx + key, Number((sum / 1000).toFixed(0)), "", "k" + einheit, false);
|
|
528
|
+
} else {
|
|
529
|
+
await this.doState(pfx + key, Number(sum.toFixed(0)), "", einheit, false);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const autarky = Number((((sums.stromerzeugung - sums.netzeinspeisung - sums.speicherbeladung + sums.speicherentnahme) / sums.stromverbrauch) * 100).toFixed(0));
|
|
533
|
+
await this.doState(pfx + "Autarkie", autarky, "", "%", false);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Rebuilds AllTimeHistory from SENEC App API
|
|
538
|
+
*/
|
|
539
|
+
async rebuildAllTimeHistory(system) {
|
|
540
|
+
if (!this.config.api_use || !apiConnected) {
|
|
541
|
+
this.log.info('Usage of SENEC App API not configured or not connected.');
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
this.log.info("Rebuilding AllTime History ...");
|
|
546
|
+
var year = new Date(new Date().getFullYear() - 1, 1, 1).toISOString().split('T')[0]; // starting last year, because we already got current year covered
|
|
547
|
+
var body = "";
|
|
548
|
+
try {
|
|
549
|
+
while (new Date(year).getFullYear() > 2008) { // senec was founded in 2009 by Mathias Hammer as Deutsche Energieversorgung GmbH (DEV) - so no way we have older data :)
|
|
550
|
+
this.log.info("Rebuilding AllTime History - Year: " + new Date(year).getFullYear());
|
|
551
|
+
const baseUrl = apiSystemsUrl + "/" + system
|
|
552
|
+
var url = "";
|
|
553
|
+
const tzObj = await this.getStateAsync("_api.Anlagen." + system + ".zeitzone");
|
|
554
|
+
const tz = tzObj ? encodeURIComponent(tzObj.val) : encodeURIComponent("Europe/Berlin");
|
|
555
|
+
url = baseUrl + "/statistik?periode=JAHR&datum=" + year + "&locale=de_DE&timezone=" + tz;
|
|
556
|
+
body = await this.doGet(url, "", this, this.config.pollingTimeout, false);
|
|
557
|
+
await this.decodeStatistik(system, JSON.parse(body), api_trans["THIS_YEAR"].dp);
|
|
558
|
+
year = new Date(new Date(year).getFullYear() - 1, 1, 1).toISOString().split('T')[0];
|
|
559
|
+
if (unloaded) return;
|
|
560
|
+
}
|
|
561
|
+
} catch (error) {
|
|
562
|
+
this.log.info("Rebuild ended.");
|
|
563
|
+
}
|
|
564
|
+
this.log.info("Restarting ...");
|
|
565
|
+
this.extendForeignObject(`system.adapter.${this.namespace}`, {native: {api_alltimeRebuild: false}});
|
|
482
566
|
}
|
|
483
567
|
|
|
484
568
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.senec",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"description": "Senec Home",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "NoBl",
|
|
@@ -35,21 +35,21 @@
|
|
|
35
35
|
"@iobroker/adapter-dev": "^1.2.0",
|
|
36
36
|
"@iobroker/testing": "^4.1.0",
|
|
37
37
|
"@tsconfig/node14": "^14.1.0",
|
|
38
|
-
"@types/chai": "^4.3.
|
|
39
|
-
"@types/chai-as-promised": "^7.1.
|
|
38
|
+
"@types/chai": "^4.3.6",
|
|
39
|
+
"@types/chai-as-promised": "^7.1.6",
|
|
40
40
|
"@types/mocha": "^10.0.1",
|
|
41
|
-
"@types/node": "^20.5.
|
|
41
|
+
"@types/node": "^20.5.9",
|
|
42
42
|
"@types/proxyquire": "^1.3.28",
|
|
43
43
|
"@types/sinon": "^10.0.16",
|
|
44
44
|
"@types/sinon-chai": "^3.2.9",
|
|
45
45
|
"chai": "^4.3.8",
|
|
46
46
|
"chai-as-promised": "^7.1.1",
|
|
47
|
-
"eslint": "^8.
|
|
47
|
+
"eslint": "^8.48.0",
|
|
48
48
|
"mocha": "^10.2.0",
|
|
49
49
|
"proxyquire": "^2.1.3",
|
|
50
50
|
"sinon": "^15.2.0",
|
|
51
51
|
"sinon-chai": "^3.7.0",
|
|
52
|
-
"typescript": "~5.
|
|
52
|
+
"typescript": "~5.2.2"
|
|
53
53
|
},
|
|
54
54
|
"main": "main.js",
|
|
55
55
|
"files": [
|