iobroker.zigbee2mqtt 1.0.0 → 2.1.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 +20 -1
- package/admin/i18n/de/translations.json +20 -8
- package/admin/i18n/en/translations.json +15 -3
- package/admin/i18n/es/translations.json +15 -3
- package/admin/i18n/fr/translations.json +15 -3
- package/admin/i18n/it/translations.json +15 -3
- package/admin/i18n/nl/translations.json +15 -3
- package/admin/i18n/pl/translations.json +15 -3
- package/admin/i18n/pt/translations.json +15 -3
- package/admin/i18n/ru/translations.json +15 -3
- package/admin/i18n/zh-cn/translations.json +15 -3
- package/admin/jsonConfig.json +90 -17
- package/io-package.json +34 -5
- package/lib/check.js +1 -2
- package/lib/colors.js +5 -3
- package/lib/deviceController.js +65 -13
- package/lib/exposes.js +56 -42
- package/lib/messages.js +31 -10
- package/lib/mqttServerController.js +42 -0
- package/lib/rgb.js +42 -17
- package/lib/states.js +39 -19
- package/lib/statesController.js +29 -18
- package/lib/utils.js +12 -19
- package/lib/websocketController.js +84 -0
- package/lib/z2mController.js +3 -3
- package/main.js +84 -43
- package/package.json +3 -3
package/lib/deviceController.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const states = require('./states').states;
|
|
2
2
|
const defineDeviceFromExposes = require('./exposes').defineDeviceFromExposes;
|
|
3
3
|
const utils = require('./utils');
|
|
4
|
+
const colors = require('./colors.js');
|
|
5
|
+
const rgb = require('./rgb.js');
|
|
4
6
|
const createCache = {};
|
|
5
7
|
|
|
6
8
|
class DeviceController {
|
|
7
|
-
constructor(adapter, deviceCache, groupCache,
|
|
9
|
+
constructor(adapter, deviceCache, groupCache, config) {
|
|
8
10
|
this.adapter = adapter;
|
|
9
11
|
this.groupCache = groupCache;
|
|
10
12
|
this.deviceCache = deviceCache;
|
|
11
|
-
this.
|
|
13
|
+
this.config = config;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
async createDeviceDefinitions(exposes) {
|
|
@@ -22,13 +24,15 @@ class DeviceController {
|
|
|
22
24
|
scenes = scenes.concat(expose.endpoints[key].scenes);
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
|
-
|
|
27
|
+
// if the device is already present in the cache, remove it
|
|
28
|
+
this.removeDeviceByIeee(this.deviceCache, expose.ieee_address);
|
|
29
|
+
defineDeviceFromExposes(this.deviceCache, expose.friendly_name, expose.ieee_address, expose.definition, expose.power_source, scenes, this.config);
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
|
|
31
|
-
async defineGroupDevice(
|
|
35
|
+
async defineGroupDevice(groupID, ieee_address, scenes) {
|
|
32
36
|
const newDevice = {
|
|
33
37
|
id: groupID,
|
|
34
38
|
ieee_address: ieee_address,
|
|
@@ -36,12 +40,46 @@ class DeviceController {
|
|
|
36
40
|
states: [
|
|
37
41
|
states.state,
|
|
38
42
|
states.brightness,
|
|
39
|
-
states.color,
|
|
43
|
+
//states.color,
|
|
40
44
|
states.brightness_move,
|
|
41
45
|
states.colortemp_move,
|
|
42
46
|
],
|
|
43
47
|
};
|
|
44
48
|
|
|
49
|
+
const color = {
|
|
50
|
+
id: 'color',
|
|
51
|
+
prop: 'color',
|
|
52
|
+
name: 'Color',
|
|
53
|
+
icon: undefined,
|
|
54
|
+
role: 'level.color.rgb',
|
|
55
|
+
write: true,
|
|
56
|
+
read: true,
|
|
57
|
+
type: 'string',
|
|
58
|
+
setter: (value) => {
|
|
59
|
+
let xy = [0, 0];
|
|
60
|
+
const rgbcolor = colors.ParseColor(value);
|
|
61
|
+
xy = rgb.rgb_to_cie(rgbcolor.r, rgbcolor.g, rgbcolor.b);
|
|
62
|
+
return {
|
|
63
|
+
x: xy[0],
|
|
64
|
+
y: xy[1]
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
getter: payload => {
|
|
68
|
+
if (payload.color_mode != 'xy' && this.config.colorTempSyncColor == false) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
if (payload.color && payload.color.x && payload.color.y) {
|
|
72
|
+
const colorval = rgb.cie_to_rgb(payload.color.x, payload.color.y);
|
|
73
|
+
return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
|
|
74
|
+
} else {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
newDevice.states.push(color);
|
|
82
|
+
|
|
45
83
|
const colortemp = {
|
|
46
84
|
id: 'colortemp',
|
|
47
85
|
prop: 'color_temp',
|
|
@@ -51,15 +89,19 @@ class DeviceController {
|
|
|
51
89
|
write: true,
|
|
52
90
|
read: true,
|
|
53
91
|
type: 'number',
|
|
54
|
-
|
|
92
|
+
min: this.config.useKelvin == true ? utils.miredKelvinConversion(500) : 150,
|
|
93
|
+
max: this.config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
94
|
+
unit: this.config.useKelvin == true ? 'K' : 'mired',
|
|
55
95
|
setter: (value) => {
|
|
56
96
|
return utils.toMired(value);
|
|
57
97
|
},
|
|
58
98
|
getter: (payload) => {
|
|
59
|
-
if (
|
|
60
|
-
return
|
|
99
|
+
if (payload.color_mode != 'color_temp') {
|
|
100
|
+
return undefined;
|
|
61
101
|
}
|
|
62
|
-
|
|
102
|
+
if (this.config.useKelvin == true) {
|
|
103
|
+
return utils.miredKelvinConversion(payload.color_temp);
|
|
104
|
+
} else {
|
|
63
105
|
return payload.color_temp;
|
|
64
106
|
}
|
|
65
107
|
},
|
|
@@ -86,13 +128,14 @@ class DeviceController {
|
|
|
86
128
|
}
|
|
87
129
|
|
|
88
130
|
// if the device is already present in the cache, remove it
|
|
89
|
-
|
|
90
|
-
|
|
131
|
+
this.removeDeviceByIeee(this.groupCache, ieee_address);
|
|
132
|
+
this.groupCache.push(newDevice);
|
|
91
133
|
}
|
|
134
|
+
|
|
92
135
|
async createGroupDefinitions(exposes) {
|
|
93
136
|
utils.clearArray(this.groupCache);
|
|
94
137
|
for (const expose of exposes) {
|
|
95
|
-
await this.defineGroupDevice(
|
|
138
|
+
await this.defineGroupDevice(expose.friendly_name, `group_${expose.id}`, expose.scenes);
|
|
96
139
|
}
|
|
97
140
|
}
|
|
98
141
|
|
|
@@ -147,7 +190,9 @@ class DeviceController {
|
|
|
147
190
|
|
|
148
191
|
async renameDeviceInCache(messageObj) {
|
|
149
192
|
const renamedDevice = this.groupCache.concat(this.deviceCache).find(x => x.id == messageObj.payload.data.from);
|
|
150
|
-
renamedDevice
|
|
193
|
+
if (renamedDevice) {
|
|
194
|
+
renamedDevice.id = messageObj.payload.data.to;
|
|
195
|
+
}
|
|
151
196
|
}
|
|
152
197
|
|
|
153
198
|
async processRemoveEvent(messageObj) {
|
|
@@ -157,6 +202,13 @@ class DeviceController {
|
|
|
157
202
|
}
|
|
158
203
|
}
|
|
159
204
|
|
|
205
|
+
removeDeviceByIeee(devices, ieee_address) {
|
|
206
|
+
const idx = devices.findIndex(x => x.ieee_address == ieee_address);
|
|
207
|
+
if (idx > -1) {
|
|
208
|
+
devices.splice(idx, 1);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
160
212
|
async copyAndCleanStateObj(state) {
|
|
161
213
|
const iobState = { ...state };
|
|
162
214
|
const blacklistedKeys = [
|
package/lib/exposes.js
CHANGED
|
@@ -38,8 +38,7 @@ function genState(expose, role, name, desc) {
|
|
|
38
38
|
|
|
39
39
|
if (readable) {
|
|
40
40
|
state.getter = (payload) => (payload[propName] === (expose.value_on || 'ON'));
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
41
|
+
} else {
|
|
43
42
|
state.getter = (_payload) => (undefined);
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -121,7 +120,7 @@ function genState(expose, role, name, desc) {
|
|
|
121
120
|
return state;
|
|
122
121
|
}
|
|
123
122
|
|
|
124
|
-
function createFromExposes(deviceID, ieee_address, definitions, power_source, scenes,
|
|
123
|
+
function createFromExposes(deviceID, ieee_address, definitions, power_source, scenes, config) {
|
|
125
124
|
const states = [];
|
|
126
125
|
// make the different (set and get) part of state is updatable if different exposes is used for get and set
|
|
127
126
|
// as example:
|
|
@@ -161,8 +160,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
161
160
|
}
|
|
162
161
|
|
|
163
162
|
return states.push(state);
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
163
|
+
} else {
|
|
166
164
|
|
|
167
165
|
if ((state.readable) && (!states[stateExists].readable)) {
|
|
168
166
|
states[stateExists].read = state.read;
|
|
@@ -192,8 +190,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
192
190
|
}
|
|
193
191
|
delete states[stateExists].prop;
|
|
194
192
|
}
|
|
195
|
-
}
|
|
196
|
-
else if (state.hasOwnProperty('prop')) {
|
|
193
|
+
} else if (state.hasOwnProperty('prop')) {
|
|
197
194
|
states[stateExists].prop = state.prop;
|
|
198
195
|
}
|
|
199
196
|
states[stateExists].readable = true;
|
|
@@ -220,16 +217,14 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
220
217
|
// or remove it
|
|
221
218
|
if (((!state.hasOwnProperty('isOption')) || (state.isOptions === false)) && (states[stateExists].hasOwnProperty('isOption'))) {
|
|
222
219
|
delete states[stateExists].isOption;
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
220
|
+
} else {
|
|
225
221
|
states[stateExists].isOption = state.isOption;
|
|
226
222
|
}
|
|
227
223
|
|
|
228
224
|
// use new `setattr` or `prop` as `setattr`
|
|
229
225
|
if (state.hasOwnProperty('setattr')) {
|
|
230
226
|
states[stateExists].setattr = state.setattr;
|
|
231
|
-
}
|
|
232
|
-
else if (state.hasOwnProperty('prop')) {
|
|
227
|
+
} else if (state.hasOwnProperty('prop')) {
|
|
233
228
|
states[stateExists].setattr = state.prop;
|
|
234
229
|
}
|
|
235
230
|
|
|
@@ -322,22 +317,24 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
322
317
|
write: true,
|
|
323
318
|
read: true,
|
|
324
319
|
type: 'number',
|
|
325
|
-
min:
|
|
326
|
-
max:
|
|
327
|
-
unit: useKelvin == true ? 'K' : 'mired',
|
|
320
|
+
min: config.useKelvin == true ? utils.miredKelvinConversion(prop.value_max) : prop.value_min,
|
|
321
|
+
max: config.useKelvin == true ? utils.miredKelvinConversion(prop.value_min) : prop.value_max,
|
|
322
|
+
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
328
323
|
setter: (value) => {
|
|
329
324
|
return utils.toMired(value);
|
|
330
325
|
},
|
|
331
|
-
setterOpt: (_value, options) => {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
},
|
|
326
|
+
// setterOpt: (_value, options) => {
|
|
327
|
+
// const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
328
|
+
// const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
329
|
+
// return { ...options, transition: transitionTime };
|
|
330
|
+
// },
|
|
336
331
|
getter: (payload) => {
|
|
337
|
-
if (
|
|
338
|
-
return
|
|
332
|
+
if (payload.color_mode != 'color_temp') {
|
|
333
|
+
return undefined;
|
|
339
334
|
}
|
|
340
|
-
|
|
335
|
+
if (config.useKelvin == true) {
|
|
336
|
+
return utils.miredKelvinConversion(payload.color_temp);
|
|
337
|
+
} else {
|
|
341
338
|
return payload.color_temp;
|
|
342
339
|
}
|
|
343
340
|
},
|
|
@@ -370,12 +367,10 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
370
367
|
};
|
|
371
368
|
|
|
372
369
|
},
|
|
373
|
-
setterOpt: (_value, options) => {
|
|
374
|
-
const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
375
|
-
const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
376
|
-
return { ...options, transition: transitionTime };
|
|
377
|
-
},
|
|
378
370
|
getter: payload => {
|
|
371
|
+
if (payload.color_mode != 'xy' && config.colorTempSyncColor == false) {
|
|
372
|
+
return undefined;
|
|
373
|
+
}
|
|
379
374
|
if (payload.color && payload.color.hasOwnProperty('x') && payload.color.hasOwnProperty('y')) {
|
|
380
375
|
const colorval = rgb.cie_to_rgb(payload.color.x, payload.color.y);
|
|
381
376
|
return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
|
|
@@ -578,6 +573,10 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
578
573
|
state = statesDefs.temperature;
|
|
579
574
|
break;
|
|
580
575
|
|
|
576
|
+
case 'device_temperature':
|
|
577
|
+
state = statesDefs.device_temperature;
|
|
578
|
+
break;
|
|
579
|
+
|
|
581
580
|
case 'humidity':
|
|
582
581
|
state = statesDefs.humidity;
|
|
583
582
|
break;
|
|
@@ -598,6 +597,24 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
598
597
|
state = statesDefs.load_power;
|
|
599
598
|
break;
|
|
600
599
|
|
|
600
|
+
case 'current':
|
|
601
|
+
state = statesDefs.load_current;
|
|
602
|
+
break;
|
|
603
|
+
|
|
604
|
+
case 'voltage':
|
|
605
|
+
state = statesDefs.voltage;
|
|
606
|
+
if (power_source == 'Battery') {
|
|
607
|
+
state = statesDefs.battery_voltage;
|
|
608
|
+
}
|
|
609
|
+
if (expose.unit == 'mV') {
|
|
610
|
+
state.getter = payload => payload.voltage / 1000;
|
|
611
|
+
}
|
|
612
|
+
break;
|
|
613
|
+
|
|
614
|
+
case 'energy':
|
|
615
|
+
state = statesDefs.energy;
|
|
616
|
+
break;
|
|
617
|
+
|
|
601
618
|
default:
|
|
602
619
|
state = genState(expose);
|
|
603
620
|
break;
|
|
@@ -761,13 +778,14 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
761
778
|
case 'running_mode':
|
|
762
779
|
pushToStates(statesDefs.climate_running_mode, prop.access);
|
|
763
780
|
break;
|
|
764
|
-
default:
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
781
|
+
default:
|
|
782
|
+
{
|
|
783
|
+
if (prop.name.includes('heating_setpoint')) {
|
|
784
|
+
pushToStates(genState(prop, 'level.temperature'), prop.access);
|
|
785
|
+
} else {
|
|
786
|
+
pushToStates(genState(prop), prop.access);
|
|
787
|
+
}
|
|
769
788
|
}
|
|
770
|
-
}
|
|
771
789
|
break;
|
|
772
790
|
}
|
|
773
791
|
}
|
|
@@ -800,13 +818,11 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
800
818
|
st.getter = payload => {
|
|
801
819
|
if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
|
|
802
820
|
return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined;
|
|
803
|
-
}
|
|
804
|
-
else {
|
|
821
|
+
} else {
|
|
805
822
|
return undefined;
|
|
806
823
|
}
|
|
807
824
|
};
|
|
808
|
-
}
|
|
809
|
-
else {
|
|
825
|
+
} else {
|
|
810
826
|
st.getter = _payload => { return undefined; };
|
|
811
827
|
}
|
|
812
828
|
pushToStates(st, prop.access);
|
|
@@ -850,15 +866,13 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
850
866
|
return newDevice;
|
|
851
867
|
}
|
|
852
868
|
|
|
853
|
-
function defineDeviceFromExposes(devices, deviceID, ieee_address, definitions, power_source, scenes,
|
|
854
|
-
// if the device is already present in the cache, remove it
|
|
855
|
-
utils.removeDeviceByIeee(devices, ieee_address);
|
|
869
|
+
function defineDeviceFromExposes(devices, deviceID, ieee_address, definitions, power_source, scenes, config) {
|
|
856
870
|
if (definitions.hasOwnProperty('exposes')) {
|
|
857
|
-
const newDevice = createFromExposes(deviceID, ieee_address, definitions, power_source, scenes,
|
|
871
|
+
const newDevice = createFromExposes(deviceID, ieee_address, definitions, power_source, scenes, config);
|
|
858
872
|
devices.push(newDevice);
|
|
859
873
|
}
|
|
860
874
|
}
|
|
861
875
|
|
|
862
876
|
module.exports = {
|
|
863
877
|
defineDeviceFromExposes: defineDeviceFromExposes,
|
|
864
|
-
};
|
|
878
|
+
};
|
package/lib/messages.js
CHANGED
|
@@ -1,18 +1,39 @@
|
|
|
1
1
|
async function adapterInfo(config, log) {
|
|
2
|
-
log.info(
|
|
3
|
-
log.info(
|
|
4
|
-
log.info(
|
|
5
|
-
log.info(
|
|
6
|
-
log.info(
|
|
2
|
+
log.info('================================= Adapter Config =================================');
|
|
3
|
+
log.info(`|| Zigbee2MQTT Frontend Scheme: ${config.webUIScheme}`);
|
|
4
|
+
log.info(`|| Zigbee2MQTT Frontend Server: ${config.webUIServer}`);
|
|
5
|
+
log.info(`|| Zigbee2MQTT Frontend Port: ${config.webUIPort}`);
|
|
6
|
+
log.info(`|| Zigbee2MQTT Connection Type: ${config.connectionType}`);
|
|
7
|
+
if (config.connectionType == 'ws') {
|
|
8
|
+
log.info(`|| Zigbee2MQTT Websocket Server: ${config.wsServerIP}`);
|
|
9
|
+
log.info(`|| Zigbee2MQTT Websocket Port: ${config.wsServerPort}`);
|
|
10
|
+
log.info(`|| Zigbee2MQTT Websocket Dummy MQTT-Server: ${config.dummyMqtt ? 'activated' : 'deactivated'}`);
|
|
11
|
+
if (config.dummyMqtt == true) {
|
|
12
|
+
log.info(`|| Zigbee2MQTT Dummy MQTT IP-Bind: ${config.mqttServerIPBind}`);
|
|
13
|
+
log.info(`|| Zigbee2MQTT Dummy MQTT Port: ${config.mqttServerPort}`);
|
|
14
|
+
}
|
|
15
|
+
} else if (config.connectionType == 'exmqtt') {
|
|
16
|
+
log.info(`|| Zigbee2MQTT Externanl MQTT Server: ${config.externalMqttServerIP}`);
|
|
17
|
+
log.info(`|| Zigbee2MQTT Externanl MQTT Port: ${config.externalMqttServerPort}`);
|
|
18
|
+
} else if (config.connectionType == 'intmqtt') {
|
|
19
|
+
log.info(`|| Zigbee2MQTT Internal MQTT IP-Bind: ${config.mqttServerIPBind}`);
|
|
20
|
+
log.info(`|| Zigbee2MQTT Internal MQTT Port: ${config.mqttServerPort}`);
|
|
21
|
+
}
|
|
22
|
+
log.info(`|| Zigbee2MQTT Debug Log: ${config.debugLogEnabled ? 'activated' : 'deactivated'}`);
|
|
23
|
+
log.info(`|| Proxy Zigbee2MQTT Logs to ioBroker Logs: ${config.proxyZ2MLogs ? 'activated' : 'deactivated'}`);
|
|
24
|
+
log.info(`|| Use Kelvin: ${config.useKelvin ? 'yes' : 'no'}`);
|
|
25
|
+
log.info('==================================================================================');
|
|
7
26
|
}
|
|
8
27
|
|
|
9
28
|
async function zigbee2mqttInfo(payload, log) {
|
|
10
|
-
log.info(
|
|
11
|
-
log.info(
|
|
12
|
-
log.info(
|
|
29
|
+
log.info('============================ Zigbee2MQTT Information =============================');
|
|
30
|
+
log.info(`|| Zigbee2MQTT Version: ${payload.version} `);
|
|
31
|
+
log.info(`|| Coordinator type: ${payload.coordinator.type} Version: ${payload.coordinator.meta.revision} Serial: ${payload.config.serial.port}`);
|
|
32
|
+
log.info(`|| Network panid ${payload.network.pan_id} channel: ${payload.network.channel} ext_pan_id: ${payload.network.extended_pan_id}`);
|
|
33
|
+
log.info('==================================================================================');
|
|
13
34
|
}
|
|
14
35
|
|
|
15
36
|
module.exports = {
|
|
16
|
-
adapterInfo
|
|
17
|
-
zigbee2mqttInfo
|
|
37
|
+
adapterInfo,
|
|
38
|
+
zigbee2mqttInfo,
|
|
18
39
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const core = require('@iobroker/adapter-core');
|
|
2
|
+
const Aedes = require('aedes');
|
|
3
|
+
const net = require('net');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MqttServerController {
|
|
7
|
+
constructor(adapter) {
|
|
8
|
+
this.adapter = adapter;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async createMQTTServer() {
|
|
12
|
+
try {
|
|
13
|
+
const NedbPersistence = require('aedes-persistence-nedb');
|
|
14
|
+
const db = new NedbPersistence({ path: `${core.getAbsoluteInstanceDataDir(this.adapter)}/mqttData`, prefix: '' });
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
const aedes = Aedes({ persistence: db });
|
|
17
|
+
const mqttServer = net.createServer(aedes.handle);
|
|
18
|
+
mqttServer.listen(this.adapter.config.mqttServerPort, this.adapter.config.mqttServerIPBind, () => {
|
|
19
|
+
this.adapter.log.info(`Statring MQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`);
|
|
20
|
+
});
|
|
21
|
+
} catch (err) {
|
|
22
|
+
this.adapter.log.error(err);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async createDummyMQTTServer() {
|
|
27
|
+
try {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
const aedes = Aedes();
|
|
30
|
+
const mqttServer = net.createServer(aedes.handle);
|
|
31
|
+
mqttServer.listen(this.adapter.config.mqttServerPort, this.adapter.config.mqttServerIPBind, () => {
|
|
32
|
+
this.adapter.log.info(`Statring DummyMQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`);
|
|
33
|
+
});
|
|
34
|
+
} catch (err) {
|
|
35
|
+
this.adapter.log.error(err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
MqttServerController
|
|
42
|
+
};
|
package/lib/rgb.js
CHANGED
|
@@ -73,14 +73,12 @@ function cie_to_rgb(x, y, brightness) {
|
|
|
73
73
|
green = green / red;
|
|
74
74
|
blue = blue / red;
|
|
75
75
|
red = 1.0;
|
|
76
|
-
}
|
|
77
|
-
else if (green > blue && green > red && green > 1.0) {
|
|
76
|
+
} else if (green > blue && green > red && green > 1.0) {
|
|
78
77
|
|
|
79
78
|
red = red / green;
|
|
80
79
|
blue = blue / green;
|
|
81
80
|
green = 1.0;
|
|
82
|
-
}
|
|
83
|
-
else if (blue > red && blue > green && blue > 1.0) {
|
|
81
|
+
} else if (blue > red && blue > green && blue > 1.0) {
|
|
84
82
|
|
|
85
83
|
red = red / blue;
|
|
86
84
|
green = green / blue;
|
|
@@ -157,7 +155,9 @@ function hsvToRGB(h, s, v) {
|
|
|
157
155
|
s = s / 100;
|
|
158
156
|
v = v / 100;
|
|
159
157
|
|
|
160
|
-
let r;
|
|
158
|
+
let r;
|
|
159
|
+
let g;
|
|
160
|
+
let b;
|
|
161
161
|
if (arguments.length === 1) {
|
|
162
162
|
s = h.s, v = h.v, h = h.h;
|
|
163
163
|
}
|
|
@@ -167,12 +167,24 @@ function hsvToRGB(h, s, v) {
|
|
|
167
167
|
const q = v * (1 - f * s);
|
|
168
168
|
const t = v * (1 - (1 - f) * s);
|
|
169
169
|
switch (i % 6) {
|
|
170
|
-
case 0:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
case
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
case 0:
|
|
171
|
+
r = v, g = t, b = p;
|
|
172
|
+
break;
|
|
173
|
+
case 1:
|
|
174
|
+
r = q, g = v, b = p;
|
|
175
|
+
break;
|
|
176
|
+
case 2:
|
|
177
|
+
r = p, g = v, b = t;
|
|
178
|
+
break;
|
|
179
|
+
case 3:
|
|
180
|
+
r = p, g = q, b = v;
|
|
181
|
+
break;
|
|
182
|
+
case 4:
|
|
183
|
+
r = t, g = p, b = v;
|
|
184
|
+
break;
|
|
185
|
+
case 5:
|
|
186
|
+
r = v, g = p, b = q;
|
|
187
|
+
break;
|
|
176
188
|
}
|
|
177
189
|
return {
|
|
178
190
|
r: Math.round(r * 255),
|
|
@@ -185,17 +197,29 @@ function rgbToHSV(r, g, b, numeric) {
|
|
|
185
197
|
if (arguments.length === 1) {
|
|
186
198
|
g = r.g, b = r.b, r = r.r;
|
|
187
199
|
}
|
|
188
|
-
const max = Math.max(r, g, b);
|
|
200
|
+
const max = Math.max(r, g, b);
|
|
201
|
+
const min = Math.min(r, g, b);
|
|
189
202
|
const d = max - min;
|
|
190
203
|
let h;
|
|
191
204
|
const s = (max === 0 ? 0 : d / max);
|
|
192
205
|
const v = max / 255;
|
|
193
206
|
|
|
194
207
|
switch (max) {
|
|
195
|
-
case min:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
case
|
|
208
|
+
case min:
|
|
209
|
+
h = 0;
|
|
210
|
+
break;
|
|
211
|
+
case r:
|
|
212
|
+
h = (g - b) + d * (g < b ? 6 : 0);
|
|
213
|
+
h /= 6 * d;
|
|
214
|
+
break;
|
|
215
|
+
case g:
|
|
216
|
+
h = (b - r) + d * 2;
|
|
217
|
+
h /= 6 * d;
|
|
218
|
+
break;
|
|
219
|
+
case b:
|
|
220
|
+
h = (r - g) + d * 4;
|
|
221
|
+
h /= 6 * d;
|
|
222
|
+
break;
|
|
199
223
|
}
|
|
200
224
|
if (numeric) return {
|
|
201
225
|
// @ts-ignore
|
|
@@ -210,6 +234,7 @@ function rgbToHSV(r, g, b, numeric) {
|
|
|
210
234
|
v: (v * 100).toFixed(3),
|
|
211
235
|
};
|
|
212
236
|
}
|
|
237
|
+
|
|
213
238
|
function colorArrayFromString(value) {
|
|
214
239
|
if (typeof (value) === 'string') {
|
|
215
240
|
const rv = [];
|
|
@@ -260,4 +285,4 @@ exports.hsvToRGB = hsvToRGB;
|
|
|
260
285
|
exports.rgbToHSV = rgbToHSV;
|
|
261
286
|
exports.colorArrayFromString = colorArrayFromString;
|
|
262
287
|
exports.colorStringFromRGBArray = colorStringFromRGBArray;
|
|
263
|
-
exports.hsvToRGBString = hsvToRGBString;
|
|
288
|
+
exports.hsvToRGBString = hsvToRGBString;
|
package/lib/states.js
CHANGED
|
@@ -274,17 +274,16 @@ const states = {
|
|
|
274
274
|
},
|
|
275
275
|
voltage: {
|
|
276
276
|
id: 'voltage',
|
|
277
|
-
name: '
|
|
277
|
+
name: 'Voltage',
|
|
278
278
|
icon: undefined,
|
|
279
|
-
role: '
|
|
279
|
+
role: 'value.voltage',
|
|
280
280
|
write: false,
|
|
281
281
|
read: true,
|
|
282
282
|
type: 'number',
|
|
283
283
|
unit: 'V',
|
|
284
|
-
getter: payload => payload.voltage / 1000,
|
|
285
284
|
def: 0,
|
|
286
285
|
},
|
|
287
|
-
|
|
286
|
+
battery_voltage: {
|
|
288
287
|
id: 'voltage',
|
|
289
288
|
name: 'Battery voltage',
|
|
290
289
|
icon: undefined,
|
|
@@ -293,9 +292,18 @@ const states = {
|
|
|
293
292
|
read: true,
|
|
294
293
|
type: 'number',
|
|
295
294
|
unit: 'V',
|
|
296
|
-
getter: payload => payload.voltage * 10,
|
|
297
295
|
def: 0,
|
|
298
296
|
},
|
|
297
|
+
energy: {
|
|
298
|
+
id: 'energy',
|
|
299
|
+
name: 'Sum of consumed energy',
|
|
300
|
+
icon: undefined,
|
|
301
|
+
role: 'value.power.consumption',
|
|
302
|
+
write: false,
|
|
303
|
+
read: true,
|
|
304
|
+
type: 'number',
|
|
305
|
+
unit: 'kWh'
|
|
306
|
+
},
|
|
299
307
|
battery: {
|
|
300
308
|
id: 'battery',
|
|
301
309
|
prop: 'battery',
|
|
@@ -546,6 +554,17 @@ const states = {
|
|
|
546
554
|
type: 'boolean',
|
|
547
555
|
getter: payload => (payload.button_right === 'hold'),
|
|
548
556
|
},
|
|
557
|
+
device_temperature: {
|
|
558
|
+
id: 'device_temperature',
|
|
559
|
+
name: 'Temperature of the device',
|
|
560
|
+
icon: undefined,
|
|
561
|
+
role: 'value.temperature',
|
|
562
|
+
write: false,
|
|
563
|
+
read: true,
|
|
564
|
+
type: 'number',
|
|
565
|
+
unit: '°C',
|
|
566
|
+
def: 0,
|
|
567
|
+
},
|
|
549
568
|
temperature: {
|
|
550
569
|
id: 'temperature',
|
|
551
570
|
name: 'Temperature',
|
|
@@ -736,7 +755,7 @@ const states = {
|
|
|
736
755
|
type: 'boolean',
|
|
737
756
|
def: false,
|
|
738
757
|
},
|
|
739
|
-
smoke_detected2: {
|
|
758
|
+
smoke_detected2: { // for Heiman
|
|
740
759
|
id: 'smoke',
|
|
741
760
|
prop: 'smoke',
|
|
742
761
|
name: 'Smoke leak detected',
|
|
@@ -747,7 +766,7 @@ const states = {
|
|
|
747
766
|
type: 'boolean',
|
|
748
767
|
def: false,
|
|
749
768
|
},
|
|
750
|
-
co_detected: {
|
|
769
|
+
co_detected: { // for Heiman
|
|
751
770
|
id: 'carbon_monoxide',
|
|
752
771
|
prop: 'carbon_monoxide',
|
|
753
772
|
name: 'CO leak detected',
|
|
@@ -1074,11 +1093,11 @@ const states = {
|
|
|
1074
1093
|
unit: 'V'
|
|
1075
1094
|
},
|
|
1076
1095
|
load_current: {
|
|
1077
|
-
id: '
|
|
1096
|
+
id: 'load_current',
|
|
1078
1097
|
prop: 'current',
|
|
1079
1098
|
name: 'Load current',
|
|
1080
1099
|
icon: undefined,
|
|
1081
|
-
role: 'value',
|
|
1100
|
+
role: 'value.current',
|
|
1082
1101
|
write: false,
|
|
1083
1102
|
read: true,
|
|
1084
1103
|
type: 'number',
|
|
@@ -1232,12 +1251,15 @@ const states = {
|
|
|
1232
1251
|
y: xy[1]
|
|
1233
1252
|
};
|
|
1234
1253
|
},
|
|
1235
|
-
setterOpt: (value, options) => {
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
},
|
|
1254
|
+
// setterOpt: (value, options) => {
|
|
1255
|
+
// const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
1256
|
+
// const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
1257
|
+
// return { ...options, transition: transitionTime };
|
|
1258
|
+
// },
|
|
1240
1259
|
getter: payload => {
|
|
1260
|
+
if (payload.color_mode != 'xy') {
|
|
1261
|
+
return undefined;
|
|
1262
|
+
}
|
|
1241
1263
|
if (payload.color && payload.color.hasOwnProperty('x') && payload.color.hasOwnProperty('y')) {
|
|
1242
1264
|
const colorval = rgb.cie_to_rgb(payload.color.x, payload.color.y);
|
|
1243
1265
|
return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
|
|
@@ -2625,8 +2647,7 @@ const states = {
|
|
|
2625
2647
|
max: 1,
|
|
2626
2648
|
type: 'number',
|
|
2627
2649
|
},
|
|
2628
|
-
thermostat_keypad_lockout:
|
|
2629
|
-
{
|
|
2650
|
+
thermostat_keypad_lockout: {
|
|
2630
2651
|
id: 'keypad_lockout',
|
|
2631
2652
|
name: 'Keypad Lockout',
|
|
2632
2653
|
prop: 'keypad_lockout',
|
|
@@ -5844,8 +5865,7 @@ const states = {
|
|
|
5844
5865
|
setter: (value, options) => {
|
|
5845
5866
|
try {
|
|
5846
5867
|
return JSON.parse(value);
|
|
5847
|
-
}
|
|
5848
|
-
catch (err) {
|
|
5868
|
+
} catch (err) {
|
|
5849
5869
|
const effectjson = {
|
|
5850
5870
|
colors: [{ r: 255, g: 0, b: 0 }, { r: 0, g: 255, b: 0 }, { r: 0, g: 0, b: 255 }],
|
|
5851
5871
|
speed: 10,
|
|
@@ -6419,4 +6439,4 @@ module.exports = {
|
|
|
6419
6439
|
states: states,
|
|
6420
6440
|
unitLookup: unitLookup,
|
|
6421
6441
|
nameLookup: nameLookup,
|
|
6422
|
-
};
|
|
6442
|
+
};
|