@iobroker/js-controller-adapter 7.0.2 → 7.0.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.
Files changed (36) hide show
  1. package/build/cjs/index.js +2 -1
  2. package/build/cjs/index.js.map +2 -2
  3. package/build/cjs/lib/_Types.d.ts +0 -2
  4. package/build/cjs/lib/adapter/adapter.d.ts +3 -6
  5. package/build/cjs/lib/adapter/adapter.js +1537 -14
  6. package/build/cjs/lib/adapter/adapter.js.map +3 -3
  7. package/build/cjs/lib/adapter/constants.js +17 -0
  8. package/build/cjs/lib/adapter/constants.js.map +1 -1
  9. package/build/cjs/lib/adapter/log.d.ts +0 -1
  10. package/build/cjs/lib/adapter/log.js +6 -0
  11. package/build/cjs/lib/adapter/log.js.map +1 -1
  12. package/build/cjs/lib/adapter/userInterfaceMessagingController.d.ts +0 -2
  13. package/build/cjs/lib/adapter/userInterfaceMessagingController.js +41 -0
  14. package/build/cjs/lib/adapter/userInterfaceMessagingController.js.map +1 -1
  15. package/build/cjs/lib/adapter/utils.js +4 -0
  16. package/build/cjs/lib/adapter/utils.js.map +1 -1
  17. package/build/cjs/lib/adapter/validator.d.ts +0 -2
  18. package/build/cjs/lib/adapter/validator.js +95 -0
  19. package/build/cjs/lib/adapter/validator.js.map +1 -1
  20. package/build/esm/index.d.ts.map +1 -1
  21. package/build/esm/index.js +1 -0
  22. package/build/esm/index.js.map +1 -1
  23. package/build/esm/lib/_Types.d.ts +0 -2
  24. package/build/esm/lib/_Types.d.ts.map +1 -1
  25. package/build/esm/lib/adapter/adapter.d.ts +3 -6
  26. package/build/esm/lib/adapter/adapter.d.ts.map +1 -1
  27. package/build/esm/lib/adapter/adapter.js +4 -4
  28. package/build/esm/lib/adapter/adapter.js.map +1 -1
  29. package/build/esm/lib/adapter/log.d.ts +0 -1
  30. package/build/esm/lib/adapter/log.d.ts.map +1 -1
  31. package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts +0 -2
  32. package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts.map +1 -1
  33. package/build/esm/lib/adapter/validator.d.ts +0 -2
  34. package/build/esm/lib/adapter/validator.d.ts.map +1 -1
  35. package/build/tsconfig.build.tsbuildinfo +1 -1
  36. package/package.json +10 -10
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  return to;
19
19
  };
20
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
25
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
26
  mod
23
27
  ));
@@ -28,6 +32,7 @@ __export(adapter_exports, {
28
32
  AdapterClass: () => AdapterClass
29
33
  });
30
34
  module.exports = __toCommonJS(adapter_exports);
35
+ var __import_meta_url = typeof document === "undefined" ? new (require("url".replace("", ""))).URL("file:" + __filename).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
31
36
  var import_node_net = __toESM(require("node:net"), 1);
32
37
  var import_fs_extra = __toESM(require("fs-extra"), 1);
33
38
  var import_node_os = __toESM(require("node:os"), 1);
@@ -49,20 +54,26 @@ var import_constants = require("../../lib/adapter/constants.js");
49
54
  var import_userInterfaceMessagingController = require("../../lib/adapter/userInterfaceMessagingController.js");
50
55
  var import_constants2 = require("@iobroker/js-controller-common-db/constants");
51
56
  var url = __toESM(require("node:url"), 1);
52
- const import_meta = {};
53
57
  const controllerVersion = import_package.default.version;
54
58
  const { FORBIDDEN_CHARS } = import_js_controller_common.tools;
55
- const thisDir = url.fileURLToPath(new URL(".", import_meta.url || `file://${__filename}`));
59
+ const thisDir = url.fileURLToPath(new URL(".", __import_meta_url || `file://${__filename}`));
56
60
  import_js_controller_common.tools.ensureDNSOrder();
