iobroker.ebus 3.8.0 → 4.0.2

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/main.js DELETED
@@ -1,1807 +0,0 @@
1
- /* eslint-disable prefer-template */
2
- /*
3
- * ebus adapter für iobroker
4
- *
5
- * Created: 15.09.2016 21:31:28
6
- * Author: Rene
7
- *
8
-
9
- */
10
-
11
- /* jshint -W097 */ // jshint strict:false
12
- /*jslint node: true */
13
- "use strict";
14
-
15
- const utils = require("@iobroker/adapter-core");
16
- const os = require("os");
17
- //const { exec } = require("child_process");
18
- const { spawn } = require("child_process");
19
- const fs = require("fs");
20
- const path = require("path");
21
- const axios = require("axios");
22
- //const net = require("net");
23
- //const { PromiseSocket } = require("promise-socket");
24
-
25
- const telnetClient = require("./lib/TelnetClient");
26
-
27
- const ebusdMinVersion = [26, 1];
28
- const ebusdVersion = [0, 0];
29
- const ebusdUpdateVersion = [0, 0];
30
-
31
- let adapter;
32
- function startAdapter(options) {
33
- options = options || {};
34
- Object.assign(options, {
35
- name: "ebus",
36
- //#######################################
37
- //
38
- ready: function () {
39
- try {
40
- //adapter.log.debug('start');
41
- main();
42
- } catch (e) {
43
- adapter.log.error(`exception catch after ready [${ e }]`);
44
- }
45
- },
46
- //#######################################
47
- // is called when adapter shuts down
48
- unload: function (callback) {
49
- try {
50
- if (intervalID != null) {
51
- clearInterval(intervalID);
52
- }
53
- if (updateTimerID != null) {
54
- clearTimeout(updateTimerID);
55
- }
56
- adapter && adapter.log && adapter.log.info && adapter.log.info("cleaned everything up...");
57
- //to do stop intervall
58
- callback();
59
- } catch (e) {
60
- adapter.log.error(`exception catch after unload [${e}]`);
61
- callback();
62
- }
63
- },
64
-
65
- stateChange: async (id, state) => {
66
- await HandleStateChange(id, state);
67
- },
68
- //#######################################
69
- //
70
- message: async obj => {
71
- if (obj) {
72
- switch (obj.command) {
73
- case "findParams":
74
- adapter.log.debug("message FindParams called");
75
- await FindParams(obj);
76
- break;
77
- case "Install":
78
- adapter.log.debug("message install called");
79
- await CallExternalScript("InstallEbusd.sh", obj);
80
- break;
81
- case "Update":
82
- adapter.log.debug("message update called");
83
- await CallExternalScript("UpdateEbusd.sh", obj);
84
- break;
85
- case "checkInstallableversion":
86
- await CheckVersion("installable", obj);
87
- break;
88
- case "checkCurrentVersion":
89
- await CheckVersion("current", obj);
90
- break;
91
- case "checkSupportedVersion":
92
- await CheckVersion("supported", obj);
93
- break;
94
- default:
95
- adapter.log.error(`unknown message ${ obj.command}`);
96
- break;
97
- }
98
- }
99
- },
100
- //#######################################
101
- //
102
- });
103
- adapter = new utils.Adapter(options);
104
-
105
- return adapter;
106
- }
107
-
108
- let intervalID = null;
109
- let updateTimerID = null;
110
-
111
- async function main() {
112
- adapter.log.debug("start with interface ebusd ");
113
-
114
- FillPolledVars();
115
- FillHistoryVars();
116
- FillHTTPParamsVars();
117
-
118
- await checkVariables();
119
-
120
- await subscribeVars();
121
-
122
- let readInterval = 5;
123
- if (parseInt(adapter.config.readInterval) > 0) {
124
- readInterval = adapter.config.readInterval;
125
- }
126
- adapter.log.debug(`read every ${ readInterval } minutes`);
127
- intervalID = setInterval(Do, readInterval * 60 * 1000);
128
-
129
- //read at adapterstart
130
- await Do();
131
- }
132
-
133
- let requestRunning = false;
134
-
135
- async function DoRequest() {
136
- adapter.log.debug("DoRequest ");
137
-
138
- if (!requestRunning) {
139
- requestRunning = true;
140
- await ebusd_ReadValues();
141
-
142
- await ebusd_ReceiveData();
143
- } else {
144
- adapter.log.debug("DoRequest: do nothing already running ");
145
- }
146
- requestRunning = false;
147
- }
148
-
149
- async function Do() {
150
- adapter.log.debug("starting ... ");
151
-
152
- await ebusd_Command();
153
-
154
- await DoRequest();
155
- }
156
-
157
- async function HandleStateChange(id, state) {
158
- if (state != null && state.ack !== true) {
159
- adapter.log.debug(`handle state change ${ id}`);
160
- const ids = id.split(".");
161
-
162
- if (ids[2] === "cmd") {
163
- await ebusd_Command();
164
- StartDataRequest();
165
- //see issue #77: only one request possible
166
- //await Do();
167
- } else if (ids[2] === "find") {
168
- //unhandled state change ebus.0.find
169
- await ebusd_find();
170
- } else {
171
- adapter.log.warn(`unhandled state change ${ id}`);
172
- }
173
- }
174
- }
175
-
176
- function StartDataRequest() {
177
- if (updateTimerID != null) {
178
- //already running
179
- clearTimeout(updateTimerID);
180
- updateTimerID = null;
181
- }
182
- //start or restart
183
- updateTimerID = setTimeout(DataRequest, 500);
184
- adapter.log.debug("StartDataRequest");
185
- }
186
-
187
- async function DataRequest() {
188
- adapter.log.debug("get data after command and timeout");
189
- if (updateTimerID != null) {
190
- clearTimeout(updateTimerID);
191
- updateTimerID = null;
192
- }
193
- await DoRequest();
194
- }
195
-
196
- const oPolledVars = [];
197
- function FillPolledVars() {
198
- try {
199
- if (
200
- adapter.config.PolledDPs !== undefined &&
201
- adapter.config.PolledDPs != null &&
202
- adapter.config.PolledDPs.length > 0
203
- ) {
204
- adapter.log.debug("use new object list for polled vars");
205
-
206
- //2023-02-10 only active vars
207
- for (let i = 0; i < adapter.config.PolledDPs.length; i++) {
208
- if (adapter.config.PolledDPs[i].active) {
209
- oPolledVars.push(adapter.config.PolledDPs[i]);
210
- }
211
- }
212
- } else {
213
- //make it compatible to old versions
214
- adapter.log.debug(`check old comma separeted list for polled vars ${ adapter.config.PolledValues}`);
215
-
216
- if (adapter.config.PolledValues !== undefined
217
- && adapter.config.PolledValues != null
218
- && typeof adapter.config.PolledValues == "string") {
219
-
220
- const oPolled = adapter.config.PolledValues.split(",");
221
-
222
- if (oPolled.length > 0) {
223
- for (let i = 0; i < oPolled.length; i++) {
224
- if (oPolled[i].length > 0) {
225
- //console.log('add ' + oPolled[i]);
226
- const value = {
227
- circuit: "",
228
- name: oPolled[i],
229
- parameter: "",
230
- };
231
- oPolledVars.push(value);
232
- }
233
- }
234
- }
235
- }
236
- }
237
- } catch (e) {
238
- adapter.log.error(`exception in FillPolledVars [${ e }]`);
239
- }
240
-
241
- adapter.log.debug(`list of polled vars ${ JSON.stringify(oPolledVars)}`);
242
- }
243
-
244
- let oHistoryVars = [];
245
- function FillHistoryVars() {
246
- try {
247
- if (
248
- adapter.config.HistoryDPs !== undefined &&
249
- adapter.config.HistoryDPs != null &&
250
- adapter.config.HistoryDPs.length > 0
251
- ) {
252
- adapter.log.debug("use new object list for history vars");
253
- oHistoryVars = adapter.config.HistoryDPs;
254
- } else if (adapter.config.HistoryValues !== undefined && typeof adapter.config.HistoryValues === "string") {
255
- //make it compatible to old versions
256
- adapter.log.debug("check old comma separeted list for history vars");
257
- const oHistory = adapter.config.HistoryValues.split(",");
258
-
259
- if (oHistory.length > 0) {
260
- for (let i = 0; i < oHistory.length; i++) {
261
- if (oHistory[i].length > 0) {
262
- console.log(`add ${oHistory[i]}`);
263
- const value = {
264
- name: oHistory[i],
265
- };
266
- oHistoryVars.push(value);
267
- }
268
- }
269
- }
270
- }
271
- } catch (e) {
272
- adapter.log.error(`exception in function FillHistoryVars [${e}]`);
273
- }
274
-
275
- adapter.log.debug(`list of history vars ${JSON.stringify(oHistoryVars)}`);
276
-
277
- //add a check, that complete dp without ebus.0 is used 2025-08-20
278
-
279
- oHistoryVars.forEach((entry, index) => {
280
- const hasDot = entry.name.includes(".");
281
- const hasInstance = entry.name.includes("ebus.");
282
- const hasValue = entry.name.includes("value");
283
-
284
- adapter.log.debug("checking " + entry.name + " index " + index + " hasDot: " + hasDot + " hasInstance: " + hasInstance + " hasValue: " + hasValue);
285
-
286
-
287
- if (!hasDot) {
288
- adapter.log.warn("please check history variable: " + entry.name + " -> should contain the complete DP");
289
- }
290
-
291
- if (!hasValue) {
292
- adapter.log.warn("please check history variable " + entry.name + " -> should contain 'value'");
293
- }
294
-
295
- if (hasInstance) {
296
- adapter.log.warn("please check history variable " + entry.name + " -> should not contain instance name and instance number e.g. 'ebus.0' ");
297
- }
298
-
299
- });
300
-
301
- //list of history vars [{"name":"ActualEnvironmentPower"},{"name":"YieldTotal"},{"name":"SourceTempInput"},{"name":"SourceTempOutput"},{"name":"HwcTemp"}]
302
-
303
- }
304
-
305
- let oHTTPParamsVars = [];
306
- function FillHTTPParamsVars() {
307
- if (
308
- adapter.config.HTTPparameter !== undefined &&
309
- adapter.config.HTTPparameter != null &&
310
- adapter.config.HTTPparameter.length > 0
311
- ) {
312
- oHTTPParamsVars = adapter.config.HTTPparameter;
313
-
314
- adapter.log.debug(`use optionally HTTP parameter ${ JSON.stringify(oHTTPParamsVars)}`);
315
- }
316
- }
317
-
318
- //===================================================================================================
319
- // ebusd interface
320
-
321
- async function ebusd_Command() {
322
- const obj = await adapter.getStateAsync("cmd");
323
-
324
- if (obj !== undefined && obj != null) {
325
- const cmds = obj.val;
326
- if (cmds !== "") {
327
- adapter.log.debug(`got command(s): ${ cmds}`);
328
-
329
- adapter.log.debug(`connect telnet to IP ${ adapter.config.targetIP } port ${ parseInt(adapter.config.targetTelnetPort)}`);
330
-
331
- try {
332
- //const socket = new net.Socket();
333
- //const promiseSocket = new PromiseSocket(socket);
334
-
335
- //await promiseSocket.connect(parseInt(adapter.config.targetTelnetPort), adapter.config.targetIP);
336
- //adapter.log.debug("telnet connected for cmd");
337
- //promiseSocket.setTimeout(5000);
338
-
339
- const telnet = new telnetClient();
340
- await telnet.connect(adapter.config.targetIP, parseInt(adapter.config.targetTelnetPort));
341
-
342
- const oCmds = cmds.split(",");
343
-
344
- if (oCmds.length > 0) {
345
- let received = "";
346
- for (let n = 0; n < oCmds.length; n++) {
347
- adapter.log.debug(`send ${ oCmds[n]}`);
348
- //await promiseSocket.write(`${oCmds[n] }\n`);
349
- await telnet.write(`${oCmds[n]}\n`);
350
-
351
- //const data = await promiseSocket.read();
352
- const data = await telnet.read();
353
-
354
- if (data.includes("ERR")) {
355
- adapter.log.warn(`sent ${ oCmds[n] }, received ${ data } please check ebusd logs for details!`);
356
-
357
- } else {
358
- adapter.log.debug(`received ${ data}`);
359
- }
360
- received += data.toString();
361
- received += ", ";
362
- }
363
-
364
- //see issue #78: remove CR, LF and last comma
365
- received = received.replace(/\r?\n|\r/g, "");
366
- received = received.slice(0, -2);
367
-
368
- //set result to cmdResult
369
- await adapter.setStateAsync("cmdResult", { ack: true, val: received });
370
- } else {
371
- adapter.log.warn(`no commands in list ${ cmds } ${ JSON.stringify(oCmds)}`);
372
- }
373
- await adapter.setStateAsync("cmd", { ack: true, val: "" });
374
-
375
- //promiseSocket.destroy();
376
- await telnet.disconnect();
377
- } catch (e) {
378
- adapter.log.error(`exception from tcp socket` + `[${ e }]`);
379
- }
380
- }
381
- } else {
382
- adapter.log.debug(`object cmd not found ${ JSON.stringify(obj)}`);
383
- }
384
- }
385
-
386
- async function ebusd_find() {
387
- try {
388
- //const socket = new net.Socket();
389
- //const promiseSocket = new PromiseSocket(socket);
390
-
391
- //await promiseSocket.connect(parseInt(adapter.config.targetTelnetPort), adapter.config.targetIP);
392
- //adapter.log.debug("telnet connected for cmd");
393
- //promiseSocket.setTimeout(5000);
394
- const telnet = new telnetClient();
395
- await telnet.connect(adapter.config.targetIP, parseInt(adapter.config.targetTelnetPort));
396
-
397
-
398
- //await promiseSocket.write("find -F circuit,name,comment\n");
399
- await telnet.write("find -F circuit,name,comment\n");
400
-
401
- //const data = await promiseSocket.read();
402
- const data = await telnet.read();
403
-
404
- if (data.includes("ERR")) {
405
- adapter.log.warn(`received error! sent find, received ${ data } please check ebusd logs for details!`);
406
- } else {
407
- adapter.log.debug(`received ${ typeof data } ${ data}`);
408
- }
409
-
410
- const str = new TextDecoder().decode(data);
411
- const datas = str.split(/\r?\n/);
412
-
413
- for (let i = 0; i < datas.length; i++) {
414
- //adapter.log.debug(JSON.stringify(datas[i]));
415
-
416
- const names = datas[i].split(",");
417
-
418
- //circuit,name,comment
419
- await UpdateDP(names[0], names[1], names[2]);
420
-
421
- let cmd = `read -f -c ${ names[0] } ${ names[1]}` ;
422
-
423
- adapter.log.debug(`send cmd ${ cmd}`);
424
-
425
- cmd += "\n";
426
- //await promiseSocket.write(cmd);
427
- await telnet.write(cmd);
428
-
429
- //const result = await promiseSocket.read();
430
- const result = await telnet.read();
431
-
432
- adapter.log.debug(`received ${ typeof result } ${ result}`);
433
- }
434
-
435
- //promiseSocket.destroy();
436
- await telnet.disconnect();
437
-
438
- } catch (e) {
439
- adapter.log.error(`exception from tcp socket in ebusd_find` + `[${ e }]`);
440
- }
441
- }
442
-
443
- //just call http://192.168.0.123:8889/data
444
-
445
- /*
446
- http://localhost:8080/data/mc?verbose&since=1483890000&exact
447
-
448
- since=seconds: limit to messages that have changed since the specified UTC seconds
449
- poll=prio: set the poll priority of matching message(s) to prio
450
- exact[=true]: exact search for circuit/message name
451
- verbose[=true]: include comments and field units
452
- indexed[=true]: return field indexes instead of names
453
- numeric[=true]: return numeric values of value list entries
454
- valuename[=true]: include value and name of value list entries
455
- full[=true]: include all available attributes
456
- required[=true]: retrieve the data from the bus if not yet cached
457
- maxage[=seconds]: retrieve the data from the bus if cached value is older than specified seconds (or not present at all)
458
- write[=true]: include write messages in addition to read
459
- raw[=true]: include the raw master/slave symbols as int arrays
460
- def[=true]: include message/field definition (qq, id, fielddefs)
461
- define=DEFINITION: (re-)define the message from DEFINITION (in CSV format)
462
- user=USER: authenticate with USER name
463
- secret=SECRET: authenticate with user SECRET
464
-
465
-
466
- */
467
-
468
- async function subscribeVars() {
469
- adapter.subscribeStates("cmd");
470
-
471
- adapter.subscribeStates("find");
472
-
473
- await adapter.setStateAsync("cmdResult", { ack: true, val: "" });
474
- }
475
-
476
- async function CreateObject(key, obj) {
477
- const obj_new = await adapter.getObjectAsync(key);
478
- //adapter.log.warn("got object " + JSON.stringify(obj_new));
479
-
480
- if (obj_new != null) {
481
- if (
482
- (obj_new.common.role != obj.common.role ||
483
- obj_new.common.type != obj.common.type ||
484
- (obj_new.common.unit != obj.common.unit && obj.common.unit != null) ||
485
- obj_new.common.read != obj.common.read ||
486
- obj_new.common.write != obj.common.write ||
487
- obj_new.common.name != obj.common.name) &&
488
- obj.type === "state"
489
- ) {
490
- adapter.log.warn(`change object ${ JSON.stringify(obj) } ${ JSON.stringify(obj_new)}`);
491
- await adapter.extendObject(key, {
492
- common: {
493
- name: obj.common.name,
494
- role: obj.common.role,
495
- type: obj.common.type,
496
- unit: obj.common.unit,
497
- read: obj.common.read,
498
- write: obj.common.write,
499
- },
500
- });
501
- }
502
- } else {
503
- await adapter.setObjectNotExistsAsync(key, obj);
504
- }
505
- }
506
-
507
- //circuit,name,comment
508
- async function UpdateDP(circuit, name, comment) {
509
- const key = `${circuit }.messages.${ name}`;
510
- adapter.log.debug(`update check for ${ key}`);
511
-
512
- // ehp.messages.Injection
513
- //ebus.0.ehp.messages.Injection
514
-
515
- const obj = await adapter.getObjectAsync(key);
516
- adapter.log.debug(`update check got ${ JSON.stringify(obj)}`);
517
-
518
- //update check got null
519
-
520
- if (obj != null) {
521
- if (obj.common.name != comment) {
522
- adapter.log.debug(`update ${ key } ${ comment}`);
523
- await adapter.extendObject(key, {
524
- common: {
525
- name: comment,
526
- read: true,
527
- write: false,
528
- },
529
- });
530
- }
531
- } else {
532
- await adapter.setObjectNotExistsAsync(key, {
533
- type: "channel",
534
- common: {
535
- name: comment,
536
- read: true,
537
- write: false,
538
- },
539
- });
540
- }
541
- }
542
-
543
- async function checkVariables() {
544
- adapter.log.debug("init variables ");
545
-
546
- let key;
547
- let obj;
548
-
549
- key = "cmd";
550
- obj = {
551
- type: "state",
552
- common: {
553
- name: "ebusd command",
554
- type: "string",
555
- role: "text",
556
- read: true,
557
- write: true,
558
- },
559
- };
560
- await CreateObject(key, obj);
561
-
562
- key = "cmdResult";
563
- obj = {
564
- type: "state",
565
- common: {
566
- name: "ebusd command result",
567
- type: "string",
568
- role: "text",
569
- read: true,
570
- write: false,
571
- },
572
- };
573
- await CreateObject(key, obj);
574
-
575
- key = "find";
576
- obj = {
577
- type: "state",
578
- common: {
579
- name: "find existing data points",
580
- type: "boolean",
581
- role: "button",
582
- read: false,
583
- write: true,
584
- },
585
- };
586
- await CreateObject(key, obj);
587
-
588
- adapter.log.debug(`init common variables and ${ oHistoryVars.length } history DP's`);
589
-
590
- if (oHistoryVars.length > 0) {
591
- if (oHistoryVars.length > 4) {
592
- adapter.log.warn(`too many history values ${ oHistoryVars.length } -> maximum is 4`);
593
- }
594
-
595
- for (let n = 1; n <= oHistoryVars.length; n++) {
596
- if (oHistoryVars[n - 1].name.length > 0) {
597
- const name = `history value ${ n } as JSON ${ oHistoryVars[n - 1].name}`;
598
- key = `history.value${ n}`;
599
- obj = {
600
- type: "state",
601
- common: {
602
- name: name,
603
- type: "string",
604
- role: "value",
605
- unit: "",
606
- read: true,
607
- write: false,
608
- },
609
- native: { location: key },
610
- };
611
- await CreateObject(key, obj);
612
- } else {
613
- adapter.log.warn(`ignoring history value ${ n } (invalid name)`);
614
- }
615
- }
616
-
617
- key = "history.date";
618
- obj = {
619
- type: "state",
620
- common: {
621
- name: "ebus history date / time as JSON",
622
- type: "string",
623
- role: "value",
624
- unit: "",
625
- read: true,
626
- write: false,
627
- },
628
- native: {
629
- location: key,
630
- },
631
- };
632
- await CreateObject(key, obj);
633
- }
634
- key = "history.error";
635
- obj = {
636
- type: "state",
637
- common: {
638
- name: "ebus error",
639
- type: "string",
640
- role: "value",
641
- unit: "",
642
- read: true,
643
- write: false,
644
- },
645
- native: { location: key },
646
- };
647
- await CreateObject(key, obj);
648
- }
649
-
650
- function VersionCheck() {
651
- if (ebusdVersion[0] > 0) {
652
- if (
653
- ebusdVersion[0] < ebusdMinVersion[0] ||
654
- (ebusdVersion[0] == ebusdMinVersion[0] && ebusdVersion[1] < ebusdMinVersion[1])
655
- ) {
656
- adapter.log.info(`please update ebusd, old version found: ${ ebusdVersion[0] }.${ ebusdVersion[1] } supported version is ${ ebusdMinVersion[0] }.${ ebusdMinVersion[1]}`);
657
- }
658
- if (
659
- ebusdVersion[0] > ebusdMinVersion[0] ||
660
- (ebusdVersion[0] >= ebusdMinVersion[0] && ebusdVersion[1] > ebusdMinVersion[1])
661
- ) {
662
- adapter.log.info(`unsupported ebusd version found (too new): ${ ebusdVersion[0] }.${ ebusdVersion[1] } supported version is ${ ebusdMinVersion[0] }.${ ebusdMinVersion[1]}`);
663
- }
664
- }
665
-
666
- if (ebusdUpdateVersion[0] > 0 && ebusdVersion[0] > 0) {
667
- if (
668
- ebusdUpdateVersion[0] > ebusdVersion[0] ||
669
- (ebusdUpdateVersion[0] == ebusdVersion[0] && ebusdUpdateVersion[1] > ebusdVersion[1])
670
- ) {
671
- adapter.log.info(`new ebusd version found: ${ ebusdUpdateVersion[0] }.${ ebusdUpdateVersion[1] } supported version is ${ ebusdMinVersion[0] }.${ ebusdMinVersion[1]}`);
672
-
673
- }
674
- }
675
- }
676
-
677
- //get data via https in json -> this is the main data receiver; telnet just triggers ebusd to read data;
678
- //https://github.com/john30/ebusd/wiki/3.2.-HTTP-client
679
-
680
- async function ebusd_ReceiveData() {
681
- try {
682
- let sUrl = `http://${ adapter.config.targetIP }:${ parseInt(adapter.config.targetHTTPPort) }/data`;
683
-
684
- //Erweiterung mit optionalen parametern
685
- var paramsCnt = 0;
686
- if (oHTTPParamsVars !== undefined && oHTTPParamsVars != null && oHTTPParamsVars.length > 0) {
687
- for (let i = 0; i < oHTTPParamsVars.length; i++) {
688
- if (oHTTPParamsVars[i].active) {
689
- if (paramsCnt == 0) {
690
- sUrl += "?";
691
- } else {
692
- sUrl += "&";
693
- }
694
- sUrl += `${oHTTPParamsVars[i].name }=${ oHTTPParamsVars[i].value}`;
695
- paramsCnt++;
696
- }
697
- }
698
- }
699
-
700
- adapter.log.debug(`request data from ${ sUrl}`);
701
- const buffer = await axios.get(sUrl);
702
-
703
- adapter.log.debug(`got data ${ typeof buffer.data } ${ JSON.stringify(buffer.data)}`);
704
-
705
- const flattenObject = (obj, delimiter = ".", prefix = "") =>
706
- Object.keys(obj).reduce((acc, k) => {
707
- const pre = prefix.length ? `${prefix}${delimiter}` : "";
708
- if (typeof obj[k] === "object" && obj[k] !== null && Object.keys(obj[k]).length > 0) {
709
- Object.assign(acc, flattenObject(obj[k], delimiter, pre + k));
710
- } else {
711
- acc[pre + k] = obj[k];
712
- }
713
- return acc;
714
- }, {});
715
-
716
- let data = flattenObject(buffer.data, ".");
717
-
718
- const historyvalues = [];
719
- const historydates = [];
720
-
721
- const oToday = new Date();
722
- const month = oToday.getMonth() + 1;
723
-
724
- historydates.push({
725
- date: `${oToday.getDate() }.${ month }.${ oToday.getFullYear()}`,
726
- time: `${oToday.getHours() }:${ oToday.getMinutes() }:${ oToday.getSeconds()}`
727
- });
728
-
729
- let sError = "none";
730
-
731
- for (let key in data) {
732
- const subnames = key.split(".");
733
- //const namelength = subnames.length;
734
- let value = data[key];
735
-
736
- //adapter.log.debug("key " + key);
737
-
738
- if (key.includes("[") || key.includes("]")) {
739
- adapter.log.debug(`found unsupported chars in ${ key}`);
740
- const start = key.indexOf("[");
741
- const end = key.lastIndexOf("]");
742
-
743
- if (start > 0 && end > 0) {
744
- const toReplace = key.slice(start, end + 1);
745
- key = key.replace(toReplace, "");
746
- }
747
- //adapter.log.warn("new key is " + key);
748
- }
749
-
750
- //======== version check
751
- if (key.includes("global.version")) {
752
- //adapter.log.info("in version, value " + value);
753
- const versionInfo = value.split(".");
754
- if (versionInfo.length > 1) {
755
- adapter.log.debug(`installed ebusd version is ${ versionInfo[0] }.${ versionInfo[1]}`);
756
-
757
- ebusdVersion[0] = versionInfo[0];
758
- ebusdVersion[1] = versionInfo[1];
759
-
760
- VersionCheck();
761
- }
762
- }
763
-
764
- if (key.includes("global.updatecheck")) {
765
- //revision v21.2 available
766
- value = value.replace("revision v", "");
767
- value = value.replace(" available", "");
768
-
769
- const versionInfo = value.split(".");
770
- if (versionInfo.length > 1) {
771
- adapter.log.info(`found ebusd update version ${ versionInfo[0] }.${ versionInfo[1]}`);
772
-
773
- ebusdUpdateVersion[0] = versionInfo[0];
774
- ebusdUpdateVersion[1] = versionInfo[1];
775
-
776
- VersionCheck();
777
- }
778
- }
779
-
780
- //============ type check
781
- let type = typeof value;
782
-
783
- if (adapter.config.useBoolean4Onoff) {
784
- if (type == "string" && (value == "on" || value == "off")) {
785
- adapter.log.debug(`Key ${ key } change to boolean ${ value}`);
786
- //Key mc.messages.Status.fields.1.value could be boolean off
787
-
788
- type = "boolean";
789
-
790
- if (value == "on") {
791
- value = true;
792
- } else {
793
- value = false;
794
- }
795
- }
796
- }
797
-
798
- //EVU Sperrzeit
799
- if (key.includes(".hcmode2.value") || key.includes(".hcmode.value")) {
800
- if (parseInt(value) === 0) {
801
- adapter.log.info(`${key }in hcmode2 with value 0: off`);
802
- value = "off";
803
- } else if (parseInt(value) === 5) {
804
- adapter.log.info(`${key } with value 5: EVU Sperrzeit`);
805
- value = "EVU Sperrzeit";
806
- } else {
807
- adapter.log.debug(`in hcmode2, value ${ value}`);
808
- }
809
- type = typeof value;
810
- }
811
-
812
- //lastup umrechnen
813
- if (key.includes(".lastup")) {
814
- if (parseInt(value) > 0) {
815
- //adapter.log.debug('Key : ' + key + ', Value : ' + newData[key] + " name " + name);
816
-
817
- //umrechnen...
818
- const oDate = new Date(value * 1000);
819
- //const nDate = oDate.getDate();
820
- //const nMonth = oDate.getMonth() + 1;
821
- //const nYear = oDate.getFullYear();
822
- //const nHours = oDate.getHours();
823
- //const nMinutes = oDate.getMinutes();
824
- //const nSeconds = oDate.getSeconds();
825
-
826
- const sDate = oDate.toLocaleString();
827
-
828
- value = sDate;
829
- type = typeof value;
830
-
831
- const oToday = new Date();
832
-
833
- let bSkip = false;
834
-
835
- if (
836
- subnames[0].includes("scan") ||
837
- subnames[0].includes("Scan") ||
838
- subnames[0].includes("ehp") ||
839
- (subnames.length > 2 && subnames[2].includes("currenterror")) ||
840
- adapter.config.DisableTimeUpdateCheck
841
- ) {
842
- bSkip = true;
843
- }
844
-
845
- //adapter.log.debug("_______________size " + temp);
846
- if (subnames.length > 2 && subnames[2].includes("Timer")) {
847
- bSkip = true;
848
- }
849
-
850
- if (!bSkip && Math.abs(oDate.getTime() - oToday.getTime()) > 1 * 60 * 60 * 1000) {
851
- const sError1 = `no update since ${ sDate } ${ key } `;
852
- if (sError.includes("none")) {
853
- sError = `ebus: ${ sError1}`;
854
- } else {
855
- sError += sError1;
856
- }
857
- adapter.log.warn(sError1);
858
- }
859
- }
860
- }
861
-
862
- //add and update data
863
- await AddObject(key, type);
864
- await UpdateObject(key, value);
865
-
866
- //push to history
867
-
868
- for (let ii = 0; ii < oHistoryVars.length; ii++) {
869
-
870
- //adapter.log.debug("check " + key + "==" + oHistoryVars[ii].name);
871
-
872
- // check uih.messages.YieldThisYear.fields.energy_1.value==ActualEnvironmentPower
873
-
874
- /*
875
- ehp.messages.ActualEnvironmentPower.fields.value.value
876
- ehp.messages.YieldTotal.fields.value.value
877
- ehp.messages.SourceTempInput.fields.temp.value
878
- ehp.messages.SourceTempOutput.fields.temp.value
879
- ehp.messages.HwcTemp.fields.temp.value
880
- */
881
-
882
-
883
- if (key === oHistoryVars[ii].name) {
884
- const sTemp = '{"' + key + '": "' + value + '"}';
885
- adapter.log.debug("push history " + sTemp);
886
- historyvalues[ii] = [];
887
- historyvalues[ii].push(JSON.parse(sTemp));
888
- //adapter.log.debug(JSON.stringify(historyvalues));
889
- }
890
- }
891
- }
892
-
893
- await adapter.setStateAsync("history.error", { ack: true, val: sError });
894
-
895
- //adapter.log.debug(JSON.stringify(historyvalues));
896
-
897
- adapter.log.debug("all http done");
898
-
899
- if (historyvalues.length > 0 && historydates.length > 0) {
900
- if (adapter.config.History4Vis2) {
901
- await UpdateHistory_Vis2(historyvalues, historydates);
902
- } else {
903
- await UpdateHistory(historyvalues, historydates);
904
- }
905
- }
906
- } catch (e) {
907
- adapter.log.error(`exception in ebusd_ReceiveData [${ e }]`);
908
-
909
- await adapter.setStateAsync("history.error", { ack: true, val: "exception in receive" });
910
- }
911
- }
912
-
913
- /*
914
- async function ebusd_ReceiveData_old() {
915
-
916
- let sUrl = "http://" + adapter.config.targetIP + ":" + parseInt(adapter.config.targetHTTPPort) + "/data";
917
-
918
- //Erweiterung mit optionalen parametern
919
- var paramsCnt = 0;
920
- if (oHTTPParamsVars !== undefined && oHTTPParamsVars != null && oHTTPParamsVars.length > 0) {
921
- for (let i = 0; i < oHTTPParamsVars.length; i++) {
922
-
923
- if (oHTTPParamsVars[i].active) {
924
- if (paramsCnt == 0) {
925
- sUrl += "?" ;
926
- }
927
- else {
928
- sUrl += "&";
929
- }
930
- sUrl += oHTTPParamsVars[i].name + "=" + oHTTPParamsVars[i].value;
931
- paramsCnt++;
932
- }
933
- }
934
- }
935
-
936
- adapter.log.debug("request data from " + sUrl);
937
-
938
- if (adapter.config.DisableTimeUpdateCheck === undefined) {
939
- adapter.log.error("please check config, DisableTimeUpdateCheck not defined yet ");
940
- }
941
-
942
-
943
-
944
- try {
945
-
946
- const buffer = await axios.get(sUrl);
947
-
948
- adapter.log.debug("got data " + typeof buffer.data + " " + JSON.stringify(buffer.data));
949
-
950
- //workaround issue #338
951
- //const oData = buffer.data;
952
-
953
- //erst nach string
954
- const sData = JSON.stringify(buffer.data);
955
-
956
- const oData = JSON.parse(sData.replace('\"updatecheck\": \"\n', '\"updatecheck\": \"'));
957
-
958
- //adapter.log.debug("000 " + typeof oData + JSON.stringify(oData));
959
-
960
- adapter.log.debug("oData " + oData);
961
-
962
- const newData = flatten.flattenDeep(oData);
963
-
964
- adapter.log.debug("111 " + JSON.stringify(newData));
965
-
966
- const keys = Object.keys(newData);
967
-
968
- //adapter.log.debug("222 " + JSON.stringify(keys));
969
-
970
- //adapter.log.debug("history: " + options.historyValues);
971
-
972
- const historyvalues = [];
973
- const historydates = [];
974
-
975
- const oToday = new Date();
976
- const month = oToday.getMonth() + 1;
977
-
978
- historydates.push({
979
- "date": oToday.getDate() + "." + month + "." + oToday.getFullYear(),
980
- "time": oToday.getHours() + ":" + oToday.getMinutes() + ":" + oToday.getSeconds()
981
- });
982
- //adapter.log.debug(JSON.stringify(historydates));
983
-
984
- let name = "unknown";
985
- let sError = "none";
986
- for (let i = 0; i < keys.length; i++) {
987
- let key = keys[i];
988
- const org_key = key;
989
-
990
- if (key.includes("[") || key.includes("]")) {
991
- adapter.log.debug("found unsupported chars in " + key);
992
- const start = key.indexOf("[");
993
- const end = key.lastIndexOf("]");
994
-
995
- if (start > 0 && end > 0) {
996
- const toReplace = key.slice(start, end + 1);
997
- key = key.replace(toReplace, "");
998
- }
999
- //adapter.log.warn("new key is " + key);
1000
- }
1001
-
1002
- const subnames = key.split(".");
1003
- const temp = subnames.length;
1004
- //adapter.log.debug('Key : ' + key + ', Value : ' + newData[key]);
1005
-
1006
- //
1007
- //if (key.match(adapter.FORBIDDEN_CHARS)) { continue; }
1008
-
1009
-
1010
- if (key.includes("global.version")) {
1011
- const value = newData[org_key];
1012
- //adapter.log.info("in version, value " + value);
1013
- const versionInfo = value.split(".");
1014
- if (versionInfo.length > 1) {
1015
- adapter.log.info("installed ebusd version is " + versionInfo[0] + "." + versionInfo[1]);
1016
-
1017
- ebusdVersion[0] = versionInfo[0];
1018
- ebusdVersion[1] = versionInfo[1];
1019
-
1020
- VersionCheck();
1021
- }
1022
- }
1023
-
1024
- if (key.includes("global.updatecheck")) {
1025
- let value = newData[org_key];
1026
- //adapter.log.info("in version, value " + value);
1027
-
1028
- //revision v21.2 available
1029
- value = value.replace("revision v", "");
1030
- value = value.replace(" available", "");
1031
-
1032
- const versionInfo = value.split(".");
1033
- if (versionInfo.length > 1) {
1034
- adapter.log.info("found ebusd update version " + versionInfo[0] + "." + versionInfo[1]);
1035
-
1036
- ebusdUpdateVersion[0] = versionInfo[0];
1037
- ebusdUpdateVersion[1] = versionInfo[1];
1038
-
1039
- VersionCheck();
1040
- }
1041
- }
1042
-
1043
-
1044
-
1045
- if (subnames[temp - 1].includes("name")) {
1046
- name = newData[org_key];
1047
- }
1048
- else if (subnames[temp - 1].includes("value")) {
1049
- //adapter.log.debug('Key : ' + key + ', Value : ' + newData[key] + " name " + name);
1050
-
1051
- let value = newData[org_key];
1052
-
1053
- if (value == null || value === undefined) {
1054
- adapter.log.debug("Key : " + key + ", Value : " + newData[org_key] + " name " + name);
1055
- }
1056
-
1057
-
1058
- if (name === "hcmode2") {
1059
- if (parseInt(value) === 0) {
1060
- adapter.log.info(key + "in hcmode2 with value 0: off");
1061
- value = "off";
1062
- }
1063
- else if (parseInt(value) === 5) {
1064
- adapter.log.info(key + " with value 5: EVU Sperrzeit");
1065
- value = "EVU Sperrzeit";
1066
- }
1067
- else {
1068
- adapter.log.debug("in hcmode2, value " + value);
1069
- }
1070
- }
1071
-
1072
- let type = typeof value;
1073
-
1074
- if (adapter.config.useBoolean4Onoff) {
1075
- if (type == "string" && (value == "on" || value == "off")) {
1076
- adapter.log.debug("Key " + key + " change to boolean " + value);
1077
- //Key mc.messages.Status.fields.1.value could be boolean off
1078
-
1079
- type = "boolean";
1080
-
1081
- if (value == "on") {
1082
- value = true;
1083
- }
1084
- else {
1085
- value = false;
1086
- }
1087
-
1088
- }
1089
- }
1090
- //value, change type if necessary
1091
- await AddObject(key, type);
1092
- await UpdateObject(key, value);
1093
-
1094
- //name parallel to value: used for lists in admin...
1095
- const keyname = key.replace("value", "name");
1096
- await AddObject(keyname, "string");
1097
-
1098
- await UpdateObject(keyname, name);
1099
-
1100
- //push to history
1101
- //ebus.0.bai.messages.ReturnTemp.fields.temp.value
1102
- //ebus.0.bai.messages.ReturnTemp.fields.tempmirror.value
1103
- if (!subnames[temp - 2].includes("sensor") //ignore sensor states
1104
- && !subnames[temp - 2].includes("mirror") //ignore mirror-data
1105
- ) {
1106
- for (let ii = 0; ii < oHistoryVars.length; ii++) {
1107
-
1108
- if (name === oHistoryVars[ii].name) {
1109
-
1110
- const sTemp = '{"' + name + '": "' + value + '"}';
1111
- //adapter.log.debug(sTemp);
1112
- historyvalues[ii] = [];
1113
- historyvalues[ii].push(JSON.parse(sTemp));
1114
- //adapter.log.debug(JSON.stringify(historyvalues));
1115
- }
1116
- }
1117
- }
1118
- }
1119
- else if (subnames[temp - 1].includes("lastup")) {
1120
-
1121
- const value = newData[org_key];
1122
-
1123
- if (parseInt(value) > 0) {
1124
- //adapter.log.debug('Key : ' + key + ', Value : ' + newData[key] + " name " + name);
1125
-
1126
- //umrechnen...
1127
- const oDate = new Date(value * 1000);
1128
- //const nDate = oDate.getDate();
1129
- //const nMonth = oDate.getMonth() + 1;
1130
- //const nYear = oDate.getFullYear();
1131
- //const nHours = oDate.getHours();
1132
- //const nMinutes = oDate.getMinutes();
1133
- //const nSeconds = oDate.getSeconds();
1134
-
1135
- const sDate = oDate.toLocaleString();
1136
- await AddObject(key, "string");
1137
- await UpdateObject(key, sDate);
1138
-
1139
- const oToday = new Date();
1140
-
1141
- let bSkip = false;
1142
-
1143
- if (subnames[0].includes("scan") ||
1144
- subnames[0].includes("Scan") ||
1145
- subnames[0].includes("ehp") ||
1146
- (subnames.length > 2 && subnames[2].includes("currenterror")) ||
1147
- adapter.config.DisableTimeUpdateCheck
1148
-
1149
- ) {
1150
- bSkip = true;
1151
- }
1152
- if (temp > 2) {
1153
- //adapter.log.debug("_______________size " + temp);
1154
- if (subnames[2].includes("Timer")) {
1155
- bSkip = true;
1156
- }
1157
- }
1158
-
1159
- if (!bSkip && Math.abs(oDate.getTime() - oToday.getTime()) > 1 * 60 * 60 * 1000) {
1160
-
1161
- const sError1 = "no update since " + sDate + " " + key + " ";
1162
- if (sError.includes("none")) {
1163
- sError = "ebus: " + sError1;
1164
- }
1165
- else {
1166
- sError += sError1;
1167
- }
1168
- adapter.log.warn(sError1);
1169
- }
1170
-
1171
-
1172
- }
1173
- }
1174
- else if (subnames[0].includes("global")) {
1175
- //adapter.log.debug('Key : ' + key + ', Value : ' + newData[key] + " name " + name);
1176
- const value = newData[org_key];
1177
- await AddObject(key, typeof value);
1178
- await UpdateObject(key, value);
1179
- }
1180
- }
1181
- await adapter.setStateAsync("history.error", { ack: true, val: sError });
1182
-
1183
- //adapter.log.debug(JSON.stringify(historyvalues));
1184
-
1185
- adapter.log.info("all http done");
1186
-
1187
-
1188
- if (historyvalues.length > 0 && historydates.length > 0) {
1189
-
1190
- if (adapter.config.History4Vis2) {
1191
- await UpdateHistory_Vis2(historyvalues, historydates);
1192
- }
1193
- else {
1194
- await UpdateHistory(historyvalues, historydates);
1195
- }
1196
- }
1197
-
1198
- }
1199
- catch (e) {
1200
- adapter.log.error("exception in ebusd_ReceiveData [" + e + "]");
1201
-
1202
- await adapter.setStateAsync("history.error", { ack: true, val: "exception in receive" });
1203
-
1204
- }
1205
- //});
1206
- }
1207
-
1208
- */
1209
-
1210
- async function UpdateHistory_Vis2(values, dates) {
1211
- adapter.log.debug(`start history 4 VIS-2 ${ JSON.stringify(values) } ${ JSON.stringify(dates)}`);
1212
-
1213
- //not used anymore
1214
- await adapter.setStateAsync("history.date", { ack: true, val: "" });
1215
-
1216
- for (let s = 0; s < values.length; s++) {
1217
- const values1 = values[s];
1218
- //adapter.log.debug(s + " " + JSON.stringify(values1));
1219
-
1220
- let val2Write = [];
1221
- const ctr = s + 1;
1222
-
1223
- const obj = await adapter.getStateAsync(`history.value${ ctr}`);
1224
-
1225
- if (obj === null || obj === undefined) {
1226
- adapter.log.warn(`history.value${ ctr } not found, creating DP ${ JSON.stringify(obj)}`);
1227
- await adapter.setStateAsync(`history.value${ ctr}`, { ack: true, val: "[]" });
1228
- }
1229
-
1230
- val2Write = JSON.parse(obj.val);
1231
- adapter.log.debug(`history.value${ ctr } got ${ JSON.stringify(val2Write)}`);
1232
-
1233
- for (let ss = 0; ss < values1.length; ss++) {
1234
- const values2 = values1[ss];
1235
- //adapter.log.debug(ss + " " + JSON.stringify(values2));
1236
-
1237
- let d = 0;
1238
-
1239
- for (const n in values2) {
1240
- const val = values2[n];
1241
- const time = dates[d]["time"];
1242
- const date = dates[d]["date"];
1243
- d++;
1244
-
1245
- const times = time.split(":");
1246
- const datesl = date.split(".");
1247
-
1248
- const day = parseInt(datesl[0]);
1249
- const month = parseInt(datesl[1]) - 1;
1250
- const year = parseInt(datesl[2]);
1251
- const hours = parseInt(times[0]);
1252
- const minutes = parseInt(times[1]);
1253
-
1254
- const oDate = new Date(year, month, day, hours, minutes, 0, 0);
1255
-
1256
- adapter.log.debug(`${n } ${ val } ${ oDate.toLocaleString()}`);
1257
-
1258
- val2Write.push([oDate, val]);
1259
-
1260
- if (val2Write.length > 200) {
1261
- for (let i = val2Write.length; i > 200; i--) {
1262
- //adapter.log.debug("delete");
1263
- val2Write.shift();
1264
- }
1265
- }
1266
- }
1267
- }
1268
- await adapter.setStateAsync(`history.value${ ctr}`, { ack: true, val: JSON.stringify(val2Write) });
1269
- }
1270
- }
1271
-
1272
- async function UpdateHistory(values, dates) {
1273
- if (oHistoryVars.length > 0) {
1274
- //prüfen ob alle json gleich lang sind
1275
- let NoOfDates = -1;
1276
-
1277
- const obj = await adapter.getStateAsync("history.date");
1278
-
1279
- if (obj !== undefined && obj != null) {
1280
- try {
1281
- let oEbusDates = [];
1282
- //adapter.log.debug("before " + obj.val);
1283
- oEbusDates = JSON.parse(obj.val);
1284
- //adapter.log.debug("after parse " + JSON.stringify(oEbusDates));
1285
-
1286
- oEbusDates.push(dates);
1287
- //adapter.log.debug("after push " + JSON.stringify(oEbusDates));
1288
- //limit length of object...
1289
- if (oEbusDates.length > 200) {
1290
- for (let i = oEbusDates.length; i > 200; i--) {
1291
- //adapter.log.debug("delete");
1292
- oEbusDates.shift();
1293
- }
1294
- }
1295
- NoOfDates = oEbusDates.length;
1296
- await adapter.setStateAsync("history.date", { ack: true, val: JSON.stringify(oEbusDates) });
1297
- } catch (e) {
1298
- adapter.log.error(`exception in UpdateHistory part1 [${ e }]`);
1299
- await adapter.setStateAsync("history.date", { ack: true, val: "[]" });
1300
- NoOfDates = 0;
1301
- }
1302
- } else {
1303
- adapter.log.warn("history.date not found, creating DP ");
1304
- await adapter.setStateAsync("history.date", { ack: true, val: "[]" });
1305
- NoOfDates = 0;
1306
- }
1307
-
1308
- if (oHistoryVars.length > 0) {
1309
- for (let ctr = 1; ctr <= oHistoryVars.length; ctr++) {
1310
- if (oHistoryVars[ctr - 1].name.length > 0) {
1311
- const ctrOkay = await UpdateHistoryValues(values, ctr, NoOfDates);
1312
-
1313
- if (!ctrOkay) {
1314
- await adapter.setStateAsync("history.date", { ack: true, val: "[]" });
1315
- NoOfDates = 0;
1316
- adapter.log.warn("reset history date too");
1317
- }
1318
- } else {
1319
- adapter.log.debug(`ignoring history value ${ ctr}`);
1320
- }
1321
- }
1322
-
1323
- adapter.log.info("all history done");
1324
- }
1325
- } else {
1326
- adapter.log.debug("nothing to do for history");
1327
- }
1328
- }
1329
-
1330
- async function UpdateHistoryValues(values, ctr, curDateCtr) {
1331
- let bRet = true;
1332
-
1333
- const obj = await adapter.getStateAsync(`history.value${ ctr}`);
1334
-
1335
- if (obj !== undefined && obj != null) {
1336
- try {
1337
- let oEbusValues = [];
1338
- if (obj !== null) {
1339
- //adapter.log.debug("before " + obj.val);
1340
-
1341
- oEbusValues = JSON.parse(obj.val);
1342
-
1343
- //adapter.log.debug("after parse " + JSON.stringify(oEbusValues));
1344
-
1345
- //adapter.log.debug("after parse cnt " + oEbusValues.length);
1346
- }
1347
-
1348
- //adapter.log.debug("values " + ctr + ": " + JSON.stringify(values[ctr-1]));
1349
-
1350
- oEbusValues.push(values[ctr - 1]);
1351
- //adapter.log.debug("after push " + JSON.stringify(oEbusValues));
1352
- //adapter.log.debug("after push cnt " + oEbusValues.length);
1353
- //limit length of object...
1354
- if (oEbusValues.length > 200) {
1355
- for (let i = oEbusValues.length; i > 200; i--) {
1356
- //adapter.log.debug("delete");
1357
- oEbusValues.shift();
1358
- }
1359
- }
1360
-
1361
- const key = `history.value${ ctr}`;
1362
- adapter.log.debug(`update history ${ key}`);
1363
-
1364
- if (curDateCtr != oEbusValues.length) {
1365
- bRet = false;
1366
- await adapter.setStateAsync(`history.value${ ctr}`, { ack: true, val: "[]" });
1367
- adapter.log.warn(`reset history ${ key } because number of values different to date values`);
1368
- } else {
1369
- await adapter.setStateAsync(key, { ack: true, val: JSON.stringify(oEbusValues) });
1370
- }
1371
- } catch (e) {
1372
- adapter.log.error(`exception in UpdateHistory part2 [${ e }]`);
1373
- await adapter.setStateAsync(`history.value${ ctr}`, { ack: true, val: "[]" });
1374
- if (curDateCtr > 0) {
1375
- bRet = false;
1376
- }
1377
- }
1378
- } else {
1379
- adapter.log.warn(`history.value${ ctr } not found, creating DP ${ JSON.stringify(obj)}`);
1380
- await adapter.setStateAsync(`history.value${ ctr}`, { ack: true, val: "[]" });
1381
- if (curDateCtr > 0) {
1382
- bRet = false;
1383
- }
1384
- }
1385
-
1386
- return bRet;
1387
- }
1388
-
1389
- async function AddObject(key, type) {
1390
- //adapter.log.debug("addObject " + key);
1391
-
1392
- try {
1393
- const obj = await adapter.getObjectAsync(key);
1394
-
1395
- if (obj != null) {
1396
- //adapter.log.debug(" got Object " + JSON.stringify(obj));
1397
- if (obj.common.role != "value" || obj.common.type != type) {
1398
- adapter.log.debug(` !!! need to extend for ${ key}`);
1399
- await adapter.extendObject(key, {
1400
- common: {
1401
- type: type,
1402
- role: "value",
1403
- },
1404
- });
1405
- }
1406
- } else {
1407
- adapter.log.warn(` !!! does not exist, creating now ${ key}` );
1408
-
1409
- await adapter.setObjectNotExistsAsync(key, {
1410
- type: "state",
1411
- common: {
1412
- name: "data",
1413
- type: type,
1414
- role: "value",
1415
- unit: "",
1416
- read: true,
1417
- write: false,
1418
- },
1419
- native: {
1420
- location: key,
1421
- },
1422
- });
1423
- }
1424
- } catch (e) {
1425
- adapter.log.error(`exception in AddObject ` + `[${ e }]`);
1426
- }
1427
- }
1428
-
1429
- async function UpdateObject(key, value) {
1430
- try {
1431
- if (value === undefined) {
1432
- adapter.log.warn(`updateObject: not updated ${ key } value: ${ value } ${ typeof value}`);
1433
- } else if (value == null ) {
1434
- adapter.log.debug(`updateObject: update to null ${ key } value: ${ value}`);
1435
- await adapter.setStateAsync(key, { ack: true, val: null });
1436
- } else {
1437
- //adapter.log.debug("updateObject " + key + " : " + value);
1438
- await adapter.setStateAsync(key, { ack: true, val: value });
1439
- }
1440
- } catch (e) {
1441
- adapter.log.error(`exception in UpdateObject ` + `[${ e }]`);
1442
- }
1443
- }
1444
-
1445
- //telnet client to write to ebusd
1446
- //https://github.com/john30/ebusd/wiki/3.1.-TCP-client-commands
1447
- /*
1448
- telnet 192.168.3.144 8890
1449
-
1450
- find -f -c broadcast outsidetemp
1451
- find -f outsidetemp
1452
- find -f YieldTotal
1453
-
1454
- read -f YieldTotal
1455
- read LegioProtectionEnabled
1456
-
1457
- read -f YieldTotal,read LegioProtectionEnabled,read -f -c broadcast outsidetemp
1458
-
1459
- */
1460
-
1461
- //this function just triggers ebusd to read data; result will not be parsed; we just take the values from http result
1462
- //here we need a loop over all configured read data in admin-page
1463
- async function ebusd_ReadValues() {
1464
- if (oPolledVars.length > 0) {
1465
- adapter.log.debug(`to poll ctr ${ oPolledVars.length } vals: ${ JSON.stringify(oPolledVars)}`);
1466
-
1467
- try {
1468
- //const socket = new net.Socket();
1469
- //const promiseSocket = new PromiseSocket(socket);
1470
-
1471
- //await promiseSocket.connect(parseInt(adapter.config.targetTelnetPort), adapter.config.targetIP);
1472
- //adapter.log.debug(`telnet connected to poll variables ${ adapter.config.targetIP } port ${ adapter.config.targetTelnetPort}`);
1473
- //promiseSocket.setTimeout(5000);
1474
-
1475
- const telnet = new telnetClient();
1476
- await telnet.connect(adapter.config.targetIP, parseInt(adapter.config.targetTelnetPort));
1477
-
1478
- let retries = 0;
1479
- for (let nCtr = 0; nCtr < oPolledVars.length; nCtr++) {
1480
- let circuit = "";
1481
- let params = "";
1482
- if (oPolledVars[nCtr].circuit != null && oPolledVars[nCtr].circuit.length > 0) {
1483
- circuit = `-c ${ oPolledVars[nCtr].circuit } `;
1484
- }
1485
- if (oPolledVars[nCtr].parameter != null && oPolledVars[nCtr].parameter.length > 0) {
1486
- params = ` ${ oPolledVars[nCtr].parameter}`;
1487
- }
1488
- let cmd = `read -f ${ circuit }${oPolledVars[nCtr].name }${params}`;
1489
-
1490
- adapter.log.debug(`send cmd ${ cmd}`);
1491
-
1492
- cmd += "\n";
1493
- let data = null;
1494
-
1495
- try {
1496
- //await promiseSocket.write(cmd);
1497
- await telnet.write(cmd);
1498
-
1499
- //const data = await promiseSocket.read();
1500
- data = await telnet.read();
1501
- } catch (e) {
1502
- adapter.log.warn(`exception from tcp socket write/read in ebusd_ReadValues for cmd ${cmd}` + `[${e}]` + ` -> retry` );
1503
-
1504
- //todo: retry nur für timeout und arbitration lost? 2025-11-01
1505
- retries++;
1506
- if (retries > adapter.config.maxretries) {
1507
- adapter.log.error(`max retries, skip cmd ${cmd}`);
1508
-
1509
- } else {
1510
- nCtr--; //counter wieder zurücksetzen
1511
- adapter.log.debug("retry to send data ");
1512
- }
1513
-
1514
- }
1515
- if (data !== null) {
1516
- adapter.log.debug(`received ${data} for ${JSON.stringify(oPolledVars[nCtr])}`);
1517
-
1518
- //todo: parse data and set DP's 2025-11-01
1519
- }
1520
- //received ERR: arbitration lost for YieldThisYear
1521
- //if (data !== null && data.includes("ERR")) {
1522
- // adapter.log.warn(`sent ${ cmd }, received ${ data } for ${ JSON.stringify(oPolledVars[nCtr]) } please check ebusd logs for details!`);
1523
- //
1524
- // /*
1525
- // * sent read -f YieldLastYear, received ERR: arbitration lost for {"circuit":"","name":"YieldLastYear","parameter":""}
1526
- // * */
1527
- // if (data.includes("arbitration lost")) {
1528
- // retries++;
1529
- // if (retries > adapter.config.maxretries) {
1530
- // adapter.log.error(`max retries, skip cmd ${ cmd}`);
1531
- // retries = 0;
1532
- // } else {
1533
- // nCtr--;
1534
- // adapter.log.debug("retry to send data ");
1535
- // }
1536
- // }
1537
- //} else {
1538
- //
1539
- // //muss wieder debug werden 2025-11-01 todo
1540
- // adapter.log.info(`received ${ data } for ${ JSON.stringify(oPolledVars[nCtr])}`);
1541
- //}
1542
- }
1543
- //promiseSocket.destroy();
1544
- await telnet.disconnect();
1545
- adapter.log.debug("telnet disonnected");
1546
- } catch (e) {
1547
- adapter.log.error(`exception from tcp socket in ebusd_ReadValues ` + `[${ e }]`);
1548
- }
1549
- } else {
1550
- adapter.log.debug("nothing to poll; skip telnet");
1551
- }
1552
- }
1553
-
1554
- async function FindParams(obj) {
1555
-
1556
- //todo muss wieder debug werden 2025-11-01
1557
- adapter.log.info(`FindParams ${ JSON.stringify(obj) } ${ JSON.stringify(obj.message) } ${ JSON.stringify(obj.message.circuit)}`);
1558
-
1559
- const list = [];
1560
-
1561
- try {
1562
- //FindParams {"command":"findParams","message":{"circuit":"cc"},"from":"system.adapter.admin.0","callback":{"message":{"circuit":"cc"},"id":90,"ack":false,"time":1733690088670},"_id":39690903}
1563
-
1564
- if (obj.message !== null && obj.message.circuit!== null) {
1565
- const circuit = obj.message.circuit;
1566
-
1567
- //const socket = new net.Socket();
1568
- //const promiseSocket = new PromiseSocket(socket);
1569
-
1570
- //await promiseSocket.connect(parseInt(adapter.config.targetTelnetPort), adapter.config.targetIP);
1571
- //adapter.log.debug("telnet connected for cmd");
1572
- //promiseSocket.setTimeout(5000);
1573
-
1574
- const telnet = new telnetClient();
1575
- await telnet.connect(adapter.config.targetIP, parseInt(adapter.config.targetTelnetPort));
1576
-
1577
- const cmd = `find -c ${ circuit } -F circuit,name\n`;
1578
- //await promiseSocket.write(cmd);
1579
-
1580
- adapter.log.debug(`send cmd ${cmd}`);
1581
- await telnet.write(cmd);
1582
-
1583
- adapter.log.debug(`sent, wait for data...`);
1584
- //const data = await promiseSocket.read();
1585
- const data = await telnet.read();
1586
- adapter.log.info(`data received: ` + data);
1587
-
1588
- if ( data.includes("ERR")) {
1589
- adapter.log.warn(`received error! sent find, received ${ data } please check ebusd logs for details! ${ cmd}`);
1590
-
1591
- } else {
1592
- adapter.log.info(`received ${ typeof data } ${ data } ${ + cmd}`);
1593
- }
1594
- /*
1595
- received object ehp,AccelerationTestModeehp,AccelerationTestModeehp,ActualEnvironmentPowerehp,ActualEnvironmentPowerehp,ActualEnvironmentPowerPercentageehp,ActualEnvironmentPowerPercentageehp,ApplianceCodeehp,ApplianceCodeehp,Backupehp,Backupehp,BackupHoursehp,BackupHoursHcehp,BackupHoursHwcehp,BackupHysteresisehp,BackupIntegralehp,BackupModeHcehp,BackupModeHwcehp,BackupPowerCutehp,BackupStartsehp,BackupStartsHcehp,BackupStartsHwcehp,BackupTypeehp,BivalentTempehp,Bleedingehp,Bleedingehp,CirPumpehp,CirPumpehp,Code1ehp,Code1Code2Validehp,Code2ehp,Compehp,Compehp,CompControlStateehp,CompCutPressHighCountehp,CompCutPressLowCountehp,CompCutTempCountehp,CompDemandehp,CompHoursehp,CompHoursHcehp,CompHoursHwcehp,CompHysteresisehp,CompIntegralehp,CompPressHighehp,CompPressHighehp,CompPressLowehp,CompPressLowehp,CompStartsehp,CompStartsHcehp,CompStartsHwcehp,CompStateehp,CondensorTempehp,CondensorTempehp,currenterrorehp,Dateehp,DateTimeehp,DeltaTempT6T7ehp,ElectricWiringDiagramehp,ElectricWiringDiagramehp,EnergyBalancingReleaseehp,errorhistoryehp,FlowTempehp,FlowTempehp,FlowtempCoolingMinehp,FlowTempOffsetehp,Hc1Pumpehp,Hc1Pumpehp,Hc1PumpHoursehp,Hc1PumpPortehp,Hc1PumpStartsehp,Hc2Pumpehp,Hc2PumpHoursehp,HcFlowTempehp,HcFlowTempOffsetehp,HcModeDemandHoursehp,HcModeFulfilledHoursehp,HcParallelStorageFillingEnabledehp,HcPressehp,HcReturnTempehp,HcReturnTempehp,HcReturnTempOffsetehp,HeatPumpStatusehp,HeatPumpStatusehp,HeatpumpTypeehp,HwcHcValveehp,HwcHcValveehp,HwcHcValveStartsehp,HwcLaggingTimeehp,HwcLoadingDelayehp,HwcModeDemandHoursehp,HwcModeFulfilledHoursehp,HwcPumpStartsehp,HwcSwitchehp,HwcTempehp,HwcTempehp,HwcTempOffsetehp,HydraulicSchemeehp,ICLOutehp,ICLOutehp,Injectionehp,Integralehp,Mixer1DutyCycleehp,NumberCompStartsehp,OutsideTempehp,OutsideTempOffsetehp,OverpressureThresholdehp,PhaseOrderehp,PhaseOrderehp,PhaseStatusehp,PhaseStatusehp,PowerCutehp,PowerCutPreloadingehp,PressSwitchehp,PressSwitchehp,RebootCounterehp,ReturnTempMaxehp,SetModeehp,SoftwareCodeehp,Source2PumpHoursehp,Sourceehp,Sourceehp,SourceHoursehp,SourcePortehp,SourcePressehp,SourcePumpPrerunTimeehp,SourceStartsehp,SourceSwitchehp,SourceSwitchehp,SourceTempInputehp,SourceTempInputehp,SourceTempInputOffsetehp,SourceTempOutputehp,SourceTempOutputehp,SourceTempOutputOffsetehp,SourceTempOutputT8Minehp,StateSoftwareCodeehp,StateSoftwareCodeehp,Status01ehp,Status02ehp,Status16ehp,Statusehp,StatusCirPumpehp,StorageTempBottomehp,StorageTempBottomehp,StorageTempBottomOffsetehp,StorageTempTopehp,StorageTempTopehp,StorageTempTopOffsetehp,Subcoolingehp,Superheatehp,T19MaxToCompOffehp,TempInputehp,TempInputehp,TempInputOffsetehp,TempOutputehp,TempOutputehp,TempOutputOffsetehp,Timeehp,TimeBetweenTwoCompStartsMinehp,TimeCompOffMinehp,TimeCompOnMinehp,TimeOfNextPredictedPowerCutehp,TimeOfNextPredictedPowerCutehp,Weekdayehp,YieldTotalehp,YieldTotal
1596
- */
1597
- //const str = new TextDecoder().decode(data);
1598
- const datas = data.split(/[\r?\n,]+/);
1599
-
1600
- adapter.log.info("found entries: " + datas.length);
1601
-
1602
- for (let i = 0; i < datas.length; i++) {
1603
- //adapter.log.info(JSON.stringify(datas[i]));
1604
-
1605
- const names = datas[i].split(",");
1606
-
1607
- //doppelte und leere herausfiltern
1608
- let add = true;
1609
-
1610
- if (names[0] == "" || names[1] == "") {
1611
- add = false;
1612
- } else {
1613
-
1614
- for (let n = 0; n < list.length; n++) {
1615
- if (list[n].circuit == names[0] && list[n].name == names[1]) {
1616
- add = false;
1617
- //already in list
1618
- }
1619
- }
1620
- }
1621
-
1622
- if (add) {
1623
- const entry = {
1624
- active: false,
1625
- circuit: names[0],
1626
- name: names[1],
1627
- };
1628
-
1629
- list.push(entry);
1630
- }
1631
- }
1632
-
1633
- await telnet.disconnect();
1634
- } else {
1635
- adapter.log.error("no circuit defined where to look for parameter, check values!");
1636
- }
1637
- } catch (e) {
1638
- adapter.log.error(`exception in FindParams ` + `[${ e }]`);
1639
- }
1640
-
1641
- adapter.log.info(`parameters ${ JSON.stringify(list)}`);
1642
-
1643
- adapter.sendTo(obj.from, obj.command, list, obj.callback);
1644
- }
1645
-
1646
- async function CallExternalScript(script, msg) {
1647
-
1648
-
1649
-
1650
- try {
1651
- if (os.platform() == "linux") {
1652
- //const cmd = spawn("ls", ["-la"]);
1653
-
1654
- adapter.log.info("we are on linux " );
1655
-
1656
- const folderName = path.join(__dirname, '..', 'iobroker.ebus', 'lib', 'scripts');
1657
-
1658
-
1659
- if (!fs.existsSync(folderName)) {
1660
-
1661
- adapter.log.info("folder doesnt exists " + folderName);
1662
-
1663
- adapter.sendTo(msg.from, msg.command, { error: 'script folder not found ' + folderName }, msg.callback);
1664
- return;
1665
- }
1666
-
1667
-
1668
- adapter.log.info("folder exists " + folderName);
1669
-
1670
- const scriptfile = path.join(folderName , script);
1671
- const stats = await fs.statSync(scriptfile);
1672
-
1673
- if (!stats.isFile()) {
1674
-
1675
- adapter.log.info("file doenst exists " + scriptfile);
1676
-
1677
- adapter.sendTo(msg.from, msg.command, { error: 'script not found ' + scriptfile }, msg.callback);
1678
-
1679
- return;
1680
-
1681
- } else {
1682
-
1683
- adapter.log.info("file exists " + scriptfile);
1684
-
1685
- const cmd = spawn(scriptfile, [""]);
1686
-
1687
- cmd.stdout.on("data", data => {
1688
- adapter.log.error(`stdout: ${data}`);
1689
- });
1690
-
1691
- cmd.stderr.on("data", data => {
1692
- adapter.log.error(`stderr: ${data}`);
1693
- });
1694
-
1695
- cmd.on('error', (error) => {
1696
- adapter.log.error(`error: ${error.message}`);
1697
- });
1698
-
1699
- cmd.on("close", code => {
1700
- adapter.log.error(`child process exited with code ${code}`);
1701
- adapter.sendTo(msg.from, msg.command, {
1702
- info: 'success '
1703
-
1704
- }, msg.callback);
1705
- });
1706
- }
1707
-
1708
- } else {
1709
- adapter.sendTo(msg.from, msg.command, { error: 'possible only on Linux systems, this system is ' + os.platform() }, msg.callback);
1710
- }
1711
- } catch (e) {
1712
- adapter.log.error("exception in CallExternalScript " + "[" + e + "]");
1713
-
1714
- adapter.sendTo(msg.from, msg.command, { error: 'error ' + e }, msg.callback);
1715
- }
1716
-
1717
-
1718
- /*
1719
- try {
1720
- if (os.platform() == "linux") {
1721
-
1722
-
1723
- let cmd = "\\lib\\scripts\\" + script;
1724
-
1725
- exec(cmd, (error, stdout, stderr) => {
1726
- if (error) {
1727
- adapter.log.error(`error: ${error.message}`);
1728
- adapter.sendTo(msg.from, msg.command, { error: 'error ' + error.message }, msg.callback);
1729
- return;
1730
- }
1731
- if (stderr) {
1732
- adapter.log.error(`stderr: ${stderr}`);
1733
- adapter.sendTo(msg.from, msg.command, { error: 'error ' + stderr }, msg.callback);
1734
- return;
1735
- }
1736
- adapter.log.info(`stdout: ${stdout}`);
1737
- adapter.sendTo(msg.from, msg.command, {
1738
- info: 'success '
1739
-
1740
- }, msg.callback);
1741
- });
1742
- }
1743
- else {
1744
- adapter.sendTo(msg.from, msg.command, { error: 'possible only on Linux systems, this system is ' + os.platform() }, msg.callback);
1745
- }
1746
- } catch (e) {
1747
- adapter.log.error("exception in CallExternalScript " + "[" + e + "]");
1748
- }
1749
-
1750
- */
1751
- }
1752
-
1753
- async function CheckVersion(version, msg) {
1754
- if (version == "installable") {
1755
- let version = "unknown";
1756
-
1757
- if (ebusdUpdateVersion[0] > 0 && ebusdVersion[0] > 0) {
1758
- version = `${ebusdUpdateVersion[0] }.${ ebusdUpdateVersion[1]}`
1759
- } else {
1760
- version = await GetLatestVersionGithub();
1761
- }
1762
- adapter.sendTo(msg.from, msg.command, version, msg.callback);
1763
- } else if (version == "current") {
1764
- adapter.sendTo(msg.from, msg.command, `${ebusdVersion[0] }.${ ebusdVersion[1]}`, msg.callback);
1765
- } else if (version == "supported") {
1766
- adapter.sendTo(msg.from, msg.command, `${ebusdMinVersion[0] }.${ ebusdMinVersion[1]}`, msg.callback);
1767
- }
1768
- }
1769
-
1770
- async function GetLatestVersionGithub() {
1771
- let latestVersion = "unknown";
1772
-
1773
- try {
1774
- const url = "https://api.github.com/repos/john30/ebusd/releases/latest";
1775
- adapter.log.debug(`call ${ url}`);
1776
-
1777
- let result = await axios.get(url, { timeout: 5000 });
1778
-
1779
- if (result != null && result.status == 200 && result.data != null) {
1780
- adapter.log.info(`installable version on github ${ JSON.stringify(result.data.tag_name) } (${ JSON.stringify(result.data.name) })`);
1781
-
1782
- latestVersion =
1783
- "on github " + JSON.stringify(result.data.tag_name) + "(" + JSON.stringify(result.data.name) + ")";
1784
- } else {
1785
- latestVersion = "unknown / no result";
1786
- }
1787
- } catch (e) {
1788
- adapter.log.error(`exception in GetLatestVersionGithub [${ e }]`);
1789
- latestVersion = "unknown / error";
1790
- }
1791
- return latestVersion;
1792
- }
1793
-
1794
-
1795
-
1796
-
1797
-
1798
-
1799
-
1800
-
1801
- // If started as allInOne/compact mode => return function to create instance
1802
- if (module && module.parent) {
1803
- module.exports = startAdapter;
1804
- } else {
1805
- // or start the instance directly
1806
- startAdapter();
1807
- }