zigbee-herdsman-converters 15.0.9 → 15.0.11
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/converters/fromZigbee.js +11 -0
- package/converters/toZigbee.js +21 -123
- package/devices/datek.js +38 -4
- package/devices/fantem.js +0 -1
- package/devices/innr.js +15 -0
- package/devices/legrand.js +2 -2
- package/devices/moes.js +2 -1
- package/devices/namron.js +8 -0
- package/devices/netvox.js +9 -0
- package/devices/philips.js +308 -115
- package/devices/sinope.js +4 -1
- package/devices/tuya.js +67 -2
- package/devices/ubisys.js +0 -1
- package/lib/ota/common.js +0 -5
- package/lib/tuya.js +14 -0
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -8320,6 +8320,17 @@ const converters = {
|
|
|
8320
8320
|
return result;
|
|
8321
8321
|
},
|
|
8322
8322
|
},
|
|
8323
|
+
led_on_motion: {
|
|
8324
|
+
cluster: 'ssIasZone',
|
|
8325
|
+
type: ['attributeReport', 'readResponse'],
|
|
8326
|
+
convert: (model, msg, publish, options, meta) => {
|
|
8327
|
+
const result = {};
|
|
8328
|
+
if (0x4000 in msg.data) {
|
|
8329
|
+
result.led_on_motion = msg.data[0x4000] == 1 ? true : false;
|
|
8330
|
+
}
|
|
8331
|
+
return result;
|
|
8332
|
+
},
|
|
8333
|
+
},
|
|
8323
8334
|
// #endregion
|
|
8324
8335
|
|
|
8325
8336
|
// #region Ignore converters (these message dont need parsing).
|
package/converters/toZigbee.js
CHANGED
|
@@ -369,8 +369,16 @@ const converters = {
|
|
|
369
369
|
warning_simple: {
|
|
370
370
|
key: ['alarm'],
|
|
371
371
|
convertSet: async (entity, key, value, meta) => {
|
|
372
|
-
const alarmState = (value === 'OFF' ? 0 : 1);
|
|
373
|
-
|
|
372
|
+
const alarmState = (value === 'alarm' || value === 'OFF' ? 0 : 1);
|
|
373
|
+
|
|
374
|
+
let info;
|
|
375
|
+
// For Develco SMSZB-120, introduced change in fw 4.0.5, tested backward with 4.0.4
|
|
376
|
+
if (['SMSZB-120'].includes(meta.mapped.model)) {
|
|
377
|
+
info = ((alarmState) << 7) + ((alarmState) << 6);
|
|
378
|
+
} else {
|
|
379
|
+
info = (3 << 6) + ((alarmState) << 2);
|
|
380
|
+
}
|
|
381
|
+
|
|
374
382
|
await entity.command(
|
|
375
383
|
'ssIasWd',
|
|
376
384
|
'startWarning',
|
|
@@ -2047,127 +2055,6 @@ const converters = {
|
|
|
2047
2055
|
return await converters.light_color_colortemp.convertGet(entity, key, meta);
|
|
2048
2056
|
},
|
|
2049
2057
|
},
|
|
2050
|
-
hue_power_on_behavior: {
|
|
2051
|
-
key: ['hue_power_on_behavior'],
|
|
2052
|
-
convertSet: async (entity, key, value, meta) => {
|
|
2053
|
-
if (value === 'default') {
|
|
2054
|
-
value = 'on';
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
let supports = {colorTemperature: false, colorXY: false};
|
|
2058
|
-
if (entity.constructor.name === 'Endpoint' && entity.supportsInputCluster('lightingColorCtrl')) {
|
|
2059
|
-
const readResult = await entity.read('lightingColorCtrl', ['colorCapabilities']);
|
|
2060
|
-
supports = {
|
|
2061
|
-
colorTemperature: (readResult.colorCapabilities & 1 << 4) > 0,
|
|
2062
|
-
colorXY: (readResult.colorCapabilities & 1 << 3) > 0,
|
|
2063
|
-
};
|
|
2064
|
-
} else if (entity.constructor.name === 'Group') {
|
|
2065
|
-
supports = {colorTemperature: true, colorXY: true};
|
|
2066
|
-
}
|
|
2067
|
-
|
|
2068
|
-
if (value === 'off') {
|
|
2069
|
-
await entity.write('genOnOff', {0x4003: {value: 0x00, type: 0x30}});
|
|
2070
|
-
} else if (value === 'recover') {
|
|
2071
|
-
await entity.write('genOnOff', {0x4003: {value: 0xff, type: 0x30}});
|
|
2072
|
-
await entity.write('genLevelCtrl', {0x4000: {value: 0xff, type: 0x20}});
|
|
2073
|
-
|
|
2074
|
-
if (supports.colorTemperature) {
|
|
2075
|
-
await entity.write('lightingColorCtrl', {0x4010: {value: 0xffff, type: 0x21}});
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
if (supports.colorXY) {
|
|
2079
|
-
await entity.write('lightingColorCtrl', {0x0003: {value: 0xffff, type: 0x21}}, manufacturerOptions.hue);
|
|
2080
|
-
await entity.write('lightingColorCtrl', {0x0004: {value: 0xffff, type: 0x21}}, manufacturerOptions.hue);
|
|
2081
|
-
}
|
|
2082
|
-
} else if (value === 'on') {
|
|
2083
|
-
await entity.write('genOnOff', {0x4003: {value: 0x01, type: 0x30}});
|
|
2084
|
-
|
|
2085
|
-
let brightness = meta.message.hasOwnProperty('hue_power_on_brightness') ?
|
|
2086
|
-
meta.message.hue_power_on_brightness : 0xfe;
|
|
2087
|
-
if (brightness === 255) {
|
|
2088
|
-
// 255 (0xFF) is the value for recover, therefore set it to 254 (0xFE)
|
|
2089
|
-
brightness = 254;
|
|
2090
|
-
}
|
|
2091
|
-
await entity.write('genLevelCtrl', {0x4000: {value: brightness, type: 0x20}});
|
|
2092
|
-
|
|
2093
|
-
if (entity.supportsInputCluster('lightingColorCtrl')) {
|
|
2094
|
-
if (
|
|
2095
|
-
meta.message.hasOwnProperty('hue_power_on_color_temperature') &&
|
|
2096
|
-
meta.message.hasOwnProperty('hue_power_on_color')
|
|
2097
|
-
) {
|
|
2098
|
-
meta.logger.error(`Provide either color temperature or color, not both`);
|
|
2099
|
-
} else if (meta.message.hasOwnProperty('hue_power_on_color_temperature')) {
|
|
2100
|
-
const colortemp = meta.message.hue_power_on_color_temperature;
|
|
2101
|
-
await entity.write('lightingColorCtrl', {0x4010: {value: colortemp, type: 0x21}});
|
|
2102
|
-
// Set color to default
|
|
2103
|
-
if (supports.colorXY) {
|
|
2104
|
-
await entity.write('lightingColorCtrl', {0x0003: {value: 0xFFFF, type: 0x21}}, manufacturerOptions.hue);
|
|
2105
|
-
await entity.write('lightingColorCtrl', {0x0004: {value: 0xFFFF, type: 0x21}}, manufacturerOptions.hue);
|
|
2106
|
-
}
|
|
2107
|
-
} else if (meta.message.hasOwnProperty('hue_power_on_color')) {
|
|
2108
|
-
const colorXY = libColor.ColorRGB.fromHex(meta.message.hue_power_on_color).toXY();
|
|
2109
|
-
value = {x: utils.mapNumberRange(colorXY.x, 0, 1, 0, 65535), y: utils.mapNumberRange(colorXY.y, 0, 1, 0, 65535)};
|
|
2110
|
-
|
|
2111
|
-
// Set colortemp to default
|
|
2112
|
-
if (supports.colorTemperature) {
|
|
2113
|
-
await entity.write('lightingColorCtrl', {0x4010: {value: 366, type: 0x21}});
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
await entity.write('lightingColorCtrl', {0x0003: {value: value.x, type: 0x21}}, manufacturerOptions.hue);
|
|
2117
|
-
await entity.write('lightingColorCtrl', {0x0004: {value: value.y, type: 0x21}}, manufacturerOptions.hue);
|
|
2118
|
-
} else {
|
|
2119
|
-
// Set defaults for colortemp and color
|
|
2120
|
-
if (supports.colorTemperature) {
|
|
2121
|
-
await entity.write('lightingColorCtrl', {0x4010: {value: 366, type: 0x21}});
|
|
2122
|
-
}
|
|
2123
|
-
|
|
2124
|
-
if (supports.colorXY) {
|
|
2125
|
-
await entity.write('lightingColorCtrl', {0x0003: {value: 0xFFFF, type: 0x21}}, manufacturerOptions.hue);
|
|
2126
|
-
await entity.write('lightingColorCtrl', {0x0004: {value: 0xFFFF, type: 0x21}}, manufacturerOptions.hue);
|
|
2127
|
-
}
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
}
|
|
2131
|
-
|
|
2132
|
-
return {state: {hue_power_on_behavior: value}};
|
|
2133
|
-
},
|
|
2134
|
-
},
|
|
2135
|
-
hue_power_on_error: {
|
|
2136
|
-
key: ['hue_power_on_brightness', 'hue_power_on_color_temperature', 'hue_power_on_color'],
|
|
2137
|
-
convertSet: async (entity, key, value, meta) => {
|
|
2138
|
-
if (!meta.message.hasOwnProperty('hue_power_on_behavior')) {
|
|
2139
|
-
throw new Error(`Provide a value for 'hue_power_on_behavior'`);
|
|
2140
|
-
}
|
|
2141
|
-
},
|
|
2142
|
-
},
|
|
2143
|
-
hue_motion_sensitivity: {
|
|
2144
|
-
// motion detect sensitivity, philips specific
|
|
2145
|
-
key: ['motion_sensitivity'],
|
|
2146
|
-
convertSet: async (entity, key, value, meta) => {
|
|
2147
|
-
// make sure you write to second endpoint!
|
|
2148
|
-
const lookup = {'low': 0, 'medium': 1, 'high': 2, 'very_high': 3, 'max': 4};
|
|
2149
|
-
value = value.toLowerCase();
|
|
2150
|
-
utils.validateValue(value, Object.keys(lookup));
|
|
2151
|
-
|
|
2152
|
-
const payload = {48: {value: lookup[value], type: 32}};
|
|
2153
|
-
await entity.write('msOccupancySensing', payload, manufacturerOptions.hue);
|
|
2154
|
-
return {state: {motion_sensitivity: value}};
|
|
2155
|
-
},
|
|
2156
|
-
convertGet: async (entity, key, meta) => {
|
|
2157
|
-
await entity.read('msOccupancySensing', [48], manufacturerOptions.hue);
|
|
2158
|
-
},
|
|
2159
|
-
},
|
|
2160
|
-
hue_motion_led_indication: {
|
|
2161
|
-
key: ['led_indication'],
|
|
2162
|
-
convertSet: async (entity, key, value, meta) => {
|
|
2163
|
-
const payload = {0x0033: {value, type: 0x10}};
|
|
2164
|
-
await entity.write('genBasic', payload, manufacturerOptions.hue);
|
|
2165
|
-
return {state: {led_indication: value}};
|
|
2166
|
-
},
|
|
2167
|
-
convertGet: async (entity, key, meta) => {
|
|
2168
|
-
await entity.read('genBasic', [0x0033], manufacturerOptions.hue);
|
|
2169
|
-
},
|
|
2170
|
-
},
|
|
2171
2058
|
aqara_motion_sensitivity: {
|
|
2172
2059
|
key: ['motion_sensitivity'],
|
|
2173
2060
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -7166,6 +7053,17 @@ const converters = {
|
|
|
7166
7053
|
}
|
|
7167
7054
|
},
|
|
7168
7055
|
},
|
|
7056
|
+
led_on_motion: {
|
|
7057
|
+
key: ['led_on_motion'],
|
|
7058
|
+
convertSet: async (entity, key, value, meta) => {
|
|
7059
|
+
await entity.write('ssIasZone', {0x4000: {value: value === true ? 1 : 0, type: 0x10}},
|
|
7060
|
+
{manufacturerCode: 4919});
|
|
7061
|
+
return {state: {led_on_motion: value}};
|
|
7062
|
+
},
|
|
7063
|
+
convertGet: async (entity, key, meta) => {
|
|
7064
|
+
await entity.read('ssIasZone', [0x4000], {manufacturerCode: 4919});
|
|
7065
|
+
},
|
|
7066
|
+
},
|
|
7169
7067
|
// #endregion
|
|
7170
7068
|
|
|
7171
7069
|
// #region Ignore converters
|
package/devices/datek.js
CHANGED
|
@@ -88,10 +88,29 @@ module.exports = [
|
|
|
88
88
|
fingerprint: [{modelID: 'Motion Sensor', manufacturerName: 'Eva'}],
|
|
89
89
|
model: 'HSE2927E',
|
|
90
90
|
vendor: 'Datek',
|
|
91
|
-
description: 'Eva
|
|
92
|
-
fromZigbee: [fz.
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
description: 'Eva motion sensor',
|
|
92
|
+
fromZigbee: [fz.battery, fz.occupancy, fz.occupancy_timeout, fz.illuminance, fz.temperature,
|
|
93
|
+
fz.ias_enroll, fz.ias_occupancy_alarm_1, fz.ias_occupancy_alarm_1_report, fz.led_on_motion],
|
|
94
|
+
toZigbee: [tz.occupancy_timeout, tz.led_on_motion],
|
|
95
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
96
|
+
const options = {manufacturerCode: 4919};
|
|
97
|
+
const endpoint = device.getEndpoint(1);
|
|
98
|
+
const binds = ['msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing', 'ssIasZone'];
|
|
99
|
+
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
100
|
+
await reporting.occupancy(endpoint);
|
|
101
|
+
await reporting.temperature(endpoint);
|
|
102
|
+
await reporting.illuminance(endpoint);
|
|
103
|
+
const payload = [{
|
|
104
|
+
attribute: {ID: 0x4000, type: 0x10},
|
|
105
|
+
}];
|
|
106
|
+
await endpoint.configureReporting('ssIasZone', payload, options);
|
|
107
|
+
await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState', 'zoneId']);
|
|
108
|
+
await endpoint.read('msOccupancySensing', ['pirOToUDelay']);
|
|
109
|
+
await endpoint.read('ssIasZone', [0x4000], options);
|
|
110
|
+
},
|
|
111
|
+
exposes: [e.temperature(), e.occupancy(), e.battery_low(), e.illuminance_lux(), e.illuminance(),
|
|
112
|
+
exposes.binary('led_on_motion', ea.ALL, true, false).withDescription('Enable/disable LED on motion'),
|
|
113
|
+
exposes.numeric('occupancy_timeout', ea.ALL).withUnit('seconds').withValueMin(0).withValueMax(65535)],
|
|
95
114
|
},
|
|
96
115
|
{
|
|
97
116
|
zigbeeModel: ['ID Lock 150'],
|
|
@@ -208,4 +227,19 @@ module.exports = [
|
|
|
208
227
|
e.action(['recall_1', 'recall_2', 'recall_3', 'recall_4', 'on', 'off',
|
|
209
228
|
'brightness_move_down', 'brightness_move_up', 'brightness_stop'])],
|
|
210
229
|
},
|
|
230
|
+
{
|
|
231
|
+
zigbeeModel: ['Door/Window Sensor'],
|
|
232
|
+
model: 'HSE2920E',
|
|
233
|
+
vendor: 'Datek',
|
|
234
|
+
description: 'Door/window sensor',
|
|
235
|
+
fromZigbee: [fz.ias_contact_alarm_1, fz.ias_contact_alarm_1_report, fz.temperature, fz.ias_enroll],
|
|
236
|
+
toZigbee: [],
|
|
237
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
238
|
+
const endpoint = device.getEndpoint(1);
|
|
239
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['ssIasZone', 'msTemperatureMeasurement']);
|
|
240
|
+
await reporting.temperature(endpoint);
|
|
241
|
+
await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState', 'zoneId']);
|
|
242
|
+
},
|
|
243
|
+
exposes: [e.contact(), e.battery_low(), e.tamper(), e.temperature()],
|
|
244
|
+
},
|
|
211
245
|
];
|
package/devices/fantem.js
CHANGED
|
@@ -49,7 +49,6 @@ module.exports = [
|
|
|
49
49
|
{
|
|
50
50
|
fingerprint: [{modelID: 'TS0202', manufacturerName: '_TZ3210_rxqls8v0'},
|
|
51
51
|
{modelID: 'TS0202', manufacturerName: '_TZ3210_zmy9hjay'},
|
|
52
|
-
{modelID: 'TS0202', manufacturerName: '_TZ3000_6ygjfyll'},
|
|
53
52
|
{modelID: 'TS0202', manufacturerName: '_TZ3210_wuhzzfqg'}],
|
|
54
53
|
model: 'ZB003-X',
|
|
55
54
|
vendor: 'Fantem',
|
package/devices/innr.js
CHANGED
|
@@ -8,6 +8,21 @@ const ea = exposes.access;
|
|
|
8
8
|
const ota = require('../lib/ota');
|
|
9
9
|
|
|
10
10
|
module.exports = [
|
|
11
|
+
{
|
|
12
|
+
zigbeeModel: ['RC 210'],
|
|
13
|
+
model: 'RC 210',
|
|
14
|
+
vendor: 'Innr',
|
|
15
|
+
description: 'Remote control',
|
|
16
|
+
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.command_move_to_level,
|
|
17
|
+
fz.command_move_to_color_temp],
|
|
18
|
+
toZigbee: [],
|
|
19
|
+
exposes: [e.action(['on', 'off', 'brightness_move_up', 'brightness_move_down', 'brightness_stop', 'brightness_move_to_level',
|
|
20
|
+
'color_temperature_move'])],
|
|
21
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
22
|
+
const ep = device.getEndpoint(1);
|
|
23
|
+
await reporting.bind(ep, coordinatorEndpoint, ['genBasic', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl']);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
11
26
|
{
|
|
12
27
|
zigbeeModel: ['RC 250'],
|
|
13
28
|
model: 'RC 250',
|
package/devices/legrand.js
CHANGED
|
@@ -54,7 +54,7 @@ module.exports = [
|
|
|
54
54
|
zigbeeModel: [' Contactor\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'+
|
|
55
55
|
'\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'],
|
|
56
56
|
model: '412171',
|
|
57
|
-
description: 'DIN contactor module (
|
|
57
|
+
description: 'DIN contactor module (BTicino FC80CC )',
|
|
58
58
|
vendor: 'Legrand',
|
|
59
59
|
extend: extend.switch(),
|
|
60
60
|
fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_cluster_fc01, fz.ignore_basic_report, fz.ignore_genOta],
|
|
@@ -78,7 +78,7 @@ module.exports = [
|
|
|
78
78
|
zigbeeModel: [' Teleruptor\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'+
|
|
79
79
|
'\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'],
|
|
80
80
|
model: '412170',
|
|
81
|
-
description: 'DIN smart relay for light control (
|
|
81
|
+
description: 'DIN smart relay for light control (BTicino FC80RC ) ',
|
|
82
82
|
vendor: 'Legrand',
|
|
83
83
|
extend: extend.switch(),
|
|
84
84
|
fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_cluster_fc01, fz.ignore_basic_report, fz.ignore_genOta],
|
package/devices/moes.js
CHANGED
|
@@ -310,7 +310,8 @@ module.exports = [
|
|
|
310
310
|
exposes.numeric('boost_heating_countdown', ea.STATE).withUnit('Min').withDescription('Countdown in minutes')
|
|
311
311
|
.withValueMin(0).withValueMax(15),
|
|
312
312
|
exposes.numeric('boost_heating_countdown_time_set', ea.STATE_SET).withUnit('second')
|
|
313
|
-
.withDescription('Boost Time Setting 100 sec - 900 sec, (default = 300 sec)').withValueMin(100)
|
|
313
|
+
.withDescription('Boost Time Setting 100 sec - 900 sec, (default = 300 sec)').withValueMin(100)
|
|
314
|
+
.withValueMax(900).withValueStep(100)],
|
|
314
315
|
},
|
|
315
316
|
{
|
|
316
317
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_e3oitdyu'}],
|
package/devices/namron.js
CHANGED
|
@@ -725,4 +725,12 @@ module.exports = [
|
|
|
725
725
|
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
726
726
|
},
|
|
727
727
|
},
|
|
728
|
+
{
|
|
729
|
+
zigbeeModel: ['3802968'],
|
|
730
|
+
model: '3802968',
|
|
731
|
+
vendor: 'Namron',
|
|
732
|
+
description: 'LED Filament Flex 5W CCT E27 Clear',
|
|
733
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 555]}),
|
|
734
|
+
meta: {turnsOffAtBrightness1: true},
|
|
735
|
+
},
|
|
728
736
|
];
|
package/devices/netvox.js
CHANGED
|
@@ -23,4 +23,13 @@ module.exports = [
|
|
|
23
23
|
},
|
|
24
24
|
exposes: [e.switch(), e.power(), e.current(), e.voltage()],
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
zigbeeModel: ['ZB02AE0ED'],
|
|
28
|
+
model: 'ZB02A',
|
|
29
|
+
vendor: 'Netvox',
|
|
30
|
+
description: 'Wireless wall switch',
|
|
31
|
+
fromZigbee: [fz.command_toggle],
|
|
32
|
+
toZigbee: [],
|
|
33
|
+
exposes: [e.action(['toggle'])],
|
|
34
|
+
},
|
|
26
35
|
];
|
package/devices/philips.js
CHANGED
|
@@ -6,6 +6,8 @@ const reporting = require('../lib/reporting');
|
|
|
6
6
|
const globalStore = require('../lib/store');
|
|
7
7
|
const philips = require('../lib/philips');
|
|
8
8
|
const utils = require('../lib/utils');
|
|
9
|
+
const libColor = require('../lib/color');
|
|
10
|
+
const herdsman = require('zigbee-herdsman');
|
|
9
11
|
const e = exposes.presets;
|
|
10
12
|
const ea = exposes.access;
|
|
11
13
|
|
|
@@ -13,115 +15,97 @@ const ea = exposes.access;
|
|
|
13
15
|
const extendDontUse = require('../lib/extend');
|
|
14
16
|
const extend = {switch: extendDontUse.switch};
|
|
15
17
|
|
|
18
|
+
const manufacturerOptions = {manufacturerCode: herdsman.Zcl.ManufacturerCode.PHILIPS};
|
|
19
|
+
|
|
16
20
|
const hueExtend = {
|
|
17
21
|
light_onoff_brightness: (options={}) => ({
|
|
18
22
|
...extendDontUse.light_onoff_brightness(options),
|
|
19
23
|
ota: ota.zigbeeOTA,
|
|
20
24
|
meta: {turnsOffAtBrightness1: true},
|
|
21
|
-
toZigbee: extendDontUse.light_onoff_brightness(options).toZigbee.concat([
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
...extendDontUse.light_onoff_brightness_colortemp(options),
|
|
25
|
-
ota: ota.zigbeeOTA,
|
|
26
|
-
meta: {turnsOffAtBrightness1: true},
|
|
27
|
-
toZigbee: extendDontUse.light_onoff_brightness_colortemp(options).toZigbee
|
|
28
|
-
.concat([tz.hue_power_on_behavior, tz.hue_power_on_error]),
|
|
29
|
-
}),
|
|
30
|
-
light_onoff_brightness_color: (options={}) => ({
|
|
31
|
-
...extendDontUse.light_onoff_brightness_color({supportsHS: true, ...options}),
|
|
32
|
-
ota: ota.zigbeeOTA,
|
|
33
|
-
meta: {turnsOffAtBrightness1: true},
|
|
34
|
-
toZigbee: extendDontUse.light_onoff_brightness_color({supportsHS: true, ...options}).toZigbee
|
|
35
|
-
.concat([tz.hue_power_on_behavior, tz.hue_power_on_error]),
|
|
36
|
-
}),
|
|
37
|
-
light_onoff_brightness_colortemp_color: (options={}) => ({
|
|
38
|
-
...extendDontUse.light_onoff_brightness_colortemp_color({supportsHS: true, ...options}),
|
|
39
|
-
ota: ota.zigbeeOTA,
|
|
40
|
-
meta: {turnsOffAtBrightness1: true},
|
|
41
|
-
toZigbee: extendDontUse.light_onoff_brightness_colortemp_color({supportsHS: true, ...options})
|
|
42
|
-
.toZigbee.concat([tz.hue_power_on_behavior, tz.hue_power_on_error]),
|
|
25
|
+
toZigbee: extendDontUse.light_onoff_brightness(options).toZigbee.concat([
|
|
26
|
+
tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error,
|
|
27
|
+
]),
|
|
43
28
|
}),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
29
|
+
light_onoff_brightness_colortemp: (options={}) => {
|
|
30
|
+
options = {disableHueEffects: true, ...options};
|
|
31
|
+
if (!options.disableHueEffects) options.disableEffect = true;
|
|
32
|
+
const result = extendDontUse.light_onoff_brightness_colortemp(options);
|
|
33
|
+
result['ota'] = ota.zigbeeOTA;
|
|
34
|
+
result['meta'] = {turnsOffAtBrightness1: true};
|
|
35
|
+
result['toZigbee'] = result['toZigbee'].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]);
|
|
36
|
+
if (!options.disableHueEffects) {
|
|
37
|
+
result['toZigbee'] = result['toZigbee'].concat([tzLocal.effect]);
|
|
38
|
+
result['exposes'] = result['exposes'].concat([exposes.enum('effect', ea.SET,
|
|
39
|
+
['blink', 'breathe', 'okay', 'channel_change', 'candle', 'finish_effect', 'stop_effect', 'stop_hue_effect'])]);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
},
|
|
43
|
+
light_onoff_brightness_color: (options={}) => {
|
|
44
|
+
options = {disableHueEffects: true, ...options};
|
|
45
|
+
if (!options.disableHueEffects) options.disableEffect = true;
|
|
46
|
+
const result = extendDontUse.light_onoff_brightness_color({supportsHS: true, ...options});
|
|
47
|
+
result['ota'] = ota.zigbeeOTA;
|
|
48
|
+
result['meta'] = {turnsOffAtBrightness1: true};
|
|
49
|
+
result['toZigbee'] = result['toZigbee'].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]);
|
|
50
|
+
if (!options.disableHueEffects) {
|
|
51
|
+
result['toZigbee'] = result['toZigbee'].concat([tzLocal.effect]);
|
|
52
|
+
result['exposes'] = result['exposes'].concat([exposes.enum('effect', ea.SET, [
|
|
53
|
+
'blink', 'breathe', 'okay', 'channel_change',
|
|
54
|
+
'candle', 'fireplace', 'colorloop',
|
|
55
|
+
'finish_effect', 'stop_effect', 'stop_hue_effect',
|
|
56
|
+
])]);
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
},
|
|
60
|
+
light_onoff_brightness_colortemp_color: (options={}) => {
|
|
61
|
+
options = {disableHueEffects: true, ...options};
|
|
62
|
+
if (!options.disableHueEffects) options.disableEffect = true;
|
|
63
|
+
const result = extendDontUse.light_onoff_brightness_colortemp_color({supportsHS: true, ...options});
|
|
64
|
+
result['ota'] = ota.zigbeeOTA;
|
|
65
|
+
result['meta'] = {turnsOffAtBrightness1: true};
|
|
66
|
+
result['toZigbee'] = result['toZigbee'].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]);
|
|
67
|
+
if (!options.disableHueEffects) {
|
|
68
|
+
result['toZigbee'] = result['toZigbee'].concat([tzLocal.effect]);
|
|
69
|
+
result['exposes'] = result['exposes'].concat([exposes.enum('effect', ea.SET, [
|
|
70
|
+
'blink', 'breathe', 'okay', 'channel_change',
|
|
71
|
+
'candle', 'fireplace', 'colorloop',
|
|
72
|
+
'finish_effect', 'stop_effect', 'stop_hue_effect',
|
|
73
|
+
])]);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
},
|
|
77
|
+
light_onoff_brightness_colortemp_color_gradient: (options={}) => {
|
|
78
|
+
options = {supportsHS: true, disableEffect: true, noConfigure: true, extraEffects: [], ...options};
|
|
79
|
+
const result = extendDontUse.light_onoff_brightness_colortemp_color({supportsHS: true, ...options});
|
|
80
|
+
result['ota'] = ota.zigbeeOTA;
|
|
81
|
+
result['meta'] = {turnsOffAtBrightness1: true};
|
|
82
|
+
result['toZigbee'] = result['toZigbee'].concat([
|
|
83
|
+
tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error, tzLocal.effect,
|
|
84
|
+
tzLocal.gradient_scene, tzLocal.gradient({reverse: true}),
|
|
85
|
+
]);
|
|
86
|
+
result['fromZigbee'] = result['fromZigbee'].concat([fzLocal.gradient({reverse: true})]);
|
|
87
|
+
result['configure'] = async (device, coordinatorEndpoint, logger) => {
|
|
88
|
+
await extendDontUse.light_onoff_brightness_colortemp_color(options)
|
|
50
89
|
.configure(device, coordinatorEndpoint, logger);
|
|
51
90
|
for (const ep of device.endpoints) {
|
|
52
91
|
await ep.bind('manuSpecificPhilips2', coordinatorEndpoint);
|
|
53
92
|
}
|
|
54
|
-
}
|
|
55
|
-
exposes
|
|
93
|
+
};
|
|
94
|
+
result['exposes'] = result['exposes'].concat([
|
|
56
95
|
// gradient_scene is deprecated, use gradient instead
|
|
57
96
|
exposes.enum('gradient_scene', ea.SET, Object.keys(gradientScenes)),
|
|
58
97
|
exposes.list('gradient', ea.ALL, exposes.text('hex', 'Color in RGB HEX format (eg #663399)'))
|
|
59
98
|
.withLengthMin(1)
|
|
60
99
|
.withLengthMax(9)
|
|
61
100
|
.withDescription('List of RGB HEX colors'),
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const fzLocal = {
|
|
71
|
-
hue_tap_dial: {
|
|
72
|
-
cluster: 'manuSpecificPhilips',
|
|
73
|
-
type: 'commandHueNotification',
|
|
74
|
-
options: [exposes.options.simulated_brightness()],
|
|
75
|
-
convert: (model, msg, publish, options, meta) => {
|
|
76
|
-
const buttonLookup = {1: 'button_1', 2: 'button_2', 3: 'button_3', 4: 'button_4', 20: 'dial'};
|
|
77
|
-
const button = buttonLookup[msg.data['button']];
|
|
78
|
-
const typeLookup = {0: 'press', 1: 'hold', 2: 'press_release', 3: 'hold_release'};
|
|
79
|
-
const type = typeLookup[msg.data['type']];
|
|
80
|
-
const direction = msg.data['unknown2'] <127 ? 'right' : 'left';
|
|
81
|
-
const time = msg.data['time'];
|
|
82
|
-
const payload = {};
|
|
83
|
-
|
|
84
|
-
if (button === 'dial') {
|
|
85
|
-
const adjustedTime = direction === 'right' ? time : 256 - time;
|
|
86
|
-
const dialType = 'rotate';
|
|
87
|
-
const speed = adjustedTime <= 25 ? 'step' : adjustedTime <= 75 ? 'slow' : 'fast';
|
|
88
|
-
payload.action = `${button}_${dialType}_${direction}_${speed}`;
|
|
89
|
-
|
|
90
|
-
// simulated brightness
|
|
91
|
-
if (options.simulated_brightness) {
|
|
92
|
-
const opts = options.simulated_brightness;
|
|
93
|
-
const deltaOpts = typeof opts === 'object' && opts.hasOwnProperty('delta') ? opts.delta : 35;
|
|
94
|
-
const delta = direction === 'right' ? deltaOpts : deltaOpts * -1;
|
|
95
|
-
const brightness = globalStore.getValue(msg.endpoint, 'brightness', 255) + delta;
|
|
96
|
-
payload.brightness = utils.numberWithinRange(brightness, 0, 255);
|
|
97
|
-
globalStore.putValue(msg.endpoint, 'brightness', payload.brightness);
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
payload.action = `${button}_${type}`;
|
|
101
|
-
// duration
|
|
102
|
-
if (type === 'press') globalStore.putValue(msg.endpoint, 'press_start', Date.now());
|
|
103
|
-
else if (type === 'hold' || type === 'hold_release') {
|
|
104
|
-
payload.action_duration = (Date.now() - globalStore.getValue(msg.endpoint, 'press_start')) / 1000;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return payload;
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
gradient: (opts = {reverse: false}) => {
|
|
111
|
-
return {
|
|
112
|
-
cluster: 'manuSpecificPhilips2',
|
|
113
|
-
type: ['attributeReport', 'readResponse'],
|
|
114
|
-
convert: (model, msg, publish, options, meta) => {
|
|
115
|
-
if (msg.data && msg.data.hasOwnProperty('state')) {
|
|
116
|
-
const input = msg.data['state'].toString('hex');
|
|
117
|
-
const decoded = philips.decodeGradientColors(input, opts);
|
|
118
|
-
if (decoded.color_mode === 'gradient') {
|
|
119
|
-
return {gradient: decoded.colors};
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return {};
|
|
123
|
-
},
|
|
124
|
-
};
|
|
101
|
+
exposes.enum('effect', ea.SET, [
|
|
102
|
+
'blink', 'breathe', 'okay', 'channel_change',
|
|
103
|
+
'candle', 'fireplace', 'colorloop', 'sunrise',
|
|
104
|
+
'finish_effect', 'stop_effect', 'stop_hue_effect',
|
|
105
|
+
...options.extraEffects,
|
|
106
|
+
]),
|
|
107
|
+
]);
|
|
108
|
+
return result;
|
|
125
109
|
},
|
|
126
110
|
};
|
|
127
111
|
|
|
@@ -203,6 +187,73 @@ const gradientScenes = {
|
|
|
203
187
|
'crystalline': '5001040013500000006ea96a92a85e58074e18543d9cf3332800',
|
|
204
188
|
};
|
|
205
189
|
|
|
190
|
+
const hueEffects = {
|
|
191
|
+
'candle': '21000101',
|
|
192
|
+
'fireplace': '21000102',
|
|
193
|
+
'colorloop': '21000103',
|
|
194
|
+
'sunrise': '21000109',
|
|
195
|
+
'sparkle': '2100010a',
|
|
196
|
+
'stop_hue_effect': '200000',
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const fzLocal = {
|
|
200
|
+
hue_tap_dial: {
|
|
201
|
+
cluster: 'manuSpecificPhilips',
|
|
202
|
+
type: 'commandHueNotification',
|
|
203
|
+
options: [exposes.options.simulated_brightness()],
|
|
204
|
+
convert: (model, msg, publish, options, meta) => {
|
|
205
|
+
const buttonLookup = {1: 'button_1', 2: 'button_2', 3: 'button_3', 4: 'button_4', 20: 'dial'};
|
|
206
|
+
const button = buttonLookup[msg.data['button']];
|
|
207
|
+
const typeLookup = {0: 'press', 1: 'hold', 2: 'press_release', 3: 'hold_release'};
|
|
208
|
+
const type = typeLookup[msg.data['type']];
|
|
209
|
+
const direction = msg.data['unknown2'] <127 ? 'right' : 'left';
|
|
210
|
+
const time = msg.data['time'];
|
|
211
|
+
const payload = {};
|
|
212
|
+
|
|
213
|
+
if (button === 'dial') {
|
|
214
|
+
const adjustedTime = direction === 'right' ? time : 256 - time;
|
|
215
|
+
const dialType = 'rotate';
|
|
216
|
+
const speed = adjustedTime <= 25 ? 'step' : adjustedTime <= 75 ? 'slow' : 'fast';
|
|
217
|
+
payload.action = `${button}_${dialType}_${direction}_${speed}`;
|
|
218
|
+
|
|
219
|
+
// simulated brightness
|
|
220
|
+
if (options.simulated_brightness) {
|
|
221
|
+
const opts = options.simulated_brightness;
|
|
222
|
+
const deltaOpts = typeof opts === 'object' && opts.hasOwnProperty('delta') ? opts.delta : 35;
|
|
223
|
+
const delta = direction === 'right' ? deltaOpts : deltaOpts * -1;
|
|
224
|
+
const brightness = globalStore.getValue(msg.endpoint, 'brightness', 255) + delta;
|
|
225
|
+
payload.brightness = utils.numberWithinRange(brightness, 0, 255);
|
|
226
|
+
globalStore.putValue(msg.endpoint, 'brightness', payload.brightness);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
payload.action = `${button}_${type}`;
|
|
230
|
+
// duration
|
|
231
|
+
if (type === 'press') globalStore.putValue(msg.endpoint, 'press_start', Date.now());
|
|
232
|
+
else if (type === 'hold' || type === 'hold_release') {
|
|
233
|
+
payload.action_duration = (Date.now() - globalStore.getValue(msg.endpoint, 'press_start')) / 1000;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return payload;
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
gradient: (opts = {reverse: false}) => {
|
|
240
|
+
return {
|
|
241
|
+
cluster: 'manuSpecificPhilips2',
|
|
242
|
+
type: ['attributeReport', 'readResponse'],
|
|
243
|
+
convert: (model, msg, publish, options, meta) => {
|
|
244
|
+
if (msg.data && msg.data.hasOwnProperty('state')) {
|
|
245
|
+
const input = msg.data['state'].toString('hex');
|
|
246
|
+
const decoded = philips.decodeGradientColors(input, opts);
|
|
247
|
+
if (decoded.color_mode === 'gradient') {
|
|
248
|
+
return {gradient: decoded.colors};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return {};
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
|
|
206
257
|
const tzLocal = {
|
|
207
258
|
gradient_scene: {
|
|
208
259
|
key: ['gradient_scene'],
|
|
@@ -226,6 +277,137 @@ const tzLocal = {
|
|
|
226
277
|
},
|
|
227
278
|
};
|
|
228
279
|
},
|
|
280
|
+
effect: {
|
|
281
|
+
key: ['effect'],
|
|
282
|
+
convertSet: async (entity, key, value, meta) => {
|
|
283
|
+
if (Object.keys(hueEffects).includes(value.toLowerCase())) {
|
|
284
|
+
await entity.command('manuSpecificPhilips2', 'multiColor', {data: Buffer.from(hueEffects[value.toLowerCase()], 'hex')});
|
|
285
|
+
} else {
|
|
286
|
+
return await tz.effect.convertSet(entity, key, value, meta);
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
hue_power_on_behavior: {
|
|
291
|
+
key: ['hue_power_on_behavior'],
|
|
292
|
+
convertSet: async (entity, key, value, meta) => {
|
|
293
|
+
if (value === 'default') {
|
|
294
|
+
value = 'on';
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
let supports = {colorTemperature: false, colorXY: false};
|
|
298
|
+
if (entity.constructor.name === 'Endpoint' && entity.supportsInputCluster('lightingColorCtrl')) {
|
|
299
|
+
const readResult = await entity.read('lightingColorCtrl', ['colorCapabilities']);
|
|
300
|
+
supports = {
|
|
301
|
+
colorTemperature: (readResult.colorCapabilities & 1 << 4) > 0,
|
|
302
|
+
colorXY: (readResult.colorCapabilities & 1 << 3) > 0,
|
|
303
|
+
};
|
|
304
|
+
} else if (entity.constructor.name === 'Group') {
|
|
305
|
+
supports = {colorTemperature: true, colorXY: true};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (value === 'off') {
|
|
309
|
+
await entity.write('genOnOff', {0x4003: {value: 0x00, type: 0x30}});
|
|
310
|
+
} else if (value === 'recover') {
|
|
311
|
+
await entity.write('genOnOff', {0x4003: {value: 0xff, type: 0x30}});
|
|
312
|
+
await entity.write('genLevelCtrl', {0x4000: {value: 0xff, type: 0x20}});
|
|
313
|
+
|
|
314
|
+
if (supports.colorTemperature) {
|
|
315
|
+
await entity.write('lightingColorCtrl', {0x4010: {value: 0xffff, type: 0x21}});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (supports.colorXY) {
|
|
319
|
+
await entity.write('lightingColorCtrl', {0x0003: {value: 0xffff, type: 0x21}}, manufacturerOptions);
|
|
320
|
+
await entity.write('lightingColorCtrl', {0x0004: {value: 0xffff, type: 0x21}}, manufacturerOptions);
|
|
321
|
+
}
|
|
322
|
+
} else if (value === 'on') {
|
|
323
|
+
await entity.write('genOnOff', {0x4003: {value: 0x01, type: 0x30}});
|
|
324
|
+
|
|
325
|
+
let brightness = meta.message.hasOwnProperty('hue_power_on_brightness') ?
|
|
326
|
+
meta.message.hue_power_on_brightness : 0xfe;
|
|
327
|
+
if (brightness === 255) {
|
|
328
|
+
// 255 (0xFF) is the value for recover, therefore set it to 254 (0xFE)
|
|
329
|
+
brightness = 254;
|
|
330
|
+
}
|
|
331
|
+
await entity.write('genLevelCtrl', {0x4000: {value: brightness, type: 0x20}});
|
|
332
|
+
|
|
333
|
+
if (entity.supportsInputCluster('lightingColorCtrl')) {
|
|
334
|
+
if (
|
|
335
|
+
meta.message.hasOwnProperty('hue_power_on_color_temperature') &&
|
|
336
|
+
meta.message.hasOwnProperty('hue_power_on_color')
|
|
337
|
+
) {
|
|
338
|
+
meta.logger.error(`Provide either color temperature or color, not both`);
|
|
339
|
+
} else if (meta.message.hasOwnProperty('hue_power_on_color_temperature')) {
|
|
340
|
+
const colortemp = meta.message.hue_power_on_color_temperature;
|
|
341
|
+
await entity.write('lightingColorCtrl', {0x4010: {value: colortemp, type: 0x21}});
|
|
342
|
+
// Set color to default
|
|
343
|
+
if (supports.colorXY) {
|
|
344
|
+
await entity.write('lightingColorCtrl', {0x0003: {value: 0xFFFF, type: 0x21}}, manufacturerOptions);
|
|
345
|
+
await entity.write('lightingColorCtrl', {0x0004: {value: 0xFFFF, type: 0x21}}, manufacturerOptions);
|
|
346
|
+
}
|
|
347
|
+
} else if (meta.message.hasOwnProperty('hue_power_on_color')) {
|
|
348
|
+
const colorXY = libColor.ColorRGB.fromHex(meta.message.hue_power_on_color).toXY();
|
|
349
|
+
value = {x: utils.mapNumberRange(colorXY.x, 0, 1, 0, 65535), y: utils.mapNumberRange(colorXY.y, 0, 1, 0, 65535)};
|
|
350
|
+
|
|
351
|
+
// Set colortemp to default
|
|
352
|
+
if (supports.colorTemperature) {
|
|
353
|
+
await entity.write('lightingColorCtrl', {0x4010: {value: 366, type: 0x21}});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
await entity.write('lightingColorCtrl', {0x0003: {value: value.x, type: 0x21}}, manufacturerOptions);
|
|
357
|
+
await entity.write('lightingColorCtrl', {0x0004: {value: value.y, type: 0x21}}, manufacturerOptions);
|
|
358
|
+
} else {
|
|
359
|
+
// Set defaults for colortemp and color
|
|
360
|
+
if (supports.colorTemperature) {
|
|
361
|
+
await entity.write('lightingColorCtrl', {0x4010: {value: 366, type: 0x21}});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (supports.colorXY) {
|
|
365
|
+
await entity.write('lightingColorCtrl', {0x0003: {value: 0xFFFF, type: 0x21}}, manufacturerOptions);
|
|
366
|
+
await entity.write('lightingColorCtrl', {0x0004: {value: 0xFFFF, type: 0x21}}, manufacturerOptions);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return {state: {hue_power_on_behavior: value}};
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
hue_power_on_error: {
|
|
376
|
+
key: ['hue_power_on_brightness', 'hue_power_on_color_temperature', 'hue_power_on_color'],
|
|
377
|
+
convertSet: async (entity, key, value, meta) => {
|
|
378
|
+
if (!meta.message.hasOwnProperty('hue_power_on_behavior')) {
|
|
379
|
+
throw new Error(`Provide a value for 'hue_power_on_behavior'`);
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
hue_motion_sensitivity: {
|
|
384
|
+
// motion detect sensitivity, philips specific
|
|
385
|
+
key: ['motion_sensitivity'],
|
|
386
|
+
convertSet: async (entity, key, value, meta) => {
|
|
387
|
+
// make sure you write to second endpoint!
|
|
388
|
+
const lookup = {'low': 0, 'medium': 1, 'high': 2, 'very_high': 3, 'max': 4};
|
|
389
|
+
value = value.toLowerCase();
|
|
390
|
+
utils.validateValue(value, Object.keys(lookup));
|
|
391
|
+
|
|
392
|
+
const payload = {48: {value: lookup[value], type: 32}};
|
|
393
|
+
await entity.write('msOccupancySensing', payload, manufacturerOptions);
|
|
394
|
+
return {state: {motion_sensitivity: value}};
|
|
395
|
+
},
|
|
396
|
+
convertGet: async (entity, key, meta) => {
|
|
397
|
+
await entity.read('msOccupancySensing', [48], manufacturerOptions);
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
hue_motion_led_indication: {
|
|
401
|
+
key: ['led_indication'],
|
|
402
|
+
convertSet: async (entity, key, value, meta) => {
|
|
403
|
+
const payload = {0x0033: {value, type: 0x10}};
|
|
404
|
+
await entity.write('genBasic', payload, manufacturerOptions);
|
|
405
|
+
return {state: {led_indication: value}};
|
|
406
|
+
},
|
|
407
|
+
convertGet: async (entity, key, meta) => {
|
|
408
|
+
await entity.read('genBasic', [0x0033], manufacturerOptions);
|
|
409
|
+
},
|
|
410
|
+
},
|
|
229
411
|
};
|
|
230
412
|
|
|
231
413
|
module.exports = [
|
|
@@ -787,7 +969,9 @@ module.exports = [
|
|
|
787
969
|
model: '929001953101',
|
|
788
970
|
vendor: 'Philips',
|
|
789
971
|
description: 'Hue White and Color Ambiance GU10',
|
|
790
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color(
|
|
972
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({
|
|
973
|
+
colorTempRange: [153, 500], disableHueEffects: false,
|
|
974
|
+
}),
|
|
791
975
|
},
|
|
792
976
|
{
|
|
793
977
|
zigbeeModel: ['LWA003', 'LWW002'],
|
|
@@ -1039,35 +1223,37 @@ module.exports = [
|
|
|
1039
1223
|
model: '9290022166',
|
|
1040
1224
|
vendor: 'Philips',
|
|
1041
1225
|
description: 'Hue white and color ambiance E26/E27',
|
|
1042
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color(),
|
|
1226
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
|
|
1043
1227
|
},
|
|
1044
1228
|
{
|
|
1045
1229
|
zigbeeModel: ['LCA004'],
|
|
1046
1230
|
model: '9290024896',
|
|
1047
1231
|
vendor: 'Philips',
|
|
1048
1232
|
description: 'Hue white and color ambiance E27',
|
|
1049
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
1233
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
|
|
1050
1234
|
},
|
|
1051
1235
|
{
|
|
1052
1236
|
zigbeeModel: ['LCA006'],
|
|
1053
1237
|
model: '9290024689',
|
|
1054
1238
|
vendor: 'Philips',
|
|
1055
1239
|
description: 'Hue white and color ambiance B22 1100lm',
|
|
1056
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
1240
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
|
|
1057
1241
|
},
|
|
1058
1242
|
{
|
|
1059
1243
|
zigbeeModel: ['LCA008'],
|
|
1060
1244
|
model: '929002471601',
|
|
1061
1245
|
vendor: 'Philips',
|
|
1062
1246
|
description: 'Hue white and color ambiance E26/E27 1600lm',
|
|
1063
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color({
|
|
1247
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({
|
|
1248
|
+
colorTempRange: [153, 500], disableHueEffects: false,
|
|
1249
|
+
}),
|
|
1064
1250
|
},
|
|
1065
1251
|
{
|
|
1066
1252
|
zigbeeModel: ['LCA009'],
|
|
1067
1253
|
model: '9290024717',
|
|
1068
1254
|
vendor: 'Philips',
|
|
1069
1255
|
description: 'Hue white and color ambiance E26/A19 1600lm',
|
|
1070
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
1256
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
|
|
1071
1257
|
},
|
|
1072
1258
|
{
|
|
1073
1259
|
zigbeeModel: ['LCT001', 'LCT007', 'LCT010', 'LCT012', 'LCT014', 'LCT015', 'LCT016', 'LCT021'],
|
|
@@ -1179,7 +1365,7 @@ module.exports = [
|
|
|
1179
1365
|
model: '929001953301',
|
|
1180
1366
|
vendor: 'Philips',
|
|
1181
1367
|
description: 'Hue white ambiance GU10 with Bluetooth',
|
|
1182
|
-
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153,
|
|
1368
|
+
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], disableHueEffects: false}),
|
|
1183
1369
|
},
|
|
1184
1370
|
{
|
|
1185
1371
|
zigbeeModel: ['LTD005'],
|
|
@@ -1741,6 +1927,13 @@ module.exports = [
|
|
|
1741
1927
|
description: 'Hue Gradient Signe floor lamp (black)',
|
|
1742
1928
|
extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
|
|
1743
1929
|
},
|
|
1930
|
+
{
|
|
1931
|
+
zigbeeModel: ['915005987501'],
|
|
1932
|
+
model: '915005987501',
|
|
1933
|
+
vendor: 'Philips',
|
|
1934
|
+
description: 'Hue Gradient Signe floor lamp (white)',
|
|
1935
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
|
|
1936
|
+
},
|
|
1744
1937
|
{
|
|
1745
1938
|
zigbeeModel: ['LCT020'],
|
|
1746
1939
|
model: '4080148P7',
|
|
@@ -2039,7 +2232,7 @@ module.exports = [
|
|
|
2039
2232
|
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
|
|
2040
2233
|
exposes.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'),
|
|
2041
2234
|
exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(65535)],
|
|
2042
|
-
toZigbee: [tz.occupancy_timeout,
|
|
2235
|
+
toZigbee: [tz.occupancy_timeout, tzLocal.hue_motion_sensitivity, tzLocal.hue_motion_led_indication],
|
|
2043
2236
|
endpoint: (device) => {
|
|
2044
2237
|
return {'default': 2, 'ep1': 1, 'ep2': 2};
|
|
2045
2238
|
},
|
|
@@ -2068,7 +2261,7 @@ module.exports = [
|
|
|
2068
2261
|
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
|
|
2069
2262
|
exposes.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'),
|
|
2070
2263
|
exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(65535)],
|
|
2071
|
-
toZigbee: [tz.occupancy_timeout,
|
|
2264
|
+
toZigbee: [tz.occupancy_timeout, tzLocal.hue_motion_sensitivity, tzLocal.hue_motion_led_indication],
|
|
2072
2265
|
endpoint: (device) => {
|
|
2073
2266
|
return {'default': 2, 'ep1': 1, 'ep2': 2};
|
|
2074
2267
|
},
|
|
@@ -2097,7 +2290,7 @@ module.exports = [
|
|
|
2097
2290
|
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high', 'very_high', 'max']),
|
|
2098
2291
|
exposes.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'),
|
|
2099
2292
|
exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(65535)],
|
|
2100
|
-
toZigbee: [tz.occupancy_timeout,
|
|
2293
|
+
toZigbee: [tz.occupancy_timeout, tzLocal.hue_motion_sensitivity, tzLocal.hue_motion_led_indication],
|
|
2101
2294
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2102
2295
|
const endpoint = device.getEndpoint(2);
|
|
2103
2296
|
const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing'];
|
|
@@ -2123,7 +2316,7 @@ module.exports = [
|
|
|
2123
2316
|
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high', 'very_high', 'max']),
|
|
2124
2317
|
exposes.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'),
|
|
2125
2318
|
exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(65535)],
|
|
2126
|
-
toZigbee: [tz.occupancy_timeout,
|
|
2319
|
+
toZigbee: [tz.occupancy_timeout, tzLocal.hue_motion_sensitivity, tzLocal.hue_motion_led_indication],
|
|
2127
2320
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2128
2321
|
const endpoint = device.getEndpoint(2);
|
|
2129
2322
|
const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing'];
|
|
@@ -2144,7 +2337,7 @@ module.exports = [
|
|
|
2144
2337
|
vendor: 'Philips',
|
|
2145
2338
|
description: 'Hue smart plug - EU',
|
|
2146
2339
|
extend: extend.switch(),
|
|
2147
|
-
toZigbee: [tz.on_off].concat([
|
|
2340
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2148
2341
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2149
2342
|
const endpoint = device.getEndpoint(11);
|
|
2150
2343
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2158,7 +2351,7 @@ module.exports = [
|
|
|
2158
2351
|
vendor: 'Philips',
|
|
2159
2352
|
description: 'Hue smart plug bluetooth',
|
|
2160
2353
|
extend: extend.switch(),
|
|
2161
|
-
toZigbee: [tz.on_off].concat([
|
|
2354
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2162
2355
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2163
2356
|
const endpoint = device.getEndpoint(11);
|
|
2164
2357
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2172,7 +2365,7 @@ module.exports = [
|
|
|
2172
2365
|
vendor: 'Philips',
|
|
2173
2366
|
description: 'Hue smart plug - UK',
|
|
2174
2367
|
extend: extend.switch(),
|
|
2175
|
-
toZigbee: [tz.on_off].concat([
|
|
2368
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2176
2369
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2177
2370
|
const endpoint = device.getEndpoint(11);
|
|
2178
2371
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2186,7 +2379,7 @@ module.exports = [
|
|
|
2186
2379
|
vendor: 'Philips',
|
|
2187
2380
|
description: 'Hue smart plug - AU',
|
|
2188
2381
|
extend: extend.switch(),
|
|
2189
|
-
toZigbee: [tz.on_off].concat([
|
|
2382
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2190
2383
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2191
2384
|
const endpoint = device.getEndpoint(11);
|
|
2192
2385
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2200,7 +2393,7 @@ module.exports = [
|
|
|
2200
2393
|
vendor: 'Philips',
|
|
2201
2394
|
description: 'Hue smart plug - AU',
|
|
2202
2395
|
extend: extend.switch(),
|
|
2203
|
-
toZigbee: [tz.on_off].concat([
|
|
2396
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2204
2397
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2205
2398
|
const endpoint = device.getEndpoint(11);
|
|
2206
2399
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2214,7 +2407,7 @@ module.exports = [
|
|
|
2214
2407
|
vendor: 'Philips',
|
|
2215
2408
|
description: 'Hue smart plug - CH',
|
|
2216
2409
|
extend: extend.switch(),
|
|
2217
|
-
toZigbee: [tz.on_off].concat([
|
|
2410
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2218
2411
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2219
2412
|
const endpoint = device.getEndpoint(11);
|
|
2220
2413
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2228,7 +2421,7 @@ module.exports = [
|
|
|
2228
2421
|
vendor: 'Philips',
|
|
2229
2422
|
description: 'Hue smart plug',
|
|
2230
2423
|
extend: extend.switch(),
|
|
2231
|
-
toZigbee: [tz.on_off].concat([
|
|
2424
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2232
2425
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2233
2426
|
const endpoint = device.getEndpoint(11);
|
|
2234
2427
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2242,7 +2435,7 @@ module.exports = [
|
|
|
2242
2435
|
vendor: 'Philips',
|
|
2243
2436
|
description: 'Hue smart plug - EU',
|
|
2244
2437
|
extend: extend.switch(),
|
|
2245
|
-
toZigbee: [tz.on_off].concat([
|
|
2438
|
+
toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
|
|
2246
2439
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2247
2440
|
const endpoint = device.getEndpoint(11);
|
|
2248
2441
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
@@ -2626,7 +2819,7 @@ module.exports = [
|
|
|
2626
2819
|
model: '9290024687',
|
|
2627
2820
|
vendor: 'Philips',
|
|
2628
2821
|
description: 'Hue White and Color Ambiance A19 1100 lumen',
|
|
2629
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
2822
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
|
|
2630
2823
|
},
|
|
2631
2824
|
{
|
|
2632
2825
|
zigbeeModel: ['RDM002'],
|
|
@@ -2665,7 +2858,7 @@ module.exports = [
|
|
|
2665
2858
|
model: '9290022266A',
|
|
2666
2859
|
vendor: 'Philips',
|
|
2667
2860
|
description: 'Hue White and color ambiance A19 800 lumen',
|
|
2668
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
2861
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
|
|
2669
2862
|
},
|
|
2670
2863
|
{
|
|
2671
2864
|
zigbeeModel: ['LWE003'],
|
|
@@ -3022,7 +3215,7 @@ module.exports = [
|
|
|
3022
3215
|
model: '929003535301',
|
|
3023
3216
|
vendor: 'Philips',
|
|
3024
3217
|
description: 'Hue Festavia gradient light string 250',
|
|
3025
|
-
extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
|
|
3218
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500], extraEffects: ['sparkle']}),
|
|
3026
3219
|
},
|
|
3027
3220
|
{
|
|
3028
3221
|
zigbeeModel: ['915005987101'],
|
package/devices/sinope.js
CHANGED
|
@@ -584,7 +584,7 @@ module.exports = [
|
|
|
584
584
|
'genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg',
|
|
585
585
|
'msTemperatureMeasurement', 'haElectricalMeasurement', 'seMetering',
|
|
586
586
|
'manuSpecificSinope'];
|
|
587
|
-
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
587
|
+
await reporting.bind(endpoint, coordinatorEndpoint, binds); // This G2 version has limited memory space
|
|
588
588
|
const thermostatDate = new Date();
|
|
589
589
|
const thermostatTimeSec = thermostatDate.getTime() / 1000;
|
|
590
590
|
const thermostatTimezoneOffsetSec = thermostatDate.getTimezoneOffset() * 60;
|
|
@@ -607,6 +607,9 @@ module.exports = [
|
|
|
607
607
|
await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 1: 1W
|
|
608
608
|
await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 100}); // divider 1000: 0.1Arms
|
|
609
609
|
await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 5}); // divider 10: 0.5Vrms
|
|
610
|
+
|
|
611
|
+
// Disable default reporting (not used by Sinope)
|
|
612
|
+
await reporting.thermostatRunningState(endpoint, {min: 1, max: 0xFFFF});
|
|
610
613
|
try {
|
|
611
614
|
await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
|
|
612
615
|
} catch (error) {/* Do nothing */}
|
package/devices/tuya.js
CHANGED
|
@@ -1144,7 +1144,7 @@ module.exports = [
|
|
|
1144
1144
|
configure: tuya.configureMagicPacket,
|
|
1145
1145
|
},
|
|
1146
1146
|
{
|
|
1147
|
-
fingerprint: tuya.fingerprint('TS0202', ['_TZ3000_mcxw5ehu', '_TZ3040_6ygjfyll']),
|
|
1147
|
+
fingerprint: tuya.fingerprint('TS0202', ['_TZ3000_mcxw5ehu', '_TZ3000_6ygjfyll', '_TZ3040_6ygjfyll']),
|
|
1148
1148
|
model: 'IH012-RT01',
|
|
1149
1149
|
vendor: 'TuYa',
|
|
1150
1150
|
description: 'Motion sensor',
|
|
@@ -1345,6 +1345,30 @@ module.exports = [
|
|
|
1345
1345
|
{vendor: 'Moes', model: 'ZS-EUD_3gang'},
|
|
1346
1346
|
],
|
|
1347
1347
|
},
|
|
1348
|
+
{
|
|
1349
|
+
fingerprint: tuya.fingerprint('TS0601', ['_TZE200_p0gzbqct']),
|
|
1350
|
+
model: 'TS0601_dimmer_knob',
|
|
1351
|
+
vendor: 'TuYa',
|
|
1352
|
+
description: 'Zigbee smart knob dimmer',
|
|
1353
|
+
fromZigbee: [tuya.fz.datapoints],
|
|
1354
|
+
toZigbee: [tuya.tz.datapoints],
|
|
1355
|
+
configure: tuya.configureMagicPacket,
|
|
1356
|
+
exposes: [tuya.exposes.lightBrightness().withMinBrightness().setAccess('min_brightness', ea.STATE_SET), tuya.exposes.lightType(),
|
|
1357
|
+
tuya.exposes.indicatorModeNoneRelayPos()],
|
|
1358
|
+
meta: {
|
|
1359
|
+
tuyaDatapoints: [
|
|
1360
|
+
[1, 'state', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
|
|
1361
|
+
[2, 'brightness', tuya.valueConverter.scale0_254to0_1000],
|
|
1362
|
+
[3, 'min_brightness', tuya.valueConverter.scale0_254to0_1000],
|
|
1363
|
+
[4, 'light_type', tuya.valueConverter.lightType],
|
|
1364
|
+
[21, 'indicator_mode', tuya.valueConverterBasic.lookup({0: 'none', 1: 'relay', 2: 'pos'})],
|
|
1365
|
+
],
|
|
1366
|
+
},
|
|
1367
|
+
whiteLabel: [
|
|
1368
|
+
{vendor: 'Moes', model: 'WS-SY-EURD'},
|
|
1369
|
+
{vendor: 'Moes', model: 'WS-SY-EURD-WH-MS'},
|
|
1370
|
+
],
|
|
1371
|
+
},
|
|
1348
1372
|
{
|
|
1349
1373
|
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_oiymh3qu'}],
|
|
1350
1374
|
model: 'TS011F_socket_module',
|
|
@@ -1644,7 +1668,6 @@ module.exports = [
|
|
|
1644
1668
|
{modelID: 'TS0201', manufacturerName: '_TZ3000_6uzkisv2'},
|
|
1645
1669
|
{modelID: 'TS0201', manufacturerName: '_TZ3000_xr3htd96'},
|
|
1646
1670
|
{modelID: 'TS0601', manufacturerName: '_TZE200_9yapgbuv'},
|
|
1647
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_yjjdcqsq'},
|
|
1648
1671
|
],
|
|
1649
1672
|
model: 'WSD500A',
|
|
1650
1673
|
vendor: 'TuYa',
|
|
@@ -2515,6 +2538,30 @@ module.exports = [
|
|
|
2515
2538
|
],
|
|
2516
2539
|
},
|
|
2517
2540
|
},
|
|
2541
|
+
{
|
|
2542
|
+
fingerprint: tuya.fingerprint('TS0601', ['_TZE200_m9skfctm']),
|
|
2543
|
+
model: 'TS0601_smoke_2',
|
|
2544
|
+
vendor: 'TuYa',
|
|
2545
|
+
description: 'Photoelectric smoke detector',
|
|
2546
|
+
fromZigbee: [tuya.fz.datapoints],
|
|
2547
|
+
toZigbee: [tuya.tz.datapoints],
|
|
2548
|
+
onEvent: tuya.onEventSetTime,
|
|
2549
|
+
configure: tuya.configureMagicPacket,
|
|
2550
|
+
exposes: [
|
|
2551
|
+
e.smoke(), e.battery(), e.test(),
|
|
2552
|
+
exposes.numeric('smoke_concentration', ea.STATE).withUnit('ppm').withDescription('Parts per million of smoke detected'),
|
|
2553
|
+
exposes.binary('device_fault', ea.STATE, true, false).withDescription('Indicates a fault with the device'),
|
|
2554
|
+
],
|
|
2555
|
+
meta: {
|
|
2556
|
+
tuyaDatapoints: [
|
|
2557
|
+
[1, 'smoke', tuya.valueConverter.true0ElseFalse],
|
|
2558
|
+
[2, 'smoke_concentration', tuya.valueConverter.divideBy10],
|
|
2559
|
+
[11, 'device_fault', tuya.valueConverter.raw],
|
|
2560
|
+
[15, 'battery', tuya.valueConverter.raw],
|
|
2561
|
+
[101, 'test', tuya.valueConverter.raw],
|
|
2562
|
+
],
|
|
2563
|
+
},
|
|
2564
|
+
},
|
|
2518
2565
|
{
|
|
2519
2566
|
zigbeeModel: ['5p1vj8r'],
|
|
2520
2567
|
fingerprint: tuya.fingerprint('TS0601', ['_TZE200_t5p1vj8r', '_TZE200_uebojraa', '_TZE200_vzekyi4c', '_TZE200_yh7aoahi',
|
|
@@ -2548,6 +2595,24 @@ module.exports = [
|
|
|
2548
2595
|
exposes.binary('silence_siren', ea.STATE_SET, true, false).withDescription('Silence the siren')],
|
|
2549
2596
|
onEvent: tuya.onEventsetTime,
|
|
2550
2597
|
},
|
|
2598
|
+
{
|
|
2599
|
+
fingerprint: tuya.fingerprint('TS0601', ['_TZE204_cjbofhxw']),
|
|
2600
|
+
model: 'TS0601_clamp_meter',
|
|
2601
|
+
vendor: 'TuYa',
|
|
2602
|
+
description: 'Clamp meter',
|
|
2603
|
+
fromZigbee: [tuya.fz.datapoints, tuya.fz.gateway_connection_status],
|
|
2604
|
+
toZigbee: [tuya.tz.datapoints],
|
|
2605
|
+
configure: tuya.configureMagicPacket,
|
|
2606
|
+
exposes: [e.current(), e.power(), e.voltage(), e.energy()],
|
|
2607
|
+
meta: {
|
|
2608
|
+
tuyaDatapoints: [
|
|
2609
|
+
[18, 'current', tuya.valueConverter.divideBy1000],
|
|
2610
|
+
[19, 'power', tuya.valueConverter.divideBy10],
|
|
2611
|
+
[20, 'voltage', tuya.valueConverter.divideBy10],
|
|
2612
|
+
[101, 'energy', tuya.valueConverter.divideBy1000],
|
|
2613
|
+
],
|
|
2614
|
+
},
|
|
2615
|
+
},
|
|
2551
2616
|
{
|
|
2552
2617
|
fingerprint: tuya.fingerprint('TS0601', ['_TZE200_bkkmqmyo', '_TZE200_eaac7dkw']),
|
|
2553
2618
|
model: 'TS0601_din_1',
|
package/devices/ubisys.js
CHANGED
|
@@ -17,7 +17,6 @@ const manufacturerOptions = {
|
|
|
17
17
|
*/
|
|
18
18
|
ubisys: {manufacturerCode: herdsman.Zcl.ManufacturerCode.UBISYS},
|
|
19
19
|
ubisysNull: {manufacturerCode: null},
|
|
20
|
-
tint: {manufacturerCode: herdsman.Zcl.ManufacturerCode.MUELLER_LICHT_INT},
|
|
21
20
|
};
|
|
22
21
|
|
|
23
22
|
const ubisysOnEventReadCurrentSummDelivered = async function(type, data, devic) {
|
package/lib/ota/common.js
CHANGED
|
@@ -27,7 +27,6 @@ const eblImageSignature = 0xe350;
|
|
|
27
27
|
|
|
28
28
|
const gblTagHeader = 0xeb17a603;
|
|
29
29
|
const gblTagEnd = 0xfc0404fc;
|
|
30
|
-
const gblPadding = 0x0;
|
|
31
30
|
|
|
32
31
|
function getOTAEndpoint(device) {
|
|
33
32
|
return device.endpoints.find((e) => e.supportsOutputCluster('genOta'));
|
|
@@ -145,10 +144,6 @@ function validateSilabsGbl(data) {
|
|
|
145
144
|
continue;
|
|
146
145
|
}
|
|
147
146
|
|
|
148
|
-
for (let position2 = position; position2 < dataLength; position2++) {
|
|
149
|
-
assert(data.readUInt8(position2) === gblPadding, `Image padding contains invalid bytes`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
147
|
const calculatedCrc32 = crc32.unsigned(data.slice(0, position));
|
|
153
148
|
|
|
154
149
|
assert(calculatedCrc32 === validSilabsCrc, `Image CRC-32 is invalid`);
|
package/lib/tuya.js
CHANGED
|
@@ -1163,6 +1163,8 @@ const tuyaExposes = {
|
|
|
1163
1163
|
backlightModeOffNormalInverted: () => exposes.enum('backlight_mode', ea.ALL, ['off', 'normal', 'inverted'])
|
|
1164
1164
|
.withDescription('Mode of the backlight'),
|
|
1165
1165
|
indicatorMode: () => exposes.enum('indicator_mode', ea.ALL, ['off', 'off/on', 'on/off', 'on']).withDescription('LED indicator mode'),
|
|
1166
|
+
indicatorModeNoneRelayPos: () => exposes.enum('indicator_mode', ea.ALL, ['none', 'relay', 'pos'])
|
|
1167
|
+
.withDescription('Mode of the indicator light'),
|
|
1166
1168
|
powerOutageMemory: () => exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
|
|
1167
1169
|
.withDescription('Recover state after power outage'),
|
|
1168
1170
|
batteryState: () => exposes.enum('battery_state', ea.STATE, ['low', 'medium', 'high']).withDescription('State of the battery'),
|
|
@@ -1616,6 +1618,18 @@ const tuyaTz = {
|
|
|
1616
1618
|
};
|
|
1617
1619
|
|
|
1618
1620
|
const tuyaFz = {
|
|
1621
|
+
gateway_connection_status: {
|
|
1622
|
+
cluster: 'manuSpecificTuya',
|
|
1623
|
+
type: ['commandMcuGatewayConnectionStatus'],
|
|
1624
|
+
convert: async (model, msg, publish, options, meta) => {
|
|
1625
|
+
// "payload" can have the following values:
|
|
1626
|
+
// 0x00: The gateway is not connected to the internet.
|
|
1627
|
+
// 0x01: The gateway is connected to the internet.
|
|
1628
|
+
// 0x02: The request timed out after three seconds.
|
|
1629
|
+
const payload = {payloadSize: 1, payload: 1};
|
|
1630
|
+
await msg.endpoint.command('manuSpecificTuya', 'mcuGatewayConnectionStatus', payload, {});
|
|
1631
|
+
},
|
|
1632
|
+
},
|
|
1619
1633
|
power_on_behavior: {
|
|
1620
1634
|
cluster: 'genOnOff',
|
|
1621
1635
|
type: ['attributeReport', 'readResponse'],
|