iobroker.senec 1.5.2 → 1.6.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 +3 -2
- package/admin/jsonConfig.json +157 -0
- package/io-package.json +21 -2
- package/main.js +128 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -366,8 +366,9 @@ 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.
|
|
370
|
-
* Added
|
|
369
|
+
### 1.6.0 (NoBl)
|
|
370
|
+
* Added option to also poll SENEC App API. This requires user credentials for mein-senec.de
|
|
371
|
+
* We are starting with just some information - more to follow. But with Dashboard we at least have current values and day statistics back.
|
|
371
372
|
|
|
372
373
|
### 1.5.1 (NoBl)
|
|
373
374
|
* Added more datapoints. If you experience messages in log - feel free to add them yourself to state_attr on github (pull request)
|
package/admin/jsonConfig.json
CHANGED
|
@@ -1086,6 +1086,163 @@
|
|
|
1086
1086
|
"newLine": false
|
|
1087
1087
|
}
|
|
1088
1088
|
}
|
|
1089
|
+
},
|
|
1090
|
+
"_api": {
|
|
1091
|
+
"type": "panel",
|
|
1092
|
+
"label": {
|
|
1093
|
+
"en": "SENEC API",
|
|
1094
|
+
"de": "SENEC API",
|
|
1095
|
+
"ru": "SENEC API",
|
|
1096
|
+
"pt": "API SENEC",
|
|
1097
|
+
"nl": "SENEC",
|
|
1098
|
+
"fr": "SENEC API",
|
|
1099
|
+
"it": "API SENEC",
|
|
1100
|
+
"es": "SENEC API",
|
|
1101
|
+
"pl": "SENEC API",
|
|
1102
|
+
"uk": "СЕНЕК API",
|
|
1103
|
+
"zh-cn": "SENECAPI"
|
|
1104
|
+
},
|
|
1105
|
+
"items": {
|
|
1106
|
+
"api_use": {
|
|
1107
|
+
"type": "checkbox",
|
|
1108
|
+
"sm": 12,
|
|
1109
|
+
"md": 6,
|
|
1110
|
+
"lg": 6,
|
|
1111
|
+
"label": {
|
|
1112
|
+
"en": "Use SENEC API?",
|
|
1113
|
+
"de": "SENEC API nutzen?",
|
|
1114
|
+
"ru": "Используйте SENEC API?",
|
|
1115
|
+
"pt": "Usar API SENEC?",
|
|
1116
|
+
"nl": "SENEC API gebruiken?",
|
|
1117
|
+
"fr": "Utilisez l'API SENEC?",
|
|
1118
|
+
"it": "Utilizzare API SENEC?",
|
|
1119
|
+
"es": "¿Usar SENEC API?",
|
|
1120
|
+
"pl": "Zastosowanie API SENEC?",
|
|
1121
|
+
"uk": "Використовуйте SENEC API?",
|
|
1122
|
+
"zh-cn": "使用ENECAPI?"
|
|
1123
|
+
},
|
|
1124
|
+
"help": {
|
|
1125
|
+
"en": "Check if the adapter shall make use of the SENEC API.",
|
|
1126
|
+
"de": "Aktivieren, falls der Adapter die SENEC API nutzen soll.",
|
|
1127
|
+
"ru": "Проверьте, следует ли адаптер использовать SENEC API.",
|
|
1128
|
+
"pt": "Verifique se o adaptador deve fazer uso da API SENEC.",
|
|
1129
|
+
"nl": "Kijk of de adapter gebruik maakt van de SENEC API.",
|
|
1130
|
+
"fr": "Vérifiez si l'adaptateur doit utiliser l'API SENEC.",
|
|
1131
|
+
"it": "Controllare se l'adattatore deve utilizzare l'API SENEC.",
|
|
1132
|
+
"es": "Compruebe si el adaptador hará uso de la API SENEC.",
|
|
1133
|
+
"pl": "W przypadku, gdy adapter będzie korzystał z API SENEC.",
|
|
1134
|
+
"uk": "Перевірте, чи використовує адаптер SENEC API.",
|
|
1135
|
+
"zh-cn": "如果适应者应使用ENECAPI。."
|
|
1136
|
+
},
|
|
1137
|
+
"default": "",
|
|
1138
|
+
"newLine": true
|
|
1139
|
+
},
|
|
1140
|
+
"api_mail": {
|
|
1141
|
+
"type": "text",
|
|
1142
|
+
"sm": 12,
|
|
1143
|
+
"md": 6,
|
|
1144
|
+
"lg": 6,
|
|
1145
|
+
"label": {
|
|
1146
|
+
"en": "Email-Address",
|
|
1147
|
+
"de": "E-Mail-Adresse",
|
|
1148
|
+
"ru": "Email-Адрес",
|
|
1149
|
+
"pt": "Endereço de email",
|
|
1150
|
+
"nl": "E-Addres",
|
|
1151
|
+
"fr": "Email-Address",
|
|
1152
|
+
"it": "Indirizzo e-mail",
|
|
1153
|
+
"es": "Email-Address",
|
|
1154
|
+
"pl": "Email-Addresser",
|
|
1155
|
+
"uk": "Електронна пошта",
|
|
1156
|
+
"zh-cn": "Email-Addres"
|
|
1157
|
+
},
|
|
1158
|
+
"help": {
|
|
1159
|
+
"en": "Email-Address used to login to mein-senec.de",
|
|
1160
|
+
"de": "Email-Adresse, um sich bei mein-senec.de anzumelden",
|
|
1161
|
+
"ru": "Email-адрес используется для входа в mein-senec.de",
|
|
1162
|
+
"pt": "Email-Endereço usado para login para mein-senec.de",
|
|
1163
|
+
"nl": "Email-Address loge in mein-senec",
|
|
1164
|
+
"fr": "Email-Adresse utilisé pour se connecter à mein-senec.de",
|
|
1165
|
+
"it": "Email-Address usato per accedere a mein-senec.de",
|
|
1166
|
+
"es": "Email-Address solía iniciar sesión en mein-senec.de",
|
|
1167
|
+
"pl": "Email-Address używany do logowania mein-senec",
|
|
1168
|
+
"uk": "Email-Address використовується для входу в mein-senec.de",
|
|
1169
|
+
"zh-cn": "Email-Address used to mein-senec.de"
|
|
1170
|
+
},
|
|
1171
|
+
"default": "",
|
|
1172
|
+
"newLine": true
|
|
1173
|
+
},
|
|
1174
|
+
"api_pwd": {
|
|
1175
|
+
"type": "password",
|
|
1176
|
+
"visible": true,
|
|
1177
|
+
"sm": 12,
|
|
1178
|
+
"md": 6,
|
|
1179
|
+
"lg": 6,
|
|
1180
|
+
"label": {
|
|
1181
|
+
"en": "Password",
|
|
1182
|
+
"de": "Passwort",
|
|
1183
|
+
"ru": "Пароль",
|
|
1184
|
+
"pt": "Senha",
|
|
1185
|
+
"nl": "Wachtwoord",
|
|
1186
|
+
"fr": "Mot de passe",
|
|
1187
|
+
"it": "Password",
|
|
1188
|
+
"es": "Contraseña",
|
|
1189
|
+
"pl": "Password",
|
|
1190
|
+
"uk": "Логін",
|
|
1191
|
+
"zh-cn": "护照"
|
|
1192
|
+
},
|
|
1193
|
+
"help": {
|
|
1194
|
+
"en": "Password used to login to mein-senec.de",
|
|
1195
|
+
"de": "Passwort für die Anmeldung an mein-senec.de",
|
|
1196
|
+
"ru": "Пароль используется для входа в mein-senec.de",
|
|
1197
|
+
"pt": "Senha usada para login para mein-senec.de",
|
|
1198
|
+
"nl": "Het wachtwoord loginde in mein-senec",
|
|
1199
|
+
"fr": "Mot de passe utilisé pour se connecter à mein-senec.de",
|
|
1200
|
+
"it": "Password usata per accedere a mein-senec.de",
|
|
1201
|
+
"es": "Contraseña usada para iniciar sesión en mein-senec.de",
|
|
1202
|
+
"pl": "Miecz używany do logowania na mein-senec.de",
|
|
1203
|
+
"uk": "Пароль використовується для входу в mein-senec.de",
|
|
1204
|
+
"zh-cn": "目 录"
|
|
1205
|
+
},
|
|
1206
|
+
"default": "",
|
|
1207
|
+
"newLine": false
|
|
1208
|
+
},
|
|
1209
|
+
"api_interval": {
|
|
1210
|
+
"type": "number",
|
|
1211
|
+
"sm": 12,
|
|
1212
|
+
"md": 6,
|
|
1213
|
+
"lg": 6,
|
|
1214
|
+
"label": {
|
|
1215
|
+
"en": "Polling Interval (minutes)",
|
|
1216
|
+
"de": "Polling Interval (Minuten)",
|
|
1217
|
+
"ru": "Поллинг Интервал (минуты)",
|
|
1218
|
+
"pt": "Polling Interval (minutos)",
|
|
1219
|
+
"nl": "Polling Interval (minuten)",
|
|
1220
|
+
"fr": "Intervalle de vote (minutes)",
|
|
1221
|
+
"it": "Polling Interval (minuti)",
|
|
1222
|
+
"es": "Intervalo de votación (minutos)",
|
|
1223
|
+
"pl": "Polling Interval (ang.)",
|
|
1224
|
+
"uk": "Поллінг Інтервал (хвилини)",
|
|
1225
|
+
"zh-cn": "中间(分钟)"
|
|
1226
|
+
},
|
|
1227
|
+
"help": {
|
|
1228
|
+
"en": "Here you can define the polling interval [min 3, max 1440 minutes]. Default = 5. SENEC updates API Data every 5 minutes.",
|
|
1229
|
+
"de": "Hier können Sie das Abfrageintervall definieren [min 3, max 1440 Minuten]. Standard = 5. SENEC aktualisiert die API-Daten alle 5 Minuten.",
|
|
1230
|
+
"ru": "Здесь вы можете определить интервал опроса [мин 3, макс 1440 минут]. По умолчанию = 5. SENEC обновление API Данные каждые 5 минут.",
|
|
1231
|
+
"pt": "Aqui você pode definir o intervalo de votação [min 3, max 1440 minutes]. Padrão = 5. API de atualizações do SENEC Dados a cada 5 minutos.",
|
|
1232
|
+
"nl": "Hier kun je de peiling interval definiëren. SenEC updates Data om de vijf minuten.",
|
|
1233
|
+
"fr": "Ici vous pouvez définir l'intervalle de vote [min 3, max 1440 minutes]. Défaut = 5. Données toutes les 5 minutes.",
|
|
1234
|
+
"it": "Qui è possibile definire l'intervallo di polling [min 3, max 1440 minuti]. Default = 5. Aggiornamenti SENEC API Dati ogni 5 minuti.",
|
|
1235
|
+
"es": "Aquí puede definir el intervalo de votación [min 3, max 1440 minutos]. Default = 5. Actualización de SENEC API Datos cada 5 minutos.",
|
|
1236
|
+
"pl": "Może ona zdefiniować przedział wyborczy (min 3, max 1440 minut). Default = 5. Dane co 5 minut.",
|
|
1237
|
+
"uk": "Тут можна визначити інтервал опитування [min 3, макс. 1440 хвилин]. JavaScript licenses API Веб-сайт Дані кожні 5 хвилин.",
|
|
1238
|
+
"zh-cn": "在此,你可以界定投票间隔[3, max1440分钟]。 Default=5 SENEC最新情况 数据每5分钟。."
|
|
1239
|
+
},
|
|
1240
|
+
"default": 5,
|
|
1241
|
+
"min": 3,
|
|
1242
|
+
"max": 1440,
|
|
1243
|
+
"newLine": true
|
|
1244
|
+
},
|
|
1245
|
+
}
|
|
1089
1246
|
}
|
|
1090
1247
|
}
|
|
1091
1248
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "senec",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.6.0": {
|
|
7
|
+
"en": "You can now configure to request SENEC App API.",
|
|
8
|
+
"de": "Sie können nun die SENEC App API abfragen.",
|
|
9
|
+
"ru": "Теперь вы можете настроить для запроса SENEC App API.",
|
|
10
|
+
"pt": "Agora você pode configurar para solicitar a API do SENEC App.",
|
|
11
|
+
"nl": "Je kunt nu configureren om SENEC App API te vragen.",
|
|
12
|
+
"fr": "Vous pouvez maintenant configurer pour demander l'API App SENEC.",
|
|
13
|
+
"it": "Ora è possibile configurare per richiedere l'API SENEC App.",
|
|
14
|
+
"es": "Ahora puede configurarse para solicitar SENEC App API.",
|
|
15
|
+
"pl": "Możesz teraz skonfigurować żądanie SENEC App API.",
|
|
16
|
+
"uk": "Ви можете налаштувати запит на SENEC App API.",
|
|
17
|
+
"zh-cn": "如今,你可以准备要求SENECSP。."
|
|
18
|
+
},
|
|
6
19
|
"1.5.2": {
|
|
7
20
|
"en": "Added more datapoints. If you experience messages in log - feel free to add them yourself to state_attr on github (pull request)",
|
|
8
21
|
"de": "Weitere Datenpunkte hinzugefügt. Du kennst weitere? Bitte PullRequest auf Github für state_attr.",
|
|
@@ -195,7 +208,13 @@
|
|
|
195
208
|
"highPrio_BAT1OBJ4": "",
|
|
196
209
|
"highPrio_BAT1OBJ4_active": false,
|
|
197
210
|
"highPrio_TEMPMEASURE": "",
|
|
198
|
-
"highPrio_TEMPMEASURE_active": false
|
|
211
|
+
"highPrio_TEMPMEASURE_active": false,
|
|
212
|
+
"api_use": false,
|
|
213
|
+
"api_interval": 5
|
|
214
|
+
},
|
|
215
|
+
"nativeEncrypted": {
|
|
216
|
+
"api_mail": "",
|
|
217
|
+
"api_pwd": ""
|
|
199
218
|
},
|
|
200
219
|
"objects": [],
|
|
201
220
|
"instanceObjects": [{
|
package/main.js
CHANGED
|
@@ -8,10 +8,19 @@ const agent = new https.Agent({
|
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
const utils = require('@iobroker/adapter-core');
|
|
11
|
+
|
|
11
12
|
const axios = require('axios').default;
|
|
13
|
+
axios.defaults.headers.common['Content-Type'] = "application/json";
|
|
14
|
+
|
|
12
15
|
const state_attr = require(__dirname + '/lib/state_attr.js');
|
|
13
16
|
const state_trans = require(__dirname + '/lib/state_trans.js');
|
|
17
|
+
const apiUrl = "https://app-gateway-prod.senecops.com/v1/senec";
|
|
18
|
+
const apiLoginUrl = apiUrl + "/login";
|
|
19
|
+
const apiSystemsUrl = apiUrl + "/anlagen";
|
|
20
|
+
const apiKnownSystems = []
|
|
14
21
|
|
|
22
|
+
let apiConnected = false;
|
|
23
|
+
let apiLoginToken = "";
|
|
15
24
|
let retry = 0; // retry-counter
|
|
16
25
|
let retryLowPrio = 0; // retry-counter
|
|
17
26
|
let connectVia = "http://";
|
|
@@ -52,8 +61,12 @@ class Senec extends utils.Adapter {
|
|
|
52
61
|
await this.checkConfig();
|
|
53
62
|
await this.initPollSettings();
|
|
54
63
|
await this.checkConnection();
|
|
64
|
+
await this.initSenecAppApi();
|
|
65
|
+
if (apiConnected) await this.getApiSystems();
|
|
55
66
|
await this.pollSenec(true, 0); // highPrio
|
|
56
67
|
await this.pollSenec(false, 0); // lowPrio
|
|
68
|
+
await this.pollSenecAppApi(0); // App API
|
|
69
|
+
this.setState('info.connection', true, true);
|
|
57
70
|
} catch (error) {
|
|
58
71
|
this.log.error(error);
|
|
59
72
|
this.setState('info.connection', false, true);
|
|
@@ -70,8 +83,8 @@ class Senec extends utils.Adapter {
|
|
|
70
83
|
if (this.timer) {
|
|
71
84
|
clearTimeout(this.timer);
|
|
72
85
|
}
|
|
73
|
-
if (this.
|
|
74
|
-
clearTimeout(this.
|
|
86
|
+
if (this.timerAPI) {
|
|
87
|
+
clearTimeout(this.timerAPI);
|
|
75
88
|
}
|
|
76
89
|
this.log.info('cleaned everything up...');
|
|
77
90
|
this.setState('info.connection', false, true);
|
|
@@ -207,6 +220,11 @@ class Senec extends utils.Adapter {
|
|
|
207
220
|
connectVia = "https://";
|
|
208
221
|
this.log.debug("(checkConf) Switching to https ... " + this.config.useHttps);
|
|
209
222
|
}
|
|
223
|
+
this.log.debug("(checkConf) Configured api polling interval: " + this.config.api_interval);
|
|
224
|
+
if (this.config.api_interval < 3 || this.config.api_interval > 1440) {
|
|
225
|
+
this.log.warn("(checkConf) Config api polling interval " + this.config.api_interval + " not [3..1440] seconds. Using default: 5");
|
|
226
|
+
this.config.api_interval = 5;
|
|
227
|
+
}
|
|
210
228
|
}
|
|
211
229
|
|
|
212
230
|
/**
|
|
@@ -217,23 +235,74 @@ class Senec extends utils.Adapter {
|
|
|
217
235
|
const form = '{"ENERGY":{"STAT_STATE":""}}';
|
|
218
236
|
try {
|
|
219
237
|
this.log.info('connecting to Senec: ' + url);
|
|
220
|
-
const body = await this.doGet(url, form, this, this.config.pollingTimeout);
|
|
238
|
+
const body = await this.doGet(url, form, this, this.config.pollingTimeout, true);
|
|
221
239
|
this.log.info('connected to Senec: ' + url);
|
|
222
|
-
this.setState('info.connection', true, true);
|
|
223
240
|
} catch (error) {
|
|
224
241
|
throw new Error("Error connecting to Senec (IP: " + connectVia + this.config.senecip + "). Exiting! (" + error + "). Try to toggle https-mode in settings and check FQDN of SENEC appliance.");
|
|
225
242
|
}
|
|
226
243
|
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Inits connection to senec app api
|
|
247
|
+
*/
|
|
248
|
+
async initSenecAppApi() {
|
|
249
|
+
if (!this.config.api_use) {
|
|
250
|
+
this.log.info('Usage of SENEC App API not configured. Not using it');
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
this.log.info('connecting to Senec App API: ' + apiLoginUrl);
|
|
254
|
+
const loginData = JSON.stringify({
|
|
255
|
+
password: this.config.api_pwd,
|
|
256
|
+
username: this.config.api_mail
|
|
257
|
+
});
|
|
258
|
+
try {
|
|
259
|
+
const body = await this.doGet(apiLoginUrl, loginData, this, this.config.pollingTimeout, true);
|
|
260
|
+
this.log.info('connected to Senec AppAPI.');
|
|
261
|
+
apiLoginToken = JSON.parse(body).token;
|
|
262
|
+
apiConnected = true;
|
|
263
|
+
axios.defaults.headers.common['authorization'] = apiLoginToken;
|
|
264
|
+
} catch (error) {
|
|
265
|
+
throw new Error("Error connecting to Senec AppAPI. Exiting! (" + error + ").");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Reads system data from senec app api
|
|
271
|
+
*/
|
|
272
|
+
async getApiSystems() {
|
|
273
|
+
const pfx = "_api.Anlagen.";
|
|
274
|
+
if (!this.config.api_use || !apiConnected) {
|
|
275
|
+
this.log.info('Usage of SENEC App API not configured or not connected.');
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
this.log.info('Reading Systems Information from Senec App API ' + apiSystemsUrl);
|
|
279
|
+
try {
|
|
280
|
+
const body = await this.doGet(apiSystemsUrl, "", this, this.config.pollingTimeout, false);
|
|
281
|
+
this.log.info('Read Systems Information from Senec AppAPI.');
|
|
282
|
+
var obj = JSON.parse(body);
|
|
283
|
+
const systems = [];
|
|
284
|
+
for (const[key, value] of Object.entries(obj)) {
|
|
285
|
+
const systemId = value.id;
|
|
286
|
+
apiKnownSystems.push(systemId);
|
|
287
|
+
for (const[key2, value2] of Object.entries(value)) {
|
|
288
|
+
this.doState(pfx + systemId + "." + key2, JSON.stringify(value2), "", "", false);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
this.doState(pfx + 'IDs', JSON.stringify(apiKnownSystems), "Anlagen IDs", "", false);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
throw new Error("Error reading Systems Information from Senec AppAPI. (" + error + ").");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
227
296
|
|
|
228
297
|
/**
|
|
229
298
|
* Read from url via axios
|
|
230
299
|
* @param url to read from
|
|
231
300
|
* @param form to post
|
|
232
301
|
*/
|
|
233
|
-
doGet(pUrl, pForm, caller, pollingTimeout) {
|
|
302
|
+
doGet(pUrl, pForm, caller, pollingTimeout, isPost) {
|
|
234
303
|
return new Promise(function (resolve, reject) {
|
|
235
304
|
axios({
|
|
236
|
-
method: 'post',
|
|
305
|
+
method: isPost ? 'post' : 'get',
|
|
237
306
|
httpsAgent: agent,
|
|
238
307
|
url: pUrl,
|
|
239
308
|
data: pForm,
|
|
@@ -251,6 +320,10 @@ class Senec extends utils.Adapter {
|
|
|
251
320
|
if (error.response) {
|
|
252
321
|
// The request was made and the server responded with a status code
|
|
253
322
|
caller.log.warn('(Poll) received error ' + error.response.status + ' response from SENEC with content: ' + JSON.stringify(error.response.data));
|
|
323
|
+
if (error.response.status == 403 && apiConnected) {
|
|
324
|
+
apiConnected = false; // apparently the api is inaccessible
|
|
325
|
+
this.initSenecAppApi();
|
|
326
|
+
}
|
|
254
327
|
reject(error.response.status);
|
|
255
328
|
} else if (error.request) {
|
|
256
329
|
// The request was made but no response was received
|
|
@@ -280,7 +353,7 @@ class Senec extends utils.Adapter {
|
|
|
280
353
|
}
|
|
281
354
|
|
|
282
355
|
try {
|
|
283
|
-
var body = await this.doGet(url, (isHighPrio ? highPrioForm : lowPrioForm), this, this.config.pollingTimeout);
|
|
356
|
+
var body = await this.doGet(url, (isHighPrio ? highPrioForm : lowPrioForm), this, this.config.pollingTimeout, true);
|
|
284
357
|
if (body.includes('\\"')) {
|
|
285
358
|
// in rare cases senec reports back extra escape sequences on some machines ...
|
|
286
359
|
this.log.info("(Poll) Double escapes detected! Body inc: " + body);
|
|
@@ -303,6 +376,53 @@ class Senec extends utils.Adapter {
|
|
|
303
376
|
this.timer = setTimeout(() => this.pollSenec(isHighPrio, retry), interval * this.config.retrymultiplier * retry);
|
|
304
377
|
}
|
|
305
378
|
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Read values from Senec App API
|
|
383
|
+
*/
|
|
384
|
+
async pollSenecAppApi(retry) {
|
|
385
|
+
var interval = this.config.api_interval * 60000;
|
|
386
|
+
this.log.debug("Polling API ...");
|
|
387
|
+
var body = "";
|
|
388
|
+
try {
|
|
389
|
+
for (let i = 0; i < apiKnownSystems.length; i++) {
|
|
390
|
+
// dashboard
|
|
391
|
+
var url = apiSystemsUrl + "/" + apiKnownSystems[i] + "/dashboard";
|
|
392
|
+
body = await this.doGet(url, "", this, this.config.pollingTimeout, false);
|
|
393
|
+
await this.decodeDashboard(apiKnownSystems[i], JSON.parse(body));
|
|
394
|
+
// // wallboxes - only if wallbox exists? - Without: error 500
|
|
395
|
+
//var url = apiSystemsUrl + "/" + apiKnownSystems[i] + "/wallboxes/1";
|
|
396
|
+
//body = await this.doGet(url, "", this, this.config.pollingTimeout, false);
|
|
397
|
+
//this.log.info("Abilities: " + body);
|
|
398
|
+
//await this.decodeWallbox(apiKnownSystems[i], JSON.parse(body));
|
|
399
|
+
}
|
|
400
|
+
retry = 0;
|
|
401
|
+
if (unloaded) return;
|
|
402
|
+
this.timerAPI = setTimeout(() => this.pollSenecAppApi(retry), interval);
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if ((retry == this.config.retries) && this.config.retries < 999) {
|
|
405
|
+
this.log.error("Error reading from Senec AppAPI. Retried " + retry + " times. Giving up now. Check config and restart adapter. (" + error + ")");
|
|
406
|
+
this.setState('info.connection', false, true);
|
|
407
|
+
} else {
|
|
408
|
+
retry += 1;
|
|
409
|
+
this.log.warn("Error reading from Senec AppAPI. Retry " + retry + "/" + this.config.retries + " in " + (interval * this.config.retrymultiplier * retry) / 1000 + " seconds! (" + error + ")");
|
|
410
|
+
this.timerAPI = setTimeout(() => this.pollSenecAppApi(retry), interval * this.config.retrymultiplier * retry);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async decodeDashboard(system, obj) {
|
|
416
|
+
const pfx = "_api.Anlagen." + system + ".Dashboard.";
|
|
417
|
+
for (const[key, value] of Object.entries(obj)) {
|
|
418
|
+
if (key == "zeitstempel" || key == "electricVehicleConnected") {
|
|
419
|
+
this.doState(pfx + key, value, "", "", false);
|
|
420
|
+
} else {
|
|
421
|
+
for (const[key2, value2] of Object.entries(value)) {
|
|
422
|
+
this.doState(pfx + key + "." + key2, value2.wert, "", value2.einheit, false);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
306
426
|
|
|
307
427
|
}
|
|
308
428
|
|
|
@@ -408,7 +528,7 @@ class Senec extends utils.Adapter {
|
|
|
408
528
|
if (value2 !== "VARIABLE_NOT_FOUND" && key2 !== "OBJECT_NOT_FOUND") {
|
|
409
529
|
const key = key1 + '.' + key2;
|
|
410
530
|
if (state_attr[key] === undefined) {
|
|
411
|
-
this.log.
|
|
531
|
+
this.log.debug('REPORT_TO_DEV: State attribute definition missing for: ' + key + ', Val: ' + value2);
|
|
412
532
|
}
|
|
413
533
|
const desc = (state_attr[key] !== undefined) ? state_attr[key].name : key2;
|
|
414
534
|
const unit = (state_attr[key] !== undefined) ? state_attr[key].unit : "";
|