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/build/main.js ADDED
@@ -0,0 +1,1350 @@
1
+ "use strict";
2
+ /* eslint-disable prefer-template */
3
+ /*
4
+ * Created with @iobroker/create-adapter v2.6.5
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ var __importDefault = (this && this.__importDefault) || function (mod) {
40
+ return (mod && mod.__esModule) ? mod : { "default": mod };
41
+ };
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.ebus = void 0;
44
+ // https://www.iobroker.net/#en/documentation/dev/adapterdev.md
45
+ //import os from "os";
46
+ //import fs from "fs";
47
+ //import path from "path";
48
+ //import spawn from "child_process";
49
+ const utils = __importStar(require("@iobroker/adapter-core"));
50
+ const axios_1 = __importDefault(require("axios"));
51
+ const TelnetClient_1 = __importDefault(require("./lib/TelnetClient"));
52
+ class ebus extends utils.Adapter {
53
+ intervalID = null;
54
+ updateTimerID = null;
55
+ requestRunning = false;
56
+ oPolledVars = [];
57
+ oHistoryVars = [];
58
+ oHTTPParamsVars = [];
59
+ ebusdMinVersion = [26, 1];
60
+ ebusdVersion = [0, 0];
61
+ ebusdUpdateVersion = [0, 0];
62
+ constructor(options = {}) {
63
+ super({
64
+ ...options,
65
+ name: "ebus",
66
+ });
67
+ this.on("ready", this.onReady.bind(this));
68
+ this.on("stateChange", this.onStateChange.bind(this));
69
+ this.on("objectChange", this.onObjectChange.bind(this));
70
+ this.on("message", this.onMessage.bind(this));
71
+ this.on("unload", this.onUnload.bind(this));
72
+ }
73
+ /**
74
+ * Wird aufgerufen, wenn die Datenbanken verbunden sind und die Adapter-Konfiguration empfangen wurde.
75
+ */
76
+ async onReady() {
77
+ this.log.debug(JSON.stringify(this.config));
78
+ try {
79
+ await this.main();
80
+ }
81
+ catch (e) {
82
+ this.log.error("Exception in onReady [" + e + "]");
83
+ }
84
+ }
85
+ /**
86
+ * Wird aufgerufen, wenn der Adapter heruntergefahren wird - Callback MUSS unter allen Umständen aufgerufen werden!
87
+ */
88
+ async onUnload(callback) {
89
+ await Promise.resolve(); //dummy await to make function async
90
+ try {
91
+ // Hier müssen alle Timeouts oder Intervalle gelöscht werden, die noch aktiv sein könnten
92
+ if (this.intervalID != null) {
93
+ clearInterval(this.intervalID);
94
+ }
95
+ if (this.updateTimerID != null) {
96
+ clearTimeout(this.updateTimerID);
97
+ }
98
+ this.log.info("cleaned everything up...");
99
+ callback();
100
+ }
101
+ catch (e) {
102
+ this.log.error("Exception in onUnload " + e);
103
+ callback();
104
+ }
105
+ }
106
+ /**
107
+ * Wird aufgerufen, wenn ein abonniertes Objekt geändert wird
108
+ */
109
+ onObjectChange(id, obj) {
110
+ if (obj) {
111
+ this.log.info(`Objekt ${id} geändert: ${JSON.stringify(obj)}`);
112
+ }
113
+ else {
114
+ this.log.info(`Objekt ${id} gelöscht`);
115
+ }
116
+ }
117
+ /**
118
+ * Wird aufgerufen, wenn ein abonnierter State geändert wird
119
+ */
120
+ async onStateChange(id, state) {
121
+ if (state != null && state.ack !== true) {
122
+ this.log.debug(`handle state change ${id}`);
123
+ const ids = id.split(".");
124
+ if (ids[2] === "cmd") {
125
+ await this.ebusd_Command();
126
+ this.StartDataRequest();
127
+ //see issue #77: only one request possible
128
+ //await Do();
129
+ }
130
+ else if (ids[2] === "find") {
131
+ //unhandled state change ebus.0.find
132
+ await this.ebusd_find();
133
+ }
134
+ else {
135
+ this.log.warn(`unhandled state change ${id}`);
136
+ }
137
+ }
138
+ }
139
+ /**
140
+ * Nachrichtenbehandlung
141
+ */
142
+ async onMessage(obj) {
143
+ this.log.info("on message " + JSON.stringify(obj));
144
+ await Promise.resolve();
145
+ if (typeof obj === "object" && obj.command) {
146
+ switch (obj.command) {
147
+ case "findParams":
148
+ this.log.debug("message FindParams called");
149
+ await this.FindParams(obj);
150
+ break;
151
+ case "Install":
152
+ this.log.debug("message install called");
153
+ //await this.CallExternalScript("InstallEbusd.sh", obj);
154
+ break;
155
+ case "Update":
156
+ this.log.debug("message update called");
157
+ //await this.CallExternalScript("UpdateEbusd.sh", obj);
158
+ break;
159
+ case "checkInstallableversion":
160
+ await this.CheckVersion("installable", obj);
161
+ break;
162
+ case "checkCurrentVersion":
163
+ await this.CheckVersion("current", obj);
164
+ break;
165
+ case "checkSupportedVersion":
166
+ await this.CheckVersion("supported", obj);
167
+ break;
168
+ default:
169
+ this.log.error(`unknown message ${obj.command}`);
170
+ break;
171
+ }
172
+ }
173
+ }
174
+ async main() {
175
+ this.log.debug("start with interface ebusd ");
176
+ this.FillPolledVars();
177
+ this.FillHistoryVars();
178
+ this.FillHTTPParamsVars();
179
+ await this.checkVariables();
180
+ await this.subscribeVars();
181
+ let readInterval = 5;
182
+ if (this.config.readInterval > 0) {
183
+ readInterval = this.config.readInterval;
184
+ }
185
+ this.log.debug(`read every ${readInterval} minutes`);
186
+ this.intervalID = setInterval(this.Do.bind(this), readInterval * 60 * 1000);
187
+ //read at thisstart
188
+ await this.Do();
189
+ }
190
+ async DoRequest() {
191
+ this.log.debug("DoRequest ");
192
+ if (!this.requestRunning) {
193
+ this.requestRunning = true;
194
+ await this.ebusd_ReadValues();
195
+ await this.ebusd_ReceiveData();
196
+ }
197
+ else {
198
+ this.log.debug("DoRequest: do nothing already running ");
199
+ }
200
+ this.requestRunning = false;
201
+ }
202
+ async Do() {
203
+ this.log.debug("starting ... ");
204
+ await this.ebusd_Command();
205
+ await this.DoRequest();
206
+ }
207
+ StartDataRequest() {
208
+ if (this.updateTimerID != null) {
209
+ //already running
210
+ clearTimeout(this.updateTimerID);
211
+ this.updateTimerID = null;
212
+ }
213
+ //start or restart
214
+ this.updateTimerID = setTimeout(this.DataRequest, 500);
215
+ this.log.debug("StartDataRequest");
216
+ }
217
+ async DataRequest() {
218
+ this.log.debug("get data after command and timeout");
219
+ if (this.updateTimerID != null) {
220
+ clearTimeout(this.updateTimerID);
221
+ this.updateTimerID = null;
222
+ }
223
+ await this.DoRequest();
224
+ }
225
+ FillPolledVars() {
226
+ try {
227
+ if (this.config.PolledDPs !== undefined &&
228
+ this.config.PolledDPs != null &&
229
+ this.config.PolledDPs.length > 0) {
230
+ this.log.debug("use new object list for polled vars");
231
+ //2023-02-10 only active vars
232
+ for (let i = 0; i < this.config.PolledDPs.length; i++) {
233
+ if (this.config.PolledDPs[i].active) {
234
+ this.oPolledVars.push(this.config.PolledDPs[i]);
235
+ }
236
+ }
237
+ }
238
+ }
239
+ catch (e) {
240
+ this.log.error(`exception in FillPolledVars [${e}]`);
241
+ }
242
+ this.log.debug(`list of polled vars ${JSON.stringify(this.oPolledVars)}`);
243
+ }
244
+ FillHistoryVars() {
245
+ try {
246
+ if (this.config.HistoryDPs !== undefined &&
247
+ this.config.HistoryDPs != null &&
248
+ this.config.HistoryDPs.length > 0) {
249
+ this.log.debug("use new object list for history vars");
250
+ this.oHistoryVars = this.config.HistoryDPs;
251
+ }
252
+ }
253
+ catch (e) {
254
+ this.log.error(`exception in function FillHistoryVars [${e}]`);
255
+ }
256
+ this.log.debug(`list of history vars ${JSON.stringify(this.oHistoryVars)}`);
257
+ //add a check, that complete dp without ebus.0 is used 2025-08-20
258
+ this.oHistoryVars.forEach((entry, index) => {
259
+ const hasDot = entry.name.includes(".");
260
+ const hasInstance = entry.name.includes("ebus.");
261
+ const hasValue = entry.name.includes("value");
262
+ this.log.debug("checking " + entry.name + " index " + index + " hasDot: " + hasDot + " hasInstance: " + hasInstance + " hasValue: " + hasValue);
263
+ if (!hasDot) {
264
+ this.log.warn("please check history variable: " + entry.name + " -> should contain the complete DP");
265
+ }
266
+ if (!hasValue) {
267
+ this.log.warn("please check history variable " + entry.name + " -> should contain 'value'");
268
+ }
269
+ if (hasInstance) {
270
+ this.log.warn("please check history variable " + entry.name + " -> should not contain instance name and instance number e.g. 'ebus.0' ");
271
+ }
272
+ });
273
+ //list of history vars [{"name":"ActualEnvironmentPower"},{"name":"YieldTotal"},{"name":"SourceTempInput"},{"name":"SourceTempOutput"},{"name":"HwcTemp"}]
274
+ }
275
+ FillHTTPParamsVars() {
276
+ if (this.config.HTTPparameter !== undefined &&
277
+ this.config.HTTPparameter != null &&
278
+ this.config.HTTPparameter.length > 0) {
279
+ this.oHTTPParamsVars = this.config.HTTPparameter;
280
+ this.log.debug(`use optionally HTTP parameter ${JSON.stringify(this.oHTTPParamsVars)}`);
281
+ }
282
+ }
283
+ //===================================================================================================
284
+ // ebusd interface
285
+ async ebusd_Command() {
286
+ const obj = await this.getStateAsync("cmd");
287
+ if (obj !== undefined && obj != null) {
288
+ const cmds = obj.val?.toString();
289
+ if (cmds != null && cmds !== "") {
290
+ this.log.debug(`got command(s): ${cmds}`);
291
+ this.log.debug(`connect telnet to IP ${this.config.targetIP} port ${this.config.targetTelnetPort}`);
292
+ try {
293
+ //const socket = new net.Socket();
294
+ //const promiseSocket = new PromiseSocket(socket);
295
+ //await promiseSocket.connect(parseInt(this.config.targetTelnetPort), this.config.targetIP);
296
+ //this.log.debug("telnet connected for cmd");
297
+ //promiseSocket.setTimeout(5000);
298
+ const telnet = new TelnetClient_1.default();
299
+ await telnet.connect(this.config.targetIP, this.config.targetTelnetPort);
300
+ const oCmds = cmds.split(",");
301
+ if (oCmds.length > 0) {
302
+ let received = "";
303
+ for (let n = 0; n < oCmds.length; n++) {
304
+ this.log.debug(`send ${oCmds[n]}`);
305
+ //await promiseSocket.write(`${oCmds[n] }\n`);
306
+ await telnet.write(`${oCmds[n]}\n`);
307
+ //const data = await promiseSocket.read();
308
+ const data = await telnet.read();
309
+ if (data.includes("ERR")) {
310
+ this.log.warn(`sent ${oCmds[n]}, received ${data} please check ebusd logs for details!`);
311
+ }
312
+ else {
313
+ this.log.debug(`received ${data}`);
314
+ }
315
+ received += data.toString();
316
+ received += ", ";
317
+ }
318
+ //see issue #78: remove CR, LF and last comma
319
+ received = received.replace(/\r?\n|\r/g, "");
320
+ received = received.slice(0, -2);
321
+ //set result to cmdResult
322
+ await this.setState("cmdResult", { ack: true, val: received });
323
+ }
324
+ else {
325
+ this.log.warn(`no commands in list ${cmds} ${JSON.stringify(oCmds)}`);
326
+ }
327
+ await this.setState("cmd", { ack: true, val: "" });
328
+ //promiseSocket.destroy();
329
+ await telnet.disconnect();
330
+ }
331
+ catch (e) {
332
+ this.log.error(`exception from tcp socket` + `[${e}]`);
333
+ }
334
+ }
335
+ }
336
+ else {
337
+ this.log.debug(`object cmd not found ${JSON.stringify(obj)}`);
338
+ }
339
+ }
340
+ async ebusd_find() {
341
+ try {
342
+ //const socket = new net.Socket();
343
+ //const promiseSocket = new PromiseSocket(socket);
344
+ //await promiseSocket.connect(parseInt(this.config.targetTelnetPort), this.config.targetIP);
345
+ //this.log.debug("telnet connected for cmd");
346
+ //promiseSocket.setTimeout(5000);
347
+ const telnet = new TelnetClient_1.default();
348
+ await telnet.connect(this.config.targetIP, this.config.targetTelnetPort);
349
+ //await promiseSocket.write("find -F circuit,name,comment\n");
350
+ await telnet.write("find -F circuit,name,comment\n");
351
+ //const data = await promiseSocket.read();
352
+ const data = await telnet.read();
353
+ if (data.includes("ERR")) {
354
+ this.log.warn(`received error! sent find, received ${data} please check ebusd logs for details!`);
355
+ }
356
+ else {
357
+ this.log.debug(`received ${typeof data} ${data}`);
358
+ }
359
+ let str;
360
+ if (typeof data === "string") {
361
+ str = data;
362
+ }
363
+ else if (data instanceof Uint8Array) {
364
+ str = new TextDecoder().decode(data);
365
+ }
366
+ else if (data instanceof ArrayBuffer) {
367
+ str = new TextDecoder().decode(new Uint8Array(data));
368
+ }
369
+ else {
370
+ // fallback: convert to string
371
+ str = String(data);
372
+ }
373
+ //const str = new TextDecoder().decode(data);
374
+ const datas = str.split(/[\r?\n,]+/);
375
+ this.log.info("found entries: " + datas.length);
376
+ for (let i = 0; i < datas.length; i++) {
377
+ //this.log.info(JSON.stringify(datas[i]));
378
+ const names = datas[i].split(",");
379
+ //circuit,name,comment
380
+ await this.UpdateDP(names[0], names[1], names[2]);
381
+ let cmd = `read -f -c ${names[0]} ${names[1]}`;
382
+ this.log.debug(`send cmd ${cmd}`);
383
+ cmd += "\n";
384
+ //await promiseSocket.write(cmd);
385
+ await telnet.write(cmd);
386
+ //const result = await promiseSocket.read();
387
+ const result = await telnet.read();
388
+ this.log.debug(`received ${typeof result} ${result}`);
389
+ }
390
+ //promiseSocket.destroy();
391
+ await telnet.disconnect();
392
+ }
393
+ catch (e) {
394
+ this.log.error(`exception from tcp socket in ebusd_find` + `[${e}]`);
395
+ }
396
+ }
397
+ //just call http://192.168.0.123:8889/data
398
+ /*
399
+ http://localhost:8080/data/mc?verbose&since=1483890000&exact
400
+
401
+ since=seconds: limit to messages that have changed since the specified UTC seconds
402
+ poll=prio: set the poll priority of matching message(s) to prio
403
+ exact[=true]: exact search for circuit/message name
404
+ verbose[=true]: include comments and field units
405
+ indexed[=true]: return field indexes instead of names
406
+ numeric[=true]: return numeric values of value list entries
407
+ valuename[=true]: include value and name of value list entries
408
+ full[=true]: include all available attributes
409
+ required[=true]: retrieve the data from the bus if not yet cached
410
+ maxage[=seconds]: retrieve the data from the bus if cached value is older than specified seconds (or not present at all)
411
+ write[=true]: include write messages in addition to read
412
+ raw[=true]: include the raw master/slave symbols as int arrays
413
+ def[=true]: include message/field definition (qq, id, fielddefs)
414
+ define=DEFINITION: (re-)define the message from DEFINITION (in CSV format)
415
+ user=USER: authenticate with USER name
416
+ secret=SECRET: authenticate with user SECRET
417
+
418
+
419
+ */
420
+ async subscribeVars() {
421
+ this.subscribeStates("cmd");
422
+ this.subscribeStates("find");
423
+ await this.setState("cmdResult", { ack: true, val: "" });
424
+ }
425
+ async checkVariables() {
426
+ this.log.debug("init variables ");
427
+ let key;
428
+ let obj;
429
+ key = "cmd";
430
+ obj = {
431
+ type: "state",
432
+ common: {
433
+ name: "ebusd command",
434
+ type: "string",
435
+ role: "text",
436
+ read: true,
437
+ write: true,
438
+ },
439
+ };
440
+ await this.CreateObject(key, obj);
441
+ key = "cmdResult";
442
+ obj = {
443
+ type: "state",
444
+ common: {
445
+ name: "ebusd command result",
446
+ type: "string",
447
+ role: "text",
448
+ read: true,
449
+ write: false,
450
+ },
451
+ };
452
+ await this.CreateObject(key, obj);
453
+ key = "find";
454
+ obj = {
455
+ type: "state",
456
+ common: {
457
+ name: "find existing data points",
458
+ type: "boolean",
459
+ role: "button",
460
+ read: false,
461
+ write: true,
462
+ },
463
+ };
464
+ await this.CreateObject(key, obj);
465
+ this.log.debug(`init common variables and ${this.oHistoryVars.length} history DP's`);
466
+ if (this.oHistoryVars.length > 0) {
467
+ if (this.oHistoryVars.length > 4) {
468
+ this.log.warn(`too many history values ${this.oHistoryVars.length} -> maximum is 4`);
469
+ }
470
+ for (let n = 1; n <= this.oHistoryVars.length; n++) {
471
+ if (this.oHistoryVars[n - 1].name.length > 0) {
472
+ const name = `history value ${n} as JSON ${this.oHistoryVars[n - 1].name}`;
473
+ key = `history.value${n}`;
474
+ obj = {
475
+ type: "state",
476
+ common: {
477
+ name: name,
478
+ type: "string",
479
+ role: "value",
480
+ unit: "",
481
+ read: true,
482
+ write: false,
483
+ },
484
+ native: { location: key },
485
+ };
486
+ await this.CreateObject(key, obj);
487
+ }
488
+ else {
489
+ this.log.warn(`ignoring history value ${n} (invalid name)`);
490
+ }
491
+ }
492
+ key = "history.date";
493
+ obj = {
494
+ type: "state",
495
+ common: {
496
+ name: "ebus history date / time as JSON",
497
+ type: "string",
498
+ role: "value",
499
+ unit: "",
500
+ read: true,
501
+ write: false,
502
+ },
503
+ native: {
504
+ location: key,
505
+ },
506
+ };
507
+ await this.CreateObject(key, obj);
508
+ }
509
+ key = "history.error";
510
+ obj = {
511
+ type: "state",
512
+ common: {
513
+ name: "ebus error",
514
+ type: "string",
515
+ role: "value",
516
+ unit: "",
517
+ read: true,
518
+ write: false,
519
+ },
520
+ native: { location: key },
521
+ };
522
+ await this.CreateObject(key, obj);
523
+ }
524
+ VersionCheck() {
525
+ if (this.ebusdVersion[0] > 0) {
526
+ if (this.ebusdVersion[0] < this.ebusdMinVersion[0] ||
527
+ (this.ebusdVersion[0] == this.ebusdMinVersion[0] && this.ebusdVersion[1] < this.ebusdMinVersion[1])) {
528
+ this.log.info(`please update ebusd, old version found: ${this.ebusdVersion[0]}.${this.ebusdVersion[1]} supported version is ${this.ebusdMinVersion[0]}.${this.ebusdMinVersion[1]}`);
529
+ }
530
+ if (this.ebusdVersion[0] > this.ebusdMinVersion[0] ||
531
+ (this.ebusdVersion[0] >= this.ebusdMinVersion[0] && this.ebusdVersion[1] > this.ebusdMinVersion[1])) {
532
+ this.log.info(`unsupported ebusd version found (too new): ${this.ebusdVersion[0]}.${this.ebusdVersion[1]} supported version is ${this.ebusdMinVersion[0]}.${this.ebusdMinVersion[1]}`);
533
+ }
534
+ }
535
+ if (this.ebusdUpdateVersion[0] > 0 && this.ebusdVersion[0] > 0) {
536
+ if (this.ebusdUpdateVersion[0] > this.ebusdVersion[0] ||
537
+ (this.ebusdUpdateVersion[0] == this.ebusdVersion[0] && this.ebusdUpdateVersion[1] > this.ebusdVersion[1])) {
538
+ this.log.info(`new ebusd version found: ${this.ebusdUpdateVersion[0]}.${this.ebusdUpdateVersion[1]} supported version is ${this.ebusdMinVersion[0]}.${this.ebusdMinVersion[1]}`);
539
+ }
540
+ }
541
+ }
542
+ //get data via https in json -> this is the main data receiver; telnet just triggers ebusd to read data;
543
+ //https://github.com/john30/ebusd/wiki/3.2.-HTTP-client
544
+ async ebusd_ReceiveData() {
545
+ try {
546
+ let sUrl = `http://${this.config.targetIP}:${this.config.targetHTTPPort}/data`;
547
+ //Erweiterung mit optionalen parametern
548
+ let paramsCnt = 0;
549
+ if (this.oHTTPParamsVars !== undefined && this.oHTTPParamsVars != null && this.oHTTPParamsVars.length > 0) {
550
+ for (let i = 0; i < this.oHTTPParamsVars.length; i++) {
551
+ if (this.oHTTPParamsVars[i].active) {
552
+ if (paramsCnt == 0) {
553
+ sUrl += "?";
554
+ }
555
+ else {
556
+ sUrl += "&";
557
+ }
558
+ sUrl += `${this.oHTTPParamsVars[i].name}=${this.oHTTPParamsVars[i].value}`;
559
+ paramsCnt++;
560
+ }
561
+ }
562
+ }
563
+ this.log.debug(`request data from ${sUrl}`);
564
+ const buffer = await axios_1.default.get(sUrl);
565
+ this.log.debug(`got data ${typeof buffer.data} ${JSON.stringify(buffer.data)}`);
566
+ const flattenObject = (obj, delimiter = ".", prefix = "") => Object.keys(obj).reduce((acc, k) => {
567
+ const pre = prefix.length ? `${prefix}${delimiter}` : "";
568
+ if (typeof obj[k] === "object" && obj[k] !== null && Object.keys(obj[k]).length > 0) {
569
+ Object.assign(acc, flattenObject(obj[k], delimiter, pre + k));
570
+ }
571
+ else {
572
+ acc[pre + k] = obj[k];
573
+ }
574
+ return acc;
575
+ }, {});
576
+ const data = flattenObject(buffer.data, ".");
577
+ //todo: replace any
578
+ const historyvalues = [];
579
+ const historydates = [];
580
+ const oToday = new Date();
581
+ const month = oToday.getMonth() + 1;
582
+ historydates.push({
583
+ date: `${oToday.getDate()}.${month}.${oToday.getFullYear()}`,
584
+ time: `${oToday.getHours()}:${oToday.getMinutes()}:${oToday.getSeconds()}`
585
+ });
586
+ let sError = "none";
587
+ for (let key in data) {
588
+ const subnames = key.split(".");
589
+ //const namelength = subnames.length;
590
+ let value = data[key];
591
+ //this.log.debug("key " + key);
592
+ if (key.includes("[") || key.includes("]")) {
593
+ this.log.debug(`found unsupported chars in ${key}`);
594
+ const start = key.indexOf("[");
595
+ const end = key.lastIndexOf("]");
596
+ if (start > 0 && end > 0) {
597
+ const toReplace = key.slice(start, end + 1);
598
+ key = key.replace(toReplace, "");
599
+ }
600
+ //this.log.warn("new key is " + key);
601
+ }
602
+ //======== version check
603
+ if (key.includes("global.version")) {
604
+ //this.log.info("in version, value " + value);
605
+ const versionInfo = value.split(".");
606
+ if (versionInfo.length > 1) {
607
+ this.log.debug(`installed ebusd version is ${versionInfo[0]}.${versionInfo[1]}`);
608
+ this.ebusdVersion[0] = versionInfo[0];
609
+ this.ebusdVersion[1] = versionInfo[1];
610
+ this.VersionCheck();
611
+ }
612
+ }
613
+ if (key.includes("global.updatecheck")) {
614
+ //revision v21.2 available
615
+ value = value.replace("revision v", "");
616
+ value = value.replace(" available", "");
617
+ const versionInfo = value.split(".");
618
+ if (versionInfo.length > 1) {
619
+ this.log.info(`found ebusd update version ${versionInfo[0]}.${versionInfo[1]}`);
620
+ this.ebusdUpdateVersion[0] = versionInfo[0];
621
+ this.ebusdUpdateVersion[1] = versionInfo[1];
622
+ this.VersionCheck();
623
+ }
624
+ }
625
+ //============ type check
626
+ let type = this.mapJsTypeToIoBrokerType(value);
627
+ if (this.config.useBoolean4Onoff) {
628
+ if (type == "string" && (value == "on" || value == "off")) {
629
+ this.log.debug(`Key ${key} change to boolean ${value}`);
630
+ //Key mc.messages.Status.fields.1.value could be boolean off
631
+ type = "boolean";
632
+ if (value == "on") {
633
+ value = true;
634
+ }
635
+ else {
636
+ value = false;
637
+ }
638
+ }
639
+ }
640
+ //EVU Sperrzeit
641
+ if (key.includes(".hcmode2.value") || key.includes(".hcmode.value")) {
642
+ if (parseInt(value) === 0) {
643
+ this.log.info(`${key}in hcmode2 with value 0: off`);
644
+ value = "off";
645
+ }
646
+ else if (parseInt(value) === 5) {
647
+ this.log.info(`${key} with value 5: EVU Sperrzeit`);
648
+ value = "EVU Sperrzeit";
649
+ }
650
+ else {
651
+ this.log.debug(`in hcmode2, value ${value}`);
652
+ }
653
+ type = this.mapJsTypeToIoBrokerType(value);
654
+ }
655
+ //lastup umrechnen
656
+ if (key.includes(".lastup")) {
657
+ if (parseInt(value) > 0) {
658
+ //this.log.debug('Key : ' + key + ', Value : ' + newData[key] + " name " + name);
659
+ //umrechnen...
660
+ const oDate = new Date(value * 1000);
661
+ //const nDate = oDate.getDate();
662
+ //const nMonth = oDate.getMonth() + 1;
663
+ //const nYear = oDate.getFullYear();
664
+ //const nHours = oDate.getHours();
665
+ //const nMinutes = oDate.getMinutes();
666
+ //const nSeconds = oDate.getSeconds();
667
+ const sDate = oDate.toLocaleString();
668
+ value = sDate;
669
+ type = this.mapJsTypeToIoBrokerType(value);
670
+ const oToday = new Date();
671
+ let bSkip = false;
672
+ if (subnames[0].includes("scan") ||
673
+ subnames[0].includes("Scan") ||
674
+ subnames[0].includes("ehp") ||
675
+ (subnames.length > 2 && subnames[2].includes("currenterror")) ||
676
+ this.config.DisableTimeUpdateCheck) {
677
+ bSkip = true;
678
+ }
679
+ //this.log.debug("_______________size " + temp);
680
+ if (subnames.length > 2 && subnames[2].includes("Timer")) {
681
+ bSkip = true;
682
+ }
683
+ if (!bSkip && Math.abs(oDate.getTime() - oToday.getTime()) > 1 * 60 * 60 * 1000) {
684
+ const sError1 = `no update since ${sDate} ${key} `;
685
+ if (sError.includes("none")) {
686
+ sError = `ebus: ${sError1}`;
687
+ }
688
+ else {
689
+ sError += sError1;
690
+ }
691
+ this.log.warn(sError1);
692
+ }
693
+ }
694
+ }
695
+ //add and update data
696
+ await this.AddObject(key, type);
697
+ await this.UpdateObject(key, value);
698
+ //push to history
699
+ for (let ii = 0; ii < this.oHistoryVars.length; ii++) {
700
+ //this.log.debug("check " + key + "==" + oHistoryVars[ii].name);
701
+ // check uih.messages.YieldThisYear.fields.energy_1.value==ActualEnvironmentPower
702
+ /*
703
+ ehp.messages.ActualEnvironmentPower.fields.value.value
704
+ ehp.messages.YieldTotal.fields.value.value
705
+ ehp.messages.SourceTempInput.fields.temp.value
706
+ ehp.messages.SourceTempOutput.fields.temp.value
707
+ ehp.messages.HwcTemp.fields.temp.value
708
+ */
709
+ if (key === this.oHistoryVars[ii].name) {
710
+ const sTemp = '{"' + key + '": "' + value + '"}';
711
+ this.log.debug("push history " + sTemp);
712
+ historyvalues[ii] = [];
713
+ historyvalues[ii].push(JSON.parse(sTemp));
714
+ //this.log.debug(JSON.stringify(historyvalues));
715
+ }
716
+ }
717
+ }
718
+ await this.setState("history.error", { ack: true, val: sError });
719
+ //this.log.debug(JSON.stringify(historyvalues));
720
+ this.log.debug("all http done");
721
+ if (historyvalues.length > 0 && historydates.length > 0) {
722
+ if (this.config.History4Vis2) {
723
+ await this.UpdateHistory_Vis2(historyvalues, historydates);
724
+ }
725
+ else {
726
+ await this.UpdateHistory(historyvalues, historydates);
727
+ }
728
+ }
729
+ }
730
+ catch (e) {
731
+ this.log.error(`exception in ebusd_ReceiveData [${e}]`);
732
+ await this.setState("history.error", { ack: true, val: "exception in receive" });
733
+ }
734
+ }
735
+ mapJsTypeToIoBrokerType(value) {
736
+ if (Array.isArray(value)) {
737
+ return "array";
738
+ }
739
+ switch (typeof value) {
740
+ case "string": return "string";
741
+ case "number": return "number";
742
+ case "boolean": return "boolean";
743
+ case "object": return value === null ? "mixed" : "object";
744
+ default: return "mixed";
745
+ }
746
+ }
747
+ async UpdateHistory_Vis2(values, dates) {
748
+ this.log.debug(`start history 4 VIS-2 ${JSON.stringify(values)} ${JSON.stringify(dates)}`);
749
+ //not used anymore
750
+ await this.setState("history.date", { ack: true, val: "" });
751
+ for (let s = 0; s < values.length; s++) {
752
+ const values1 = values[s];
753
+ //this.log.debug(s + " " + JSON.stringify(values1));
754
+ let val2Write = [];
755
+ const ctr = s + 1;
756
+ const obj = await this.getStateAsync(`history.value${ctr}`);
757
+ if (obj === null || obj === undefined) {
758
+ this.log.warn(`history.value${ctr} not found, creating DP ${JSON.stringify(obj)}`);
759
+ await this.setState(`history.value${ctr}`, { ack: true, val: "[]" });
760
+ }
761
+ else {
762
+ if (obj.val != null && obj.val != "" && typeof obj.val === "string") {
763
+ val2Write = JSON.parse(obj.val);
764
+ this.log.debug(`history.value${ctr} got ${JSON.stringify(val2Write)}`);
765
+ }
766
+ }
767
+ for (let ss = 0; ss < values1.length; ss++) {
768
+ const values2 = values1[ss];
769
+ //this.log.debug(ss + " " + JSON.stringify(values2));
770
+ let d = 0;
771
+ for (const n in values2) {
772
+ const val = values2[n];
773
+ const time = dates[d].time;
774
+ const date = dates[d].date;
775
+ d++;
776
+ const times = time.split(":");
777
+ const datesl = date.split(".");
778
+ const day = parseInt(datesl[0]);
779
+ const month = parseInt(datesl[1]) - 1;
780
+ const year = parseInt(datesl[2]);
781
+ const hours = parseInt(times[0]);
782
+ const minutes = parseInt(times[1]);
783
+ const oDate = new Date(year, month, day, hours, minutes, 0, 0);
784
+ this.log.debug(`${n} ${val} ${oDate.toLocaleString()}`);
785
+ val2Write.push([oDate, val]);
786
+ if (val2Write.length > 200) {
787
+ for (let i = val2Write.length; i > 200; i--) {
788
+ //this.log.debug("delete");
789
+ val2Write.shift();
790
+ }
791
+ }
792
+ }
793
+ }
794
+ await this.setState(`history.value${ctr}`, { ack: true, val: JSON.stringify(val2Write) });
795
+ }
796
+ }
797
+ async UpdateHistory(values, dates) {
798
+ if (this.oHistoryVars.length > 0) {
799
+ //prüfen ob alle json gleich lang sind
800
+ let NoOfDates = -1;
801
+ const obj = await this.getStateAsync("history.date");
802
+ if (obj !== undefined && obj != null) {
803
+ try {
804
+ let oEbusDates = [];
805
+ //this.log.debug("before " + obj.val);
806
+ if (obj.val != null && obj.val != "" && typeof obj.val === "string") {
807
+ oEbusDates = JSON.parse(obj.val);
808
+ }
809
+ //this.log.debug("after parse " + JSON.stringify(oEbusDates));
810
+ oEbusDates.push(dates);
811
+ //this.log.debug("after push " + JSON.stringify(oEbusDates));
812
+ //limit length of object...
813
+ if (oEbusDates.length > 200) {
814
+ for (let i = oEbusDates.length; i > 200; i--) {
815
+ //this.log.debug("delete");
816
+ oEbusDates.shift();
817
+ }
818
+ }
819
+ NoOfDates = oEbusDates.length;
820
+ await this.setState("history.date", { ack: true, val: JSON.stringify(oEbusDates) });
821
+ }
822
+ catch (e) {
823
+ this.log.error(`exception in UpdateHistory part1 [${e}]`);
824
+ await this.setState("history.date", { ack: true, val: "[]" });
825
+ NoOfDates = 0;
826
+ }
827
+ }
828
+ else {
829
+ this.log.warn("history.date not found, creating DP ");
830
+ await this.setState("history.date", { ack: true, val: "[]" });
831
+ NoOfDates = 0;
832
+ }
833
+ if (this.oHistoryVars.length > 0) {
834
+ for (let ctr = 1; ctr <= this.oHistoryVars.length; ctr++) {
835
+ if (this.oHistoryVars[ctr - 1].name.length > 0) {
836
+ const ctrOkay = await this.UpdateHistoryValues(values, ctr, NoOfDates);
837
+ if (!ctrOkay) {
838
+ await this.setState("history.date", { ack: true, val: "[]" });
839
+ NoOfDates = 0;
840
+ this.log.warn("reset history date too");
841
+ }
842
+ }
843
+ else {
844
+ this.log.debug(`ignoring history value ${ctr}`);
845
+ }
846
+ }
847
+ this.log.info("all history done");
848
+ }
849
+ }
850
+ else {
851
+ this.log.debug("nothing to do for history");
852
+ }
853
+ }
854
+ async UpdateHistoryValues(values, ctr, curDateCtr) {
855
+ let bRet = true;
856
+ const obj = await this.getStateAsync(`history.value${ctr}`);
857
+ if (obj !== undefined && obj != null) {
858
+ try {
859
+ let oEbusValues = [];
860
+ if (obj !== null) {
861
+ //this.log.debug("before " + obj.val);
862
+ if (obj.val != null && obj.val != "" && typeof obj.val === "string") {
863
+ oEbusValues = JSON.parse(obj.val);
864
+ }
865
+ //this.log.debug("after parse " + JSON.stringify(oEbusValues));
866
+ //this.log.debug("after parse cnt " + oEbusValues.length);
867
+ }
868
+ //this.log.debug("values " + ctr + ": " + JSON.stringify(values[ctr-1]));
869
+ oEbusValues.push(values[ctr - 1]);
870
+ //this.log.debug("after push " + JSON.stringify(oEbusValues));
871
+ //this.log.debug("after push cnt " + oEbusValues.length);
872
+ //limit length of object...
873
+ if (oEbusValues.length > 200) {
874
+ for (let i = oEbusValues.length; i > 200; i--) {
875
+ //this.log.debug("delete");
876
+ oEbusValues.shift();
877
+ }
878
+ }
879
+ const key = `history.value${ctr}`;
880
+ this.log.debug(`update history ${key}`);
881
+ if (curDateCtr != oEbusValues.length) {
882
+ bRet = false;
883
+ await this.setState(`history.value${ctr}`, { ack: true, val: "[]" });
884
+ this.log.warn(`reset history ${key} because number of values different to date values`);
885
+ }
886
+ else {
887
+ await this.setState(key, { ack: true, val: JSON.stringify(oEbusValues) });
888
+ }
889
+ }
890
+ catch (e) {
891
+ this.log.error(`exception in UpdateHistory part2 [${e}]`);
892
+ await this.setState(`history.value${ctr}`, { ack: true, val: "[]" });
893
+ if (curDateCtr > 0) {
894
+ bRet = false;
895
+ }
896
+ }
897
+ }
898
+ else {
899
+ this.log.warn(`history.value${ctr} not found, creating DP ${JSON.stringify(obj)}`);
900
+ await this.setState(`history.value${ctr}`, { ack: true, val: "[]" });
901
+ if (curDateCtr > 0) {
902
+ bRet = false;
903
+ }
904
+ }
905
+ return bRet;
906
+ }
907
+ //this function just triggers ebusd to read data; result will not be parsed; we just take the values from http result
908
+ //here we need a loop over all configured read data in admin-page
909
+ async ebusd_ReadValues() {
910
+ if (this.oPolledVars.length > 0) {
911
+ this.log.debug(`to poll ctr ${this.oPolledVars.length} vals: ${JSON.stringify(this.oPolledVars)}`);
912
+ try {
913
+ //const socket = new net.Socket();
914
+ //const promiseSocket = new PromiseSocket(socket);
915
+ //await promiseSocket.connect(parseInt(this.config.targetTelnetPort), this.config.targetIP);
916
+ //this.log.debug(`telnet connected to poll variables ${ this.config.targetIP } port ${ this.config.targetTelnetPort}`);
917
+ //promiseSocket.setTimeout(5000);
918
+ const telnet = new TelnetClient_1.default();
919
+ await telnet.connect(this.config.targetIP, this.config.targetTelnetPort);
920
+ let retries = 0;
921
+ for (let nCtr = 0; nCtr < this.oPolledVars.length; nCtr++) {
922
+ let circuit = "";
923
+ let params = "";
924
+ if (this.oPolledVars[nCtr].circuit != null && this.oPolledVars[nCtr].circuit.length > 0) {
925
+ circuit = `-c ${this.oPolledVars[nCtr].circuit} `;
926
+ }
927
+ if (this.oPolledVars[nCtr].parameter != null && this.oPolledVars[nCtr].parameter.length > 0) {
928
+ params = ` ${this.oPolledVars[nCtr].parameter}`;
929
+ }
930
+ let cmd = `read -f ${circuit}${this.oPolledVars[nCtr].name}${params}`;
931
+ this.log.debug(`send cmd ${cmd}`);
932
+ cmd += "\n";
933
+ let data = null;
934
+ try {
935
+ //await promiseSocket.write(cmd);
936
+ await telnet.write(cmd);
937
+ //const data = await promiseSocket.read();
938
+ data = await telnet.read();
939
+ }
940
+ catch (e) {
941
+ this.log.warn(`exception from tcp socket write/read in ebusd_ReadValues for cmd ${cmd}` + `[${e}]` + ` -> retry`);
942
+ //todo: retry nur für timeout und arbitration lost? 2025-11-01
943
+ retries++;
944
+ if (retries > this.config.maxretries) {
945
+ this.log.error(`max retries, skip cmd ${cmd}`);
946
+ }
947
+ else {
948
+ nCtr--; //counter wieder zurücksetzen
949
+ this.log.debug("retry to send data ");
950
+ }
951
+ }
952
+ if (data !== null) {
953
+ this.log.debug(`received ${data} for ${JSON.stringify(this.oPolledVars[nCtr])}`);
954
+ //todo: parse data and set DP's 2025-11-01
955
+ }
956
+ //received ERR: arbitration lost for YieldThisYear
957
+ //if (data !== null && data.includes("ERR")) {
958
+ // this.log.warn(`sent ${ cmd }, received ${ data } for ${ JSON.stringify(oPolledVars[nCtr]) } please check ebusd logs for details!`);
959
+ //
960
+ // /*
961
+ // * sent read -f YieldLastYear, received ERR: arbitration lost for {"circuit":"","name":"YieldLastYear","parameter":""}
962
+ // * */
963
+ // if (data.includes("arbitration lost")) {
964
+ // retries++;
965
+ // if (retries > this.config.maxretries) {
966
+ // this.log.error(`max retries, skip cmd ${ cmd}`);
967
+ // retries = 0;
968
+ // } else {
969
+ // nCtr--;
970
+ // this.log.debug("retry to send data ");
971
+ // }
972
+ // }
973
+ //} else {
974
+ //
975
+ // //muss wieder debug werden 2025-11-01 todo
976
+ // this.log.info(`received ${ data } for ${ JSON.stringify(oPolledVars[nCtr])}`);
977
+ //}
978
+ }
979
+ //promiseSocket.destroy();
980
+ await telnet.disconnect();
981
+ this.log.debug("telnet disonnected");
982
+ }
983
+ catch (e) {
984
+ this.log.error(`exception from tcp socket in ebusd_ReadValues ` + `[${e}]`);
985
+ }
986
+ }
987
+ else {
988
+ this.log.debug("nothing to poll; skip telnet");
989
+ }
990
+ }
991
+ async FindParams(obj) {
992
+ //todo muss wieder debug werden 2025-11-01
993
+ this.log.debug(`FindParams ${JSON.stringify(obj)}`);
994
+ const list = [];
995
+ try {
996
+ //FindParams {"command":"findParams","message":{"circuit":"cc"},"from":"system.this.admin.0","callback":{"message":{"circuit":"cc"},"id":90,"ack":false,"time":1733690088670},"_id":39690903}
997
+ if (obj.message !== null && obj.message.circuit !== null) {
998
+ const circuit = obj.message.circuit;
999
+ //const socket = new net.Socket();
1000
+ //const promiseSocket = new PromiseSocket(socket);
1001
+ //await promiseSocket.connect(parseInt(this.config.targetTelnetPort), this.config.targetIP);
1002
+ //this.log.debug("telnet connected for cmd");
1003
+ //promiseSocket.setTimeout(5000);
1004
+ const telnet = new TelnetClient_1.default();
1005
+ await telnet.connect(this.config.targetIP, this.config.targetTelnetPort);
1006
+ const cmd = `find -c ${circuit} -F circuit,name\n`;
1007
+ //await promiseSocket.write(cmd);
1008
+ this.log.debug(`send cmd ${cmd}`);
1009
+ await telnet.write(cmd);
1010
+ this.log.debug(`sent, wait for data...`);
1011
+ //const data = await promiseSocket.read();
1012
+ const data = await telnet.read();
1013
+ this.log.info(`data received: ` + data);
1014
+ if (data.includes("ERR")) {
1015
+ this.log.warn(`received error! sent find, received ${data} please check ebusd logs for details! ${cmd}`);
1016
+ }
1017
+ else {
1018
+ this.log.info(`received ${typeof data} ${data} ${+cmd}`);
1019
+ }
1020
+ /*
1021
+ 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
1022
+ */
1023
+ //const str = new TextDecoder().decode(data);
1024
+ let str;
1025
+ if (typeof data === "string") {
1026
+ str = data;
1027
+ }
1028
+ else if (data instanceof Uint8Array) {
1029
+ str = new TextDecoder().decode(data);
1030
+ }
1031
+ else if (data instanceof ArrayBuffer) {
1032
+ str = new TextDecoder().decode(new Uint8Array(data));
1033
+ }
1034
+ else {
1035
+ // fallback: convert to string
1036
+ str = String(data);
1037
+ }
1038
+ const datas = str.split(/[\r?\n,]+/);
1039
+ this.log.info("found entries: " + datas.length);
1040
+ for (let i = 0; i < datas.length; i++) {
1041
+ //this.log.info(JSON.stringify(datas[i]));
1042
+ const names = datas[i].split(",");
1043
+ //doppelte und leere herausfiltern
1044
+ let add = true;
1045
+ if (names[0] == "" || names[1] == "") {
1046
+ add = false;
1047
+ }
1048
+ else {
1049
+ for (let n = 0; n < list.length; n++) {
1050
+ if (list[n].circuit == names[0] && list[n].name == names[1]) {
1051
+ add = false;
1052
+ //already in list
1053
+ }
1054
+ }
1055
+ }
1056
+ if (add) {
1057
+ const entry = {
1058
+ active: false,
1059
+ circuit: names[0],
1060
+ name: names[1],
1061
+ };
1062
+ list.push(entry);
1063
+ }
1064
+ }
1065
+ await telnet.disconnect();
1066
+ }
1067
+ else {
1068
+ this.log.error("no circuit defined where to look for parameter, check values!");
1069
+ }
1070
+ }
1071
+ catch (e) {
1072
+ this.log.error(`exception in FindParams ` + `[${e}]`);
1073
+ }
1074
+ this.log.info(`parameters ${JSON.stringify(list)}`);
1075
+ this.sendTo(obj.from, obj.command, list, obj.callback);
1076
+ }
1077
+ /*
1078
+ async CallExternalScript(script, msg) {
1079
+
1080
+
1081
+
1082
+ try {
1083
+ if (os.platform() == "linux") {
1084
+ //const cmd = spawn("ls", ["-la"]);
1085
+
1086
+ this.log.info("we are on linux ");
1087
+
1088
+ const folderName = path.join(__dirname, '..', 'iobroker.ebus', 'lib', 'scripts');
1089
+
1090
+
1091
+ if (!fs.existsSync(folderName)) {
1092
+
1093
+ this.log.info("folder doesnt exists " + folderName);
1094
+
1095
+ this.sendTo(msg.from, msg.command, { error: 'script folder not found ' + folderName }, msg.callback);
1096
+ return;
1097
+ }
1098
+
1099
+
1100
+ this.log.info("folder exists " + folderName);
1101
+
1102
+ const scriptfile = path.join(folderName, script);
1103
+ const stats = await fs.statSync(scriptfile);
1104
+
1105
+ if (!stats.isFile()) {
1106
+
1107
+ this.log.info("file doenst exists " + scriptfile);
1108
+
1109
+ this.sendTo(msg.from, msg.command, { error: 'script not found ' + scriptfile }, msg.callback);
1110
+
1111
+ return;
1112
+
1113
+ } else {
1114
+
1115
+ this.log.info("file exists " + scriptfile);
1116
+
1117
+ const cmd = spawn(scriptfile, [""]);
1118
+
1119
+ cmd.stdout.on("data", data => {
1120
+ this.log.error(`stdout: ${data}`);
1121
+ });
1122
+
1123
+ cmd.stderr.on("data", data => {
1124
+ this.log.error(`stderr: ${data}`);
1125
+ });
1126
+
1127
+ cmd.on('error', (error) => {
1128
+ this.log.error(`error: ${error.message}`);
1129
+ });
1130
+
1131
+ cmd.on("close", code => {
1132
+ this.log.error(`child process exited with code ${code}`);
1133
+ this.sendTo(msg.from, msg.command, {
1134
+ info: 'success '
1135
+
1136
+ }, msg.callback);
1137
+ });
1138
+ }
1139
+
1140
+ } else {
1141
+ this.sendTo(msg.from, msg.command, { error: 'possible only on Linux systems, this system is ' + os.platform() }, msg.callback);
1142
+ }
1143
+ } catch (e) {
1144
+ this.log.error("exception in CallExternalScript " + "[" + e + "]");
1145
+
1146
+ this.sendTo(msg.from, msg.command, { error: 'error ' + e }, msg.callback);
1147
+ }
1148
+
1149
+
1150
+ /*
1151
+ try {
1152
+ if (os.platform() == "linux") {
1153
+
1154
+
1155
+ let cmd = "\\lib\\scripts\\" + script;
1156
+
1157
+ exec(cmd, (error, stdout, stderr) => {
1158
+ if (error) {
1159
+ this.log.error(`error: ${error.message}`);
1160
+ this.sendTo(msg.from, msg.command, { error: 'error ' + error.message }, msg.callback);
1161
+ return;
1162
+ }
1163
+ if (stderr) {
1164
+ this.log.error(`stderr: ${stderr}`);
1165
+ this.sendTo(msg.from, msg.command, { error: 'error ' + stderr }, msg.callback);
1166
+ return;
1167
+ }
1168
+ this.log.info(`stdout: ${stdout}`);
1169
+ this.sendTo(msg.from, msg.command, {
1170
+ info: 'success '
1171
+
1172
+ }, msg.callback);
1173
+ });
1174
+ }
1175
+ else {
1176
+ this.sendTo(msg.from, msg.command, { error: 'possible only on Linux systems, this system is ' + os.platform() }, msg.callback);
1177
+ }
1178
+ } catch (e) {
1179
+ this.log.error("exception in CallExternalScript " + "[" + e + "]");
1180
+ }
1181
+
1182
+ */
1183
+ //}
1184
+ async CheckVersion(version, msg) {
1185
+ if (version == "installable") {
1186
+ let vers = "unknown";
1187
+ if (this.ebusdUpdateVersion[0] > 0 && this.ebusdVersion[0] > 0) {
1188
+ vers = `${this.ebusdUpdateVersion[0]}.${this.ebusdUpdateVersion[1]}`;
1189
+ }
1190
+ else {
1191
+ vers = await this.GetLatestVersionGithub();
1192
+ }
1193
+ this.sendTo(msg.from, msg.command, vers, msg.callback);
1194
+ }
1195
+ else if (version == "current") {
1196
+ this.sendTo(msg.from, msg.command, `${this.ebusdVersion[0]}.${this.ebusdVersion[1]}`, msg.callback);
1197
+ }
1198
+ else if (version == "supported") {
1199
+ this.sendTo(msg.from, msg.command, `${this.ebusdMinVersion[0]}.${this.ebusdMinVersion[1]}`, msg.callback);
1200
+ }
1201
+ }
1202
+ async GetLatestVersionGithub() {
1203
+ let latestVersion = "unknown";
1204
+ try {
1205
+ const url = "https://api.github.com/repos/john30/ebusd/releases/latest";
1206
+ this.log.debug(`call ${url}`);
1207
+ const result = await axios_1.default.get(url, { timeout: 5000 });
1208
+ if (result != null && result.status == 200 && result.data != null) {
1209
+ this.log.info(`installable version on github ${JSON.stringify(result.data.tag_name)} (${JSON.stringify(result.data.name)})`);
1210
+ latestVersion =
1211
+ "on github " + JSON.stringify(result.data.tag_name) + "(" + JSON.stringify(result.data.name) + ")";
1212
+ }
1213
+ else {
1214
+ latestVersion = "unknown / no result";
1215
+ }
1216
+ }
1217
+ catch (e) {
1218
+ this.log.error(`exception in GetLatestVersionGithub [${e}]`);
1219
+ latestVersion = "unknown / error";
1220
+ }
1221
+ return latestVersion;
1222
+ }
1223
+ //==========================================================
1224
+ // replace by general functions from base.ts
1225
+ async CreateObject(key, obj) {
1226
+ const obj_new = await this.getObjectAsync(key);
1227
+ //adapter.log.warn("got object " + JSON.stringify(obj_new));
1228
+ if (obj_new != null) {
1229
+ if ((obj_new.common.role != obj.common.role ||
1230
+ obj_new.common.type != obj.common.type ||
1231
+ (obj_new.common.unit != obj.common.unit && obj.common.unit != null) ||
1232
+ obj_new.common.read != obj.common.read ||
1233
+ obj_new.common.write != obj.common.write ||
1234
+ obj_new.common.name != obj.common.name) &&
1235
+ obj.type === "state") {
1236
+ this.log.warn(`change object ${JSON.stringify(obj)} ${JSON.stringify(obj_new)}`);
1237
+ await this.extendObject(key, {
1238
+ common: {
1239
+ name: obj.common.name,
1240
+ role: obj.common.role,
1241
+ type: obj.common.type,
1242
+ unit: obj.common.unit,
1243
+ read: obj.common.read,
1244
+ write: obj.common.write,
1245
+ },
1246
+ });
1247
+ }
1248
+ }
1249
+ else {
1250
+ await this.setObjectNotExistsAsync(key, obj);
1251
+ }
1252
+ }
1253
+ //circuit,name,comment
1254
+ async UpdateDP(circuit, name, comment) {
1255
+ const key = `${circuit}.messages.${name}`;
1256
+ this.log.debug(`update check for ${key}`);
1257
+ // ehp.messages.Injection
1258
+ //ebus.0.ehp.messages.Injection
1259
+ const obj = await this.getObjectAsync(key);
1260
+ this.log.debug(`update check got ${JSON.stringify(obj)}`);
1261
+ //update check got null
1262
+ if (obj != null) {
1263
+ if (obj.common.name != comment) {
1264
+ this.log.debug(`update ${key} ${comment}`);
1265
+ await this.extendObject(key, {
1266
+ common: {
1267
+ name: comment,
1268
+ read: true,
1269
+ write: false,
1270
+ },
1271
+ });
1272
+ }
1273
+ }
1274
+ else {
1275
+ await this.setObjectNotExistsAsync(key, {
1276
+ type: "channel",
1277
+ common: {
1278
+ name: comment
1279
+ //read: true,
1280
+ //write: false,
1281
+ },
1282
+ native: {}
1283
+ });
1284
+ }
1285
+ }
1286
+ async AddObject(key, types) {
1287
+ try {
1288
+ const obj = await this.getObjectAsync(key);
1289
+ if (obj != null) {
1290
+ if (obj.common.role != "value" || obj.common.type != types) {
1291
+ this.log.debug(` !!! need to extend for ${key}`);
1292
+ await this.extendObject(key, {
1293
+ common: {
1294
+ type: types,
1295
+ role: "value",
1296
+ },
1297
+ });
1298
+ }
1299
+ }
1300
+ else {
1301
+ this.log.warn(` !!! does not exist, creating now ${key}`);
1302
+ await this.setObjectNotExistsAsync(key, {
1303
+ type: "state",
1304
+ common: {
1305
+ name: "data",
1306
+ type: types,
1307
+ role: "value",
1308
+ unit: "",
1309
+ read: true,
1310
+ write: false,
1311
+ },
1312
+ native: {
1313
+ location: key,
1314
+ },
1315
+ });
1316
+ }
1317
+ }
1318
+ catch (e) {
1319
+ this.log.error(`exception in AddObject ` + `[${e}]`);
1320
+ }
1321
+ }
1322
+ async UpdateObject(key, value) {
1323
+ try {
1324
+ if (value === undefined) {
1325
+ this.log.warn(`updateObject: not updated ${key} value: ${value} ${typeof value}`);
1326
+ }
1327
+ else if (value == null) {
1328
+ this.log.debug(`updateObject: update to null ${key} value: ${value}`);
1329
+ await this.setState(key, { ack: true, val: null });
1330
+ }
1331
+ else {
1332
+ //this.log.debug("updateObject " + key + " : " + value);
1333
+ await this.setState(key, { ack: true, val: value });
1334
+ }
1335
+ }
1336
+ catch (e) {
1337
+ this.log.error(`exception in UpdateObject ` + `[${e}]`);
1338
+ }
1339
+ }
1340
+ }
1341
+ exports.ebus = ebus;
1342
+ if (require.main !== module) {
1343
+ // Exportiere den Konstruktor im Kompaktmodus
1344
+ module.exports = (options) => new ebus(options);
1345
+ }
1346
+ else {
1347
+ // Starte die Instanz direkt
1348
+ (() => new ebus())();
1349
+ }
1350
+ //# sourceMappingURL=main.js.map