zigbee-herdsman-converters 14.0.371 → 14.0.372
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 +98 -2
- package/converters/toZigbee.js +130 -3
- package/devices/awox.js +5 -0
- package/devices/centralite.js +10 -6
- package/devices/innr.js +8 -0
- package/devices/nous.js +9 -0
- package/devices/philips.js +9 -0
- package/devices/skydance.js +74 -0
- package/devices/tuya.js +1 -1
- package/devices/xiaomi.js +19 -16
- package/devices/zemismart.js +1 -1
- package/lib/exposes.js +1 -1
- package/lib/tuya.js +1 -0
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -5017,7 +5017,8 @@ const converters = {
|
|
|
5017
5017
|
aqara_opple: {
|
|
5018
5018
|
cluster: 'aqaraOpple',
|
|
5019
5019
|
type: ['attributeReport', 'readResponse'],
|
|
5020
|
-
options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature')
|
|
5020
|
+
options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature'),
|
|
5021
|
+
exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual')],
|
|
5021
5022
|
convert: (model, msg, publish, options, meta) => {
|
|
5022
5023
|
const payload = {};
|
|
5023
5024
|
if (msg.data.hasOwnProperty('247')) {
|
|
@@ -5142,6 +5143,8 @@ const converters = {
|
|
|
5142
5143
|
if (['QBKG19LM', 'QBKG20LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5143
5144
|
const mapping = model.model === 'QBCZ15LM' ? 'usb' : 'right';
|
|
5144
5145
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
5146
|
+
} else if (['RTCGQ12LM'].includes(model.model)) {
|
|
5147
|
+
payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
|
|
5145
5148
|
}
|
|
5146
5149
|
} else if (index === 149) {
|
|
5147
5150
|
payload.energy = precisionRound(value, 2); // 0x95
|
|
@@ -5157,7 +5160,7 @@ const converters = {
|
|
|
5157
5160
|
if (msg.data.hasOwnProperty('0')) payload.detection_period = msg.data['0'];
|
|
5158
5161
|
if (msg.data.hasOwnProperty('4')) payload.mode_switch = {4: 'anti_flicker_mode', 1: 'quick_mode'}[msg.data['4']];
|
|
5159
5162
|
if (msg.data.hasOwnProperty('10')) payload.switch_type = {1: 'toggle', 2: 'momentary'}[msg.data['10']];
|
|
5160
|
-
if (msg.data.hasOwnProperty('258')) payload.
|
|
5163
|
+
if (msg.data.hasOwnProperty('258')) payload.occupancy_timeout = msg.data['258'];
|
|
5161
5164
|
if (msg.data.hasOwnProperty('268')) payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[msg.data['268']];
|
|
5162
5165
|
if (msg.data.hasOwnProperty('512')) {
|
|
5163
5166
|
if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
|
|
@@ -5310,6 +5313,65 @@ const converters = {
|
|
|
5310
5313
|
return payload;
|
|
5311
5314
|
},
|
|
5312
5315
|
},
|
|
5316
|
+
RTCGQ12LM_occupancy_illuminance: {
|
|
5317
|
+
cluster: 'aqaraOpple',
|
|
5318
|
+
type: ['attributeReport', 'readResponse'],
|
|
5319
|
+
options: [exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual')],
|
|
5320
|
+
convert: (model, msg, publish, options, meta) => {
|
|
5321
|
+
if (msg.data.hasOwnProperty('illuminance')) {
|
|
5322
|
+
// The occupancy sensor only sends a message when motion detected.
|
|
5323
|
+
// Therefore we need to publish the no_motion detected by ourselves.
|
|
5324
|
+
const timeout = meta && meta.state && meta.state.hasOwnProperty('occupancy_timeout') ? meta.state.occupancy_timeout : 60;
|
|
5325
|
+
|
|
5326
|
+
// Stop existing timers because motion is detected and set a new one.
|
|
5327
|
+
globalStore.getValue(msg.endpoint, 'timers', []).forEach((t) => clearTimeout(t));
|
|
5328
|
+
globalStore.putValue(msg.endpoint, 'timers', []);
|
|
5329
|
+
|
|
5330
|
+
if (timeout !== 0) {
|
|
5331
|
+
const timer = setTimeout(() => {
|
|
5332
|
+
publish({occupancy: false});
|
|
5333
|
+
}, timeout * 1000);
|
|
5334
|
+
|
|
5335
|
+
globalStore.getValue(msg.endpoint, 'timers').push(timer);
|
|
5336
|
+
}
|
|
5337
|
+
|
|
5338
|
+
const illuminance = msg.data['illuminance'] - 65536;
|
|
5339
|
+
return {occupancy: true, illuminance: calibrateAndPrecisionRoundOptions(illuminance, options, 'illuminance')};
|
|
5340
|
+
}
|
|
5341
|
+
},
|
|
5342
|
+
},
|
|
5343
|
+
RTCGQ13LM_occupancy: {
|
|
5344
|
+
// This is for occupancy sensor that only send a message when motion detected,
|
|
5345
|
+
// but do not send a motion stop.
|
|
5346
|
+
// Therefore we need to publish the no_motion detected by ourselves.
|
|
5347
|
+
cluster: 'msOccupancySensing',
|
|
5348
|
+
type: ['attributeReport', 'readResponse'],
|
|
5349
|
+
convert: (model, msg, publish, options, meta) => {
|
|
5350
|
+
if (msg.data.occupancy !== 1) {
|
|
5351
|
+
// In case of 0 no occupancy is reported.
|
|
5352
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/467
|
|
5353
|
+
return;
|
|
5354
|
+
}
|
|
5355
|
+
|
|
5356
|
+
// The occupancy sensor only sends a message when motion detected.
|
|
5357
|
+
// Therefore we need to publish the no_motion detected by ourselves.
|
|
5358
|
+
const timeout = meta && meta.state && meta.state.hasOwnProperty('occupancy_timeout') ? meta.state.occupancy_timeout : 60;
|
|
5359
|
+
|
|
5360
|
+
// Stop existing timers because motion is detected and set a new one.
|
|
5361
|
+
globalStore.getValue(msg.endpoint, 'timers', []).forEach((t) => clearTimeout(t));
|
|
5362
|
+
globalStore.putValue(msg.endpoint, 'timers', []);
|
|
5363
|
+
|
|
5364
|
+
if (timeout !== 0) {
|
|
5365
|
+
const timer = setTimeout(() => {
|
|
5366
|
+
publish({occupancy: false});
|
|
5367
|
+
}, timeout * 1000);
|
|
5368
|
+
|
|
5369
|
+
globalStore.getValue(msg.endpoint, 'timers').push(timer);
|
|
5370
|
+
}
|
|
5371
|
+
|
|
5372
|
+
return {occupancy: true};
|
|
5373
|
+
},
|
|
5374
|
+
},
|
|
5313
5375
|
xiaomi_WXKG01LM_action: {
|
|
5314
5376
|
cluster: 'genOnOff',
|
|
5315
5377
|
type: ['attributeReport', 'readResponse'],
|
|
@@ -7770,6 +7832,40 @@ const converters = {
|
|
|
7770
7832
|
};
|
|
7771
7833
|
},
|
|
7772
7834
|
},
|
|
7835
|
+
tuya_light_wz5: {
|
|
7836
|
+
cluster: 'manuSpecificTuya',
|
|
7837
|
+
type: ['commandDataResponse', 'commandDataReport'],
|
|
7838
|
+
convert: (model, msg, publish, options, meta) => {
|
|
7839
|
+
const separateWhite = (model.meta && model.meta.separateWhite);
|
|
7840
|
+
const result = {};
|
|
7841
|
+
// eslint-disable-next-line no-unused-vars
|
|
7842
|
+
for (const [i, dpValue] of msg.data.dpValues.entries()) {
|
|
7843
|
+
const dp = dpValue.dp;
|
|
7844
|
+
const value = tuya.getDataValue(dpValue);
|
|
7845
|
+
if (dp === tuya.dataPoints.state) {
|
|
7846
|
+
result.state = value ? 'ON': 'OFF';
|
|
7847
|
+
} else if (dp === tuya.dataPoints.silvercrestSetBrightness) {
|
|
7848
|
+
const brightness = mapNumberRange(value, 0, 1000, 0, 255);
|
|
7849
|
+
if (separateWhite) {
|
|
7850
|
+
result.white_brightness = brightness;
|
|
7851
|
+
} else {
|
|
7852
|
+
result.brightness = brightness;
|
|
7853
|
+
}
|
|
7854
|
+
} else if (dp === tuya.dataPoints.silvercrestSetColor) {
|
|
7855
|
+
const h = parseInt(value.substring(0, 4), 16);
|
|
7856
|
+
const s = parseInt(value.substring(4, 8), 16);
|
|
7857
|
+
const b = parseInt(value.substring(8, 12), 16);
|
|
7858
|
+
result.color_mode = 'hs';
|
|
7859
|
+
result.color = {hue: h, saturation: mapNumberRange(s, 0, 1000, 0, 100)};
|
|
7860
|
+
result.brightness = mapNumberRange(b, 0, 1000, 0, 255);
|
|
7861
|
+
} else if (dp === tuya.dataPoints.silvercrestSetColorTemp) {
|
|
7862
|
+
const [colorTempMin, colorTempMax] = [250, 454];
|
|
7863
|
+
result.color_temp = mapNumberRange(value, 0, 1000, colorTempMax, colorTempMin);
|
|
7864
|
+
}
|
|
7865
|
+
}
|
|
7866
|
+
return result;
|
|
7867
|
+
},
|
|
7868
|
+
},
|
|
7773
7869
|
// #endregion
|
|
7774
7870
|
|
|
7775
7871
|
// #region Ignore converters (these message dont need parsing).
|
package/converters/toZigbee.js
CHANGED
|
@@ -2076,12 +2076,12 @@ const converters = {
|
|
|
2076
2076
|
await entity.read('aqaraOpple', [0x0000], manufacturerOptions.xiaomi);
|
|
2077
2077
|
},
|
|
2078
2078
|
},
|
|
2079
|
-
|
|
2080
|
-
key: ['
|
|
2079
|
+
aqara_occupancy_timeout: {
|
|
2080
|
+
key: ['occupancy_timeout'],
|
|
2081
2081
|
convertSet: async (entity, key, value, meta) => {
|
|
2082
2082
|
value *= 1;
|
|
2083
2083
|
await entity.write('aqaraOpple', {0x0102: {value: [value], type: 0x20}}, manufacturerOptions.xiaomi);
|
|
2084
|
-
return {state: {
|
|
2084
|
+
return {state: {occupancy_timeout: value}};
|
|
2085
2085
|
},
|
|
2086
2086
|
convertGet: async (entity, key, meta) => {
|
|
2087
2087
|
await entity.read('aqaraOpple', [0x0102], manufacturerOptions.xiaomi);
|
|
@@ -6404,6 +6404,133 @@ const converters = {
|
|
|
6404
6404
|
return {state: {click_mode: value}};
|
|
6405
6405
|
},
|
|
6406
6406
|
},
|
|
6407
|
+
tuya_light_wz5: {
|
|
6408
|
+
key: ['color', 'color_temp', 'brightness', 'white_brightness'],
|
|
6409
|
+
convertSet: async (entity, key, value, meta) => {
|
|
6410
|
+
const separateWhite = (meta.mapped.meta && meta.mapped.meta.separateWhite);
|
|
6411
|
+
if (key == 'white_brightness' || (!separateWhite && (key == 'brightness'))) {
|
|
6412
|
+
// upscale to 1000
|
|
6413
|
+
let newValue;
|
|
6414
|
+
if (value >= 0 && value <= 255) {
|
|
6415
|
+
newValue = utils.mapNumberRange(value, 0, 255, 0, 1000);
|
|
6416
|
+
} else {
|
|
6417
|
+
throw new Error('Dimmer brightness is out of range 0..255');
|
|
6418
|
+
}
|
|
6419
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white);
|
|
6420
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.dimmerLevel, newValue);
|
|
6421
|
+
|
|
6422
|
+
return {state: {white_brightness: value}};
|
|
6423
|
+
} else if (key == 'color_temp') {
|
|
6424
|
+
const [colorTempMin, colorTempMax] = [250, 454];
|
|
6425
|
+
const preset = {
|
|
6426
|
+
'warmest': colorTempMax,
|
|
6427
|
+
'warm': 454,
|
|
6428
|
+
'neutral': 370,
|
|
6429
|
+
'cool': 250,
|
|
6430
|
+
'coolest': colorTempMin,
|
|
6431
|
+
};
|
|
6432
|
+
if (typeof value === 'string' && isNaN(value)) {
|
|
6433
|
+
const presetName = value.toLowerCase();
|
|
6434
|
+
if (presetName in preset) {
|
|
6435
|
+
value = preset[presetName];
|
|
6436
|
+
} else {
|
|
6437
|
+
throw new Error(`Unknown preset '${value}'`);
|
|
6438
|
+
}
|
|
6439
|
+
} else {
|
|
6440
|
+
value = light.clampColorTemp(Number(value), colorTempMin, colorTempMax, meta.logger);
|
|
6441
|
+
}
|
|
6442
|
+
const data = utils.mapNumberRange(value, colorTempMax, colorTempMin, 0, 1000);
|
|
6443
|
+
|
|
6444
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white);
|
|
6445
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.silvercrestSetColorTemp, data);
|
|
6446
|
+
|
|
6447
|
+
return {state: {color_temp: value}};
|
|
6448
|
+
} else if (key == 'color' || (separateWhite && (key == 'brightness'))) {
|
|
6449
|
+
const newState = {};
|
|
6450
|
+
if (key == 'brightness') {
|
|
6451
|
+
newState.brightness = value;
|
|
6452
|
+
} else if (key == 'color') {
|
|
6453
|
+
newState.color = value;
|
|
6454
|
+
newState.color_mode = 'hs';
|
|
6455
|
+
}
|
|
6456
|
+
|
|
6457
|
+
const make4sizedString = (v) => {
|
|
6458
|
+
if (v.length >= 4) {
|
|
6459
|
+
return v;
|
|
6460
|
+
} else if (v.length === 3) {
|
|
6461
|
+
return '0' + v;
|
|
6462
|
+
} else if (v.length === 2) {
|
|
6463
|
+
return '00' + v;
|
|
6464
|
+
} else if (v.length === 1) {
|
|
6465
|
+
return '000' + v;
|
|
6466
|
+
} else {
|
|
6467
|
+
return '0000';
|
|
6468
|
+
}
|
|
6469
|
+
};
|
|
6470
|
+
|
|
6471
|
+
const fillInHSB = (h, s, b, state) => {
|
|
6472
|
+
// Define default values. Device expects leading zero in string.
|
|
6473
|
+
const hsb = {
|
|
6474
|
+
h: '0168', // 360
|
|
6475
|
+
s: '03e8', // 1000
|
|
6476
|
+
b: '03e8', // 1000
|
|
6477
|
+
};
|
|
6478
|
+
|
|
6479
|
+
if (h) {
|
|
6480
|
+
// The device expects 0-359
|
|
6481
|
+
if (h >= 360) {
|
|
6482
|
+
h = 359;
|
|
6483
|
+
}
|
|
6484
|
+
hsb.h = make4sizedString(h.toString(16));
|
|
6485
|
+
} else if (state.color && state.color.hue) {
|
|
6486
|
+
hsb.h = make4sizedString(state.color.hue.toString(16));
|
|
6487
|
+
}
|
|
6488
|
+
|
|
6489
|
+
// Device expects 0-1000, saturation normally is 0-100 so we expect that from the user
|
|
6490
|
+
// The device expects a round number, otherwise everything breaks
|
|
6491
|
+
if (s) {
|
|
6492
|
+
hsb.s = make4sizedString(utils.mapNumberRange(s, 0, 100, 0, 1000).toString(16));
|
|
6493
|
+
} else if (state.color && state.color.saturation) {
|
|
6494
|
+
hsb.s = make4sizedString(utils.mapNumberRange(state.color.saturation, 0, 100, 0, 1000).toString(16));
|
|
6495
|
+
}
|
|
6496
|
+
|
|
6497
|
+
// Scale 0-255 to 0-1000 what the device expects.
|
|
6498
|
+
if (b) {
|
|
6499
|
+
hsb.b = make4sizedString(utils.mapNumberRange(b, 0, 255, 0, 1000).toString(16));
|
|
6500
|
+
} else if (state.brightness) {
|
|
6501
|
+
hsb.b = make4sizedString(utils.mapNumberRange(state.brightness, 0, 255, 0, 1000).toString(16));
|
|
6502
|
+
}
|
|
6503
|
+
|
|
6504
|
+
return hsb;
|
|
6505
|
+
};
|
|
6506
|
+
|
|
6507
|
+
const hsb = fillInHSB(
|
|
6508
|
+
value.h || value.hue || null,
|
|
6509
|
+
value.s || value.saturation || null,
|
|
6510
|
+
value.b || value.brightness || (key == 'brightness') ? value : null,
|
|
6511
|
+
meta.state,
|
|
6512
|
+
);
|
|
6513
|
+
|
|
6514
|
+
|
|
6515
|
+
let data = [];
|
|
6516
|
+
data = data.concat(tuya.convertStringToHexArray(hsb.h));
|
|
6517
|
+
data = data.concat(tuya.convertStringToHexArray(hsb.s));
|
|
6518
|
+
data = data.concat(tuya.convertStringToHexArray(hsb.b));
|
|
6519
|
+
|
|
6520
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.color);
|
|
6521
|
+
await tuya.sendDataPointStringBuffer(entity, tuya.dataPoints.silvercrestSetColor, data);
|
|
6522
|
+
|
|
6523
|
+
if (separateWhite && meta.state.white_brightness != undefined) {
|
|
6524
|
+
// restore white state
|
|
6525
|
+
const newValue = utils.mapNumberRange(meta.state.white_brightness, 0, 255, 0, 1000);
|
|
6526
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white);
|
|
6527
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.dimmerLevel, newValue);
|
|
6528
|
+
}
|
|
6529
|
+
|
|
6530
|
+
return {state: newState};
|
|
6531
|
+
}
|
|
6532
|
+
},
|
|
6533
|
+
},
|
|
6407
6534
|
// #endregion
|
|
6408
6535
|
|
|
6409
6536
|
// #region Ignore converters
|
package/devices/awox.js
CHANGED
|
@@ -10,6 +10,11 @@ module.exports = [
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
fingerprint: [
|
|
13
|
+
{type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
|
|
14
|
+
{ID: 1, profileID: 260, deviceID: 269, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599, 10], outputClusters: [6]},
|
|
15
|
+
{ID: 3, profileID: 4751, deviceID: 269, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
|
|
16
|
+
{ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
|
|
17
|
+
]},
|
|
13
18
|
{type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
|
|
14
19
|
{ID: 1, profileID: 260, deviceID: 258, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096], outputClusters: [6, 25]},
|
|
15
20
|
{ID: 3, profileID: 49152, deviceID: 258, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
|
package/devices/centralite.js
CHANGED
|
@@ -196,12 +196,15 @@ module.exports = [
|
|
|
196
196
|
tz.thermostat_occupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
|
|
197
197
|
tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
|
|
198
198
|
tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode,
|
|
199
|
-
tz.thermostat_relay_status_log, tz.fan_mode, tz.thermostat_running_state],
|
|
200
|
-
exposes: [e.battery(),
|
|
201
|
-
.
|
|
202
|
-
|
|
203
|
-
.withSetpoint('
|
|
204
|
-
|
|
199
|
+
tz.thermostat_relay_status_log, tz.fan_mode, tz.thermostat_running_state, tz.thermostat_temperature_setpoint_hold],
|
|
200
|
+
exposes: [e.battery(),
|
|
201
|
+
exposes.binary('temperature_setpoint_hold', ea.ALL, true, false)
|
|
202
|
+
.withDescription('Prevent changes. `false` = run normally. `true` = prevent from making changes.'),
|
|
203
|
+
exposes.climate().withSetpoint('occupied_heating_setpoint', 10, 30, 1).withLocalTemperature()
|
|
204
|
+
.withSystemMode(['off', 'heat', 'cool', 'emergency_heating'])
|
|
205
|
+
.withRunningState(['idle', 'heat', 'cool', 'fan_only']).withFanMode(['auto', 'on'])
|
|
206
|
+
.withSetpoint('occupied_cooling_setpoint', 10, 30, 1)
|
|
207
|
+
.withLocalTemperatureCalibration(-30, 30, 0.1)],
|
|
205
208
|
meta: {battery: {voltageToPercentage: '3V_1500_2800'}},
|
|
206
209
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
207
210
|
const endpoint = device.getEndpoint(1);
|
|
@@ -210,6 +213,7 @@ module.exports = [
|
|
|
210
213
|
await reporting.thermostatRunningState(endpoint);
|
|
211
214
|
await reporting.thermostatTemperature(endpoint);
|
|
212
215
|
await reporting.fanMode(endpoint);
|
|
216
|
+
await reporting.thermostatTemperatureSetpointHold(endpoint);
|
|
213
217
|
},
|
|
214
218
|
},
|
|
215
219
|
{
|
package/devices/innr.js
CHANGED
|
@@ -79,6 +79,14 @@ module.exports = [
|
|
|
79
79
|
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555], supportsHS: true}),
|
|
80
80
|
meta: {enhancedHue: false, applyRedFix: true, turnsOffAtBrightness1: true},
|
|
81
81
|
},
|
|
82
|
+
{
|
|
83
|
+
zigbeeModel: ['RB 251 C'],
|
|
84
|
+
model: 'RB 251 C',
|
|
85
|
+
vendor: 'Innr',
|
|
86
|
+
description: 'E14 bulb RGBW',
|
|
87
|
+
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555], supportsHS: true}),
|
|
88
|
+
meta: {enhancedHue: false, applyRedFix: true, turnsOffAtBrightness1: true},
|
|
89
|
+
},
|
|
82
90
|
{
|
|
83
91
|
zigbeeModel: ['RB 265'],
|
|
84
92
|
model: 'RB 265',
|
package/devices/nous.js
CHANGED
|
@@ -7,6 +7,15 @@ const e = exposes.presets;
|
|
|
7
7
|
const ea = exposes.access;
|
|
8
8
|
|
|
9
9
|
module.exports = [
|
|
10
|
+
{
|
|
11
|
+
fingerprint: [{modelID: 'TS0201', manufacturerName: '_TZ3000_lbtpiody'}],
|
|
12
|
+
model: 'E5',
|
|
13
|
+
vendor: 'Nous',
|
|
14
|
+
description: 'Temperature & humidity',
|
|
15
|
+
fromZigbee: [fz.temperature, fz.humidity, fz.battery],
|
|
16
|
+
toZigbee: [],
|
|
17
|
+
exposes: [e.temperature(), e.humidity(), e.battery()],
|
|
18
|
+
},
|
|
10
19
|
{
|
|
11
20
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_nnrfa68v'}],
|
|
12
21
|
model: 'E6',
|
package/devices/philips.js
CHANGED
|
@@ -29,6 +29,15 @@ const hueExtend = {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
module.exports = [
|
|
32
|
+
{
|
|
33
|
+
zigbeeModel: ['929003047501'],
|
|
34
|
+
model: '929003047501',
|
|
35
|
+
vendor: 'Philips',
|
|
36
|
+
description: 'Centura recessed spotlight',
|
|
37
|
+
meta: {turnsOffAtBrightness1: true},
|
|
38
|
+
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
|
|
39
|
+
ota: ota.zigbeeOTA,
|
|
40
|
+
},
|
|
32
41
|
{
|
|
33
42
|
zigbeeModel: ['915005996401'],
|
|
34
43
|
model: '915005996401',
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const exposes = require('../lib/exposes');
|
|
2
|
+
const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
|
|
3
|
+
const tz = require('../converters/toZigbee');
|
|
4
|
+
const ea = exposes.access;
|
|
5
|
+
|
|
6
|
+
module.exports = [
|
|
7
|
+
{
|
|
8
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_6qoazbre'}],
|
|
9
|
+
model: 'WZ5_dim',
|
|
10
|
+
vendor: 'Skydance',
|
|
11
|
+
description: 'Zigbee & RF 5 in 1 LED controller (DIM mode)',
|
|
12
|
+
fromZigbee: [fz.tuya_light_wz5],
|
|
13
|
+
toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
|
|
14
|
+
exposes: [
|
|
15
|
+
exposes.light().withBrightness().setAccess('state',
|
|
16
|
+
ea.STATE_SET).setAccess('brightness', ea.STATE_SET),
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_gz3n0tzf'}],
|
|
21
|
+
model: 'WZ5_cct',
|
|
22
|
+
vendor: 'Skydance',
|
|
23
|
+
description: 'Zigbee & RF 5 in 1 LED controller (CCT mode)',
|
|
24
|
+
fromZigbee: [fz.tuya_light_wz5],
|
|
25
|
+
toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
|
|
26
|
+
exposes: [
|
|
27
|
+
exposes.light().withBrightness().setAccess('state',
|
|
28
|
+
ea.STATE_SET).setAccess('brightness', ea.STATE_SET).withColorTemp([250, 454]).setAccess('color_temp', ea.STATE_SET),
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_9hghastn'}],
|
|
33
|
+
model: 'WZ5_rgb',
|
|
34
|
+
vendor: 'Skydance',
|
|
35
|
+
description: 'Zigbee & RF 5 in 1 LED controller (RGB mode)',
|
|
36
|
+
fromZigbee: [fz.tuya_light_wz5],
|
|
37
|
+
toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
|
|
38
|
+
exposes: [
|
|
39
|
+
exposes.light().withBrightness().setAccess('state', ea.STATE_SET).setAccess('brightness',
|
|
40
|
+
ea.STATE_SET).withColor('hs'),
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_3thxjahu'}],
|
|
45
|
+
model: 'WZ5_rgbw',
|
|
46
|
+
vendor: 'Skydance',
|
|
47
|
+
description: 'Zigbee & RF 5 in 1 LED controller (RGBW mode)',
|
|
48
|
+
fromZigbee: [fz.tuya_light_wz5],
|
|
49
|
+
toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
|
|
50
|
+
exposes: [
|
|
51
|
+
exposes.light().withBrightness().setAccess('state', ea.STATE_SET).setAccess('brightness',
|
|
52
|
+
ea.STATE_SET).withColor('hs'),
|
|
53
|
+
exposes.numeric('white_brightness', ea.STATE_SET).withValueMin(0).withValueMax(254).withDescription(
|
|
54
|
+
'White brightness of this light'),
|
|
55
|
+
],
|
|
56
|
+
meta: {separateWhite: true},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_mde0utnv'}],
|
|
60
|
+
model: 'WZ5_rgbcct',
|
|
61
|
+
vendor: 'Skydance',
|
|
62
|
+
description: 'Zigbee & RF 5 in 1 LED controller (RGB+CCT mode)',
|
|
63
|
+
fromZigbee: [fz.tuya_light_wz5],
|
|
64
|
+
toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
|
|
65
|
+
exposes: [
|
|
66
|
+
exposes.light().withBrightness().setAccess('state', ea.STATE_SET).setAccess('brightness',
|
|
67
|
+
ea.STATE_SET).withColor('hs').withColorTemp([250, 454]).setAccess('color_temp',
|
|
68
|
+
ea.STATE_SET),
|
|
69
|
+
exposes.numeric('white_brightness', ea.STATE_SET).withValueMin(0).withValueMax(254).withDescription(
|
|
70
|
+
'White brightness of this light'),
|
|
71
|
+
],
|
|
72
|
+
meta: {separateWhite: true},
|
|
73
|
+
},
|
|
74
|
+
];
|
package/devices/tuya.js
CHANGED
|
@@ -12,7 +12,7 @@ const utils = require('../lib/utils');
|
|
|
12
12
|
|
|
13
13
|
const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak', '_TZ3000_ew3ldmgx', '_TZ3000_gjnozsaz',
|
|
14
14
|
'_TZ3000_jvzvulen', '_TZ3000_mraovvmm', '_TZ3000_nfnmi125', '_TZ3000_ps3dmato', '_TZ3000_w0qqde0g', '_TZ3000_u5u4cakc',
|
|
15
|
-
'_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_v1pdxuqq'];
|
|
15
|
+
'_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_v1pdxuqq', '_TZ3000_bfn1w0mm'];
|
|
16
16
|
|
|
17
17
|
const tzLocal = {
|
|
18
18
|
TS0504B_color: {
|
package/devices/xiaomi.js
CHANGED
|
@@ -686,6 +686,11 @@ module.exports = [
|
|
|
686
686
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
687
687
|
.withDescription('Decoupled mode'),
|
|
688
688
|
],
|
|
689
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
690
|
+
device.type = 'Router';
|
|
691
|
+
device.powerSource = 'Mains (single phase)';
|
|
692
|
+
device.save();
|
|
693
|
+
},
|
|
689
694
|
},
|
|
690
695
|
{
|
|
691
696
|
zigbeeModel: ['lumi.switch.b2nacn02'],
|
|
@@ -868,19 +873,17 @@ module.exports = [
|
|
|
868
873
|
zigbeeModel: ['lumi.motion.agl02'],
|
|
869
874
|
model: 'RTCGQ12LM',
|
|
870
875
|
vendor: 'Xiaomi',
|
|
871
|
-
description: 'Aqara T1 human body movement and illuminance sensor
|
|
872
|
-
fromZigbee: [fz.
|
|
873
|
-
toZigbee: [tz.
|
|
874
|
-
exposes: [e.occupancy(), e.
|
|
875
|
-
exposes.numeric('occupancy_timeout',
|
|
876
|
-
.withDescription('Time in seconds till occupancy goes to false')],
|
|
876
|
+
description: 'Aqara T1 human body movement and illuminance sensor',
|
|
877
|
+
fromZigbee: [fz.RTCGQ12LM_occupancy_illuminance, fz.aqara_opple, fz.battery],
|
|
878
|
+
toZigbee: [tz.aqara_occupancy_timeout],
|
|
879
|
+
exposes: [e.occupancy(), e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'),
|
|
880
|
+
exposes.numeric('occupancy_timeout', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
881
|
+
.withDescription('Time in seconds till occupancy goes to false'), e.battery()],
|
|
877
882
|
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
878
883
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
879
884
|
const endpoint = device.getEndpoint(1);
|
|
880
|
-
await
|
|
881
|
-
await
|
|
882
|
-
await reporting.batteryVoltage(endpoint);
|
|
883
|
-
await endpoint.read('msOccupancySensing', ['pirOToUDelay']);
|
|
885
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
886
|
+
await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
|
|
884
887
|
},
|
|
885
888
|
},
|
|
886
889
|
{
|
|
@@ -888,15 +891,15 @@ module.exports = [
|
|
|
888
891
|
model: 'RTCGQ13LM',
|
|
889
892
|
vendor: 'Xiaomi',
|
|
890
893
|
description: 'Aqara high precision motion sensor',
|
|
891
|
-
fromZigbee: [fz.
|
|
892
|
-
toZigbee: [tz.
|
|
893
|
-
exposes: [e.occupancy(),
|
|
894
|
-
exposes.
|
|
895
|
-
|
|
896
|
-
.withDescription('Time interval for detecting actions')],
|
|
894
|
+
fromZigbee: [fz.RTCGQ13LM_occupancy, fz.aqara_opple, fz.battery],
|
|
895
|
+
toZigbee: [tz.aqara_occupancy_timeout, tz.RTCGQ13LM_motion_sensitivity],
|
|
896
|
+
exposes: [e.occupancy(), exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
|
|
897
|
+
exposes.numeric('occupancy_timeout', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
898
|
+
.withDescription('Time in seconds till occupancy goes to false'), e.battery()],
|
|
897
899
|
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
898
900
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
899
901
|
const endpoint = device.getEndpoint(1);
|
|
902
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
900
903
|
await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
|
|
901
904
|
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
902
905
|
},
|
package/devices/zemismart.js
CHANGED
|
@@ -9,7 +9,7 @@ const tuya = require('../lib/tuya');
|
|
|
9
9
|
const fzLocal = {
|
|
10
10
|
ZMRM02: {
|
|
11
11
|
cluster: 'manuSpecificTuya',
|
|
12
|
-
type: ['commandGetData', 'commandSetDataResponse'],
|
|
12
|
+
type: ['commandGetData', 'commandSetDataResponse', 'commandDataResponse'],
|
|
13
13
|
convert: (model, msg, publish, options, meta) => {
|
|
14
14
|
const dpValue = tuya.firstDpValue(msg, meta, 'ZMRM02');
|
|
15
15
|
const button = dpValue.dp;
|
package/lib/exposes.js
CHANGED
|
@@ -527,7 +527,7 @@ module.exports = {
|
|
|
527
527
|
current: () => new Numeric('current', access.STATE).withUnit('A').withDescription('Instantaneous measured electrical current'),
|
|
528
528
|
current_phase_b: () => new Numeric('current_phase_b', access.STATE).withUnit('A').withDescription('Instantaneous measured electrical current on phase B'),
|
|
529
529
|
current_phase_c: () => new Numeric('current_phase_c', access.STATE).withUnit('A').withDescription('Instantaneous measured electrical current on phase C'),
|
|
530
|
-
deadzone_temperature: () => new Numeric('deadzone_temperature', access.STATE_SET).withUnit('°C').withDescription('The delta between local_temperature and current_heating_setpoint to trigger Heat').withValueMin(0
|
|
530
|
+
deadzone_temperature: () => new Numeric('deadzone_temperature', access.STATE_SET).withUnit('°C').withDescription('The delta between local_temperature and current_heating_setpoint to trigger Heat').withValueMin(0).withValueMax(5).withValueStep(1),
|
|
531
531
|
device_temperature: () => new Numeric('device_temperature', access.STATE).withUnit('°C').withDescription('Temperature of the device'),
|
|
532
532
|
eco2: () => new Numeric('eco2', access.STATE).withUnit('ppm').withDescription('Measured eCO2 value'),
|
|
533
533
|
eco_mode: () => new Binary('eco_mode', access.STATE_SET, 'ON', 'OFF').withDescription('ECO mode (energy saving mode)'),
|
package/lib/tuya.js
CHANGED
package/npm-shrinkwrap.json
CHANGED