iobroker.zigbee 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/io-package.json +2 -2
- package/lib/binding.js +9 -13
- package/lib/colors.js +148 -145
- package/lib/commands.js +15 -13
- package/lib/developer.js +3 -5
- package/lib/devices.js +29 -30
- package/lib/exposes.js +60 -31
- package/lib/groups.js +32 -33
- package/lib/json.js +2 -2
- package/lib/networkmap.js +0 -1
- package/lib/ota.js +11 -3
- package/lib/rgb.js +72 -33
- package/lib/seriallist.js +9 -9
- package/lib/states.js +48 -49
- package/lib/statescontroller.js +44 -27
- package/lib/utils.js +3 -3
- package/lib/zbDeviceAvailability.js +26 -25
- package/lib/zbDeviceConfigure.js +2 -2
- package/lib/zigbeecontroller.js +22 -8
- package/main.js +17 -17
- package/package.json +1 -1
package/lib/commands.js
CHANGED
|
@@ -5,7 +5,7 @@ const statesMapping = require('./devices');
|
|
|
5
5
|
const disallowedDashStates = [
|
|
6
6
|
'link_quality', 'available', 'battery', 'groups', 'device_query',
|
|
7
7
|
'hue_move', 'color_temp_move', 'satuation_move', 'brightness_move', 'brightness_step', 'hue_calibration',
|
|
8
|
-
'msg_from_zigbee','send_payload'
|
|
8
|
+
'msg_from_zigbee', 'send_payload',
|
|
9
9
|
];
|
|
10
10
|
|
|
11
11
|
class Commands {
|
|
@@ -183,16 +183,16 @@ class Commands {
|
|
|
183
183
|
result.forEach(async devInfo => {
|
|
184
184
|
if (devInfo._id) {
|
|
185
185
|
// groups
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
//
|
|
186
|
+
// const grState = alls[`${devInfo._id}.groups`];
|
|
187
|
+
// if (grState && grState.val) {
|
|
188
|
+
// groups[devInfo._id] = JSON.parse(grState.val);
|
|
189
|
+
// }
|
|
190
190
|
// battery and link_quality
|
|
191
191
|
const lqState = alls[`${devInfo._id}.link_quality`];
|
|
192
|
-
devInfo.link_quality = lqState ? lqState.val: undefined;
|
|
193
|
-
devInfo.link_quality_lc = lqState ? lqState.lc: undefined;
|
|
192
|
+
devInfo.link_quality = lqState ? lqState.val : undefined;
|
|
193
|
+
devInfo.link_quality_lc = lqState ? lqState.lc : undefined;
|
|
194
194
|
const batState = alls[`${devInfo._id}.battery`];
|
|
195
|
-
devInfo.battery = batState ? batState.val: undefined;
|
|
195
|
+
devInfo.battery = batState ? batState.val : undefined;
|
|
196
196
|
// devInfo.states = states || {};
|
|
197
197
|
|
|
198
198
|
const states = allst.filter(item => item._id.startsWith(devInfo._id));
|
|
@@ -241,11 +241,12 @@ class Commands {
|
|
|
241
241
|
if (groups) {
|
|
242
242
|
const grouparray = groups[member.ieee];
|
|
243
243
|
if (grouparray) {
|
|
244
|
-
if (!grouparray.includes(match[1]))
|
|
244
|
+
if (!grouparray.includes(match[1])) {
|
|
245
245
|
groups[member.ieee].push(match[1]);
|
|
246
246
|
}
|
|
247
|
+
} else {
|
|
248
|
+
groups[member.ieee] = [match[1]];
|
|
247
249
|
}
|
|
248
|
-
else groups[member.ieee] = [match[1]];
|
|
249
250
|
}
|
|
250
251
|
const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
|
|
251
252
|
if (device) {
|
|
@@ -291,7 +292,7 @@ class Commands {
|
|
|
291
292
|
// fill group info
|
|
292
293
|
for (const groupdev in groups) {
|
|
293
294
|
this.debug(`GetDevices scanning group ${groupdev} ${JSON.stringify(groups[groupdev])}`);
|
|
294
|
-
const device = devices.find(
|
|
295
|
+
const device = devices.find(dev => (groupdev === getZbId(dev._id)));
|
|
295
296
|
if (device) {
|
|
296
297
|
device.groups = groups[groupdev];
|
|
297
298
|
this.debug(`adding group info to device ${groupdev}`);
|
|
@@ -394,10 +395,11 @@ class Commands {
|
|
|
394
395
|
coordinatorinfo.version = vt;
|
|
395
396
|
}
|
|
396
397
|
}
|
|
398
|
+
} catch {
|
|
399
|
+
this.warn('exception raised in getCoordinatorInfo');
|
|
397
400
|
}
|
|
398
|
-
catch { this.warn('exception raised in getCoordinatorInfo');}
|
|
399
401
|
|
|
400
|
-
this.debug(`
|
|
402
|
+
this.debug(`getCoordinatorInfo result: ${JSON.stringify(coordinatorinfo)}`);
|
|
401
403
|
this.adapter.sendTo(from, command, coordinatorinfo, callback);
|
|
402
404
|
});
|
|
403
405
|
} else {
|
package/lib/developer.js
CHANGED
|
@@ -91,11 +91,9 @@ class Developer {
|
|
|
91
91
|
const zclData = obj.message.zclData;
|
|
92
92
|
if (cmdType === 'functional') {
|
|
93
93
|
cmd = zcl.Utils.getCluster(cid).getCommand(obj.message.cmd);
|
|
94
|
-
}
|
|
95
|
-
else if (cmdType === 'functionalResp') {
|
|
94
|
+
} else if (cmdType === 'functionalResp') {
|
|
96
95
|
cmd = zcl.Utils.getCluster(cid).getCommandResponse(obj.message.cmd);
|
|
97
|
-
}
|
|
98
|
-
else if (cmdType === 'foundation') {
|
|
96
|
+
} else if (cmdType === 'foundation') {
|
|
99
97
|
cmd = zcl.Utils.getGlobalCommand((obj.message.cmd));
|
|
100
98
|
} else {
|
|
101
99
|
this.adapter.sendTo(obj.from, obj.command, {localErr: 'Invalid cmdType'}, obj.callback);
|
|
@@ -124,7 +122,7 @@ class Developer {
|
|
|
124
122
|
}
|
|
125
123
|
result.statusCode = 0;
|
|
126
124
|
this.adapter.sendTo(obj.from, obj.command, result, obj.callback);
|
|
127
|
-
},obj.message.zclSeqNum);
|
|
125
|
+
}, obj.message.zclSeqNum);
|
|
128
126
|
} catch (exception) {
|
|
129
127
|
// report exceptions
|
|
130
128
|
// happens for example if user tries to send write command but did not provide value/type
|
package/lib/devices.js
CHANGED
|
@@ -52,8 +52,7 @@ const comb = {
|
|
|
52
52
|
effectjson.colors = rgb.colorsArrayFromString(options.effect_colors);
|
|
53
53
|
}
|
|
54
54
|
// effectjson = JSON.parse(value);
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
55
|
+
} catch {
|
|
57
56
|
const effectjson = {
|
|
58
57
|
colors: [{r: 255, g: 0, b: 0}, {r: 0, g: 255, b: 0}, {r: 0, g: 0, b: 255}],
|
|
59
58
|
speed: 10,
|
|
@@ -120,11 +119,11 @@ const sync = {
|
|
|
120
119
|
},
|
|
121
120
|
};
|
|
122
121
|
|
|
123
|
-
const lightStatesWithColortemp = [states.state, states.brightness, states.colortemp,states.brightness_move, states.colortemp_move, states.transition_time];
|
|
124
|
-
const lightStatesWithColor = [states.state, states.brightness, states.colortemp, states.color,states.brightness_move, states.colortemp_move, states.transition_time];
|
|
125
|
-
const lightStatesWithColor_hue = [states.state, states.brightness, states.colortemp, states.color,states.brightness_move, states.colortemp_move, states.hue_move, states.transition_time, states.effect_type_hue];
|
|
122
|
+
const lightStatesWithColortemp = [states.state, states.brightness, states.colortemp, states.brightness_move, states.colortemp_move, states.transition_time];
|
|
123
|
+
const lightStatesWithColor = [states.state, states.brightness, states.colortemp, states.color, states.brightness_move, states.colortemp_move, states.transition_time];
|
|
124
|
+
const lightStatesWithColor_hue = [states.state, states.brightness, states.colortemp, states.color, states.brightness_move, states.colortemp_move, states.hue_move, states.transition_time, states.effect_type_hue];
|
|
126
125
|
const lightStatesWithColorNoTemp = [states.state, states.brightness, states.color, states.brightness_move, states.transition_time];
|
|
127
|
-
const lightStates = [states.state, states.brightness, states.brightness_move,
|
|
126
|
+
const lightStates = [states.state, states.brightness, states.brightness_move, states.transition_time];
|
|
128
127
|
|
|
129
128
|
const gl_lightStatesWithColor = [states.gl_state, states.gl_brightness, states.gl_colortemp, states.gl_color, states.transition_time];
|
|
130
129
|
const gl_white_channel = [states.white_brightness, states.white_state, states.white_colortemp];
|
|
@@ -233,8 +232,8 @@ const generator = {
|
|
|
233
232
|
}
|
|
234
233
|
return freepad_states.concat(freepad_st);
|
|
235
234
|
},
|
|
236
|
-
ptvo_switch_channels: entity =>{
|
|
237
|
-
const devstates = [states.ptvo_trigger,states.ptvo_interval];
|
|
235
|
+
ptvo_switch_channels: entity => {
|
|
236
|
+
const devstates = [states.ptvo_trigger, states.ptvo_interval];
|
|
238
237
|
for (const endpoint of entity.device.endpoints) {
|
|
239
238
|
const epID = endpoint.ID;
|
|
240
239
|
const epName = getKey(entity.mapped.endpoint(entity.device), epID);
|
|
@@ -260,7 +259,7 @@ const generator = {
|
|
|
260
259
|
// l7:l7=143voltage_l7=143
|
|
261
260
|
|
|
262
261
|
if (payload.hasOwnProperty(`device_${epName}`)) {
|
|
263
|
-
id = (typeof
|
|
262
|
+
id = (typeof payload[`device_${epName}`] === 'string' ? payload[`device_${epName}`].replace(/[-. ]/g, '') : 'unset');
|
|
264
263
|
} else if (payload.hasOwnProperty(`voltage_${epName}`)) {
|
|
265
264
|
id = 'voltage';
|
|
266
265
|
}
|
|
@@ -277,12 +276,13 @@ const generator = {
|
|
|
277
276
|
}
|
|
278
277
|
}
|
|
279
278
|
}
|
|
280
|
-
if (measurement && id !== 'voltage')
|
|
279
|
+
if (measurement && id !== 'voltage') {
|
|
281
280
|
rv.stateid = `${id}_${measurement}`;
|
|
282
|
-
else
|
|
281
|
+
} else {
|
|
283
282
|
rv.stateid = id;
|
|
283
|
+
}
|
|
284
284
|
rv.value = payload[epName];
|
|
285
|
-
rv.name = measurement? `${measurement} 0x${id}
|
|
285
|
+
rv.name = measurement ? `${measurement} 0x${id}` : `0x${id}`;
|
|
286
286
|
rv.unit = unit;
|
|
287
287
|
rv.role = measurement;
|
|
288
288
|
|
|
@@ -569,13 +569,13 @@ const generator = {
|
|
|
569
569
|
},
|
|
570
570
|
};
|
|
571
571
|
|
|
572
|
-
function states_with_epname
|
|
572
|
+
function states_with_epname(entity, states) {
|
|
573
573
|
const devstates = [];
|
|
574
574
|
for (const endpoint of entity.device.endpoints) {
|
|
575
575
|
const epID = endpoint.ID;
|
|
576
576
|
const epName = getKey(entity.mapped.endpoint(entity.device), epID);
|
|
577
577
|
for (const state of states) {
|
|
578
|
-
const newState = {
|
|
578
|
+
const newState = {...state};
|
|
579
579
|
newState.id = `${newState.id}_${epName}`;
|
|
580
580
|
if (newState.name) newState.name = `${newState.name} (${epName})`;
|
|
581
581
|
if (newState.prop) newState.prop = `${newState.prop}_${epName}`;
|
|
@@ -622,7 +622,7 @@ const devices = [
|
|
|
622
622
|
],
|
|
623
623
|
},
|
|
624
624
|
{
|
|
625
|
-
models: ['WXKG03LM','WXKG03LM_rev2'],
|
|
625
|
+
models: ['WXKG03LM', 'WXKG03LM_rev2'],
|
|
626
626
|
icon: 'img/86sw1.png',
|
|
627
627
|
states: [
|
|
628
628
|
states.click, states.double_click, states.voltage, states.battery,
|
|
@@ -638,7 +638,7 @@ const devices = [
|
|
|
638
638
|
],
|
|
639
639
|
},
|
|
640
640
|
{
|
|
641
|
-
models: ['WXKG02LM','WXKG02LM_rev2'],
|
|
641
|
+
models: ['WXKG02LM', 'WXKG02LM_rev2'],
|
|
642
642
|
icon: 'img/86sw2.png',
|
|
643
643
|
states: [
|
|
644
644
|
states.left_click, states.right_click, states.both_click,
|
|
@@ -995,7 +995,7 @@ const devices = [
|
|
|
995
995
|
states: [states.occupancy, states.temperature, states.temp_calibration],
|
|
996
996
|
},
|
|
997
997
|
{
|
|
998
|
-
models: ['595UGR22','4058075181472'],
|
|
998
|
+
models: ['595UGR22', '4058075181472'],
|
|
999
999
|
icon: 'img/FLOALT.panel.WS.png',
|
|
1000
1000
|
states: lightStatesWithColortemp,
|
|
1001
1001
|
syncStates: [sync.brightness],
|
|
@@ -1168,7 +1168,7 @@ const devices = [
|
|
|
1168
1168
|
syncStates: [sync.brightness],
|
|
1169
1169
|
},
|
|
1170
1170
|
{
|
|
1171
|
-
models: ['5055131P7','5055148P7'],
|
|
1171
|
+
models: ['5055131P7', '5055148P7'],
|
|
1172
1172
|
icon: 'img/philips_hue_centura_square.png',
|
|
1173
1173
|
states: lightStatesWithColor_hue,
|
|
1174
1174
|
syncStates: [sync.brightness],
|
|
@@ -1490,7 +1490,7 @@ const devices = [
|
|
|
1490
1490
|
{
|
|
1491
1491
|
models: ['E1757', 'E1926'],
|
|
1492
1492
|
states: [states.battery, states.blind_position, states.blind_open, states.blind_close, states.blind_stop],
|
|
1493
|
-
icon:
|
|
1493
|
+
icon: 'img/Ikea_fyrtur.png',
|
|
1494
1494
|
},
|
|
1495
1495
|
{
|
|
1496
1496
|
models: ['ICPSHC24-10EU-IL-1', 'ICPSHC24-30EU-IL-1'],
|
|
@@ -1512,7 +1512,7 @@ const devices = [
|
|
|
1512
1512
|
{
|
|
1513
1513
|
models: ['E1744'],
|
|
1514
1514
|
icon: 'img/ikea_SYMFONISK_Sound_Controller.png',
|
|
1515
|
-
states: [states.button_action_skip_back, states.button_action_skip_forward,
|
|
1515
|
+
states: [states.button_action_skip_back, states.button_action_skip_forward, states.action_play_pause,
|
|
1516
1516
|
states.rotate_left, states.rotate_right, states.rotate_stop, states.battery],
|
|
1517
1517
|
},
|
|
1518
1518
|
// Hive
|
|
@@ -1611,7 +1611,7 @@ const devices = [
|
|
|
1611
1611
|
{
|
|
1612
1612
|
models: ['SP 120', 'SP 220', 'SP 222', 'SP 224'],
|
|
1613
1613
|
icon: 'img/innr_plug.png',
|
|
1614
|
-
states: [states.state,states.load_power],
|
|
1614
|
+
states: [states.state, states.load_power],
|
|
1615
1615
|
},
|
|
1616
1616
|
{
|
|
1617
1617
|
models: ['FL 130 C'],
|
|
@@ -1918,7 +1918,7 @@ const devices = [
|
|
|
1918
1918
|
syncStates: [sync.brightness],
|
|
1919
1919
|
},
|
|
1920
1920
|
{
|
|
1921
|
-
models: ['798.09','371000002'],
|
|
1921
|
+
models: ['798.09', '371000002'],
|
|
1922
1922
|
icon: 'img/Paulmann_79809.png',
|
|
1923
1923
|
states: lightStatesWithColor,
|
|
1924
1924
|
syncStates: [sync.brightness],
|
|
@@ -1938,7 +1938,7 @@ const devices = [
|
|
|
1938
1938
|
states.brightness_move_down, states.brightness_move_down_size,
|
|
1939
1939
|
states.enhanced_move_to_hue_and_saturation, states.enhanced_move_enhanced_hue,
|
|
1940
1940
|
states.enhanced_move_hue, states.enhanced_move_saturation,
|
|
1941
|
-
states.scene,states.action_group
|
|
1941
|
+
states.scene, states.action_group,
|
|
1942
1942
|
],
|
|
1943
1943
|
},
|
|
1944
1944
|
|
|
@@ -2091,7 +2091,7 @@ const devices = [
|
|
|
2091
2091
|
linkedStates: [comb.brightnessAndState],
|
|
2092
2092
|
},
|
|
2093
2093
|
{
|
|
2094
|
-
models: ['MLI-404011','MLI-404049','MLI-404011/MLI-404049'],
|
|
2094
|
+
models: ['MLI-404011', 'MLI-404049', 'MLI-404011/MLI-404049'],
|
|
2095
2095
|
icon: 'img/MLI-404011-MLI-404049.png',
|
|
2096
2096
|
states: [
|
|
2097
2097
|
states.tint404011_scene_sunset, states.tint404011_scene_party,
|
|
@@ -2228,7 +2228,7 @@ const devices = [
|
|
|
2228
2228
|
{
|
|
2229
2229
|
models: ['07048L'],
|
|
2230
2230
|
icon: 'img/innr_plug.png',
|
|
2231
|
-
states: [states.state,states.load_power],
|
|
2231
|
+
states: [states.state, states.load_power],
|
|
2232
2232
|
},
|
|
2233
2233
|
{
|
|
2234
2234
|
models: ['AV2010/32'],
|
|
@@ -2404,12 +2404,12 @@ const devices = [
|
|
|
2404
2404
|
states: [states.state],
|
|
2405
2405
|
},
|
|
2406
2406
|
{
|
|
2407
|
-
models: [
|
|
2407
|
+
models: ['X712A'],
|
|
2408
2408
|
icon: 'img/tuya_switch_2.png',
|
|
2409
2409
|
states: [states.l1, states.l2],
|
|
2410
2410
|
},
|
|
2411
2411
|
{
|
|
2412
|
-
models: [
|
|
2412
|
+
models: ['X713A'],
|
|
2413
2413
|
icon: 'img/tuya_switch_3.png',
|
|
2414
2414
|
states: [states.l1, states.l2, states.l3],
|
|
2415
2415
|
},
|
|
@@ -2553,7 +2553,7 @@ const devices = [
|
|
|
2553
2553
|
],
|
|
2554
2554
|
},
|
|
2555
2555
|
{
|
|
2556
|
-
models: ['SEA802-Zigbee','SEA801-Zigbee/SEA802-Zigbee'],
|
|
2556
|
+
models: ['SEA802-Zigbee', 'SEA801-Zigbee/SEA802-Zigbee'],
|
|
2557
2557
|
icon: 'img/tuya_TS0601.png',
|
|
2558
2558
|
states: [
|
|
2559
2559
|
states.child_lock,
|
|
@@ -3108,7 +3108,6 @@ function fillStatesWithExposes(allExcludesObj) {
|
|
|
3108
3108
|
applyExposes(devices, byModel, allExcludesObj);
|
|
3109
3109
|
|
|
3110
3110
|
removeEmptyStates(devices);
|
|
3111
|
-
|
|
3112
3111
|
}
|
|
3113
3112
|
|
|
3114
3113
|
// remove empty states
|
|
@@ -3122,7 +3121,7 @@ function removeEmptyStates(devices) {
|
|
|
3122
3121
|
|
|
3123
3122
|
function findModel(model) {
|
|
3124
3123
|
const byModel = getByModel();
|
|
3125
|
-
const stripModel =
|
|
3124
|
+
const stripModel = model ? model.replace(/0.*$/g, '').trim() : '';
|
|
3126
3125
|
return byModel.get(stripModel);
|
|
3127
3126
|
}
|
|
3128
3127
|
|
package/lib/exposes.js
CHANGED
|
@@ -29,9 +29,8 @@ function genState(expose, role, name, desc) {
|
|
|
29
29
|
type: 'boolean',
|
|
30
30
|
};
|
|
31
31
|
if (readable) {
|
|
32
|
-
state.getter = payload =>
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
32
|
+
state.getter = payload => payload[propName] === (expose.value_on || 'ON');
|
|
33
|
+
} else {
|
|
35
34
|
state.getter = payload => undefined;
|
|
36
35
|
}
|
|
37
36
|
if (writable) {
|
|
@@ -124,7 +123,7 @@ function createFromExposes(model, def) {
|
|
|
124
123
|
}
|
|
125
124
|
state.readable = (access & ea.STATE) > 0;
|
|
126
125
|
state.writable = (access & ea.SET) > 0;
|
|
127
|
-
const stateExists = states.findIndex(
|
|
126
|
+
const stateExists = states.findIndex((element, index, array) => element.id === state.id);
|
|
128
127
|
if (stateExists < 0) {
|
|
129
128
|
state.write = state.writable;
|
|
130
129
|
if (!state.writable) {
|
|
@@ -137,13 +136,12 @@ function createFromExposes(model, def) {
|
|
|
137
136
|
}
|
|
138
137
|
if (!state.readable) {
|
|
139
138
|
if (state.hasOwnProperty('getter')) {
|
|
140
|
-
//to
|
|
141
|
-
state.getter = payload =>
|
|
139
|
+
// to awoid some warnings on unprocessed data
|
|
140
|
+
state.getter = payload => undefined;
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
return states.push(state);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
144
|
+
} else {
|
|
147
145
|
if ((state.readable) && (!states[stateExists].readable)) {
|
|
148
146
|
states[stateExists].read = state.read;
|
|
149
147
|
// as state is readable, it can't be button or event
|
|
@@ -154,14 +152,14 @@ function createFromExposes(model, def) {
|
|
|
154
152
|
delete states[stateExists].isEvent;
|
|
155
153
|
}
|
|
156
154
|
// we have to use the getter from "new" state
|
|
157
|
-
if (
|
|
155
|
+
if (state.hasOwnProperty('getter')) {
|
|
158
156
|
states[stateExists].getter = state.getter;
|
|
159
157
|
}
|
|
160
158
|
// trying to remove the `prop` property, as main key for get and set,
|
|
161
159
|
// as it can be different in new and old states, and leave only:
|
|
162
160
|
// setattr for old and id for new
|
|
163
161
|
if ((state.hasOwnProperty('prop')) && (state.prop === state.id)) {
|
|
164
|
-
if (
|
|
162
|
+
if (states[stateExists].hasOwnProperty('prop')) {
|
|
165
163
|
if (states[stateExists].prop !== states[stateExists].id) {
|
|
166
164
|
if (!states[stateExists].hasOwnProperty('setattr')) {
|
|
167
165
|
states[stateExists].setattr = states[stateExists].prop;
|
|
@@ -169,7 +167,7 @@ function createFromExposes(model, def) {
|
|
|
169
167
|
}
|
|
170
168
|
delete states[stateExists].prop;
|
|
171
169
|
}
|
|
172
|
-
} else if (
|
|
170
|
+
} else if (state.hasOwnProperty('prop')) {
|
|
173
171
|
states[stateExists].prop = state.prop;
|
|
174
172
|
}
|
|
175
173
|
states[stateExists].readable = true;
|
|
@@ -191,7 +189,7 @@ function createFromExposes(model, def) {
|
|
|
191
189
|
// as we have new state, responsible for set, we have to use new `isOption`
|
|
192
190
|
// or remove it
|
|
193
191
|
if (((!state.hasOwnProperty('isOption')) || (state.isOptions === false))
|
|
194
|
-
|
|
192
|
+
&& (states[stateExists].hasOwnProperty('isOption'))) {
|
|
195
193
|
delete states[stateExists].isOption;
|
|
196
194
|
} else {
|
|
197
195
|
states[stateExists].isOption = state.isOption;
|
|
@@ -217,6 +215,7 @@ function createFromExposes(model, def) {
|
|
|
217
215
|
return states.length;
|
|
218
216
|
}
|
|
219
217
|
}
|
|
218
|
+
|
|
220
219
|
const icon = utils.getDeviceIcon(def);
|
|
221
220
|
for (const expose of def.exposes) {
|
|
222
221
|
let state;
|
|
@@ -318,7 +317,7 @@ function createFromExposes(model, def) {
|
|
|
318
317
|
read: true,
|
|
319
318
|
type: 'string',
|
|
320
319
|
setter: value => {
|
|
321
|
-
|
|
320
|
+
// convert RGB to XY for set
|
|
322
321
|
/*
|
|
323
322
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(value);
|
|
324
323
|
let xy = [0, 0];
|
|
@@ -375,7 +374,7 @@ function createFromExposes(model, def) {
|
|
|
375
374
|
const _rgb = colors.ParseColor(value);
|
|
376
375
|
const hsv = rgb.rgbToHSV(_rgb.r, _rgb.g, _rgb.b, true);
|
|
377
376
|
return {
|
|
378
|
-
hue: Math.min(Math.max(hsv.h,1),359),
|
|
377
|
+
hue: Math.min(Math.max(hsv.h, 1), 359),
|
|
379
378
|
saturation: hsv.s,
|
|
380
379
|
// brightness: Math.floor(hsv.v * 2.55),
|
|
381
380
|
};
|
|
@@ -412,17 +411,27 @@ function createFromExposes(model, def) {
|
|
|
412
411
|
const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
|
|
413
412
|
if (hasHueCalibrationTable)
|
|
414
413
|
try {
|
|
415
|
-
return {
|
|
416
|
-
|
|
417
|
-
|
|
414
|
+
return {
|
|
415
|
+
...options,
|
|
416
|
+
transition: transitionTime,
|
|
417
|
+
hue_correction: JSON.parse(options.hue_calibration)
|
|
418
|
+
};
|
|
419
|
+
} catch {
|
|
418
420
|
const hue_correction_table = [];
|
|
419
421
|
options.hue_calibration.split(',').forEach(element => {
|
|
420
422
|
const match = /([0-9]+):([0-9]+)/.exec(element);
|
|
421
423
|
if (match && match.length === 3)
|
|
422
|
-
hue_correction_table.push({
|
|
424
|
+
hue_correction_table.push({
|
|
425
|
+
in: Number(match[1]),
|
|
426
|
+
out: Number(match[2])
|
|
427
|
+
});
|
|
423
428
|
});
|
|
424
429
|
if (hue_correction_table.length > 0) {
|
|
425
|
-
return {
|
|
430
|
+
return {
|
|
431
|
+
...options,
|
|
432
|
+
transition: transitionTime,
|
|
433
|
+
hue_correction: hue_correction_table
|
|
434
|
+
};
|
|
426
435
|
}
|
|
427
436
|
}
|
|
428
437
|
return {...options, transition: transitionTime};
|
|
@@ -451,17 +460,27 @@ function createFromExposes(model, def) {
|
|
|
451
460
|
const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
|
|
452
461
|
if (hasHueCalibrationTable)
|
|
453
462
|
try {
|
|
454
|
-
return {
|
|
455
|
-
|
|
456
|
-
|
|
463
|
+
return {
|
|
464
|
+
...options,
|
|
465
|
+
transition: transitionTime,
|
|
466
|
+
hue_correction: JSON.parse(options.hue_calibration)
|
|
467
|
+
};
|
|
468
|
+
} catch {
|
|
457
469
|
const hue_correction_table = [];
|
|
458
470
|
options.hue_calibration.split(',').forEach(element => {
|
|
459
471
|
const match = /([0-9]+):([0-9]+)/.exec(element);
|
|
460
472
|
if (match && match.length === 3)
|
|
461
|
-
hue_correction_table.push({
|
|
473
|
+
hue_correction_table.push({
|
|
474
|
+
in: Number(match[1]),
|
|
475
|
+
out: Number(match[2])
|
|
476
|
+
});
|
|
462
477
|
});
|
|
463
478
|
if (hue_correction_table.length > 0) {
|
|
464
|
-
return {
|
|
479
|
+
return {
|
|
480
|
+
...options,
|
|
481
|
+
transition: transitionTime,
|
|
482
|
+
hue_correction: hue_correction_table
|
|
483
|
+
};
|
|
465
484
|
}
|
|
466
485
|
}
|
|
467
486
|
return {...options, transition: transitionTime};
|
|
@@ -490,17 +509,28 @@ function createFromExposes(model, def) {
|
|
|
490
509
|
const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
|
|
491
510
|
if (hasHueCalibrationTable)
|
|
492
511
|
try {
|
|
493
|
-
return {
|
|
512
|
+
return {
|
|
513
|
+
...options,
|
|
514
|
+
transition: transitionTime,
|
|
515
|
+
hue_correction: JSON.parse(options.hue_calibration)
|
|
516
|
+
};
|
|
494
517
|
} catch {
|
|
495
518
|
const hue_correction_table = [];
|
|
496
519
|
options.hue_calibration.split(',').forEach(element => {
|
|
497
520
|
const match = /([0-9]+):([0-9]+)/.exec(element);
|
|
498
521
|
if (match && match.length === 3) {
|
|
499
|
-
hue_correction_table.push({
|
|
522
|
+
hue_correction_table.push({
|
|
523
|
+
in: Number(match[1]),
|
|
524
|
+
out: Number(match[2])
|
|
525
|
+
});
|
|
500
526
|
}
|
|
501
527
|
});
|
|
502
528
|
if (hue_correction_table.length > 0) {
|
|
503
|
-
return {
|
|
529
|
+
return {
|
|
530
|
+
...options,
|
|
531
|
+
transition: transitionTime,
|
|
532
|
+
hue_correction: hue_correction_table
|
|
533
|
+
};
|
|
504
534
|
}
|
|
505
535
|
}
|
|
506
536
|
return {...options, transition: transitionTime};
|
|
@@ -739,10 +769,9 @@ function createFromExposes(model, def) {
|
|
|
739
769
|
// if we have a composite expose, the payload will be an object {expose.property : {prop.property: value}}
|
|
740
770
|
if (prop.access & ea.STATE) {
|
|
741
771
|
st.getter = payload => {
|
|
742
|
-
if (
|
|
743
|
-
return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined
|
|
744
|
-
}
|
|
745
|
-
else {
|
|
772
|
+
if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
|
|
773
|
+
return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined;
|
|
774
|
+
} else {
|
|
746
775
|
return undefined;
|
|
747
776
|
}
|
|
748
777
|
};
|
package/lib/groups.js
CHANGED
|
@@ -92,7 +92,7 @@ class Groups {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
async getGroups(obj) {
|
|
95
|
-
const response = {
|
|
95
|
+
const response = {groups: {}};
|
|
96
96
|
try {
|
|
97
97
|
// const groupsState = await this.adapter.getStateAsync('info.groups');
|
|
98
98
|
const herdsmanGroups = await this.zbController.getGroups();
|
|
@@ -104,7 +104,7 @@ class Groups {
|
|
|
104
104
|
for (const group of herdsmanGroups) {
|
|
105
105
|
const gid = group.groupID;
|
|
106
106
|
if (gid) {
|
|
107
|
-
groups[gid]=this.stController.verifyDeviceName(`group_${gid}
|
|
107
|
+
groups[gid] = this.stController.verifyDeviceName(`group_${gid}`, `Group ${gid}`);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -137,13 +137,13 @@ class Groups {
|
|
|
137
137
|
for (const gpid of groups[epid]) {
|
|
138
138
|
const gpidn = parseInt(gpid);
|
|
139
139
|
if (gpidn < 0) {
|
|
140
|
-
|
|
140
|
+
const response = await this.zbController.removeDevFromGroup(sysid, (-gpidn), epid);
|
|
141
141
|
if (response && response.error) {
|
|
142
142
|
errors.push(response.error);
|
|
143
143
|
this.error(`remove dev from group Error: ${JSON.stringify(response.error)}`);
|
|
144
144
|
}
|
|
145
|
-
} else if (gpidn > 0){
|
|
146
|
-
|
|
145
|
+
} else if (gpidn > 0) {
|
|
146
|
+
const response = await this.zbController.addDevToGroup(sysid, (gpidn), epid);
|
|
147
147
|
if (response && response.error) {
|
|
148
148
|
errors.push(response.error);
|
|
149
149
|
this.error(`add dev to group Error: ${JSON.stringify(response.error)}`);
|
|
@@ -157,7 +157,7 @@ class Groups {
|
|
|
157
157
|
this.adapter.sendTo(from, command, {error: e}, callback);
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
160
|
-
this.adapter.sendTo(from, command, {
|
|
160
|
+
this.adapter.sendTo(from, command, {}, callback);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
|
|
@@ -188,43 +188,43 @@ class Groups {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
if (result.unsupported.length>0) {
|
|
191
|
+
if (result.unsupported.length > 0) {
|
|
192
192
|
const error = {
|
|
193
193
|
code: 134,
|
|
194
194
|
message: `unsupported ${stateDesc.id} change for group members ${result.unsupported.join()}`
|
|
195
195
|
};
|
|
196
196
|
throw error;
|
|
197
197
|
}
|
|
198
|
-
if (result.unread.length>0) {
|
|
198
|
+
if (result.unread.length > 0) {
|
|
199
199
|
this.warn(`unread ${stateDesc.id} change for group members ${JSON.stringify(result.unread)}`);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
async deleteGroup(from, command, message) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
204
|
+
/*
|
|
205
|
+
const members = await this.getGroupMembersFromController(parseInt(message));
|
|
206
|
+
if (members && members.length) {
|
|
207
|
+
for (const member of members) {
|
|
208
|
+
const devName = member.device.substring(2);
|
|
209
|
+
const groupEntry = this.adapter.getStateAsync(`${devName}.groups`);
|
|
210
|
+
const memberarray = (groupEntry && groupEntry.val) ? JSON.parse(groupEntry.val) : [];
|
|
211
|
+
const index = memberarray.indexOf(message.toString());
|
|
212
|
+
if (index > -1) {
|
|
213
|
+
memberarray.splice(index, 1);
|
|
214
|
+
}
|
|
215
|
+
if (memberarray.length > 0) {
|
|
216
|
+
await this.adapter.setStateAsync(`${devName}.groups`, JSON.stringify(memberarray), true);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
await this.adapter.setStateAsync(`${devName}.groups`, '', true);
|
|
220
|
+
}
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
*/
|
|
223
|
+
const groupsEntry = await this.adapter.getStateAsync('info.groups');
|
|
224
|
+
const objGroups = (groupsEntry && groupsEntry.val ? JSON.parse(groupsEntry.val) : {});
|
|
225
|
+
delete objGroups[message.toString()];
|
|
226
|
+
await this.adapter.setStateAsync('info.groups', JSON.stringify(objGroups), true);
|
|
227
|
+
*/
|
|
228
228
|
await this.zbController.removeGroupById(message);
|
|
229
229
|
await this.stController.deleteDeviceStatesAsync(`group_${parseInt(message)}`);
|
|
230
230
|
}
|
|
@@ -317,7 +317,7 @@ class Groups {
|
|
|
317
317
|
usedGroupsIds.push(parseInt(j));
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
|
-
chain.push(new Promise(resolve =>
|
|
320
|
+
chain.push(new Promise(resolve =>
|
|
321
321
|
// remove unused adapter groups
|
|
322
322
|
this.adapter.getDevices((err, devices) => {
|
|
323
323
|
if (!err) {
|
|
@@ -331,8 +331,7 @@ class Groups {
|
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
333
|
resolve();
|
|
334
|
-
});
|
|
335
|
-
}));
|
|
334
|
+
})));
|
|
336
335
|
|
|
337
336
|
await Promise.all(chain);
|
|
338
337
|
}
|