iobroker.senec 1.1.1 → 1.3.3

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 CHANGED
@@ -1,16 +1,9 @@
1
1
  'use strict';
2
2
 
3
- /*
4
- * Created with @iobroker/create-adapter v1.17.0
5
- */
6
-
7
3
  const utils = require('@iobroker/adapter-core');
8
4
  const request = require('request');
9
- const mode_desc = require(__dirname + '/lib/mode_desc.js');
10
- const sys_type_desc = require(__dirname + '/lib/sys_type_desc.js');
11
- const country_desc = require(__dirname + '/lib/country_desc.js');
12
- const batt_type_desc = require(__dirname + '/lib/batt_type_desc.js');
13
5
  const state_attr = require(__dirname + '/lib/state_attr.js');
6
+ const state_trans = require(__dirname + '/lib/state_trans.js');
14
7
 
15
8
  let retry = 0; // retry-counter
16
9
  let retryLowPrio = 0; // retry-counter
@@ -61,7 +54,7 @@ class Senec extends utils.Adapter {
61
54
  clearTimeout(this.timerLowPrio);
62
55
  }
63
56
  this.log.info('cleaned everything up...');
64
- this.setState('info.connection', false, false);
57
+ this.setState('info.connection', false, true);
65
58
  callback();
66
59
  } catch (e) {
67
60
  callback();
@@ -163,24 +156,14 @@ class Senec extends utils.Adapter {
163
156
  form += ',"PWR_UNIT":{"POWER_L1":"","POWER_L2":"","POWER_L3":""}';
164
157
  form += ',"PM1OBJ1":{"FREQ":"","U_AC":"","I_AC":"","P_AC":"","P_TOTAL":""}';
165
158
  form += ',"PM1OBJ2":{"FREQ":"","U_AC":"","I_AC":"","P_AC":"","P_TOTAL":""}';
159
+ form += ',"STATISTIC":{"LIVE_GRID_EXPORT":"","LIVE_GRID_IMPORT":"","LIVE_HOUSE_CONS":"","LIVE_PV_GEN":"","LIVE_BAT_CHARGE_MASTER":"","LIVE_BAT_DISCHARGE_MASTER":""}';
166
160
  form += '}';
167
-
161
+
168
162
  try {
169
163
  const body = await this.doGet(url, form, this, this.config.pollingTimeout);
170
164
  var obj = JSON.parse(body, reviverNumParse);
171
-
172
165
  await this.evalPoll(obj);
173
166
 
174
- // this isn't part of the JSON but we supply it as an additional state for easier reading of system-mode
175
- const key = "ENERGY.STAT_STATE_Text";
176
- const desc = (state_attr[key] !== undefined) ? state_attr[key].name : "undefined";
177
- const unit = (state_attr[key] !== undefined) ? state_attr[key].unit : "";
178
- if (mode_desc[obj.ENERGY.STAT_STATE] === undefined) {
179
- this.log.warn('Senec mode definition missing for + ' + obj.ENERGY.STAT_STATE);
180
- }
181
- var value = (mode_desc[obj.ENERGY.STAT_STATE] !== undefined) ? mode_desc[obj.ENERGY.STAT_STATE].name : "unknown";
182
- this.doState(key, value, desc, unit);
183
-
184
167
  retry = 0;
185
168
  this.timer = setTimeout(() => this.readSenecV21(), this.config.interval * 1000);
186
169
  } catch (error) {
@@ -204,7 +187,7 @@ class Senec extends utils.Adapter {
204
187
  // we are polling all known objects ...
205
188
 
206
189
  const url = 'http://' + this.config.senecip + '/lala.cgi';
207
- const form = '{"STATISTIC":{},"ENERGY":{},"FEATURES":{},"LOG":{},"SYS_UPDATE":{},"WIZARD":{},"BMS":{},"BAT1":{},"BAT1OBJ1":{},"BAT1OBJ2":{},"BAT1OBJ2":{},"BAT1OBJ3":{},"BAT1OBJ4":{},"PWR_UNIT":{},"PV1":{},"FACTORY":{},"GRIDCONFIG":{}}';
190
+ const form = '{"STATISTIC":{},"ENERGY":{},"FEATURES":{},"LOG":{},"SYS_UPDATE":{},"WIZARD":{},"BMS":{},"BAT1":{},"BAT1OBJ1":{},"BAT1OBJ2":{},"BAT1OBJ2":{},"BAT1OBJ3":{},"BAT1OBJ4":{},"PWR_UNIT":{},"PM1OBJ1":{},"PM1OBJ2":{},"PV1":{},"FACTORY":{},"GRIDCONFIG":{},"EG_CONTROL":{},"RTC":{},"PM1":{},"TEMPMEASURE":{},"DEBUG":{},"SOCKETS":{},"CASC":{},"WALLBOX":{},"CONNX50":{},"STECA":{}}';
208
191
 
209
192
  try {
210
193
  const body = await this.doGet(url, form, this, this.config.pollingTimeout);
@@ -229,7 +212,7 @@ class Senec extends utils.Adapter {
229
212
  /**
230
213
  * sets a state's value and creates the state if it doesn't exist yet
231
214
  */
232
- async doState(name, value, description, unit) {
215
+ async doState(name, value, description, unit, write) {
233
216
  await this.setObjectNotExistsAsync(name, {
234
217
  type: 'state',
235
218
  common: {
@@ -238,7 +221,7 @@ class Senec extends utils.Adapter {
238
221
  role: 'value',
239
222
  unit: unit,
240
223
  read: true,
241
- write: false
224
+ write: write
242
225
  },
243
226
  native: {}
244
227
  });
@@ -257,19 +240,59 @@ class Senec extends utils.Adapter {
257
240
  this.log.debug("Updating object: " + name + " (unit): " + obj.common.unit + " -> " + unit);
258
241
  await this.extendObject(name, {common: {unit: unit}});
259
242
  }
243
+ if (obj.common.write != write) {
244
+ this.log.debug("Updating object: " + name + " (write): " + obj.common.write + " -> " + write);
245
+ await this.extendObject(name, {common: {write: write}});
246
+ }
260
247
 
261
248
  var oldState = await this.getStateAsync(name);
262
249
  if (oldState) {
263
- if (oldState.val === value)
250
+ if (oldState.val === value) {
251
+ await this.checkUpdateSelfStat(name);
264
252
  return;
253
+ }
265
254
  this.log.silly('Update: ' + name + ': ' + oldState.val + ' -> ' + value);
266
255
  }
267
256
  await this.setStateAsync(name, {
268
257
  val: value,
269
258
  ack: true
270
259
  });
271
- }
260
+ await this.checkUpdateSelfStat(name);
261
+ await this.doDecode(name, value);
262
+ }
263
+
264
+ /**
265
+ * Checks if there is decoding possible for a given value and creates/updates a decoded state
266
+ * Language used for translations is the language of the SENEC appliance
267
+ */
268
+ async doDecode(name, value) {
269
+ // Lang: WIZARD.GUI_LANG 0=German, 1=English, 2=Italian
270
+ var lang = 1; // fallback to english
271
+ var langState = await this.getStateAsync('WIZARD.GUI_LANG');
272
+ if (langState) lang = langState.val;
273
+ this.log.silly("Senec language: " + lang);
274
+ var key = name;
275
+ if (!isNaN(name.substring(name.lastIndexOf('.')) + 1)) key = name.substring(0, name.lastIndexOf('.'));
276
+ this.log.silly("Checking: " + name + " -> " + key);
277
+
278
+ if (state_trans[key + "." + lang] !== undefined) {
279
+ this.log.silly("Trans found for: " + key + "." + lang);
280
+ const trans = (state_trans[key + "." + lang] !== undefined ? (state_trans[key + "." + lang][value] !== undefined ? state_trans[key + "." + lang][value] : "(unknown)") : "(unknown)");
281
+ this.log.debug("Trans " + key + ":" + value + " = " + trans);
282
+ const desc = (state_attr[key + "_Text"] !== undefined) ? state_attr[key + "_Text"].name : key;
283
+ await this.doState(name + "_Text", trans, desc, "", true);
284
+ }
285
+ }
272
286
 
287
+ /**
288
+ * Helper routine
289
+ */
290
+ async checkUpdateSelfStat(name) {
291
+ if (name === "STATISTIC.LIVE_GRID_EXPORT" || name === "STATISTIC.LIVE_GRID_IMPORT" || name === "STATISTIC.LIVE_HOUSE_CONS" || name === "STATISTIC.LIVE_PV_GEN" || name === "STATISTIC.LIVE_BAT_CHARGE_MASTER" || name === "STATISTIC.LIVE_BAT_DISCHARGE_MASTER") {
292
+ await this.updateSelfStat(name);
293
+ }
294
+ }
295
+
273
296
  /**
274
297
  * evaluates data polled from SENEC system.
275
298
  * creates / updates the state.
@@ -287,15 +310,112 @@ class Senec extends utils.Adapter {
287
310
 
288
311
  if (Array.isArray(value2)) {
289
312
  for (var i = 0; i < value2.length; i++) {
290
- this.doState(key + '.' + i, ValueTyping(key, value2[i]), desc + '[' + i + ']', unit);
313
+ this.doState(key + '.' + i, ValueTyping(key, value2[i]), desc + '[' + i + ']', unit, false);
291
314
  }
292
315
  } else {
293
- this.doState(key, ValueTyping(key, value2), desc, unit);
316
+ this.doState(key, ValueTyping(key, value2), desc, unit, false);
294
317
  }
295
318
  }
296
319
  }
297
320
  }
298
321
  }
322
+
323
+ async updateSelfStat(name, value) {
324
+ await this.updateSelfStatHelper(name, value, ".today", ".yesterday", ".refValue", "Day", getCurDay());
325
+ await this.updateSelfStatHelper(name, value, ".week", ".lastWeek", ".refValueWeek", "Week", getCurWeek());
326
+ await this.updateSelfStatHelper(name, value, ".month", ".lastMonth", ".refValueMonth", "Month", getCurMonth());
327
+ await this.updateSelfStatHelper(name, value, ".year", ".lastYear", ".refValueYear", "Year", getCurYear());
328
+ return;
329
+ }
330
+
331
+ async updateSelfStatHelper(name, value, today, yesterday, refValue, day, curDay) {
332
+ const key = "_calc." + name.substring(10);
333
+
334
+ const refDayObj = await this.getStateAsync(key + ".ref" + day);
335
+ const refDay = refDayObj ? refDayObj.val : -1;
336
+
337
+ const valCurObj = await this.getStateAsync(name);
338
+ const valCur = valCurObj ? valCurObj.val : 0;
339
+
340
+ const valRefObj = await this.getStateAsync(key + refValue);
341
+ const valRef = valRefObj ? valRefObj.val : 0;
342
+ const valTodayObj = await this.getStateAsync(key + today);
343
+ const valToday = valTodayObj ? valTodayObj.val : 0;
344
+
345
+ const descToday = (state_attr[key + today] !== undefined) ? state_attr[key + today].name : key;
346
+ const unitToday = (state_attr[key + today] !== undefined) ? state_attr[key + today].unit : "";
347
+ const descYesterday = (state_attr[key + yesterday] !== undefined) ? state_attr[key + yesterday].name : key;
348
+ const unitYesterday = (state_attr[key + yesterday] !== undefined) ? state_attr[key + yesterday].unit : "";
349
+ const descRef = (state_attr[key + refValue] !== undefined) ? state_attr[key + refValue].name : key;
350
+ const unitRef = (state_attr[key + refValue] !== undefined) ? state_attr[key + refValue].unit : "";
351
+ const descRefDay = (state_attr[key + ".ref" + day] !== undefined) ? state_attr[key + ".ref" + day].name : key;
352
+ const unitRefDay = (state_attr[key + ".ref" + day] !== undefined) ? state_attr[key + ".ref" + day].unit : "";
353
+
354
+ if (refDay != curDay) {
355
+ this.log.debug("New " + day + " (or first value seen). Updating stat data for: " + name.substring(10));
356
+ // Change of day
357
+ await this.doState(key + ".ref" + day, curDay, descRefDay, unitRefDay, false);
358
+ await this.doState(key + yesterday, valToday, descYesterday, unitYesterday, false);
359
+ await this.doState(key + today, 0, descToday, unitToday, false);
360
+ if (valRef < valCur) {
361
+ await this.doState(key + refValue, valCur, descRef, unitRef, true);
362
+ } else {
363
+ this.log.warning("Not updating reference value for: " + name.substring(10) + "! Old RefValue (" + valRef + ") >= new RefValue (" + valCur + "). Impossible situation. If this is intentional, please update via admin!");
364
+ }
365
+ } else {
366
+ this.log.debug("Updating " + day +" value for: " + name.substring(10));
367
+ // update today's value
368
+ await this.doState(key + today, Number((valCur - valRef).toFixed(2)), descToday, unitToday, false);
369
+ }
370
+
371
+ if (name === "STATISTIC.LIVE_HOUSE_CONS") await this.updateAutarkyHelper(today, yesterday, day, curDay); // otherwise we get way too many updates
372
+
373
+ }
374
+
375
+ async updateAutarkyHelper(today, yesterday, day, curDay) {
376
+ const key = "_calc.Autarky";
377
+
378
+ // reference object to decide on change of day
379
+ const refDayObj = await this.getStateAsync(key + ".ref" + day);
380
+ const refDay = refDayObj ? refDayObj.val : -1;
381
+ // current day's value (needed in case of day-change)
382
+ const valTodayObj = await this.getStateAsync(key + today);
383
+ const valToday = valTodayObj ? valTodayObj.val : 0;
384
+
385
+ // reading values required for calc
386
+ const valBatChargeObj = await this.getStateAsync("_calc.LIVE_BAT_CHARGE_MASTER" + today);
387
+ const valBatCharge = valBatChargeObj ? valBatChargeObj.val : 0;
388
+ const valBatDischargeObj = await this.getStateAsync("_calc.LIVE_BAT_DISCHARGE_MASTER" + today);
389
+ const valBatDischarge = valBatDischargeObj ? valBatDischargeObj.val : 0;
390
+ const valGridExpObj = await this.getStateAsync("_calc.LIVE_GRID_EXPORT" + today);
391
+ const valGridExp = valGridExpObj ? valGridExpObj.val : 0;
392
+ const valGridImpObj = await this.getStateAsync("_calc.LIVE_GRID_IMPORT" + today);
393
+ const valGridImp = valGridImpObj ? valGridImpObj.val : 0;
394
+ const valHouseConsObj = await this.getStateAsync("_calc.LIVE_HOUSE_CONS" + today);
395
+ const valHouseCons = valHouseConsObj ? valHouseConsObj.val : 1;
396
+ const valPVGenObj = await this.getStateAsync("_calc.LIVE_PV_GEN" + today);
397
+ const valPVGen = valPVGenObj ? valPVGenObj.val : 0;
398
+
399
+ const descToday = (state_attr[key + today] !== undefined) ? state_attr[key + today].name : key;
400
+ const unitToday = (state_attr[key + today] !== undefined) ? state_attr[key + today].unit : "%";
401
+ const descYesterday = (state_attr[key + yesterday] !== undefined) ? state_attr[key + yesterday].name : key;
402
+ const unitYesterday = (state_attr[key + yesterday] !== undefined) ? state_attr[key + yesterday].unit : "%";
403
+ const descRefDay = (state_attr[key + ".ref" + day] !== undefined) ? state_attr[key + ".ref" + day].name : key;
404
+ const unitRefDay = (state_attr[key + ".ref" + day] !== undefined) ? state_attr[key + ".ref" + day].unit : "";
405
+
406
+ if (refDay != curDay) {
407
+ this.log.debug("New " + day + " (or first value seen). Updating Autarky data for: " + key + " " + day);
408
+ // Change of day
409
+ await this.doState(key + ".ref" + day, curDay, descRefDay, unitRefDay, false);
410
+ await this.doState(key + yesterday, valToday, descYesterday, unitYesterday, false);
411
+ // await this.doState(key + today, 0, descToday, unitToday, false); // we don't need to reset autarky to 0 because it is calculated by reference values.
412
+ // instead do the regular calc right after the change of day
413
+ }
414
+ this.log.debug("Updating Autarky " + day +" value for: " + key + today);
415
+ // update today's value - but beware of div/0
416
+ if (valHouseCons > 0) await this.doState(key + today, Number((((valPVGen - valGridExp - valBatCharge + valBatDischarge) / valHouseCons) * 100).toFixed(0)), descToday, unitToday, false);
417
+ }
418
+
299
419
  }
300
420
 
301
421
  /**
@@ -304,15 +424,6 @@ class Senec extends utils.Adapter {
304
424
  */
305
425
  const ValueTyping = (key, value) => {
306
426
  if (!isNaN(value)) value = Number(value); // otherwise iobroker will note it as string
307
- if (key === "FACTORY.SYS_TYPE") {
308
- return (sys_type_desc[value] !== undefined) ? sys_type_desc[value].name : "unknown";
309
- }
310
- if (key === "FACTORY.COUNTRY") {
311
- return (country_desc[value] !== undefined) ? country_desc[value].name : "unknown";
312
- }
313
- if (key === "FACTORY.BAT_TYPE") {
314
- return (batt_type_desc[value] !== undefined) ? batt_type_desc[value].name : "unknown";
315
- }
316
427
  if (state_attr[key] === undefined) {
317
428
  return value;
318
429
  }
@@ -430,8 +541,44 @@ const reviverNumParse = (key, value) => {
430
541
  }
431
542
  }
432
543
 
433
- // @ts-ignore parent is a valid property on module
434
- if (module.parent) {
544
+ /**
545
+ * Returns the current day of the year
546
+ */
547
+ const getCurDay = () => {
548
+ return (Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24));
549
+ }
550
+
551
+ /**
552
+ * Returns the current month of the year
553
+ */
554
+ const getCurMonth = () => {
555
+ return (new Date().getMonth());
556
+ }
557
+
558
+ /**
559
+ * Returns the current year
560
+ */
561
+ const getCurYear = () => {
562
+ return (new Date().getFullYear());
563
+ }
564
+
565
+ /**
566
+ * Returns the current week of the year
567
+ * Using Standard ISO8601
568
+ */
569
+ const getCurWeek = () => {
570
+ var tdt = new Date();
571
+ var dayn = (tdt.getDay() + 6) % 7;
572
+ tdt.setDate(tdt.getDate() - dayn + 3);
573
+ var firstThursday = tdt.valueOf();
574
+ tdt.setMonth(0, 1);
575
+ if (tdt.getDay() !== 4) {
576
+ tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
577
+ }
578
+ return 1 + Math.ceil((firstThursday - tdt) / 604800000);
579
+ }
580
+
581
+ if (require.main !== module) {
435
582
  // Export the constructor in compact mode
436
583
  /**
437
584
  * @param {Partial<ioBroker.AdapterOptions>} [options={}]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.senec",
3
- "version": "1.1.1",
3
+ "version": "1.3.3",
4
4
  "description": "Senec Home",
5
5
  "author": {
6
6
  "name": "NoBl",
@@ -25,38 +25,49 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "request": "^2.88.2",
28
- "@iobroker/adapter-core": "^2.4.0"
28
+ "@iobroker/adapter-core": "^2.5.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@iobroker/testing": "^2.3.0",
32
- "@types/chai": "^4.2.14",
33
- "@types/chai-as-promised": "^7.1.3",
34
- "@types/gulp": "^4.0.7",
35
- "@types/mocha": "^8.0.4",
36
- "@types/node": "^14.14.10",
31
+ "@alcalzone/release-script": "^3.5.2",
32
+ "@iobroker/testing": "^2.5.2",
33
+ "@types/chai": "^4.3.0",
34
+ "@types/chai-as-promised": "^7.1.4",
35
+ "@types/gulp": "^4.0.9",
36
+ "@types/mocha": "^9.0.0",
37
+ "@types/node": "^17.0.17",
37
38
  "@types/proxyquire": "^1.3.28",
38
- "@types/sinon": "^9.0.9",
39
- "@types/sinon-chai": "^3.2.5",
40
- "axios": "^0.21.1",
41
- "chai": "^4.2.0",
39
+ "@types/sinon": "^10.0.6",
40
+ "@types/sinon-chai": "^3.2.8",
41
+ "axios": "^0.25.0",
42
+ "chai": "^4.3.6",
42
43
  "chai-as-promised": "^7.1.1",
43
- "eslint": "^7.14.0",
44
+ "eslint": "^8.8.0",
44
45
  "gulp": "^4.0.2",
45
- "mocha": "^8.2.1",
46
+ "mocha": "^9.1.3",
46
47
  "proxyquire": "^2.1.3",
47
- "sinon": "^9.2.1",
48
- "sinon-chai": "^3.5.0",
49
- "typescript": "^4.1.2"
48
+ "sinon": "^12.0.1",
49
+ "sinon-chai": "^3.7.0",
50
+ "typescript": "~4.5.5"
50
51
  },
51
52
  "main": "main.js",
53
+ "files": [
54
+ "admin{,/!(src)/**}/!(tsconfig|tsconfig.*).json",
55
+ "admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}",
56
+ "lib/",
57
+ "www/",
58
+ "io-package.json",
59
+ "LICENSE",
60
+ "main.js"
61
+ ],
52
62
  "scripts": {
53
63
  "test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
54
- "test:package": "mocha test/package --exit",
55
- "test:unit": "mocha test/unit --exit",
56
- "test:integration": "mocha test/integration --exit",
57
- "test": "npm run test:js && npm run test:package",
58
- "check": "tsc --noEmit -p tsconfig.check.json",
59
- "lint": "eslint"
64
+ "test:package": "mocha test/package --exit",
65
+ "test:unit": "mocha test/unit --exit",
66
+ "test:integration": "mocha test/integration --exit",
67
+ "test": "npm run test:js && npm run test:package",
68
+ "check": "tsc --noEmit -p tsconfig.check.json",
69
+ "lint": "eslint",
70
+ "release": "release-script"
60
71
  },
61
72
  "bugs": {
62
73
  "url": "https://github.com/nobl/ioBroker.senec/issues"
package/admin/admin.d.ts DELETED
@@ -1,93 +0,0 @@
1
- declare let systemDictionary: Record<string, Record<string, string>>;
2
-
3
- declare let load: (settings: Record<string, unknown>, onChange: (hasChanges: boolean) => void) => void;
4
- declare let save: (callback: (settings: Record<string, unknown>) => void) => void;
5
-
6
- // make load and save exist on the window object
7
- interface Window {
8
- load: typeof load;
9
- save: typeof save;
10
- }
11
-
12
- declare const instance: number;
13
- declare const adapter: string;
14
- /** Translates text */
15
- declare function _(text: string): string;
16
- declare const socket: ioBrokerSocket;
17
- declare function sendTo(
18
- instance: any | null,
19
- command: string,
20
- message: any,
21
- callback: (result: SendToResult) => void | Promise<void>,
22
- ): void;
23
-
24
- interface SendToResult {
25
- error?: string | Error;
26
- result?: any;
27
- }
28
-
29
- // tslint:disable-next-line:class-name
30
- interface ioBrokerSocket {
31
- emit(
32
- command: 'subscribeObjects',
33
- pattern: string,
34
- callback?: (err?: string) => void | Promise<void>,
35
- ): void;
36
- emit(
37
- command: 'subscribeStates',
38
- pattern: string,
39
- callback?: (err?: string) => void | Promise<void>,
40
- ): void;
41
- emit(
42
- command: 'unsubscribeObjects',
43
- pattern: string,
44
- callback?: (err?: string) => void | Promise<void>,
45
- ): void;
46
- emit(
47
- command: 'unsubscribeStates',
48
- pattern: string,
49
- callback?: (err?: string) => void | Promise<void>,
50
- ): void;
51
-
52
- emit(
53
- event: 'getObjectView',
54
- view: 'system',
55
- type: 'device',
56
- options: ioBroker.GetObjectViewParams,
57
- callback: (
58
- err: string | undefined,
59
- result?: any,
60
- ) => void | Promise<void>,
61
- ): void;
62
- emit(
63
- event: 'getStates',
64
- callback: (
65
- err: string | undefined,
66
- result?: Record<string, any>,
67
- ) => void,
68
- ): void;
69
- emit(
70
- event: 'getState',
71
- id: string,
72
- callback: (err: string | undefined, result?: ioBroker.State) => void,
73
- ): void;
74
- emit(
75
- event: 'setState',
76
- id: string,
77
- state: unknown,
78
- callback: (err: string | undefined, result?: any) => void,
79
- ): void;
80
-
81
- on(event: 'objectChange', handler: ioBroker.ObjectChangeHandler): void;
82
- on(event: 'stateChange', handler: ioBroker.StateChangeHandler): void;
83
- removeEventHandler(
84
- event: 'objectChange',
85
- handler: ioBroker.ObjectChangeHandler,
86
- ): void;
87
- removeEventHandler(
88
- event: 'stateChange',
89
- handler: ioBroker.StateChangeHandler,
90
- ): void;
91
-
92
- // TODO: other events
93
- }