iobroker.zigbee 1.8.0 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.eslintrc.json +37 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/auto-merge.yml +17 -0
- package/.github/dependabot.yml +24 -0
- package/.github/stale.yml +13 -0
- package/.github/workflows/codeql.yml +41 -0
- package/.github/workflows/dependabot-automerge.yml +22 -0
- package/.github/workflows/test-and-release.yml +149 -0
- package/.releaseconfig.json +3 -0
- package/.travis/wiki.sh +28 -0
- package/.travis.yml +41 -0
- package/README.md +32 -9
- package/admin/admin.js +466 -482
- package/admin/i18n/de/translations.json +2 -2
- package/admin/index_m.html +1 -1
- package/admin/tab_m.html +3 -44
- package/admin/words.js +2 -2
- package/gulpfile.js +464 -0
- package/io-package.json +19 -26
- package/lib/backup.js +2 -2
- package/lib/binding.js +24 -23
- package/lib/colors.js +14 -16
- package/lib/commands.js +82 -89
- package/lib/developer.js +7 -6
- package/lib/devices.js +153 -144
- package/lib/exclude.js +36 -30
- package/lib/exposes.js +111 -106
- package/lib/groups.js +54 -53
- package/lib/json.js +4 -3
- package/lib/networkmap.js +2 -2
- package/lib/ota.js +15 -23
- package/lib/rgb.js +44 -47
- package/lib/seriallist.js +16 -21
- package/lib/states.js +496 -482
- package/lib/statescontroller.js +164 -170
- package/lib/utils.js +21 -22
- package/lib/zbBaseExtension.js +4 -4
- package/lib/zbDelayedAction.js +13 -5
- package/lib/zbDeviceAvailability.js +44 -47
- package/lib/zbDeviceConfigure.js +19 -7
- package/lib/zbDeviceEvent.js +4 -3
- package/lib/zigbeecontroller.js +96 -88
- package/main.js +133 -149
- package/package.json +15 -29
- package/test/integration.js +5 -0
- package/test/mocha.custom.opts +2 -0
- package/test/mocha.setup.js +14 -0
- package/test/package.js +5 -0
- package/test/unit.js +5 -0
- package/docs/de/img/CC2531.png +0 -0
- package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
- package/docs/de/img/CC2591.png +0 -0
- package/docs/de/img/boards.jpg +0 -0
- package/docs/de/img/cc26x2r.PNG +0 -0
- package/docs/de/img/results.jpg +0 -0
- package/docs/de/img/sku_429478_2.png +0 -0
- package/docs/de/img/sku_429601_2.png +0 -0
- package/docs/de/readme.md +0 -27
- package/docs/en/img/CC2531.png +0 -0
- package/docs/en/img/CC2591.png +0 -0
- package/docs/en/img/deconz.png +0 -0
- package/docs/en/img/sku_429478_2.png +0 -0
- package/docs/en/img/sku_429601_2.png +0 -0
- package/docs/en/readme.md +0 -30
- package/docs/flashing_via_arduino_(en).md +0 -110
- package/docs/ru/img/CC2531.png +0 -0
- package/docs/ru/img/CC2591.png +0 -0
- package/docs/ru/img/sku_429478_2.png +0 -0
- package/docs/ru/img/sku_429601_2.png +0 -0
- package/docs/ru/readme.md +0 -28
- package/docs/tutorial/CC2530_20190425.zip +0 -0
- package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
- package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
- package/docs/tutorial/CC2531_20190425.zip +0 -0
- package/docs/tutorial/adm5_1.PNG +0 -0
- package/docs/tutorial/adm5_2.PNG +0 -0
- package/docs/tutorial/cat.PNG +0 -0
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/inst.PNG +0 -0
- package/docs/tutorial/reflash-finish.PNG +0 -0
- package/docs/tutorial/reflash-step0.png +0 -0
- package/docs/tutorial/reflash-step1.PNG +0 -0
- package/docs/tutorial/reflash-step2.PNG +0 -0
- package/docs/tutorial/settings.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/docs/tutorial/zigbee.png +0 -0
- package/docs/tutorial/zigbee15.png +0 -0
package/lib/groups.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const statesMapping = require('./devices');
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
class Groups {
|
|
6
7
|
constructor(adapter) {
|
|
7
8
|
this.adapter = adapter;
|
|
@@ -12,12 +13,12 @@ class Groups {
|
|
|
12
13
|
this.zbController = zbController;
|
|
13
14
|
this.stController = stController;
|
|
14
15
|
this.adapter.getStateAsync('info.groups')
|
|
15
|
-
.then(groupsState => {
|
|
16
|
+
.then((groupsState) => {
|
|
16
17
|
const groups = (groupsState && groupsState.val) ? JSON.parse(groupsState.val) : {};
|
|
17
18
|
for (const gid in groups) {
|
|
18
19
|
stController.storeDeviceName(`group_${gid}`, groups[gid]);
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
+
// this.Adapter.deleteState('info.groups');
|
|
21
22
|
this.syncGroups();
|
|
22
23
|
});
|
|
23
24
|
}
|
|
@@ -76,16 +77,15 @@ class Groups {
|
|
|
76
77
|
for (const member of groupmembers) {
|
|
77
78
|
const nwk = member.deviceNetworkAddress;
|
|
78
79
|
const device = this.zbController.getDeviceByNetworkAddress(nwk);
|
|
79
|
-
if (device && device.ieeeAddr) {
|
|
80
|
-
members.push({device: device.ieeeAddr});
|
|
81
|
-
}
|
|
80
|
+
if (device && device.ieeeAddr) members.push( { device:device.ieeeAddr } );
|
|
82
81
|
}
|
|
83
|
-
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
84
|
return undefined;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
} catch (error) {
|
|
88
|
-
if (error) this.error(
|
|
88
|
+
if (error) this.error('getGroupMembersFromController: error is ' + JSON.stringify(error) + ' ' + JSON.stringify(new Error().stack));
|
|
89
89
|
else this.error('unidentifed error in getGroupMembersFromController');
|
|
90
90
|
}
|
|
91
91
|
return members;
|
|
@@ -94,10 +94,10 @@ class Groups {
|
|
|
94
94
|
async getGroups(obj) {
|
|
95
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();
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
// const groups = (groupsState && groupsState.val) ? JSON.parse(groupsState.val) : {};
|
|
101
101
|
|
|
102
102
|
const groups = {};
|
|
103
103
|
if (typeof herdsmanGroups === 'object') {
|
|
@@ -108,21 +108,25 @@ class Groups {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
this.debug(
|
|
111
|
+
this.debug('getGroups result: ' + JSON.stringify(groups));
|
|
112
112
|
response.groups = groups;
|
|
113
|
-
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
114
115
|
response.error = `getGroups: caught error: ${error}`;
|
|
115
116
|
this.error(`getGroups: caught error: ${error}`);
|
|
116
|
-
}
|
|
117
|
-
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
if (obj)
|
|
120
|
+
this.adapter.sendTo(obj.from, obj.command, response, obj.callback);
|
|
121
|
+
|
|
118
122
|
}
|
|
119
123
|
return response.groups;
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
async updateGroupMembership(from, command, message, callback) {
|
|
123
127
|
try {
|
|
124
|
-
const groups = message && message.groups ? message.groups : {};
|
|
125
|
-
const devId = message && message.id ? message.id : undefined;
|
|
128
|
+
const groups = (message && message.groups ? message.groups : {});
|
|
129
|
+
const devId = (message && message.id ? message.id : undefined);
|
|
126
130
|
if (devId === undefined) {
|
|
127
131
|
this.adapter.sendTo(from, command, {error: 'No device specified'}, callback);
|
|
128
132
|
}
|
|
@@ -132,7 +136,7 @@ class Groups {
|
|
|
132
136
|
// this.adapter.setState(id, JSON.stringify(groups), true);
|
|
133
137
|
|
|
134
138
|
//const current = await this.zbController.getGroupMembersFromController(sysid);
|
|
135
|
-
const errors = []
|
|
139
|
+
const errors = []
|
|
136
140
|
for (const epid in groups) {
|
|
137
141
|
for (const gpid of groups[epid]) {
|
|
138
142
|
const gpidn = parseInt(gpid);
|
|
@@ -140,17 +144,18 @@ class Groups {
|
|
|
140
144
|
let response = await this.zbController.removeDevFromGroup(sysid,(-gpidn), epid);
|
|
141
145
|
if (response && response.error) {
|
|
142
146
|
errors.push(response.error);
|
|
143
|
-
this.error(
|
|
147
|
+
this.error("remove dev from group Error: "+ JSON.stringify(response.error));
|
|
144
148
|
}
|
|
145
|
-
}
|
|
149
|
+
}
|
|
150
|
+
else if (gpidn > 0){
|
|
146
151
|
let response = await this.zbController.addDevToGroup(sysid,(gpidn), epid);
|
|
147
152
|
if (response && response.error) {
|
|
148
153
|
errors.push(response.error);
|
|
149
|
-
this.error(
|
|
154
|
+
this.error("add dev to group Error: "+ JSON.stringify(response.error));
|
|
150
155
|
}
|
|
151
|
-
|
|
152
|
-
this.warn('illegal group id 0');
|
|
156
|
+
|
|
153
157
|
}
|
|
158
|
+
else this.warn('illegal group id 0');
|
|
154
159
|
}
|
|
155
160
|
}
|
|
156
161
|
} catch (e) {
|
|
@@ -169,13 +174,11 @@ class Groups {
|
|
|
169
174
|
};
|
|
170
175
|
for (const member of members) {
|
|
171
176
|
const entity = await this.zbController.resolveEntity(member.device);
|
|
172
|
-
if (!entity)
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
177
|
+
if (!entity) return false;
|
|
175
178
|
this.debug(`entity: ${JSON.stringify(entity)}`);
|
|
176
179
|
const mappedModel = entity.mapped;
|
|
177
|
-
this.debug(
|
|
178
|
-
const converter = mappedModel.toZigbee.find(c => c && (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id)));
|
|
180
|
+
this.debug('Mapped Model: ' + JSON.stringify(mappedModel));
|
|
181
|
+
const converter = mappedModel.toZigbee.find((c) => c && (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id)));
|
|
179
182
|
if (!converter) {
|
|
180
183
|
result.unsupported.push(member.device);
|
|
181
184
|
continue;
|
|
@@ -196,12 +199,12 @@ class Groups {
|
|
|
196
199
|
throw error;
|
|
197
200
|
}
|
|
198
201
|
if (result.unread.length>0) {
|
|
199
|
-
this.warn(
|
|
202
|
+
this.warn('unread ' + stateDesc.id + ' change for group members ' + JSON.stringify(result.unread));
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
205
|
|
|
203
206
|
async deleteGroup(from, command, message) {
|
|
204
|
-
|
|
207
|
+
/*
|
|
205
208
|
const members = await this.getGroupMembersFromController(parseInt(message));
|
|
206
209
|
if (members && members.length) {
|
|
207
210
|
for (const member of members) {
|
|
@@ -224,26 +227,27 @@ class Groups {
|
|
|
224
227
|
const objGroups = (groupsEntry && groupsEntry.val ? JSON.parse(groupsEntry.val) : {});
|
|
225
228
|
delete objGroups[message.toString()];
|
|
226
229
|
await this.adapter.setStateAsync('info.groups', JSON.stringify(objGroups), true);
|
|
227
|
-
|
|
230
|
+
*/
|
|
228
231
|
await this.zbController.removeGroupById(message);
|
|
229
232
|
await this.stController.deleteDeviceStatesAsync(`group_${parseInt(message)}`);
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
async renameGroup(from, command, message) {
|
|
233
|
-
|
|
234
|
-
|
|
236
|
+
|
|
237
|
+
// const groupsEntry = await this.adapter.getStateAsync('info.groups');
|
|
238
|
+
// const objGroups = (groupsEntry && groupsEntry.val ? JSON.parse(groupsEntry.val) : {});
|
|
235
239
|
const name = message.name;
|
|
236
240
|
const id = `group_${message.id}`;
|
|
237
241
|
this.stController.storeDeviceName(id, name);
|
|
238
242
|
try {
|
|
239
|
-
|
|
240
|
-
} catch (e) {
|
|
241
|
-
if (e && e.hasOwnProperty('code')) {
|
|
242
|
-
this.warn(`renameGroup caught error ${JSON.stringify(e.code)}`);
|
|
243
|
-
}
|
|
243
|
+
await this.zbController.verifyGroupExists(message.id);
|
|
244
244
|
}
|
|
245
|
-
|
|
246
|
-
|
|
245
|
+
catch (e)
|
|
246
|
+
{
|
|
247
|
+
if (e && e.hasOwnProperty('code')) this.warn('renameGroup caught error ' + JSON.stringify(e.code));
|
|
248
|
+
}
|
|
249
|
+
// objGroups[message.id.toString()] = message.name;
|
|
250
|
+
// await this.adapter.setStateAsync('info.groups', JSON.stringify(objGroups), true);
|
|
247
251
|
|
|
248
252
|
const group = await this.adapter.getStateAsync(id);
|
|
249
253
|
if (!group) {
|
|
@@ -251,14 +255,12 @@ class Groups {
|
|
|
251
255
|
this.adapter.setObjectNotExists(id, {
|
|
252
256
|
type: 'device',
|
|
253
257
|
common: {name: name, type: 'group'},
|
|
254
|
-
native: {id}
|
|
258
|
+
native: {id: id}
|
|
255
259
|
}, () => {
|
|
256
|
-
this.adapter.extendObject(id, {common: {name, type: 'group'}});
|
|
260
|
+
this.adapter.extendObject(id , {common: {name: name, type: 'group'}});
|
|
257
261
|
// create writable states for groups from their devices
|
|
258
262
|
for (const stateInd in statesMapping.groupStates) {
|
|
259
|
-
if (!statesMapping.groupStates.hasOwnProperty(stateInd))
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
263
|
+
if (!statesMapping.groupStates.hasOwnProperty(stateInd)) continue;
|
|
262
264
|
const statedesc = statesMapping.groupStates[stateInd];
|
|
263
265
|
const common = {
|
|
264
266
|
name: statedesc.name,
|
|
@@ -277,15 +279,16 @@ class Groups {
|
|
|
277
279
|
}
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
|
|
280
283
|
async syncGroups() {
|
|
281
284
|
const groups = await this.getGroups();
|
|
282
285
|
const chain = [];
|
|
283
286
|
const usedGroupsIds = [];
|
|
284
287
|
for (const j in groups) {
|
|
285
288
|
if (groups.hasOwnProperty(j)) {
|
|
286
|
-
const id = `group_${j}
|
|
287
|
-
|
|
288
|
-
chain.push(new Promise(resolve => {
|
|
289
|
+
const id = `group_${j}`,
|
|
290
|
+
name = groups[j];
|
|
291
|
+
chain.push(new Promise((resolve) => {
|
|
289
292
|
this.adapter.setObjectNotExists(id, {
|
|
290
293
|
type: 'device',
|
|
291
294
|
common: {name: name, type: 'group'},
|
|
@@ -294,9 +297,7 @@ class Groups {
|
|
|
294
297
|
this.adapter.extendObject(id, {common: {type: 'group'}});
|
|
295
298
|
// create writable states for groups from their devices
|
|
296
299
|
for (const stateInd in statesMapping.groupStates) {
|
|
297
|
-
if (!statesMapping.groupStates.hasOwnProperty(stateInd))
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
+
if (!statesMapping.groupStates.hasOwnProperty(stateInd)) continue;
|
|
300
301
|
const statedesc = statesMapping.groupStates[stateInd];
|
|
301
302
|
const common = {
|
|
302
303
|
name: statedesc.name,
|
|
@@ -317,8 +318,8 @@ class Groups {
|
|
|
317
318
|
usedGroupsIds.push(parseInt(j));
|
|
318
319
|
}
|
|
319
320
|
}
|
|
320
|
-
chain.push(new Promise(resolve => {
|
|
321
|
-
// remove unused
|
|
321
|
+
chain.push(new Promise((resolve) => {
|
|
322
|
+
// remove unused adpter groups
|
|
322
323
|
this.adapter.getDevices((err, devices) => {
|
|
323
324
|
if (!err) {
|
|
324
325
|
devices.forEach((dev) => {
|
|
@@ -333,9 +334,9 @@ class Groups {
|
|
|
333
334
|
resolve();
|
|
334
335
|
});
|
|
335
336
|
}));
|
|
336
|
-
|
|
337
|
-
await Promise.all(chain);
|
|
337
|
+
Promise.all(chain);
|
|
338
338
|
}
|
|
339
|
+
|
|
339
340
|
}
|
|
340
341
|
|
|
341
342
|
module.exports = Groups;
|
package/lib/json.js
CHANGED
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
const hasProp = Object.prototype.hasOwnProperty;
|
|
4
4
|
|
|
5
5
|
function throwsMessage(err) {
|
|
6
|
-
return
|
|
6
|
+
return '[Throws: ' + (err ? err.message : '?') + ']';
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function safeGetValueFromPropertyOnObject(obj, property) {
|
|
10
10
|
if (hasProp.call(obj, property)) {
|
|
11
11
|
try {
|
|
12
12
|
return obj[property];
|
|
13
|
-
}
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
14
15
|
return throwsMessage(err);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
@@ -26,7 +27,7 @@ function ensureProperties(obj) {
|
|
|
26
27
|
return obj;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
if (seen.
|
|
30
|
+
if (seen.indexOf(obj) !== -1) {
|
|
30
31
|
return '[Circular]';
|
|
31
32
|
}
|
|
32
33
|
seen.push(obj);
|
package/lib/networkmap.js
CHANGED
|
@@ -46,8 +46,8 @@ class NetworkMap {
|
|
|
46
46
|
|
|
47
47
|
getMap(from, command, callback) {
|
|
48
48
|
if (this.zbController) {
|
|
49
|
-
this.zbController.getMap(networkmap => {
|
|
50
|
-
this.adapter.log.debug(
|
|
49
|
+
this.zbController.getMap((networkmap) => {
|
|
50
|
+
this.adapter.log.debug('getMap result: ' + JSON.stringify(networkmap));
|
|
51
51
|
this.adapter.sendTo(from, command, networkmap, callback);
|
|
52
52
|
});
|
|
53
53
|
}
|
package/lib/ota.js
CHANGED
|
@@ -65,24 +65,16 @@ class Ota {
|
|
|
65
65
|
// do not attempt update for a device which has been deactivated or is unavailable
|
|
66
66
|
const stateObj = await this.adapter.getObjectAsync(obj.message.devId);
|
|
67
67
|
if (stateObj && stateObj.common && stateObj.common.deactivated) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
device: getZbId(obj.message.devId),
|
|
72
|
-
msg: 'Device is deactivated'
|
|
73
|
-
}, obj.callback);
|
|
74
|
-
return;
|
|
68
|
+
this.warn(`Device ${obj.message.devId} is deactivated, skipping...`);
|
|
69
|
+
this.adapter.sendTo(obj.from, obj.command, {status: 'fail', device: getZbId(obj.message.devId), msg: 'Device is deactivated'}, obj.callback);
|
|
70
|
+
return;
|
|
75
71
|
}
|
|
76
|
-
const availablestate = await this.adapter.getStateAsync(
|
|
77
|
-
const lqi = await this.adapter.getStateAsync(
|
|
72
|
+
const availablestate = await this.adapter.getStateAsync(obj.message.devId.replace(this.namespace + '.', '') + '.available');
|
|
73
|
+
const lqi = await this.adapter.getStateAsync(obj.message.devId.replace(this.namespace + '.', '') + '.link_quality');
|
|
78
74
|
if ((availablestate && (!availablestate.val)) || (lqi && lqi.val < 1)) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
device: getZbId(obj.message.devId),
|
|
83
|
-
msg: 'Device is marked unavailable'
|
|
84
|
-
}, obj.callback);
|
|
85
|
-
return;
|
|
75
|
+
this.warn(`Device ${obj.message.devId} is marked unavailable, skipping...`);
|
|
76
|
+
this.adapter.sendTo(obj.from, obj.command, {status: 'fail', device: getZbId(obj.message.devId), msg: 'Device is marked unavailable'}, obj.callback);
|
|
77
|
+
return;
|
|
86
78
|
}
|
|
87
79
|
this.inProgress.add(device.device.ieeeAddr);
|
|
88
80
|
const result = {status: 'unknown', device: device ? device.name : null};
|
|
@@ -121,14 +113,14 @@ class Ota {
|
|
|
121
113
|
// do not attempt update for a device which has been deactivated or is unavailable
|
|
122
114
|
const stateObj = await this.adapter.getObjectAsync(obj.message.devId);
|
|
123
115
|
if (stateObj && stateObj.common && stateObj.common.deactivated) {
|
|
124
|
-
|
|
125
|
-
|
|
116
|
+
this.warn(`Device ${obj.message.devId} is deactivated, skipping...`);
|
|
117
|
+
return;
|
|
126
118
|
}
|
|
127
|
-
const availablestate = await this.adapter.getStateAsync(
|
|
128
|
-
const lqi = await this.adapter.getStateAsync(
|
|
119
|
+
const availablestate = await this.adapter.getStateAsync(obj.message.devId.replace(this.namespace + '.', '') + '.available');
|
|
120
|
+
const lqi = await this.adapter.getStateAsync(obj.message.devId.replace(this.namespace + '.', '') + '.link_quality');
|
|
129
121
|
if ((availablestate && (!availablestate.val)) || (lqi && lqi.val < 1)) {
|
|
130
|
-
|
|
131
|
-
|
|
122
|
+
this.warn(`Device ${obj.message.devId} is marked unavailable, skipping...`);
|
|
123
|
+
return;
|
|
132
124
|
}
|
|
133
125
|
this.inProgress.add(device.device.ieeeAddr);
|
|
134
126
|
const result = {status: 'unknown', device: device ? device.name : null};
|
|
@@ -148,7 +140,7 @@ class Ota {
|
|
|
148
140
|
const to = await this.readSoftwareBuildIDAndDateCode(device.device, true);
|
|
149
141
|
const [fromS, toS] = [JSON.stringify(from_), JSON.stringify(to)];
|
|
150
142
|
result.status = 'success';
|
|
151
|
-
result.msg = `Finished update of '${device.name}'
|
|
143
|
+
result.msg = `Finished update of '${device.name}'` + (to ? `, from '${fromS}' to '${toS}'` : ``);
|
|
152
144
|
this.info(result.msg);
|
|
153
145
|
this.adapter.sendTo(obj.from, obj.command, result, obj.callback);
|
|
154
146
|
} catch (error) {
|
package/lib/rgb.js
CHANGED
|
@@ -61,19 +61,23 @@ function cie_to_rgb(x, y, brightness) {
|
|
|
61
61
|
|
|
62
62
|
//Convert to RGB using Wide RGB D65 conversion
|
|
63
63
|
let red = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
|
64
|
-
let green
|
|
64
|
+
let green = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
|
|
65
65
|
let blue = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
|
|
66
66
|
|
|
67
67
|
//If red, green or blue is larger than 1.0 set it back to the maximum of 1.0
|
|
68
68
|
if (red > blue && red > green && red > 1.0) {
|
|
69
|
+
|
|
69
70
|
green = green / red;
|
|
70
71
|
blue = blue / red;
|
|
71
72
|
red = 1.0;
|
|
72
|
-
}
|
|
73
|
+
}
|
|
74
|
+
else if (green > blue && green > red && green > 1.0) {
|
|
75
|
+
|
|
73
76
|
red = red / green;
|
|
74
77
|
blue = blue / green;
|
|
75
78
|
green = 1.0;
|
|
76
|
-
}
|
|
79
|
+
}
|
|
80
|
+
else if (blue > red && blue > green && blue > 1.0) {
|
|
77
81
|
|
|
78
82
|
red = red / blue;
|
|
79
83
|
green = green / blue;
|
|
@@ -85,6 +89,7 @@ function cie_to_rgb(x, y, brightness) {
|
|
|
85
89
|
green = green <= 0.0031308 ? 12.92 * green : (1.0 + 0.055) * Math.pow(green, (1.0 / 2.4)) - 0.055;
|
|
86
90
|
blue = blue <= 0.0031308 ? 12.92 * blue : (1.0 + 0.055) * Math.pow(blue, (1.0 / 2.4)) - 0.055;
|
|
87
91
|
|
|
92
|
+
|
|
88
93
|
//Convert normalized decimal to decimal
|
|
89
94
|
red = Math.round(red * 255);
|
|
90
95
|
green = Math.round(green * 255);
|
|
@@ -115,18 +120,18 @@ function cie_to_rgb(x, y, brightness) {
|
|
|
115
120
|
*/
|
|
116
121
|
function rgb_to_cie(red, green, blue) {
|
|
117
122
|
// Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
|
|
118
|
-
red
|
|
119
|
-
green
|
|
120
|
-
blue
|
|
123
|
+
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
|
124
|
+
green = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
|
|
125
|
+
blue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
|
|
121
126
|
|
|
122
127
|
// RGB values to XYZ using the Wide RGB D65 conversion formula
|
|
123
|
-
const X
|
|
124
|
-
const Y
|
|
125
|
-
const Z
|
|
128
|
+
const X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
|
|
129
|
+
const Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
|
|
130
|
+
const Z = red * 0.000088 + green * 0.072310 + blue * 0.986039;
|
|
126
131
|
|
|
127
132
|
// Calculate the xy values from the XYZ values
|
|
128
|
-
let x
|
|
129
|
-
let y
|
|
133
|
+
let x = (X / (X + Y + Z)).toFixed(4);
|
|
134
|
+
let y = (Y / (X + Y + Z)).toFixed(4);
|
|
130
135
|
|
|
131
136
|
if (isNaN(x)) {
|
|
132
137
|
x = 0;
|
|
@@ -147,9 +152,7 @@ function hsvToRGB(h, s, v) {
|
|
|
147
152
|
|
|
148
153
|
let r; let g; let b;
|
|
149
154
|
if (arguments.length === 1) {
|
|
150
|
-
s = h.s;
|
|
151
|
-
v = h.v;
|
|
152
|
-
h = h.h;
|
|
155
|
+
s = h.s, v = h.v, h = h.h;
|
|
153
156
|
}
|
|
154
157
|
const i = Math.floor(h * 6);
|
|
155
158
|
const f = h * 6 - i;
|
|
@@ -173,9 +176,7 @@ function hsvToRGB(h, s, v) {
|
|
|
173
176
|
|
|
174
177
|
function rgbToHSV(r, g, b, numeric) {
|
|
175
178
|
if (arguments.length === 1) {
|
|
176
|
-
g = r.g;
|
|
177
|
-
b = r.b;
|
|
178
|
-
r = r.r;
|
|
179
|
+
g = r.g, b = r.b, r = r.r;
|
|
179
180
|
}
|
|
180
181
|
const max = Math.max(r, g, b); const min = Math.min(r, g, b);
|
|
181
182
|
const d = max - min;
|
|
@@ -189,13 +190,11 @@ function rgbToHSV(r, g, b, numeric) {
|
|
|
189
190
|
case g: h = (b - r) + d * 2; h /= 6 * d; break;
|
|
190
191
|
case b: h = (r - g) + d * 4; h /= 6 * d; break;
|
|
191
192
|
}
|
|
192
|
-
if (numeric) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
};
|
|
198
|
-
}
|
|
193
|
+
if (numeric) return {
|
|
194
|
+
h: Math.round(h*360),
|
|
195
|
+
s: Math.round(s*100),
|
|
196
|
+
v: Math.round(v*100),
|
|
197
|
+
};
|
|
199
198
|
return {
|
|
200
199
|
h: (h * 360).toFixed(3),
|
|
201
200
|
s: (s * 100).toFixed(3),
|
|
@@ -205,17 +204,20 @@ function rgbToHSV(r, g, b, numeric) {
|
|
|
205
204
|
function colorArrayFromString(value) {
|
|
206
205
|
if (typeof(value) === 'string') {
|
|
207
206
|
const rv = [];
|
|
208
|
-
value.split(',').forEach(element =>
|
|
209
|
-
rv.push(colors.ParseColor(element))
|
|
207
|
+
value.split(',').forEach(element => {
|
|
208
|
+
rv.push(colors.ParseColor(element));
|
|
209
|
+
});
|
|
210
210
|
return rv;
|
|
211
211
|
}
|
|
212
|
-
return [{r:
|
|
212
|
+
return [{r:0,g:128,b:255}];
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
function colorStringFromRGBArray(payload)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
215
|
+
function colorStringFromRGBArray(payload)
|
|
216
|
+
{
|
|
217
|
+
let rv = []
|
|
218
|
+
payload.forEach(element => {
|
|
219
|
+
rv.push(rgb_to_rgbstring(element));
|
|
220
|
+
});
|
|
219
221
|
return rv.toString();
|
|
220
222
|
}
|
|
221
223
|
|
|
@@ -226,26 +228,21 @@ function hsv_to_cie(h,s,v){
|
|
|
226
228
|
|
|
227
229
|
function rgb_to_rgbstring(element) {
|
|
228
230
|
let col = '#';
|
|
229
|
-
if (element && element.hasOwnProperty(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
if (element && element.hasOwnProperty('b')) {
|
|
240
|
-
col = col + element.b.toString(16).padStart(2, '0');
|
|
241
|
-
} else {
|
|
242
|
-
col = col + '00';
|
|
243
|
-
}
|
|
231
|
+
if (element && element.hasOwnProperty("r"))
|
|
232
|
+
col = col + element.r.toString(16).padStart(2, '0');
|
|
233
|
+
else col = col + '00';
|
|
234
|
+
if (element && element.hasOwnProperty("g"))
|
|
235
|
+
col = col + element.g.toString(16).padStart(2, '0');
|
|
236
|
+
else col = col + '00';
|
|
237
|
+
if (element && element.hasOwnProperty("b"))
|
|
238
|
+
col = col + element.b.toString(16).padStart(2, '0');
|
|
239
|
+
else col = col + '00';
|
|
244
240
|
return col;
|
|
245
241
|
}
|
|
246
242
|
|
|
243
|
+
|
|
247
244
|
function hsvToRGBString(h,s,v) {
|
|
248
|
-
return rgb_to_rgbstring(hsvToRGB(h,s,v))
|
|
245
|
+
return rgb_to_rgbstring(hsvToRGB(h,s,v))
|
|
249
246
|
}
|
|
250
247
|
|
|
251
248
|
exports.hsv_to_cie = hsv_to_cie;
|
package/lib/seriallist.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const serialPortUtils = require('zigbee-herdsman/dist/adapter/serialPortUtils').default;
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
|
|
6
6
|
class SerialList {
|
|
7
7
|
constructor(adapter) {
|
|
8
8
|
this.adapter = adapter;
|
|
9
|
-
this.adapter.on('message',
|
|
9
|
+
this.adapter.on('message', this.onMessage.bind(this));
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* @param {ioBroker.Message} obj
|
|
@@ -16,22 +16,17 @@ class SerialList {
|
|
|
16
16
|
switch (obj.command) {
|
|
17
17
|
case 'listUart':
|
|
18
18
|
if (obj.callback) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
} else {
|
|
32
|
-
this.adapter.log.warn('Module serialport is not available');
|
|
33
|
-
this.adapter.sendTo(obj.from, obj.command, [{label: 'Not available', value: ''}], obj.callback);
|
|
34
|
-
}
|
|
19
|
+
this.listSerial()
|
|
20
|
+
.then((ports) => {
|
|
21
|
+
this.adapter.log.debug('List of ports: ' + JSON.stringify(ports));
|
|
22
|
+
this.adapter.sendTo(obj.from, obj.command, ports.map(item => ({
|
|
23
|
+
label: item.friendlyName || item.pnpId || item.manufacturer,
|
|
24
|
+
comName: item.path
|
|
25
|
+
})), obj.callback);
|
|
26
|
+
}).catch((err) => {
|
|
27
|
+
this.adapter.log.error(`List of ports error: ${err}`);
|
|
28
|
+
this.adapter.sendTo(obj.from, obj.command, [], obj.callback);
|
|
29
|
+
});
|
|
35
30
|
}
|
|
36
31
|
break;
|
|
37
32
|
}
|
|
@@ -39,9 +34,9 @@ class SerialList {
|
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
listSerial() {
|
|
42
|
-
return serialPortUtils.find([{}])
|
|
43
|
-
.
|
|
44
|
-
|
|
37
|
+
return serialPortUtils.find([{}]).then((ports) => {
|
|
38
|
+
return ports.map((port) => {return {comName: port};});
|
|
39
|
+
});
|
|
45
40
|
}
|
|
46
41
|
}
|
|
47
42
|
|