iobroker.iot 3.5.2 → 4.0.1

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 (111) hide show
  1. package/README.md +24 -9
  2. package/admin/assets/index-Y479CE6x.js +681 -0
  3. package/admin/index_m.html +1 -1
  4. package/admin/rules/assets/{ActionVisu-D9x2f6zu.js → ActionVisu-DE8dgNVF.js} +1 -1
  5. package/admin/rules/assets/{ActionVisu__loadShare__react__loadShare__-Cg21Ef1U.js → ActionVisu__loadShare__react__loadShare__-BKaC-p5K.js} +1 -1
  6. package/admin/rules/assets/{ActionVisu__loadShare__react_mf_2_dom__loadShare__-B1zRWn0u.js → ActionVisu__loadShare__react_mf_2_dom__loadShare__-Bs1o8DtQ.js} +2 -2
  7. package/admin/rules/assets/ActionVisu__mf_v__runtimeInit__mf_v__-DtUoI3FU.js +5 -0
  8. package/admin/rules/assets/bootstrap-Ba57tu25.js +1 -0
  9. package/admin/rules/assets/hostInit-hos3Txsy.js +1 -1
  10. package/admin/rules/assets/{index-Duo7mFlZ.js → index-CbxmbJvB.js} +2 -2
  11. package/admin/rules/assets/{index-CAAeiKCc.js → index-DjPMvPni.js} +2 -2
  12. package/admin/rules/assets/index-_Y2FN5EZ.js +1152 -0
  13. package/admin/rules/assets/{virtualExposes-BqVak7rX.js → virtualExposes-BNZJTatg.js} +2 -2
  14. package/admin/rules/customRuleBlocks.js +2 -2
  15. package/io-package.json +27 -27
  16. package/package.json +17 -14
  17. package/admin/assets/index-Df2NS929.js +0 -681
  18. package/admin/rules/assets/ActionVisu__mf_v__runtimeInit__mf_v__-Cz053nO7.js +0 -10
  19. package/admin/rules/assets/bootstrap-BCFKIiwZ.js +0 -1
  20. package/admin/rules/assets/index-BwcOGyWI.js +0 -1152
  21. package/lib/AlexaSmartHomeV3/Alexa/AlexaResponse.js +0 -262
  22. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/Base.js +0 -124
  23. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js +0 -15
  24. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js +0 -10
  25. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js +0 -15
  26. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js +0 -10
  27. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js +0 -10
  28. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ModeController.js +0 -69
  29. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js +0 -10
  30. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js +0 -10
  31. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js +0 -15
  32. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js +0 -20
  33. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js +0 -10
  34. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js +0 -34
  35. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js +0 -14
  36. package/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js +0 -27
  37. package/lib/AlexaSmartHomeV3/Alexa/Directives/ChangeReport.js +0 -75
  38. package/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js +0 -39
  39. package/lib/AlexaSmartHomeV3/Alexa/Directives/ReportState.js +0 -50
  40. package/lib/AlexaSmartHomeV3/Alexa/Directives/index.js +0 -13
  41. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js +0 -38
  42. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js +0 -55
  43. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js +0 -56
  44. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js +0 -14
  45. package/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js +0 -11
  46. package/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js +0 -108
  47. package/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js +0 -14
  48. package/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js +0 -40
  49. package/lib/AlexaSmartHomeV3/Alexa/Properties/ColorTemperatureInKelvin.js +0 -62
  50. package/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js +0 -22
  51. package/lib/AlexaSmartHomeV3/Alexa/Properties/LockState.js +0 -40
  52. package/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js +0 -32
  53. package/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js +0 -17
  54. package/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js +0 -14
  55. package/lib/AlexaSmartHomeV3/Alexa/Properties/PowerState.js +0 -25
  56. package/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js +0 -28
  57. package/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js +0 -20
  58. package/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js +0 -52
  59. package/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js +0 -19
  60. package/lib/AlexaSmartHomeV3/Alexa/Properties/index.js +0 -14
  61. package/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js +0 -22
  62. package/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js +0 -28
  63. package/lib/AlexaSmartHomeV3/Controls/AirCondition.js +0 -144
  64. package/lib/AlexaSmartHomeV3/Controls/Blind.js +0 -12
  65. package/lib/AlexaSmartHomeV3/Controls/ContactSensor.js +0 -17
  66. package/lib/AlexaSmartHomeV3/Controls/Control.js +0 -352
  67. package/lib/AlexaSmartHomeV3/Controls/Ct.js +0 -172
  68. package/lib/AlexaSmartHomeV3/Controls/Dimmer.js +0 -124
  69. package/lib/AlexaSmartHomeV3/Controls/Door.js +0 -9
  70. package/lib/AlexaSmartHomeV3/Controls/Gate.js +0 -42
  71. package/lib/AlexaSmartHomeV3/Controls/Hue.js +0 -207
  72. package/lib/AlexaSmartHomeV3/Controls/Light.js +0 -54
  73. package/lib/AlexaSmartHomeV3/Controls/Lock.js +0 -36
  74. package/lib/AlexaSmartHomeV3/Controls/Motion.js +0 -17
  75. package/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js +0 -25
  76. package/lib/AlexaSmartHomeV3/Controls/Slider.js +0 -10
  77. package/lib/AlexaSmartHomeV3/Controls/Socket.js +0 -21
  78. package/lib/AlexaSmartHomeV3/Controls/Temperature.js +0 -22
  79. package/lib/AlexaSmartHomeV3/Controls/Thermostat.js +0 -86
  80. package/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js +0 -28
  81. package/lib/AlexaSmartHomeV3/Controls/Volume.js +0 -109
  82. package/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js +0 -9
  83. package/lib/AlexaSmartHomeV3/Controls/Window.js +0 -9
  84. package/lib/AlexaSmartHomeV3/Controls/index.js +0 -14
  85. package/lib/AlexaSmartHomeV3/Device.js +0 -84
  86. package/lib/AlexaSmartHomeV3/DeviceManager.js +0 -415
  87. package/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js +0 -8
  88. package/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js +0 -5
  89. package/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js +0 -5
  90. package/lib/AlexaSmartHomeV3/Helpers/AdapterProvider.js +0 -46
  91. package/lib/AlexaSmartHomeV3/Helpers/FileHelper.js +0 -70
  92. package/lib/AlexaSmartHomeV3/Helpers/IotProxy.js +0 -44
  93. package/lib/AlexaSmartHomeV3/Helpers/Logger.js +0 -95
  94. package/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js +0 -82
  95. package/lib/AlexaSmartHomeV3/Helpers/Utils.js +0 -583
  96. package/lib/Utils.js +0 -608
  97. package/lib/adminCommonSocket.js +0 -781
  98. package/lib/alexaCustom.js +0 -622
  99. package/lib/alexaSmartHomeV2.js +0 -2792
  100. package/lib/alexaSmartHomeV3.js +0 -117
  101. package/lib/alisa.js +0 -2412
  102. package/lib/devices.js +0 -20
  103. package/lib/functions.js +0 -21
  104. package/lib/googleHome.js +0 -3323
  105. package/lib/notifications.js +0 -37
  106. package/lib/remote.js +0 -1363
  107. package/lib/rooms.js +0 -45
  108. package/lib/texts.js +0 -79
  109. package/lib/translate.js +0 -19
  110. package/lib/visuApp.js +0 -157
  111. package/main.js +0 -1444
