@iobroker/socket-classes 1.6.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +790 -774
- package/dist/index.d.ts +7 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/passportSocket.d.ts +37 -0
- package/{lib → dist/lib}/passportSocket.js +25 -42
- package/dist/lib/passportSocket.js.map +1 -0
- package/dist/lib/socketCommands.d.ts +83 -0
- package/dist/lib/socketCommands.js +2024 -0
- package/dist/lib/socketCommands.js.map +1 -0
- package/dist/lib/socketCommandsAdmin.d.ts +139 -0
- package/dist/lib/socketCommandsAdmin.js +1584 -0
- package/dist/lib/socketCommandsAdmin.js.map +1 -0
- package/dist/lib/socketCommon.d.ts +141 -0
- package/dist/lib/socketCommon.js +496 -0
- package/dist/lib/socketCommon.js.map +1 -0
- package/dist/types.d.ts +62 -0
- package/package.json +23 -17
- package/index.js +0 -19
- package/lib/socketAdmin.js +0 -203
- package/lib/socketCommands.js +0 -1886
- package/lib/socketCommandsAdmin.js +0 -1492
- package/lib/socketCommon.js +0 -480
package/lib/socketCommands.js
DELETED
|
@@ -1,1886 +0,0 @@
|
|
|
1
|
-
const utils = require('@iobroker/adapter-core'); // Get common adapter utils
|
|
2
|
-
const pattern2RegEx = utils.commonTools.pattern2RegEx;
|
|
3
|
-
let axios = null;
|
|
4
|
-
let zipFiles = null;
|
|
5
|
-
|
|
6
|
-
class SocketCommands {
|
|
7
|
-
static ERROR_PERMISSION = 'permissionError';
|
|
8
|
-
static COMMANDS_PERMISSIONS = {
|
|
9
|
-
getObject: { type: 'object', operation: 'read' },
|
|
10
|
-
getObjects: { type: 'object', operation: 'list' },
|
|
11
|
-
getObjectView: { type: 'object', operation: 'list' },
|
|
12
|
-
setObject: { type: 'object', operation: 'write' },
|
|
13
|
-
requireLog: { type: 'object', operation: 'write' }, // just mapping to some command
|
|
14
|
-
delObject: { type: 'object', operation: 'delete' },
|
|
15
|
-
extendObject: { type: 'object', operation: 'write' },
|
|
16
|
-
getHostByIp: { type: 'object', operation: 'list' },
|
|
17
|
-
subscribeObjects: { type: 'object', operation: 'read' },
|
|
18
|
-
unsubscribeObjects: { type: 'object', operation: 'read' },
|
|
19
|
-
|
|
20
|
-
getStates: { type: 'state', operation: 'list' },
|
|
21
|
-
getState: { type: 'state', operation: 'read' },
|
|
22
|
-
setState: { type: 'state', operation: 'write' },
|
|
23
|
-
delState: { type: 'state', operation: 'delete' },
|
|
24
|
-
createState: { type: 'state', operation: 'create' },
|
|
25
|
-
subscribe: { type: 'state', operation: 'read' },
|
|
26
|
-
unsubscribe: { type: 'state', operation: 'read' },
|
|
27
|
-
getStateHistory: { type: 'state', operation: 'read' },
|
|
28
|
-
getVersion: { type: '', operation: '' },
|
|
29
|
-
getAdapterName: { type: '', operation: '' },
|
|
30
|
-
|
|
31
|
-
addUser: { type: 'users', operation: 'create' },
|
|
32
|
-
delUser: { type: 'users', operation: 'delete' },
|
|
33
|
-
addGroup: { type: 'users', operation: 'create' },
|
|
34
|
-
delGroup: { type: 'users', operation: 'delete' },
|
|
35
|
-
changePassword: { type: 'users', operation: 'write' },
|
|
36
|
-
|
|
37
|
-
httpGet: { type: 'other', operation: 'http' },
|
|
38
|
-
cmdExec: { type: 'other', operation: 'execute' },
|
|
39
|
-
sendTo: { type: 'other', operation: 'sendto' },
|
|
40
|
-
sendToHost: { type: 'other', operation: 'sendto' },
|
|
41
|
-
readLogs: { type: 'other', operation: 'execute' },
|
|
42
|
-
|
|
43
|
-
readDir: { type: 'file', operation: 'list' },
|
|
44
|
-
createFile: { type: 'file', operation: 'create' },
|
|
45
|
-
writeFile: { type: 'file', operation: 'write' },
|
|
46
|
-
readFile: { type: 'file', operation: 'read' },
|
|
47
|
-
fileExists: { type: 'file', operation: 'read' },
|
|
48
|
-
deleteFile: { type: 'file', operation: 'delete' },
|
|
49
|
-
readFile64: { type: 'file', operation: 'read' },
|
|
50
|
-
writeFile64: { type: 'file', operation: 'write' },
|
|
51
|
-
unlink: { type: 'file', operation: 'delete' },
|
|
52
|
-
rename: { type: 'file', operation: 'write' },
|
|
53
|
-
mkdir: { type: 'file', operation: 'write' },
|
|
54
|
-
chmodFile: { type: 'file', operation: 'write' },
|
|
55
|
-
chownFile: { type: 'file', operation: 'write' },
|
|
56
|
-
subscribeFiles: { type: 'file', operation: 'read' },
|
|
57
|
-
unsubscribeFiles: { type: 'file', operation: 'read' },
|
|
58
|
-
|
|
59
|
-
authEnabled: { type: '', operation: '' },
|
|
60
|
-
disconnect: { type: '', operation: '' },
|
|
61
|
-
listPermissions: { type: '', operation: '' },
|
|
62
|
-
getUserPermissions: { type: 'object', operation: 'read' }
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
constructor(adapter, updateSession) {
|
|
66
|
-
this.adapter = adapter;
|
|
67
|
-
this.commands = {};
|
|
68
|
-
this.subscribes = {};
|
|
69
|
-
this.logEnabled = false;
|
|
70
|
-
this.clientSubscribes = {};
|
|
71
|
-
|
|
72
|
-
this._updateSession = updateSession;
|
|
73
|
-
|
|
74
|
-
if (!this._updateSession) {
|
|
75
|
-
this._updateSession = () => true;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
this._initCommands();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async _rename(_adapter, oldName, newName, options) {
|
|
82
|
-
// read if it is a file or folder
|
|
83
|
-
try {
|
|
84
|
-
if (oldName.endsWith('/')) {
|
|
85
|
-
oldName = oldName.substring(0, oldName.length - 1);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (newName.endsWith('/')) {
|
|
89
|
-
newName = newName.substring(0, newName.length - 1);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const files = await this.adapter.readDirAsync(_adapter, oldName, options);
|
|
93
|
-
if (files && files.length) {
|
|
94
|
-
for (let f = 0; f < files.length; f++) {
|
|
95
|
-
await this._rename(_adapter, `${oldName}/${files[f].file}`, `${newName}/${files[f].file}`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} catch (error) {
|
|
99
|
-
if (error.message !== 'Not exists') {
|
|
100
|
-
throw error;
|
|
101
|
-
}
|
|
102
|
-
// else ignore, because it is a file and not a folder
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
await this.adapter.renameAsync(_adapter, oldName, newName, options);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
if (error.message !== 'Not exists') {
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
// else ignore, because folder cannot be deleted
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async _unlink(_adapter, name, options) {
|
|
116
|
-
// read if it is a file or folder
|
|
117
|
-
try {
|
|
118
|
-
// remove trailing '/'
|
|
119
|
-
if (name.endsWith('/')) {
|
|
120
|
-
name = name.substring(0, name.length - 1);
|
|
121
|
-
}
|
|
122
|
-
const files = await this.adapter.readDirAsync(_adapter, name, options);
|
|
123
|
-
if (files && files.length) {
|
|
124
|
-
for (let f = 0; f < files.length; f++) {
|
|
125
|
-
await this._unlink(_adapter, `${name}/${files[f].file}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} catch (error) {
|
|
129
|
-
// ignore, because it is a file and not a folder
|
|
130
|
-
if (error.message !== 'Not exists') {
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
await this.adapter.unlinkAsync(_adapter, name, options);
|
|
137
|
-
} catch (error) {
|
|
138
|
-
if (error.message !== 'Not exists') {
|
|
139
|
-
throw error;
|
|
140
|
-
}
|
|
141
|
-
// else ignore, because folder cannot be deleted
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Convert errors into strings and then call cb
|
|
147
|
-
* @param {function} cb - callback
|
|
148
|
-
* @param {string|Error|null} error - error argument
|
|
149
|
-
* @param {any[]} args - args passed to cb
|
|
150
|
-
*/
|
|
151
|
-
static _fixCallback(cb, error, ...args) {
|
|
152
|
-
if (typeof cb !== 'function') {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (error instanceof Error) {
|
|
157
|
-
error = error.message;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
cb(error, ...args);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
_checkPermissions(socket, command, callback, arg) {
|
|
164
|
-
if (socket._acl.user !== 'system.user.admin') {
|
|
165
|
-
// type: file, object, state, other
|
|
166
|
-
// operation: create, read, write, list, delete, sendto, execute, sendToHost, readLogs
|
|
167
|
-
if (SocketCommands.COMMANDS_PERMISSIONS[command]) {
|
|
168
|
-
// If permission required
|
|
169
|
-
if (SocketCommands.COMMANDS_PERMISSIONS[command].type) {
|
|
170
|
-
if (
|
|
171
|
-
socket._acl[SocketCommands.COMMANDS_PERMISSIONS[command].type] &&
|
|
172
|
-
socket._acl[SocketCommands.COMMANDS_PERMISSIONS[command].type][
|
|
173
|
-
SocketCommands.COMMANDS_PERMISSIONS[command].operation
|
|
174
|
-
]
|
|
175
|
-
) {
|
|
176
|
-
return true;
|
|
177
|
-
} else {
|
|
178
|
-
this.adapter.log.warn(
|
|
179
|
-
`No permission for "${socket._acl.user}" to call ${command}. Need "${SocketCommands.COMMANDS_PERMISSIONS[command].type}"."${SocketCommands.COMMANDS_PERMISSIONS[command].operation}"`
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
183
|
-
return true;
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
this.adapter.log.warn(`No rule for command: ${command}`);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (typeof callback === 'function') {
|
|
190
|
-
callback(SocketCommands.ERROR_PERMISSION);
|
|
191
|
-
} else {
|
|
192
|
-
if (SocketCommands.COMMANDS_PERMISSIONS[command]) {
|
|
193
|
-
socket.emit(SocketCommands.ERROR_PERMISSION, {
|
|
194
|
-
command,
|
|
195
|
-
type: SocketCommands.COMMANDS_PERMISSIONS[command].type,
|
|
196
|
-
operation: SocketCommands.COMMANDS_PERMISSIONS[command].operation,
|
|
197
|
-
arg
|
|
198
|
-
});
|
|
199
|
-
} else {
|
|
200
|
-
socket.emit(SocketCommands.ERROR_PERMISSION, { command, arg });
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
publish(socket, type, id, obj) {
|
|
210
|
-
if (socket && socket.subscribe && socket.subscribe[type] && this._updateSession(socket)) {
|
|
211
|
-
return !!socket.subscribe[type].find(sub => {
|
|
212
|
-
if (sub.regex.test(id)) {
|
|
213
|
-
// replace language
|
|
214
|
-
if (this.adapter._language && id === 'system.config' && obj.common) {
|
|
215
|
-
obj.common.language = this.adapter._language;
|
|
216
|
-
}
|
|
217
|
-
socket.emit(type, id, obj);
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return false;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
publishFile(socket, id, fileName, size) {
|
|
227
|
-
if (socket && socket.subscribe && socket.subscribe.fileChange && this._updateSession(socket)) {
|
|
228
|
-
const key = `${id}####${fileName}`;
|
|
229
|
-
return !!socket.subscribe.fileChange.find(sub => {
|
|
230
|
-
if (sub.regex.test(key)) {
|
|
231
|
-
socket.emit('fileChange', id, fileName, size);
|
|
232
|
-
return true;
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return false;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
publishInstanceMessage(socket, sourceInstance, messageType, data) {
|
|
241
|
-
if (
|
|
242
|
-
this.clientSubscribes[socket.id] &&
|
|
243
|
-
this.clientSubscribes[socket.id][sourceInstance] &&
|
|
244
|
-
this.clientSubscribes[socket.id][sourceInstance].includes(messageType)
|
|
245
|
-
) {
|
|
246
|
-
socket.emit('im', messageType, sourceInstance, data);
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// inform instance about missing subscription
|
|
251
|
-
this.adapter.sendTo(sourceInstance, 'clientSubscribeError', {
|
|
252
|
-
type: messageType,
|
|
253
|
-
sid: socket.id,
|
|
254
|
-
reason: 'no one subscribed'
|
|
255
|
-
});
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
_showSubscribes(socket, type) {
|
|
260
|
-
if (socket && socket.subscribe) {
|
|
261
|
-
const s = socket.subscribe[type] || [];
|
|
262
|
-
const ids = [];
|
|
263
|
-
for (let i = 0; i < s.length; i++) {
|
|
264
|
-
ids.push(s[i].pattern);
|
|
265
|
-
}
|
|
266
|
-
this.adapter.log.debug(`Subscribes: ${ids.join(', ')}`);
|
|
267
|
-
} else {
|
|
268
|
-
this.adapter.log.debug('Subscribes: no subscribes');
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
isLogEnabled() {
|
|
273
|
-
return this.logEnabled;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
subscribe(socket, type, pattern, patternFile) {
|
|
277
|
-
if (!pattern) {
|
|
278
|
-
return this.adapter.log.warn('Empty pattern on subscribe!');
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
this.subscribes[type] = this.subscribes[type] || {};
|
|
282
|
-
|
|
283
|
-
let p;
|
|
284
|
-
let key;
|
|
285
|
-
pattern = pattern.toString();
|
|
286
|
-
if (patternFile && type === 'fileChange') {
|
|
287
|
-
patternFile = patternFile.toString();
|
|
288
|
-
key = `${pattern}####${patternFile}`;
|
|
289
|
-
} else {
|
|
290
|
-
key = pattern;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
try {
|
|
294
|
-
p = pattern2RegEx(key);
|
|
295
|
-
} catch (e) {
|
|
296
|
-
this.adapter.log.error(`Invalid pattern on subscribe: ${e.message}`);
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (p === null) {
|
|
301
|
-
return this.adapter.log.warn('Empty pattern on subscribe!');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
let s;
|
|
305
|
-
if (socket) {
|
|
306
|
-
socket.subscribe = socket.subscribe || {};
|
|
307
|
-
s = socket.subscribe[type] = socket.subscribe[type] || [];
|
|
308
|
-
|
|
309
|
-
if (s.find(item => item.pattern === key)) {
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
s.push({ pattern: key, regex: new RegExp(p) });
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const options = socket && socket._acl ? { user: socket._acl.user } : undefined;
|
|
316
|
-
|
|
317
|
-
if (this.subscribes[type][key] === undefined) {
|
|
318
|
-
this.subscribes[type][key] = 1;
|
|
319
|
-
if (type === 'stateChange') {
|
|
320
|
-
this.adapter
|
|
321
|
-
.subscribeForeignStatesAsync(pattern, options)
|
|
322
|
-
.catch(e => this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`));
|
|
323
|
-
} else if (type === 'objectChange') {
|
|
324
|
-
this.adapter
|
|
325
|
-
.subscribeForeignObjectsAsync(pattern, options)
|
|
326
|
-
.catch(e => this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`));
|
|
327
|
-
} else if (type === 'log') {
|
|
328
|
-
if (!this.logEnabled && this.adapter.requireLog) {
|
|
329
|
-
this.logEnabled = true;
|
|
330
|
-
this.adapter.requireLog(true, options);
|
|
331
|
-
}
|
|
332
|
-
} else if (type === 'fileChange' && this.adapter.subscribeForeignFiles) {
|
|
333
|
-
this.adapter
|
|
334
|
-
.subscribeForeignFiles(pattern, patternFile, options)
|
|
335
|
-
.catch(e => this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`));
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
this.subscribes[type][key]++;
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
unsubscribe(socket, type, pattern, patternFile) {
|
|
343
|
-
if (!pattern) {
|
|
344
|
-
return this.adapter.log.warn('Empty pattern on subscribe!');
|
|
345
|
-
}
|
|
346
|
-
// console.log((socket._name || socket.id) + ' unsubscribe ' + pattern);
|
|
347
|
-
if (!this.subscribes[type]) {
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
let key;
|
|
352
|
-
pattern = pattern.toString();
|
|
353
|
-
if (patternFile && type === 'fileChange') {
|
|
354
|
-
patternFile = patternFile.toString();
|
|
355
|
-
key = `${pattern}####${patternFile}`;
|
|
356
|
-
} else {
|
|
357
|
-
key = pattern;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
const options = socket && socket._acl ? { user: socket._acl.user } : undefined;
|
|
361
|
-
|
|
362
|
-
if (socket && typeof socket === 'object') {
|
|
363
|
-
if (!socket.subscribe || !socket.subscribe[type]) {
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
for (let i = socket.subscribe[type].length - 1; i >= 0; i--) {
|
|
368
|
-
if (socket.subscribe[type][i].pattern === key) {
|
|
369
|
-
// Remove a pattern from a global list
|
|
370
|
-
if (this.subscribes[type][key] !== undefined) {
|
|
371
|
-
this.subscribes[type][key]--;
|
|
372
|
-
if (this.subscribes[type][key] <= 0) {
|
|
373
|
-
if (type === 'stateChange') {
|
|
374
|
-
this.adapter
|
|
375
|
-
.unsubscribeForeignStatesAsync(pattern, options)
|
|
376
|
-
.catch(e =>
|
|
377
|
-
this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`)
|
|
378
|
-
);
|
|
379
|
-
} else if (type === 'objectChange') {
|
|
380
|
-
this.adapter
|
|
381
|
-
.unsubscribeForeignObjectsAsync(pattern, options)
|
|
382
|
-
.catch(e =>
|
|
383
|
-
this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`)
|
|
384
|
-
);
|
|
385
|
-
} else if (type === 'log') {
|
|
386
|
-
if (this.logEnabled && this.adapter.requireLog) {
|
|
387
|
-
this.logEnabled = false;
|
|
388
|
-
this.adapter.requireLog(false, options);
|
|
389
|
-
}
|
|
390
|
-
} else if (type === 'fileChange' && this.adapter.unsubscribeForeignFiles) {
|
|
391
|
-
this.adapter
|
|
392
|
-
.unsubscribeForeignFiles(pattern, patternFile, options)
|
|
393
|
-
.catch(e =>
|
|
394
|
-
this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`)
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
delete this.subscribes[type][pattern];
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
delete socket.subscribe[type][i];
|
|
402
|
-
socket.subscribe[type].splice(i, 1);
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
} else if (key) {
|
|
407
|
-
// Remove a pattern from a global list
|
|
408
|
-
if (this.subscribes[type][key] !== undefined) {
|
|
409
|
-
this.subscribes[type][key]--;
|
|
410
|
-
if (this.subscribes[type][key] <= 0) {
|
|
411
|
-
if (type === 'stateChange') {
|
|
412
|
-
this.adapter
|
|
413
|
-
.unsubscribeForeignStatesAsync(pattern, options)
|
|
414
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
415
|
-
} else if (type === 'objectChange') {
|
|
416
|
-
this.adapter
|
|
417
|
-
.unsubscribeForeignObjectsAsync(pattern, options)
|
|
418
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
419
|
-
} else if (type === 'log') {
|
|
420
|
-
if (this.adapter.requireLog && this.logEnabled) {
|
|
421
|
-
this.logEnabled = false;
|
|
422
|
-
this.adapter.requireLog(false, options);
|
|
423
|
-
}
|
|
424
|
-
} else if (type === 'fileChange' && this.adapter.unsubscribeForeignFiles) {
|
|
425
|
-
this.adapter
|
|
426
|
-
.unsubscribeForeignFiles(pattern, patternFile, options)
|
|
427
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
428
|
-
}
|
|
429
|
-
delete this.subscribes[type][key];
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
} else {
|
|
433
|
-
for (const pattern of Object.keys(this.subscribes[type])) {
|
|
434
|
-
if (type === 'stateChange') {
|
|
435
|
-
this.adapter
|
|
436
|
-
.unsubscribeForeignStatesAsync(pattern, options)
|
|
437
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
438
|
-
} else if (type === 'objectChange') {
|
|
439
|
-
this.adapter
|
|
440
|
-
.unsubscribeForeignObjectsAsync(pattern, options)
|
|
441
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
442
|
-
} else if (type === 'log') {
|
|
443
|
-
// console.log((socket._name || socket.id) + ' requireLog false');
|
|
444
|
-
if (this.adapter.requireLog && this.logEnabled) {
|
|
445
|
-
this.logEnabled = false;
|
|
446
|
-
this.adapter.requireLog(false, options);
|
|
447
|
-
}
|
|
448
|
-
} else if (type === 'fileChange' && this.adapter.unsubscribeForeignFiles) {
|
|
449
|
-
const [id, fileName] = pattern.split('####');
|
|
450
|
-
this.adapter
|
|
451
|
-
.unsubscribeForeignFiles(id, fileName, options)
|
|
452
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
this.subscribes[type] = {};
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
subscribeSocket(socket, type) {
|
|
461
|
-
if (!socket || !socket.subscribe) {
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
if (!type) {
|
|
466
|
-
// all
|
|
467
|
-
return Object.keys(socket.subscribe).forEach(type => this.subscribeSocket(socket, type));
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (!socket.subscribe[type]) {
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const options = socket && socket._acl ? { user: socket._acl.user } : undefined;
|
|
475
|
-
|
|
476
|
-
for (let i = 0; i < socket.subscribe[type].length; i++) {
|
|
477
|
-
const pattern = socket.subscribe[type][i].pattern;
|
|
478
|
-
if (this.subscribes[type][pattern] === undefined) {
|
|
479
|
-
this.subscribes[type][pattern] = 1;
|
|
480
|
-
if (type === 'stateChange') {
|
|
481
|
-
this.adapter
|
|
482
|
-
.subscribeForeignStatesAsync(pattern, options)
|
|
483
|
-
.catch(e => this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`));
|
|
484
|
-
} else if (type === 'objectChange') {
|
|
485
|
-
this.adapter
|
|
486
|
-
.subscribeForeignObjectsAsync(pattern, options)
|
|
487
|
-
.catch(e => this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`));
|
|
488
|
-
} else if (type === 'log') {
|
|
489
|
-
if (this.adapter.requireLog && !this.logEnabled) {
|
|
490
|
-
this.logEnabled = true;
|
|
491
|
-
this.adapter.requireLog(true, options);
|
|
492
|
-
}
|
|
493
|
-
} else if (type === 'fileChange' && this.adapter.subscribeForeignFiles) {
|
|
494
|
-
const [id, fileName] = pattern.split('####');
|
|
495
|
-
this.adapter
|
|
496
|
-
.subscribeForeignFiles(id, fileName, options)
|
|
497
|
-
.catch(e => this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`));
|
|
498
|
-
}
|
|
499
|
-
} else {
|
|
500
|
-
this.subscribes[type][pattern]++;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
unsubscribeSocket(socket, type) {
|
|
506
|
-
if (!socket || !socket.subscribe) {
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
// inform all instances about disconnected socket
|
|
510
|
-
this._informAboutDisconnect(socket.id);
|
|
511
|
-
|
|
512
|
-
if (!type) {
|
|
513
|
-
// all
|
|
514
|
-
return Object.keys(socket.subscribe).forEach(type => this.unsubscribeSocket(socket, type));
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
if (!socket.subscribe[type]) {
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
const options = socket && socket._acl ? { user: socket._acl.user } : undefined;
|
|
522
|
-
|
|
523
|
-
for (let i = 0; i < socket.subscribe[type].length; i++) {
|
|
524
|
-
const pattern = socket.subscribe[type][i].pattern;
|
|
525
|
-
if (this.subscribes[type][pattern] !== undefined) {
|
|
526
|
-
this.subscribes[type][pattern]--;
|
|
527
|
-
if (this.subscribes[type][pattern] <= 0) {
|
|
528
|
-
if (type === 'stateChange') {
|
|
529
|
-
this.adapter
|
|
530
|
-
.unsubscribeForeignStatesAsync(pattern, options)
|
|
531
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
532
|
-
} else if (type === 'objectChange') {
|
|
533
|
-
this.adapter
|
|
534
|
-
.unsubscribeForeignObjectsAsync(pattern, options)
|
|
535
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
536
|
-
} else if (type === 'log') {
|
|
537
|
-
if (this.adapter.requireLog && !this.logEnabled) {
|
|
538
|
-
this.logEnabled = true;
|
|
539
|
-
this.adapter.requireLog(true, options);
|
|
540
|
-
}
|
|
541
|
-
} else if (type === 'fileChange' && this.adapter.unsubscribeForeignFiles) {
|
|
542
|
-
const [id, fileName] = pattern.split('####');
|
|
543
|
-
this.adapter
|
|
544
|
-
.unsubscribeForeignFiles(id, fileName, options)
|
|
545
|
-
.catch(e => this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`));
|
|
546
|
-
}
|
|
547
|
-
delete this.subscribes[type][pattern];
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
_subscribeStates(socket, pattern, callback) {
|
|
554
|
-
if (this._checkPermissions(socket, 'subscribe', callback, pattern)) {
|
|
555
|
-
if (Array.isArray(pattern)) {
|
|
556
|
-
for (let p = 0; p < pattern.length; p++) {
|
|
557
|
-
this.subscribe(socket, 'stateChange', pattern[p]);
|
|
558
|
-
}
|
|
559
|
-
} else {
|
|
560
|
-
this.subscribe(socket, 'stateChange', pattern);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
this.adapter.log.level === 'debug' && this._showSubscribes(socket, 'stateChange');
|
|
564
|
-
|
|
565
|
-
typeof callback === 'function' && setImmediate(callback, null);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
_unsubscribeStates(socket, pattern, callback) {
|
|
570
|
-
if (this._checkPermissions(socket, 'unsubscribe', callback, pattern)) {
|
|
571
|
-
if (Array.isArray(pattern)) {
|
|
572
|
-
for (let p = 0; p < pattern.length; p++) {
|
|
573
|
-
this.unsubscribe(socket, 'stateChange', pattern[p]);
|
|
574
|
-
}
|
|
575
|
-
} else {
|
|
576
|
-
this.unsubscribe(socket, 'stateChange', pattern);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
this.adapter.log.level === 'debug' && this._showSubscribes(socket, 'stateChange');
|
|
580
|
-
|
|
581
|
-
typeof callback === 'function' && setImmediate(callback, null);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
_subscribeFiles(socket, id, pattern, callback) {
|
|
586
|
-
if (this._checkPermissions(socket, 'subscribeFiles', callback, pattern)) {
|
|
587
|
-
if (Array.isArray(pattern)) {
|
|
588
|
-
for (let p = 0; p < pattern.length; p++) {
|
|
589
|
-
this.subscribe(socket, 'fileChange', id, pattern[p]);
|
|
590
|
-
}
|
|
591
|
-
} else {
|
|
592
|
-
this.subscribe(socket, 'fileChange', id, pattern);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
this.adapter.log.level === 'debug' && this._showSubscribes(socket, 'fileChange');
|
|
596
|
-
|
|
597
|
-
typeof callback === 'function' && setImmediate(callback, null);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
_unsubscribeFiles(socket, id, pattern, callback) {
|
|
602
|
-
if (this._checkPermissions(socket, 'unsubscribeFiles', callback, pattern)) {
|
|
603
|
-
if (Array.isArray(pattern)) {
|
|
604
|
-
for (let p = 0; p < pattern.length; p++) {
|
|
605
|
-
this.unsubscribe(socket, 'fileChange', id, pattern[p]);
|
|
606
|
-
}
|
|
607
|
-
} else {
|
|
608
|
-
this.unsubscribe(socket, 'fileChange', id, pattern);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
this.adapter.log.level === 'debug' && this._showSubscribes(socket, 'fileChange');
|
|
612
|
-
|
|
613
|
-
typeof callback === 'function' && setImmediate(callback, null);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
addCommandHandler(command, handler) {
|
|
618
|
-
if (handler) {
|
|
619
|
-
this.commands[command] = handler;
|
|
620
|
-
} else if (command in this.commands) {
|
|
621
|
-
delete this.commands[command];
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
getCommandHandler(command) {
|
|
626
|
-
return this.commands[command];
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
_fixAdminUI(obj) {
|
|
630
|
-
if (obj && obj.common && !obj.common.adminUI) {
|
|
631
|
-
if (obj.common.noConfig) {
|
|
632
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
633
|
-
obj.common.adminUI.config = 'none';
|
|
634
|
-
} else if (obj.common.jsonConfig) {
|
|
635
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
636
|
-
obj.common.adminUI.config = 'json';
|
|
637
|
-
} else if (obj.common.materialize) {
|
|
638
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
639
|
-
obj.common.adminUI.config = 'materialize';
|
|
640
|
-
} else {
|
|
641
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
642
|
-
obj.common.adminUI.config = 'html';
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
if (obj.common.jsonCustom) {
|
|
646
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
647
|
-
obj.common.adminUI.custom = 'json';
|
|
648
|
-
} else if (obj.common.supportCustoms) {
|
|
649
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
650
|
-
obj.common.adminUI.custom = 'json';
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
if (obj.common.materializeTab && obj.common.adminTab) {
|
|
654
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
655
|
-
obj.common.adminUI.tab = 'materialize';
|
|
656
|
-
} else if (obj.common.adminTab) {
|
|
657
|
-
obj.common.adminUI = obj.common.adminUI || {};
|
|
658
|
-
obj.common.adminUI.tab = 'html';
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
obj.common.adminUI &&
|
|
662
|
-
this.adapter.log.debug(
|
|
663
|
-
`Please add to "${obj._id.replace(/\.\d+$/, '')}" common.adminUI=${JSON.stringify(
|
|
664
|
-
obj.common.adminUI
|
|
665
|
-
)}`
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
__initCommandsCommon() {
|
|
671
|
-
this.commands['authenticate'] = (socket, user, pass, callback) => {
|
|
672
|
-
// Authenticate user by login and password
|
|
673
|
-
// @param {string} user - user name
|
|
674
|
-
// @param {string} pass - password
|
|
675
|
-
// @param {function} callback - `function (isUserAuthenticated, isAuthenticationUsed)`
|
|
676
|
-
if (socket && socket.___socket) {
|
|
677
|
-
socket = socket.___socket;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
this.adapter.log.debug(`${new Date().toISOString()} Request authenticate [${socket._acl.user}]`);
|
|
681
|
-
if (typeof user === 'function') {
|
|
682
|
-
callback = user;
|
|
683
|
-
// user = undefined;
|
|
684
|
-
}
|
|
685
|
-
if (socket._acl.user !== null) {
|
|
686
|
-
if (typeof callback === 'function') {
|
|
687
|
-
callback(true, socket._secure);
|
|
688
|
-
}
|
|
689
|
-
} else {
|
|
690
|
-
this.adapter.log.debug(`${new Date().toISOString()} Request authenticate [${socket._acl.user}]`);
|
|
691
|
-
socket._authPending = callback;
|
|
692
|
-
}
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
this.commands['error'] = (socket, error) => {
|
|
696
|
-
// Write error into ioBroker log
|
|
697
|
-
// @param {string} error - error text
|
|
698
|
-
this.adapter.log.error(`Socket error: ${error}`);
|
|
699
|
-
};
|
|
700
|
-
|
|
701
|
-
this.commands['log'] = (socket, text, level) => {
|
|
702
|
-
// Write log entry into ioBroker log
|
|
703
|
-
// @param {string} text - log text
|
|
704
|
-
// @param {string} level - one of `['silly', 'debug', 'info', 'warn', 'error']`. Default is 'debug'.
|
|
705
|
-
if (level === 'error') {
|
|
706
|
-
this.adapter.log.error(text);
|
|
707
|
-
} else if (level === 'warn') {
|
|
708
|
-
this.adapter.log.warn(text);
|
|
709
|
-
} else if (level === 'info') {
|
|
710
|
-
this.adapter.log.info(text);
|
|
711
|
-
} else {
|
|
712
|
-
this.adapter.log.debug(text);
|
|
713
|
-
}
|
|
714
|
-
};
|
|
715
|
-
|
|
716
|
-
this.commands['checkFeatureSupported'] = (socket, feature, callback) => {
|
|
717
|
-
// Checks, if the same feature is supported by the current js-controller
|
|
718
|
-
// @param {string} feature - feature name like `CONTROLLER_LICENSE_MANAGER`
|
|
719
|
-
// @param {function} callback - `function (error, isSupported)`
|
|
720
|
-
if (feature === 'INSTANCE_MESSAGES') {
|
|
721
|
-
SocketCommands._fixCallback(callback, null, true);
|
|
722
|
-
} else if (feature === 'PARTIAL_OBJECT_TREE') {
|
|
723
|
-
SocketCommands._fixCallback(callback, null, true);
|
|
724
|
-
} else {
|
|
725
|
-
SocketCommands._fixCallback(
|
|
726
|
-
callback,
|
|
727
|
-
null,
|
|
728
|
-
this.adapter.supportsFeature && this.adapter.supportsFeature(feature)
|
|
729
|
-
);
|
|
730
|
-
}
|
|
731
|
-
};
|
|
732
|
-
|
|
733
|
-
// new History
|
|
734
|
-
this.commands['getHistory'] = (socket, id, options, callback) => {
|
|
735
|
-
// Get history data from specific instance
|
|
736
|
-
// @param {string} id - object ID
|
|
737
|
-
// @param {object} options - See object description here: https://github.com/ioBroker/ioBroker.history/blob/master/docs/en/README.md#access-values-from-javascript-adapter
|
|
738
|
-
// @param {function} callback - `function (error, result)`
|
|
739
|
-
if (this._checkPermissions(socket, 'getStateHistory', callback, id)) {
|
|
740
|
-
if (typeof options === 'string') {
|
|
741
|
-
options = {
|
|
742
|
-
instance: options
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
options = options || {};
|
|
746
|
-
options.user = socket._acl.user;
|
|
747
|
-
options.aggregate = options.aggregate || 'none';
|
|
748
|
-
try {
|
|
749
|
-
this.adapter.getHistory(id, options, (error, ...args) =>
|
|
750
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
751
|
-
);
|
|
752
|
-
} catch (error) {
|
|
753
|
-
this.adapter.log.error(`[getHistory] ERROR: ${error.toString()}`);
|
|
754
|
-
SocketCommands._fixCallback(callback, error);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
};
|
|
758
|
-
|
|
759
|
-
// HTTP
|
|
760
|
-
this.commands['httpGet'] = (socket, url, callback) => {
|
|
761
|
-
// Read content of HTTP(S) page server-side (without CORS and stuff)
|
|
762
|
-
// @param {string} url - Page URL
|
|
763
|
-
// @param {function} callback - `function (error, {status, statusText}, body)`
|
|
764
|
-
if (this._checkPermissions(socket, 'httpGet', callback, url)) {
|
|
765
|
-
axios = axios || require('axios');
|
|
766
|
-
this.adapter.log.debug(`httpGet: ${url}`);
|
|
767
|
-
try {
|
|
768
|
-
axios(url, {
|
|
769
|
-
responseType: 'arraybuffer',
|
|
770
|
-
timeout: 15000,
|
|
771
|
-
validateStatus: status => status < 400
|
|
772
|
-
})
|
|
773
|
-
.then(result =>
|
|
774
|
-
callback(null, { status: result.status, statusText: result.statusText }, result.data)
|
|
775
|
-
)
|
|
776
|
-
.catch(error => callback(error));
|
|
777
|
-
} catch (error) {
|
|
778
|
-
callback(error);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
};
|
|
782
|
-
|
|
783
|
-
// commands
|
|
784
|
-
this.commands['sendTo'] = (socket, adapterInstance, command, message, callback) => {
|
|
785
|
-
// Send the message to specific instance
|
|
786
|
-
// @param {string} adapterInstance - instance name, e.g. `history.0`
|
|
787
|
-
// @param {string} command - command name
|
|
788
|
-
// @param {object} message - the message is instance dependent
|
|
789
|
-
// @param {function} callback - `function (result)`
|
|
790
|
-
if (this._checkPermissions(socket, 'sendTo', callback, command)) {
|
|
791
|
-
try {
|
|
792
|
-
this.adapter.sendTo(
|
|
793
|
-
adapterInstance,
|
|
794
|
-
command,
|
|
795
|
-
message,
|
|
796
|
-
res => typeof callback === 'function' && setImmediate(() => callback(res))
|
|
797
|
-
);
|
|
798
|
-
} catch (error) {
|
|
799
|
-
typeof callback === 'function' && setImmediate(() => callback({ error }));
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
};
|
|
803
|
-
|
|
804
|
-
// following commands are protected and require the extra permissions
|
|
805
|
-
const protectedCommands = [
|
|
806
|
-
'cmdExec',
|
|
807
|
-
'getLocationOnDisk',
|
|
808
|
-
'getDiagData',
|
|
809
|
-
'getDevList',
|
|
810
|
-
'delLogs',
|
|
811
|
-
'writeDirAsZip',
|
|
812
|
-
'writeObjectsAsZip',
|
|
813
|
-
'readObjectsAsZip',
|
|
814
|
-
'checkLogging',
|
|
815
|
-
'updateMultihost',
|
|
816
|
-
'rebuildAdapter'
|
|
817
|
-
];
|
|
818
|
-
|
|
819
|
-
this.commands['sendToHost'] = (socket, host, command, message, callback) => {
|
|
820
|
-
// Send a message to the specific host.
|
|
821
|
-
// Host can answer to the following commands: `cmdExec, getRepository, getInstalled, getInstalledAdapter, getVersion, getDiagData, getLocationOnDisk, getDevList, getLogs, getHostInfo, delLogs, readDirAsZip, writeDirAsZip, readObjectsAsZip, writeObjectsAsZip, checkLogging, updateMultihost`.
|
|
822
|
-
// @param {string} host - instance name, e.g. `history.0`
|
|
823
|
-
// @param {string} command - command name
|
|
824
|
-
// @param {object} message - the message is command-specific
|
|
825
|
-
// @param {function} callback - `function (result)`
|
|
826
|
-
if (
|
|
827
|
-
this._checkPermissions(
|
|
828
|
-
socket,
|
|
829
|
-
protectedCommands.includes(command) ? 'cmdExec' : 'sendToHost',
|
|
830
|
-
callback,
|
|
831
|
-
command
|
|
832
|
-
)
|
|
833
|
-
) {
|
|
834
|
-
// Try to decode this file locally as redis has a limitation for files bigger than 20MB
|
|
835
|
-
if (command === 'writeDirAsZip' && message && message.data.length > 1024 * 1024) {
|
|
836
|
-
let buffer;
|
|
837
|
-
try {
|
|
838
|
-
buffer = Buffer.from(message.data, 'base64');
|
|
839
|
-
} catch (error) {
|
|
840
|
-
this.adapter.log.error(`Cannot convert data: ${error.toString()}`);
|
|
841
|
-
return callback && callback({ error: `Cannot convert data: ${error.toString()}` });
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
zipFiles = zipFiles || utils.commonTools.zipFiles;
|
|
845
|
-
|
|
846
|
-
zipFiles
|
|
847
|
-
.writeDirAsZip(
|
|
848
|
-
this.adapter, // normally we have to pass here the internal "objects" object, but as
|
|
849
|
-
// only writeFile is used, and it has the same name, we can pass here the
|
|
850
|
-
// adapter, which has the function with the same name and arguments
|
|
851
|
-
message.id,
|
|
852
|
-
message.name,
|
|
853
|
-
buffer,
|
|
854
|
-
message.options,
|
|
855
|
-
error => callback({ error }) // this is for back compatibility with js-controller@4.0 or older
|
|
856
|
-
)
|
|
857
|
-
.then(() => callback({}))
|
|
858
|
-
.catch(error => {
|
|
859
|
-
this.adapter.log.error(`Cannot write zip file as folder: ${error.toString()}`);
|
|
860
|
-
callback && callback({ error });
|
|
861
|
-
});
|
|
862
|
-
} else if (this._sendToHost) {
|
|
863
|
-
this._sendToHost(host, command, message, callback);
|
|
864
|
-
} else {
|
|
865
|
-
try {
|
|
866
|
-
this.adapter.sendToHost(host, command, message, callback);
|
|
867
|
-
} catch (error) {
|
|
868
|
-
return callback && callback({ error });
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
};
|
|
873
|
-
|
|
874
|
-
this.commands['authEnabled'] = (socket, callback) => {
|
|
875
|
-
// Ask server is authentication enabled, and if the user authenticated
|
|
876
|
-
// @param {function} callback - `function (isAuthenticationUsed, userName)`
|
|
877
|
-
if (this._checkPermissions(socket, 'authEnabled', callback)) {
|
|
878
|
-
if (typeof callback === 'function') {
|
|
879
|
-
callback(this.adapter.config.auth, (socket._acl.user || '').replace(/^system\.user\./, ''));
|
|
880
|
-
} else {
|
|
881
|
-
this.adapter.log.warn('[authEnabled] Invalid callback');
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
};
|
|
885
|
-
|
|
886
|
-
this.commands['logout'] = (socket, callback) => {
|
|
887
|
-
// Logout user
|
|
888
|
-
// @param {function} callback - function (error)
|
|
889
|
-
if (socket.id) {
|
|
890
|
-
this.adapter.destroySession(socket.id, callback);
|
|
891
|
-
}
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
this.commands['listPermissions'] = (socket, callback) => {
|
|
895
|
-
// List commands and permissions
|
|
896
|
-
// @param {function} callback - `function (permissions)`
|
|
897
|
-
if (typeof callback === 'function') {
|
|
898
|
-
callback(SocketCommands.COMMANDS_PERMISSIONS);
|
|
899
|
-
} else {
|
|
900
|
-
this.adapter.log.warn('[listPermissions] Invalid callback');
|
|
901
|
-
}
|
|
902
|
-
};
|
|
903
|
-
|
|
904
|
-
this.commands['getUserPermissions'] = (socket, callback) => {
|
|
905
|
-
// Get user permissions
|
|
906
|
-
// @param {function} callback - `function (error, permissions)`
|
|
907
|
-
if (this._checkPermissions(socket, 'getUserPermissions', callback)) {
|
|
908
|
-
if (typeof callback === 'function') {
|
|
909
|
-
callback(null, socket._acl);
|
|
910
|
-
} else {
|
|
911
|
-
this.adapter.log.warn('[getUserPermissions] Invalid callback');
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
};
|
|
915
|
-
|
|
916
|
-
this.commands['getVersion'] = (socket, callback) => {
|
|
917
|
-
// Get the adapter version. Not the socket-classes version!
|
|
918
|
-
// @param {function} callback - `function (error, adapterVersion, adapterName)`
|
|
919
|
-
if (this._checkPermissions(socket, 'getVersion', callback)) {
|
|
920
|
-
if (typeof callback === 'function') {
|
|
921
|
-
callback(null, this.adapter.version, this.adapter.name);
|
|
922
|
-
} else {
|
|
923
|
-
this.adapter.log.warn('[getVersion] Invalid callback');
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
};
|
|
927
|
-
|
|
928
|
-
this.commands['getAdapterName'] = (socket, callback) => {
|
|
929
|
-
// Get adapter name. Not the socket-classes version!
|
|
930
|
-
// @param {function} callback - `function (error, adapterVersion)`
|
|
931
|
-
if (this._checkPermissions(socket, 'getAdapterName', callback)) {
|
|
932
|
-
if (typeof callback === 'function') {
|
|
933
|
-
callback(null, this.adapter.name || 'unknown');
|
|
934
|
-
} else {
|
|
935
|
-
this.adapter.log.warn('[getAdapterName] Invalid callback');
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
__initCommandsFiles() {
|
|
942
|
-
// file operations
|
|
943
|
-
this.commands['readFile'] = (socket, _adapter, fileName, callback) => {
|
|
944
|
-
// Read file from ioBroker DB
|
|
945
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
946
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
947
|
-
// @param {function} callback - `function (error, data, mimeType)`
|
|
948
|
-
if (this._checkPermissions(socket, 'readFile', callback, fileName)) {
|
|
949
|
-
try {
|
|
950
|
-
this.adapter.readFile(_adapter, fileName, { user: socket._acl.user }, (error, ...args) =>
|
|
951
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
952
|
-
);
|
|
953
|
-
} catch (error) {
|
|
954
|
-
this.adapter.log.error(`[readFile] ERROR: ${error.toString()}`);
|
|
955
|
-
SocketCommands._fixCallback(callback, error);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
};
|
|
959
|
-
|
|
960
|
-
this.commands['readFile64'] = (socket, _adapter, fileName, callback) => {
|
|
961
|
-
// Read file from ioBroker DB as base64 string
|
|
962
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
963
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
964
|
-
// @param {function} callback - `function (error, base64, mimeType)`
|
|
965
|
-
if (this._checkPermissions(socket, 'readFile64', callback, fileName)) {
|
|
966
|
-
try {
|
|
967
|
-
this.adapter.readFile(_adapter, fileName, { user: socket._acl.user }, (error, buffer, type) => {
|
|
968
|
-
let data64;
|
|
969
|
-
if (buffer) {
|
|
970
|
-
try {
|
|
971
|
-
if (
|
|
972
|
-
type === 'application/json' ||
|
|
973
|
-
type === 'application/json5' ||
|
|
974
|
-
fileName.toLowerCase().endsWith('.json5')
|
|
975
|
-
) {
|
|
976
|
-
data64 = Buffer.from(encodeURIComponent(buffer)).toString('base64');
|
|
977
|
-
} else {
|
|
978
|
-
if (typeof buffer === 'string') {
|
|
979
|
-
data64 = Buffer.from(buffer).toString('base64');
|
|
980
|
-
} else {
|
|
981
|
-
data64 = buffer.toString('base64');
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
} catch (error) {
|
|
985
|
-
this.adapter.log.error(`[readFile64] Cannot convert data: ${error.toString()}`);
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
// Convert buffer to base 64
|
|
990
|
-
if (typeof callback === 'function') {
|
|
991
|
-
callback(error, data64 || '', type);
|
|
992
|
-
} else {
|
|
993
|
-
this.adapter.log.warn('[readFile64] Invalid callback');
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
} catch (error) {
|
|
997
|
-
this.adapter.log.error(`[readFile64] ERROR: ${error.toString()}`);
|
|
998
|
-
SocketCommands._fixCallback(callback, error);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
};
|
|
1002
|
-
|
|
1003
|
-
this.commands['writeFile64'] = (socket, _adapter, fileName, data64, options, callback) => {
|
|
1004
|
-
// Write file into ioBroker DB as base64 string
|
|
1005
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1006
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
1007
|
-
// @param {string} data64 - file content as base64 string
|
|
1008
|
-
// @param {object} options - optional `{mode: 0x0644}`
|
|
1009
|
-
// @param {function} callback - `function (error)`
|
|
1010
|
-
if (typeof options === 'function') {
|
|
1011
|
-
callback = options;
|
|
1012
|
-
options = { user: socket._acl.user };
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
options = options || {};
|
|
1016
|
-
options.user = socket._acl.user;
|
|
1017
|
-
|
|
1018
|
-
if (this._checkPermissions(socket, 'writeFile64', callback, fileName)) {
|
|
1019
|
-
if (!data64) {
|
|
1020
|
-
return SocketCommands._fixCallback(callback, 'No data provided');
|
|
1021
|
-
}
|
|
1022
|
-
// Convert base 64 to buffer
|
|
1023
|
-
|
|
1024
|
-
try {
|
|
1025
|
-
const buffer = Buffer.from(data64, 'base64');
|
|
1026
|
-
this.adapter.writeFile(_adapter, fileName, buffer, options, (error, ...args) =>
|
|
1027
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1028
|
-
);
|
|
1029
|
-
} catch (error) {
|
|
1030
|
-
this.adapter.log.error(`[writeFile64] Cannot convert data: ${error.toString()}`);
|
|
1031
|
-
SocketCommands._fixCallback(callback, `Cannot convert data: ${error.toString()}`);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
};
|
|
1035
|
-
|
|
1036
|
-
// this function is overloaded in admin (because admin accepts only base64)
|
|
1037
|
-
this.commands['writeFile'] = (socket, _adapter, fileName, data, options, callback) => {
|
|
1038
|
-
// Write file into ioBroker DB as text **DEPRECATED**
|
|
1039
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1040
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
1041
|
-
// @param {string} data64 - file content as base64 string
|
|
1042
|
-
// @param {object} options - optional `{mode: 0x644}`
|
|
1043
|
-
// @param {function} callback - `function (error)`
|
|
1044
|
-
if (this._checkPermissions(socket, 'writeFile', callback, fileName)) {
|
|
1045
|
-
if (typeof options === 'function') {
|
|
1046
|
-
callback = options;
|
|
1047
|
-
options = { user: socket._acl.user };
|
|
1048
|
-
}
|
|
1049
|
-
options = options || {};
|
|
1050
|
-
options.user = socket._acl.user;
|
|
1051
|
-
this.adapter.log.debug('writeFile deprecated. Please use writeFile64');
|
|
1052
|
-
// const buffer = Buffer.from(data64, 'base64');
|
|
1053
|
-
try {
|
|
1054
|
-
this.adapter.writeFile(_adapter, fileName, data, options, (error, ...args) =>
|
|
1055
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1056
|
-
);
|
|
1057
|
-
} catch (error) {
|
|
1058
|
-
this.adapter.log.error(`[writeFile] ERROR: ${error.toString()}`);
|
|
1059
|
-
SocketCommands._fixCallback(callback, error);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
};
|
|
1063
|
-
|
|
1064
|
-
this.commands['unlink'] = (socket, _adapter, name, callback) => {
|
|
1065
|
-
// Delete file in ioBroker DB
|
|
1066
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1067
|
-
// @param {string} name - file name, e.g. `main/vis-views.json`
|
|
1068
|
-
// @param {function} callback - `function (error)`
|
|
1069
|
-
if (this._checkPermissions(socket, 'unlink', callback, name)) {
|
|
1070
|
-
try {
|
|
1071
|
-
this._unlink(_adapter, name, { user: socket._acl.user })
|
|
1072
|
-
.then(() => SocketCommands._fixCallback(callback))
|
|
1073
|
-
.catch(error => SocketCommands._fixCallback(callback, error));
|
|
1074
|
-
} catch (error) {
|
|
1075
|
-
this.adapter.log.error(`[unlink] ERROR: ${error.toString()}`);
|
|
1076
|
-
SocketCommands._fixCallback(callback, error);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
|
-
|
|
1081
|
-
this.commands['deleteFile'] = (socket, _adapter, name, callback) => {
|
|
1082
|
-
// Delete file in ioBroker DB (same as unlink, but only for files)
|
|
1083
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1084
|
-
// @param {string} name - file name, e.g. `main/vis-views.json`
|
|
1085
|
-
// @param {function} callback - `function (error)`
|
|
1086
|
-
if (this._checkPermissions(socket, 'unlink', callback, name)) {
|
|
1087
|
-
try {
|
|
1088
|
-
this.adapter.unlink(_adapter, name, { user: socket._acl.user }, (error, ...args) =>
|
|
1089
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1090
|
-
);
|
|
1091
|
-
} catch (error) {
|
|
1092
|
-
this.adapter.log.error(`[deleteFile] ERROR: ${error.toString()}`);
|
|
1093
|
-
SocketCommands._fixCallback(callback, error);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
};
|
|
1097
|
-
|
|
1098
|
-
this.commands['deleteFolder'] = (socket, _adapter, name, callback) => {
|
|
1099
|
-
// Delete file in ioBroker DB (same as unlink, but only for folders)
|
|
1100
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1101
|
-
// @param {string} name - folder name, e.g. `main`
|
|
1102
|
-
// @param {function} callback - `function (error)`
|
|
1103
|
-
if (this._checkPermissions(socket, 'unlink', callback, name)) {
|
|
1104
|
-
try {
|
|
1105
|
-
this._unlink(_adapter, name, { user: socket._acl.user })
|
|
1106
|
-
.then(() => SocketCommands._fixCallback(callback, null))
|
|
1107
|
-
.catch(error => SocketCommands._fixCallback(callback, error));
|
|
1108
|
-
} catch (error) {
|
|
1109
|
-
this.adapter.log.error(`[deleteFolder] ERROR: ${error.toString()}`);
|
|
1110
|
-
SocketCommands._fixCallback(callback, error);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
};
|
|
1114
|
-
|
|
1115
|
-
this.commands['renameFile'] = (socket, _adapter, oldName, newName, callback) => {
|
|
1116
|
-
// Rename file in ioBroker DB
|
|
1117
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1118
|
-
// @param {string} oldName - current file name, e.g. `main/vis-views.json`
|
|
1119
|
-
// @param {string} newName - new file name, e.g. `main/vis-views-new.json`
|
|
1120
|
-
// @param {function} callback - `function (error)`
|
|
1121
|
-
if (this._checkPermissions(socket, 'rename', callback, oldName)) {
|
|
1122
|
-
try {
|
|
1123
|
-
this.adapter.rename(_adapter, oldName, newName, { user: socket._acl.user }, (error, ...args) =>
|
|
1124
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1125
|
-
);
|
|
1126
|
-
} catch (error) {
|
|
1127
|
-
this.adapter.log.error(`[renameFile] ERROR: ${error.toString()}`);
|
|
1128
|
-
SocketCommands._fixCallback(callback, error);
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
};
|
|
1132
|
-
|
|
1133
|
-
this.commands['rename'] = (socket, _adapter, oldName, newName, callback) => {
|
|
1134
|
-
// Rename file or folder in ioBroker DB
|
|
1135
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1136
|
-
// @param {string} oldName - current file name, e.g. `main/vis-views.json`
|
|
1137
|
-
// @param {string} newName - new file name, e.g. `main/vis-views-new.json`
|
|
1138
|
-
// @param {function} callback - `function (error)`
|
|
1139
|
-
if (this._checkPermissions(socket, 'rename', callback, oldName)) {
|
|
1140
|
-
try {
|
|
1141
|
-
this._rename(_adapter, oldName, newName, { user: socket._acl.user })
|
|
1142
|
-
.then(() => SocketCommands._fixCallback(callback))
|
|
1143
|
-
.catch(error => SocketCommands._fixCallback(callback, error));
|
|
1144
|
-
} catch (error) {
|
|
1145
|
-
this.adapter.log.error(`[rename] ERROR: ${error.toString()}`);
|
|
1146
|
-
SocketCommands._fixCallback(callback, error);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
};
|
|
1150
|
-
|
|
1151
|
-
this.commands['mkdir'] = (socket, _adapter, dirName, callback) => {
|
|
1152
|
-
// Create folder in ioBroker DB
|
|
1153
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1154
|
-
// @param {string} dirName - desired folder name, e.g. `main`
|
|
1155
|
-
// @param {function} callback - `function (error)`
|
|
1156
|
-
if (this._checkPermissions(socket, 'mkdir', callback, dirName)) {
|
|
1157
|
-
try {
|
|
1158
|
-
this.adapter.mkdir(_adapter, dirName, { user: socket._acl.user }, (error, ...args) =>
|
|
1159
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1160
|
-
);
|
|
1161
|
-
} catch (error) {
|
|
1162
|
-
this.adapter.log.error(`[mkdir] ERROR: ${error.toString()}`);
|
|
1163
|
-
SocketCommands._fixCallback(callback, error);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
};
|
|
1167
|
-
|
|
1168
|
-
this.commands['readDir'] = (socket, _adapter, dirName, options, callback) => {
|
|
1169
|
-
// Read content of folder in ioBroker DB
|
|
1170
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1171
|
-
// @param {string} dirName - folder name, e.g. `main`
|
|
1172
|
-
// @param {object} options - optional `{filter: '*'}` or `{filter: '*.json'}`
|
|
1173
|
-
// @param {function} callback - `function (error, files)` where `files` is an array of objects, like `{file: 'vis-views.json', isDir: false, stats: {size: 123}, modifiedAt: 1661336290090, acl: {owner: 'system.user.admin', ownerGroup: 'system.group.administrator', permissions: 1632, read: true, write: true}`
|
|
1174
|
-
if (typeof options === 'function') {
|
|
1175
|
-
callback = options;
|
|
1176
|
-
options = {};
|
|
1177
|
-
}
|
|
1178
|
-
options = options || {};
|
|
1179
|
-
options.user = socket._acl.user;
|
|
1180
|
-
|
|
1181
|
-
if (options.filter === undefined) {
|
|
1182
|
-
options.filter = true;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
if (this._checkPermissions(socket, 'readDir', callback, dirName)) {
|
|
1186
|
-
try {
|
|
1187
|
-
this.adapter.readDir(_adapter, dirName, { user: socket._acl.user }, (error, ...args) =>
|
|
1188
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1189
|
-
);
|
|
1190
|
-
} catch (error) {
|
|
1191
|
-
this.adapter.log.error(`[readDir] ERROR: ${error.toString()}`);
|
|
1192
|
-
SocketCommands._fixCallback(callback, error);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
};
|
|
1196
|
-
|
|
1197
|
-
this.commands['chmodFile'] = (socket, _adapter, fileName, options, callback) => {
|
|
1198
|
-
// Change file mode in ioBroker DB
|
|
1199
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1200
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
1201
|
-
// @param {object} options - `{mode: 0x644}` or 0x644. The first digit is user, second group, third others. Bit 1 is `execute`, bit 2 is `write`, bit 3 is `read`
|
|
1202
|
-
// @param {function} callback - `function (error)`
|
|
1203
|
-
if (typeof options === 'function') {
|
|
1204
|
-
callback = options;
|
|
1205
|
-
options = {};
|
|
1206
|
-
}
|
|
1207
|
-
options = options || {};
|
|
1208
|
-
options.user = socket._acl.user;
|
|
1209
|
-
|
|
1210
|
-
if (options.filter === undefined) {
|
|
1211
|
-
options.filter = true;
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
if (this._checkPermissions(socket, 'chmodFile', callback, fileName)) {
|
|
1215
|
-
try {
|
|
1216
|
-
this.adapter.chmodFile(_adapter, fileName, options, (error, ...args) =>
|
|
1217
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1218
|
-
);
|
|
1219
|
-
} catch (error) {
|
|
1220
|
-
this.adapter.log.error(`[chmodFile] ERROR: ${error.toString()}`);
|
|
1221
|
-
SocketCommands._fixCallback(callback, error);
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
};
|
|
1225
|
-
|
|
1226
|
-
this.commands['chownFile'] = (socket, _adapter, fileName, options, callback) => {
|
|
1227
|
-
// Change file owner in ioBroker DB
|
|
1228
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1229
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
1230
|
-
// @param {object} options - `{owner: 'system.user.user', ownerGroup: ''system.group.administrator'}` or 'system.user.user'. If ownerGroup is not defined, it will be taken from owner.
|
|
1231
|
-
// @param {function} callback - `function (error)`
|
|
1232
|
-
if (this._checkPermissions(socket, 'chownFile', callback, fileName)) {
|
|
1233
|
-
options = options || {};
|
|
1234
|
-
options.user = socket._acl.user;
|
|
1235
|
-
try {
|
|
1236
|
-
this.adapter.chownFile(_adapter, fileName, options, (error, ...args) =>
|
|
1237
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1238
|
-
);
|
|
1239
|
-
} catch (error) {
|
|
1240
|
-
this.adapter.log.error(`[chownFile] ERROR: ${error.toString()}`);
|
|
1241
|
-
SocketCommands._fixCallback(callback, error);
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
};
|
|
1245
|
-
|
|
1246
|
-
this.commands['fileExists'] = (socket, _adapter, fileName, callback) => {
|
|
1247
|
-
// Check if the file or folder exists in ioBroker DB
|
|
1248
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1249
|
-
// @param {string} fileName - file name, e.g. `main/vis-views.json`
|
|
1250
|
-
// @param {function} callback - `function (error, isExist)`
|
|
1251
|
-
if (this._checkPermissions(socket, 'fileExists', callback, fileName)) {
|
|
1252
|
-
try {
|
|
1253
|
-
this.adapter.fileExists(_adapter, fileName, { user: socket._acl.user }, (error, ...args) =>
|
|
1254
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1255
|
-
);
|
|
1256
|
-
} catch (error) {
|
|
1257
|
-
this.adapter.log.error(`[fileExists] ERROR: ${error.toString()}`);
|
|
1258
|
-
SocketCommands._fixCallback(callback, error);
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
};
|
|
1262
|
-
|
|
1263
|
-
this.commands['subscribeFiles'] = (socket, id, pattern, callback) => {
|
|
1264
|
-
// Subscribe to file changes in ioBroker DB
|
|
1265
|
-
// @param {string} id - instance name, e.g. `vis.0` or any object ID of type `meta`. `id` could have wildcards `*` too.
|
|
1266
|
-
// @param {string} pattern - file name pattern, e.g. `main/*.json`
|
|
1267
|
-
// @param {function} callback - `function (error)`
|
|
1268
|
-
return this._subscribeFiles(socket, id, pattern, callback);
|
|
1269
|
-
};
|
|
1270
|
-
|
|
1271
|
-
this.commands['unsubscribeFiles'] = (socket, id, pattern, callback) => {
|
|
1272
|
-
// Unsubscribe from file changes in ioBroker DB
|
|
1273
|
-
// @param {string} id - instance name, e.g. `vis.0` or any object ID of type `meta`. `id` could have wildcards `*` too.
|
|
1274
|
-
// @param {string} pattern - file name pattern, e.g. `main/*.json`
|
|
1275
|
-
// @param {function} callback - `function (error)`
|
|
1276
|
-
|
|
1277
|
-
return this._unsubscribeFiles(socket, id, pattern, callback);
|
|
1278
|
-
};
|
|
1279
|
-
|
|
1280
|
-
this.commands['getAdapterInstances'] = (socket, adapterName, callback) => {
|
|
1281
|
-
// Read all instances of the given adapter, or all instances of all adapters if adapterName is not defined
|
|
1282
|
-
// @param {string} adapterName - optional adapter name, e.g. `history`.
|
|
1283
|
-
// @param {function} callback - `function (error, instanceList)`, where instanceList is an array of instance objects, e.g. `{_id: 'system.adapter.history.0', common: {name: 'history', ...}, native: {...}}`
|
|
1284
|
-
if (typeof callback === 'function') {
|
|
1285
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1286
|
-
let _adapterName =
|
|
1287
|
-
adapterName !== undefined && adapterName !== null ? adapterName : this.adapterName || '';
|
|
1288
|
-
if (_adapterName) {
|
|
1289
|
-
_adapterName += '.';
|
|
1290
|
-
}
|
|
1291
|
-
try {
|
|
1292
|
-
this.adapter.getObjectView(
|
|
1293
|
-
'system',
|
|
1294
|
-
'instance',
|
|
1295
|
-
{
|
|
1296
|
-
startkey: `system.adapter.${_adapterName}`,
|
|
1297
|
-
endkey: `system.adapter.${_adapterName}\u9999`
|
|
1298
|
-
},
|
|
1299
|
-
{ user: socket._acl.user },
|
|
1300
|
-
(error, doc) => {
|
|
1301
|
-
if (error) {
|
|
1302
|
-
callback(error);
|
|
1303
|
-
} else {
|
|
1304
|
-
callback(
|
|
1305
|
-
null,
|
|
1306
|
-
doc.rows
|
|
1307
|
-
.map(item => {
|
|
1308
|
-
const obj = item.value;
|
|
1309
|
-
if (obj.common) {
|
|
1310
|
-
delete obj.common.news;
|
|
1311
|
-
}
|
|
1312
|
-
this._fixAdminUI(obj);
|
|
1313
|
-
return obj;
|
|
1314
|
-
})
|
|
1315
|
-
.filter(
|
|
1316
|
-
obj =>
|
|
1317
|
-
obj &&
|
|
1318
|
-
(!adapterName || (obj.common && obj.common.name === adapterName))
|
|
1319
|
-
)
|
|
1320
|
-
);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
);
|
|
1324
|
-
} catch (error) {
|
|
1325
|
-
this.adapter.log.error(`[getAdapterInstances] ERROR: ${error.toString()}`);
|
|
1326
|
-
SocketCommands._fixCallback(callback, error);
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
};
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
__initCommandsStates() {
|
|
1334
|
-
this.commands['getStates'] = (socket, pattern, callback) => {
|
|
1335
|
-
// Read states by pattern
|
|
1336
|
-
// @param {string} pattern - optional pattern, like `system.adapter.*` or array of state IDs
|
|
1337
|
-
// @param {function} callback - `function (error, states)`, where `states` is an object like `{'system.adapter.history.0': {_id: 'system.adapter.history.0', common: {name: 'history', ...}, native: {...}, 'system.adapter.history.1': {...}}}`
|
|
1338
|
-
if (this._checkPermissions(socket, 'getStates', callback, pattern)) {
|
|
1339
|
-
if (typeof pattern === 'function') {
|
|
1340
|
-
callback = pattern;
|
|
1341
|
-
pattern = null;
|
|
1342
|
-
}
|
|
1343
|
-
if (typeof callback === 'function') {
|
|
1344
|
-
try {
|
|
1345
|
-
this.adapter.getForeignStates(pattern || '*', { user: socket._acl.user }, (error, ...args) =>
|
|
1346
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1347
|
-
);
|
|
1348
|
-
} catch (error) {
|
|
1349
|
-
this.adapter.log.error(`[getStates] ERROR: ${error.toString()}`);
|
|
1350
|
-
SocketCommands._fixCallback(callback, error);
|
|
1351
|
-
}
|
|
1352
|
-
} else {
|
|
1353
|
-
this.adapter.log.warn('[getStates] Invalid callback');
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
};
|
|
1357
|
-
|
|
1358
|
-
this.commands['getForeignStates'] = (socket, pattern, callback) => {
|
|
1359
|
-
// Read all states (which might not belong to this adapter) which match the given pattern
|
|
1360
|
-
// @param {string} pattern - pattern like `system.adapter.*` or array of state IDs
|
|
1361
|
-
// @param {function} callback - `function (error)`
|
|
1362
|
-
if (this._checkPermissions(socket, 'getStates', callback)) {
|
|
1363
|
-
if (typeof callback === 'function') {
|
|
1364
|
-
try {
|
|
1365
|
-
this.adapter.getForeignStates(pattern, { user: socket._acl.user }, (error, ...args) =>
|
|
1366
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1367
|
-
);
|
|
1368
|
-
} catch (error) {
|
|
1369
|
-
this.adapter.log.error(`[getForeignStates] ERROR: ${error}`);
|
|
1370
|
-
SocketCommands._fixCallback(callback, error);
|
|
1371
|
-
}
|
|
1372
|
-
} else {
|
|
1373
|
-
this.adapter.log.warn('[getForeignStates] Invalid callback');
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
};
|
|
1377
|
-
|
|
1378
|
-
this.commands['getState'] = (socket, id, callback) => {
|
|
1379
|
-
// Read one state.
|
|
1380
|
-
// @param {string} id - State ID like, 'system.adapter.admin.0.memRss'
|
|
1381
|
-
// @param {function} callback - `function (error, state)`, where `state` is an object like `{val: 123, ts: 1663915537418, ack: true, from: 'system.adapter.admin.0', q: 0, lc: 1663915537418, c: 'javascript.0'}`
|
|
1382
|
-
if (this._checkPermissions(socket, 'getState', callback, id)) {
|
|
1383
|
-
if (typeof callback === 'function') {
|
|
1384
|
-
if (this.states && this.states[id]) {
|
|
1385
|
-
callback(null, this.states[id]);
|
|
1386
|
-
} else {
|
|
1387
|
-
try {
|
|
1388
|
-
this.adapter.getForeignState(id, { user: socket._acl.user }, (error, ...args) =>
|
|
1389
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1390
|
-
);
|
|
1391
|
-
} catch (error) {
|
|
1392
|
-
this.adapter.log.error(`[getState] ERROR: ${error.toString()}`);
|
|
1393
|
-
SocketCommands._fixCallback(callback, error);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
} else {
|
|
1397
|
-
this.adapter.log.warn('[getState] Invalid callback');
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
};
|
|
1401
|
-
|
|
1402
|
-
this.commands['setState'] = (socket, id, state, callback) => {
|
|
1403
|
-
// Write one state.
|
|
1404
|
-
// @param {string} id - State ID like, 'system.adapter.admin.0.memRss'
|
|
1405
|
-
// @param {any} state - value or object like `{val: 123, ack: true}`
|
|
1406
|
-
// @param {function} callback - `function (error, state)`, where `state` is an object like `{val: 123, ts: 1663915537418, ack: true, from: 'system.adapter.admin.0', q: 0, lc: 1663915537418, c: 'javascript.0'}`
|
|
1407
|
-
if (this._checkPermissions(socket, 'setState', callback, id)) {
|
|
1408
|
-
if (typeof state !== 'object') {
|
|
1409
|
-
state = { val: state };
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
// clear cache
|
|
1413
|
-
if (this.states && this.states[id]) {
|
|
1414
|
-
delete this.states[id];
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
try {
|
|
1418
|
-
this.adapter.setForeignState(id, state, { user: socket._acl.user }, (error, ...args) =>
|
|
1419
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1420
|
-
);
|
|
1421
|
-
} catch (error) {
|
|
1422
|
-
this.adapter.log.error(`[setState] ERROR: ${error.toString()}`);
|
|
1423
|
-
SocketCommands._fixCallback(callback, error);
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
};
|
|
1427
|
-
|
|
1428
|
-
this.commands['getBinaryState'] = (socket, id, callback) => {
|
|
1429
|
-
// Read one binary state.
|
|
1430
|
-
// @param {string} id - State ID like, 'javascript.0.binary'
|
|
1431
|
-
// @param {function} callback - `function (error, base64)`
|
|
1432
|
-
if (this._checkPermissions(socket, 'getState', callback, id)) {
|
|
1433
|
-
if (typeof callback === 'function') {
|
|
1434
|
-
try {
|
|
1435
|
-
if (this.adapter.getForeignBinaryState) {
|
|
1436
|
-
this.adapter.getForeignBinaryState(id, { user: socket._acl.user }, (error, data) => {
|
|
1437
|
-
if (data) {
|
|
1438
|
-
try {
|
|
1439
|
-
data = Buffer.from(data).toString('base64');
|
|
1440
|
-
} catch (error) {
|
|
1441
|
-
this.adapter.log.error(
|
|
1442
|
-
`[getBinaryState] Cannot convert data: ${error.toString()}`
|
|
1443
|
-
);
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
SocketCommands._fixCallback(callback, error, data);
|
|
1447
|
-
});
|
|
1448
|
-
} else {
|
|
1449
|
-
this.adapter.getBinaryState(id, { user: socket._acl.user }, (error, data) => {
|
|
1450
|
-
if (data) {
|
|
1451
|
-
try {
|
|
1452
|
-
data = Buffer.from(data).toString('base64');
|
|
1453
|
-
} catch (error) {
|
|
1454
|
-
this.adapter.log.error(
|
|
1455
|
-
`[getBinaryState] Cannot convert data: ${error.toString()}`
|
|
1456
|
-
);
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
SocketCommands._fixCallback(callback, error, data);
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
} catch (error) {
|
|
1463
|
-
this.adapter.log.error(`[getBinaryState] ERROR: ${error.toString()}`);
|
|
1464
|
-
SocketCommands._fixCallback(callback, error);
|
|
1465
|
-
}
|
|
1466
|
-
} else {
|
|
1467
|
-
this.adapter.log.warn('[getBinaryState] Invalid callback');
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
};
|
|
1471
|
-
|
|
1472
|
-
this.commands['setBinaryState'] = (socket, id, base64, callback) => {
|
|
1473
|
-
// Write one binary state.
|
|
1474
|
-
// @param {string} id - State ID like, 'javascript.0.binary'
|
|
1475
|
-
// @param {string} base64 - State value as base64 string. Binary states have no acknowledged flag.
|
|
1476
|
-
// @param {function} callback - `function (error)`
|
|
1477
|
-
if (this._checkPermissions(socket, 'setState', callback, id)) {
|
|
1478
|
-
if (typeof callback === 'function') {
|
|
1479
|
-
let data = null;
|
|
1480
|
-
try {
|
|
1481
|
-
data = Buffer.from(base64, 'base64');
|
|
1482
|
-
} catch (error) {
|
|
1483
|
-
this.adapter.log.warn(`[setBinaryState] Cannot convert base64 data: ${error.toString()}`);
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
try {
|
|
1487
|
-
if (this.adapter.setForeignBinaryState) {
|
|
1488
|
-
this.adapter.setForeignBinaryState(id, data, { user: socket._acl.user }, (error, ...args) =>
|
|
1489
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1490
|
-
);
|
|
1491
|
-
} else {
|
|
1492
|
-
this.adapter.setBinaryState(id, data, { user: socket._acl.user }, (error, ...args) =>
|
|
1493
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
} catch (error) {
|
|
1497
|
-
this.adapter.log.error(`[setBinaryState] ERROR: ${error.toString()}`);
|
|
1498
|
-
SocketCommands._fixCallback(callback, error);
|
|
1499
|
-
}
|
|
1500
|
-
} else {
|
|
1501
|
-
this.adapter.log.warn('[setBinaryState] Invalid callback');
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
};
|
|
1505
|
-
|
|
1506
|
-
this.commands['subscribe'] = (socket, pattern, callback) => {
|
|
1507
|
-
// Subscribe to state changes by pattern. The events will come as 'stateChange' events to the socket.
|
|
1508
|
-
// @param {string} pattern - pattern like 'system.adapter.*' or array of states like ['system.adapter.admin.0.memRss', 'system.adapter.admin.0.memHeapTotal']
|
|
1509
|
-
// @param {function} callback - `function (error)`
|
|
1510
|
-
return this._subscribeStates(socket, pattern, callback);
|
|
1511
|
-
};
|
|
1512
|
-
|
|
1513
|
-
this.commands['subscribeStates'] = (socket, pattern, callback) => {
|
|
1514
|
-
// Subscribe to state changes by pattern. Same as `subscribe`. The events will come as 'stateChange' events to the socket.
|
|
1515
|
-
// @param {string} pattern - pattern like 'system.adapter.*' or array of states like ['system.adapter.admin.0.memRss', 'system.adapter.admin.0.memHeapTotal']
|
|
1516
|
-
// @param {function} callback - `function (error)`
|
|
1517
|
-
return this._subscribeStates(socket, pattern, callback);
|
|
1518
|
-
};
|
|
1519
|
-
|
|
1520
|
-
this.commands['unsubscribe'] = (socket, pattern, callback) => {
|
|
1521
|
-
// Unsubscribe from state changes by pattern.
|
|
1522
|
-
// @param {string} pattern - pattern like 'system.adapter.*' or array of states like ['system.adapter.admin.0.memRss', 'system.adapter.admin.0.memHeapTotal']
|
|
1523
|
-
// @param {function} callback - `function (error)`
|
|
1524
|
-
return this._unsubscribeStates(socket, pattern, callback);
|
|
1525
|
-
};
|
|
1526
|
-
|
|
1527
|
-
this.commands['unsubscribeStates'] = (socket, pattern, callback) => {
|
|
1528
|
-
// Unsubscribe from state changes by pattern. Same as `unsubscribe`.
|
|
1529
|
-
// @param {string} pattern - pattern like 'system.adapter.*' or array of states like ['system.adapter.admin.0.memRss', 'system.adapter.admin.0.memHeapTotal']
|
|
1530
|
-
// @param {function} callback - `function (error)`
|
|
1531
|
-
return this._unsubscribeStates(socket, pattern, callback);
|
|
1532
|
-
};
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
__initCommandsObjects() {
|
|
1536
|
-
this.commands['getObject'] = (socket, id, callback) => {
|
|
1537
|
-
// Get one object
|
|
1538
|
-
// @param {string} id - object ID.
|
|
1539
|
-
// @param {function} callback - `function (error, obj)`
|
|
1540
|
-
if (this._checkPermissions(socket, 'getObject', callback, id)) {
|
|
1541
|
-
try {
|
|
1542
|
-
this.adapter.getForeignObject(id, { user: socket._acl.user }, (error, obj) => {
|
|
1543
|
-
// overload language from current instance
|
|
1544
|
-
if (this.adapter._language && id === 'system.config' && obj.common) {
|
|
1545
|
-
obj.common.language = this.adapter._language;
|
|
1546
|
-
}
|
|
1547
|
-
SocketCommands._fixCallback(callback, error, obj);
|
|
1548
|
-
});
|
|
1549
|
-
} catch (error) {
|
|
1550
|
-
this.adapter.log.error(`[getObject] ERROR: ${error.toString()}`);
|
|
1551
|
-
SocketCommands._fixCallback(callback, error);
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
};
|
|
1555
|
-
|
|
1556
|
-
// not admin version of "all objects"
|
|
1557
|
-
// this function is overloaded in admin
|
|
1558
|
-
this.commands['getObjects'] = (socket, list, callback) => {
|
|
1559
|
-
// Get all objects that are relevant for web: all states and enums with rooms
|
|
1560
|
-
// @param {string} id - object ID.
|
|
1561
|
-
// @param {string[]} list - optional list of IDs.
|
|
1562
|
-
// @param {function} callback - `function (error, obj)`
|
|
1563
|
-
if (typeof list === 'function') {
|
|
1564
|
-
callback = list;
|
|
1565
|
-
list = null;
|
|
1566
|
-
}
|
|
1567
|
-
if (list && list.length) {
|
|
1568
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1569
|
-
if (typeof callback === 'function') {
|
|
1570
|
-
try {
|
|
1571
|
-
this.adapter.getForeignObjects(list, { user: socket._acl.user }, (error, objs) =>
|
|
1572
|
-
SocketCommands._fixCallback(callback, error, objs)
|
|
1573
|
-
);
|
|
1574
|
-
} catch (error) {
|
|
1575
|
-
this.adapter.log.error(`[getObjects] ERROR: ${error.toString()}`);
|
|
1576
|
-
SocketCommands._fixCallback(callback, error);
|
|
1577
|
-
}
|
|
1578
|
-
} else {
|
|
1579
|
-
this.adapter.log.warn('[getObjects] Invalid callback');
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
} else if (this._checkPermissions(socket, 'getObjects', callback)) {
|
|
1583
|
-
try {
|
|
1584
|
-
if (typeof callback === 'function') {
|
|
1585
|
-
this.adapter.getForeignObjects(
|
|
1586
|
-
'*',
|
|
1587
|
-
'state',
|
|
1588
|
-
'rooms',
|
|
1589
|
-
{ user: socket._acl.user },
|
|
1590
|
-
async (error, objs) => {
|
|
1591
|
-
try {
|
|
1592
|
-
const channels = await this.adapter.getForeignObjectsAsync('*', 'channel', null, {
|
|
1593
|
-
user: socket._acl.user
|
|
1594
|
-
});
|
|
1595
|
-
const devices = await this.adapter.getForeignObjectsAsync('*', 'device', null, {
|
|
1596
|
-
user: socket._acl.user
|
|
1597
|
-
});
|
|
1598
|
-
const enums = await this.adapter.getForeignObjectsAsync('*', 'enum', null, {
|
|
1599
|
-
user: socket._acl.user
|
|
1600
|
-
});
|
|
1601
|
-
const config = await this.adapter.getForeignObjectAsync('system.config', {
|
|
1602
|
-
user: socket._acl.user
|
|
1603
|
-
});
|
|
1604
|
-
Object.assign(objs, channels, devices, enums);
|
|
1605
|
-
objs['system.config'] = config;
|
|
1606
|
-
} catch (e) {
|
|
1607
|
-
this.adapter.log.error(`[getObjects] ERROR: ${e.toString()}`);
|
|
1608
|
-
}
|
|
1609
|
-
// overload language
|
|
1610
|
-
if (this.adapter._language && objs['system.config'] && objs['system.config'].common) {
|
|
1611
|
-
objs['system.config'].common.language = this.adapter._language;
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
SocketCommands._fixCallback(callback, error, objs);
|
|
1615
|
-
}
|
|
1616
|
-
);
|
|
1617
|
-
} else {
|
|
1618
|
-
this.adapter.log.warn('[getObjects] Invalid callback');
|
|
1619
|
-
}
|
|
1620
|
-
} catch (error) {
|
|
1621
|
-
this.adapter.log.error(`[getObjects] ERROR: ${error.toString()}`);
|
|
1622
|
-
SocketCommands._fixCallback(callback, error);
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
};
|
|
1626
|
-
|
|
1627
|
-
this.commands['subscribeObjects'] = (socket, pattern, callback) => {
|
|
1628
|
-
// Subscribe to object changes by pattern. The events will come as 'objectChange' events to the socket.
|
|
1629
|
-
// @param {string} pattern - pattern like 'system.adapter.*' or array of IDs like ['system.adapter.admin.0.memRss', 'system.adapter.admin.0.memHeapTotal']
|
|
1630
|
-
// @param {function} callback - `function (error)`
|
|
1631
|
-
if (this._checkPermissions(socket, 'subscribeObjects', callback, pattern)) {
|
|
1632
|
-
try {
|
|
1633
|
-
if (Array.isArray(pattern)) {
|
|
1634
|
-
for (let p = 0; p < pattern.length; p++) {
|
|
1635
|
-
this.subscribe(socket, 'objectChange', pattern[p]);
|
|
1636
|
-
}
|
|
1637
|
-
} else {
|
|
1638
|
-
this.subscribe(socket, 'objectChange', pattern);
|
|
1639
|
-
}
|
|
1640
|
-
if (typeof callback === 'function') {
|
|
1641
|
-
setImmediate(callback, null);
|
|
1642
|
-
}
|
|
1643
|
-
} catch (error) {
|
|
1644
|
-
if (typeof callback === 'function') {
|
|
1645
|
-
setImmediate(callback, error);
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
}
|
|
1649
|
-
};
|
|
1650
|
-
|
|
1651
|
-
this.commands['unsubscribeObjects'] = (socket, pattern, callback) => {
|
|
1652
|
-
// Unsubscribe from object changes by pattern.
|
|
1653
|
-
// @param {string} pattern - pattern like 'system.adapter.*' or array of IDs like ['system.adapter.admin.0.memRss', 'system.adapter.admin.0.memHeapTotal']
|
|
1654
|
-
// @param {function} callback - `function (error)`
|
|
1655
|
-
if (this._checkPermissions(socket, 'unsubscribeObjects', callback, pattern)) {
|
|
1656
|
-
try {
|
|
1657
|
-
if (Array.isArray(pattern)) {
|
|
1658
|
-
for (let p = 0; p < pattern.length; p++) {
|
|
1659
|
-
this.unsubscribe(socket, 'objectChange', pattern[p]);
|
|
1660
|
-
}
|
|
1661
|
-
} else {
|
|
1662
|
-
this.unsubscribe(socket, 'objectChange', pattern);
|
|
1663
|
-
}
|
|
1664
|
-
if (typeof callback === 'function') {
|
|
1665
|
-
setImmediate(callback, null);
|
|
1666
|
-
}
|
|
1667
|
-
} catch (error) {
|
|
1668
|
-
if (typeof callback === 'function') {
|
|
1669
|
-
setImmediate(callback, error);
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
};
|
|
1674
|
-
|
|
1675
|
-
this.commands['getObjectView'] = (socket, design, search, params, callback) => {
|
|
1676
|
-
// Make a query to the object database.
|
|
1677
|
-
// @param {string} design - 'system' or other designs like `custom`, but it must exist object `_design/custom`. Too 99,9% use `system`.
|
|
1678
|
-
// @param {string} search - object type, like `state`, `instance`, `adapter`, `host`, ...
|
|
1679
|
-
// @param {string} params - parameters for the query in form `{startkey: 'system.adapter.', endkey?: 'system.adapter.\u9999', depth?: number}`
|
|
1680
|
-
// @param {function} callback - `function (error)`
|
|
1681
|
-
if (typeof callback === 'function') {
|
|
1682
|
-
if (this._checkPermissions(socket, 'getObjectView', callback, search)) {
|
|
1683
|
-
try {
|
|
1684
|
-
if (params && (params.root || params.depth)) {
|
|
1685
|
-
// To save the bandwidth, the request can define root and depth. Default is depth 1.
|
|
1686
|
-
this.adapter.getObjectView(
|
|
1687
|
-
design,
|
|
1688
|
-
search,
|
|
1689
|
-
params,
|
|
1690
|
-
{ user: socket._acl.user },
|
|
1691
|
-
(err, result) => {
|
|
1692
|
-
if (result?.rows?.length && result.rows[0].value?._id) {
|
|
1693
|
-
const rows = [];
|
|
1694
|
-
// filter rows
|
|
1695
|
-
const depth = params.depth || 1;
|
|
1696
|
-
let root = params.startkey;
|
|
1697
|
-
let rootWithoutDot;
|
|
1698
|
-
if (!root.endsWith('.')) {
|
|
1699
|
-
root += '.';
|
|
1700
|
-
rootWithoutDot = root;
|
|
1701
|
-
} else {
|
|
1702
|
-
rootWithoutDot = root.substring(0, root.length - 1);
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
const rootDepth = root.split('.').length;
|
|
1706
|
-
const virtualObjects = {};
|
|
1707
|
-
for (let r = 0; r < result.rows.length; r++) {
|
|
1708
|
-
if (
|
|
1709
|
-
result.rows[r].value._id.startsWith(root) ||
|
|
1710
|
-
result.rows[r].value._id === rootWithoutDot
|
|
1711
|
-
) {
|
|
1712
|
-
const parts = result.rows[r].id.split('.');
|
|
1713
|
-
if (parts.length - rootDepth <= depth) {
|
|
1714
|
-
rows.push(result.rows[r]);
|
|
1715
|
-
} else {
|
|
1716
|
-
// create virtual objects to show that there are more objects
|
|
1717
|
-
for (let d = depth; d < parts.length - rootDepth; d++) {
|
|
1718
|
-
const id = parts.slice(0, rootDepth + d).join('.');
|
|
1719
|
-
if (!virtualObjects[id]) {
|
|
1720
|
-
virtualObjects[id] = {
|
|
1721
|
-
id,
|
|
1722
|
-
value: {
|
|
1723
|
-
_id: id,
|
|
1724
|
-
common: {},
|
|
1725
|
-
type: 'folder',
|
|
1726
|
-
virtual: true,
|
|
1727
|
-
hasChildren: 1
|
|
1728
|
-
}
|
|
1729
|
-
};
|
|
1730
|
-
rows.push(virtualObjects[id]);
|
|
1731
|
-
} else {
|
|
1732
|
-
virtualObjects[id].value.hasChildren++;
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
}
|
|
1738
|
-
result.rows = rows;
|
|
1739
|
-
}
|
|
1740
|
-
callback(err, result);
|
|
1741
|
-
}
|
|
1742
|
-
);
|
|
1743
|
-
} else {
|
|
1744
|
-
this.adapter.getObjectView(design, search, params, { user: socket._acl.user }, callback);
|
|
1745
|
-
}
|
|
1746
|
-
} catch (error) {
|
|
1747
|
-
this.adapter.log.error(`[getObjectView] ERROR: ${error.toString()}`);
|
|
1748
|
-
SocketCommands._fixCallback(callback, error);
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
} else {
|
|
1752
|
-
this.adapter.log.error('Callback is not a function');
|
|
1753
|
-
}
|
|
1754
|
-
};
|
|
1755
|
-
|
|
1756
|
-
this.commands['setObject'] = (socket, id, obj, callback) => {
|
|
1757
|
-
// Set object.
|
|
1758
|
-
// @param {string} id - object ID
|
|
1759
|
-
// @param {object} obj - object itself
|
|
1760
|
-
// @param {function} callback - `function (error)`
|
|
1761
|
-
if (this._checkPermissions(socket, 'setObject', callback, id)) {
|
|
1762
|
-
try {
|
|
1763
|
-
this.adapter.setForeignObject(id, obj, { user: socket._acl.user }, (error, ...args) =>
|
|
1764
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1765
|
-
);
|
|
1766
|
-
} catch (error) {
|
|
1767
|
-
this.adapter.log.error(`[setObject] ERROR: ${error.toString()}`);
|
|
1768
|
-
SocketCommands._fixCallback(callback, error);
|
|
1769
|
-
}
|
|
1770
|
-
}
|
|
1771
|
-
};
|
|
1772
|
-
|
|
1773
|
-
// this function is overloaded in admin
|
|
1774
|
-
this.commands['delObject'] = (socket, id, options, callback) => {
|
|
1775
|
-
// Delete object. Only deletion of flot objects is allowed
|
|
1776
|
-
// @param {string} id - Object ID like, 'flot.0.myChart'
|
|
1777
|
-
// @param {string} options - ignored
|
|
1778
|
-
// @param {function} callback - `function (error)`
|
|
1779
|
-
if (id.startsWith('flot.') || id.startsWith('fullcalendar.')) {
|
|
1780
|
-
if (this._checkPermissions(socket, 'delObject', callback, id)) {
|
|
1781
|
-
try {
|
|
1782
|
-
this.adapter.delForeignObject(id, { user: socket._acl.user }, (error, ...args) =>
|
|
1783
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1784
|
-
);
|
|
1785
|
-
} catch (error) {
|
|
1786
|
-
this.adapter.log.error(`[delObject] ERROR: ${error.toString()}`);
|
|
1787
|
-
SocketCommands._fixCallback(callback, error);
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
} else {
|
|
1791
|
-
SocketCommands._fixCallback(callback, SocketCommands.ERROR_PERMISSION);
|
|
1792
|
-
}
|
|
1793
|
-
};
|
|
1794
|
-
|
|
1795
|
-
this.commands['clientSubscribe'] = (socket, targetInstance, messageType, data, callback) => {
|
|
1796
|
-
// Client informs specific instance about subscription on its messages. After subscription the socket will receive "im" messages from desired instance
|
|
1797
|
-
// @param {string} targetInstance - instance name, e.g. "cameras.0"
|
|
1798
|
-
// @param {string} messageType - message type, e.g. "startRecording/cam1"
|
|
1799
|
-
// @param {object} data - optional data object, e.g. {width: 640, height: 480}
|
|
1800
|
-
// @param {function} callback - `function (error, result)`, target instance MUST acknowledge the subscription and return some object as result
|
|
1801
|
-
if (typeof data === 'function') {
|
|
1802
|
-
callback = data;
|
|
1803
|
-
data = null;
|
|
1804
|
-
}
|
|
1805
|
-
if (!targetInstance.startsWith('system.adapter.')) {
|
|
1806
|
-
targetInstance = `system.adapter.${targetInstance}`;
|
|
1807
|
-
}
|
|
1808
|
-
const sid = socket.id;
|
|
1809
|
-
// GUI subscribes for messages from targetInstance
|
|
1810
|
-
this.clientSubscribes[sid] = this.clientSubscribes[sid] || {};
|
|
1811
|
-
this.clientSubscribes[sid][targetInstance] = this.clientSubscribes[sid][targetInstance] || [];
|
|
1812
|
-
if (!this.clientSubscribes[sid][targetInstance].includes(messageType)) {
|
|
1813
|
-
this.clientSubscribes[sid][targetInstance].push(messageType);
|
|
1814
|
-
}
|
|
1815
|
-
// inform instance about new subscription
|
|
1816
|
-
this.adapter.sendTo(targetInstance, 'clientSubscribe', { type: messageType, sid, data }, result =>
|
|
1817
|
-
SocketCommands._fixCallback(callback, null, result)
|
|
1818
|
-
);
|
|
1819
|
-
};
|
|
1820
|
-
|
|
1821
|
-
this.commands['clientUnsubscribe'] = (socket, targetInstance, messageType, callback) => {
|
|
1822
|
-
// Client unsubscribes from specific instance's messages
|
|
1823
|
-
// @param {string} targetInstance - instance name, e.g. "cameras.0"
|
|
1824
|
-
// @param {string} messageType - message type, e.g. "startRecording/cam1"
|
|
1825
|
-
// @param {function} callback - `function (error, wasSubscribed)`, target instance MUST NOT acknowledge the un-subscription
|
|
1826
|
-
const sid = socket.id;
|
|
1827
|
-
if (!targetInstance.startsWith('system.adapter.')) {
|
|
1828
|
-
targetInstance = `system.adapter.${targetInstance}`;
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
// GUI unsubscribes for messages from targetInstance
|
|
1832
|
-
if (this.clientSubscribes[sid] && this.clientSubscribes[sid][targetInstance]) {
|
|
1833
|
-
const pos = this.clientSubscribes[sid][targetInstance].indexOf(messageType);
|
|
1834
|
-
if (pos !== -1) {
|
|
1835
|
-
this.clientSubscribes[sid][targetInstance].splice(pos, 1);
|
|
1836
|
-
// inform instance about unsubscription
|
|
1837
|
-
this.adapter.sendTo(targetInstance, 'clientUnsubscribe', {
|
|
1838
|
-
type: [messageType],
|
|
1839
|
-
sid,
|
|
1840
|
-
reason: 'client'
|
|
1841
|
-
});
|
|
1842
|
-
SocketCommands._fixCallback(callback, null, true);
|
|
1843
|
-
return;
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
SocketCommands._fixCallback(callback, null, false);
|
|
1847
|
-
};
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
_initCommands() {
|
|
1851
|
-
this.__initCommandsCommon();
|
|
1852
|
-
this.__initCommandsObjects();
|
|
1853
|
-
this.__initCommandsStates();
|
|
1854
|
-
this.__initCommandsFiles();
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
_informAboutDisconnect(socketId) {
|
|
1858
|
-
// say to all instances, that this socket was disconnected
|
|
1859
|
-
if (this.clientSubscribes[socketId]) {
|
|
1860
|
-
Object.keys(this.clientSubscribes[socketId]).forEach(targetInstance => {
|
|
1861
|
-
this.adapter.sendTo(targetInstance, 'clientUnsubscribe', {
|
|
1862
|
-
type: this.clientSubscribes[socketId][targetInstance],
|
|
1863
|
-
sid: socketId,
|
|
1864
|
-
reason: 'disconnect'
|
|
1865
|
-
});
|
|
1866
|
-
});
|
|
1867
|
-
delete this.clientSubscribes[socketId];
|
|
1868
|
-
}
|
|
1869
|
-
}
|
|
1870
|
-
|
|
1871
|
-
applyCommands(socket) {
|
|
1872
|
-
Object.keys(this.commands).forEach(command =>
|
|
1873
|
-
socket.on(command, (...args) => {
|
|
1874
|
-
if (this._updateSession(socket)) {
|
|
1875
|
-
this.commands[command](socket, ...args);
|
|
1876
|
-
}
|
|
1877
|
-
})
|
|
1878
|
-
);
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
destroy() {
|
|
1882
|
-
// could be overloaded
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
|
-
module.exports = SocketCommands;
|