@iobroker/dm-utils 0.3.1 → 0.6.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/README.md +11 -0
- package/build/ActionContext.d.ts +2 -2
- package/build/DeviceManagement.d.ts +5 -5
- package/build/DeviceManagement.js +106 -52
- package/build/index.d.ts +3 -3
- package/build/index.js +0 -1
- package/build/types/adapter.d.ts +7 -7
- package/build/types/api.d.ts +7 -7
- package/build/types/base.d.ts +17 -17
- package/build/types/common.d.ts +223 -19
- package/build/types/index.d.ts +4 -4
- package/build/types/index.js +0 -2
- package/package.json +8 -10
package/README.md
CHANGED
|
@@ -295,6 +295,17 @@ This method returns a promise that resolves to a `ProgressDialog` object.
|
|
|
295
295
|
### **WORK IN PROGRESS**
|
|
296
296
|
-->
|
|
297
297
|
## Changelog
|
|
298
|
+
### 0.6.0 (2024-11-17)
|
|
299
|
+
|
|
300
|
+
* (@GermanBluefox) used new ioBroker/eslint-config lib and changed prettifier settings
|
|
301
|
+
* (@GermanBluefox) updated JsonConfig types
|
|
302
|
+
|
|
303
|
+
### 0.5.0 (2024-08-30)
|
|
304
|
+
* (bluefox) Migrated to eslint 9
|
|
305
|
+
|
|
306
|
+
### 0.4.0 (2024-08-30)
|
|
307
|
+
* (bluefox) Added `state` type for JSON config
|
|
308
|
+
|
|
298
309
|
### 0.3.1 (2024-07-18)
|
|
299
310
|
* (bluefox) Added qrCode type for JSON config
|
|
300
311
|
|
package/build/ActionContext.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { JsonFormData, JsonFormSchema } from
|
|
2
|
-
import { ProgressDialog } from
|
|
1
|
+
import type { JsonFormData, JsonFormSchema } from '.';
|
|
2
|
+
import type { ProgressDialog } from './ProgressDialog';
|
|
3
3
|
export interface ActionContext {
|
|
4
4
|
showMessage(text: ioBroker.StringOrTranslated): Promise<void>;
|
|
5
5
|
showConfirmation(text: ioBroker.StringOrTranslated): Promise<boolean>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AdapterInstance } from
|
|
2
|
-
import { ActionContext } from
|
|
3
|
-
import { ProgressDialog } from
|
|
4
|
-
import { DeviceDetails, DeviceInfo, ErrorResponse, InstanceDetails, JsonFormData, JsonFormSchema, RefreshResponse, RetVal } from
|
|
5
|
-
import { ControlState } from
|
|
1
|
+
import type { AdapterInstance } from '@iobroker/adapter-core';
|
|
2
|
+
import type { ActionContext } from './ActionContext';
|
|
3
|
+
import type { ProgressDialog } from './ProgressDialog';
|
|
4
|
+
import { type DeviceDetails, type DeviceInfo, type ErrorResponse, type InstanceDetails, type JsonFormData, type JsonFormSchema, type RefreshResponse, type RetVal } from './types';
|
|
5
|
+
import type { ControlState } from './types/base';
|
|
6
6
|
export declare abstract class DeviceManagement<T extends AdapterInstance = AdapterInstance> {
|
|
7
7
|
protected readonly adapter: T;
|
|
8
8
|
private instanceInfo?;
|
|
@@ -6,13 +6,13 @@ class DeviceManagement {
|
|
|
6
6
|
constructor(adapter) {
|
|
7
7
|
this.adapter = adapter;
|
|
8
8
|
this.contexts = new Map();
|
|
9
|
-
adapter.on(
|
|
9
|
+
adapter.on('message', this.onMessage.bind(this));
|
|
10
10
|
}
|
|
11
11
|
get log() {
|
|
12
12
|
return this.adapter.log;
|
|
13
13
|
}
|
|
14
14
|
getInstanceInfo() {
|
|
15
|
-
return { apiVersion:
|
|
15
|
+
return { apiVersion: 'v1' };
|
|
16
16
|
}
|
|
17
17
|
getDeviceDetails(id) {
|
|
18
18
|
return { id, schema: {} };
|
|
@@ -21,17 +21,30 @@ class DeviceManagement {
|
|
|
21
21
|
var _a;
|
|
22
22
|
if (!this.instanceInfo) {
|
|
23
23
|
this.log.warn(`Instance action ${actionId} was called before getInstanceInfo()`);
|
|
24
|
-
return {
|
|
24
|
+
return {
|
|
25
|
+
error: {
|
|
26
|
+
code: types_1.ErrorCodes.E_INSTANCE_ACTION_NOT_INITIALIZED,
|
|
27
|
+
message: `Instance action ${actionId} was called before getInstanceInfo()`,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
25
30
|
}
|
|
26
|
-
const action = (_a = this.instanceInfo.actions) === null || _a === void 0 ? void 0 : _a.find(
|
|
31
|
+
const action = (_a = this.instanceInfo.actions) === null || _a === void 0 ? void 0 : _a.find(a => a.id === actionId);
|
|
27
32
|
if (!action) {
|
|
28
33
|
this.log.warn(`Instance action ${actionId} is unknown`);
|
|
29
|
-
return {
|
|
34
|
+
return {
|
|
35
|
+
error: {
|
|
36
|
+
code: types_1.ErrorCodes.E_INSTANCE_ACTION_UNKNOWN,
|
|
37
|
+
message: `Instance action ${actionId} is unknown`,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
30
40
|
}
|
|
31
41
|
if (!action.handler) {
|
|
32
42
|
this.log.warn(`Instance action ${actionId} is disabled because it has no handler`);
|
|
33
43
|
return {
|
|
34
|
-
error: {
|
|
44
|
+
error: {
|
|
45
|
+
code: types_1.ErrorCodes.E_INSTANCE_ACTION_NO_HANDLER,
|
|
46
|
+
message: `Instance action ${actionId} is disabled because it has no handler`,
|
|
47
|
+
},
|
|
35
48
|
};
|
|
36
49
|
}
|
|
37
50
|
return action.handler(context, options);
|
|
@@ -40,19 +53,32 @@ class DeviceManagement {
|
|
|
40
53
|
var _a;
|
|
41
54
|
if (!this.devices) {
|
|
42
55
|
this.log.warn(`Device action ${actionId} was called before listDevices()`);
|
|
43
|
-
return {
|
|
56
|
+
return {
|
|
57
|
+
error: {
|
|
58
|
+
code: types_1.ErrorCodes.E_DEVICE_ACTION_NOT_INITIALIZED,
|
|
59
|
+
message: `Device action ${actionId} was called before listDevices()`,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
44
62
|
}
|
|
45
63
|
const device = this.devices.get(deviceId);
|
|
46
64
|
if (!device) {
|
|
47
65
|
this.log.warn(`Device action ${actionId} was called on unknown device: ${deviceId}`);
|
|
48
66
|
return {
|
|
49
|
-
error: {
|
|
67
|
+
error: {
|
|
68
|
+
code: types_1.ErrorCodes.E_DEVICE_ACTION_DEVICE_UNKNOWN,
|
|
69
|
+
message: `Device action ${actionId} was called on unknown device: ${deviceId}`,
|
|
70
|
+
},
|
|
50
71
|
};
|
|
51
72
|
}
|
|
52
|
-
const action = (_a = device.actions) === null || _a === void 0 ? void 0 : _a.find(
|
|
73
|
+
const action = (_a = device.actions) === null || _a === void 0 ? void 0 : _a.find(a => a.id === actionId);
|
|
53
74
|
if (!action) {
|
|
54
75
|
this.log.warn(`Device action ${actionId} doesn't exist on device ${deviceId}`);
|
|
55
|
-
return {
|
|
76
|
+
return {
|
|
77
|
+
error: {
|
|
78
|
+
code: types_1.ErrorCodes.E_DEVICE_ACTION_UNKNOWN,
|
|
79
|
+
message: `Device action ${actionId} doesn't exist on device ${deviceId}`,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
56
82
|
}
|
|
57
83
|
if (!action.handler) {
|
|
58
84
|
this.log.warn(`Device action ${actionId} on ${deviceId} is disabled because it has no handler`);
|
|
@@ -69,19 +95,32 @@ class DeviceManagement {
|
|
|
69
95
|
var _a;
|
|
70
96
|
if (!this.devices) {
|
|
71
97
|
this.log.warn(`Device control ${controlId} was called before listDevices()`);
|
|
72
|
-
return {
|
|
98
|
+
return {
|
|
99
|
+
error: {
|
|
100
|
+
code: types_1.ErrorCodes.E_DEVICE_CONTROL_NOT_INITIALIZED,
|
|
101
|
+
message: `Device control ${controlId} was called before listDevices()`,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
73
104
|
}
|
|
74
105
|
const device = this.devices.get(deviceId);
|
|
75
106
|
if (!device) {
|
|
76
107
|
this.log.warn(`Device control ${controlId} was called on unknown device: ${deviceId}`);
|
|
77
108
|
return {
|
|
78
|
-
error: {
|
|
109
|
+
error: {
|
|
110
|
+
code: types_1.ErrorCodes.E_DEVICE_CONTROL_DEVICE_UNKNOWN,
|
|
111
|
+
message: `Device control ${controlId} was called on unknown device: ${deviceId}`,
|
|
112
|
+
},
|
|
79
113
|
};
|
|
80
114
|
}
|
|
81
|
-
const control = (_a = device.controls) === null || _a === void 0 ? void 0 : _a.find(
|
|
115
|
+
const control = (_a = device.controls) === null || _a === void 0 ? void 0 : _a.find(a => a.id === controlId);
|
|
82
116
|
if (!control) {
|
|
83
117
|
this.log.warn(`Device control ${controlId} doesn't exist on device ${deviceId}`);
|
|
84
|
-
return {
|
|
118
|
+
return {
|
|
119
|
+
error: {
|
|
120
|
+
code: types_1.ErrorCodes.E_DEVICE_CONTROL_UNKNOWN,
|
|
121
|
+
message: `Device control ${controlId} doesn't exist on device ${deviceId}`,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
85
124
|
}
|
|
86
125
|
if (!control.handler) {
|
|
87
126
|
this.log.warn(`Device control ${controlId} on ${deviceId} is disabled because it has no handler`);
|
|
@@ -99,19 +138,32 @@ class DeviceManagement {
|
|
|
99
138
|
var _a;
|
|
100
139
|
if (!this.devices) {
|
|
101
140
|
this.log.warn(`Device get state ${controlId} was called before listDevices()`);
|
|
102
|
-
return {
|
|
141
|
+
return {
|
|
142
|
+
error: {
|
|
143
|
+
code: types_1.ErrorCodes.E_DEVICE_GET_STATE_NOT_INITIALIZED,
|
|
144
|
+
message: `Device control ${controlId} was called before listDevices()`,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
103
147
|
}
|
|
104
148
|
const device = this.devices.get(deviceId);
|
|
105
149
|
if (!device) {
|
|
106
150
|
this.log.warn(`Device get state ${controlId} was called on unknown device: ${deviceId}`);
|
|
107
151
|
return {
|
|
108
|
-
error: {
|
|
152
|
+
error: {
|
|
153
|
+
code: types_1.ErrorCodes.E_DEVICE_GET_STATE_DEVICE_UNKNOWN,
|
|
154
|
+
message: `Device control ${controlId} was called on unknown device: ${deviceId}`,
|
|
155
|
+
},
|
|
109
156
|
};
|
|
110
157
|
}
|
|
111
|
-
const control = (_a = device.controls) === null || _a === void 0 ? void 0 : _a.find(
|
|
158
|
+
const control = (_a = device.controls) === null || _a === void 0 ? void 0 : _a.find(a => a.id === controlId);
|
|
112
159
|
if (!control) {
|
|
113
160
|
this.log.warn(`Device get state ${controlId} doesn't exist on device ${deviceId}`);
|
|
114
|
-
return {
|
|
161
|
+
return {
|
|
162
|
+
error: {
|
|
163
|
+
code: types_1.ErrorCodes.E_DEVICE_GET_STATE_UNKNOWN,
|
|
164
|
+
message: `Device control ${controlId} doesn't exist on device ${deviceId}`,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
115
167
|
}
|
|
116
168
|
if (!control.getStateHandler) {
|
|
117
169
|
this.log.warn(`Device get state ${controlId} on ${deviceId} is disabled because it has no handler`);
|
|
@@ -125,20 +177,20 @@ class DeviceManagement {
|
|
|
125
177
|
return control.getStateHandler(deviceId, controlId, context);
|
|
126
178
|
}
|
|
127
179
|
onMessage(obj) {
|
|
128
|
-
if (!obj.command.startsWith(
|
|
180
|
+
if (!obj.command.startsWith('dm:')) {
|
|
129
181
|
return;
|
|
130
182
|
}
|
|
131
|
-
this.handleMessage(obj).catch(this.log.error);
|
|
183
|
+
void this.handleMessage(obj).catch(this.log.error);
|
|
132
184
|
}
|
|
133
185
|
async handleMessage(msg) {
|
|
134
186
|
this.log.debug(`DeviceManagement received: ${JSON.stringify(msg)}`);
|
|
135
187
|
switch (msg.command) {
|
|
136
|
-
case
|
|
188
|
+
case 'dm:instanceInfo': {
|
|
137
189
|
this.instanceInfo = await this.getInstanceInfo();
|
|
138
190
|
this.sendReply(Object.assign(Object.assign({}, this.instanceInfo), { actions: this.convertActions(this.instanceInfo.actions) }), msg);
|
|
139
191
|
return;
|
|
140
192
|
}
|
|
141
|
-
case
|
|
193
|
+
case 'dm:listDevices': {
|
|
142
194
|
const deviceList = await this.listDevices();
|
|
143
195
|
this.devices = deviceList.reduce((map, value) => {
|
|
144
196
|
if (map.has(value.id)) {
|
|
@@ -147,17 +199,17 @@ class DeviceManagement {
|
|
|
147
199
|
map.set(value.id, value);
|
|
148
200
|
return map;
|
|
149
201
|
}, new Map());
|
|
150
|
-
const apiDeviceList = deviceList.map(
|
|
202
|
+
const apiDeviceList = deviceList.map(d => (Object.assign(Object.assign({}, d), { actions: this.convertActions(d.actions), controls: this.convertControls(d.controls) })));
|
|
151
203
|
this.sendReply(apiDeviceList, msg);
|
|
152
204
|
this.adapter.sendTo(msg.from, msg.command, this.devices, msg.callback);
|
|
153
205
|
return;
|
|
154
206
|
}
|
|
155
|
-
case
|
|
207
|
+
case 'dm:deviceDetails': {
|
|
156
208
|
const details = await this.getDeviceDetails(msg.message);
|
|
157
209
|
this.adapter.sendTo(msg.from, msg.command, details, msg.callback);
|
|
158
210
|
return;
|
|
159
211
|
}
|
|
160
|
-
case
|
|
212
|
+
case 'dm:instanceAction': {
|
|
161
213
|
const action = msg.message;
|
|
162
214
|
const context = new MessageContext(msg, this.adapter);
|
|
163
215
|
this.contexts.set(msg._id, context);
|
|
@@ -166,16 +218,18 @@ class DeviceManagement {
|
|
|
166
218
|
context.sendFinalResult(result);
|
|
167
219
|
return;
|
|
168
220
|
}
|
|
169
|
-
case
|
|
221
|
+
case 'dm:deviceAction': {
|
|
170
222
|
const action = msg.message;
|
|
171
223
|
const context = new MessageContext(msg, this.adapter);
|
|
172
224
|
this.contexts.set(msg._id, context);
|
|
173
|
-
const result = await this.handleDeviceAction(action.deviceId, action.actionId, context, {
|
|
225
|
+
const result = await this.handleDeviceAction(action.deviceId, action.actionId, context, {
|
|
226
|
+
value: action.value,
|
|
227
|
+
});
|
|
174
228
|
this.contexts.delete(msg._id);
|
|
175
229
|
context.sendFinalResult(result);
|
|
176
230
|
return;
|
|
177
231
|
}
|
|
178
|
-
case
|
|
232
|
+
case 'dm:deviceControl': {
|
|
179
233
|
const control = msg.message;
|
|
180
234
|
const context = new MessageContext(msg, this.adapter);
|
|
181
235
|
this.contexts.set(msg._id, context);
|
|
@@ -184,7 +238,7 @@ class DeviceManagement {
|
|
|
184
238
|
context.sendControlResult(control.deviceId, control.controlId, result);
|
|
185
239
|
return;
|
|
186
240
|
}
|
|
187
|
-
case
|
|
241
|
+
case 'dm:deviceControlState': {
|
|
188
242
|
const control = msg.message;
|
|
189
243
|
const context = new MessageContext(msg, this.adapter);
|
|
190
244
|
this.contexts.set(msg._id, context);
|
|
@@ -193,12 +247,12 @@ class DeviceManagement {
|
|
|
193
247
|
context.sendControlResult(control.deviceId, control.controlId, result);
|
|
194
248
|
return;
|
|
195
249
|
}
|
|
196
|
-
case
|
|
250
|
+
case 'dm:actionProgress': {
|
|
197
251
|
const { origin } = msg.message;
|
|
198
252
|
const context = this.contexts.get(origin);
|
|
199
253
|
if (!context) {
|
|
200
254
|
this.log.warn(`Unknown message origin: ${origin}`);
|
|
201
|
-
this.sendReply({ error:
|
|
255
|
+
this.sendReply({ error: 'Unknown action origin' }, msg);
|
|
202
256
|
return;
|
|
203
257
|
}
|
|
204
258
|
context.handleProgress(msg);
|
|
@@ -212,7 +266,7 @@ class DeviceManagement {
|
|
|
212
266
|
}
|
|
213
267
|
// detect duplicate IDs
|
|
214
268
|
const ids = new Set();
|
|
215
|
-
actions.forEach(
|
|
269
|
+
actions.forEach(a => {
|
|
216
270
|
if (ids.has(a.id)) {
|
|
217
271
|
throw new Error(`Action ID ${a.id} is used twice, this would lead to unexpected behavior`);
|
|
218
272
|
}
|
|
@@ -227,7 +281,7 @@ class DeviceManagement {
|
|
|
227
281
|
}
|
|
228
282
|
// detect duplicate IDs
|
|
229
283
|
const ids = new Set();
|
|
230
|
-
controls.forEach(
|
|
284
|
+
controls.forEach(a => {
|
|
231
285
|
if (ids.has(a.id)) {
|
|
232
286
|
throw new Error(`Control ID ${a.id} is used twice, this would lead to unexpected behavior`);
|
|
233
287
|
}
|
|
@@ -249,30 +303,30 @@ class MessageContext {
|
|
|
249
303
|
}
|
|
250
304
|
showMessage(text) {
|
|
251
305
|
this.checkPreconditions();
|
|
252
|
-
const promise = new Promise(
|
|
306
|
+
const promise = new Promise(resolve => {
|
|
253
307
|
this.progressHandler = () => resolve();
|
|
254
308
|
});
|
|
255
|
-
this.send(
|
|
309
|
+
this.send('message', {
|
|
256
310
|
message: text,
|
|
257
311
|
});
|
|
258
312
|
return promise;
|
|
259
313
|
}
|
|
260
314
|
showConfirmation(text) {
|
|
261
315
|
this.checkPreconditions();
|
|
262
|
-
const promise = new Promise(
|
|
263
|
-
this.progressHandler =
|
|
316
|
+
const promise = new Promise(resolve => {
|
|
317
|
+
this.progressHandler = msg => resolve(!!msg.confirm);
|
|
264
318
|
});
|
|
265
|
-
this.send(
|
|
319
|
+
this.send('confirm', {
|
|
266
320
|
confirm: text,
|
|
267
321
|
});
|
|
268
322
|
return promise;
|
|
269
323
|
}
|
|
270
324
|
showForm(schema, options) {
|
|
271
325
|
this.checkPreconditions();
|
|
272
|
-
const promise = new Promise(
|
|
273
|
-
this.progressHandler =
|
|
326
|
+
const promise = new Promise(resolve => {
|
|
327
|
+
this.progressHandler = msg => resolve(msg.data);
|
|
274
328
|
});
|
|
275
|
-
this.send(
|
|
329
|
+
this.send('form', {
|
|
276
330
|
form: Object.assign({ schema }, options),
|
|
277
331
|
});
|
|
278
332
|
return promise;
|
|
@@ -282,43 +336,43 @@ class MessageContext {
|
|
|
282
336
|
this.hasOpenProgressDialog = true;
|
|
283
337
|
const dialog = {
|
|
284
338
|
update: (update) => {
|
|
285
|
-
const promise = new Promise(
|
|
339
|
+
const promise = new Promise(resolve => {
|
|
286
340
|
this.progressHandler = () => resolve();
|
|
287
341
|
});
|
|
288
|
-
this.send(
|
|
342
|
+
this.send('progress', {
|
|
289
343
|
progress: Object.assign(Object.assign(Object.assign({ title }, options), update), { open: true }),
|
|
290
344
|
});
|
|
291
345
|
return promise;
|
|
292
346
|
},
|
|
293
347
|
close: () => {
|
|
294
|
-
const promise = new Promise(
|
|
348
|
+
const promise = new Promise(resolve => {
|
|
295
349
|
this.progressHandler = () => {
|
|
296
350
|
this.hasOpenProgressDialog = false;
|
|
297
351
|
resolve();
|
|
298
352
|
};
|
|
299
353
|
});
|
|
300
|
-
this.send(
|
|
354
|
+
this.send('progress', {
|
|
301
355
|
progress: { open: false },
|
|
302
356
|
});
|
|
303
357
|
return promise;
|
|
304
358
|
},
|
|
305
359
|
};
|
|
306
|
-
const promise = new Promise(
|
|
360
|
+
const promise = new Promise(resolve => {
|
|
307
361
|
this.progressHandler = () => resolve(dialog);
|
|
308
362
|
});
|
|
309
|
-
this.send(
|
|
363
|
+
this.send('progress', {
|
|
310
364
|
progress: Object.assign(Object.assign({ title }, options), { open: true }),
|
|
311
365
|
});
|
|
312
366
|
return promise;
|
|
313
367
|
}
|
|
314
368
|
sendFinalResult(result) {
|
|
315
|
-
this.send(
|
|
369
|
+
this.send('result', {
|
|
316
370
|
result,
|
|
317
371
|
});
|
|
318
372
|
}
|
|
319
373
|
sendControlResult(deviceId, controlId, result) {
|
|
320
|
-
if (typeof result ===
|
|
321
|
-
this.send(
|
|
374
|
+
if (typeof result === 'object' && 'error' in result) {
|
|
375
|
+
this.send('result', {
|
|
322
376
|
result: {
|
|
323
377
|
error: result.error,
|
|
324
378
|
deviceId,
|
|
@@ -327,7 +381,7 @@ class MessageContext {
|
|
|
327
381
|
});
|
|
328
382
|
}
|
|
329
383
|
else {
|
|
330
|
-
this.send(
|
|
384
|
+
this.send('result', {
|
|
331
385
|
result: {
|
|
332
386
|
state: result,
|
|
333
387
|
deviceId,
|
|
@@ -338,7 +392,7 @@ class MessageContext {
|
|
|
338
392
|
}
|
|
339
393
|
handleProgress(message) {
|
|
340
394
|
const currentHandler = this.progressHandler;
|
|
341
|
-
if (currentHandler && typeof message.message !==
|
|
395
|
+
if (currentHandler && typeof message.message !== 'string') {
|
|
342
396
|
this.lastMessage = message;
|
|
343
397
|
this.progressHandler = undefined;
|
|
344
398
|
currentHandler(message.message);
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export type * from './ActionContext';
|
|
2
|
+
export * from './DeviceManagement';
|
|
3
|
+
export * from './types';
|
package/build/index.js
CHANGED
|
@@ -14,7 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./ActionContext"), exports);
|
|
18
17
|
__exportStar(require("./DeviceManagement"), exports);
|
|
19
18
|
// don't export * from "./MessageContext" as it is private
|
|
20
19
|
__exportStar(require("./types"), exports);
|
package/build/types/adapter.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as base from
|
|
2
|
-
export type ActionBase = base.ActionBase<
|
|
3
|
-
export type InstanceAction = base.InstanceAction<
|
|
4
|
-
export type DeviceAction = base.DeviceAction<
|
|
5
|
-
export type InstanceDetails = base.InstanceDetails<
|
|
6
|
-
export type DeviceInfo = base.DeviceInfo<
|
|
7
|
-
export type DeviceControl = base.DeviceControl<
|
|
1
|
+
import type * as base from './base';
|
|
2
|
+
export type ActionBase = base.ActionBase<'adapter'>;
|
|
3
|
+
export type InstanceAction = base.InstanceAction<'adapter'>;
|
|
4
|
+
export type DeviceAction = base.DeviceAction<'adapter'>;
|
|
5
|
+
export type InstanceDetails = base.InstanceDetails<'adapter'>;
|
|
6
|
+
export type DeviceInfo = base.DeviceInfo<'adapter'>;
|
|
7
|
+
export type DeviceControl = base.DeviceControl<'adapter'>;
|
package/build/types/api.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as base from
|
|
2
|
-
export type ActionBase = base.ActionBase<
|
|
3
|
-
export type InstanceAction = base.InstanceAction<
|
|
4
|
-
export type DeviceAction = base.DeviceAction<
|
|
5
|
-
export type InstanceDetails = base.InstanceDetails<
|
|
6
|
-
export type DeviceInfo = base.DeviceInfo<
|
|
7
|
-
export type DeviceControl = base.DeviceControl<
|
|
1
|
+
import type * as base from './base';
|
|
2
|
+
export type ActionBase = base.ActionBase<'api'>;
|
|
3
|
+
export type InstanceAction = base.InstanceAction<'api'>;
|
|
4
|
+
export type DeviceAction = base.DeviceAction<'api'>;
|
|
5
|
+
export type InstanceDetails = base.InstanceDetails<'api'>;
|
|
6
|
+
export type DeviceInfo = base.DeviceInfo<'api'>;
|
|
7
|
+
export type DeviceControl = base.DeviceControl<'api'>;
|
package/build/types/base.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { ActionContext, ErrorResponse, MessageContext } from
|
|
2
|
-
import { ApiVersion, DeviceRefresh, DeviceStatus, RetVal } from
|
|
3
|
-
type ActionType =
|
|
4
|
-
export type Color =
|
|
1
|
+
import type { ActionContext, ErrorResponse, MessageContext } from '..';
|
|
2
|
+
import type { ApiVersion, DeviceRefresh, DeviceStatus, RetVal } from './common';
|
|
3
|
+
type ActionType = 'api' | 'adapter';
|
|
4
|
+
export type Color = 'primary' | 'secondary' | (string & {});
|
|
5
5
|
export type ControlState = string | number | boolean | null;
|
|
6
6
|
export interface ActionBase<T extends ActionType> {
|
|
7
7
|
id: string;
|
|
8
8
|
/**
|
|
9
9
|
* This can either be base64 or the URL to an icon.
|
|
10
10
|
*/
|
|
11
|
-
icon?:
|
|
11
|
+
icon?: 'edit' | 'rename' | 'delete' | 'refresh' | 'newDevice' | 'new' | 'add' | 'discover' | 'search' | 'unpairDevice' | 'pairDevice' | 'identify' | 'play' | 'stop' | 'pause' | 'forward' | 'next' | 'rewind' | 'previous' | 'lamp' | 'light' | 'backlight' | 'dimmer' | 'socket' | 'settings' | 'users' | 'group' | 'user' | string;
|
|
12
12
|
description?: ioBroker.StringOrTranslated;
|
|
13
|
-
disabled?: T extends
|
|
13
|
+
disabled?: T extends 'api' ? boolean : never;
|
|
14
14
|
color?: Color;
|
|
15
15
|
backgroundColor?: Color;
|
|
16
16
|
/** If true, the user will be asked for confirmation before executing the action */
|
|
@@ -20,7 +20,7 @@ export interface ActionBase<T extends ActionType> {
|
|
|
20
20
|
/** This label will be shown for the text input */
|
|
21
21
|
label: ioBroker.StringOrTranslated;
|
|
22
22
|
/** This type of input will be shown. Default is type */
|
|
23
|
-
type?:
|
|
23
|
+
type?: 'text' | 'number' | 'checkbox' | 'select' | 'slider' | 'color';
|
|
24
24
|
/** If a type is "select", the options must be defined */
|
|
25
25
|
options?: {
|
|
26
26
|
label: ioBroker.StringOrTranslated;
|
|
@@ -48,7 +48,7 @@ export interface ChannelInfo {
|
|
|
48
48
|
}
|
|
49
49
|
export interface ControlBase {
|
|
50
50
|
id: string;
|
|
51
|
-
type:
|
|
51
|
+
type: 'button' | 'switch' | 'slider' | 'select' | 'icon' | 'color' | 'text' | 'number' | 'info';
|
|
52
52
|
state?: ioBroker.State;
|
|
53
53
|
stateId?: string;
|
|
54
54
|
icon?: string;
|
|
@@ -70,26 +70,26 @@ export interface ControlBase {
|
|
|
70
70
|
}[];
|
|
71
71
|
channel?: ChannelInfo;
|
|
72
72
|
}
|
|
73
|
-
export interface DeviceControl<T extends ActionType =
|
|
74
|
-
handler?: T extends
|
|
75
|
-
getStateHandler?: T extends
|
|
73
|
+
export interface DeviceControl<T extends ActionType = 'api'> extends ControlBase {
|
|
74
|
+
handler?: T extends 'api' ? never : (deviceId: string, actionId: string, state: ControlState, context: MessageContext) => RetVal<ErrorResponse | ioBroker.State>;
|
|
75
|
+
getStateHandler?: T extends 'api' ? never : (deviceId: string, actionId: string, context: MessageContext) => RetVal<ErrorResponse | ioBroker.State>;
|
|
76
76
|
}
|
|
77
|
-
export interface InstanceAction<T extends ActionType =
|
|
78
|
-
handler?: T extends
|
|
77
|
+
export interface InstanceAction<T extends ActionType = 'api'> extends ActionBase<T> {
|
|
78
|
+
handler?: T extends 'api' ? never : (context: ActionContext, options?: Record<string, any>) => RetVal<{
|
|
79
79
|
refresh: boolean;
|
|
80
80
|
}>;
|
|
81
81
|
title: ioBroker.StringOrTranslated;
|
|
82
82
|
}
|
|
83
|
-
export interface DeviceAction<T extends ActionType =
|
|
84
|
-
handler?: T extends
|
|
83
|
+
export interface DeviceAction<T extends ActionType = 'api'> extends ActionBase<T> {
|
|
84
|
+
handler?: T extends 'api' ? never : (deviceId: string, context: ActionContext, options?: Record<string, any>) => RetVal<{
|
|
85
85
|
refresh: DeviceRefresh;
|
|
86
86
|
}>;
|
|
87
87
|
}
|
|
88
|
-
export interface InstanceDetails<T extends ActionType =
|
|
88
|
+
export interface InstanceDetails<T extends ActionType = 'api'> {
|
|
89
89
|
apiVersion: ApiVersion;
|
|
90
90
|
actions?: InstanceAction<T>[];
|
|
91
91
|
}
|
|
92
|
-
export interface DeviceInfo<T extends ActionType =
|
|
92
|
+
export interface DeviceInfo<T extends ActionType = 'api'> {
|
|
93
93
|
id: string;
|
|
94
94
|
icon?: string;
|
|
95
95
|
manufacturer?: ioBroker.StringOrTranslated;
|
package/build/types/common.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export type ApiVersion =
|
|
2
|
-
export type DeviceStatus =
|
|
1
|
+
export type ApiVersion = 'v1';
|
|
2
|
+
export type DeviceStatus = 'connected' | 'disconnected' | {
|
|
3
3
|
/**
|
|
4
4
|
* This can either be the name of a font awesome icon (e.g. "fa-signal") or the URL to an icon.
|
|
5
5
|
*/
|
|
6
6
|
icon?: string;
|
|
7
|
-
battery?: number | boolean |
|
|
8
|
-
connection?:
|
|
7
|
+
battery?: number | boolean | 'charging';
|
|
8
|
+
connection?: 'connected' | 'disconnected';
|
|
9
9
|
rssi?: number;
|
|
10
10
|
warning?: ioBroker.StringOrTranslated | boolean;
|
|
11
11
|
};
|
|
12
|
-
export type DeviceRefresh =
|
|
12
|
+
export type DeviceRefresh = 'device' | 'instance' | false | true;
|
|
13
13
|
export type RefreshResponse = {
|
|
14
14
|
refresh: DeviceRefresh;
|
|
15
15
|
};
|
|
@@ -30,7 +30,7 @@ interface ObjectBrowserCustomFilter {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
export type ObjectBrowserType = 'state' | 'instance' | 'channel' | 'device' | 'chart';
|
|
33
|
-
export type ConfigItemType = 'tabs' | 'panel' | 'text' | 'number' | 'color' | 'checkbox' | 'slider' | 'ip' | 'user' | 'room' | 'func' | 'select' | 'autocomplete' | 'image' | 'objectId' | 'password' | 'instance' | 'chips' | 'alive' | 'pattern' | 'sendto' | 'setState' | 'staticText' | 'staticLink' | 'staticImage' | 'table' | 'accordion' | 'jsonEditor' | 'language' | 'certificate' | 'certificates' | 'certCollection' | 'custom' | 'datePicker' | 'timePicker' | 'divider' | 'header' | 'cron' | 'fileSelector' | 'file' | 'imageSendTo' | 'selectSendTo' | 'autocompleteSendTo' | 'textSendTo' | 'coordinates' | 'interface' | 'license' | 'checkLicense' | 'uuid' | 'port' | 'deviceManager' | 'topic' | 'qrCode';
|
|
33
|
+
export type ConfigItemType = 'tabs' | 'panel' | 'text' | 'number' | 'color' | 'checkbox' | 'slider' | 'ip' | 'user' | 'room' | 'func' | 'select' | 'autocomplete' | 'image' | 'objectId' | 'password' | 'instance' | 'chips' | 'alive' | 'pattern' | 'sendto' | 'setState' | 'staticInfo' | 'staticText' | 'staticLink' | 'staticImage' | 'table' | 'accordion' | 'jsonEditor' | 'language' | 'certificate' | 'certificates' | 'certCollection' | 'custom' | 'datePicker' | 'timePicker' | 'divider' | 'header' | 'cron' | 'fileSelector' | 'file' | 'imageSendTo' | 'selectSendTo' | 'autocompleteSendTo' | 'textSendTo' | 'coordinates' | 'interface' | 'license' | 'checkLicense' | 'uuid' | 'port' | 'deviceManager' | 'topic' | 'qrCode' | 'state';
|
|
34
34
|
type ConfigIconType = 'edit' | 'auth' | 'send' | 'web' | 'warning' | 'error' | 'info' | 'search' | 'book' | 'help' | 'upload' | 'user' | 'group' | 'delete' | 'refresh' | 'add' | 'unpair' | 'pair' | string;
|
|
35
35
|
export interface ConfigItemConfirmData {
|
|
36
36
|
condition: string;
|
|
@@ -42,19 +42,33 @@ export interface ConfigItemConfirmData {
|
|
|
42
42
|
alsoDependsOn?: string[];
|
|
43
43
|
}
|
|
44
44
|
export interface ConfigItem {
|
|
45
|
+
/** Type of the JSON config item */
|
|
45
46
|
type: ConfigItemType;
|
|
47
|
+
/** Width of the control on "extra small" displays */
|
|
48
|
+
xs?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
49
|
+
/** Width of the control on "small" displays */
|
|
46
50
|
sm?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
51
|
+
/** Width of the control on "medium" displays */
|
|
47
52
|
md?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
53
|
+
/** Width of the control on "large" displays */
|
|
48
54
|
lg?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
49
|
-
|
|
55
|
+
/** Width of the control on "extra large" displays */
|
|
56
|
+
xl?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
57
|
+
/** If the control should be shown in a new line */
|
|
50
58
|
newLine?: boolean;
|
|
59
|
+
/** Label of the control */
|
|
51
60
|
label?: ioBroker.StringOrTranslated;
|
|
52
61
|
/** @deprecated use label */
|
|
53
62
|
text?: ioBroker.StringOrTranslated;
|
|
63
|
+
/** Formula or false to hide the control: "data.attr === 5" */
|
|
54
64
|
hidden?: string | boolean;
|
|
65
|
+
/** If true and the control is hidden, the place of the control will be still reserved for it */
|
|
55
66
|
hideOnlyControl?: boolean;
|
|
67
|
+
/** JS function to calculate if the control is disabled. You can write "true" too */
|
|
56
68
|
disabled?: string | boolean;
|
|
69
|
+
/** Help text of the control */
|
|
57
70
|
help?: ioBroker.StringOrTranslated;
|
|
71
|
+
/** Link that will be opened by clicking on the help text */
|
|
58
72
|
helpLink?: string;
|
|
59
73
|
style?: CustomCSSProperties;
|
|
60
74
|
darkStyle?: CustomCSSProperties;
|
|
@@ -65,6 +79,8 @@ export interface ConfigItem {
|
|
|
65
79
|
default?: boolean | number | string;
|
|
66
80
|
defaultFunc?: string;
|
|
67
81
|
defaultSendTo?: string;
|
|
82
|
+
/** Allow saving of configuration even with error */
|
|
83
|
+
allowSaveWithError?: boolean;
|
|
68
84
|
data?: string | number | boolean;
|
|
69
85
|
jsonData?: string;
|
|
70
86
|
button?: ioBroker.StringOrTranslated;
|
|
@@ -102,58 +118,92 @@ interface ConfigItemTableIndexed extends ConfigItem {
|
|
|
102
118
|
}
|
|
103
119
|
export interface ConfigItemAlive extends ConfigItem {
|
|
104
120
|
type: 'alive';
|
|
121
|
+
/** check if the instance is alive. If not defined, it will be used current instance. You can use `${data.number}` pattern in the text. */
|
|
105
122
|
instance?: string;
|
|
123
|
+
/** default text is `Instance %s is alive`, where %s will be replaced by `ADAPTER.0`. The translation must exist in i18n files. */
|
|
106
124
|
textAlive?: string;
|
|
125
|
+
/** default text is `Instance %s is not alive`, where %s will be replaced by `ADAPTER.0`. The translation must exist in i18n files. */
|
|
107
126
|
textNotAlive?: string;
|
|
108
127
|
}
|
|
109
128
|
export interface ConfigItemSelectOption {
|
|
129
|
+
/** Label of option */
|
|
110
130
|
label: ioBroker.StringOrTranslated;
|
|
131
|
+
/** Value of option */
|
|
111
132
|
value: number | string;
|
|
133
|
+
/** Formula or boolean value to show or hide the option */
|
|
112
134
|
hidden?: string | boolean;
|
|
113
135
|
}
|
|
114
136
|
export interface ConfigItemPanel extends ConfigItem {
|
|
115
137
|
type: 'panel' | never;
|
|
138
|
+
/** Label of tab */
|
|
116
139
|
label?: ioBroker.StringOrTranslated;
|
|
117
140
|
items: Record<string, ConfigItemAny>;
|
|
141
|
+
/** only possible as not part of tabs */
|
|
118
142
|
collapsable?: boolean;
|
|
143
|
+
/** color of collapsable header `primary` or `secondary` or nothing */
|
|
119
144
|
color?: 'primary' | 'secondary';
|
|
145
|
+
/** CSS Styles in React format (`marginLeft` and not `margin-left`) for the Panel component */
|
|
120
146
|
innerStyle?: CustomCSSProperties;
|
|
147
|
+
/** i18n definitions: true - load from a file, string - name of subdirectory, object - translations */
|
|
121
148
|
i18n?: boolean | string | Record<string, Record<ioBroker.Languages, string>>;
|
|
122
149
|
}
|
|
123
150
|
export interface ConfigItemPattern extends ConfigItem {
|
|
124
151
|
type: 'pattern';
|
|
152
|
+
/** if true - show copy button */
|
|
125
153
|
copyToClipboard?: boolean;
|
|
154
|
+
/** pattern like 'https://${data.ip}:${data.port}' */
|
|
126
155
|
pattern: string;
|
|
127
156
|
}
|
|
128
157
|
export interface ConfigItemChip extends ConfigItem {
|
|
129
158
|
type: 'chips';
|
|
159
|
+
/** if it is defined, so the option will be stored as string with delimiter instead of an array. E.g., by `delimiter=;` you will get `a;b;c` instead of `['a', 'b', 'c']` */
|
|
130
160
|
delimiter?: string;
|
|
131
|
-
pattern: string;
|
|
132
161
|
}
|
|
133
162
|
export interface ConfigItemTabs extends ConfigItem {
|
|
134
163
|
type: 'tabs';
|
|
164
|
+
/** Object with panels `{"tab1": {}, "tab2": {}...}` */
|
|
135
165
|
items: Record<string, ConfigItemPanel>;
|
|
166
|
+
/** `bottom`, `end`, `start` or `top`. Only for panels that has `icon` attribute. Default: `start` */
|
|
136
167
|
iconPosition?: 'bottom' | 'end' | 'start' | 'top';
|
|
168
|
+
/** CSS Styles in React format (`marginLeft` and not `margin-left`) for the Mui-Tabs component */
|
|
137
169
|
tabsStyle?: CustomCSSProperties;
|
|
170
|
+
/** i18n definitions: true - load from a file, string - name of subdirectory, object - translations */
|
|
138
171
|
i18n?: boolean | string | Record<string, Record<ioBroker.Languages, string>>;
|
|
139
172
|
}
|
|
140
173
|
export interface ConfigItemText extends ConfigItem {
|
|
141
174
|
type: 'text';
|
|
175
|
+
/** max length of the text in field */
|
|
142
176
|
maxLength?: number;
|
|
143
177
|
/** @deprecated use maxLength */
|
|
144
178
|
max?: number;
|
|
179
|
+
/** read-only field */
|
|
145
180
|
readOnly?: boolean;
|
|
181
|
+
/** show copy to clipboard button, but only if disabled or read-only */
|
|
182
|
+
copyToClipboard?: boolean;
|
|
183
|
+
/** default is true. Set this attribute to `false` if trim is not desired. */
|
|
146
184
|
trim?: boolean;
|
|
185
|
+
/** default is 1. Set this attribute to `2` or more if you want to have a textarea with more than one row. */
|
|
147
186
|
minRows?: number;
|
|
187
|
+
/** max rows of textarea. Used only if `minRows` > 1. */
|
|
148
188
|
maxRows?: number;
|
|
189
|
+
/** if true, the clear button will not be shown */
|
|
149
190
|
noClearButton?: boolean;
|
|
191
|
+
/** if true, the text will be validated as JSON */
|
|
192
|
+
validateJson?: boolean;
|
|
193
|
+
/** if true, the JSON will be validated only if the value is not empty */
|
|
194
|
+
allowEmpty?: boolean;
|
|
195
|
+
/** the value is time in ms or a string. Used only with readOnly flag */
|
|
196
|
+
time?: boolean;
|
|
150
197
|
}
|
|
151
198
|
export interface ConfigItemColor extends ConfigItem {
|
|
152
199
|
type: 'color';
|
|
200
|
+
/** if true, the clear button will not be shown */
|
|
153
201
|
noClearButton?: boolean;
|
|
154
202
|
}
|
|
155
203
|
export interface ConfigItemCheckbox extends ConfigItem {
|
|
156
204
|
type: 'checkbox';
|
|
205
|
+
/** Same as disabled */
|
|
206
|
+
readOnly?: boolean;
|
|
157
207
|
}
|
|
158
208
|
export interface ConfigItemNumber extends ConfigItem {
|
|
159
209
|
type: 'number';
|
|
@@ -181,6 +231,8 @@ export interface ConfigItemPassword extends ConfigItem {
|
|
|
181
231
|
repeat?: boolean;
|
|
182
232
|
/** true if allow viewing the password by toggling the view button (only for a new password while entering) */
|
|
183
233
|
visible?: boolean;
|
|
234
|
+
/** The read-only flag. Visible is automatically true if readOnly is true */
|
|
235
|
+
readOnly?: boolean;
|
|
184
236
|
/** max length of the text in field */
|
|
185
237
|
maxLength?: number;
|
|
186
238
|
/** @deprecated use maxLength */
|
|
@@ -192,7 +244,8 @@ export interface ConfigItemObjectId extends ConfigItem {
|
|
|
192
244
|
types?: ObjectBrowserType | ObjectBrowserType[];
|
|
193
245
|
/** Show only this root object and its children */
|
|
194
246
|
root?: string;
|
|
195
|
-
/**
|
|
247
|
+
/**
|
|
248
|
+
* Cannot be used together with `type` settings. It is an object and not a JSON string. Examples
|
|
196
249
|
* - `{common: {custom: true}}` - show only objects with some custom settings
|
|
197
250
|
* - `{common: {custom: 'sql.0'}}` - show only objects with sql.0 custom settings (only of the specific instance)
|
|
198
251
|
* - `{common: {custom: '_dataSources'}}` - show only objects of adapters `influxdb` or `sql` or `history`
|
|
@@ -228,6 +281,7 @@ export interface ConfigItemSlider extends ConfigItem {
|
|
|
228
281
|
}
|
|
229
282
|
export interface ConfigItemTopic extends ConfigItem {
|
|
230
283
|
type: 'topic';
|
|
284
|
+
/** max length of the text in field */
|
|
231
285
|
maxLength?: number;
|
|
232
286
|
/** @deprecated use maxLength */
|
|
233
287
|
max?: number;
|
|
@@ -265,11 +319,15 @@ export interface ConfigItemStaticImage extends ConfigItem {
|
|
|
265
319
|
export interface ConfigItemStaticText extends Omit<ConfigItem, 'button'> {
|
|
266
320
|
type: 'staticText';
|
|
267
321
|
/** multi-language text */
|
|
268
|
-
text:
|
|
322
|
+
text: ioBroker.StringOrTranslated;
|
|
269
323
|
/** @deprecated use text */
|
|
270
324
|
label?: ioBroker.StringOrTranslated;
|
|
271
325
|
/** link. Link could be dynamic like `#tab-objects/customs/${data.parentId} */
|
|
272
326
|
href?: string;
|
|
327
|
+
/** target of the link: _self, _blank or window name. For relative links default is _self and for absolute - _blank */
|
|
328
|
+
target?: string;
|
|
329
|
+
/** If the GUI should be closed after a link was opened (only if the target is equal to '_self') */
|
|
330
|
+
close?: boolean;
|
|
273
331
|
/** show a link as button */
|
|
274
332
|
button?: boolean;
|
|
275
333
|
/** type of button (`outlined`, `contained`, `text`) */
|
|
@@ -278,6 +336,35 @@ export interface ConfigItemStaticText extends Omit<ConfigItem, 'button'> {
|
|
|
278
336
|
color?: 'primary' | 'secondary' | 'grey';
|
|
279
337
|
/** if icon should be shown: `auth`, `send`, `web`, `warning`, `error`, `info`, `search`, `book`, `help`, `upload`. You can use `base64` icons (it starts with `data:image/svg+xml;base64,...`) or `jpg/png` images (ends with `.png`) . (Request via issue if you need more icons) */
|
|
280
338
|
icon?: ConfigIconType;
|
|
339
|
+
/** styles for the button */
|
|
340
|
+
controlStyle?: CustomCSSProperties;
|
|
341
|
+
}
|
|
342
|
+
export interface ConfigItemStaticInfo extends Omit<ConfigItem, 'data'> {
|
|
343
|
+
type: 'staticInfo';
|
|
344
|
+
/** multi-language text or value */
|
|
345
|
+
data: ioBroker.StringOrTranslated | number | boolean;
|
|
346
|
+
/** Base64 icon */
|
|
347
|
+
labelIcon?: string;
|
|
348
|
+
/** Unit */
|
|
349
|
+
unit?: ioBroker.StringOrTranslated;
|
|
350
|
+
/** Normally the title and value are shown on the left and right of the line. With this flag, the value will appear just after the label*/
|
|
351
|
+
narrow?: boolean;
|
|
352
|
+
/** Add to label the colon at the end if not exist in label */
|
|
353
|
+
addColon?: boolean;
|
|
354
|
+
/** Value should blink when updated (true or color) */
|
|
355
|
+
blinkOnUpdate?: boolean | string;
|
|
356
|
+
/** Value should blink continuously (true or color) */
|
|
357
|
+
blink?: boolean | string;
|
|
358
|
+
/** Show copy to clipboard button for value */
|
|
359
|
+
copyToClipboard?: boolean;
|
|
360
|
+
/** Label style */
|
|
361
|
+
styleLabel?: CustomCSSProperties;
|
|
362
|
+
/** Value style */
|
|
363
|
+
styleValue?: CustomCSSProperties;
|
|
364
|
+
/** Unit style */
|
|
365
|
+
styleUnit?: CustomCSSProperties;
|
|
366
|
+
/** Font size */
|
|
367
|
+
size?: number | 'small' | 'normal' | 'large';
|
|
281
368
|
}
|
|
282
369
|
export interface ConfigItemRoom extends ConfigItem {
|
|
283
370
|
type: 'room';
|
|
@@ -291,9 +378,10 @@ export interface ConfigItemFunc extends ConfigItem {
|
|
|
291
378
|
}
|
|
292
379
|
export interface ConfigItemSelect extends ConfigItem {
|
|
293
380
|
type: 'select';
|
|
294
|
-
/**
|
|
295
|
-
`[{
|
|
296
|
-
|
|
381
|
+
/**
|
|
382
|
+
* `[{label: {en: "option 1"}, value: 1}, ...]` or
|
|
383
|
+
* `[{"items": [{"label": "Val1", "value": 1}, {"label": "Val2", value: "2}], "name": "group1"}, {"items": [{"label": "Val3", "value": 3}, {"label": "Val4", value: "4}], "name": "group2"}, {"label": "Val5", "value": 5}]`
|
|
384
|
+
*/
|
|
297
385
|
options: (ConfigItemSelectOption | {
|
|
298
386
|
items: ConfigItemSelectOption[];
|
|
299
387
|
label: ioBroker.StringOrTranslated;
|
|
@@ -331,6 +419,7 @@ export interface ConfigItemAutocompleteSendTo extends Omit<ConfigItem, 'data'> {
|
|
|
331
419
|
options?: (string | ConfigItemSelectOption)[];
|
|
332
420
|
data?: Record<string, any>;
|
|
333
421
|
freeSolo?: boolean;
|
|
422
|
+
/** max length of the text in field */
|
|
334
423
|
maxLength?: number;
|
|
335
424
|
/** @deprecated use maxLength */
|
|
336
425
|
max?: string;
|
|
@@ -338,9 +427,13 @@ export interface ConfigItemAutocompleteSendTo extends Omit<ConfigItem, 'data'> {
|
|
|
338
427
|
}
|
|
339
428
|
export interface ConfigItemAccordion extends ConfigItem {
|
|
340
429
|
type: 'accordion';
|
|
430
|
+
/** Title shown on the accordion */
|
|
341
431
|
titleAttr?: string;
|
|
432
|
+
/** If delete or add disabled, If noDelete is false, add, delete and move up/down should work */
|
|
342
433
|
noDelete?: boolean;
|
|
434
|
+
/** If clone button should be shown. If true, the clone button will be shown. If attribute name, this name will be unique. */
|
|
343
435
|
clone?: boolean | string;
|
|
436
|
+
/** Items of accordion */
|
|
344
437
|
items: ConfigItemIndexed[];
|
|
345
438
|
}
|
|
346
439
|
export interface ConfigItemDivider extends ConfigItem {
|
|
@@ -355,12 +448,19 @@ export interface ConfigItemHeader extends ConfigItem {
|
|
|
355
448
|
}
|
|
356
449
|
export interface ConfigItemCoordinates extends ConfigItem {
|
|
357
450
|
type: 'coordinates';
|
|
451
|
+
/** divider between latitude and longitude. Default "," (Used if longitudeName and latitudeName are not defined) */
|
|
358
452
|
divider?: string;
|
|
453
|
+
/** init field with current coordinates if empty */
|
|
359
454
|
autoInit?: boolean;
|
|
455
|
+
/** if defined, the longitude will be stored in this attribute, divider will be ignored */
|
|
360
456
|
longitudeName?: string;
|
|
457
|
+
/** if defined, the latitude will be stored in this attribute, divider will be ignored */
|
|
361
458
|
latitudeName?: string;
|
|
459
|
+
/** if defined, the checkbox with "Use system settings" will be shown and latitude, longitude will be read from system.config, a boolean will be saved to the given name */
|
|
362
460
|
useSystemName?: string;
|
|
461
|
+
/** max length of the text in field */
|
|
363
462
|
maxLength?: number;
|
|
463
|
+
/** @deprecated use maxLength */
|
|
364
464
|
max?: number;
|
|
365
465
|
}
|
|
366
466
|
export interface ConfigItemCustom extends ConfigItem {
|
|
@@ -376,6 +476,7 @@ export interface ConfigItemCustom extends ConfigItem {
|
|
|
376
476
|
}
|
|
377
477
|
export interface ConfigItemDatePicker extends ConfigItem {
|
|
378
478
|
type: 'datePicker';
|
|
479
|
+
/** max length of the text in field */
|
|
379
480
|
maxLength?: number;
|
|
380
481
|
/** @deprecated use maxLength */
|
|
381
482
|
max?: number;
|
|
@@ -421,44 +522,107 @@ export interface ConfigItemSendTo extends Omit<ConfigItem, 'data'> {
|
|
|
421
522
|
/** button tooltip */
|
|
422
523
|
title?: ioBroker.StringOrTranslated;
|
|
423
524
|
alsoDependsOn?: string[];
|
|
424
|
-
container?: 'text' | 'div';
|
|
525
|
+
container?: 'text' | 'div' | 'html';
|
|
425
526
|
copyToClipboard?: boolean;
|
|
527
|
+
/** Styles for button itself */
|
|
528
|
+
controlStyle?: CustomCSSProperties;
|
|
529
|
+
}
|
|
530
|
+
export interface ConfigItemState extends ConfigItem {
|
|
531
|
+
type: 'state';
|
|
532
|
+
/** Describes, which object ID should be taken for the controlling. The ID is without "adapter.X." prefix */
|
|
533
|
+
oid: string;
|
|
534
|
+
/** If true, the state will be taken from system.adapter.XX.I. and not from XX.I */
|
|
535
|
+
system?: boolean;
|
|
536
|
+
/** How the value of the state should be shown */
|
|
537
|
+
control?: 'text' | 'html' | 'input' | 'slider' | 'select' | 'button' | 'switch' | 'number';
|
|
538
|
+
/** If true, the state will be shown as switch, select, button, slider or text input. Used only if no control property is defined */
|
|
539
|
+
controlled?: boolean;
|
|
540
|
+
/** Add unit to the value */
|
|
541
|
+
unit?: string;
|
|
542
|
+
/** this text will be shown if the value is true */
|
|
543
|
+
trueText?: string;
|
|
544
|
+
/** Style of the text if the value is true */
|
|
545
|
+
trueTextStyle?: CustomCSSProperties;
|
|
546
|
+
/** this text will be shown if the value is false or if the control is a "button" */
|
|
547
|
+
falseText?: string;
|
|
548
|
+
/** Style of the text if the value is false or if the control is a "button" */
|
|
549
|
+
falseTextStyle?: CustomCSSProperties;
|
|
550
|
+
/** This image will be shown if the value is true */
|
|
551
|
+
trueImage?: string;
|
|
552
|
+
/** This image will be shown if the value is false or if the control is a "button" */
|
|
553
|
+
falseImage?: string;
|
|
554
|
+
/** Minimum value for control type slider or number */
|
|
555
|
+
min?: number;
|
|
556
|
+
/** Maximum value for control type slider or number */
|
|
557
|
+
max?: number;
|
|
558
|
+
/** Step value for control type slider or number */
|
|
559
|
+
step?: number;
|
|
560
|
+
/** delay in ms for slider or number */
|
|
561
|
+
controlDelay?: number;
|
|
562
|
+
/** Variant of button */
|
|
563
|
+
variant?: 'contained' | 'outlined' | 'text';
|
|
564
|
+
/** Defines if the control is read-only. Applied only to 'input', 'slider', 'select', 'button', 'switch', 'number' */
|
|
565
|
+
readOnly?: boolean;
|
|
426
566
|
}
|
|
427
567
|
export interface ConfigItemTextSendTo extends Omit<ConfigItem, 'data'> {
|
|
428
568
|
type: 'textSendTo';
|
|
429
569
|
container?: 'text' | 'div';
|
|
570
|
+
/** if true - show copy to clipboard button */
|
|
430
571
|
copyToClipboard?: boolean;
|
|
572
|
+
/** by change of which attributes, the command must be resent */
|
|
431
573
|
alsoDependsOn?: string[];
|
|
574
|
+
/** sendTo command */
|
|
432
575
|
command?: string;
|
|
576
|
+
/** string - `{"subject1": "${data.subject}", "options1": {"host": "${data.host}"}}`. This data will be sent to the backend */
|
|
433
577
|
jsonData?: string;
|
|
578
|
+
/** object - `{"subject1": 1, "data": "static"}`. You can specify jsonData or data, but not both. This data will be sent to the backend if jsonData is not defined. */
|
|
434
579
|
data?: Record<string, any>;
|
|
435
580
|
}
|
|
436
581
|
export interface ConfigItemSelectSendTo extends Omit<ConfigItem, 'data'> {
|
|
437
582
|
type: 'selectSendTo';
|
|
583
|
+
/** allow manual editing. Without drop-down menu (if instance is offline). Default `true`. */
|
|
438
584
|
manual?: boolean;
|
|
585
|
+
/** Multiple choice select */
|
|
439
586
|
multiple?: boolean;
|
|
587
|
+
/** show item even if no label was found for it (by multiple), default=`true` */
|
|
440
588
|
showAllValues?: boolean;
|
|
589
|
+
/** if true, the clear button will not be shown */
|
|
441
590
|
noClearButton?: boolean;
|
|
591
|
+
/** sendTo command */
|
|
442
592
|
command?: string;
|
|
593
|
+
/** string - `{"subject1": "${data.subject}", "options1": {"host": "${data.host}"}}`. This data will be sent to the backend */
|
|
443
594
|
jsonData?: string;
|
|
595
|
+
/** object - `{"subject1": 1, "data": "static"}`. You can specify jsonData or data, but not both. This data will be sent to the backend if jsonData is not defined. */
|
|
444
596
|
data?: Record<string, any>;
|
|
597
|
+
/** by change of which attributes, the command must be resent */
|
|
445
598
|
alsoDependsOn?: string[];
|
|
446
599
|
}
|
|
447
600
|
export interface ConfigItemTable extends ConfigItem {
|
|
448
601
|
type: 'table';
|
|
449
602
|
items?: ConfigItemTableIndexed[];
|
|
603
|
+
/** If delete or add disabled, If noDelete is false, add, delete and move up/down should work */
|
|
450
604
|
noDelete?: boolean;
|
|
451
605
|
/** @deprecated don't use */
|
|
452
606
|
objKeyName?: string;
|
|
453
607
|
/** @deprecated don't use */
|
|
454
608
|
objValueName?: string;
|
|
609
|
+
/** If add allowed even if filter is set */
|
|
455
610
|
allowAddByFilter?: boolean;
|
|
611
|
+
/** The number of lines from which the second add button at the bottom of the table will be shown. Default 5 */
|
|
456
612
|
showSecondAddAt?: number;
|
|
613
|
+
/** Show first plus button on top of the first column and not on the left. */
|
|
457
614
|
showFirstAddOnTop?: boolean;
|
|
615
|
+
/** If clone button should be shown. If true, the clone button will be shown. If attribute name, this name will be unique. */
|
|
458
616
|
clone?: boolean | string;
|
|
617
|
+
/** If export button should be shown. Export as csv file. */
|
|
459
618
|
export?: boolean;
|
|
619
|
+
/** If import button should be shown. Import from csv file. */
|
|
460
620
|
import?: boolean;
|
|
621
|
+
/** Show table in compact mode */
|
|
622
|
+
compact?: boolean;
|
|
623
|
+
/** Specify the 'attr' name of columns which need to be unique */
|
|
461
624
|
uniqueColumns?: string[];
|
|
625
|
+
/** These items will be encrypted before saving with simple (not SHA) encryption method */
|
|
462
626
|
encryptedAttributes?: string[];
|
|
463
627
|
}
|
|
464
628
|
export interface ConfigItemTimePicker extends ConfigItem {
|
|
@@ -529,6 +693,10 @@ export interface ConfigItemUUID extends ConfigItem {
|
|
|
529
693
|
}
|
|
530
694
|
export interface ConfigItemJsonEditor extends ConfigItem {
|
|
531
695
|
type: 'jsonEditor';
|
|
696
|
+
/** if false, the text will be not validated as JSON */
|
|
697
|
+
validateJson?: boolean;
|
|
698
|
+
/** if true, the JSON will be validated only if the value is not empty */
|
|
699
|
+
allowEmpty?: boolean;
|
|
532
700
|
}
|
|
533
701
|
export interface ConfigItemInterface extends ConfigItem {
|
|
534
702
|
type: 'interface';
|
|
@@ -539,11 +707,11 @@ export interface ConfigItemInterface extends ConfigItem {
|
|
|
539
707
|
}
|
|
540
708
|
export interface ConfigItemImageUpload extends ConfigItem {
|
|
541
709
|
type: 'image';
|
|
542
|
-
/** name of file is structure name. In the below example `login-bg.png` is file name for `writeFile("myAdapter.INSTANCE", "login-bg.png")` */
|
|
710
|
+
/** name of a file is structure name. In the below example `login-bg.png` is file name for `writeFile("myAdapter.INSTANCE", "login-bg.png")` */
|
|
543
711
|
filename?: string;
|
|
544
|
-
/**
|
|
712
|
+
/** HTML accept attribute, like `{ 'image/**': [], 'application/pdf': ['.pdf'] }`, default `{ 'image/*': [] }` */
|
|
545
713
|
accept?: Record<string, string[]>;
|
|
546
|
-
/** maximal size of file to upload */
|
|
714
|
+
/** maximal size of a file to upload */
|
|
547
715
|
maxSize?: number;
|
|
548
716
|
/** if true, the image will be saved as data-url in attribute, elsewise as binary in file storage */
|
|
549
717
|
base64?: boolean;
|
|
@@ -617,8 +785,44 @@ export interface ConfigItemFileSelector extends ConfigItem {
|
|
|
617
785
|
/** Do not show the size of files */
|
|
618
786
|
noSize?: boolean;
|
|
619
787
|
}
|
|
620
|
-
export type ConfigItemAny = ConfigItemAlive | ConfigItemAutocomplete | ConfigItemAutocompleteSendTo | ConfigItemPanel | ConfigItemTabs | ConfigItemText | ConfigItemNumber | ConfigItemColor | ConfigItemCheckbox | ConfigItemSlider | ConfigItemIP | ConfigItemUser | ConfigItemRoom | ConfigItemFunc | ConfigItemSelect | ConfigItemAccordion | ConfigItemCoordinates | ConfigItemDivider | ConfigItemHeader | ConfigItemCustom | ConfigItemDatePicker | ConfigItemDeviceManager | ConfigItemLanguage | ConfigItemPort | ConfigItemSendTo | ConfigItemTable | ConfigItemTimePicker | ConfigItemTextSendTo | ConfigItemSelectSendTo | ConfigItemCertCollection | ConfigItemCertificateSelect | ConfigItemCertificates | ConfigItemUUID | ConfigItemCheckLicense | ConfigItemPattern | ConfigItemChip | ConfigItemCRON | ConfigItemFile | ConfigItemFileSelector | ConfigItemImageSendTo | ConfigItemInstanceSelect | ConfigItemImageUpload | ConfigItemInterface | ConfigItemJsonEditor | ConfigItemLicense | ConfigItemPassword | ConfigItemSetState | ConfigItemStaticDivider | ConfigItemStaticHeader | ConfigItemStaticImage | ConfigItemStaticText | ConfigItemTopic | ConfigItemObjectId | ConfigItemQrCode;
|
|
621
|
-
export type
|
|
788
|
+
export type ConfigItemAny = ConfigItemAlive | ConfigItemAutocomplete | ConfigItemAutocompleteSendTo | ConfigItemPanel | ConfigItemTabs | ConfigItemText | ConfigItemNumber | ConfigItemColor | ConfigItemCheckbox | ConfigItemSlider | ConfigItemIP | ConfigItemUser | ConfigItemRoom | ConfigItemFunc | ConfigItemSelect | ConfigItemAccordion | ConfigItemCoordinates | ConfigItemDivider | ConfigItemHeader | ConfigItemCustom | ConfigItemDatePicker | ConfigItemDeviceManager | ConfigItemLanguage | ConfigItemPort | ConfigItemSendTo | ConfigItemState | ConfigItemTable | ConfigItemTimePicker | ConfigItemTextSendTo | ConfigItemSelectSendTo | ConfigItemCertCollection | ConfigItemCertificateSelect | ConfigItemCertificates | ConfigItemUUID | ConfigItemCheckLicense | ConfigItemPattern | ConfigItemChip | ConfigItemCRON | ConfigItemFile | ConfigItemFileSelector | ConfigItemImageSendTo | ConfigItemInstanceSelect | ConfigItemImageUpload | ConfigItemInterface | ConfigItemJsonEditor | ConfigItemLicense | ConfigItemPassword | ConfigItemSetState | ConfigItemStaticDivider | ConfigItemStaticHeader | ConfigItemStaticInfo | ConfigItemStaticImage | ConfigItemStaticText | ConfigItemTopic | ConfigItemObjectId | ConfigItemQrCode;
|
|
789
|
+
export type BackEndCommandType = 'nop' | 'refresh' | 'link' | 'message';
|
|
790
|
+
export interface BackEndCommandGeneric {
|
|
791
|
+
command: BackEndCommandType;
|
|
792
|
+
/** New GUI schema */
|
|
793
|
+
schema?: ConfigItemPanel;
|
|
794
|
+
/** New GUI data */
|
|
795
|
+
data?: Record<string, any>;
|
|
796
|
+
refresh?: boolean;
|
|
797
|
+
}
|
|
798
|
+
export interface BackEndCommandNoOperation extends BackEndCommandGeneric {
|
|
799
|
+
command: 'nop';
|
|
800
|
+
}
|
|
801
|
+
export interface BackEndCommandRefresh extends BackEndCommandGeneric {
|
|
802
|
+
command: 'refresh';
|
|
803
|
+
/** If refresh the GUI */
|
|
804
|
+
fullRefresh?: boolean;
|
|
805
|
+
}
|
|
806
|
+
export interface BackEndCommandOpenLink extends BackEndCommandGeneric {
|
|
807
|
+
command: 'link';
|
|
808
|
+
/** Link url. Could be relative ('#blabla') or absolute ('https://blabla') */
|
|
809
|
+
url: string;
|
|
810
|
+
/** Target of the link. Default is `_self` for relative and '_blank' for absolute links */
|
|
811
|
+
target?: '_self' | '_blank' | string;
|
|
812
|
+
/** If GUI should be closed after the link was opened (Only for target='_self') */
|
|
813
|
+
close?: boolean;
|
|
814
|
+
}
|
|
815
|
+
export interface BackEndCommandMessage extends BackEndCommandGeneric {
|
|
816
|
+
command: 'message';
|
|
817
|
+
/** Message text */
|
|
818
|
+
message: ioBroker.StringOrTranslated;
|
|
819
|
+
/** If GUI should be closed after the message shown */
|
|
820
|
+
close?: boolean;
|
|
821
|
+
/** Type of message. Default is 'popup' */
|
|
822
|
+
variant: 'popup' | 'dialog';
|
|
823
|
+
}
|
|
824
|
+
export type BackEndCommand = BackEndCommandMessage | BackEndCommandOpenLink | BackEndCommandRefresh;
|
|
825
|
+
export type JsonFormSchema = ConfigItemPanel | ConfigItemTabs;
|
|
622
826
|
export type JsonFormData = Record<string, any>;
|
|
623
827
|
export interface DeviceDetails {
|
|
624
828
|
id: string;
|
package/build/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export { ChannelInfo, Color, ControlState, ControlBase } from
|
|
1
|
+
export type * from './adapter';
|
|
2
|
+
export type * from './common';
|
|
3
|
+
export * from './errorCodes';
|
|
4
|
+
export type { ChannelInfo, Color, ControlState, ControlBase } from './base';
|
package/build/types/index.js
CHANGED
|
@@ -14,6 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./adapter"), exports);
|
|
18
|
-
__exportStar(require("./common"), exports);
|
|
19
17
|
__exportStar(require("./errorCodes"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iobroker/dm-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "ioBroker Device Manager utilities for backend",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc -p tsconfig.json",
|
|
12
12
|
"lint": "eslint .",
|
|
13
|
+
"updateCommonTs": "node tasks.js",
|
|
13
14
|
"prettier": "prettier -u -w examples src",
|
|
14
15
|
"release": "release-script",
|
|
15
16
|
"release-patch": "release-script patch --yes",
|
|
@@ -21,18 +22,15 @@
|
|
|
21
22
|
"author": "UncleSamSwiss",
|
|
22
23
|
"license": "MIT",
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@iobroker/adapter-core": "^3.
|
|
25
|
+
"@iobroker/adapter-core": "^3.2.2"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
|
-
"@alcalzone/release-script": "^3.
|
|
28
|
+
"@alcalzone/release-script": "^3.8.0",
|
|
28
29
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"eslint-config-prettier": "^9.1.0",
|
|
34
|
-
"prettier": "^3.3.3",
|
|
35
|
-
"typescript": "^5.5.3"
|
|
30
|
+
"@iobroker/eslint-config": "^1.0.0",
|
|
31
|
+
"@types/node": "^22.9.0",
|
|
32
|
+
"axios": "^1.7.7",
|
|
33
|
+
"typescript": "^5.6.3"
|
|
36
34
|
},
|
|
37
35
|
"files": [
|
|
38
36
|
"LICENSE",
|