package/lib/remote.js DELETED
@@ -1,1363 +0,0 @@
1
- const MESSAGE_TYPES = {
2
- MESSAGE: 0,
3
- PING: 1,
4
- PONG: 2,
5
- CALLBACK: 3,
6
- READY: 4,
7
- WAIT: 5,
8
- SENDING_DONE: 6,
9
- MISSING: 7,
10
- TIMEOUT: 8,
11
- HTML: 9,
12
- COMBINED_CALLBACK: 10,
13
- COMBINED_MESSAGE: 11,
14
- };
15
-
16
- let axios;
17
- let zlib;
18
- let AdminSocket;
19
-
20
- const MAX_IOT_MESSAGE_LENGTH = 127 * 1024;
21
- const MAX_POST_MESSAGE_LENGTH = 127 * 1024;
22
- const MAX_FILE_SIZE = 4 * 1024 * 1024;
23
-
24
- const COLLECT_OBJS_MS = 400;
25
- const COLLECT_STATES_MS = 400;
26
- const COLLECT_LOGS_MS = 800;
27
-
28
- const NONE = '___none___';
29
-
30
- class RemoteAccess {
31
- constructor(adapter, clientId) {
32
- this.adapter = adapter;
33
- this.device = null;
34
- this.gcInterval = null;
35
-
36
- if (!this.adapter.config.remote) {
37
- return;
38
- }
39
-
40
- axios = require('axios');
41
- zlib = require('node:zlib');
42
- AdminSocket = require('./adminCommonSocket');
43
-
44
- this.name = {};
45
- this.objects = {};
46
- this.packets = {};
47
- this.clientId = clientId;
48
- this.statesCache = {};
49
- this.listOfLogs = [];
50
- this.listOfStates = { ids: [], states: [] };
51
- this.listOfObjects = { ids: [], objs: [] };
52
- this.collectStatesMs =
53
- adapter.config.collectStatesMs === undefined
54
- ? COLLECT_STATES_MS
55
- : parseInt(adapter.config.collectStatesMs, 10);
56
- this.collectObjectsMs =
57
- adapter.config.collectObjectsMs === undefined
58
- ? COLLECT_OBJS_MS
59
- : parseInt(adapter.config.collectObjectsMs, 10);
60
- this.collectLogsMs =
61
- adapter.config.collectLogsMs === undefined ? COLLECT_LOGS_MS : parseInt(adapter.config.collectLogsMs, 10);
62
-
63
- this.handlers = {
64
- getObject: { f: this.adapter.getForeignObjectAsync.bind(this.adapter), args: 1 },
65
- setObject: { f: this.adapter.setForeignObjectAsync.bind(this.adapter), args: 2 },
66
- getState: { f: this.adapter.getForeignStateAsync.bind(this.adapter), args: 1 },
67
- setState: { f: this.adapter.setForeignStateAsync.bind(this.adapter), args: 2 },
68
- delState: { f: this.adapter.delForeignStateAsync.bind(this.adapter), args: 2 },
69
- getObjectView: { f: this.adapter.getObjectViewAsync.bind(this.adapter), args: 4 },
70
- delObject: { f: this.adapter.delForeignObjectAsync.bind(this.adapter), args: 2 },
71
- delObjects: { f: this.adapter.delForeignObjectAsync.bind(this.adapter), args: 2 },
72
- extendObject: { f: this.adapter.extendForeignObjectAsync.bind(this.adapter), args: 2 },
73
- getForeignStates: { f: this.adapter.getForeignStatesAsync.bind(this.adapter), args: 1 },
74
- getForeignObjects: { f: this.adapter.getForeignObjectsAsync.bind(this.adapter), args: 2 },
75
- fileExists: { f: this.adapter.fileExistsAsync.bind(this.adapter), args: 2 },
76
- chownFile: { f: this.adapter.chownFileAsync.bind(this.adapter), args: 3 },
77
- chmodFile: { f: this.adapter.chmodFileAsync.bind(this.adapter), args: 3 },
78
- deleteFolder: { f: this.adapter.unlinkAsync.bind(this.adapter), args: 2 },
79
- deleteFile: { f: this.adapter.unlinkAsync.bind(this.adapter), args: 2 },
80
- mkdir: { f: this.adapter.mkdirAsync.bind(this.adapter), args: 2 },
81
- renameFile: { f: this.adapter.renameAsync.bind(this.adapter), args: 3 },
82
- readDir: { f: this.adapter.readDirAsync.bind(this.adapter), args: 2 },
83
- changePassword: { f: this.adapter.setPasswordAsync.bind(this.adapter), args: 2 },
84
- };
85
-
86
- this.subscribes = {};
87
- this.sockets = {};
88
-
89
- if (this.adapter.config.remoteAdminInstance) {
90
- try {
91
- this.localAdmin = require
92
- .resolve('iobroker.admin')
93
- .replace(/\\/g, '/')
94
- .replace(/main\.js$/, 'www-react');
95
- } catch (error) {
96
- this.localAdmin = null;
97
- this.adapter.log.warn('[REMOTE] Cannot read admin files while iobroker.admin was not found');
98
- }
99
- this.adapter
100
- .getForeignObjectAsync(`system.adapter.${this.adapter.config.remoteAdminInstance}`)
101
- .then(obj => {
102
- this.adminObj = obj;
103
- if (obj && obj.native && !obj.native.auth) {
104
- this.adminUrl = `${obj.native.secure ? 'https:' : 'http:'}//localhost:${obj.native.port}`;
105
- }
106
- });
107
- }
108
- if (this.adapter.config.remoteWebInstance) {
109
- this.adapter.getForeignObjectAsync(`system.adapter.${this.adapter.config.remoteWebInstance}`).then(obj => {
110
- this.webObj = obj;
111
- if (obj && obj.native && !obj.native.auth) {
112
- this.webUrl = `${obj.native.secure ? 'https:' : 'http:'}//localhost:${obj.native.port}`;
113
- }
114
- });
115
- }
116
-
117
- this.vendorPrefix = '';
118
-
119
- this.adapter.getForeignObjectAsync('system.meta.uuid').then(obj => {
120
- if (obj && obj.native) {
121
- this.vendorPrefix = obj.native.uuid.length > 36 ? obj.native.uuid.substring(0, 2) : '';
122
- }
123
- });
124
- }
125
-
126
- setLanguage(_lang) {
127
- this.lang = _lang || 'de';
128
- }
129
-
130
- registerDevice(device) {
131
- this.device = device;
132
- }
133
-
134
- async _sendCachedStates() {
135
- const sids = Object.keys(this.sockets);
136
-
137
- const listOfStates = this.listOfStates;
138
- // clear cache
139
- this.listOfStates = { ids: [], states: [] };
140
-
141
- if (sids.length) {
142
- this.adapter.log.debug(
143
- `Send to ${sids.length} sockets: ${listOfStates.ids.map((id, i) => `${id}: ${listOfStates.states[i].val}`).join(', ')}`,
144
- );
145
-
146
- // pack the data
147
- const data = JSON.stringify([listOfStates.ids, listOfStates.states]);
148
- const args = zlib.deflateSync(data).toString('base64');
149
-
150
- for (let s = 0; s < sids.length; s++) {
151
- const error = await this._sendEvent({ name: 'stateChange', args, sid: sids[s], multi: true });
152
- if (error) {
153
- this.adapter.log.warn(`[REMOTE] cannot send "stateChange": ${JSON.stringify(error)}`);
154
- }
155
- }
156
- }
157
- }
158
-
159
- updateState(id, state) {
160
- if (!this.adapter.config.remote) {
161
- return;
162
- }
163
- const cache = JSON.stringify(state);
164
-
165
- if (this.statesCache[id] && this.statesCache[id] !== cache) {
166
- this.adapter.config.debug &&
167
- this.adapter.log.debug(`[REMOTE] send stateChange "${id}": ${JSON.stringify(state)}`);
168
-
169
- this.statesCache[id] = cache;
170
-
171
- this.listOfStates.ids.push(id);
172
- this.listOfStates.states.push(JSON.parse(JSON.stringify(state)));
173
-
174
- // do not wait if the list will be too long
175
- if (this.listOfStates.ids.length > 70) {
176
- this.sendObjectsTimeout && clearTimeout(this.sendObjectsTimeout);
177
- this.sendObjectsTimeout = null;
178
- this._sendCachedStates().catch(e => this.adapter.log.error(`[REMOTE] Cannot send cached states: ${e}`));
179
- } else {
180
- this.sendObjectsTimeout =
181
- this.sendObjectsTimeout ||
182
- setTimeout(() => {
183
- this.sendObjectsTimeout = null;
184
- this._sendCachedStates().catch(e =>
185
- this.adapter.log.error(`[REMOTE] Cannot send cached states: ${e}`),
186
- );
187
- }, this.collectStatesMs);
188
- }
189
- } else {
190
- // this.adapter.log.debug(`[REMOTE] ignore stateChange "${id}": ${JSON.stringify(state)}`);
191
- }
192
- }
193
-
194
- updateObject(id, obj) {
195
- if (!this.adapter.config.remote) {
196
- return;
197
- }
198
- this.listOfObjects.ids.push(id);
199
- this.listOfObjects.objs.push(JSON.parse(JSON.stringify(obj)));
200
-
201
- this.sendObjectsTimeout && clearTimeout(this.sendObjectsTimeout);
202
-
203
- this.sendObjectsTimeout = setTimeout(async () => {
204
- this.sendObjectsTimeout = null;
205
- const listOfObjects = this.listOfObjects;
206
- this.listOfObjects = { ids: [], objs: [] };
207
- const sids = Object.keys(this.sockets);
208
-
209
- for (let s = 0; s < sids.length; s++) {
210
- const error = await this._sendEvent({
211
- name: 'objectChange',
212
- args: [listOfObjects.ids, listOfObjects.objs],
213
- sid: sids[s],
214
- multi: true,
215
- });
216
- if (error) {
217
- this.adapter.log.warn(`[REMOTE] cannot send "objectChange": ${JSON.stringify(error)}`);
218
- }
219
- }
220
- }, COLLECT_OBJS_MS);
221
- }
222
-
223
- onLog(obj) {
224
- if (!this.adapter.config.remote) {
225
- return;
226
- }
227
- this.listOfLogs.push(obj);
228
-
229
- this.sendLogsTimeout && clearTimeout(this.sendLogsTimeout);
230
-
231
- this.sendLogsTimeout = setTimeout(async () => {
232
- this.sendLogsTimeout = null;
233
- const listOfLogs = this.listOfLogs;
234
- this.listOfLogs = [];
235
- const sids = Object.keys(this.sockets);
236
- for (let s = 0; s < sids.length; s++) {
237
- const error = await this._sendEvent({ name: 'log', args: [listOfLogs], sid: sids[s], multi: true });
238
- if (error) {
239
- this.adapter.log.error(`[REMOTE] cannot send "log": ${JSON.stringify(error)}`);
240
- }
241
- }
242
- }, COLLECT_LOGS_MS);
243
- }
244
-
245
- destroy() {
246
- this.gcInterval && clearInterval(this.gcInterval);
247
- this.gcInterval = null;
248
- this.sendLogsTimeout && clearTimeout(this.sendLogsTimeout);
249
- this.sendLogsTimeout = null;
250
- this.sendObjectsTimeout && clearTimeout(this.sendObjectsTimeout);
251
- this.sendObjectsTimeout = null;
252
- this.sendStatesTimeout && clearTimeout(this.sendStatesTimeout);
253
- this.sendStatesTimeout = null;
254
- AdminSocket.stopGB();
255
- this._unsubscribeAll();
256
- this.sockets = null;
257
- }
258
-
259
- _clearMemory() {
260
- const now = Date.now();
261
- const DAY = 36000000 * 3;
262
- Object.keys(this.sockets).forEach(sid => {
263
- if (now - this.sockets[sid].ts > DAY) {
264
- this._unsubscribeSocket(sid, 'stateChange');
265
- this._unsubscribeSocket(sid, 'objectChange');
266
- this._unsubscribeSocket(sid, 'log');
267
- delete this.sockets[sid];
268
- }
269
- });
270
-
271
- Object.keys(this.packets).forEach(id => {
272
- if (now - this.packets[id].ts > 120000) {
273
- delete this.packets[id];
274
- }
275
- });
276
- }
277
-
278
- _readAllObjects() {
279
- return this.adapter.getObjectListAsync({ include_docs: true }).then(res => {
280
- const objects = {};
281
- this.adapter.log.info('[REMOTE] received all objects');
282
- if (res) {
283
- res = res.rows;
284
-
285
- for (let i = 0; i < res.length; i++) {
286
- objects[res[i].doc._id] = res[i].doc;
287
- }
288
- }
289
- return objects;
290
- });
291
- }
292
-
293
- pattern2RegEx(pattern) {
294
- if (!pattern || typeof pattern !== 'string') {
295
- return null;
296
- }
297
- if (pattern !== '*') {
298
- if (pattern[0] === '*' && pattern[pattern.length - 1] !== '*') {
299
- pattern += '$';
300
- }
301
- if (pattern[0] !== '*' && pattern[pattern.length - 1] === '*') {
302
- pattern = `^${pattern}`;
303
- }
304
- }
305
- pattern = pattern.replace(/\./g, '\\.');
306
- pattern = pattern.replace(/\*/g, '.*');
307
- pattern = pattern.replace(/\[/g, '\\[');
308
- pattern = pattern.replace(/]/g, '\\]');
309
- pattern = pattern.replace(/\(/g, '\\(');
310
- pattern = pattern.replace(/\)/g, '\\)');
311
- return pattern;
312
- }
313
-
314
- _subscribe(sid, type, pattern) {
315
- //console.log((socket._name || socket.id) + ' subscribe ' + pattern);
316
- const socket = this.sockets[sid];
317
-
318
- this.subscribes[type] = this.subscribes[type] || {};
319
-
320
- let s;
321
- if (socket) {
322
- s = socket._subscribe[type] = socket._subscribe[type] || [];
323
- for (let i = 0; i < s.length; i++) {
324
- if (s[i].pattern === pattern) {
325
- return;
326
- }
327
- }
328
- }
329
-
330
- let p = this.pattern2RegEx(pattern);
331
- if (p === null) {
332
- return this.adapter.log.warn('[REMOTE] Empty or invalid pattern on subscribe!');
333
- }
334
- if (socket) {
335
- s.push({ pattern: pattern, regex: new RegExp(p) });
336
- }
337
-
338
- if (this.subscribes[type][pattern] === undefined) {
339
- this.subscribes[type][pattern] = 1;
340
- if (type === 'stateChange') {
341
- this.adapter.log.debug(`[REMOTE] Subscribe STATES: ${pattern}`);
342
- this.adapter.subscribeForeignStates(pattern);
343
- } else if (type === 'objectChange') {
344
- this.adapter.log.debug(`[REMOTE] Subscribe OBJECTS: ${pattern}`);
345
- return this.adapter.subscribeForeignObjects && this.adapter.subscribeForeignObjects(pattern);
346
- } else if (type === 'log') {
347
- this.adapter.log.debug('[REMOTE] Subscribe LOGS');
348
- this.adapter.requireLog && this.adapter.requireLog(true);
349
- }
350
- } else {
351
- this.subscribes[type][pattern]++;
352
- }
353
- }
354
-
355
- _showSubscribes(sid, type) {
356
- const socket = this.sockets[sid];
357
-
358
- if (socket && socket._subscribe) {
359
- const s = socket._subscribe[type] || [];
360
- const ids = [];
361
- for (let i = 0; i < s.length; i++) {
362
- ids.push(s[i].pattern);
363
- }
364
- this.adapter.log.debug(`[REMOTE] Subscribes: ${ids.join(', ')}`);
365
- } else {
366
- this.adapter.log.debug('[REMOTE] Subscribes: no subscribes');
367
- }
368
- }
369
-
370
- _updateConnectedInfo() {
371
- if (this.infoTimeout) {
372
- clearTimeout(this.infoTimeout);
373
- this.infoTimeout = null;
374
- }
375
-
376
- // TODO
377
- // this.adapter.setState('info.connection', text, true);
378
- }
379
-
380
- _unsubscribe(sid, type, pattern) {
381
- const socket = this.sockets[sid];
382
- this.subscribes[type] = this.subscribes[type] || {};
383
-
384
- if (socket && typeof socket === 'object') {
385
- if (!socket._subscribe || !socket._subscribe[type]) {
386
- return;
387
- }
388
-
389
- for (let i = socket._subscribe[type].length - 1; i >= 0; i--) {
390
- if (socket._subscribe[type][i].pattern === pattern) {
391
- // Remove pattern from global list
392
- if (this.subscribes[type][pattern] !== undefined) {
393
- this.subscribes[type][pattern]--;
394
- if (this.subscribes[type][pattern] <= 0) {
395
- if (type === 'stateChange') {
396
- this.adapter.log.debug(`[REMOTE] Unsubscribe STATES: ${pattern}`);
397
- //console.log((socket._name || socket.id) + ' unsubscribeForeignStates ' + pattern);
398
- this.adapter.unsubscribeForeignStates(pattern);
399
- } else if (type === 'objectChange') {
400
- this.adapter.log.debug(`[REMOTE] Unsubscribe OBJECTS: ${pattern}`);
401
- //console.log((socket._name || socket.id) + ' unsubscribeForeignObjects ' + pattern);
402
- this.adapter.unsubscribeForeignObjects &&
403
- this.adapter.unsubscribeForeignObjects(pattern);
404
- } else if (type === 'log') {
405
- //console.log((socket._name || socket.id) + ' requireLog false');
406
- this.adapter.log.debug('[REMOTE] Unsubscribe LOGS');
407
- this.adapter.requireLog && this.adapter.requireLog(false);
408
- }
409
- delete this.subscribes[type][pattern];
410
- }
411
- }
412
-
413
- delete socket._subscribe[type][i];
414
- socket._subscribe[type].splice(i, 1);
415
- return;
416
- }
417
- }
418
- } else {
419
- // Remove pattern from global list
420
- if (this.subscribes[type][pattern] !== undefined) {
421
- this.subscribes[type][pattern]--;
422
- if (this.subscribes[type][pattern] <= 0) {
423
- if (type === 'stateChange') {
424
- this.adapter.log.debug(`[REMOTE] Unsubscribe STATES: ${pattern}`);
425
- this.adapter.unsubscribeForeignStates(pattern);
426
- } else if (type === 'objectChange') {
427
- this.adapter.log.debug(`[REMOTE] Unsubscribe OBJECTS: ${pattern}`);
428
- this.adapter.unsubscribeForeignObjects && this.adapter.unsubscribeForeignObjects(pattern);
429
- } else if (type === 'log') {
430
- this.adapter.log.debug('[REMOTE] Unsubscribe LOGS');
431
- this.adapter.requireLog && this.adapter.requireLog(false);
432
- }
433
- delete this.subscribes[type][pattern];
434
- }
435
- }
436
- }
437
- }
438
-
439
- _unsubscribeAll() {
440
- Object.keys(this.sockets).forEach(sid => {
441
- this._unsubscribe(sid, 'stateChange');
442
- this._unsubscribe(sid, 'objectChange');
443
- this._unsubscribe(sid, 'log');
444
- });
445
- }
446
-
447
- _unsubscribeSocket(sid, type) {
448
- const socket = this.sockets[sid];
449
-
450
- if (!socket || !socket._subscribe || !socket._subscribe[type]) {
451
- return;
452
- }
453
-
454
- for (let i = 0; i < socket._subscribe[type].length; i++) {
455
- const pattern = socket._subscribe[type][i].pattern;
456
- if (this.subscribes[type][pattern] !== undefined) {
457
- this.subscribes[type][pattern]--;
458
- if (this.subscribes[type][pattern] <= 0) {
459
- if (type === 'stateChange') {
460
- this.adapter.log.debug(`[REMOTE] Unsubscribe STATES: ${pattern}`);
461
- this.adapter.unsubscribeForeignStates(pattern);
462
- } else if (type === 'objectChange') {
463
- this.adapter.log.debug(`[REMOTE] Unsubscribe OBJECTS: ${pattern}`);
464
- this.adapter.unsubscribeForeignObjects && this.adapter.unsubscribeForeignObjects(pattern);
465
- } else if (type === 'log') {
466
- this.adapter.log.debug(`[REMOTE] Unsubscribe LOGS: ${pattern}`);
467
- this.adapter.requireLog && this.adapter.requireLog(false);
468
- }
469
- delete this.subscribes[type][pattern];
470
- }
471
- }
472
- }
473
- }
474
-
475
- _subscribeSocket(sid, type) {
476
- const socket = this.sockets[sid];
477
-
478
- if (!socket || !socket._subscribe || !socket._subscribe[type]) {
479
- return;
480
- }
481
-
482
- for (let i = 0; i < socket._subscribe[type].length; i++) {
483
- const pattern = socket._subscribe[type][i].pattern;
484
- if (this.subscribes[type][pattern] === undefined) {
485
- this.subscribes[type][pattern] = 1;
486
- if (type === 'stateChange') {
487
- this.adapter.log.debug(`[REMOTE] Subscribe STATES: ${pattern}`);
488
- this.adapter.subscribeForeignStates(pattern);
489
- } else if (type === 'objectChange') {
490
- this.adapter.log.debug(`[REMOTE] Subscribe OBJECTS: ${pattern}`);
491
- this.adapter.subscribeForeignObjects && this.adapter.subscribeForeignObjects(pattern);
492
- } else if (type === 'log') {
493
- this.adapter.log.debug('[REMOTE] Subscribe LOGS');
494
- this.adapter.requireLog && this.adapter.requireLog(true);
495
- }
496
- } else {
497
- this.subscribes[type][pattern]++;
498
- }
499
- }
500
- }
501
-
502
- _sendEvent(message, _originalMessage) {
503
- return axios
504
- .post('https://remote-events.iobroker.in/', message, {
505
- validateStatus: status => status === 200,
506
- timeout: 5000,
507
- })
508
- .then(response => {
509
- // console.log(response.data || response.status);
510
- return false;
511
- })
512
- .catch(error => {
513
- let errorMessage;
514
- if (error.response) {
515
- errorMessage = error.response.data || error.response.status;
516
- } else {
517
- errorMessage = error.message;
518
- }
519
-
520
- this.adapter.log.warn(
521
- `[REMOTE] Cannot send status update to ${message.sid} (${JSON.stringify(_originalMessage)}): ${JSON.stringify(errorMessage)}`,
522
- );
523
-
524
- if (errorMessage.error === 'invalid connectionId') {
525
- if (this.sockets[message.sid]) {
526
- this.adapter.log.debug(`[REMOTE] delete connection id ${message.sid}`);
527
- delete this.sockets[message.sid];
528
- }
529
- errorMessage = false;
530
- } else {
531
- this.adapter.log.warn(
532
- `[REMOTE] Cannot send status update to "${message.sid}" (${JSON.stringify(_originalMessage)}): ${JSON.stringify(errorMessage)}`,
533
- );
534
- }
535
-
536
- return errorMessage;
537
- });
538
- }
539
-
540
- async _getStatesManyArgs(args) {
541
- const response = [];
542
- for (let a = 0; a < args.length; a++) {
543
- const id = args[a][0];
544
- try {
545
- const result = await this.adapter.getForeignStatesAsync(id || '*');
546
- response[a] = [null, result];
547
- result && Object.keys(result).forEach(id => (this.statesCache[id] = result[id]));
548
- } catch (error) {
549
- response[a] = [error];
550
- }
551
- }
552
- return response;
553
- }
554
-
555
- async _getStateManyArgs(args) {
556
- const response = [];
557
- for (let a = 0; a < args.length; a++) {
558
- const id = args[a][0];
559
- try {
560
- const result = await this.adapter.getForeignStateAsync(id || '*');
561
- response[a] = [null, result];
562
- this.statesCache[id] = result;
563
- } catch (error) {
564
- response[a] = [error];
565
- }
566
- }
567
- return response;
568
- }
569
-
570
- async _getObjectManyArgs(args) {
571
- const response = [];
572
- for (let a = 0; a < args.length; a++) {
573
- const id = args[a][0];
574
- try {
575
- const result = await this.adapter.getForeignObjectAsync(id || '*');
576
- response[a] = [null, result];
577
- this.statesCache[id] = result;
578
- } catch (error) {
579
- response[a] = [error];
580
- }
581
- }
582
- return response;
583
- }
584
-
585
- async _subscribeManyArgs(sid, args) {
586
- const response = [];
587
- for (let a = 0; a < args.length; a++) {
588
- const pattern = args[a][0];
589
- if (pattern && typeof pattern === 'object' && pattern instanceof Array) {
590
- for (let p = 0; p < pattern.length; p++) {
591
- this._subscribe(sid, 'stateChange', pattern[p]);
592
- }
593
- } else {
594
- this._subscribe(sid, 'stateChange', pattern);
595
- }
596
- }
597
- return response;
598
- }
599
-
600
- async _unsubscribeManyArgs(sid, args) {
601
- const response = [];
602
- for (let a = 0; a < args.length; a++) {
603
- const pattern = args[a][0];
604
- if (pattern && typeof pattern === 'object' && pattern instanceof Array) {
605
- for (let p = 0; p < pattern.length; p++) {
606
- this._unsubscribe(sid, 'stateChange', pattern[p]);
607
- }
608
- } else {
609
- this._unsubscribe(sid, 'stateChange', pattern);
610
- }
611
- }
612
- return response;
613
- }
614
-
615
- uploadToServer(url, data, raw) {
616
- return axios
617
- .put(url, raw ? data.file : Buffer.from(data.file, 'base64'), {
618
- headers: {
619
- 'Content-Type': data.mimeType,
620
- },
621
- })
622
- .then(() => {
623
- return true;
624
- })
625
- .catch(e => {
626
- console.log(e);
627
- return false;
628
- });
629
- }
630
-
631
- readUrlFile(url, path, sid, type, id) {
632
- return url
633
- ? axios(url + path, { responseType: 'arraybuffer', validateStatus: status => status === 200, timeout: 500 })
634
- .then(response => {
635
- // replace port
636
- if (path.endsWith('_socket/info.js')) {
637
- response.data = response.data.toString();
638
- // var socketUrl = ":8084"; var socketSession = ""; window.sysLang = "ru"; window.socketForceWebSockets = false;
639
- // replace ":8084"; => "";
640
- response.data = response.data.replace(/":\d+";/, '"";');
641
- }
642
-
643
- return {
644
- file: Buffer.from(response.data).toString('base64'),
645
- mimeType: response.headers['content-type'],
646
- };
647
- })
648
- .catch(error => {
649
- this.adapter.log.warn(`[REMOTE] File ${url}${path} not found`);
650
- let errorMessage;
651
- if (error.response && error.response.status === 404) {
652
- errorMessage = 'Not exists';
653
- } else if (error.response && error.response.status === 401) {
654
- errorMessage = 'Not authorised';
655
- } else {
656
- if (error.response) {
657
- errorMessage = error.response.data || error.response.status;
658
- } else if (error.request) {
659
- errorMessage = 'No answer';
660
- } else {
661
- errorMessage = error.message;
662
- }
663
- }
664
- return { sid, d: [type, id, '', { error: errorMessage }] };
665
- })
666
- : { sid, d: [type, id, '', { error: 'Not exists' }] };
667
- }
668
-
669
- _sendResponse(sid, _type, id, name, args, writeUrl, readUrl) {
670
- let packed = zlib.deflateSync(JSON.stringify(args)).toString('base64');
671
-
672
- if (packed.length > MAX_IOT_MESSAGE_LENGTH) {
673
- if (writeUrl) {
674
- if (args.length === 3) {
675
- const [error, file, mimeType] = args;
676
- if (!error) {
677
- return this.uploadToServer(writeUrl, { file, mimeType }, true).then(done => ({
678
- sid,
679
- d: [_type, id, name, done ? readUrl : ['Cannot upload']],
680
- }));
681
- }
682
- } else if (args.length === 2) {
683
- const [error, result] = args;
684
- if (!error) {
685
- return this.uploadToServer(
686
- writeUrl,
687
- { file: JSON.stringify(result), mimeType: 'application/json' },
688
- true,
689
- ).then(done => ({ sid, d: [_type, id, name, done ? readUrl : ['Cannot upload']] }));
690
- }
691
- } else if (args.length === 1) {
692
- const [result] = args;
693
- return this.uploadToServer(
694
- writeUrl,
695
- { file: JSON.stringify(result), mimeType: 'application/json' },
696
- true,
697
- ).then(done => ({ sid, d: [_type, id, name, done ? readUrl : ['Cannot upload']] }));
698
- }
699
- }
700
- // too big message. Do not use iot for that and send directly to socket
701
- /*const packets = []
702
- while (packed.length > MAX_IOT_MESSAGE_LENGTH) {
703
- const trunk = packed.substring(0, MAX_IOT_MESSAGE_LENGTH);
704
- packed = packed.substring(MAX_IOT_MESSAGE_LENGTH);
705
- packets.push(trunk);
706
- }
707
- if (packed.length) {
708
- packets.push(packed);
709
- }
710
-
711
- const trunks = packets.map((trunk, i) =>
712
- sid: message.sid, i, l: packets.length, d: [_type, id, name, trunk]}));
713
-
714
- this.packets[id] = {ts: Date.now(), trunks};
715
-
716
- // start garbage collector
717
- this.gcInterval = this.gcInterval || setInterval(() => this._clearMemory(), 60000);
718
-
719
- return trunks;*/
720
- setImmediate(async () => {
721
- if (packed.length > MAX_POST_MESSAGE_LENGTH) {
722
- // too big message. Do not use iot for that and send directly to socket
723
- const packets = [];
724
- while (packed.length > MAX_POST_MESSAGE_LENGTH) {
725
- const trunk = packed.substring(0, MAX_POST_MESSAGE_LENGTH);
726
- packed = packed.substring(MAX_POST_MESSAGE_LENGTH);
727
- packets.push(trunk);
728
- }
729
- if (packed.length) {
730
- packets.push(packed);
731
- }
732
-
733
- for (let i = 0; i < packets.length; i++) {
734
- const error = await this._sendEvent({
735
- sid: sid,
736
- d: [_type, id, name, packets[i], packets.length, i],
737
- });
738
- if (error) {
739
- this.adapter.log.error(`[REMOTE] cannot send: ${JSON.stringify(error)}`);
740
- break;
741
- }
742
- }
743
- } else {
744
- await this._sendEvent({ sid: sid, d: [_type, id, name, packed] });
745
- }
746
- });
747
-
748
- return { sid, d: [MESSAGE_TYPES.WAIT, id, name, [packed.length]] };
749
- }
750
- return { sid, d: [_type, id, name, packed] };
751
- }
752
-
753
- onCloudDisconnect() {
754
- // delete all sockets
755
- this.adapter.log.debug(`[REMOTE] Cloud disconnected`);
756
- if (!this.sockets) {
757
- return;
758
- }
759
-
760
- const sids = Object.keys(this.sockets);
761
- for (let s = 0; s < sids.length; s++) {
762
- this._unsubscribeSocket(sids[s], 'stateChange');
763
- this._unsubscribeSocket(sids[s], 'objectChange');
764
- this._unsubscribeSocket(sids[s], 'log');
765
- delete this.sockets[sids[s]];
766
- }
767
- }
768
-
769
- process(request, serviceType) {
770
- let message;
771
- if (typeof request === 'string') {
772
- try {
773
- message = JSON.parse(request);
774
- } catch (err) {
775
- this.adapter.log.error(`[REMOTE] Cannot parse request: ${request}`);
776
- message = null;
777
- }
778
- } else {
779
- message = request;
780
- }
781
-
782
- if (message) {
783
- const [_type, id, name, args, readUrl] = message.d;
784
- let promiseOne; // answer will be created automatically (error, result)
785
- let promiseResult; // answer will be created by promise
786
-
787
- if (this.adapter.config.remote && _type === MESSAGE_TYPES.MISSING) {
788
- if (this.packets[id]) {
789
- const missing = args[0];
790
- this.adapter.log.warn(`[REMOTE] Request for existing trunks: ${id}, "${name}": ${missing}`);
791
-
792
- this.device &&
793
- setImmediate(async () => {
794
- try {
795
- for (let m = 0; m < missing.length; m++) {
796
- await new Promise((resolve, reject) =>
797
- this.device.publish(
798
- `response/${this.clientId}/${serviceType}`,
799
- JSON.stringify(this.packets[id].trunks[m]),
800
- { qos: 1 },
801
- error => {
802
- if (error) {
803
- reject(error);
804
- } else {
805
- resolve();
806
- }
807
- },
808
- ),
809
- );
810
- }
811
- } catch (err) {
812
- this.adapter.log.error(`[REMOTE] Cannot send packet: ${err}`);
813
- }
814
- });
815
- } else {
816
- this.adapter.log.warn(`[REMOTE] Request for non existing trunks: ${id}, "${name}"`);
817
- }
818
- promiseResult = Promise.resolve(NONE);
819
- } else if (this.adapter.config.remote && _type === MESSAGE_TYPES.SENDING_DONE) {
820
- this.adapter.log.debug(`[REMOTE] Packet received: ${id}, "${name}"`);
821
- delete this.packets[id];
822
- promiseResult = Promise.resolve(NONE);
823
- } else if (_type === MESSAGE_TYPES.HTML) {
824
- let promiseFile;
825
-
826
- if (!this.adapter.config.remote) {
827
- return Promise.resolve({ sid: message.sid, d: [_type, id, '', ['Not enabled']] });
828
- } else if (name === 'listOfPrograms' || name === '/listOfPrograms') {
829
- promiseFile = AdminSocket.getListOfAllAdapters(this.adapter)
830
- .then(result => {
831
- let packed = zlib.deflateSync(JSON.stringify([null, result])).toString('base64');
832
- return { sid: message.sid, d: [_type, id, '', packed] };
833
- })
834
- .catch(error => ({ sid: message.sid, d: [_type, id, '', [error.toString()]] }));
835
- } else if (name === 'vendorPrefix' || name === '/vendorPrefix') {
836
- return Promise.resolve({ sid: message.sid, d: [_type, id, '', [null, this.vendorPrefix]] });
837
- } else if (name.startsWith('/adapter')) {
838
- if (this.adapter.config.remoteAdminInstance) {
839
- promiseFile = this.readUrlFile(this.adminUrl, name, message.sid, _type, id);
840
- } else {
841
- promiseFile = Promise.resolve({
842
- sid: message.sid,
843
- d: [_type, id, '', { error: 'Not exists' }],
844
- });
845
- }
846
- } else {
847
- const path = name.split('?')[0];
848
- const parts = path.split('/');
849
- parts.shift(); // remove leading /
850
- const _adapter = parts.shift();
851
- this.adapter.log.debug(`[REMOTE] HTML: ${path}`);
852
-
853
- // html must be returned only by iot channel, as lambda must process the answer
854
- promiseFile = this.adapter
855
- .readFileAsync(_adapter, parts.join('/'))
856
- .then(data => {
857
- data.file = Buffer.from(data.file).toString('base64');
858
- return data;
859
- })
860
- .catch(err =>
861
- // try to read from server
862
- this.readUrlFile(this.webUrl, path, message.sid, _type, id),
863
- );
864
- }
865
-
866
- return promiseFile.then(data => {
867
- // if error
868
- if (data.sid) {
869
- return data;
870
- } else {
871
- let packed = zlib.deflateSync(JSON.stringify(data)).toString('base64');
872
- if (
873
- typeof args === 'string' &&
874
- args?.startsWith('https:') &&
875
- packed.length > MAX_IOT_MESSAGE_LENGTH
876
- ) {
877
- // upload file to temp server
878
- return this.uploadToServer(args, data).then(done => ({
879
- sid: message.sid,
880
- d: [_type, id, '', done ? '_$%URL' : 'Cannot upload'],
881
- }));
882
- }
883
-
884
- if (data.file.length > MAX_FILE_SIZE) {
885
- // file too big
886
- this.adapter.log.warn(
887
- `[REMOTE] Requested file ${name} is too big (${Math.round(data.file.length / 1000)}Kb). Max length is ${MAX_FILE_SIZE / 1024}Kb`,
888
- );
889
- return {
890
- sid: message.sid,
891
- d: [
892
- _type,
893
- id,
894
- '',
895
- {
896
- error: `File is too big: ${Math.round(data.file.length / 1000)}Kb, max ${MAX_FILE_SIZE / 1024}Kb`,
897
- },
898
- ],
899
- };
900
- }
901
-
902
- if (packed.length > MAX_IOT_MESSAGE_LENGTH) {
903
- const packets = [];
904
- while (packed.length > MAX_IOT_MESSAGE_LENGTH) {
905
- const trunk = packed.substring(0, MAX_IOT_MESSAGE_LENGTH);
906
- packed = packed.substring(MAX_IOT_MESSAGE_LENGTH);
907
- packets.push(trunk);
908
- }
909
- if (packed.length) {
910
- packets.push(packed);
911
- }
912
-
913
- const trunks = packets.map((trunk, i) => ({
914
- sid: message.sid,
915
- i,
916
- l: packets.length,
917
- d: [_type, id, '', trunk],
918
- }));
919
-
920
- this.packets[id] = { ts: Date.now(), trunks };
921
-
922
- // start garbage collector
923
- this.gcInterval = this.gcInterval || setInterval(() => this._clearMemory(), 60000);
924
-
925
- return trunks;
926
- } else {
927
- return { sid: message.sid, d: [_type, id, '', packed] };
928
- }
929
- }
930
- });
931
- }
932
-
933
- if (!this.adapter.config.remote) {
934
- promiseResult = Promise.resolve(
935
- JSON.stringify({ sid: message.sid, d: [_type, id, name, ['Not enabled']] }),
936
- );
937
- }
938
- let isNew = false;
939
- if (this.sockets) {
940
- if (!this.sockets[message.sid]) {
941
- this.adapter.log.debug(`[REMOTE] +++++ CONNECT ${message.sid}`);
942
- this.sockets[message.sid] = { _subscribe: {}, ts: Date.now() };
943
- isNew = true;
944
- } else {
945
- this.sockets[message.sid].ts = Date.now();
946
- }
947
- }
948
-
949
- if (promiseResult) {
950
- // this answer will be processed at the very end of the function
951
- } else if (_type === MESSAGE_TYPES.COMBINED_CALLBACK || _type === MESSAGE_TYPES.COMBINED_MESSAGE) {
952
- let promiseMany;
953
- if (name === 'getStates') {
954
- promiseMany = this._getStatesManyArgs(args);
955
- } else if (name === 'getState') {
956
- promiseMany = this._getStateManyArgs(args);
957
- } else if (name === 'getObject') {
958
- promiseMany = this._getObjectManyArgs(args);
959
- } else if (name === 'subscribe' || name === 'subscribeStates') {
960
- promiseMany = this._subscribeManyArgs(message.sid, args);
961
- } else if (name === 'unsubscribe' || name === 'unsubscribeStates') {
962
- promiseMany = this._unsubscribeManyArgs(message.sid, args);
963
- } else if (name === 'ppng') {
964
- // ping
965
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, [0, isNew ? 0 : 1]] }); // 1 is OK, 0 is not OK
966
- } else {
967
- // error
968
- this.adapter.log.error(`[REMOTE] Received unknown multiple request: ${name}`);
969
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, ['Unknown command']] });
970
- }
971
- if (promiseMany) {
972
- promiseResult = promiseMany
973
- .then(result => this._sendResponse(message.sid, _type, id, name, result))
974
- /* let packed = zlib.deflateSync(JSON.stringify(result)).toString('base64');
975
-
976
- if (packed.length > MAX_IOT_MESSAGE_LENGTH) {
977
- setImmediate(async () => {
978
- if (packed.length > MAX_POST_MESSAGE_LENGTH) {
979
- // too big message. Do not use iot for that and send directly to socket
980
- const packets = []
981
- while (packed.length > MAX_POST_MESSAGE_LENGTH) {
982
- const trunk = packed.substring(0, MAX_POST_MESSAGE_LENGTH);
983
- packed = packed.substring(MAX_POST_MESSAGE_LENGTH);
984
- packets.push(trunk);
985
- }
986
- if (packed.length) {
987
- packets.push(packed);
988
- }
989
-
990
- for (let i = 0; i < packets.length; i++) {
991
- const error = await this._sendEvent({sid: message.sid, d: [_type, id, name, packets[i], packets.length, i]});
992
- if (error) {
993
- this.adapter.log.error('[REMOTE] cannot send: ' + JSON.stringify(error));
994
- break;
995
- }
996
- }
997
- } else {
998
- await this._sendEvent({sid: message.sid, d: [_type, id, name, packed]});
999
- }
1000
- });
1001
- return {sid: message.sid, d: [MESSAGE_TYPES.WAIT, id, name, [packed.length]]};
1002
- } else {
1003
- return {sid: message.sid, d: [_type, id, name, packed]};
1004
- }
1005
- })*/
1006
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1007
- }
1008
- } else if (this.handlers[name]) {
1009
- if (!this.handlers[name].args) {
1010
- promiseOne = this.handlers[name].f();
1011
- } else if (this.handlers[name].args === 1) {
1012
- promiseOne = this.handlers[name].f(args[0]);
1013
- } else if (this.handlers[name].args === 2) {
1014
- promiseOne = this.handlers[name].f(args[0], args[1]);
1015
- } else if (this.handlers[name].args === 3) {
1016
- promiseOne = this.handlers[name].f(args[0], args[1], args[2]);
1017
- } else if (this.handlers[name].args === 4) {
1018
- promiseOne = this.handlers[name].f(args[0], args[1], args[2], args[3]);
1019
- } else if (this.handlers[name].args === 5) {
1020
- promiseOne = this.handlers[name].f(args[0], args[1], args[2], args[3], args[4]);
1021
- } else if (this.handlers[name].args === 6) {
1022
- promiseOne = this.handlers[name].f(args[0], args[1], args[2], args[3], args[4], args[5]);
1023
- } else {
1024
- this.adapter.log.warn('[REMOTE] Unsupported number of arguments');
1025
- }
1026
- } else if (name === 'ppng') {
1027
- // ping
1028
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, [null, !isNew]] });
1029
- } else if (name === 'name') {
1030
- const socket = this.sockets[message.sid];
1031
- if (socket.name === undefined) {
1032
- socket.name = name;
1033
- this.adapter.log.info(`[REMOTE] socket ${message.sid} connected with name "${name}"`);
1034
- } else if (socket.name !== name) {
1035
- this.adapter.log.warn(
1036
- `[REMOTE] socket ${message.sid} changed socket name from ${socket.name} to ${name}`,
1037
- );
1038
- socket.name = name;
1039
- }
1040
-
1041
- // start garbage collector
1042
- this.gcInterval = this.gcInterval || setInterval(() => this._clearMemory(), 60000);
1043
-
1044
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, []] });
1045
- } else if (name === 'authenticate') {
1046
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, [true, false]] });
1047
- } else if (name === 'getObjects') {
1048
- promiseOne = this._readAllObjects();
1049
- } else if (name === 'getHostByIp') {
1050
- promiseResult = AdminSocket.getHostByIp(this.adapter, args[0]).then(result => ({
1051
- sid: message.sid,
1052
- d: [_type, id, name, [result.ip, result.obj]],
1053
- }));
1054
- } else if (name === 'getStates') {
1055
- promiseOne = this.adapter.getForeignStatesAsync(args[0] || '*');
1056
- } else if (name === 'getBinaryState') {
1057
- promiseOne = this.adapter.getBinaryStateAsync(args[0]).then(data => {
1058
- data = data && Buffer.from(data).toString('base64');
1059
- return data;
1060
- });
1061
- } else if (name === 'setBinaryState') {
1062
- let data = null;
1063
- try {
1064
- data = Buffer.from(args[1], 'base64');
1065
- } catch (e) {
1066
- this.adapter.log.warn(`[REMOTE] [setBinaryState] Cannot convert base64 data: ${e}`);
1067
- }
1068
-
1069
- promiseOne = this.adapter.setBinaryStateAsync(args[0], data);
1070
- } else if (name === 'requireLog') {
1071
- const isEnabled = args[0];
1072
- if (isEnabled) {
1073
- this._subscribe(this, 'log', 'dummy');
1074
- } else {
1075
- this._unsubscribe(this, 'log', 'dummy');
1076
- }
1077
-
1078
- this.adapter.log.level === 'debug' && this._showSubscribes(message.sid, 'log');
1079
-
1080
- promiseOne = Promise.resolve({ sid: message.sid, d: [_type, id, name, [null]] });
1081
- } else if (name === 'DCT') {
1082
- // disconnect
1083
- const socket = this.sockets[message.sid];
1084
- this.adapter.log.debug(`[REMOTE] ---- DISCONNECT ${message.sid}`);
1085
- if (socket) {
1086
- this._unsubscribeSocket(message.sid, 'stateChange');
1087
- this._unsubscribeSocket(message.sid, 'objectChange');
1088
- this._unsubscribeSocket(message.sid, 'log');
1089
- delete this.sockets[message.sid];
1090
- }
1091
- } else if (name === 'getVersion') {
1092
- promiseResult = Promise.resolve({
1093
- sid: message.sid,
1094
- d: [_type, id, name, [null, this.adminObj.common.version, 'admin']],
1095
- });
1096
- } else if (name === 'subscribe' || name === 'subscribeStates') {
1097
- const pattern = args[0];
1098
- if (pattern && typeof pattern === 'object' && pattern instanceof Array) {
1099
- for (let p = 0; p < pattern.length; p++) {
1100
- this._subscribe(message.sid, 'stateChange', pattern[p]);
1101
- }
1102
- } else {
1103
- this._subscribe(message.sid, 'stateChange', pattern);
1104
- }
1105
-
1106
- this.adapter.log.level === 'debug' && this._showSubscribes(message.sid, 'stateChange');
1107
- promiseOne = Promise.resolve({ sid: message.sid, d: [_type, id, name, [null]] });
1108
- } else if (name === 'unsubscribe' || name === 'unsubscribeStates') {
1109
- const pattern = args[0];
1110
- if (pattern && typeof pattern === 'object' && pattern instanceof Array) {
1111
- for (let p = 0; p < pattern.length; p++) {
1112
- this._unsubscribe(message.sid, 'stateChange', pattern[p]);
1113
- }
1114
- } else {
1115
- this._unsubscribe(message.sid, 'stateChange', pattern);
1116
- }
1117
-
1118
- this.adapter.log.level === 'debug' && this._showSubscribes(message.sid, 'stateChange');
1119
- promiseOne = Promise.resolve({ sid: message.sid, d: [_type, id, name, [null]] });
1120
- } else if (name === 'subscribeObjects') {
1121
- const pattern = args && args[0] ? args[0] : '*';
1122
- if (pattern && typeof pattern === 'object' && pattern instanceof Array) {
1123
- for (let p = 0; p < pattern.length; p++) {
1124
- this._subscribe(message.sid, 'objectChange', pattern[p]);
1125
- }
1126
- } else {
1127
- this._subscribe(message.sid, 'objectChange', pattern);
1128
- }
1129
-
1130
- this.adapter.log.level === 'debug' && this._showSubscribes(message.sid, 'objectChange');
1131
- promiseOne = Promise.resolve({ sid: message.sid, d: [_type, id, name, [null]] });
1132
- } else if (name === 'unsubscribeObjects') {
1133
- const pattern = args[0];
1134
- if (pattern && typeof pattern === 'object' && pattern instanceof Array) {
1135
- for (let p = 0; p < pattern.length; p++) {
1136
- this._unsubscribe(message.sid, 'objectChange', pattern[p]);
1137
- }
1138
- } else {
1139
- this._unsubscribe(message.sid, 'objectChange', pattern);
1140
- }
1141
-
1142
- this.adapter.log.level === 'debug' && this._showSubscribes(message.sid, 'objectChange');
1143
- promiseOne = Promise.resolve({ sid: message.sid, d: [_type, id, name, [null]] });
1144
- } else if (name === 'authEnabled') {
1145
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, [false, 'admin']] });
1146
- } else if (name === 'readFile') {
1147
- const adapter = args[0];
1148
- const fileName = args[1];
1149
- promiseResult = this.adapter
1150
- .readFileAsync(adapter, fileName)
1151
- .then(data =>
1152
- this._sendResponse(
1153
- message.sid,
1154
- _type,
1155
- id,
1156
- name,
1157
- [null, data.file, data.mimeType],
1158
- message.wu,
1159
- message.ru,
1160
- ),
1161
- )
1162
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1163
- } else if (name === 'readFile64') {
1164
- const adapter = args[0];
1165
- const fileName = args[1];
1166
- promiseResult = this.adapter
1167
- .readFileAsync(adapter, fileName)
1168
- .then(data => {
1169
- let data64;
1170
- if (data.mimeType) {
1171
- try {
1172
- if (
1173
- data.mimeType === 'application/json' ||
1174
- data.mimeType === 'application/json5' ||
1175
- fileName.toLowerCase().endsWith('.json5')
1176
- ) {
1177
- data64 = Buffer.from(encodeURIComponent(data.mimeType)).toString('base64');
1178
- } else {
1179
- if (typeof data.mimeType === 'string') {
1180
- data64 = Buffer.from(data.mimeType).toString('base64');
1181
- } else {
1182
- data64 = data.mimeType.toString('base64');
1183
- }
1184
- }
1185
- } catch (error) {
1186
- this.adapter.log.error(`[readFile64] Cannot convert data: ${error.toString()}`);
1187
- }
1188
- }
1189
-
1190
- return this._sendResponse(
1191
- message.sid,
1192
- _type,
1193
- id,
1194
- name,
1195
- [null, data64, data.mimeType],
1196
- message.wu,
1197
- message.ru,
1198
- );
1199
- })
1200
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1201
- } else if (name === 'writeFile' || name === 'writeFile64') {
1202
- const [adr, fileName, data64, options] = args;
1203
- if (readUrl) {
1204
- promiseOne = axios(readUrl, {
1205
- responseType: 'arraybuffer',
1206
- validateStatus: status => status === 200,
1207
- timeout: 15000,
1208
- }).then(response =>
1209
- this.adapter.writeFileAsync(adr, fileName, Buffer.from(response.data), options),
1210
- );
1211
- } else if (name === 'wirteFile') {
1212
- this.adapter.log.debug('writeFile deprecated. Please use writeFile64');
1213
- promiseOne = this.adapter.writeFileAsync(adr, fileName, data64, options);
1214
- } else if (name === 'wirteFile64') {
1215
- const buffer = Buffer.from(data64, 'base64');
1216
- promiseOne = this.adapter.writeFileAsync(adr, fileName, buffer, options);
1217
- }
1218
- } else if (name === 'getHistory') {
1219
- const _id = args[0];
1220
- const options = args[1];
1221
- promiseResult = this.adapter
1222
- .getHistoryAsync(_id, options)
1223
- .then(data =>
1224
- this._sendResponse(
1225
- message.sid,
1226
- _type,
1227
- id,
1228
- name,
1229
- [null, data.result, data.step, data.sessionId],
1230
- message.wu,
1231
- message.ru,
1232
- ),
1233
- )
1234
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1235
- } else if (name === 'writeFile64' || name === 'writeFile') {
1236
- const [_adapter, fileName, data64, options] = args;
1237
- // Convert base 64 to buffer
1238
- const buffer = Buffer.from(data64, 'base64');
1239
- promiseOne = this.adapter.writeFileAsync(_adapter, fileName, buffer, options);
1240
- } else if (name === 'getEasyMode') {
1241
- promiseOne = AdminSocket.getEasyMode(this.adapter, this.adminObj);
1242
- } else if (name === 'getAdapterInstances') {
1243
- promiseOne = AdminSocket.getAdapterInstances(this.adapter, args[0]);
1244
- } else if (name === 'getCurrentInstance') {
1245
- promiseOne = Promise.resolve(this.adapter.config.remoteAdminInstance);
1246
- } else if (name === 'checkFeatureSupported') {
1247
- promiseOne = Promise.resolve(this.adapter.supportsFeature && this.adapter.supportsFeature(args[0]));
1248
- } else if (name === 'getAdapterName') {
1249
- promiseOne = Promise.resolve('admin');
1250
- } else if (name === 'decrypt') {
1251
- if (this.secret) {
1252
- promiseOne = Promise.resolve(this.adapter.tools.decrypt(this.secret, args[0]));
1253
- } else {
1254
- promiseOne = this.adapter.getForeignObjectAsync('system.config', (err, obj) => {
1255
- if (obj && obj.native && obj.native.secret) {
1256
- this.secret = obj.native.secret;
1257
- return this.adapter.tools.decrypt(this.secret, args[0]);
1258
- } else {
1259
- this.adapter.log.error(`No system.config found: ${err}`);
1260
- throw new Error('No system.config found');
1261
- }
1262
- });
1263
- }
1264
- } else if (name === 'encrypt') {
1265
- if (this.secret) {
1266
- promiseOne = Promise.resolve(this.adapter.tools.encrypt(this.secret, args[0]));
1267
- } else {
1268
- promiseOne = this.adapter.getForeignObjectAsync('system.config', (err, obj) => {
1269
- if (obj && obj.native && obj.native.secret) {
1270
- this.secret = obj.native.secret;
1271
- return this.adapter.tools.encrypt(this.secret, args[0]);
1272
- } else {
1273
- this.adapter.log.error(`No system.config found: ${err}`);
1274
- throw new Error('No system.config found');
1275
- }
1276
- });
1277
- }
1278
- } else if (name === 'getIsEasyModeStrict') {
1279
- promiseOne = AdminSocket.getIsEasyModeStrict(this.adapter, this.adminObj);
1280
- } else if (name === 'getAdapters') {
1281
- promiseOne = AdminSocket.getAdapters(this.adapter, args[0]);
1282
- } else if (name === 'updateLicenses') {
1283
- promiseOne = AdminSocket.updateLicenses(this.adapter, args[0], args[1], this.adminObj);
1284
- } else if (name === 'getCompactInstances') {
1285
- promiseOne = AdminSocket.getCompactInstances(this.adapter);
1286
- } else if (name === 'getCompactSystemRepositories') {
1287
- promiseOne = AdminSocket.getCompactSystemRepositories(this.adapter);
1288
- } else if (name === 'getCompactAdapters') {
1289
- promiseOne = AdminSocket.getCompactAdapters(this.adapter);
1290
- } else if (name === 'getCompactInstalled') {
1291
- promiseResult = AdminSocket.getCompactInstalled(
1292
- this.adapter,
1293
- args[0] || this.adminObj.common.host,
1294
- ).then(data => ({ sid: message.sid, d: [_type, id, name, [data]] }));
1295
- } else if (name === 'getCompactSystemConfig') {
1296
- promiseOne = AdminSocket.getCompactSystemConfig(this.adapter);
1297
- } else if (name === 'getCompactRepository') {
1298
- promiseResult = AdminSocket.getCompactRepository(
1299
- this.adapter,
1300
- args[0] || this.adminObj.common.host,
1301
- ).then(data => ({ sid: message.sid, d: [_type, id, name, [data]] }));
1302
- } else if (name === 'getCompactHosts') {
1303
- promiseOne = AdminSocket.getCompactHosts(this.adapter);
1304
- } else if (name === 'readLogs') {
1305
- promiseOne = AdminSocket.readLogs(this.adapter, args[0] || this.adminObj.common.host);
1306
- } else if (name === 'eventsThreshold') {
1307
- promiseOne = Promise.resolve(NONE);
1308
- } else if (name === 'getRatings') {
1309
- promiseOne = AdminSocket.getRatings(this.adapter, args[0]);
1310
- } else if (name === 'getUserPermissions') {
1311
- this.adapter.log.error(`[REMOTE] getUserPermissions not implemented!!!!!!!!!!!!!!!!!!!!!`);
1312
- } else if (name === 'listPermissions') {
1313
- promiseResult = AdminSocket.listPermissions(this.adapter)
1314
- .then(commandsPermissions =>
1315
- this._sendResponse(message.sid, _type, id, name, [commandsPermissions]),
1316
- )
1317
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1318
- } else if (name === 'sendToHost') {
1319
- const [host, command, msg] = args;
1320
- this.adapter.log.debug(`[REMOTE] SEND_TO_HOST: ${command}`);
1321
- // check if the host is alive
1322
- promiseResult = AdminSocket.sendToHost(this.adapter, host, command, msg)
1323
- .then(data => this._sendResponse(message.sid, _type, id, name, [data], message.wu, message.ru))
1324
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1325
- } else if (name === 'sendTo') {
1326
- const [adapterInstance, command, message] = args;
1327
- promiseResult = AdminSocket.sendTo(this.adapter, adapterInstance, command, message)
1328
- .then(data => this._sendResponse(message.sid, _type, id, name, [data], message.wu, message.ru))
1329
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1330
- } else if (name === 'getAllObjects') {
1331
- promiseOne = AdminSocket.getAllObjects(this.adapter);
1332
- }
1333
-
1334
- // MESSAGE is the only one-way message and no answer is expected
1335
- if (_type === MESSAGE_TYPES.MESSAGE || _type === MESSAGE_TYPES.COMBINED_MESSAGE) {
1336
- promiseResult = promiseOne ? promiseOne.then(() => NONE) : Promise.resolve(NONE);
1337
- } else if (!promiseResult && promiseOne) {
1338
- promiseResult = promiseOne
1339
- .then(result =>
1340
- this._sendResponse(message.sid, _type, id, name, [null, result], message.wu, message.ru),
1341
- )
1342
- .catch(error => ({ sid: message.sid, d: [_type, id, name, [error]] }));
1343
- }
1344
-
1345
- if (!promiseResult) {
1346
- this.adapter.log.warn(`[REMOTE] Received unknown command: ${name}`);
1347
- promiseResult = Promise.resolve({ sid: message.sid, d: [_type, id, name, ['Unknown command']] });
1348
- }
1349
-
1350
- return promiseResult.then(result => {
1351
- if (result !== NONE && result.d && result.d[0] !== MESSAGE_TYPES.WAIT) {
1352
- setImmediate(async (result, message) => await this._sendEvent(result, message), result, message);
1353
- }
1354
-
1355
- return NONE;
1356
- });
1357
- } else {
1358
- return Promise.reject('Null message');
1359
- }
1360
- }
1361
- }
1362
-
1363
- module.exports = RemoteAccess;