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