zigbee-herdsman-converters 14.0.494 → 14.0.497
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 +71 -0
- package/converters/toZigbee.js +122 -0
- package/devices/ikea.js +4 -4
- package/devices/innr.js +12 -0
- package/devices/keen_home.js +1 -1
- package/devices/lonsonho.js +1 -1
- package/devices/namron.js +166 -12
- package/devices/niko.js +60 -18
- package/devices/orvibo.js +7 -0
- package/devices/prolight.js +10 -3
- package/devices/sinope.js +16 -0
- package/devices/tuya.js +2 -1
- package/devices/woox.js +81 -3
- package/lib/ota/OTA_URLs.md +13 -1
- package/lib/tuya.js +2 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -1652,6 +1652,77 @@ const converters = {
|
|
|
1652
1652
|
// #endregion
|
|
1653
1653
|
|
|
1654
1654
|
// #region Non-generic converters
|
|
1655
|
+
namron_thermostat: {
|
|
1656
|
+
cluster: 'hvacThermostat',
|
|
1657
|
+
type: ['attributeReport', 'readResponse'],
|
|
1658
|
+
convert: (model, msg, publish, options, meta) => {
|
|
1659
|
+
const result = {};
|
|
1660
|
+
const data = msg.data;
|
|
1661
|
+
if (data.hasOwnProperty(0x1000)) { // Display brightness
|
|
1662
|
+
const lookup = {0: 'low', 1: 'mid', 2: 'high'};
|
|
1663
|
+
result.lcd_brightness = lookup[data[0x1000]];
|
|
1664
|
+
}
|
|
1665
|
+
if (data.hasOwnProperty(0x1001)) { // Button vibration level
|
|
1666
|
+
const lookup = {0: 'off', 1: 'low', 2: 'high'};
|
|
1667
|
+
result.button_vibration_level = lookup[data[0x1001]];
|
|
1668
|
+
}
|
|
1669
|
+
if (data.hasOwnProperty(0x1002)) { // Floor sensor type
|
|
1670
|
+
const lookup = {1: '10k', 2: '15k', 3: '50k', 4: '100k', 5: '12k'};
|
|
1671
|
+
result.floor_sensor_type = lookup[data[0x1002]];
|
|
1672
|
+
}
|
|
1673
|
+
if (data.hasOwnProperty(0x1003)) { // Sensor
|
|
1674
|
+
const lookup = {0: 'air', 1: 'floor', 2: 'both'};
|
|
1675
|
+
result.sensor = lookup[data[0x1003]];
|
|
1676
|
+
}
|
|
1677
|
+
if (data.hasOwnProperty(0x1004)) { // PowerUpStatus
|
|
1678
|
+
const lookup = {0: 'default', 1: 'last_status'};
|
|
1679
|
+
result.powerup_status = lookup[data[0x1004]];
|
|
1680
|
+
}
|
|
1681
|
+
if (data.hasOwnProperty(0x1005)) { // FloorSensorCalibration
|
|
1682
|
+
result.floor_sensor_calibration = precisionRound(data[0x1005], 2) / 10;
|
|
1683
|
+
}
|
|
1684
|
+
if (data.hasOwnProperty(0x1006)) { // DryTime
|
|
1685
|
+
result.dry_time = data[0x1006];
|
|
1686
|
+
}
|
|
1687
|
+
if (data.hasOwnProperty(0x1007)) { // ModeAfterDry
|
|
1688
|
+
const lookup = {0: 'off', 1: 'manual', 2: 'auto', 3: 'away'};
|
|
1689
|
+
result.mode_after_dry = lookup[data[0x1007]];
|
|
1690
|
+
}
|
|
1691
|
+
if (data.hasOwnProperty(0x1008)) { // TemperatureDisplay
|
|
1692
|
+
const lookup = {0: 'room', 1: 'floor'};
|
|
1693
|
+
result.temperature_display = lookup[data[0x1008]];
|
|
1694
|
+
}
|
|
1695
|
+
if (data.hasOwnProperty(0x1009)) { // WindowOpenCheck
|
|
1696
|
+
result.window_open_check = data[0x1009];
|
|
1697
|
+
}
|
|
1698
|
+
if (data.hasOwnProperty(0x100A)) { // Hysterersis
|
|
1699
|
+
result.hysterersis = data[0x100A];
|
|
1700
|
+
}
|
|
1701
|
+
if (data.hasOwnProperty(0x100B)) { // DisplayAutoOffEnable
|
|
1702
|
+
const lookup = {0: 'enable', 1: 'disable'};
|
|
1703
|
+
result.display_auto_off_enabled = lookup[data[0x100B]];
|
|
1704
|
+
}
|
|
1705
|
+
if (data.hasOwnProperty(0x2001)) { // AlarmAirTempOverValue
|
|
1706
|
+
result.alarm_airtemp_overvalue = data[0x2001];
|
|
1707
|
+
}
|
|
1708
|
+
if (data.hasOwnProperty(0x2002)) { // Away Mode Set
|
|
1709
|
+
result.away_mode = data[0x2002] ? 'ON' : 'OFF';
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
return result;
|
|
1713
|
+
},
|
|
1714
|
+
},
|
|
1715
|
+
namron_hvac_user_interface: {
|
|
1716
|
+
cluster: 'hvacUserInterfaceCfg',
|
|
1717
|
+
type: ['attributeReport', 'readResponse'],
|
|
1718
|
+
convert: (model, msg, publish, options, meta) => {
|
|
1719
|
+
const result = {};
|
|
1720
|
+
if (msg.data.hasOwnProperty('keypadLockout')) { // Set as child lock instead as keypadlockout
|
|
1721
|
+
result.child_lock = msg.data['keypadLockout'] === 0 ? 'UNLOCK' : 'LOCK';
|
|
1722
|
+
}
|
|
1723
|
+
return result;
|
|
1724
|
+
},
|
|
1725
|
+
},
|
|
1655
1726
|
elko_thermostat: {
|
|
1656
1727
|
cluster: 'hvacThermostat',
|
|
1657
1728
|
type: ['attributeReport', 'readResponse'],
|
package/converters/toZigbee.js
CHANGED
|
@@ -11,6 +11,7 @@ const libColor = require('../lib/color');
|
|
|
11
11
|
const exposes = require('../lib/exposes');
|
|
12
12
|
|
|
13
13
|
const manufacturerOptions = {
|
|
14
|
+
sunricher: {manufacturerCode: herdsman.Zcl.ManufacturerCode.SHENZHEN_SUNRICH},
|
|
14
15
|
xiaomi: {manufacturerCode: herdsman.Zcl.ManufacturerCode.LUMI_UNITED_TECH, disableDefaultResponse: true},
|
|
15
16
|
osram: {manufacturerCode: herdsman.Zcl.ManufacturerCode.OSRAM},
|
|
16
17
|
eurotronic: {manufacturerCode: herdsman.Zcl.ManufacturerCode.JENNIC},
|
|
@@ -3005,6 +3006,127 @@ const converters = {
|
|
|
3005
3006
|
await entity.read('closuresWindowCovering', [isPosition ? 'currentPositionLiftPercentage' : 'currentPositionTiltPercentage']);
|
|
3006
3007
|
},
|
|
3007
3008
|
},
|
|
3009
|
+
namron_thermostat: {
|
|
3010
|
+
key: [
|
|
3011
|
+
'lcd_brightness', 'button_vibration_level', 'floor_sensor_type', 'sensor', 'powerup_status', 'floor_sensor_calibration',
|
|
3012
|
+
'dry_time', 'mode_after_dry', 'temperature_display', 'window_open_check', 'hysterersis', 'display_auto_off_enabled',
|
|
3013
|
+
'alarm_airtemp_overvalue', 'away_mode',
|
|
3014
|
+
],
|
|
3015
|
+
convertSet: async (entity, key, value, meta) => {
|
|
3016
|
+
if (key === 'lcd_brightness') {
|
|
3017
|
+
const lookup = {'low': 0, 'mid': 1, 'high': 2};
|
|
3018
|
+
const payload = {0x1000: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3019
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3020
|
+
} else if (key === 'button_vibration_level') {
|
|
3021
|
+
const lookup = {'off': 0, 'low': 1, 'high': 2};
|
|
3022
|
+
const payload = {0x1001: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3023
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3024
|
+
} else if (key === 'floor_sensor_type') {
|
|
3025
|
+
const lookup = {'10k': 1, '15k': 2, '50k': 3, '100k': 4, '12k': 5};
|
|
3026
|
+
const payload = {0x1002: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3027
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3028
|
+
} else if (key === 'sensor') {
|
|
3029
|
+
const lookup = {'air': 0, 'floor': 1, 'both': 2};
|
|
3030
|
+
const payload = {0x1003: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3031
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3032
|
+
} else if (key==='powerup_status') {
|
|
3033
|
+
const lookup = {'default': 0, 'last_status': 1};
|
|
3034
|
+
const payload = {0x1004: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3035
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3036
|
+
} else if (key==='floor_sensor_calibration') {
|
|
3037
|
+
const payload = {0x1005: {value: Math.round(value * 10), type: 0x28}}; // INT8S
|
|
3038
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3039
|
+
} else if (key==='dry_time') {
|
|
3040
|
+
const payload = {0x1006: {value: value, type: 0x20}}; // INT8U
|
|
3041
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3042
|
+
} else if (key==='mode_after_dry') {
|
|
3043
|
+
const lookup = {'off': 0, 'manual': 1, 'auto': 2, 'away': 3};
|
|
3044
|
+
const payload = {0x1007: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3045
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3046
|
+
} else if (key==='temperature_display') {
|
|
3047
|
+
const lookup = {'room': 0, 'floor': 1};
|
|
3048
|
+
const payload = {0x1008: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3049
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3050
|
+
} else if (key==='window_open_check') {
|
|
3051
|
+
const payload = {0x1009: {value: Math.round(value * 10), type: 0x20}};
|
|
3052
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3053
|
+
} else if (key==='hysterersis') {
|
|
3054
|
+
const payload = {0x100A: {value: Math.round(value * 10), type: 0x20}};
|
|
3055
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3056
|
+
} else if (key==='display_auto_off_enabled') {
|
|
3057
|
+
const lookup = {'enable': 0, 'disabled': 1};
|
|
3058
|
+
const payload = {0x100B: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3059
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3060
|
+
} else if (key==='alarm_airtemp_overvalue') {
|
|
3061
|
+
const payload = {0x2001: {value: value, type: 0x20}};
|
|
3062
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3063
|
+
} else if (key==='away_mode') {
|
|
3064
|
+
const payload = {0x2002: {value: Number(value==='ON'), type: 0x30}};
|
|
3065
|
+
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3066
|
+
}
|
|
3067
|
+
},
|
|
3068
|
+
convertGet: async (entity, key, meta) => {
|
|
3069
|
+
switch (key) {
|
|
3070
|
+
case 'lcd_brightness':
|
|
3071
|
+
await entity.read('hvacThermostat', [0x1000], manufacturerOptions.sunricher);
|
|
3072
|
+
break;
|
|
3073
|
+
case 'button_vibration_level':
|
|
3074
|
+
await entity.read('hvacThermostat', [0x1001], manufacturerOptions.sunricher);
|
|
3075
|
+
break;
|
|
3076
|
+
case 'floor_sensor_type':
|
|
3077
|
+
await entity.read('hvacThermostat', [0x1002], manufacturerOptions.sunricher);
|
|
3078
|
+
break;
|
|
3079
|
+
case 'sensor':
|
|
3080
|
+
await entity.read('hvacThermostat', [0x1003], manufacturerOptions.sunricher);
|
|
3081
|
+
break;
|
|
3082
|
+
case 'powerup_status':
|
|
3083
|
+
await entity.read('hvacThermostat', [0x1004], manufacturerOptions.sunricher);
|
|
3084
|
+
break;
|
|
3085
|
+
case 'floor_sensor_calibration':
|
|
3086
|
+
await entity.read('hvacThermostat', [0x1005], manufacturerOptions.sunricher);
|
|
3087
|
+
break;
|
|
3088
|
+
case 'dry_time':
|
|
3089
|
+
await entity.read('hvacThermostat', [0x1006], manufacturerOptions.sunricher);
|
|
3090
|
+
break;
|
|
3091
|
+
case 'mode_after_dry':
|
|
3092
|
+
await entity.read('hvacThermostat', [0x1007], manufacturerOptions.sunricher);
|
|
3093
|
+
break;
|
|
3094
|
+
case 'temperature_display':
|
|
3095
|
+
await entity.read('hvacThermostat', [0x1008], manufacturerOptions.sunricher);
|
|
3096
|
+
break;
|
|
3097
|
+
case 'window_open_check':
|
|
3098
|
+
await entity.read('hvacThermostat', [0x1009], manufacturerOptions.sunricher);
|
|
3099
|
+
break;
|
|
3100
|
+
case 'hysterersis':
|
|
3101
|
+
await entity.read('hvacThermostat', [0x100A], manufacturerOptions.sunricher);
|
|
3102
|
+
break;
|
|
3103
|
+
case 'display_auto_off_enabled':
|
|
3104
|
+
await entity.read('hvacThermostat', [0x100B], manufacturerOptions.sunricher);
|
|
3105
|
+
break;
|
|
3106
|
+
case 'alarm_airtemp_overvalue':
|
|
3107
|
+
await entity.read('hvacThermostat', [0x2001], manufacturerOptions.sunricher);
|
|
3108
|
+
break;
|
|
3109
|
+
case 'away_mode':
|
|
3110
|
+
await entity.read('hvacThermostat', [0x2002], manufacturerOptions.sunricher);
|
|
3111
|
+
break;
|
|
3112
|
+
|
|
3113
|
+
default: // Unknown key
|
|
3114
|
+
throw new Error(`Unhandled key toZigbee.namron_thermostat.convertGet ${key}`);
|
|
3115
|
+
}
|
|
3116
|
+
},
|
|
3117
|
+
|
|
3118
|
+
},
|
|
3119
|
+
namron_thermostat_child_lock: {
|
|
3120
|
+
key: ['child_lock'],
|
|
3121
|
+
convertSet: async (entity, key, value, meta) => {
|
|
3122
|
+
const keypadLockout = Number(value==='LOCK');
|
|
3123
|
+
await entity.write('hvacUserInterfaceCfg', {keypadLockout});
|
|
3124
|
+
return {readAfterWriteTime: 250, state: {child_lock: value}};
|
|
3125
|
+
},
|
|
3126
|
+
convertGet: async (entity, key, meta) => {
|
|
3127
|
+
await entity.read('hvacUserInterfaceCfg', ['keypadLockout']);
|
|
3128
|
+
},
|
|
3129
|
+
},
|
|
3008
3130
|
connecte_thermostat: {
|
|
3009
3131
|
key: [
|
|
3010
3132
|
'child_lock', 'current_heating_setpoint', 'local_temperature_calibration', 'max_temperature_protection', 'window_detection',
|
package/devices/ikea.js
CHANGED
|
@@ -279,10 +279,10 @@ module.exports = [
|
|
|
279
279
|
extend: tradfriExtend.light_onoff_brightness_colortemp(),
|
|
280
280
|
},
|
|
281
281
|
{
|
|
282
|
-
zigbeeModel: ['TRADFRIbulbE27WSglobeopal1055lm'],
|
|
282
|
+
zigbeeModel: ['TRADFRIbulbE27WSglobeopal1055lm', 'TRADFRIbulbE26WSglobeopal1100lm'],
|
|
283
283
|
model: 'LED2003G10',
|
|
284
284
|
vendor: 'IKEA',
|
|
285
|
-
description: 'TRADFRI LED bulb
|
|
285
|
+
description: 'TRADFRI LED bulb E26/27 1100/1055 lumen, dimmable, white spectrum, opal white',
|
|
286
286
|
extend: tradfriExtend.light_onoff_brightness_colortemp(),
|
|
287
287
|
},
|
|
288
288
|
{
|
|
@@ -796,10 +796,10 @@ module.exports = [
|
|
|
796
796
|
extend: tradfriExtend.light_onoff_brightness(),
|
|
797
797
|
},
|
|
798
798
|
{
|
|
799
|
-
zigbeeModel: ['TRADFRIbulbGU10WS345lm', 'TRADFRI bulb GU10 WW 345lm'],
|
|
799
|
+
zigbeeModel: ['TRADFRIbulbGU10WS345lm', 'TRADFRI bulb GU10 WW 345lm', 'TRADFRIbulbGU10WS380lm'],
|
|
800
800
|
model: 'LED2005R5',
|
|
801
801
|
vendor: 'IKEA',
|
|
802
|
-
description: 'TRADFRI LED bulb GU10 345 lumen, dimmable, white spectrum',
|
|
802
|
+
description: 'TRADFRI LED bulb GU10 345/380 lumen, dimmable, white spectrum',
|
|
803
803
|
extend: tradfriExtend.light_onoff_brightness_colortemp(),
|
|
804
804
|
},
|
|
805
805
|
{
|
package/devices/innr.js
CHANGED
|
@@ -497,6 +497,18 @@ module.exports = [
|
|
|
497
497
|
},
|
|
498
498
|
exposes: [e.power(), e.current(), e.voltage().withAccess(ea.STATE), e.switch(), e.energy()],
|
|
499
499
|
},
|
|
500
|
+
{
|
|
501
|
+
zigbeeModel: ['SP 110'],
|
|
502
|
+
model: 'SP 110',
|
|
503
|
+
vendor: 'Innr',
|
|
504
|
+
description: 'Smart plug',
|
|
505
|
+
extend: extend.switch(),
|
|
506
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
507
|
+
const endpoint = device.getEndpoint(1);
|
|
508
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
509
|
+
await reporting.onOff(endpoint);
|
|
510
|
+
},
|
|
511
|
+
},
|
|
500
512
|
{
|
|
501
513
|
zigbeeModel: ['SP 220'],
|
|
502
514
|
model: 'SP 220',
|
package/devices/keen_home.js
CHANGED
|
@@ -41,7 +41,7 @@ module.exports = [
|
|
|
41
41
|
exposes: [e.cover_position().setAccess('state', ea.ALL), e.temperature(), e.battery(), e.pressure()],
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
|
-
zigbeeModel: ['SV02-410-MP-1.3', 'SV02-412-MP-1.3', 'SV02-610-MP-1.3', 'SV02-612-MP-1.3', 'SV02-410-MP-1.0'],
|
|
44
|
+
zigbeeModel: ['SV02-410-MP-1.3', 'SV02-412-MP-1.3', 'SV02-610-MP-1.3', 'SV02-612-MP-1.3', 'SV02-410-MP-1.0', 'SV02-410-MP-1.2'],
|
|
45
45
|
model: 'SV02',
|
|
46
46
|
vendor: 'Keen Home',
|
|
47
47
|
description: 'Smart vent',
|
package/devices/lonsonho.js
CHANGED
|
@@ -127,7 +127,7 @@ module.exports = [
|
|
|
127
127
|
},
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
|
-
fingerprint: [{modelID: 'TS110F', manufacturerName: '_TZ3000_92chsky7'}],
|
|
130
|
+
fingerprint: [{modelID: 'TS110F', manufacturerName: '_TZ3000_92chsky7'}, {modelID: 'TS110E', manufacturerName: '_TZ3210_4ubylghk'}],
|
|
131
131
|
model: 'QS-Zigbee-D02-TRIAC-2C-L',
|
|
132
132
|
vendor: 'Lonsonho',
|
|
133
133
|
description: '2 gang smart dimmer switch module without neutral',
|
package/devices/namron.js
CHANGED
|
@@ -263,29 +263,68 @@ module.exports = [
|
|
|
263
263
|
model: '4512737/4512738',
|
|
264
264
|
vendor: 'Namron',
|
|
265
265
|
description: 'Touch termostat',
|
|
266
|
-
fromZigbee: [fz.thermostat, fz.
|
|
266
|
+
fromZigbee: [fz.thermostat, fz.namron_thermostat, fz.metering, fz.electrical_measurement,
|
|
267
|
+
fz.namron_hvac_user_interface],
|
|
267
268
|
toZigbee: [tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint, tz.thermostat_occupancy,
|
|
268
269
|
tz.thermostat_local_temperature_calibration, tz.thermostat_local_temperature, tz.thermostat_outdoor_temperature,
|
|
269
270
|
tz.thermostat_system_mode, tz.thermostat_control_sequence_of_operation, tz.thermostat_running_state,
|
|
270
|
-
tz.
|
|
271
|
+
tz.namron_thermostat_child_lock, tz.namron_thermostat],
|
|
271
272
|
exposes: [
|
|
272
273
|
e.local_temperature(),
|
|
273
274
|
exposes.numeric('outdoor_temperature', ea.STATE_GET).withUnit('°C')
|
|
274
275
|
.withDescription('Current temperature measured from the floor sensor'),
|
|
275
|
-
e.keypad_lockout(),
|
|
276
276
|
exposes.climate()
|
|
277
|
-
.withSetpoint('occupied_heating_setpoint',
|
|
277
|
+
.withSetpoint('occupied_heating_setpoint', 0, 40, 0.1)
|
|
278
278
|
.withLocalTemperature()
|
|
279
279
|
.withLocalTemperatureCalibration(-30, 30, 0.1)
|
|
280
280
|
.withSystemMode(['off', 'auto', 'heat'])
|
|
281
281
|
.withRunningState(['idle', 'heat']),
|
|
282
|
+
exposes.binary('away_mode', ea.ALL, 'ON', 'OFF')
|
|
283
|
+
.withDescription('Enable/disable away mode'),
|
|
284
|
+
exposes.binary('child_lock', ea.ALL, 'LOCK', 'UNLOCK')
|
|
285
|
+
.withDescription('Enables/disables physical input on the device'),
|
|
282
286
|
e.power(), e.current(), e.voltage(), e.energy(),
|
|
287
|
+
exposes.enum('lcd_brightness', ea.ALL, ['low', 'mid', 'high'])
|
|
288
|
+
.withDescription('OLED brightness when operating the buttons. Default: Medium.'),
|
|
289
|
+
exposes.enum('button_vibration_level', ea.ALL, ['off', 'low', 'high'])
|
|
290
|
+
.withDescription('Key beep volume and vibration level. Default: Low.'),
|
|
291
|
+
exposes.enum('floor_sensor_type', ea.ALL, ['10k', '15k', '50k', '100k', '12k'])
|
|
292
|
+
.withDescription('Type of the external floor sensor. Default: NTC 10K/25.'),
|
|
293
|
+
exposes.enum('sensor', ea.ALL, ['air', 'floor', 'both'])
|
|
294
|
+
.withDescription('The sensor used for heat control. Default: Room Sensor.'),
|
|
295
|
+
exposes.enum('powerup_status', ea.ALL, ['default', 'last_status'])
|
|
296
|
+
.withDescription('The mode after a power reset. Default: Previous Mode.'),
|
|
297
|
+
exposes.numeric('floor_sensor_calibration', ea.ALL)
|
|
298
|
+
.withUnit('°C')
|
|
299
|
+
.withValueMin(-3).withValueMax(3).withValueStep(0.1)
|
|
300
|
+
.withDescription('The tempearatue calibration for the exernal floor sensor, between -3 and 3 in 0.1°C. Default: 0.'),
|
|
301
|
+
exposes.numeric('dry_time', ea.ALL)
|
|
302
|
+
.withUnit('min')
|
|
303
|
+
.withValueMin(5).withValueMax(100)
|
|
304
|
+
.withDescription('The duration of Dry Mode, between 5 and 100 minutes. Default: 5.'),
|
|
305
|
+
exposes.enum('mode_after_dry', ea.ALL, ['off', 'manual', 'auto', 'away'])
|
|
306
|
+
.withDescription('The mode after Dry Mode. Default: Auto.'),
|
|
307
|
+
exposes.enum('temperature_display', ea.ALL, ['room', 'floor'])
|
|
308
|
+
.withDescription('The temperature on the display. Default: Room Temperature.'),
|
|
309
|
+
exposes.numeric('window_open_check', ea.ALL)
|
|
310
|
+
.withUnit('°C')
|
|
311
|
+
.withValueMin(3).withValueMax(8).withValueStep(0.5)
|
|
312
|
+
.withDescription('The threshold to detect window open, between 3 and 8 in 0.5 °C. Default: 0 (disabled).'),
|
|
313
|
+
exposes.numeric('hysterersis', ea.ALL)
|
|
314
|
+
.withUnit('°C')
|
|
315
|
+
.withValueMin(5).withValueMax(20).withValueStep(0.1)
|
|
316
|
+
.withDescription('Hysteresis setting, between 5 and 20 in 0.1 °C. Default: 5.'),
|
|
317
|
+
exposes.enum('display_auto_off_enabled', ea.ALL, ['enable', 'disabled']),
|
|
318
|
+
exposes.numeric('alarm_airtemp_overvalue', ea.ALL)
|
|
319
|
+
.withUnit('°C')
|
|
320
|
+
.withValueMin(20).withValueMax(60).withValueStep(1)
|
|
321
|
+
.withDescription('Room temperature alarm threshold, between 20 and 60 in °C. 0 means disabled. Default: 45.'),
|
|
283
322
|
],
|
|
284
323
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
285
324
|
const endpoint = device.getEndpoint(1);
|
|
286
325
|
const binds = [
|
|
287
|
-
'genBasic', 'genIdentify', '
|
|
288
|
-
'
|
|
326
|
+
'genBasic', 'genIdentify', 'hvacThermostat', 'seMetering', 'haElectricalMeasurement', 'genAlarms',
|
|
327
|
+
'msOccupancySensing', 'genTime', 'hvacUserInterfaceCfg',
|
|
289
328
|
];
|
|
290
329
|
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
291
330
|
|
|
@@ -302,15 +341,130 @@ module.exports = [
|
|
|
302
341
|
reportableChange: null,
|
|
303
342
|
}]);
|
|
304
343
|
|
|
344
|
+
await endpoint.read('haElectricalMeasurement', ['acVoltageMultiplier', 'acVoltageDivisor', 'acCurrentMultiplier']);
|
|
345
|
+
await endpoint.read('haElectricalMeasurement', ['acCurrentDivisor']);
|
|
346
|
+
|
|
305
347
|
await reporting.activePower(endpoint);
|
|
306
|
-
await reporting.
|
|
307
|
-
await reporting.
|
|
308
|
-
await reporting.rmsCurrent(endpoint);
|
|
309
|
-
await reporting.rmsVoltage(endpoint);
|
|
348
|
+
await reporting.rmsCurrent(endpoint, {min: 10, change: 10});
|
|
349
|
+
await reporting.rmsVoltage(endpoint, {min: 10});
|
|
310
350
|
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
351
|
+
await reporting.currentSummDelivered(endpoint);
|
|
352
|
+
|
|
353
|
+
// Custom attributes
|
|
354
|
+
const options = {manufacturerCode: 0x1224};
|
|
355
|
+
|
|
356
|
+
// OperateDisplayLcdBrightnesss
|
|
357
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
358
|
+
attribute: {ID: 0x1000, type: 0x30},
|
|
359
|
+
minimumReportInterval: 0,
|
|
360
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
361
|
+
reportableChange: null}],
|
|
362
|
+
options);
|
|
363
|
+
// ButtonVibrationLevel
|
|
364
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
365
|
+
attribute: {ID: 0x1001, type: 0x30},
|
|
366
|
+
minimumReportInterval: 0,
|
|
367
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
368
|
+
reportableChange: null}],
|
|
369
|
+
options);
|
|
370
|
+
// FloorSensorType
|
|
371
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
372
|
+
attribute: {ID: 0x1002, type: 0x30},
|
|
373
|
+
minimumReportInterval: 0,
|
|
374
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
375
|
+
reportableChange: null}],
|
|
376
|
+
options);
|
|
377
|
+
// ControlType
|
|
378
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
379
|
+
attribute: {ID: 0x1003, type: 0x30},
|
|
380
|
+
minimumReportInterval: 0,
|
|
381
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
382
|
+
reportableChange: null}],
|
|
383
|
+
options);
|
|
384
|
+
// PowerUpStatus
|
|
385
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
386
|
+
attribute: {ID: 0x1004, type: 0x30},
|
|
387
|
+
minimumReportInterval: 0,
|
|
388
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
389
|
+
reportableChange: null}],
|
|
390
|
+
options);
|
|
391
|
+
// FloorSensorCalibration
|
|
392
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
393
|
+
attribute: {ID: 0x1005, type: 0x28},
|
|
394
|
+
minimumReportInterval: 0,
|
|
395
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
396
|
+
reportableChange: 0}],
|
|
397
|
+
options);
|
|
398
|
+
// DryTime
|
|
399
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
400
|
+
attribute: {ID: 0x1006, type: 0x20},
|
|
401
|
+
minimumReportInterval: 0,
|
|
402
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
403
|
+
reportableChange: 0}],
|
|
404
|
+
options);
|
|
405
|
+
// ModeAfterDry
|
|
406
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
407
|
+
attribute: {ID: 0x1007, type: 0x30},
|
|
408
|
+
minimumReportInterval: 0,
|
|
409
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
410
|
+
reportableChange: null}],
|
|
411
|
+
options);
|
|
412
|
+
// TemperatureDisplay
|
|
413
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
414
|
+
attribute: {ID: 0x1008, type: 0x30},
|
|
415
|
+
minimumReportInterval: 0,
|
|
416
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
417
|
+
reportableChange: null}],
|
|
418
|
+
options);
|
|
419
|
+
// WindowOpenCheck
|
|
420
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
421
|
+
attribute: {ID: 0x1009, type: 0x20},
|
|
422
|
+
minimumReportInterval: 0,
|
|
423
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
424
|
+
reportableChange: 0}],
|
|
425
|
+
options);
|
|
426
|
+
|
|
427
|
+
// Hysterersis
|
|
428
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
429
|
+
attribute: {ID: 0x100A, type: 0x20},
|
|
430
|
+
minimumReportInterval: 0,
|
|
431
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
432
|
+
reportableChange: 0}],
|
|
433
|
+
options);
|
|
434
|
+
// DisplayAutoOffEnable
|
|
435
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
436
|
+
attribute: {ID: 0x100B, type: 0x30},
|
|
437
|
+
minimumReportInterval: 0,
|
|
438
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
439
|
+
reportableChange: null}],
|
|
440
|
+
options);
|
|
441
|
+
|
|
442
|
+
// AlarmAirTempOverValue
|
|
443
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
444
|
+
attribute: {ID: 0x2001, type: 0x20},
|
|
445
|
+
minimumReportInterval: 0,
|
|
446
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
447
|
+
reportableChange: 0}],
|
|
448
|
+
options);
|
|
449
|
+
// Away Mode Set
|
|
450
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
451
|
+
attribute: {ID: 0x2002, type: 0x30},
|
|
452
|
+
minimumReportInterval: 0,
|
|
453
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
454
|
+
reportableChange: null}],
|
|
455
|
+
options);
|
|
456
|
+
|
|
457
|
+
// Device does not asks for the time with binding, we need to write time during configure
|
|
458
|
+
const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000);
|
|
459
|
+
const values = {time: time};
|
|
460
|
+
endpoint.write('genTime', values);
|
|
311
461
|
|
|
312
|
-
// Trigger read
|
|
313
|
-
await endpoint.read('hvacThermostat', ['systemMode', 'runningState', '
|
|
462
|
+
// Trigger initial read
|
|
463
|
+
await endpoint.read('hvacThermostat', ['systemMode', 'runningState', 'occupiedHeatingSetpoint']);
|
|
464
|
+
await endpoint.read('hvacThermostat', [0x1000, 0x1001, 0x1002, 0x1003], options);
|
|
465
|
+
await endpoint.read('hvacThermostat', [0x1004, 0x1005, 0x1006, 0x1007], options);
|
|
466
|
+
await endpoint.read('hvacThermostat', [0x1008, 0x1009, 0x100A, 0x100B], options);
|
|
467
|
+
await endpoint.read('hvacThermostat', [0x2001, 0x2002], options);
|
|
314
468
|
},
|
|
315
469
|
},
|
|
316
470
|
];
|
package/devices/niko.js
CHANGED
|
@@ -5,33 +5,47 @@ const reporting = require('../lib/reporting');
|
|
|
5
5
|
const e = exposes.presets;
|
|
6
6
|
const ea = exposes.access;
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const local = {
|
|
9
9
|
fz: {
|
|
10
10
|
switch_operation_mode: {
|
|
11
|
-
cluster: '
|
|
11
|
+
cluster: 'manuSpecificNiko1',
|
|
12
12
|
type: ['attributeReport', 'readResponse'],
|
|
13
13
|
convert: (model, msg, publish, options, meta) => {
|
|
14
14
|
const state = {};
|
|
15
|
-
if (msg.data.hasOwnProperty('
|
|
15
|
+
if (msg.data.hasOwnProperty('switchOperationMode')) {
|
|
16
16
|
const operationModeProperty = `operation_mode${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
|
|
17
17
|
const operationModeMap = {0x02: 'control_relay', 0x01: 'decoupled', 0x00: 'unknown'};
|
|
18
|
-
state[operationModeProperty] = operationModeMap[msg.data.
|
|
18
|
+
state[operationModeProperty] = operationModeMap[msg.data.switchOperationMode];
|
|
19
19
|
}
|
|
20
20
|
return state;
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
switch_action: {
|
|
24
|
-
cluster: '
|
|
24
|
+
cluster: 'manuSpecificNiko2',
|
|
25
25
|
type: ['attributeReport', 'readResponse'],
|
|
26
26
|
convert: (model, msg, publish, options, meta) => {
|
|
27
27
|
const state = {};
|
|
28
28
|
|
|
29
|
-
if (msg.data.hasOwnProperty('
|
|
29
|
+
if (msg.data.hasOwnProperty('switchAction')) {
|
|
30
30
|
// NOTE: a single press = two seperate values reported, 16 followed by 64
|
|
31
31
|
// a hold/release cyle = three seperate values, 16, 32, and 48
|
|
32
32
|
const actionProperty = `action${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
|
|
33
33
|
const actionMap = {16: null, 64: 'single', 32: 'hold', 48: 'release'};
|
|
34
|
-
state[actionProperty] = actionMap[msg.data.
|
|
34
|
+
state[actionProperty] = actionMap[msg.data.switchAction];
|
|
35
|
+
}
|
|
36
|
+
return state;
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
outlet: {
|
|
40
|
+
cluster: 'manuSpecificNiko1',
|
|
41
|
+
type: ['attributeReport', 'readResponse'],
|
|
42
|
+
convert: (model, msg, publish, options, meta) => {
|
|
43
|
+
const state = {};
|
|
44
|
+
if (msg.data.hasOwnProperty('outletChildLock')) {
|
|
45
|
+
state['child_lock'] = (msg.data['outletChildLock'] == 0 ? 'LOCK' : 'UNLOCK');
|
|
46
|
+
}
|
|
47
|
+
if (msg.data.hasOwnProperty('outletLedState')) {
|
|
48
|
+
state['led_enable'] = (msg.data['outletLedState'] == 1);
|
|
35
49
|
}
|
|
36
50
|
return state;
|
|
37
51
|
},
|
|
@@ -48,12 +62,32 @@ const fzLocal = {
|
|
|
48
62
|
throw new Error(`operation_mode was called with an invalid value (${value})`);
|
|
49
63
|
} else {
|
|
50
64
|
const operationModeProperty = `operation_mode${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
|
|
51
|
-
await entity.write('
|
|
65
|
+
await entity.write('manuSpecificNiko1', {'switchOperationMode': operationModeLookup[value]});
|
|
52
66
|
return {state: {[operationModeProperty]: value.toLowerCase()}};
|
|
53
67
|
}
|
|
54
68
|
},
|
|
55
69
|
convertGet: async (entity, key, meta) => {
|
|
56
|
-
await entity.read('
|
|
70
|
+
await entity.read('manuSpecificNiko1', ['switchOperationMode']);
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
outlet_child_lock: {
|
|
74
|
+
key: ['child_lock'],
|
|
75
|
+
convertSet: async (entity, key, value, meta) => {
|
|
76
|
+
await entity.write('manuSpecificNiko1', {'outletChildLock': ((value.toLowerCase() === 'lock') ? 0 : 1)});
|
|
77
|
+
return {state: {child_lock: ((value.toLowerCase() === 'lock') ? 'LOCK' : 'UNLOCK')}};
|
|
78
|
+
},
|
|
79
|
+
convertGet: async (entity, key, meta) => {
|
|
80
|
+
await entity.read('manuSpecificNiko1', ['outletChildLock']);
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
outlet_led_enable: {
|
|
84
|
+
key: ['led_enable'],
|
|
85
|
+
convertSet: async (entity, key, value, meta) => {
|
|
86
|
+
await entity.write('manuSpecificNiko1', {'outletLedState': ((value) ? 1 : 0)});
|
|
87
|
+
return {state: {led_enable: ((value) ? true : false)}};
|
|
88
|
+
},
|
|
89
|
+
convertGet: async (entity, key, meta) => {
|
|
90
|
+
await entity.read('manuSpecificNiko1', ['outletLedState']);
|
|
57
91
|
},
|
|
58
92
|
},
|
|
59
93
|
},
|
|
@@ -65,8 +99,11 @@ module.exports = [
|
|
|
65
99
|
model: '170-33505',
|
|
66
100
|
vendor: 'Niko',
|
|
67
101
|
description: 'Connected socket outlet',
|
|
68
|
-
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
|
|
69
|
-
toZigbee: [
|
|
102
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, local.fz.outlet],
|
|
103
|
+
toZigbee: [
|
|
104
|
+
tz.on_off, tz.electrical_measurement_power, tz.currentsummdelivered,
|
|
105
|
+
local.tz.outlet_child_lock, local.tz.outlet_led_enable,
|
|
106
|
+
],
|
|
70
107
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
71
108
|
const endpoint = device.getEndpoint(1);
|
|
72
109
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
@@ -83,11 +120,16 @@ module.exports = [
|
|
|
83
120
|
|
|
84
121
|
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
85
122
|
await reporting.currentSummDelivered(endpoint, {min: 60, change: 1});
|
|
123
|
+
|
|
124
|
+
await endpoint.read('manuSpecificNiko1', ['outletChildLock']);
|
|
125
|
+
await endpoint.read('manuSpecificNiko1', ['outletLedState']);
|
|
86
126
|
},
|
|
87
127
|
exposes: [
|
|
88
128
|
e.switch(),
|
|
89
129
|
e.power().withAccess(ea.STATE_GET), e.current(), e.voltage(),
|
|
90
130
|
e.energy().withAccess(ea.STATE_GET),
|
|
131
|
+
exposes.binary('child_lock', ea.ALL, 'LOCK', 'UNLOCK').withDescription('Enables/disables physical input on the device'),
|
|
132
|
+
exposes.binary('led_enable', ea.ALL, true, false).withDescription('Enable LED'),
|
|
91
133
|
],
|
|
92
134
|
},
|
|
93
135
|
{
|
|
@@ -134,13 +176,13 @@ module.exports = [
|
|
|
134
176
|
model: '552-721X1',
|
|
135
177
|
vendor: 'Niko',
|
|
136
178
|
description: 'Single connectable switch',
|
|
137
|
-
fromZigbee: [fz.on_off,
|
|
138
|
-
toZigbee: [tz.on_off,
|
|
179
|
+
fromZigbee: [fz.on_off, local.fz.switch_operation_mode, local.fz.switch_action],
|
|
180
|
+
toZigbee: [tz.on_off, local.tz.switch_operation_mode],
|
|
139
181
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
140
182
|
const endpoint = device.getEndpoint(1);
|
|
141
183
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
142
184
|
await reporting.onOff(endpoint);
|
|
143
|
-
await endpoint.read('
|
|
185
|
+
await endpoint.read('manuSpecificNiko1', ['switchOperationMode']);
|
|
144
186
|
},
|
|
145
187
|
exposes: [
|
|
146
188
|
e.switch(),
|
|
@@ -153,8 +195,8 @@ module.exports = [
|
|
|
153
195
|
model: '552-721X2',
|
|
154
196
|
vendor: 'Niko',
|
|
155
197
|
description: 'Double connectable switch',
|
|
156
|
-
fromZigbee: [fz.on_off,
|
|
157
|
-
toZigbee: [tz.on_off,
|
|
198
|
+
fromZigbee: [fz.on_off, local.fz.switch_operation_mode, local.fz.switch_action],
|
|
199
|
+
toZigbee: [tz.on_off, local.tz.switch_operation_mode],
|
|
158
200
|
endpoint: (device) => {
|
|
159
201
|
return {'l1': 1, 'l2': 2};
|
|
160
202
|
},
|
|
@@ -166,8 +208,8 @@ module.exports = [
|
|
|
166
208
|
await reporting.bind(ep2, coordinatorEndpoint, ['genOnOff']);
|
|
167
209
|
await reporting.onOff(ep1);
|
|
168
210
|
await reporting.onOff(ep2);
|
|
169
|
-
await ep1.read('
|
|
170
|
-
await ep2.read('
|
|
211
|
+
await ep1.read('manuSpecificNiko1', ['switchOperationMode']);
|
|
212
|
+
await ep2.read('manuSpecificNiko1', ['switchOperationMode']);
|
|
171
213
|
},
|
|
172
214
|
exposes: [
|
|
173
215
|
e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
|
package/devices/orvibo.js
CHANGED
|
@@ -6,6 +6,13 @@ const extend = require('../lib/extend');
|
|
|
6
6
|
const e = exposes.presets;
|
|
7
7
|
|
|
8
8
|
module.exports = [
|
|
9
|
+
{
|
|
10
|
+
zigbeeModel: ['4a33f5ea766a4c96a962b371ffde9943'],
|
|
11
|
+
model: 'DS20Z07B',
|
|
12
|
+
vendor: 'ORVIBO',
|
|
13
|
+
description: 'Downlight (S series)',
|
|
14
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [166, 370]}),
|
|
15
|
+
},
|
|
9
16
|
{
|
|
10
17
|
zigbeeModel: ['ORVIBO Socket', '93e29b89b2ee45bea5bdbb7679d75d24'],
|
|
11
18
|
model: 'OR-ZB-S010-3C',
|
package/devices/prolight.js
CHANGED
|
@@ -6,10 +6,10 @@ const e = exposes.presets;
|
|
|
6
6
|
module.exports = [
|
|
7
7
|
{
|
|
8
8
|
zigbeeModel: ['PROLIGHT E27 WHITE AND COLOUR'],
|
|
9
|
-
model: '
|
|
9
|
+
model: '5412748727371',
|
|
10
10
|
vendor: 'Prolight',
|
|
11
11
|
description: 'E27 white and colour bulb',
|
|
12
|
-
extend: extend.light_onoff_brightness_colortemp_color(),
|
|
12
|
+
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555]}),
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
zigbeeModel: ['PROLIGHT E27 WARM WHITE CLEAR'],
|
|
@@ -32,9 +32,16 @@ module.exports = [
|
|
|
32
32
|
description: 'GU10 white and colour spot',
|
|
33
33
|
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555]}),
|
|
34
34
|
},
|
|
35
|
+
{
|
|
36
|
+
zigbeeModel: ['PROLIGHT GU10 WARM WHITE'],
|
|
37
|
+
model: '5412748727395',
|
|
38
|
+
vendor: 'Prolight',
|
|
39
|
+
description: 'GU10 spot dimmable',
|
|
40
|
+
extend: extend.light_onoff_brightness(),
|
|
41
|
+
},
|
|
35
42
|
{
|
|
36
43
|
zigbeeModel: ['PROLIGHT REMOTE CONTROL'],
|
|
37
|
-
model: '
|
|
44
|
+
model: '5412748727388',
|
|
38
45
|
vendor: 'Prolight',
|
|
39
46
|
description: 'Remote control',
|
|
40
47
|
toZigbee: [],
|
package/devices/sinope.js
CHANGED
|
@@ -259,6 +259,22 @@ module.exports = [
|
|
|
259
259
|
await reporting.activePower(endpoint, {min: 10, change: 1});
|
|
260
260
|
},
|
|
261
261
|
},
|
|
262
|
+
{
|
|
263
|
+
zigbeeModel: ['SP2610ZB'],
|
|
264
|
+
model: 'SP2610ZB',
|
|
265
|
+
vendor: 'Sinopé',
|
|
266
|
+
description: 'Zigbee smart outlet',
|
|
267
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement],
|
|
268
|
+
toZigbee: [tz.on_off],
|
|
269
|
+
exposes: [e.switch(), e.power()],
|
|
270
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
271
|
+
const endpoint = device.getEndpoint(1);
|
|
272
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
|
|
273
|
+
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
|
|
274
|
+
await reporting.onOff(endpoint);
|
|
275
|
+
await reporting.activePower(endpoint, {min: 10, change: 1});
|
|
276
|
+
},
|
|
277
|
+
},
|
|
262
278
|
{
|
|
263
279
|
zigbeeModel: ['DM2500ZB'],
|
|
264
280
|
model: 'DM2500ZB',
|
package/devices/tuya.js
CHANGED
|
@@ -2174,7 +2174,8 @@ module.exports = [
|
|
|
2174
2174
|
],
|
|
2175
2175
|
},
|
|
2176
2176
|
{
|
|
2177
|
-
fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_4fjiwweb'}, {modelID: 'TS004F', manufacturerName: '_TZ3000_uri7ongn'}
|
|
2177
|
+
fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_4fjiwweb'}, {modelID: 'TS004F', manufacturerName: '_TZ3000_uri7ongn'},
|
|
2178
|
+
{modelID: 'TS004F', manufacturerName: '_TZ3000_ixla93vd'}],
|
|
2178
2179
|
model: 'ERS-10TZBVK-AA',
|
|
2179
2180
|
vendor: 'TuYa',
|
|
2180
2181
|
description: 'Smart knob',
|
package/devices/woox.js
CHANGED
|
@@ -7,6 +7,75 @@ const extend = require('../lib/extend');
|
|
|
7
7
|
const e = exposes.presets;
|
|
8
8
|
const ea = exposes.access;
|
|
9
9
|
|
|
10
|
+
const fzLocal = {
|
|
11
|
+
R7049_status: {
|
|
12
|
+
cluster: 'manuSpecificTuya',
|
|
13
|
+
type: ['commandDataResponse', 'commandDataReport'],
|
|
14
|
+
convert: (model, msg, publish, options, meta) => {
|
|
15
|
+
const result = {};
|
|
16
|
+
for (const dpValue of msg.data.dpValues) {
|
|
17
|
+
const dp = dpValue.dp; // First we get the data point ID
|
|
18
|
+
const value = tuya.getDataValue(dpValue); // This function will take care of converting the data to proper JS type
|
|
19
|
+
switch (dp) {
|
|
20
|
+
case 1:
|
|
21
|
+
result.smoke = Boolean(!value);
|
|
22
|
+
break;
|
|
23
|
+
case 8:
|
|
24
|
+
result.test_alarm = value;
|
|
25
|
+
break;
|
|
26
|
+
case 9: {
|
|
27
|
+
const testAlarmResult = {0: 'checking', 1: 'check_success', 2: 'check_failure', 3: 'others'};
|
|
28
|
+
result.test_alarm_result = testAlarmResult[value];
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case 11:
|
|
32
|
+
result.fault_alarm = Boolean(value);
|
|
33
|
+
break;
|
|
34
|
+
case 14: {
|
|
35
|
+
const batteryLevels = {0: 'low', 1: 'middle', 2: 'high'};
|
|
36
|
+
result.battery_level = batteryLevels[value];
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case 16:
|
|
40
|
+
result.silence_siren = value;
|
|
41
|
+
break;
|
|
42
|
+
case 20: {
|
|
43
|
+
const alarm = {0: true, 1: false};
|
|
44
|
+
result.alarm = alarm[value];
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
meta.logger.warn(`zigbee-herdsman-converters:Woox Smoke Detector: NOT RECOGNIZED DP #${
|
|
49
|
+
dp} with data ${JSON.stringify(dpValue)}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const tzLocal = {
|
|
58
|
+
R7049_silenceSiren: {
|
|
59
|
+
key: ['silence_siren'],
|
|
60
|
+
convertSet: async (entity, key, value, meta) => {
|
|
61
|
+
await tuya.sendDataPointBool(entity, 16, value);
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
R7049_testAlarm: {
|
|
65
|
+
key: ['test_alarm'],
|
|
66
|
+
convertSet: async (entity, key, value, meta) => {
|
|
67
|
+
await tuya.sendDataPointBool(entity, 8, value);
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
R7049_alarm: {
|
|
71
|
+
key: ['alarm'],
|
|
72
|
+
convertSet: async (entity, key, value, meta) => {
|
|
73
|
+
const linkAlarm = {true: 0, false: 1};
|
|
74
|
+
await tuya.sendDataPointEnum(entity, 20, linkAlarm[value]);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
10
79
|
module.exports = [
|
|
11
80
|
{
|
|
12
81
|
fingerprint: [{modelID: 'TS0101', manufacturerName: '_TZ3210_eymunffl'}],
|
|
@@ -50,10 +119,19 @@ module.exports = [
|
|
|
50
119
|
model: 'R7049',
|
|
51
120
|
vendor: 'Woox',
|
|
52
121
|
description: 'Smart smoke alarm',
|
|
53
|
-
|
|
54
|
-
|
|
122
|
+
meta: {timeout: 30000, disableDefaultResponse: true},
|
|
123
|
+
fromZigbee: [fzLocal.R7049_status, fz.ignore_tuya_set_time, fz.ignore_time_read],
|
|
124
|
+
toZigbee: [tzLocal.R7049_silenceSiren, tzLocal.R7049_testAlarm, tzLocal.R7049_alarm],
|
|
125
|
+
exposes: [e.battery_low(),
|
|
126
|
+
exposes.binary('smoke', ea.STATE, true, false).withDescription('Smoke alarm status'),
|
|
127
|
+
exposes.binary('test_alarm', ea.STATE_SET, true, false).withDescription('Test alarm'),
|
|
128
|
+
exposes.enum('test_alarm_result', ea.STATE, ['checking', 'check_success', 'check_failure', 'others'])
|
|
129
|
+
.withDescription('Test alarm result'),
|
|
130
|
+
exposes.enum('battery_level', ea.STATE, ['low', 'middle', 'high']).withDescription('Battery level state'),
|
|
131
|
+
exposes.binary('alarm', ea.STATE_SET, true, false).withDescription('Alarm enable'),
|
|
132
|
+
exposes.binary('fault_alarm', ea.STATE, true, false).withDescription('Fault alarm status'),
|
|
133
|
+
exposes.binary('silence_siren', ea.STATE_SET, true, false).withDescription('Silence siren')],
|
|
55
134
|
onEvent: tuya.onEventsetTime,
|
|
56
|
-
exposes: [e.smoke(), e.battery_low()],
|
|
57
135
|
},
|
|
58
136
|
{
|
|
59
137
|
fingerprint: [{modelID: 'TS0219', manufacturerName: '_TYZB01_ynsiasng'}],
|
package/lib/ota/OTA_URLs.md
CHANGED
|
@@ -76,7 +76,19 @@ https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/OTA-Image-Types---
|
|
|
76
76
|
|
|
77
77
|
### Philips Hue (Signify)
|
|
78
78
|
|
|
79
|
-
Philips Hue
|
|
79
|
+
Philips Hue OTA firmware images are available for different Hue devices for several official sources that do not all use the same APIs:
|
|
80
|
+
|
|
81
|
+
https://firmware.meethue.com/v1/checkUpdate
|
|
82
|
+
|
|
83
|
+
https://firmware.meethue.com/storage/
|
|
84
|
+
|
|
85
|
+
http://fds.dc1.philips.com/firmware/
|
|
86
|
+
|
|
87
|
+
Philips Hue (Signify) Zigbee OTA firmware images direct URLs are available by Koenkk zigbee-OTA repository (third-party) at following URL:
|
|
88
|
+
|
|
89
|
+
https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/index.json
|
|
90
|
+
|
|
91
|
+
Philips Hue (Signify) Zigbee OTA firmware images are also made publicly available by Dresden Elektronik (third-party) at following URL:
|
|
80
92
|
|
|
81
93
|
https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/OTA-Image-Types---Firmware-versions#philips-hue
|
|
82
94
|
|
package/lib/tuya.js
CHANGED
|
@@ -219,7 +219,8 @@ function convertStringToHexArray(value) {
|
|
|
219
219
|
// Default is 100 = open, 0 = closed; Devices listed here will use 0 = open, 100 = closed instead
|
|
220
220
|
// Use manufacturerName to identify device!
|
|
221
221
|
// Dont' invert _TZE200_cowvfni3: https://github.com/Koenkk/zigbee2mqtt/issues/6043
|
|
222
|
-
const coverPositionInvert = ['_TZE200_wmcdj3aq', '_TZE200_nogaemzt', '_TZE200_xuzcvlku', '_TZE200_xaabybja', '_TZE200_rmymn92d'
|
|
222
|
+
const coverPositionInvert = ['_TZE200_wmcdj3aq', '_TZE200_nogaemzt', '_TZE200_xuzcvlku', '_TZE200_xaabybja', '_TZE200_rmymn92d',
|
|
223
|
+
'_TZE200_gubdgai2'];
|
|
223
224
|
|
|
224
225
|
// Gets a boolean indicating whether the cover by this manufacturerName needs reversed positions
|
|
225
226
|
function isCoverInverted(manufacturerName) {
|