57
61
  class AdapterClass extends import_node_events.EventEmitter {
62
+ /** Cache of all deprecations which have already been transmitted */
58
63
  reportedDeprecations = /* @__PURE__ */ new Set();
64
+ /** Instance to access states DB */
59
65
  #states;
66
+ /** Instance to access objects DB */
60
67
  #objects;
68
+ /** States DB constructor */
61
69
  States;
70
+ /** Objects DB constructor */
62
71
  Objects;
72
+ /** Contents of iobroker.json */
63
73
  _config;
64
74
  _options;
65
75
  startedInCompactMode;
76
+ /** List of instances which want our logs */
66
77
  logList = /* @__PURE__ */ new Set();
67
78
  aliases = /* @__PURE__ */ new Map();
68
79
  aliasPatterns = /* @__PURE__ */ new Set();
@@ -70,8 +81,17 @@ class AdapterClass extends import_node_events.EventEmitter {
70
81
  eventLoopLags = [];
71
82
  overwriteLogLevel = false;
72
83
  adapterReady = false;
84
+ /** Callbacks from sendTo */
73
85
  messageCallbacks = /* @__PURE__ */ new Map();
86
+ /**
87
+ * Contains a live cache of the adapter's states.
88
+ * NOTE: This is only defined if the adapter was initialized with the option states: true.
89
+ */
74
90
  oStates;
91
+ /**
92
+ * Contains a live cache of the adapter's objects.
93
+ * NOTE: This is only defined if the adapter was initialized with the option objects: true.
94
+ */
75
95
  oObjects;
76
96
  _stopInProgress = false;
77
97
  _callbackId = 1;
@@ -79,6 +99,7 @@ class AdapterClass extends import_node_events.EventEmitter {
79
99
  _timers = /* @__PURE__ */ new Set();
80
100
  _intervals = /* @__PURE__ */ new Set();
81
101
  _delays = /* @__PURE__ */ new Set();
102
+ /** For ease of use the log property is always defined, however it is only available after `ready` has been called. */
82
103
  log;
83
104
  performStrictObjectChecks;
84
105
  _logger;
@@ -88,13 +109,20 @@ class AdapterClass extends import_node_events.EventEmitter {
88
109
  namespace;
89
110
  name;
90
111
  _systemSecret;
112
+ /** Whether the adapter has already terminated */
91
113
  terminated = false;
114
+ /** The cache of usernames */
92
115
  usernames = {};
116
+ /** A RegExp to test for forbidden chars in object IDs */
93
117
  FORBIDDEN_CHARS = FORBIDDEN_CHARS;
94
118
  inputCount = 0;
95
119
  outputCount = 0;
120
+ /** The cache of users */
96
121
  users = {};
122
+ // todo
123
+ /** The cache of user groups */
97
124
  groups = {};
125
+ /** An array of instances, that support auto subscribe */
98
126
  autoSubscribe = [];
99
127
  defaultHistory = null;
100
128
  pluginHandler;
@@ -102,19 +130,29 @@ class AdapterClass extends import_node_events.EventEmitter {
102
130
  getPortRunning = null;
103
131
  _namespaceRegExp;
104
132
  instance;
133
+ // @ts-expect-error decide how to handle it
105
134
  _utils;
135
+ /** contents of io-package.json */
106
136
  adapterConfig;
107
137
  connected;
108
138
  adapterDir;
139
+ /** contents of package.json */
109
140
  pack;
141
+ /** contents of io-package.json */
110
142
  ioPack;
111
143
  _initializeTimeout;
112
144
  inited;
145
+ /** contents of iobroker.json if required via AdapterOptions */
113
146
  systemConfig;
147
+ /** the configured date format of system.config, only available if requested via AdapterOptions `useFormatDate` */
114
148
  dateFormat;
149
+ /** if float comma instead of dot is used, only available if requested via AdapterOptions `useFormatDate` */
115
150
  isFloatComma;
151
+ /** configured language of system.config, only available if requested via AdapterOptions `useFormatDate` */
116
152
  language;
153
+ /** longitude configured in system.config, only available if requested via AdapterOptions `useFormatDate`*/
117
154
  longitude;
155
+ /** latitude configured in system.config, only available if requested via AdapterOptions `useFormatDate`*/
118
156
  latitude;
119
157
  _defaultObjs;
120
158
  _aliasObjectsSubscribed;
@@ -122,19 +160,32 @@ class AdapterClass extends import_node_events.EventEmitter {
122
160
  host;
123
161
  common;
124
162
  mboxSubscribed;
163
+ /** Stop the adapter */
125
164
  stop;
126
165
  version;
166
+ /** Stop the adapter only defined in compact, not for external usage */
127
167
  kill;
128
168
  processLog;
169
+ /**
170
+ * Start or stop subscribing to log messages
171
+ * The method is only available if logTransporter is active via io-pack or adapter options
172
+ * Note, that stopping will stop after 10 seconds, not immediately
173
+ *
174
+ * @param isActive - if log subscription should be activated or deactivated
175
+ * @param options - options passed to setState e.g. user permissions
176
+ */
129
177
  requireLog;
130
178
  logOffTimer;
131
179
  logRequired;
132
180
  patterns;
133
181
  statesConnectedTime;
182
+ /** Constants for frequent use in adapters */
134
183
  constants = {
135
184
  STATE_QUALITY: import_constants.STATE_QUALITY
136
185
  };
186
+ /** Features supported by the running instance */
137
187
  SUPPORTED_FEATURES = (0, import_utils.getSupportedFeatures)();
188
+ /** Controller for messaging related functionality */
138
189
  uiMessagingController;
139
190
  constructor(options) {
140
191
  super();
@@ -327,9 +378,20 @@ class AdapterClass extends import_node_events.EventEmitter {
327
378
  this.setExecutableCapabilities = import_js_controller_common.tools.setExecutableCapabilities;
328
379
  this._init();
329
380
  }
381
+ /**
382
+ * Get the adapter scoped package identifier of a node module
383
+ *
384
+ * @param moduleName name of the node module
385
+ */
330
386
  getAdapterScopedPackageIdentifier(moduleName) {
331
387
  return (0, import_utils.getAdapterScopedPackageIdentifier)({ moduleName, namespace: this.namespace });
332
388
  }
389
+ /**
390
+ * Install specified npm module
391
+ *
392
+ * @param moduleNameOrUrl name of the node module or GitHub url which can be passed to `npm install`
393
+ * @param options version information
394
+ */
333
395
  installNodeModule(moduleNameOrUrl, options) {
334
396
  import_validator.Validator.assertString(moduleNameOrUrl, "moduleNameOrUrl");
335
397
  import_validator.Validator.assertObject(options, "options");
@@ -346,19 +408,39 @@ class AdapterClass extends import_node_events.EventEmitter {
346
408
  const packageIdentifier = isUrl ? moduleNameOrUrl : `npm:${moduleName}@${version}`;
347
409
  return import_js_controller_common.tools.installNodeModule(`${internalModuleName}@${packageIdentifier}`);
348
410
  }
411
+ /**
412
+ * List all additional installed node modules from this adapter
413
+ */
349
414
  listInstalledNodeModules() {
350
415
  return (0, import_utils.listInstalledNodeModules)(this.namespace);
351
416
  }
417
+ /**
418
+ * Uninstall specified npm module
419
+ *
420
+ * @param moduleName name of the node module
421
+ */
352
422
  uninstallNodeModule(moduleName) {
353
423
  import_validator.Validator.assertString(moduleName, "moduleName");
354
424
  const internalModuleName = (0, import_utils.getAdapterScopedPackageIdentifier)({ moduleName, namespace: this.namespace });
355
425
  return import_js_controller_common.tools.uninstallNodeModule(internalModuleName);
356
426
  }
427
+ /**
428
+ * Import a node module which has been installed via `installNodeModule`
429
+ *
430
+ * @param moduleName name of the node module
431
+ * @returns the required node module
432
+ */
357
433
  importNodeModule(moduleName) {
358
434
  import_validator.Validator.assertString(moduleName, "moduleName");
359
435
  const internalModuleName = (0, import_utils.getAdapterScopedPackageIdentifier)({ moduleName, namespace: this.namespace });
360
436
  return import(internalModuleName);
361
437
  }
438
+ /**
439
+ * Decrypt the password/value with given key
440
+ *
441
+ * @param secretVal to use for decrypt (or value if only one parameter is given)
442
+ * @param value value to decrypt (if secret is provided)
443
+ */
362
444
  decrypt(secretVal, value) {
363
445
  if (value === void 0) {
364
446
  value = secretVal;
@@ -368,6 +450,12 @@ class AdapterClass extends import_node_events.EventEmitter {
368
450
  import_validator.Validator.assertString(value, "value");
369
451
  return import_js_controller_common.tools.decrypt(secretVal, value);
370
452
  }
453
+ /**
454
+ * Encrypt the password/value with given key
455
+ *
456
+ * @param secretVal to use for encrypting (or value if only one parameter is given)
457
+ * @param [value] value to encrypt (if secret is provided)
458
+ */
371
459
  encrypt(secretVal, value) {
372
460
  if (value === void 0) {
373
461
  value = secretVal;
@@ -377,11 +465,13 @@ class AdapterClass extends import_node_events.EventEmitter {
377
465
  import_validator.Validator.assertString(value, "value");
378
466
  return import_js_controller_common.tools.encrypt(secretVal, value);
379
467
  }
468
+ // unknown guard implementation
380
469
  getSession(id, callback) {
381
470
  import_validator.Validator.assertString(id, "id");
382
471
  import_validator.Validator.assertCallback(callback, "callback");
383
472
  return this._getSession({ id, callback });
384
473
  }
474
+ // actual implementation
385
475
  _getSession(options) {
386
476
  if (!this.#states) {
387
477
  this._logger.info(`${this.namespaceLog} getSession not processed because States database not connected`);
@@ -389,6 +479,7 @@ class AdapterClass extends import_node_events.EventEmitter {
389
479
  }
390
480
  this.#states.getSession(options.id, options.callback);
391
481
  }
482
+ // unknown implementation guards
392
483
  setSession(id, ttl, data, callback) {
393
484
  import_validator.Validator.assertString(id, "id");
394
485
  import_validator.Validator.assertOptionalCallback(callback, "callback");
@@ -396,6 +487,7 @@ class AdapterClass extends import_node_events.EventEmitter {
396
487
  import_validator.Validator.assertObject(data, "data");
397
488
  return this._setSession({ id, ttl, data, callback });
398
489
  }
490
+ // actual implementation
399
491
  _setSession(options) {
400
492
  if (!this.#states) {
401
493
  this._logger.info(`${this.namespaceLog} setSession not processed because States database not connected`);
@@ -424,6 +516,14 @@ class AdapterClass extends import_node_events.EventEmitter {
424
516
  return [];
425
517
  }
426
518
  }
519
+ /**
520
+ * stops the execution of adapter, but not disables it.
521
+ *
522
+ * Sometimes, the adapter must be stopped if some libraries are missing.
523
+ *
524
+ * @param reason optional termination description
525
+ * @param exitCode optional exit code
526
+ */
427
527
  terminate(reason, exitCode) {
428
528
  if (this.terminated) {
429
529
  return;
@@ -480,6 +580,23 @@ class AdapterClass extends import_node_events.EventEmitter {
480
580
  }
481
581
  }, 500);
482
582
  }
583
+ /**
584
+ * Helper function to find next free port
585
+ *
586
+ * Looks for first free TCP port starting with given one:
587
+ * ```js
588
+ * adapter.getPort(8081, function (port) {
589
+ * adapter.log.debug('Following port is free: ' + port);
590
+ * });
591
+ * ```
592
+ *
593
+ * @param port port number to start the search for free port
594
+ * @param [host] optional hostname for the port search
595
+ * @param callback return result
596
+ * ```js
597
+ * function (port) {}
598
+ * ```
599
+ */
483
600
  getPort(port, host, callback) {
484
601
  if (!port) {
485
602
  throw new Error("adapterGetPort: no port");
@@ -519,12 +636,38 @@ class AdapterClass extends import_node_events.EventEmitter {
519
636
  setImmediate(() => this.getPort(options.port + 1, options.host, options.callback));
520
637
  }
521
638
  }
639
+ /**
640
+ * Method to check for available Features for adapter development
641
+ *
642
+ * Use it like ...
643
+ * ```js
644
+ * if (adapter.supportsFeature && adapter.supportsFeature('ALIAS')) {
645
+ * ...
646
+ * }
647
+ * ```
648
+
649
+ * @param featureName the name of the feature to check
650
+ * @returns true/false if the feature is in the list of supported features
651
+ */
522
652
  supportsFeature(featureName) {
523
653
  if (typeof featureName === "string") {
524
654
  return this.SUPPORTED_FEATURES.includes(featureName);
525
655
  }
526
656
  return false;
527
657
  }
658
+ /**
659
+ * validates user and password
660
+ *
661
+ * @param user user name as text
662
+ * @param pw password as text
663
+ * @param [options] optional user context
664
+ * @param callback return result
665
+ * ```js
666
+ * function (result) {
667
+ * if (result) adapter.log.debug('User is valid');
668
+ * }
669
+ * ```
670
+ */
528
671
  checkPassword(user, pw, options, callback) {
529
672
  if (typeof options === "function") {
530
673
  callback = options;
@@ -569,6 +712,9 @@ class AdapterClass extends import_node_events.EventEmitter {
569
712
  });
570
713
  });
571
714
  }
715
+ /**
716
+ * This method update the cached values in `this.usernames`
717
+ */
572
718
  async _updateUsernameCache() {
573
719
  try {
574
720
  const obj = await this.getObjectListAsync({ startkey: "system.user.", endkey: "system.user.\u9999" });
@@ -584,6 +730,11 @@ class AdapterClass extends import_node_events.EventEmitter {
584
730
  throw new Error(`Could not update user cache: ${e.message}`);
585
731
  }
586
732
  }
733
+ /**
734
+ * Return ID of given username
735
+ *
736
+ * @param username - name of the user
737
+ */
587
738
  getUserID(username) {
588
739
  import_validator.Validator.assertString(username, "username");
589
740
  return this._getUserID({ username });
@@ -602,6 +753,19 @@ class AdapterClass extends import_node_events.EventEmitter {
602
753
  }
603
754
  return this.usernames[options.username].id;
604
755
  }
756
+ /**
757
+ * sets the user's password
758
+ *
759
+ * @param user user name as text
760
+ * @param pw password as text
761
+ * @param [options] optional user context
762
+ * @param [callback] return result
763
+ * ```js
764
+ * function (err) {
765
+ * if (err) adapter.log.error('Cannot set password: ' + err);
766
+ * }
767
+ * ```
768
+ */
605
769
  setPassword(user, pw, options, callback) {
606
770
  if (typeof options === "function") {
607
771
  callback = options;
@@ -660,6 +824,21 @@ class AdapterClass extends import_node_events.EventEmitter {
660
824
  }
661
825
  });
662
826
  }
827
+ /**
828
+ * returns if user exists and is in the group
829
+ *
830
+ * This function used mostly internally and the adapter developer do not require it.
831
+ *
832
+ * @param user user name as text
833
+ * @param group group name
834
+ * @param [options] optional user context
835
+ * @param callback return result
836
+ * ```js
837
+ * function (result) {
838
+ * if (result) adapter.log.debug('User exists and in the group');
839
+ * }
840
+ * ```
841
+ */
663
842
  checkGroup(user, group, options, callback) {
664
843
  user = user || "";
665
844
  if (typeof options === "function") {
@@ -709,6 +888,99 @@ class AdapterClass extends import_node_events.EventEmitter {
709
888
  });
710
889
  });
711
890
  }
891
+ /**
892
+ * get the user permissions
893
+ *
894
+ * This function used mostly internally and the adapter developer do not require it.
895
+ * The function reads permissions of user's groups (it can be more than one) and merge permissions together
896
+ *
897
+ * @param user user name as text
898
+ * @param commandsPermissions object that describes the access rights like
899
+ * ```js
900
+ * // static information
901
+ * var commandsPermissions = {
902
+ * getObject: {type: 'object', operation: 'read'},
903
+ * getObjects: {type: 'object', operation: 'list'},
904
+ * getObjectView: {type: 'object', operation: 'list'},
905
+ * setObject: {type: 'object', operation: 'write'},
906
+ * subscribeObjects: {type: 'object', operation: 'read'},
907
+ * unsubscribeObjects: {type: 'object', operation: 'read'},
908
+ * subscribeFiles: {type: 'object', operation: 'read'},
909
+ * unsubscribeFiles: {type: 'object', operation: 'read'},
910
+ *
911
+ * getStates: {type: 'state', operation: 'list'},
912
+ * getState: {type: 'state', operation: 'read'},
913
+ * setState: {type: 'state', operation: 'write'},
914
+ * getStateHistory: {type: 'state', operation: 'read'},
915
+ * subscribe: {type: 'state', operation: 'read'},
916
+ * unsubscribe: {type: 'state', operation: 'read'},
917
+ * getVersion: {type: '', operation: ''},
918
+ *
919
+ * httpGet: {type: 'other', operation: 'http'},
920
+ * sendTo: {type: 'other', operation: 'sendto'},
921
+ * sendToHost: {type: 'other', operation: 'sendto'},
922
+ *
923
+ * readFile: {type: 'file', operation: 'read'},
924
+ * readFile64: {type: 'file', operation: 'read'},
925
+ * writeFile: {type: 'file', operation: 'write'},
926
+ * writeFile64: {type: 'file', operation: 'write'},
927
+ * unlink: {type: 'file', operation: 'delete'},
928
+ * rename: {type: 'file', operation: 'write'},
929
+ * mkdir: {type: 'file', operation: 'write'},
930
+ * readDir: {type: 'file', operation: 'list'},
931
+ * chmodFile: {type: 'file', operation: 'write'},
932
+ * chownFile: {type: 'file', operation: 'write'},
933
+ *
934
+ * authEnabled: {type: '', operation: ''},
935
+ * disconnect: {type: '', operation: ''},
936
+ * listPermissions: {type: '', operation: ''},
937
+ * getUserPermissions: {type: 'object', operation: 'read'}
938
+ * };
939
+ * ```
940
+ * @param [options] optional user context
941
+ * @param [callback] return result
942
+ * ```js
943
+ * function (acl) {
944
+ * // Access control object for admin looks like:
945
+ * // {
946
+ * // file: {
947
+ * // read: true,
948
+ * // write: true,
949
+ * // 'delete': true,
950
+ * // create: true,
951
+ * // list: true
952
+ * // },
953
+ * // object: {
954
+ * // read: true,
955
+ * // write: true,
956
+ * // 'delete': true,
957
+ * // list: true
958
+ * // },
959
+ * // state: {
960
+ * // read: true,
961
+ * // write: true,
962
+ * // 'delete': true,
963
+ * // create: true,
964
+ * // list: true
965
+ * // },
966
+ * // user: 'admin',
967
+ * // users: {
968
+ * // read: true,
969
+ * // write: true,
970
+ * // create: true,
971
+ * // 'delete': true,
972
+ * // list: true
973
+ * // },
974
+ * // other: {
975
+ * // execute: true,
976
+ * // http: true,
977
+ * // sendto: true
978
+ * // },
979
+ * // groups: ['administrator'] // can be more than one
980
+ * // }
981
+ * }
982
+ * ```
983
+ */
712
984
  calculatePermissions(user, commandsPermissions, options, callback) {
713
985
  user = user || "";
714
986
  if (typeof options === "function") {
@@ -773,6 +1045,7 @@ class AdapterClass extends import_node_events.EventEmitter {
773
1045
  create: true,
774
1046
  list: true
775
1047
  },
1048
+ // @ts-expect-error create is missing
776
1049
  object: {
777
1050
  read: true,
778
1051
  write: true,
@@ -830,6 +1103,11 @@ class AdapterClass extends import_node_events.EventEmitter {
830
1103
  return import_js_controller_common.tools.maybeCallback(options.callback, acl);
831
1104
  });
832
1105
  }
1106
+ /**
1107
+ * Stop an instance gracefully
1108
+ *
1109
+ * @param options information about the stoppage
1110
+ */
833
1111
  async _stop(options = {}) {
834
1112
  const { isPause, isScheduled, reason } = options;
835
1113
  let { exitCode, updateAliveState } = options;
@@ -911,6 +1189,12 @@ class AdapterClass extends import_node_events.EventEmitter {
911
1189
  }, this.common?.stopTimeout || 500);
912
1190
  }
913
1191
  }
1192
+ /**
1193
+ * Reads the file certificate from a given path and adds a file watcher to restart adapter on cert changes
1194
+ * if a cert is passed it is returned as it is
1195
+ *
1196
+ * @param cert cert or path to cert
1197
+ */
914
1198
  _readFileCertificate(cert) {
915
1199
  if (typeof cert === "string") {
916
1200
  try {
@@ -928,6 +1212,25 @@ class AdapterClass extends import_node_events.EventEmitter {
928
1212
  }
929
1213
  return cert;
930
1214
  }
1215
+ /**
1216
+ * returns SSL certificates by name
1217
+ *
1218
+ * This function returns SSL certificates (private key, public cert and chained certificate).
1219
+ * Names are defined in the system's configuration in admin, e.g. "defaultPrivate", "defaultPublic".
1220
+ * The result can be directly used for creation of https server.
1221
+ *
1222
+ * @param [publicName] public certificate name
1223
+ * @param [privateName] private certificate name
1224
+ * @param [chainedName] optional chained certificate name
1225
+ * @param callback return result
1226
+ * ```js
1227
+ * function (err, certs, letsEncrypt) {
1228
+ * adapter.log.debug('private key: ' + certs.key);
1229
+ * adapter.log.debug('public cert: ' + certs.cert);
1230
+ * adapter.log.debug('chained cert: ' + certs.ca);
1231
+ * }
1232
+ * ```
1233
+ */
931
1234
  getCertificates(publicName, privateName, chainedName, callback) {
932
1235
  if (typeof publicName === "function") {
933
1236
  callback = publicName;
@@ -995,6 +1298,10 @@ class AdapterClass extends import_node_events.EventEmitter {
995
1298
  ca
996
1299
  }, obj.native.letsEncrypt);
997
1300
  }
1301
+ /**
1302
+ * Restarts an instance of the adapter.
1303
+ *
1304
+ */
998
1305
  restart() {
999
1306
  if (this.stop) {
1000
1307
  this._logger.warn(`${this.namespaceLog} Restart initiated`);
@@ -1003,6 +1310,16 @@ class AdapterClass extends import_node_events.EventEmitter {
1003
1310
  this._logger.warn(`${this.namespaceLog} Cannot initiate restart, because this.stop is not defined`);
1004
1311
  }
1005
1312
  }
1313
+ /**
1314
+ * Updates the adapter config with new values. Only a subset of the configuration has to be provided,
1315
+ * since merging with the existing config is done automatically, e.g., like this:
1316
+ *
1317
+ * `adapter.updateConfig({prop1: "newValue1"})`
1318
+ *
1319
+ * After updating the configuration, the adapter is automatically restarted.
1320
+ *
1321
+ * @param newConfig The new config values to be stored
1322
+ */
1006
1323
  updateConfig(newConfig) {
1007
1324
  import_validator.Validator.assertObject(newConfig, "newConfig");
1008
1325
  return this._updateConfig({ newConfig });
@@ -1032,6 +1349,10 @@ class AdapterClass extends import_node_events.EventEmitter {
1032
1349
  obj.native = mergedConfig;
1033
1350
  return this.setForeignObjectAsync(configObjId, obj);
1034
1351
  }
1352
+ /**
1353
+ * Disables and stops the adapter instance.
1354
+ *
1355
+ */
1035
1356
  async disable() {
1036
1357
  const configObjId = `system.adapter.${this.namespace}`;
1037
1358
  let obj;
@@ -1046,6 +1367,14 @@ class AdapterClass extends import_node_events.EventEmitter {
1046
1367
  obj.common.enabled = false;
1047
1368
  return this.setForeignObjectAsync(configObjId, obj);
1048
1369
  }
1370
+ /**
1371
+ * Reads the encrypted parameter from config.
1372
+ *
1373
+ * It returns promise if no callback is provided.
1374
+ *
1375
+ * @param attribute - attribute name in native configuration part
1376
+ * @param [callback] - optional callback
1377
+ */
1049
1378
  getEncryptedConfig(attribute, callback) {
1050
1379
  import_validator.Validator.assertString(attribute, "attribute");
1051
1380
  import_validator.Validator.assertOptionalCallback(callback, "callback");
@@ -1060,6 +1389,9 @@ class AdapterClass extends import_node_events.EventEmitter {
1060
1389
  }
1061
1390
  return import_js_controller_common.tools.maybeCallbackWithError(callback, `Attribute "${attribute}" not found`);
1062
1391
  }
1392
+ /**
1393
+ * Get the system secret, after retrieved once it will be read from the cache
1394
+ */
1063
1395
  async getSystemSecret() {
1064
1396
  if (this._systemSecret !== void 0) {
1065
1397
  return this._systemSecret;
@@ -1074,6 +1406,16 @@ class AdapterClass extends import_node_events.EventEmitter {
1074
1406
  this._systemSecret = this._systemSecret || import_constants.DEFAULT_SECRET;
1075
1407
  return this._systemSecret;
1076
1408
  }
1409
+ /**
1410
+ * Same as setTimeout,
1411
+ * but it clears the running timers during the unloading process
1412
+ * does not work after unload has been called
1413
+ *
1414
+ * @param cb - timer callback
1415
+ * @param timeout - timeout in milliseconds
1416
+ * @param args - as many arguments as needed, which will be passed to setTimeout
1417
+ * @returns timer id
1418
+ */
1077
1419
  setTimeout(cb, timeout, ...args) {
1078
1420
  if (typeof cb !== "function") {
1079
1421
  this._logger.warn(`${this.namespaceLog} setTimeout expected callback to be of type "function", but got "${typeof cb}"`);
@@ -1092,6 +1434,12 @@ class AdapterClass extends import_node_events.EventEmitter {
1092
1434
  this._timers.add(timer);
1093
1435
  return timer;
1094
1436
  }
1437
+ /**
1438
+ * Same as clearTimeout
1439
+ * but it checks the running timers on unload
1440
+ *
1441
+ * @param timer - the timer object
1442
+ */
1095
1443
  clearTimeout(timer) {
1096
1444
  if (timer === void 0) {
1097
1445
  return;
@@ -1099,6 +1447,13 @@ class AdapterClass extends import_node_events.EventEmitter {
1099
1447
  clearTimeout(timer);
1100
1448
  this._timers.delete(timer);
1101
1449
  }
1450
+ /**
1451
+ * delays the fulfillment of the promise the amount of time.
1452
+ * it will not fulfill during and after adapter shutdown
1453
+ *
1454
+ * @param timeout - timeout in milliseconds
1455
+ * @returns promise when timeout is over
1456
+ */
1102
1457
  delay(timeout) {
1103
1458
  if (this._stopInProgress) {
1104
1459
  this._logger.warn(`${this.namespaceLog} delay called, but adapter is shutting down`);
@@ -1114,6 +1469,16 @@ class AdapterClass extends import_node_events.EventEmitter {
1114
1469
  this._delays.add(timer);
1115
1470
  });
1116
1471
  }
1472
+ /**
1473
+ * Same as setInterval
1474
+ * but it clears the running intervals during the unload process
1475
+ * does not work after unload has been called
1476
+ *
1477
+ * @param cb - interval callback
1478
+ * @param timeout - interval in milliseconds
1479
+ * @param args - as many arguments as needed, which will be passed to setTimeout
1480
+ * @returns interval interval object
1481
+ */
1117
1482
  setInterval(cb, timeout, ...args) {
1118
1483
  if (typeof cb !== "function") {
1119
1484
  this._logger.error(`${this.namespaceLog} setInterval expected callback to be of type "function", but got "${typeof cb}"`);
@@ -1129,6 +1494,12 @@ class AdapterClass extends import_node_events.EventEmitter {
1129
1494
  this._intervals.add(id);
1130
1495
  return id;
1131
1496
  }
1497
+ /**
1498
+ * Same as clearInterval
1499
+ * but it checks the running intervals on unload
1500
+ *
1501
+ * @param interval - interval object
1502
+ */
1132
1503
  clearInterval(interval) {
1133
1504
  if (interval === void 0) {
1134
1505
  return;
@@ -1136,6 +1507,36 @@ class AdapterClass extends import_node_events.EventEmitter {
1136
1507
  clearInterval(interval);
1137
1508
  this._intervals.delete(interval);
1138
1509
  }
1510
+ /**
1511
+ * Creates or overwrites an object in objectDB.
1512
+ *
1513
+ * This function can create or overwrite objects in objectDB for this adapter.
1514
+ * Only Ids that belong to this adapter can be modified. So the function automatically adds "adapter.X." to ID.
1515
+ * <b>common</b>, <b>native</b> and <b>type</b> attributes are mandatory, and it will be checked.
1516
+ * Additionally, type "state" requires <b>role</b>, <b>type</b> and <b>name</b>, e.g.:
1517
+ * ```js
1518
+ * {
1519
+ * common: {
1520
+ * name: 'object name',
1521
+ * type: 'number', // string, boolean, object, mixed, array
1522
+ * role: 'value' // see https://github.com/ioBroker/ioBroker/blob/master/doc/SCHEMA.md#state-commonrole
1523
+ * },
1524
+ * native: {},
1525
+ * type: 'state' // channel, device
1526
+ * }
1527
+ * ```
1528
+ *
1529
+ * @param id object ID, that must be overwritten or created.
1530
+ * @param obj new object
1531
+ * @param [options] optional user context
1532
+ * @param [callback] return result
1533
+ * ```js
1534
+ * function (err, obj) {
1535
+ * // obj is {id: id}
1536
+ * if (err) adapter.log.error('Cannot write object: ' + err);
1537
+ * }
1538
+ * ```
1539
+ */
1139
1540
  setObject(id, obj, options, callback) {
1140
1541
  if (typeof options === "function") {
1141
1542
  callback = options;
@@ -1213,6 +1614,14 @@ class AdapterClass extends import_node_events.EventEmitter {
1213
1614
  return import_js_controller_common.tools.maybeCallbackWithError(options.callback, "mandatory property type missing!");
1214
1615
  }
1215
1616
  }
1617
+ /**
1618
+ * Helper method for `set[Foreign]Object[NotExists]` that also sets the default value if one is configured
1619
+ *
1620
+ * @param id of the object
1621
+ * @param obj The object to set
1622
+ * @param options optional user context
1623
+ * @param callback optional callback
1624
+ */
1216
1625
  async _setObjectWithDefaultValue(id, obj, options, callback) {
1217
1626
  if (!this.#objects) {
1218
1627
  this._logger.info(`${this.namespaceLog} setObject not processed because Objects database not connected`);
@@ -1248,6 +1657,18 @@ class AdapterClass extends import_node_events.EventEmitter {
1248
1657
  return import_js_controller_common.tools.maybeCallbackWithError(callback, e);
1249
1658
  }
1250
1659
  }
1660
+ /**
1661
+ * Get all states, channels and devices of this adapter.
1662
+ *
1663
+ * @param callback return result
1664
+ * ```js
1665
+ * function (objects) {
1666
+ * for (var id in objects) {
1667
+ * adapter.log.debug(id);
1668
+ * }
1669
+ * }
1670
+ * ```
1671
+ */
1251
1672
  getAdapterObjects(callback) {
1252
1673
  import_validator.Validator.assertOptionalCallback(callback, "callback");
1253
1674
  return this._getAdapterObjects({ callback });
@@ -1299,6 +1720,62 @@ class AdapterClass extends import_node_events.EventEmitter {
1299
1720
  }
1300
1721
  return import_js_controller_common.tools.maybeCallback(options.callback, ret);
1301
1722
  }
1723
+ /**
1724
+ * Extend some object and create it if it does not exist
1725
+ *
1726
+ * You can change or extend some object. E.g. existing object is:
1727
+ * ```js
1728
+ * {
1729
+ * common: {
1730
+ * name: 'Adapter name',
1731
+ * desc: 'Description'
1732
+ * },
1733
+ * type: 'state',
1734
+ * native: {
1735
+ * unused: 'text'
1736
+ * }
1737
+ * }
1738
+ * ```
1739
+ *
1740
+ * If following object will be passed as argument
1741
+ *
1742
+ * ```js
1743
+ * {
1744
+ * common: {
1745
+ * desc: 'New description',
1746
+ * min: 0,
1747
+ * max: 100
1748
+ * },
1749
+ * native: {
1750
+ * unused: null
1751
+ * }
1752
+ * }
1753
+ * ```
1754
+ *
1755
+ * We will get as output:
1756
+ * ```js
1757
+ * {
1758
+ * common: {
1759
+ * desc: 'New description',
1760
+ * min: 0,
1761
+ * max: 100
1762
+ * },
1763
+ * type: 'state',
1764
+ * native: {}
1765
+ * }
1766
+ * ```
1767
+ *
1768
+ * @param id object ID, that must be extended
1769
+ * @param obj part that must be extended
1770
+ * @param options optional user context
1771
+ * @param callback return result
1772
+ * ```js
1773
+ * function (err, obj) {
1774
+ * if (err) adapter.log.error(err);
1775
+ * // obj is {"id": id}
1776
+ * }
1777
+ * ```
1778
+ */
1302
1779
  extendObject(id, obj, options, callback) {
1303
1780
  if (typeof options === "function") {
1304
1781
  callback = options;
@@ -1319,6 +1796,7 @@ class AdapterClass extends import_node_events.EventEmitter {
1319
1796
  }
1320
1797
  return this._extendObject({ id, obj, options, callback });
1321
1798
  }
1799
+ // TODO: the public return type needs to be defined correctly, probably needs to be discussed
1322
1800
  async _extendObject(options) {
1323
1801
  if (!this.#objects) {
1324
1802
  this._logger.info(`${this.namespaceLog} extendObject not processed because Objects database not connected`);
@@ -1428,6 +1906,22 @@ class AdapterClass extends import_node_events.EventEmitter {
1428
1906
  return import_js_controller_common.tools.maybeCallbackWithError(options.callback, e);
1429
1907
  }
1430
1908
  }
1909
+ /**
1910
+ * Same as {@link AdapterClass.setObject}, but for any object.
1911
+ *
1912
+ * ID must be specified as a full name with adapter namespace. E.g "hm-rpc.0.ABC98989.1.STATE"
1913
+ *
1914
+ * @param id object ID, that must be overwritten or created.
1915
+ * @param obj new object
1916
+ * @param options optional user context
1917
+ * @param callback return result
1918
+ * ```js
1919
+ * function (err, obj) {
1920
+ * // obj is {id: id}
1921
+ * if (err) adapter.log.error('Cannot write object: ' + err);
1922
+ * }
1923
+ * ```
1924
+ */
1431
1925
  setForeignObject(id, obj, options, callback) {
1432
1926
  if (typeof options === "function") {
1433
1927
  callback = options;
@@ -1479,6 +1973,22 @@ class AdapterClass extends import_node_events.EventEmitter {
1479
1973
  }
1480
1974
  this._setObjectWithDefaultValue(id, obj, options, callback);
1481
1975
  }
1976
+ /**
1977
+ * Same as {@link AdapterClass.extendObject}, but for any object.
1978
+ *
1979
+ * ID must be specified as a full name with adapter namespace. E.g "hm-rpc.0.ABC98989.1.STATE"
1980
+ *
1981
+ * @param id object ID, that must be extended
1982
+ * @param obj part that must be extended
1983
+ * @param options optional user context, or use attribute preserve e.g. `{preserve: {common: ['name']}}` to preserve common.name
1984
+ * @param callback return result
1985
+ * ```js
1986
+ * function (err, obj) {
1987
+ * // obj is {"id": id}
1988
+ * if (err) adapter.log.error(err);
1989
+ * }
1990
+ * ```
1991
+ */
1482
1992
  extendForeignObject(id, obj, options, callback) {
1483
1993
  if (typeof options === "function") {
1484
1994
  callback = options;
@@ -1596,6 +2106,12 @@ class AdapterClass extends import_node_events.EventEmitter {
1596
2106
  return import_js_controller_common.tools.maybeCallbackWithError(callback, e);
1597
2107
  }
1598
2108
  }
2109
+ /**
2110
+ * Checks if an object exists to the given id, id will be fixed first
2111
+ *
2112
+ * @param id id of the object
2113
+ * @param options optional user context
2114
+ */
1599
2115
  objectExists(id, options) {
1600
2116
  if (!this.#objects) {
1601
2117
  this._logger.info(`${this.namespaceLog} objectExists not processed because Objects database not connected`);
@@ -1609,6 +2125,12 @@ class AdapterClass extends import_node_events.EventEmitter {
1609
2125
  this._utils.validateId(id, false, null);
1610
2126
  return this.#objects.objectExists(id, options);
1611
2127
  }
2128
+ /**
2129
+ * Checks if an object exists to the given id
2130
+ *
2131
+ * @param id id of the object
2132
+ * @param options optional user context
2133
+ */
1612
2134
  foreignObjectExists(id, options) {
1613
2135
  if (!this.#objects) {
1614
2136
  this._logger.info(`${this.namespaceLog} foreignObjectExists not processed because Objects database not connected`);
@@ -1621,6 +2143,20 @@ class AdapterClass extends import_node_events.EventEmitter {
1621
2143
  this._utils.validateId(id, true, null);
1622
2144
  return this.#objects.objectExists(id, options);
1623
2145
  }
2146
+ /**
2147
+ * Get object of this instance.
2148
+ *
2149
+ * It is not required, that ID consists namespace. E.g. to get object of "adapterName.X.myObject", only "myObject" is required as ID.
2150
+ *
2151
+ * @param id exactly object ID (without namespace)
2152
+ * @param options optional user context
2153
+ * @param callback return result
2154
+ * ```js
2155
+ * function (err, obj) {
2156
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2157
+ * }
2158
+ * ```
2159
+ */
1624
2160
  getObject(id, options, callback) {
1625
2161
  if (typeof options === "function") {
1626
2162
  callback = options;
@@ -1642,6 +2178,32 @@ class AdapterClass extends import_node_events.EventEmitter {
1642
2178
  }
1643
2179
  this.#objects.getObject(this._utils.fixId(id), options, callback);
1644
2180
  }
2181
+ /**
2182
+ * Read object view from DB.
2183
+ *
2184
+ * It is required, that ID consists namespace in startkey and endkey. E.g. `{startkey: 'hm-rpc.' + adapter.instance + '.', endkey: 'hm-rpc.' + adapter.instance + '.\u9999'}`
2185
+ * to get all objects of the instance.
2186
+ *
2187
+ * @param design name of the design
2188
+ * @param search name of the view
2189
+ * @param params object containing startkey: first id to include in result; endkey: last id to include in result
2190
+ * @param options additional objects, e.g. for permissions
2191
+ * @param callback return result
2192
+ * ```js
2193
+ * function (err, doc) {
2194
+ * if (doc && doc.rows) {
2195
+ * for (var i = 0; i < doc.rows.length; i++) {
2196
+ * var id = doc.rows[i].id;
2197
+ * var obj = doc.rows[i].value;
2198
+ * adapter.log.info('Found ' + id + ': ' + JSON.stringify(obj));
2199
+ * }
2200
+ * if (!doc.rows.length) adapter.log.info('No objects found.');
2201
+ * } else {
2202
+ * adapter.log.info('No objects found: ' + err);
2203
+ * }
2204
+ * }
2205
+ * ```
2206
+ */
1645
2207
  getObjectView(design, search, params, options, callback) {
1646
2208
  if (typeof options === "function") {
1647
2209
  callback = options;
@@ -1699,6 +2261,30 @@ class AdapterClass extends import_node_events.EventEmitter {
1699
2261
  }
1700
2262
  return this.#objects.getObjectView(design, search, params, options, callback);
1701
2263
  }
2264
+ /**
2265
+ * Read object list from DB.
2266
+ *
2267
+ * It is required, that ID consists namespace in startkey and endkey. E.g. `{startkey: 'hm-rpc.' + adapter.instance + '.', endkey: 'hm-rpc.' + adapter.instance + '.\u9999'}`
2268
+ * to get all objects of the instance.
2269
+ *
2270
+ * @param params startkey and endkey information
2271
+ * @param options additional options, e.g. for permissions
2272
+ * @param callback optional callback
2273
+ * ```js
2274
+ * function (err, res) {
2275
+ * if (res && res.rows) {
2276
+ * for (var i = 0; i < res.rows.length; i++) {
2277
+ * var id = res.rows[i].id;
2278
+ * var obj = res.rows[i].value;
2279
+ * adapter.log.info('Found ' + id + ': ' + JSON.stringify(obj));
2280
+ * }
2281
+ * if (!res.rows.length) adapter.log.info('No objects found.');
2282
+ * } else {
2283
+ * adapter.log.info('No objects found: ' + err);
2284
+ * }
2285
+ * }
2286
+ * ```
2287
+ */
1702
2288
  getObjectList(params, options, callback) {
1703
2289
  if (typeof options === "function") {
1704
2290
  callback = options;
@@ -1715,6 +2301,34 @@ class AdapterClass extends import_node_events.EventEmitter {
1715
2301
  }
1716
2302
  this.#objects.getObjectList(params, options, callback);
1717
2303
  }
2304
+ /**
2305
+ * Get the enum tree.
2306
+ *
2307
+ * Get enums of specified tree or all enums if nothing specified as object with values.
2308
+ * If getEnum called with no enum specified, all enums will be returned:
2309
+ * ```js
2310
+ * adapter.getEnums(function (err, enums, requestEnum) {
2311
+ * // All enums
2312
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2313
+ * for (var e in enums) {
2314
+ * adapter.log.debug('Enum "' + e + '" has following members: ' + enums[e].common.members.join(', '));
2315
+ * }
2316
+ * });
2317
+ * ```
2318
+ *
2319
+ * @param _enum enum name, e.g. 'rooms', 'function' or '' (all enums)
2320
+ * @param options optional user context
2321
+ * @param callback return result
2322
+ * ```js
2323
+ * function (err, enums, requestEnum) {
2324
+ * // requestEnum is _enum
2325
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2326
+ * for (var e in enums) {
2327
+ * adapter.log.debug('Enum "' + e + '" has following members: ' + enums[e].common.members.join(', '));
2328
+ * }
2329
+ * }
2330
+ * ```
2331
+ */
1718
2332
  getEnum(_enum, options, callback) {
1719
2333
  if (typeof _enum === "function") {
1720
2334
  callback = _enum;
@@ -1758,6 +2372,48 @@ class AdapterClass extends import_node_events.EventEmitter {
1758
2372
  return import_js_controller_common.tools.maybeCallbackWithError(callback, err, result, _enum);
1759
2373
  });
1760
2374
  }
2375
+ /**
2376
+ * Read the members of given enums.
2377
+ *
2378
+ * Get enums of specified tree or all enums if nothing specified as object with values.
2379
+ *
2380
+ * @param _enumList enum name or names, e.g. ['rooms', 'function']
2381
+ * @param options optional user context
2382
+ * @param callback return result
2383
+ * ```js
2384
+ * function (err, enums) {
2385
+ * // requestEnum is _enum
2386
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2387
+ * // Result is like
2388
+ * // {
2389
+ * // "enum.rooms": {
2390
+ * // "enum.rooms.livingroom": {
2391
+ * // common: {
2392
+ * // members: ['ID1', 'ID2']
2393
+ * // }
2394
+ * // },
2395
+ * // "enum.rooms.sleepingroom": {
2396
+ * // common: {
2397
+ * // members: ['ID3', 'ID4']
2398
+ * // }
2399
+ * // }
2400
+ * // },
2401
+ * // "enum.functions": {
2402
+ * // "enum.rooms.light": {
2403
+ * // common: {
2404
+ * // members: ['ID1', 'ID6']
2405
+ * // }
2406
+ * // },
2407
+ * // "enum.rooms.weather": {
2408
+ * // common: {
2409
+ * // members: ['ID4', 'ID7']
2410
+ * // }
2411
+ * // }
2412
+ * // }
2413
+ * // }
2414
+ * }
2415
+ * ```
2416
+ */
1761
2417
  getEnums(_enumList, options, callback) {
1762
2418
  if (typeof _enumList === "function") {
1763
2419
  callback = _enumList;
@@ -1827,6 +2483,48 @@ class AdapterClass extends import_node_events.EventEmitter {
1827
2483
  });
1828
2484
  }
1829
2485
  }
2486
+ /**
2487
+ * Get objects by pattern, by specific type and resolve their enums.
2488
+ *
2489
+ * Get all objects in the system of specified type. E.g.:
2490
+ *
2491
+ * ```js
2492
+ * adapter.getForeignObjects('hm-rega.0.*', 'state', ['rooms', 'functions'], function (err, objs) {
2493
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2494
+ * // objs look like:
2495
+ * // {
2496
+ * // "hm-rega.0.ABC0000.1.STATE": {
2497
+ * // common: {...},
2498
+ * // native: {},
2499
+ * // type: 'state',
2500
+ * // enums: {
2501
+ * // 'enums.rooms.livingroom': 'Living room',
2502
+ * // 'enums.functions.light': 'Light'
2503
+ * // }
2504
+ * // },
2505
+ * // "hm-rega.0.ABC0000.2.STATE": {
2506
+ * // common: {...},
2507
+ * // native: {},
2508
+ * // type: 'state',
2509
+ * // enums: {
2510
+ * // 'enums.rooms.sleepingroom': 'Sleeping room',
2511
+ * // 'enums.functions.window': 'Windows'
2512
+ * // }
2513
+ * // }
2514
+ * }
2515
+ * ```
2516
+ *
2517
+ * @param pattern object ID/wildcards
2518
+ * @param type type of object: 'state', 'channel' or 'device'. Default - 'state'
2519
+ * @param enums object ID, that must be overwritten or created.
2520
+ * @param options optional user context
2521
+ * @param callback return result
2522
+ * ```js
2523
+ * function (err, obj) {
2524
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2525
+ * }
2526
+ * ```
2527
+ */
1830
2528
  getForeignObjects(pattern, type, enums, options, callback) {
1831
2529
  if (typeof options === "function") {
1832
2530
  callback = options;
@@ -1933,6 +2631,22 @@ class AdapterClass extends import_node_events.EventEmitter {
1933
2631
  }
1934
2632
  return import_js_controller_common.tools.maybeCallbackWithError(callback, null, list);
1935
2633
  }
2634
+ /**
2635
+ * Find any object by name or ID.
2636
+ *
2637
+ * Find object by the exact name or ID.
2638
+ *
2639
+ * @param id exactly object ID (without namespace)
2640
+ * @param type optional common.type of state: 'number', 'string', 'boolean', 'file', ...
2641
+ * @param options optional user context
2642
+ * @param callback return result
2643
+ * ```js
2644
+ * adapter.findForeignObject('Some name', function (err, id, name) {
2645
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2646
+ * adapter.log.debug('ID of object with name "' + name + '" is "' + id + '"');
2647
+ * }
2648
+ * ```
2649
+ */
1936
2650
  findForeignObject(id, type, options, callback) {
1937
2651
  if (typeof options === "function") {
1938
2652
  callback = options;
@@ -1960,6 +2674,20 @@ class AdapterClass extends import_node_events.EventEmitter {
1960
2674
  }
1961
2675
  this.#objects.findObject(id, type, options || {}, callback);
1962
2676
  }
2677
+ /**
2678
+ * Get any object.
2679
+ *
2680
+ * ID must be specified with namespace.
2681
+ *
2682
+ * @param id exactly object ID (with namespace)
2683
+ * @param options optional user context
2684
+ * @param callback return result
2685
+ * ```js
2686
+ * function (err, obj) {
2687
+ * if (err) adapter.log.error('Cannot get object: ' + err);
2688
+ * }
2689
+ * ```
2690
+ */
1963
2691
  getForeignObject(id, options, callback) {
1964
2692
  if (typeof options === "function") {
1965
2693
  callback = options;
@@ -1993,6 +2721,23 @@ class AdapterClass extends import_node_events.EventEmitter {
1993
2721
  return import_js_controller_common.tools.maybeCallbackWithError(options.callback, e);
1994
2722
  }
1995
2723
  }
2724
+ /**
2725
+ * Delete an object of this instance.
2726
+ *
2727
+ * It is not required to provide the adapter namespace, because it will automatically be added.
2728
+ * E.g. to delete "adapterName.X.myObject", only "myObject" is required as ID.
2729
+ *
2730
+ * The corresponding state will be deleted too if the object has type "state".
2731
+ *
2732
+ * @param id exactly object ID (without namespace)
2733
+ * @param options optional user context. E.g. recursive option could be true
2734
+ * @param callback return result
2735
+ * ```js
2736
+ * function (err) {
2737
+ * if (err) adapter.log.error('Cannot delete object: ' + err);
2738
+ * }
2739
+ * ```
2740
+ */
1996
2741
  delObject(id, options, callback) {
1997
2742
  import_validator.Validator.assertString(id, "id");
1998
2743
  id = this._utils.fixId(id);
@@ -2022,6 +2767,20 @@ class AdapterClass extends import_node_events.EventEmitter {
2022
2767
  setImmediate(() => this._deleteObjects(tasks, options, cb));
2023
2768
  });
2024
2769
  }
2770
+ /**
2771
+ * Delete any object.
2772
+ *
2773
+ * The full ID with namespace must be specified. The corresponding state will be deleted too if the object has type "state".
2774
+ *
2775
+ * @param id exactly object ID (with namespace)
2776
+ * @param options optional user context or `{ recursive: true }` to delete all underlying objects
2777
+ * @param callback return result
2778
+ * ```js
2779
+ * function (err) {
2780
+ * if (err) adapter.log.error('Cannot delete object: ' + err);
2781
+ * }
2782
+ * ```
2783
+ */
2025
2784
  delForeignObject(id, options, callback) {
2026
2785
  if (typeof options === "function") {
2027
2786
  callback = options;
@@ -2054,7 +2813,8 @@ class AdapterClass extends import_node_events.EventEmitter {
2054
2813
  const tasks = obj && (!obj.common || !obj.common.dontDelete) ? [{ id, state: obj.type === "state" }] : [];
2055
2814
  const selector = { startkey: `${id}.`, endkey: `${id}.\u9999` };
2056
2815
  this.#objects.getObjectList(selector, options, (err2, res) => {
2057
- res && res.rows.forEach((item) => !tasks.find((task) => task.id === item.id) && (!item.value || !item.value.common || !item.value.common.dontDelete) && tasks.push({ id: item.id, state: item.value && item.value.type === "state" }));
2816
+ res && res.rows.forEach((item) => !tasks.find((task) => task.id === item.id) && (!item.value || !item.value.common || !item.value.common.dontDelete) && // exclude objects with dontDelete flag
2817
+ tasks.push({ id: item.id, state: item.value && item.value.type === "state" }));
2058
2818
  this._deleteObjects(tasks, options, callback);
2059
2819
  });
2060
2820
  });
@@ -2087,6 +2847,18 @@ class AdapterClass extends import_node_events.EventEmitter {
2087
2847
  });
2088
2848
  }
2089
2849
  }
2850
+ /**
2851
+ * Subscribe for the changes of objects in this instance.
2852
+ *
2853
+ * @param pattern pattern like 'channel.*' or '*' (all objects of this adapter) - without namespaces
2854
+ * @param options optional user context
2855
+ * @param callback optional returns result
2856
+ * ```js
2857
+ * function (err) {
2858
+ * if (err) adapter.log.error('Cannot subscribe object: ' + err);
2859
+ * }
2860
+ * ```
2861
+ */
2090
2862
  subscribeObjects(pattern, options, callback) {
2091
2863
  if (typeof options === "function") {
2092
2864
  callback = options;
@@ -2108,6 +2880,18 @@ class AdapterClass extends import_node_events.EventEmitter {
2108
2880
  this.#objects.subscribeUser(fixedPattern, options, callback);
2109
2881
  }
2110
2882
  }
2883
+ /**
2884
+ * Unsubscribe on the changes of objects in this instance.
2885
+ *
2886
+ * @param pattern pattern like 'channel.*' or '*' (all objects) - without namespaces
2887
+ * @param options optional user context
2888
+ * @param callback optional returns result
2889
+ * ```js
2890
+ * function (err) {
2891
+ * if (err) adapter.log.error('Cannot unsubscribe object: ' + err);
2892
+ * }
2893
+ * ```
2894
+ */
2111
2895
  unsubscribeObjects(pattern, options, callback) {
2112
2896
  if (typeof options === "function") {
2113
2897
  callback = options;
@@ -2129,6 +2913,18 @@ class AdapterClass extends import_node_events.EventEmitter {
2129
2913
  this.#objects.unsubscribeUser(fixedPattern, options, callback);
2130
2914
  }
2131
2915
  }
2916
+ /**
2917
+ * Subscribe for the changes of objects in any instance.
2918
+ *
2919
+ * @param pattern pattern like 'channel.*' or '*' (all objects) - without namespaces. You can use array of patterns
2920
+ * @param options optional user context
2921
+ * @param callback optional returns result
2922
+ * ```js
2923
+ * function (err) {
2924
+ * if (err) adapter.log.error('Cannot subscribe object: ' + err);
2925
+ * }
2926
+ * ```
2927
+ */
2132
2928
  subscribeForeignObjects(pattern, options, callback) {
2133
2929
  if (typeof options === "function") {
2134
2930
  callback = options;
@@ -2145,6 +2941,18 @@ class AdapterClass extends import_node_events.EventEmitter {
2145
2941
  }
2146
2942
  this.#objects.subscribeUser(pattern, options, callback);
2147
2943
  }
2944
+ /**
2945
+ * Unsubscribe for the patterns on all objects.
2946
+ *
2947
+ * @param pattern pattern like 'channel.*' or '*' (all objects) - without namespaces
2948
+ * @param options optional user context
2949
+ * @param callback optional returns result
2950
+ * ```js
2951
+ * function (err) {
2952
+ * if (err) adapter.log.error('Cannot unsubscribe object: ' + err);
2953
+ * }
2954
+ * ```
2955
+ */
2148
2956
  unsubscribeForeignObjects(pattern, options, callback) {
2149
2957
  if (typeof options === "function") {
2150
2958
  callback = options;
@@ -2164,6 +2972,13 @@ class AdapterClass extends import_node_events.EventEmitter {
2164
2972
  }
2165
2973
  this.#objects.unsubscribeUser(pattern, options, callback);
2166
2974
  }
2975
+ /**
2976
+ * Subscribe for the changes of files in specific instance.
2977
+ *
2978
+ * @param id adapter ID like 'vis-2.0' or 'vis-2.admin'
2979
+ * @param pattern pattern like 'channel.*' or '*' (all files) - without namespaces. You can use array of patterns
2980
+ * @param options optional user context
2981
+ */
2167
2982
  subscribeForeignFiles(id, pattern, options) {
2168
2983
  if (!this.#objects) {
2169
2984
  this._logger.info(`${this.namespaceLog} subscribeForeignFiles not processed because Objects database not connected`);
@@ -2176,6 +2991,13 @@ class AdapterClass extends import_node_events.EventEmitter {
2176
2991
  }
2177
2992
  return this.#objects.subscribeUserFile(id, pattern, options);
2178
2993
  }
2994
+ /**
2995
+ * Unsubscribe for the changes of files on specific instance.
2996
+ *
2997
+ * @param id adapter ID like 'vis-2.0' or 'vis-2.admin'
2998
+ * @param pattern pattern like 'channel.*' or '*' (all objects) - without namespaces
2999
+ * @param options optional user context
3000
+ */
2179
3001
  unsubscribeForeignFiles(id, pattern, options) {
2180
3002
  if (!pattern) {
2181
3003
  pattern = "*";
@@ -2191,6 +3013,23 @@ class AdapterClass extends import_node_events.EventEmitter {
2191
3013
  }
2192
3014
  return this.#objects.unsubscribeUserFile(id, pattern, options);
2193
3015
  }
3016
+ /**
3017
+ * Same as {@link AdapterClass.setObject}, but with check if the object exists.
3018
+ *
3019
+ * Only Ids that belong to this adapter can be modified. So the function automatically adds "adapter.X." to ID.
3020
+ * New object will be created only if no object exists with such ID.
3021
+ *
3022
+ * @param id object ID, that must be overwritten or created.
3023
+ * @param obj new object
3024
+ * @param options optional user context
3025
+ * @param callback return result
3026
+ * ```js
3027
+ * function (err, obj) {
3028
+ * // obj is {id: id}
3029
+ * if (err) adapter.log.error('Cannot write object: ' + err);
3030
+ * }
3031
+ * ```
3032
+ */
2194
3033
  setObjectNotExists(id, obj, options, callback) {
2195
3034
  if (typeof options === "function") {
2196
3035
  callback = options;
@@ -2241,6 +3080,23 @@ class AdapterClass extends import_node_events.EventEmitter {
2241
3080
  }
2242
3081
  return import_js_controller_common.tools.maybeCallbackWithError(options.callback, null);
2243
3082
  }
3083
+ /**
3084
+ * Same as {@link AdapterClass.setForeignObject}, but with check if the object exists.
3085
+ *
3086
+ * ID must be specified as a full name with adapter namespace. E.g "hm-rpc.0.ABC98989.1.STATE".
3087
+ * New object will be created only if no object exists with such ID.
3088
+ *
3089
+ * @param id object ID, that must be overwritten or created.
3090
+ * @param obj new object
3091
+ * @param options user context
3092
+ * @param callback return result
3093
+ * ```js
3094
+ * function (err, obj) {
3095
+ * // obj is {id: id}
3096
+ * if (err) adapter.log.error('Cannot write object: ' + err);
3097
+ * }
3098
+ * ```
3099
+ */
2244
3100
  setForeignObjectNotExists(id, obj, options, callback) {
2245
3101
  if (typeof options === "function") {
2246
3102
  callback = options;
@@ -2302,6 +3158,14 @@ class AdapterClass extends import_node_events.EventEmitter {
2302
3158
  }
2303
3159
  return id;
2304
3160
  }
3161
+ /**
3162
+ * @param deviceName
3163
+ * @param common
3164
+ * @param _native
3165
+ * @param options
3166
+ * @param callback
3167
+ * @deprecated use `this.extendObject` instead
3168
+ */
2305
3169
  createDevice(deviceName, common, _native, options, callback) {
2306
3170
  this._logger.info(`${this.namespaceLog} Method "createDevice" is deprecated and will be removed in js-controller 7.1, use "extendObject/setObjectNotExists" instead`);
2307
3171
  if (typeof options === "function") {
@@ -2346,6 +3210,17 @@ class AdapterClass extends import_node_events.EventEmitter {
2346
3210
  native: _native
2347
3211
  }, options, callback);
2348
3212
  }
3213
+ /**
3214
+ * Name of channel must be in format "channel"
3215
+ *
3216
+ * @param parentDevice
3217
+ * @param channelName
3218
+ * @param roleOrCommon
3219
+ * @param _native
3220
+ * @param options
3221
+ * @param callback
3222
+ * @deprecated use `this.extendObject` instead
3223
+ */
2349
3224
  createChannel(parentDevice, channelName, roleOrCommon, _native, options, callback) {
2350
3225
  this._logger.info(`${this.namespaceLog} Method "createChannel" is deprecated and will be removed in js-controller 7.1, use "extendObject/setObjectNotExists" instead`);
2351
3226
  if (typeof options === "function") {
@@ -2390,6 +3265,16 @@ class AdapterClass extends import_node_events.EventEmitter {
2390
3265
  };
2391
3266
  this.setObjectNotExists(channelName, obj, options, callback);
2392
3267
  }
3268
+ /**
3269
+ * @param parentDevice
3270
+ * @param parentChannel
3271
+ * @param stateName
3272
+ * @param roleOrCommon
3273
+ * @param _native
3274
+ * @param options
3275
+ * @param callback
3276
+ * @deprecated use `this.extendObject` instead
3277
+ */
2393
3278
  createState(parentDevice, parentChannel, stateName, roleOrCommon, _native, options, callback) {
2394
3279
  this._logger.info(`${this.namespaceLog} Method "createState" is deprecated and will be removed in js-controller 7.1, use "extendObject/setObjectNotExists" instead`);
2395
3280
  if (typeof options === "function") {
@@ -2534,6 +3419,19 @@ class AdapterClass extends import_node_events.EventEmitter {
2534
3419
  }
2535
3420
  });
2536
3421
  }
3422
+ /**
3423
+ * Delete device with all its channels and states.
3424
+ *
3425
+ * @deprecated use `this.delObject` instead
3426
+ * @param deviceName is the part of ID like: adapter.instance.<deviceName>
3427
+ * @param options optional user context
3428
+ * @param callback return result
3429
+ * ```js
3430
+ * function (err) {
3431
+ * if (err) adapter.log.error('Cannot delete device: ' + err);
3432
+ * }
3433
+ * ```
3434
+ */
2537
3435
  deleteDevice(deviceName, options, callback) {
2538
3436
  this._logger.info(`${this.namespaceLog} Method "deleteDevice" is deprecated and will be removed in js-controller 7.1, use "delObject" instead`);
2539
3437
  if (typeof options === "function") {
@@ -2726,6 +3624,21 @@ class AdapterClass extends import_node_events.EventEmitter {
2726
3624
  return import_js_controller_common.tools.maybeCallback(callback);
2727
3625
  });
2728
3626
  }
3627
+ /**
3628
+ * Deletes channel and underlying structure
3629
+ *
3630
+ * @deprecated use `this.delObject` instead
3631
+ * @alias deleteChannel
3632
+ * @param parentDevice is the part of ID like: adapter.instance.<deviceName>
3633
+ * @param channelName is the part of ID like: adapter.instance.<deviceName>.<channelName>
3634
+ * @param options optional user context
3635
+ * @param callback return result
3636
+ * ```js
3637
+ * function (err) {
3638
+ * if (err) adapter.log.error('Cannot delete device: ' + err);
3639
+ * }
3640
+ * ```
3641
+ */
2729
3642
  deleteChannel(parentDevice, channelName, options, callback) {
2730
3643
  this._logger.info(`${this.namespaceLog} Method "deleteChannel" is deprecated and will be removed in js-controller 7.1, use "delObject" instead`);
2731
3644
  if (typeof options === "function") {
@@ -2792,6 +3705,14 @@ class AdapterClass extends import_node_events.EventEmitter {
2792
3705
  }
2793
3706
  return import_js_controller_common.tools.maybeCallback(callback);
2794
3707
  }
3708
+ /**
3709
+ * @param parentDevice
3710
+ * @param parentChannel
3711
+ * @param stateName
3712
+ * @param options
3713
+ * @param callback
3714
+ * @deprecated use `this.delObject` instead
3715
+ */
2795
3716
  deleteState(parentDevice, parentChannel, stateName, options, callback) {
2796
3717
  this._logger.info(`${this.namespaceLog} Method "deleteState" is deprecated and will be removed in js-controller 7.1, use "delObject" instead`);
2797
3718
  if (typeof parentChannel === "function" && stateName === void 0) {
@@ -3176,11 +4097,15 @@ class AdapterClass extends import_node_events.EventEmitter {
3176
4097
  stateName = stateName.substring(parentChannel.length + 1);
3177
4098
  }
3178
4099
  stateName = stateName.replace(FORBIDDEN_CHARS, "_").replace(/\./g, "_");
3179
- const objId = this._utils.fixId({
3180
- device: parentDevice,
3181
- channel: parentChannel,
3182
- state: stateName
3183
- }, false);
4100
+ const objId = this._utils.fixId(
4101
+ {
4102
+ device: parentDevice,
4103
+ channel: parentChannel,
4104
+ state: stateName
4105
+ },
4106
+ false
4107
+ /*, 'state'*/
4108
+ );
3184
4109
  if (enumName) {
3185
4110
  enumName = `enum.${enumName}.`;
3186
4111
  } else {
@@ -3213,6 +4138,27 @@ class AdapterClass extends import_node_events.EventEmitter {
3213
4138
  return import_js_controller_common.tools.maybeCallback(callback);
3214
4139
  });
3215
4140
  }
4141
+ /**
4142
+ * Change file access rights
4143
+ *
4144
+ * This function updates the file access rights
4145
+ * ```js
4146
+ * adapter.chmodFile('vis-2.0', '/main/vis-views.json', {mode: 0x644}, function (err, processed) {
4147
+ * if (err) adapter.log.error('Cannot read file: ' + err);
4148
+ * adapter.log.info('New files: ' + JSON.stringify(processed));
4149
+ * });
4150
+ * ```
4151
+ *
4152
+ * @param _adapter adapter name. If the adapter name is null, so the name (not instance) of the current adapter will be taken.
4153
+ * @param path path to file without adapter name. E.g., If you want to update "/vis-2.0/main/*", here must be "/main/*" and _adapter must be equal to "vis-2.0".
4154
+ * @param options data with mode
4155
+ * @param callback return result
4156
+ * ```js
4157
+ * function (err, processedFiles) {
4158
+ * list of processed files with new groups
4159
+ * }
4160
+ * ```
4161
+ */
3216
4162
  chmodFile(_adapter, path2, options, callback) {
3217
4163
  if (_adapter === null) {
3218
4164
  _adapter = this.name;
@@ -3227,6 +4173,27 @@ class AdapterClass extends import_node_events.EventEmitter {
3227
4173
  }
3228
4174
  this.#objects.chmodFile(_adapter, path2, options, callback);
3229
4175
  }
4176
+ /**
4177
+ * Change a file owner
4178
+ *
4179
+ * This function updates the file owner and ownerGroup
4180
+ * ```js
4181
+ * adapter.chownFile('vis-2.0', '/main/vis-views.json', {owner: 'newOwner', ownerGroup: 'newgroup'}, function (err, processed) {
4182
+ * if (err) adapter.log.error('Cannot read file: ' + err);
4183
+ * adapter.log.info('New files: ' + JSON.stringify(processed));
4184
+ * });
4185
+ * ```
4186
+ *
4187
+ * @param _adapter adapter name. If the adapter name is null, so the name (not instance) of the current adapter will be taken.
4188
+ * @param path path to file without adapter name. E.g., If you want to update "/vis-2.0/main/*", here must be "/main/*" and _adapter must be equal to "vis-2.0".
4189
+ * @param options data with owner and ownerGroup
4190
+ * @param callback return result
4191
+ * ```js
4192
+ * function (err, processedFiles) {
4193
+ * list of processed files with new groups
4194
+ * }
4195
+ * ```
4196
+ */
3230
4197
  chownFile(_adapter, path2, options, callback) {
3231
4198
  if (_adapter === null) {
3232
4199
  _adapter = this.name;
@@ -3241,6 +4208,41 @@ class AdapterClass extends import_node_events.EventEmitter {
3241
4208
  }
3242
4209
  this.#objects.chownFile(_adapter, path2, options, callback);
3243
4210
  }
4211
+ /**
4212
+ * Read directory from DB.
4213
+ *
4214
+ * This function reads the content of directory from DB for given adapter and path.
4215
+ * If getEnum called with no enum specified, all enums will be returned:
4216
+ * ```js
4217
+ * adapter.readDir('vis-2.0', '/main/', function (err, filesOrDirs) {
4218
+ * // All enums
4219
+ * if (err) adapter.log.error('Cannot read directory: ' + err);
4220
+ * if (filesOrDirs) {
4221
+ * for (var f = 0; f < filesOrDirs.length; f++) {
4222
+ * adapter.log.debug('Directory main has the following files and dirs: ' + filesOrDirs[f].file + '[dir - ' + filesOrDirs[f].isDir + ']');
4223
+ * }
4224
+ * }
4225
+ * });
4226
+ * ```
4227
+ *
4228
+ * @param _adapter adapter name. If the adapter name is null, so the name (not instance) of the current adapter will be taken.
4229
+ * @param path path to directory without adapter name. E.g., If you want to read "/vis-2.0/main/views.json", here must be "/main/views.json" and _adapter must be equal to "vis-2.0".
4230
+ * @param options optional user context
4231
+ * @param callback return result
4232
+ * ```js
4233
+ * function (err, filesOrDirs) {
4234
+ * // filesOrDirs is array with elements like
4235
+ * // {
4236
+ * // file: 'views.json,
4237
+ * // stats: node.js stats object like https://nodejs.org/api/fs.html#fs_class_fs_stats ,
4238
+ * // isDir: true/false,
4239
+ * // acl: access control list object,
4240
+ * // modifiedAt: time when modified,
4241
+ * // createdAt: time when created
4242
+ * // }
4243
+ * }
4244
+ * ```
4245
+ */
3244
4246
  readDir(_adapter, path2, options, callback) {
3245
4247
  if (_adapter === null) {
3246
4248
  _adapter = this.name;
@@ -3322,6 +4324,28 @@ class AdapterClass extends import_node_events.EventEmitter {
3322
4324
  }
3323
4325
  this.#objects.mkdir(_adapter, dirname, options, callback);
3324
4326
  }
4327
+ /**
4328
+ * Read file from DB.
4329
+ *
4330
+ * This function reads the content of one file from DB for given adapter and file name.
4331
+ * ```js
4332
+ * adapter.readFile('vis-2.0', '/main/vis-views.json', function (err, data) {
4333
+ * // All enums
4334
+ * if (err) adapter.log.error('Cannot read file: ' + err);
4335
+ * adapter.log.info('Content of file is: ' + data);
4336
+ * });
4337
+ * ```
4338
+ *
4339
+ * @param _adapter adapter name. If the adapter name is null, so the name (not instance) of the current adapter will be taken.
4340
+ * @param filename path to file without adapter name. E.g., If you want to read "/vis-2.0/main/views.json", here must be "/main/views.json" and _adapter must be equal to "vis-2.0".
4341
+ * @param options optional user context
4342
+ * @param callback return result
4343
+ * ```js
4344
+ * function (err, data) {
4345
+ * // data is utf8 or binary Buffer depends on the file extension.
4346
+ * }
4347
+ * ```
4348
+ */
3325
4349
  readFile(_adapter, filename, options, callback) {
3326
4350
  if (_adapter === null) {
3327
4351
  _adapter = this.name;
@@ -3342,6 +4366,27 @@ class AdapterClass extends import_node_events.EventEmitter {
3342
4366
  }
3343
4367
  this.#objects.readFile(_adapter, filename, options, callback);
3344
4368
  }
4369
+ /**
4370
+ * Write file to DB.
4371
+ *
4372
+ * This function writes the content of one file into DB for given adapter and file name.
4373
+ * ```js
4374
+ * adapter.writeFile('vis-2.0', '/main/vis-views.json', data, function (err) {
4375
+ * err && adapter.log.error('Cannot write file: ' + err);
4376
+ * });
4377
+ * ```
4378
+ *
4379
+ * @param _adapter adapter name. If the adapter name is null, so the name (not instance) of the current adapter will be taken.
4380
+ * @param filename path to file without adapter name. E.g., If you want to read "/vis-2.0/main/views.json", here must be "/main/views.json" and _adapter must be equal to "vis-2.0".
4381
+ * @param data data as UTF8 string or buffer depends on the file extension.
4382
+ * @param options optional user context
4383
+ * @param callback return result
4384
+ * ```js
4385
+ * function (err) {
4386
+ *
4387
+ * }
4388
+ * ```
4389
+ */
3345
4390
  writeFile(_adapter, filename, data, options, callback) {
3346
4391
  if (_adapter === null) {
3347
4392
  _adapter = this.name;
@@ -3365,6 +4410,14 @@ class AdapterClass extends import_node_events.EventEmitter {
3365
4410
  }
3366
4411
  return this.#objects.writeFile(_adapter, filename, data, options, callback);
3367
4412
  }
4413
+ /**
4414
+ * Checks if file exists in DB.
4415
+ *
4416
+ * @param _adapter adapter name
4417
+ * @param filename path to file without adapter name. E.g., If you want to check "/vis-2.0/main/views.json", here must be "/main/views.json" and _adapter must be equal to "vis-2.0".
4418
+ * @param options optional user context
4419
+ * @param callback cb function if none provided, a promise is returned
4420
+ */
3368
4421
  async fileExists(_adapter, filename, options, callback) {
3369
4422
  if (typeof options === "function") {
3370
4423
  callback = options;
@@ -3392,11 +4445,17 @@ class AdapterClass extends import_node_events.EventEmitter {
3392
4445
  _format = decimals;
3393
4446
  decimals = 2;
3394
4447
  }
3395
- const format = !_format || _format.length !== 2 ? this.isFloatComma === void 0 ? ".," : this.isFloatComma ? ".," : ",." : _format;
4448
+ const format = (
4449
+ // @ts-expect-error fix later
4450
+ !_format || _format.length !== 2 ? this.isFloatComma === void 0 ? ".," : this.isFloatComma ? ".," : ",." : _format
4451
+ );
3396
4452
  if (typeof value !== "number") {
3397
4453
  value = parseFloat(value);
3398
4454
  }
3399
- return isNaN(value) ? "" : value.toFixed(decimals).replace(format[0], format[1]).replace(/\B(?=(\d{3})+(?!\d))/g, format[0]);
4455
+ return isNaN(value) ? "" : (
4456
+ // @ts-expect-error fix later
4457
+ value.toFixed(decimals).replace(format[0], format[1]).replace(/\B(?=(\d{3})+(?!\d))/g, format[0])
4458
+ );
3400
4459
  }
3401
4460
  formatDate(dateObj, isDuration, _format) {
3402
4461
  if (typeof isDuration === "string" && isDuration.toLowerCase() === "duration" || isDuration === true) {
@@ -3535,6 +4594,24 @@ class AdapterClass extends import_node_events.EventEmitter {
3535
4594
  put(s);
3536
4595
  return result;
3537
4596
  }
4597
+ /**
4598
+ * Send message to other adapter instance or all instances of adapter.
4599
+ *
4600
+ * This function sends a message to specific instance or all instances of some specific adapter.
4601
+ * If no instance given (e.g. "pushover"), the callback argument will be ignored. Because normally many responses will come.
4602
+ *
4603
+ * @param instanceName name of the instance where the message must be sent to. E.g. "pushover.0" or "system.adapter.pushover.0".
4604
+ * @param command command name, like "send", "browse", "list". Command is depend on target adapter implementation.
4605
+ * @param message object that will be given as argument for request
4606
+ * @param callback optional return result
4607
+ * ```js
4608
+ * function (result) {
4609
+ * // result is target adapter specific and can vary from adapter to adapter
4610
+ * if (!result) adapter.log.error('No response received');
4611
+ * }
4612
+ * ```
4613
+ * @param options optional options to define a timeout. This allows to get an error callback if no answer received in time (only if target is specific instance)
4614
+ */
3538
4615
  sendTo(instanceName, command, message, callback, options) {
3539
4616
  if (typeof message === "function" && typeof callback === "undefined") {
3540
4617
  callback = message;
@@ -3560,6 +4637,15 @@ class AdapterClass extends import_node_events.EventEmitter {
3560
4637
  callback
3561
4638
  });
3562
4639
  }
4640
+ /**
4641
+ * Async version of sendTo
4642
+ * As we have a special case (first arg can be error or result, we need to promisify manually)
4643
+ *
4644
+ * @param instanceName name of the instance where the message must be sent to. E.g. "pushover.0" or "system.adapter.pushover.0".
4645
+ * @param command command name, like "send", "browse", "list". Command is depend on target adapter implementation.
4646
+ * @param message object that will be given as argument for request
4647
+ * @param options optional options to define a timeout. This allows to get an error callback if no answer received in time (only if target is specific instance)
4648
+ */
3563
4649
  sendToAsync(instanceName, command, message, options) {
3564
4650
  return new Promise((resolve, reject) => {
3565
4651
  const callback = (resOrError) => {
@@ -3661,6 +4747,23 @@ class AdapterClass extends import_node_events.EventEmitter {
3661
4747
  }
3662
4748
  }
3663
4749
  }
4750
+ /**
4751
+ * Send message to specific host or to all hosts.
4752
+ *
4753
+ * This function sends a message to specific host or all hosts.
4754
+ * If no host name given (e.g. null), the callback argument will be ignored. Because normally many responses will come.
4755
+ *
4756
+ * @param hostName name of the host where the message must be sent to. E.g. "myPC" or "system.host.myPC". If argument is null, the message will be sent to all hosts.
4757
+ * @param command command name. One of: "cmdExec", "getRepository", "getInstalled", "getVersion", "getDiagData", "getLocationOnDisk", "getDevList", "getLogs", "delLogs", "readDirAsZip", "writeDirAsZip", "readObjectsAsZip", "writeObjectsAsZip", "checkLogging". Commands can be checked in controller.js (function processMessage)
4758
+ * @param message object that will be given as argument for request
4759
+ * @param callback optional return result
4760
+ * ```js
4761
+ * function (result) {
4762
+ * // result is target adapter specific and can vary from command to command
4763
+ * if (!result) adapter.log.error('No response received');
4764
+ * }
4765
+ * ```
4766
+ */
3664
4767
  sendToHost(hostName, command, message, callback) {
3665
4768
  if (typeof message === "undefined") {
3666
4769
  message = command;
@@ -3745,6 +4848,11 @@ class AdapterClass extends import_node_events.EventEmitter {
3745
4848
  }
3746
4849
  }
3747
4850
  }
4851
+ /**
4852
+ * Send a message to an active UI Client
4853
+ *
4854
+ * @param options clientId and data options
4855
+ */
3748
4856
  sendToUI(options) {
3749
4857
  if (!this.#states) {
3750
4858
  throw new Error(import_js_controller_common.tools.ERRORS.ERROR_DB_CLOSED);
@@ -3763,6 +4871,14 @@ class AdapterClass extends import_node_events.EventEmitter {
3763
4871
  states: this.#states
3764
4872
  });
3765
4873
  }
4874
+ /**
4875
+ * Send notification with given scope and category to host of this adapter
4876
+ *
4877
+ * @param scope - scope to be addressed
4878
+ * @param category - to be addressed, if a null message will be checked by regex of given scope
4879
+ * @param message - message to be stored/checked
4880
+ * @param options - Additional options for the notification, currently `contextData` is supported
4881
+ */
3766
4882
  async registerNotification(scope, category, message, options) {
3767
4883
  if (!this.#states) {
3768
4884
  this._logger.info(`${this.namespaceLog} registerNotification not processed because States database not connected`);
@@ -3789,6 +4905,37 @@ class AdapterClass extends import_node_events.EventEmitter {
3789
4905
  };
3790
4906
  await this.#states.pushMessage(`system.host.${this.host}`, obj);
3791
4907
  }
4908
+ /**
4909
+ * Writes value into states DB.
4910
+ *
4911
+ * This function can write values into states DB for this adapter.
4912
+ * Only Ids that belong to this adapter can be modified. So the function automatically adds "adapter.X." to ID.
4913
+ * ack, options and callback are optional
4914
+ *
4915
+ * @param id object ID of the state.
4916
+ * @param state simple value or object with attributes.
4917
+ * If state is object and ack exists too as function argument, function argument has priority.
4918
+ * ```js
4919
+ * {
4920
+ * val: value,
4921
+ * ack: true|false, // default - false; is command(false) or status(true)
4922
+ * ts: timestampMS, // default - now
4923
+ * q: qualityAsNumber, // default - 0 (ok)
4924
+ * from: origin, // default - this adapter
4925
+ * c: comment, // default - empty
4926
+ * expire: expireInSeconds // default - 0
4927
+ * lc: timestampMS // default - automatic calculation
4928
+ * }
4929
+ * ```
4930
+ * @param ack optional is command(false) or status(true)
4931
+ * @param options optional user context
4932
+ * @param callback optional return error and id
4933
+ * ```js
4934
+ * function (err, id) {
4935
+ * if (err) adapter.log.error('Cannot set value for "' + id + '": ' + err);
4936
+ * }
4937
+ * ```
4938
+ */
3792
4939
  setState(id, state, ack, options, callback) {
3793
4940
  if (typeof state === "object" && typeof ack !== "boolean") {
3794
4941
  callback = options;
@@ -3928,6 +5075,7 @@ class AdapterClass extends import_node_events.EventEmitter {
3928
5075
  }
3929
5076
  }
3930
5077
  }
5078
+ // Cache will be cleared if user or group changes. Important! only if subscribed.
3931
5079
  async _getUserGroups(options) {
3932
5080
  if (this.users[options.user]) {
3933
5081
  options.groups = this.users[options.user].groups;
@@ -3958,6 +5106,7 @@ class AdapterClass extends import_node_events.EventEmitter {
3958
5106
  }
3959
5107
  this.users[options.user] = {
3960
5108
  groups: options.groups,
5109
+ // @ts-expect-error TODO: UserCommon has no acl
3961
5110
  acl: userAcl.common?.acl || {}
3962
5111
  };
3963
5112
  await this._getGroups(options.groups);
@@ -4226,6 +5375,25 @@ class AdapterClass extends import_node_events.EventEmitter {
4226
5375
  return { id, notChanged: true };
4227
5376
  }
4228
5377
  }
5378
+ /**
5379
+ * Writes value into states DB only if the value really changed.
5380
+ *
5381
+ * This function can write values into states DB for this adapter.
5382
+ * Only Ids that belong to this adapter can be modified. So the function automatically adds "adapter.X." to ID.
5383
+ * ack, options and callback are optional
5384
+ *
5385
+ * @param id object ID of the state.
5386
+ * @param state simple value or object with attribues.
5387
+ * @param ack optional is command(false) or status(true)
5388
+ * @param options optional user context
5389
+ * @param callback optional return error, id and notChanged
5390
+ * ```js
5391
+ * function (err, id, notChanged) {
5392
+ * if (err) adapter.log.error('Cannot set value for "' + id + '": ' + err);
5393
+ * if (!notChanged) adapter.log.debug('Value was changed');
5394
+ * }
5395
+ * ```
5396
+ */
4229
5397
  setStateChanged(id, state, ack, options, callback) {
4230
5398
  if (typeof state === "object" && typeof ack !== "boolean") {
4231
5399
  callback = options;
@@ -4294,6 +5462,36 @@ class AdapterClass extends import_node_events.EventEmitter {
4294
5462
  const res = await this._setStateChangedHelper(fixedId, stateObj);
4295
5463
  return import_js_controller_common.tools.maybeCallbackWithError(callback, null, res.id, res.notChanged);
4296
5464
  }
5465
+ /**
5466
+ * Writes value into states DB for any instance.
5467
+ *
5468
+ * This function can write values into states DB for all instances and system states too.
5469
+ * ack, options and callback are optional
5470
+ *
5471
+ * @param id object ID of the state.
5472
+ * @param state simple value or object with attribues.
5473
+ * If state is object, so the ack will be ignored and must be included into object.
5474
+ * ```js
5475
+ * {
5476
+ * val: value,
5477
+ * ack: true|false, // default - false; is command(false) or status(true)
5478
+ * ts: timestampMS, // default - now
5479
+ * q: qualityAsNumber, // default - 0 (ok)
5480
+ * from: origin, // default - this adapter
5481
+ * c: comment, // default - empty
5482
+ * expire: expireInSeconds // default - 0
5483
+ * lc: timestampMS // default - automatic calculation
5484
+ * }
5485
+ * ```
5486
+ * @param ack optional is command(false) or status(true)
5487
+ * @param options optional user context
5488
+ * @param callback optional return error and id
5489
+ * ```js
5490
+ * function (err, id) {
5491
+ * if (err) adapter.log.error('Cannot set value for "' + id + '": ' + err);
5492
+ * }
5493
+ * ```
5494
+ */
4297
5495
  async setForeignState(id, state, ack, options, callback) {
4298
5496
  if (typeof state === "object" && typeof ack !== "boolean") {
4299
5497
  callback = options;
@@ -4460,6 +5658,36 @@ class AdapterClass extends import_node_events.EventEmitter {
4460
5658
  }
4461
5659
  }
4462
5660
  }
5661
+ /**
5662
+ * Writes value into states DB for any instance, but only if state changed.
5663
+ *
5664
+ * This function can write values into states DB for all instances and system states too.
5665
+ * ack, options and callback are optional
5666
+ *
5667
+ * @param id object ID of the state.
5668
+ * @param state simple value or object with attribues.
5669
+ * If state is object and ack exists too as function argument, function argument has priority.
5670
+ * ```js
5671
+ * {
5672
+ * val: value,
5673
+ * ack: true|false, // default - false; is command(false) or status(true)
5674
+ * ts: timestampMS, // default - now
5675
+ * q: qualityAsNumber, // default - 0 (ok)
5676
+ * from: origin, // default - this adapter
5677
+ * c: comment, // default - empty
5678
+ * expire: expireInSeconds // default - 0
5679
+ * lc: timestampMS // default - automatic calculation
5680
+ * }
5681
+ * ```
5682
+ * @param ack optional is command(false) or status(true)
5683
+ * @param options optional user context
5684
+ * @param callback optional return error and id
5685
+ * ```js
5686
+ * function (err, id) {
5687
+ * if (err) adapter.log.error('Cannot set value for "' + id + '": ' + err);
5688
+ * }
5689
+ * ```
5690
+ */
4463
5691
  async setForeignStateChanged(id, state, ack, options, callback) {
4464
5692
  if (typeof state === "object" && typeof ack !== "boolean") {
4465
5693
  callback = options;
@@ -4513,6 +5741,23 @@ class AdapterClass extends import_node_events.EventEmitter {
4513
5741
  const res = await this._setStateChangedHelper(id, state);
4514
5742
  return import_js_controller_common.tools.maybeCallbackWithError(callback, null, res.id, res.notChanged);
4515
5743
  }
5744
+ /**
5745
+ * Read value from states DB.
5746
+ *
5747
+ * This function can read values from states DB for this adapter.
5748
+ * Only Ids that belong to this adapter can be read. So the function automatically adds "adapter.X." to ID.
5749
+ *
5750
+ * @param id object ID of the state.
5751
+ * @param options optional user context
5752
+ * @param callback return result
5753
+ * ```js
5754
+ * function (err, state) {
5755
+ * if (err) adapter.log.error('Cannot read value: ' + err);
5756
+ * }
5757
+ * ```
5758
+ *
5759
+ * See possible attributes of the state in @setState explanation
5760
+ */
4516
5761
  getState(id, options, callback) {
4517
5762
  if (!import_js_controller_common.tools.isObject(id)) {
4518
5763
  import_validator.Validator.assertString(id, "id");
@@ -4520,6 +5765,22 @@ class AdapterClass extends import_node_events.EventEmitter {
4520
5765
  const fixedId = this._utils.fixId(id, false);
4521
5766
  return this.getForeignState(fixedId, options, callback);
4522
5767
  }
5768
+ /**
5769
+ * Read value from states DB for any instance and system state.
5770
+ *
5771
+ * This function can read values from states DB for all instances and adapters. It expects the full path of object ID.
5772
+ *
5773
+ * @param id object ID of the state.
5774
+ * @param options optional user context
5775
+ * @param callback return result
5776
+ * ```js
5777
+ * function (err, state) {
5778
+ * if (err) adapter.log.error('Cannot read value: ' + err);
5779
+ * }
5780
+ * ```
5781
+ *
5782
+ * See possible attributes of the state in @setState explanation
5783
+ */
4523
5784
  getForeignState(id, options, callback) {
4524
5785
  if (typeof options === "function") {
4525
5786
  callback = options;
@@ -4611,6 +5872,7 @@ class AdapterClass extends import_node_events.EventEmitter {
4611
5872
  return this.#states.getState(id, callback);
4612
5873
  }
4613
5874
  }
5875
+ // find out default history instance
4614
5876
  async _getDefaultHistory() {
4615
5877
  if (!this.defaultHistory) {
4616
5878
  let data;
@@ -4647,6 +5909,46 @@ class AdapterClass extends import_node_events.EventEmitter {
4647
5909
  }
4648
5910
  }
4649
5911
  }
5912
+ /**
5913
+ * Read historian data for states of any instance or system state.
5914
+ *
5915
+ * This function can read values from history adapters like: history, sql, influxdb. It expects the full path of object ID.
5916
+ * Normally only foreign history has interest, so there is no getHistory and getForeignHistory
5917
+ *
5918
+ * Possible options:
5919
+ *
5920
+ * - instance - (optional) name of instance, where to read the historian data, e.g. 'history.0', 'sql.1'. By default, will be taken from system settings.
5921
+ * - start - (optional) time in ms - Date.now()', by default is (now - 1 week)
5922
+ * - end - (optional) time in ms - Date.now()', by default is (now + 5000 seconds)
5923
+ * - step - (optional) used in aggregate (m4, max, min, average, total) step in ms of intervals
5924
+ * - count - number of values if aggregate is 'onchange' or number of intervals if other aggregate method. Count will be ignored if step is set.
5925
+ * - from - if from field should be included in answer
5926
+ * - ack - if ack field should be included in answer
5927
+ * - q - if q field should be included in answer
5928
+ * - addId - if id field should be included in answer
5929
+ * - limit - do not return more entries than limit
5930
+ * - ignoreNull - if null values should be included (false), replaced by last not null value (true) or replaced with 0 (0)
5931
+ * - sessionId - (optional) identifier of request, will be returned back in the answer
5932
+ * - aggregate - aggregate method:
5933
+ * - minmax - used special algorithm. Splice the whole time range in small intervals and find for every interval max, min, start and end values.
5934
+ * - max - Splice the whole time range in small intervals and find for every interval max value and use it for this interval (nulls will be ignored).
5935
+ * - min - Same as max, but take minimal value.
5936
+ * - average - Same as max, but take average value.
5937
+ * - total - Same as max, but calculate total value.
5938
+ * - count - Same as max, but calculate number of values (nulls will be calculated).
5939
+ * - none - No aggregation at all. Only raw values in the given period.
5940
+ *
5941
+ * @param id object ID of the state.
5942
+ * @param options see function description
5943
+ * @param callback return result
5944
+ * ```js
5945
+ * function (error, result, step, sessionId) {
5946
+ * if (error) adapter.log.error('Cannot read value: ' + err);
5947
+ * }
5948
+ * ```
5949
+ *
5950
+ * See possible attributes of the state in @setState explanation
5951
+ */
4650
5952
  getHistory(id, options, callback) {
4651
5953
  if (typeof options === "function") {
4652
5954
  callback = options;
@@ -4659,6 +5961,7 @@ class AdapterClass extends import_node_events.EventEmitter {
4659
5961
  import_validator.Validator.assertCallback(callback, "callback");
4660
5962
  return this._getHistory({ id, options, callback });
4661
5963
  }
5964
+ // Checked implementation
4662
5965
  async _getHistory(_options) {
4663
5966
  const { id, callback } = _options;
4664
5967
  let { options } = _options;
@@ -4683,6 +5986,15 @@ class AdapterClass extends import_node_events.EventEmitter {
4683
5986
  import_js_controller_common.tools.maybeCallbackWithError(callback, res.error, res.result, res.step, res.sessionId);
4684
5987
  });
4685
5988
  }
5989
+ /**
5990
+ * Convert ID into object with device's, channel's and state's name.
5991
+ *
5992
+ * Convert "adapter.instance.D.C.S" in object `{device: D, channel: C, state: S}`
5993
+ * Convert ID to `{device: D, channel: C, state: S}`
5994
+ *
5995
+ * @param id short or long string of ID like "stateID" or "adapterName.0.stateID".
5996
+ * @returns parsed ID as an object
5997
+ */
4686
5998
  idToDCS(id) {
4687
5999
  if (!id) {
4688
6000
  return null;
@@ -4695,6 +6007,24 @@ class AdapterClass extends import_node_events.EventEmitter {
4695
6007
  }
4696
6008
  return { device: parts[2], channel: parts[3], state: parts[4] };
4697
6009
  }
6010
+ /**
6011
+ * Deletes a state of this instance.
6012
+ * The object will NOT be deleted. If you want to delete it too, use @delObject instead.
6013
+ *
6014
+ * It is not required to provice the adapter namespace, because it will automatically be added.
6015
+ * E.g. to delete "adapterName.X.myObject", only "myObject" is required as ID.
6016
+ *
6017
+ * No error is returned if state does not exist.
6018
+ *
6019
+ * @param id exactly object ID (without namespace)
6020
+ * @param options optional user context
6021
+ * @param callback return result
6022
+ * ```js
6023
+ * function (err) {
6024
+ * if (err) adapter.log.error('Cannot delete object: ' + err);
6025
+ * }
6026
+ * ```
6027
+ */
4698
6028
  delState(id, options, callback) {
4699
6029
  if (typeof options === "function") {
4700
6030
  callback = options;
@@ -4718,6 +6048,19 @@ class AdapterClass extends import_node_events.EventEmitter {
4718
6048
  id = this._utils.fixId(id);
4719
6049
  return this.delForeignState(id, options, callback);
4720
6050
  }
6051
+ /**
6052
+ * Deletes a state of any adapter.
6053
+ * The object is NOT deleted. If you want to delete it too, use @delForeignObject instead.
6054
+ *
6055
+ * No error is returned if state does not exist.
6056
+ *
6057
+ * @param id long string for ID like "adapterName.0.stateID".
6058
+ * @param options optional argument to describe the user context
6059
+ * @param callback return result
6060
+ * ```js
6061
+ * function (err) {}
6062
+ * ```
6063
+ */
4721
6064
  delForeignState(id, options, callback) {
4722
6065
  if (typeof options === "function") {
4723
6066
  callback = options;
@@ -4750,6 +6093,25 @@ class AdapterClass extends import_node_events.EventEmitter {
4750
6093
  }
4751
6094
  this.#states.delState(id, callback);
4752
6095
  }
6096
+ /**
6097
+ * Read all states of this adapter, that pass the pattern
6098
+ *
6099
+ * Allows to read all states of current adapter according to pattern. To read all states of current adapter use:
6100
+ * ```js
6101
+ * adapter.getStates('*', function (err, states) {
6102
+ * for (var id in states) {
6103
+ * adapter.log.debug('"' + id + '" = "' + states[id].val);
6104
+ * }
6105
+ * });
6106
+ * ```
6107
+ *
6108
+ * @param pattern string in form 'adapter.0.*' or like this. It can be an array of IDs too.
6109
+ * @param options optional argument to describe the user context
6110
+ * @param callback return result
6111
+ * ```js
6112
+ * function (err, states) {}, where states is an object like {"ID1": {"val": 1, "ack": true}, "ID2": {"val": 2, "ack": false}, ...}
6113
+ * ```
6114
+ */
4753
6115
  getStates(pattern, options, callback) {
4754
6116
  if (typeof options === "function") {
4755
6117
  callback = options;
@@ -4785,6 +6147,13 @@ class AdapterClass extends import_node_events.EventEmitter {
4785
6147
  }
4786
6148
  return result;
4787
6149
  }
6150
+ /**
6151
+ * Ensures, that object information is read, and the alias id is mapped to the source id if an alias is contained in the getStates call
6152
+ * The adaption of the actual values is then performed in _processStatesSecondary, to apply alias conversion methods
6153
+ *
6154
+ * @param keys all ids of the getStates call
6155
+ * @param targetObjs the target objects (e.g. alias objects or the actual objects)
6156
+ */
4788
6157
  async _processStates(keys, targetObjs) {
4789
6158
  const aliasIndexes = [];
4790
6159
  const aliasIds = [];
@@ -4815,6 +6184,25 @@ class AdapterClass extends import_node_events.EventEmitter {
4815
6184
  }
4816
6185
  return this._processStatesSecondary(keys, null, null);
4817
6186
  }
6187
+ /**
6188
+ * Read all states of all adapters (and system states), that pass the pattern
6189
+ *
6190
+ * Allows to read all states of current adapter according to pattern. To read all states of current adapter use:
6191
+ * ```js
6192
+ * adapter.getStates('*', function (err, states) {
6193
+ * for (var id in states) {
6194
+ * adapter.log.debug('"' + id + '" = "' + states[id].val);
6195
+ * }
6196
+ * });
6197
+ * ```
6198
+ *
6199
+ * @param pattern string in form 'adapter.0.*' or like this. It can be an array of IDs too.
6200
+ * @param options optional argument to describe the user context
6201
+ * @param callback return result
6202
+ * ```js
6203
+ * function (err, states) {}, where states is an object like {"ID1": {"val": 1, "ack": true}, "ID2": {"val": 2, "ack": false}, ...}
6204
+ * ```
6205
+ */
4818
6206
  getForeignStates(pattern, options, callback) {
4819
6207
  if (typeof options === "function") {
4820
6208
  callback = options;
@@ -4910,6 +6298,12 @@ class AdapterClass extends import_node_events.EventEmitter {
4910
6298
  }
4911
6299
  }
4912
6300
  }
6301
+ /**
6302
+ * Add subscription for given alias, if it is not a state it will be ignored
6303
+ *
6304
+ * @param aliasObj the alias object
6305
+ * @param pattern pattern to subscribe for
6306
+ */
4913
6307
  async _addAliasSubscribe(aliasObj, pattern) {
4914
6308
  if (aliasObj.type !== "state") {
4915
6309
  return;
@@ -4954,6 +6348,12 @@ class AdapterClass extends import_node_events.EventEmitter {
4954
6348
  }
4955
6349
  aliasDetails.targets.push(targetEntry);
4956
6350
  }
6351
+ /**
6352
+ * Remove an alias subscribe
6353
+ *
6354
+ * @param sourceId id of the source object
6355
+ * @param aliasObjOrIdx the alias target or the index of the targets array
6356
+ */
4957
6357
  async _removeAliasSubscribe(sourceId, aliasObjOrIdx) {
4958
6358
  if (!this.aliases.has(sourceId)) {
4959
6359
  return;
@@ -4968,6 +6368,18 @@ class AdapterClass extends import_node_events.EventEmitter {
4968
6368
  }
4969
6369
  }
4970
6370
  }
6371
+ /**
6372
+ * Subscribe for changes on all states of all adapters (and system states), that pass the pattern
6373
+ *
6374
+ * Allows to Subscribe on changes all states of all instances according to pattern. E.g. to read all states of 'adapterName.X' instance use:
6375
+ * ```js
6376
+ * adapter.subscribeForeignStates('adapterName.X.*');
6377
+ * ```
6378
+ *
6379
+ * @param pattern string in form 'adapter.0.*' or like this. It can be an array of IDs too.
6380
+ * @param options optional argument to describe the user context
6381
+ * @param callback return result ```function (err) {}```
6382
+ */
4971
6383
  subscribeForeignStates(pattern, options, callback) {
4972
6384
  pattern = pattern || "*";
4973
6385
  if (typeof options === "function") {
@@ -5113,6 +6525,23 @@ class AdapterClass extends import_node_events.EventEmitter {
5113
6525
  this.#states.subscribeUser(pattern, callback);
5114
6526
  }
5115
6527
  }
6528
+ /**
6529
+ * Unsubscribe for changes for given pattern
6530
+ *
6531
+ * This function allows to unsubscribe from changes. The pattern must be equal to requested one.
6532
+ * ```js
6533
+ * adapter.subscribeForeignStates('adapterName.X.*');
6534
+ * adapter.unsubscribeForeignStates('adapterName.X.abc*'); // This will not work
6535
+ * adapter.unsubscribeForeignStates('adapterName.X.*'); // Valid unsubscribe
6536
+ * ```
6537
+ *
6538
+ * @param pattern string in form 'adapter.0.*'. Must be the same as subscribe.
6539
+ * @param options optional argument to describe the user context
6540
+ * @param callback return result
6541
+ * ```js
6542
+ * function (err) {}
6543
+ * ```
6544
+ */
5116
6545
  unsubscribeForeignStates(pattern, options, callback) {
5117
6546
  pattern = pattern || "*";
5118
6547
  if (typeof options === "function") {
@@ -5207,6 +6636,18 @@ class AdapterClass extends import_node_events.EventEmitter {
5207
6636
  }
5208
6637
  return import_js_controller_common.tools.maybeCallback(callback);
5209
6638
  }
6639
+ /**
6640
+ * Subscribe for changes on all states of this instance, that pass the pattern
6641
+ *
6642
+ * Allows to Subscribe on changes all states of current adapter according to pattern. To read all states of current adapter use:
6643
+ * ```js
6644
+ * adapter.subscribeStates('*'); // subscribe for all states of this adapter
6645
+ * ```
6646
+ *
6647
+ * @param pattern string in form 'adapter.0.*' or like this. Only string allowed
6648
+ * @param options optional argument to describe the user context
6649
+ * @param callback optional callback
6650
+ */
5210
6651
  subscribeStates(pattern, options, callback) {
5211
6652
  if (typeof options === "function") {
5212
6653
  callback = options;
@@ -5223,6 +6664,20 @@ class AdapterClass extends import_node_events.EventEmitter {
5223
6664
  callback
5224
6665
  });
5225
6666
  }
6667
+ /**
6668
+ * Unsubscribe for changes for given pattern for own states.
6669
+ *
6670
+ * This function allows to unsubscribe from changes. The pattern must be equal to requested one.
6671
+ *
6672
+ * ```js
6673
+ * adapter.unsubscribeStates('abc*'); // This will not work
6674
+ * adapter.unsubscribeStates('*'); // Valid unsubscribe
6675
+ * ```
6676
+ *
6677
+ * @param pattern string in form 'adapter.0.*'. Must be the same as subscribe.
6678
+ * @param options optional argument to describe the user context
6679
+ * @param callback optional callback
6680
+ */
5226
6681
  unsubscribeStates(pattern, options, callback) {
5227
6682
  if (typeof options === "function") {
5228
6683
  callback = options;
@@ -5239,6 +6694,12 @@ class AdapterClass extends import_node_events.EventEmitter {
5239
6694
  callback
5240
6695
  });
5241
6696
  }
6697
+ /**
6698
+ * Return plugin instance
6699
+ *
6700
+ * @param name name of the plugin to return
6701
+ * @returns plugin instance or null if not existent or not isActive
6702
+ */
5242
6703
  getPluginInstance(name) {
5243
6704
  if (!this.pluginHandler) {
5244
6705
  return null;
@@ -5246,6 +6707,12 @@ class AdapterClass extends import_node_events.EventEmitter {
5246
6707
  import_validator.Validator.assertString(name, "name");
5247
6708
  return this.pluginHandler.getPluginInstance(name);
5248
6709
  }
6710
+ /**
6711
+ * Return plugin configuration
6712
+ *
6713
+ * @param name name of the plugin to return
6714
+ * @returns plugin configuration or null if not existent or not isActive
6715
+ */
5249
6716
  getPluginConfig(name) {
5250
6717
  if (!this.pluginHandler) {
5251
6718
  return null;
@@ -5274,6 +6741,13 @@ class AdapterClass extends import_node_events.EventEmitter {
5274
6741
  }
5275
6742
  }
5276
6743
  }
6744
+ /**
6745
+ * This method returns the list of license that can be used by this adapter
6746
+ *
6747
+ * @param all if return the licenses, that used by other instances (true) or only for this instance (false)
6748
+ * @param adapterName Return licenses for specific adapter
6749
+ * @returns list of suitable licenses
6750
+ */
5277
6751
  async getSuitableLicenses(all, adapterName) {
5278
6752
  const licenses = [];
5279
6753
  try {
@@ -5343,6 +6817,12 @@ class AdapterClass extends import_node_events.EventEmitter {
5343
6817
  });
5344
6818
  return licenses;
5345
6819
  }
6820
+ /**
6821
+ * Add given id to log redirect list
6822
+ *
6823
+ * @param isActive if id should be added or removed
6824
+ * @param id the id to add
6825
+ */
5346
6826
  logRedirect(isActive, id) {
5347
6827
  if (id === `system.adapter.${this.namespace}`) {
5348
6828
  return;
@@ -5453,6 +6933,7 @@ class AdapterClass extends import_node_events.EventEmitter {
5453
6933
  this.inputCount = 0;
5454
6934
  this.outputCount = 0;
5455
6935
  }
6936
+ // debug function to find error with stop logging
5456
6937
  _checkLogging() {
5457
6938
  let logs = [];
5458
6939
  logs.push(`Actual Loglist - ${JSON.stringify(Array.from(this.logList))}`);
@@ -5470,7 +6951,8 @@ class AdapterClass extends import_node_events.EventEmitter {
5470
6951
  const objPart = obj[i];
5471
6952
  if (objPart) {
5472
6953
  const id = keys[i].substring(0, keys[i].length - ".logging".length);
5473
- if (typeof objPart === "string" && (objPart.includes('"val":true') || objPart.includes('"val":"true"')) || typeof objPart === "object" && (objPart.val === true || objPart.val === "true")) {
6954
+ if (typeof objPart === "string" && // @ts-expect-error recheck code-wise this should not be possible to have a string
6955
+ (objPart.includes('"val":true') || objPart.includes('"val":"true"')) || typeof objPart === "object" && (objPart.val === true || objPart.val === "true")) {
5474
6956
  logs.push(`Subscriber - ${id} ENABLED`);
5475
6957
  } else {
5476
6958
  if (logs) {
@@ -5492,6 +6974,9 @@ class AdapterClass extends import_node_events.EventEmitter {
5492
6974
  }
5493
6975
  });
5494
6976
  }
6977
+ /**
6978
+ * Initialize the logging logic
6979
+ */
5495
6980
  async _initLogging() {
5496
6981
  if (!this.#states) {
5497
6982
  return;
@@ -5607,6 +7092,7 @@ class AdapterClass extends import_node_events.EventEmitter {
5607
7092
  };
5608
7093
  }
5609
7094
  }
7095
+ // initStates is called from initAdapter
5610
7096
  _initStates(cb) {
5611
7097
  this._logger.silly(`${this.namespaceLog} objectDB connected`);
5612
7098
  this._config.states.maxQueue = this._config.states.maxQueue || 1e3;
@@ -6032,7 +7518,8 @@ class AdapterClass extends import_node_events.EventEmitter {
6032
7518
  }
6033
7519
  }
6034
7520
  if (!this._stopInProgress) {
6035
- typeof this._options.objectChange === "function" && setImmediate(() => this._options.objectChange(id, obj));
7521
+ typeof this._options.objectChange === "function" && // @ts-expect-error
7522
+ setImmediate(() => this._options.objectChange(id, obj));
6036
7523
  setImmediate(() => this.emit("objectChange", id, obj));
6037
7524
  }
6038
7525
  }
@@ -6049,6 +7536,9 @@ class AdapterClass extends import_node_events.EventEmitter {
6049
7536
  }
6050
7537
  });
6051
7538
  }
7539
+ /**
7540
+ * Called if states and objects successfully initialized
7541
+ */
6052
7542
  async _prepareInitAdapter() {
6053
7543
  if (this.terminated || !this.#objects || !this.#states) {
6054
7544
  return;
@@ -6085,6 +7575,11 @@ class AdapterClass extends import_node_events.EventEmitter {
6085
7575
  }
6086
7576
  }
6087
7577
  }
7578
+ /**
7579
+ * Initialize the adapter
7580
+ *
7581
+ * @param adapterConfig the AdapterOptions or the InstanceObject, is null/undefined if it is install process
7582
+ */
6088
7583
  async _initAdapter(adapterConfig) {
6089
7584
  await this._initLogging();
6090
7585
  if (!this.pluginHandler) {
@@ -6148,6 +7643,7 @@ class AdapterClass extends import_node_events.EventEmitter {
6148
7643
  name = this.name;
6149
7644
  instance = 0;
6150
7645
  adapterConfig = adapterConfig || {
7646
+ // @ts-expect-error protectedNative exists on instance objects
6151
7647
  common: { mode: "once", name, protectedNative: [] },
6152
7648
  native: {}
6153
7649
  };
@@ -6170,7 +7666,11 @@ class AdapterClass extends import_node_events.EventEmitter {
6170
7666
  this.config = adapterConfig.native;
6171
7667
  this.host = adapterConfig.common.host;
6172
7668
  this.common = adapterConfig.common;
6173
- if (adapterConfig.common.mode === "schedule" || adapterConfig.common.mode === "once") {
7669
+ if (
7670
+ // @ts-expect-error
7671
+ adapterConfig.common.mode === "schedule" || // @ts-expect-error
7672
+ adapterConfig.common.mode === "once"
7673
+ ) {
6174
7674
  this.stop = (params) => this._stop({ ...params, isPause: true });
6175
7675
  } else if (this.startedInCompactMode) {
6176
7676
  this.stop = (params) => this._stop({ ...params, isPause: false });
@@ -6179,7 +7679,8 @@ class AdapterClass extends import_node_events.EventEmitter {
6179
7679
  this.stop = (params) => this._stop({ ...params, isPause: false });
6180
7680
  }
6181
7681
  this.#states.subscribe(`${import_constants2.SYSTEM_ADAPTER_PREFIX}*.logging`);
6182
- if (typeof this._options.message === "function" && !(0, import_utils.isMessageboxSupported)(adapterConfig.common)) {
7682
+ if (typeof this._options.message === "function" && // @ts-expect-error, we should infer correctly that this is an InstanceObject in this case
7683
+ !(0, import_utils.isMessageboxSupported)(adapterConfig.common)) {
6183
7684
  this._logger.error(`${this.namespaceLog} : message handler implemented, but messagebox not enabled. Define common.messagebox in io-package.json for adapter or delete message handler.`);
6184
7685
  } else if ((0, import_utils.isMessageboxSupported)(adapterConfig.common)) {
6185
7686
  this.mboxSubscribed = true;
@@ -6294,6 +7795,9 @@ class AdapterClass extends import_node_events.EventEmitter {
6294
7795
  this.adapterReady = true;
6295
7796
  }
6296
7797
  }
7798
+ /**
7799
+ * Calls the ready handler, if it is an install run it calls the install handler instead
7800
+ */
6297
7801
  _callReadyHandler() {
6298
7802
  if (this._config.isInstall && (typeof this._options.install === "function" || this.listeners("install").length)) {
6299
7803
  if (typeof this._options.install === "function") {
@@ -6460,6 +7964,12 @@ class AdapterClass extends import_node_events.EventEmitter {
6460
7964
  setImmediate(() => this._extendObjects(tasks, callback));
6461
7965
  }
6462
7966
  }
7967
+ /**
7968
+ * Replaces forbidden chars in an id if present
7969
+ * Additionally logs a warning
7970
+ *
7971
+ * @param id the id which will be replaced
7972
+ */
6463
7973
  fixForbiddenCharsInId(id) {
6464
7974
  const mId = id.replace(FORBIDDEN_CHARS, "_");
6465
7975
  if (mId !== id) {
@@ -6467,6 +7977,11 @@ class AdapterClass extends import_node_events.EventEmitter {
6467
7977
  }
6468
7978
  return mId;
6469
7979
  }
7980
+ /**
7981
+ * This method reports deprecations via Sentry (controller own instance) and can only be used internally
7982
+ *
7983
+ * @param options information about version to remove feature and the log message
7984
+ */
6470
7985
  async reportDeprecation(options) {
6471
7986
  if (!this.#states) {
6472
7987
  throw new Error(import_js_controller_common.tools.ERRORS.ERROR_DB_CLOSED);
@@ -6493,13 +8008,18 @@ class AdapterClass extends import_node_events.EventEmitter {
6493
8008
  };
6494
8009
  await this.#states.pushMessage(`system.host.${this.host}`, obj);
6495
8010
  }
8011
+ /**
8012
+ * Initialize the plugin handler for this adapter
8013
+ */
6496
8014
  _initPluginHandler() {
6497
8015
  const pluginSettings = {
6498
8016
  scope: "adapter",
6499
8017
  namespace: `system.adapter.${this.namespace}`,
6500
8018
  logNamespace: this.namespaceLog,
8019
+ // @ts-expect-error
6501
8020
  log: this._logger,
6502
8021
  iobrokerConfig: this._config,
8022
+ // @ts-expect-error
6503
8023
  parentPackage: this.pack,
6504
8024
  controllerVersion
6505
8025
  };
@@ -6510,6 +8030,9 @@ class AdapterClass extends import_node_events.EventEmitter {
6510
8030
  this._logger.error(`Could not add plugins: ${e.message}`);
6511
8031
  }
6512
8032
  }
8033
+ /**
8034
+ * Initializes the adapter
8035
+ */
6513
8036
  async _init() {
6514
8037
  const _initDBs = () => {
6515
8038
  this._initObjects(() => {