zigbee-herdsman-converters 14.0.510 → 14.0.513
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 +33 -1
- package/converters/toZigbee.js +118 -75
- package/devices/awox.js +2 -0
- package/devices/ikea.js +11 -1
- package/devices/immax.js +5 -3
- package/devices/lellki.js +6 -25
- package/devices/mecrator.js +41 -0
- package/devices/moes.js +1 -1
- package/devices/namron.js +1 -1
- package/devices/philips.js +18 -0
- package/devices/tuya.js +22 -2
- package/devices/xiaomi.js +2 -1
- package/lib/tuya.js +6 -0
- package/package.json +2 -2
package/converters/fromZigbee.js
CHANGED
|
@@ -1699,7 +1699,7 @@ const converters = {
|
|
|
1699
1699
|
result.hysterersis = precisionRound(data[0x100A], 2) / 10;
|
|
1700
1700
|
}
|
|
1701
1701
|
if (data.hasOwnProperty(0x100B)) { // DisplayAutoOffEnable
|
|
1702
|
-
const lookup = {0: '
|
|
1702
|
+
const lookup = {0: 'enabled', 1: 'disabled'};
|
|
1703
1703
|
result.display_auto_off_enabled = lookup[data[0x100B]];
|
|
1704
1704
|
}
|
|
1705
1705
|
if (data.hasOwnProperty(0x2001)) { // AlarmAirTempOverValue
|
|
@@ -8496,6 +8496,38 @@ const converters = {
|
|
|
8496
8496
|
return result;
|
|
8497
8497
|
},
|
|
8498
8498
|
},
|
|
8499
|
+
ZG204ZL_lms: {
|
|
8500
|
+
cluster: 'manuSpecificTuya',
|
|
8501
|
+
type: ['commandDataResponse', 'commandDataReport'],
|
|
8502
|
+
convert: (model, msg, publish, options, meta) => {
|
|
8503
|
+
const result = {};
|
|
8504
|
+
for (const dpValue of msg.data.dpValues) {
|
|
8505
|
+
const dp = dpValue.dp;
|
|
8506
|
+
const value = tuya.getDataValue(dpValue);
|
|
8507
|
+
switch (dp) {
|
|
8508
|
+
case tuya.dataPoints.lmsState:
|
|
8509
|
+
result.occupancy = (value === 0);
|
|
8510
|
+
break;
|
|
8511
|
+
case tuya.dataPoints.lmsBattery:
|
|
8512
|
+
result.battery = value;
|
|
8513
|
+
break;
|
|
8514
|
+
case tuya.dataPoints.lmsSensitivity:
|
|
8515
|
+
result.sensitivity = {'0': 'low', '1': 'medium', '2': 'high'}[value];
|
|
8516
|
+
break;
|
|
8517
|
+
case tuya.dataPoints.lmsKeepTime:
|
|
8518
|
+
result.keep_time = {'0': '10', '1': '30', '2': '60', '3': '120'}[value];
|
|
8519
|
+
break;
|
|
8520
|
+
case tuya.dataPoints.lmsIlluminance:
|
|
8521
|
+
result.illuminance = value;
|
|
8522
|
+
break;
|
|
8523
|
+
default:
|
|
8524
|
+
meta.logger.warn(`zigbee-herdsman-converters:ZG204ZL_lms: NOT RECOGNIZED DP #${
|
|
8525
|
+
dp} with data ${JSON.stringify(dpValue)}`);
|
|
8526
|
+
}
|
|
8527
|
+
}
|
|
8528
|
+
return result;
|
|
8529
|
+
},
|
|
8530
|
+
},
|
|
8499
8531
|
// #endregion
|
|
8500
8532
|
|
|
8501
8533
|
// #region Ignore converters (these message dont need parsing).
|
package/converters/toZigbee.js
CHANGED
|
@@ -798,7 +798,7 @@ const converters = {
|
|
|
798
798
|
const {message} = meta;
|
|
799
799
|
const transition = utils.getTransition(entity, 'brightness', meta);
|
|
800
800
|
const turnsOffAtBrightness1 = utils.getMetaValue(entity, meta.mapped, 'turnsOffAtBrightness1', 'allEqual', false);
|
|
801
|
-
let state = message.hasOwnProperty('state') ? message.state.toLowerCase() : undefined;
|
|
801
|
+
let state = message.hasOwnProperty('state') ? (message.state === null ? null : message.state.toLowerCase()) : undefined;
|
|
802
802
|
let brightness = undefined;
|
|
803
803
|
if (message.hasOwnProperty('brightness')) {
|
|
804
804
|
brightness = Number(message.brightness);
|
|
@@ -806,91 +806,106 @@ const converters = {
|
|
|
806
806
|
brightness = utils.mapNumberRange(Number(message.brightness_percent), 0, 100, 0, 255);
|
|
807
807
|
}
|
|
808
808
|
|
|
809
|
-
if (brightness
|
|
810
|
-
// Allow 255
|
|
809
|
+
if (brightness === 255) {
|
|
810
|
+
// Allow 255 for backwards compatibility.
|
|
811
|
+
brightness = 254;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (brightness !== undefined && (isNaN(brightness) || brightness < 0 || brightness > 254)) {
|
|
811
815
|
throw new Error(`Brightness value of message: '${JSON.stringify(message)}' invalid, must be a number >= 0 and =< 254`);
|
|
812
816
|
}
|
|
813
817
|
|
|
814
|
-
if (state !== undefined && ['on', 'off', 'toggle'].includes(state) === false) {
|
|
818
|
+
if (state !== undefined && state !== null && ['on', 'off', 'toggle'].includes(state) === false) {
|
|
815
819
|
throw new Error(`State value of message: '${JSON.stringify(message)}' invalid, must be 'ON', 'OFF' or 'TOGGLE'`);
|
|
816
820
|
}
|
|
817
821
|
|
|
818
|
-
if (state ===
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
//
|
|
860
|
-
//
|
|
861
|
-
if (
|
|
862
|
-
|
|
863
|
-
globalStore.putValue(entity, 'turnedOffWithTransition', false);
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
const result = await converters.on_off.convertSet(entity, 'state', state, meta);
|
|
867
|
-
result.readAfterWriteTime = 0;
|
|
868
|
-
if (result.state && result.state.state === 'ON' && meta.state.brightness === 0) {
|
|
869
|
-
result.state.brightness = 1;
|
|
822
|
+
if ((state === undefined || state === null) && brightness === undefined) {
|
|
823
|
+
throw new Error(`At least one of "brightness" or "state" must have a value: '${JSON.stringify(message)}'`);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Infer state from desired brightness if unset. Ideally we'd want to keep it as it is, but this code has always
|
|
827
|
+
// used 'MoveToLevelWithOnOff' so that'd break backwards compatibility. To keep the state, the user
|
|
828
|
+
// has to explicitly set it to null.
|
|
829
|
+
if (state === undefined) {
|
|
830
|
+
// Also write to `meta.message.state` in case we delegate to the `on_off` converter.
|
|
831
|
+
state = meta.message.state = brightness === 0 ? 'off' : 'on';
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const targetState = state === 'toggle' ? (meta.state.state === 'ON' ? 'off' : 'on') : state;
|
|
835
|
+
if (targetState === 'off') {
|
|
836
|
+
// Simulate 'Off' with transition via 'MoveToLevelWithOnOff', otherwise just use 'Off'.
|
|
837
|
+
// TODO: if this is a group where some members don't support Level Control, turning them off
|
|
838
|
+
// with transition may have no effect. (Some devices, such as Envilar ZG302-BOX-RELAY, handle
|
|
839
|
+
// 'MoveToLevelWithOnOff' despite not supporting the cluster; others, like the LEDVANCE SMART+
|
|
840
|
+
// plug, do not.)
|
|
841
|
+
brightness = transition.specified || brightness === 0 ? 0 : undefined;
|
|
842
|
+
if (meta.state.hasOwnProperty('brightness') && meta.state.state === 'ON') {
|
|
843
|
+
// The light's current level gets clobbered in two cases:
|
|
844
|
+
// 1. when 'Off' has a transition, in which case it is really 'MoveToLevelWithOnOff'
|
|
845
|
+
// https://github.com/Koenkk/zigbee-herdsman-converters/issues/1073
|
|
846
|
+
// 2. when 'OnLevel' is set: "If OnLevel is not defined, set the CurrentLevel to the stored level."
|
|
847
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/2850#issuecomment-580365633
|
|
848
|
+
// We need to remember current brightness in case the next 'On' does not provide it. `meta` is not reliable
|
|
849
|
+
// here, as it will get clobbered too if reporting is configured.
|
|
850
|
+
globalStore.putValue(entity, 'brightness', meta.state.brightness);
|
|
851
|
+
globalStore.putValue(entity, 'turnedOffWithTransition', brightness !== undefined);
|
|
852
|
+
}
|
|
853
|
+
} else if (targetState === 'on' && brightness === undefined) {
|
|
854
|
+
// Simulate 'On' with transition via 'MoveToLevelWithOnOff', or restore the level from before
|
|
855
|
+
// it was clobbered by a previous transition to off; otherwise just use 'On'.
|
|
856
|
+
// TODO: same problem as above.
|
|
857
|
+
// TODO: if transition is not specified, should use device default (OnTransitionTime), not 0.
|
|
858
|
+
if (transition.specified || globalStore.getValue(entity, 'turnedOffWithTransition') === true) {
|
|
859
|
+
const current = utils.getObjectProperty(meta.state, 'brightness', 254);
|
|
860
|
+
brightness = globalStore.getValue(entity, 'brightness', current);
|
|
861
|
+
try {
|
|
862
|
+
const attributeRead = await entity.read('genLevelCtrl', ['onLevel']);
|
|
863
|
+
// TODO: for groups, `read` does not wait for responses. If it did, we could still issue a single
|
|
864
|
+
// command if all values of `OnLevel` are equal, or split into one command per device if not.
|
|
865
|
+
if (attributeRead !== undefined && attributeRead['onLevel'] != 255) {
|
|
866
|
+
brightness = attributeRead['onLevel'];
|
|
870
867
|
}
|
|
871
|
-
|
|
872
|
-
|
|
868
|
+
} catch (e) {
|
|
869
|
+
// OnLevel not supported
|
|
873
870
|
}
|
|
874
871
|
}
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (brightness === undefined) {
|
|
875
|
+
const result = await converters.on_off.convertSet(entity, 'state', state, meta);
|
|
876
|
+
result.readAfterWriteTime = 0;
|
|
877
|
+
if (result.state && result.state.state === 'ON' && meta.state.brightness === 0) {
|
|
878
|
+
result.state.brightness = 1;
|
|
879
879
|
}
|
|
880
|
+
return result;
|
|
881
|
+
}
|
|
880
882
|
|
|
883
|
+
if (brightness === 0 && (targetState === 'on' || state === null)) {
|
|
884
|
+
brightness = 1;
|
|
885
|
+
}
|
|
886
|
+
if (brightness === 1 && turnsOffAtBrightness1) {
|
|
887
|
+
brightness = 2;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (targetState !== 'off') {
|
|
881
891
|
globalStore.putValue(entity, 'brightness', brightness);
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
)
|
|
892
|
+
globalStore.clearValue(entity, 'turnedOffWithTransition');
|
|
893
|
+
}
|
|
894
|
+
await entity.command(
|
|
895
|
+
'genLevelCtrl',
|
|
896
|
+
state === null ? 'moveToLevel' : 'moveToLevelWithOnOff',
|
|
897
|
+
{level: Number(brightness), transtime: transition.time},
|
|
898
|
+
utils.getOptions(meta.mapped, entity),
|
|
899
|
+
);
|
|
888
900
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
901
|
+
const result = {state: {}, readAfterWriteTime: transition.time * 100};
|
|
902
|
+
if (brightness !== 0) {
|
|
903
|
+
result.state.brightness = Number(brightness);
|
|
904
|
+
}
|
|
905
|
+
if (state !== null) {
|
|
906
|
+
result.state.state = brightness === 0 ? 'OFF' : 'ON';
|
|
893
907
|
}
|
|
908
|
+
return result;
|
|
894
909
|
},
|
|
895
910
|
convertGet: async (entity, key, meta) => {
|
|
896
911
|
if (key === 'brightness') {
|
|
@@ -2546,8 +2561,9 @@ const converters = {
|
|
|
2546
2561
|
key: ['state'],
|
|
2547
2562
|
convertSet: async (entity, key, value, meta) => {
|
|
2548
2563
|
const options = {disableDefaultResponse: true};
|
|
2564
|
+
value = value.toLowerCase();
|
|
2549
2565
|
utils.validateValue(value, ['toggle', 'off', 'on']);
|
|
2550
|
-
if (value
|
|
2566
|
+
if (value === 'toggle') {
|
|
2551
2567
|
if (!meta.state.hasOwnProperty('state')) {
|
|
2552
2568
|
throw new Error('Cannot toggle, state not known yet');
|
|
2553
2569
|
} else {
|
|
@@ -3076,10 +3092,10 @@ const converters = {
|
|
|
3076
3092
|
const payload = {0x1009: {value: value * 2, type: 0x20}};
|
|
3077
3093
|
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3078
3094
|
} else if (key==='hysterersis') {
|
|
3079
|
-
const payload = {0x100A: {value: value* 10, type: 0x20}};
|
|
3095
|
+
const payload = {0x100A: {value: value * 10, type: 0x20}};
|
|
3080
3096
|
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3081
3097
|
} else if (key==='display_auto_off_enabled') {
|
|
3082
|
-
const lookup = {'
|
|
3098
|
+
const lookup = {'enabled': 0, 'disabled': 1};
|
|
3083
3099
|
const payload = {0x100B: {value: lookup[value], type: herdsman.Zcl.DataType.enum8}};
|
|
3084
3100
|
await entity.write('hvacThermostat', payload, manufacturerOptions.sunricher);
|
|
3085
3101
|
} else if (key==='alarm_airtemp_overvalue') {
|
|
@@ -7420,6 +7436,33 @@ const converters = {
|
|
|
7420
7436
|
}
|
|
7421
7437
|
},
|
|
7422
7438
|
},
|
|
7439
|
+
ZG204ZL_lms: {
|
|
7440
|
+
key: ['sensitivity', 'keep_time'],
|
|
7441
|
+
convertSet: async (entity, key, value, meta) => {
|
|
7442
|
+
switch (key) {
|
|
7443
|
+
case 'sensitivity':
|
|
7444
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.lmsSensitivity, {'low': 0, 'medium': 1, 'high': 2}[value]);
|
|
7445
|
+
break;
|
|
7446
|
+
case 'keep_time':
|
|
7447
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.lmsKeepTime, {'10': 0, '30': 1, '60': 2, '120': 3}[value]);
|
|
7448
|
+
break;
|
|
7449
|
+
default: // Unknown key
|
|
7450
|
+
meta.logger.warn(`tz.ZG204ZL_lms: Unhandled key ${key}`);
|
|
7451
|
+
}
|
|
7452
|
+
},
|
|
7453
|
+
convertGet: async (entity, key, meta) => {
|
|
7454
|
+
switch (key) {
|
|
7455
|
+
case 'sensitivity':
|
|
7456
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.lmsSensitivity, 0, 'dataQuery' );
|
|
7457
|
+
break;
|
|
7458
|
+
case 'keep_time':
|
|
7459
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.lmsKeepTime, 0, 'dataQuery' );
|
|
7460
|
+
break;
|
|
7461
|
+
default: // Unknown key
|
|
7462
|
+
meta.logger.warn(`Unhandled key toZigbee.ZG204ZL_lms.convertGet ${key}`);
|
|
7463
|
+
}
|
|
7464
|
+
},
|
|
7465
|
+
},
|
|
7423
7466
|
// #endregion
|
|
7424
7467
|
|
|
7425
7468
|
// #region Ignore converters
|
package/devices/awox.js
CHANGED
|
@@ -67,6 +67,7 @@ module.exports = [
|
|
|
67
67
|
vendor: 'AwoX',
|
|
68
68
|
description: 'LED white',
|
|
69
69
|
extend: extend.light_onoff_brightness(),
|
|
70
|
+
whiteLabel: [{vendor: 'EGLO', model: '12229'}],
|
|
70
71
|
},
|
|
71
72
|
{
|
|
72
73
|
fingerprint: [
|
|
@@ -248,6 +249,7 @@ module.exports = [
|
|
|
248
249
|
vendor: 'AwoX',
|
|
249
250
|
description: 'LED light with color temperature',
|
|
250
251
|
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
|
|
252
|
+
whiteLabel: [{vendor: 'EGLO', model: '12239'}],
|
|
251
253
|
},
|
|
252
254
|
{
|
|
253
255
|
fingerprint: [
|
package/devices/ikea.js
CHANGED
|
@@ -13,11 +13,15 @@ const {
|
|
|
13
13
|
calibrateAndPrecisionRoundOptions, postfixWithEndpointName, getMetaValue,
|
|
14
14
|
} = require('../lib/utils');
|
|
15
15
|
|
|
16
|
-
const bulbOnEvent = async (type, data, device) => {
|
|
16
|
+
const bulbOnEvent = async (type, data, device, options, state) => {
|
|
17
17
|
/**
|
|
18
18
|
* IKEA bulbs lose their configured reportings when losing power.
|
|
19
19
|
* A deviceAnnounce indicates they are powered on again.
|
|
20
20
|
* Reconfigure the configured reoprting here.
|
|
21
|
+
*
|
|
22
|
+
* Additionally some other information is lost like
|
|
23
|
+
* color_options.execute_if_off. We also restore these.
|
|
24
|
+
*
|
|
21
25
|
* NOTE: binds are not lost so rebinding is not needed!
|
|
22
26
|
*/
|
|
23
27
|
if (type === 'deviceAnnounce') {
|
|
@@ -29,6 +33,12 @@ const bulbOnEvent = async (type, data, device) => {
|
|
|
29
33
|
}]);
|
|
30
34
|
}
|
|
31
35
|
}
|
|
36
|
+
|
|
37
|
+
// NOTE: execute_if_off default is false
|
|
38
|
+
// we only restore if true, to save unneeded network writes
|
|
39
|
+
if (state.color_options.execute_if_off === true) {
|
|
40
|
+
device.endpoints[0].write('lightingColorCtrl', {'options': 1});
|
|
41
|
+
}
|
|
32
42
|
}
|
|
33
43
|
};
|
|
34
44
|
|
package/devices/immax.js
CHANGED
|
@@ -66,16 +66,18 @@ module.exports = [
|
|
|
66
66
|
model: '07048L',
|
|
67
67
|
vendor: 'Immax',
|
|
68
68
|
description: 'NEO SMART plug',
|
|
69
|
-
fromZigbee: [fz.on_off, fz.electrical_measurement],
|
|
69
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
|
|
70
70
|
toZigbee: [tz.on_off],
|
|
71
71
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
72
72
|
const endpoint = device.getEndpoint(1);
|
|
73
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
|
|
73
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
74
74
|
await reporting.onOff(endpoint);
|
|
75
75
|
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
|
|
76
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
77
|
+
await reporting.currentSummDelivered(endpoint);
|
|
76
78
|
await reporting.activePower(endpoint);
|
|
77
79
|
},
|
|
78
|
-
exposes: [e.switch(), e.power()],
|
|
80
|
+
exposes: [e.switch(), e.power(), e.energy()],
|
|
79
81
|
},
|
|
80
82
|
{
|
|
81
83
|
zigbeeModel: ['losfena'],
|
package/devices/lellki.js
CHANGED
|
@@ -9,9 +9,10 @@ const tuya = require('../lib/tuya');
|
|
|
9
9
|
|
|
10
10
|
module.exports = [
|
|
11
11
|
{
|
|
12
|
-
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_air9m6af'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_9djocypn'}
|
|
12
|
+
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_air9m6af'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_9djocypn'},
|
|
13
|
+
{modelID: 'TS011F', manufacturerName: '_TZ3000_bppxj3sf'}],
|
|
13
14
|
zigbeeModel: ['JZ-ZB-005'],
|
|
14
|
-
model: 'WP33-EU',
|
|
15
|
+
model: 'WP33-EU/WP34-EU',
|
|
15
16
|
vendor: 'LELLKI',
|
|
16
17
|
description: 'Multiprise with 4 AC outlets and 2 USB super charging ports (16A)',
|
|
17
18
|
extend: extend.switch(),
|
|
@@ -22,11 +23,9 @@ module.exports = [
|
|
|
22
23
|
return {l1: 1, l2: 2, l3: 3, l4: 4, l5: 5};
|
|
23
24
|
},
|
|
24
25
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
|
|
29
|
-
await reporting.bind(device.getEndpoint(5), coordinatorEndpoint, ['genOnOff']);
|
|
26
|
+
for (const ID of [1, 2, 3, 4, 5]) {
|
|
27
|
+
await reporting.bind(device.getEndpoint(ID), coordinatorEndpoint, ['genOnOff']);
|
|
28
|
+
}
|
|
30
29
|
},
|
|
31
30
|
},
|
|
32
31
|
{
|
|
@@ -104,24 +103,6 @@ module.exports = [
|
|
|
104
103
|
.withDescription('Recover state after power outage')],
|
|
105
104
|
onEvent: tuya.onEventMeasurementPoll,
|
|
106
105
|
},
|
|
107
|
-
{
|
|
108
|
-
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_bppxj3sf'}],
|
|
109
|
-
model: 'WP34-EU',
|
|
110
|
-
vendor: 'LELLKI',
|
|
111
|
-
description: 'Outlet power cord with 4 sockets and 2 USB',
|
|
112
|
-
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
|
|
113
|
-
e.switch().withEndpoint('l4'), e.switch().withEndpoint('l5')],
|
|
114
|
-
extend: extend.switch(),
|
|
115
|
-
meta: {multiEndpoint: true},
|
|
116
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
117
|
-
for (const ID of [1, 2, 3, 4, 5]) {
|
|
118
|
-
await reporting.bind(device.getEndpoint(ID), coordinatorEndpoint, ['genOnOff']);
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
endpoint: (device) => {
|
|
122
|
-
return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4, 'l5': 5};
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
106
|
{
|
|
126
107
|
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_0yxeawjt'}],
|
|
127
108
|
model: 'WK34-EU',
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const exposes = require('../lib/exposes');
|
|
2
|
+
const fz = require('../converters/fromZigbee');
|
|
3
|
+
const tz = require('../converters/toZigbee');
|
|
4
|
+
const reporting = require('../lib/reporting');
|
|
5
|
+
const e = exposes.presets;
|
|
6
|
+
const ea = exposes.access;
|
|
7
|
+
|
|
8
|
+
module.exports = [
|
|
9
|
+
{
|
|
10
|
+
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3210_7jnk7l3k'}],
|
|
11
|
+
model: 'SPP02GIP',
|
|
12
|
+
vendor: 'Mercator',
|
|
13
|
+
description: 'Ikuü double outdoors power point',
|
|
14
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory],
|
|
15
|
+
toZigbee: [tz.on_off],
|
|
16
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
|
|
17
|
+
e.power().withEndpoint('left'), e.current().withEndpoint('left'),
|
|
18
|
+
e.voltage().withEndpoint('left').withAccess(ea.STATE), e.energy()],
|
|
19
|
+
endpoint: (device) => {
|
|
20
|
+
return {left: 1, right: 2};
|
|
21
|
+
},
|
|
22
|
+
meta: {multiEndpoint: true},
|
|
23
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
24
|
+
const endpoint1 = device.getEndpoint(1);
|
|
25
|
+
const endpoint2 = device.getEndpoint(2);
|
|
26
|
+
await reporting.bind(endpoint1, coordinatorEndpoint, ['genBasic', 'genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
27
|
+
await reporting.bind(endpoint2, coordinatorEndpoint, ['genOnOff']);
|
|
28
|
+
await reporting.onOff(endpoint1);
|
|
29
|
+
await reporting.onOff(endpoint1);
|
|
30
|
+
await reporting.onOff(endpoint1);
|
|
31
|
+
await reporting.rmsVoltage(endpoint1, {change: 5});
|
|
32
|
+
await reporting.rmsCurrent(endpoint1, {change: 50});
|
|
33
|
+
await reporting.activePower(endpoint1, {change: 1});
|
|
34
|
+
await reporting.onOff(endpoint1);
|
|
35
|
+
await reporting.onOff(endpoint2);
|
|
36
|
+
endpoint1.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
|
|
37
|
+
endpoint1.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
|
|
38
|
+
device.save();
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
];
|
package/devices/moes.js
CHANGED
|
@@ -165,7 +165,7 @@ module.exports = [
|
|
|
165
165
|
},
|
|
166
166
|
},
|
|
167
167
|
{
|
|
168
|
-
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_tz32mtza'}
|
|
168
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_tz32mtza'}],
|
|
169
169
|
model: 'ZTS-EU_3gang',
|
|
170
170
|
vendor: 'Moes',
|
|
171
171
|
description: 'Wall touch light switch (3 gang)',
|
package/devices/namron.js
CHANGED
|
@@ -314,7 +314,7 @@ module.exports = [
|
|
|
314
314
|
.withUnit('°C')
|
|
315
315
|
.withValueMin(0.5).withValueMax(2).withValueStep(0.1)
|
|
316
316
|
.withDescription('Hysteresis setting, between 0.5 and 2 in 0.1 °C. Default: 0.5.'),
|
|
317
|
-
exposes.enum('display_auto_off_enabled', ea.ALL, ['
|
|
317
|
+
exposes.enum('display_auto_off_enabled', ea.ALL, ['enabled', 'disabled']),
|
|
318
318
|
exposes.numeric('alarm_airtemp_overvalue', ea.ALL)
|
|
319
319
|
.withUnit('°C')
|
|
320
320
|
.withValueMin(20).withValueMax(60)
|
package/devices/philips.js
CHANGED
|
@@ -81,6 +81,15 @@ module.exports = [
|
|
|
81
81
|
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
82
82
|
ota: ota.zigbeeOTA,
|
|
83
83
|
},
|
|
84
|
+
{
|
|
85
|
+
zigbeeModel: ['929003045501_01', '929003045501_02', '929003045501_03'],
|
|
86
|
+
model: '929003045501',
|
|
87
|
+
vendor: 'Philips',
|
|
88
|
+
description: 'Hue Centura recessed spotlight white and color ambiance GU10 (black)',
|
|
89
|
+
meta: {turnsOffAtBrightness1: true},
|
|
90
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
91
|
+
ota: ota.zigbeeOTA,
|
|
92
|
+
},
|
|
84
93
|
{
|
|
85
94
|
zigbeeModel: ['929003047501'],
|
|
86
95
|
model: '929003047501',
|
|
@@ -2636,6 +2645,15 @@ module.exports = [
|
|
|
2636
2645
|
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
2637
2646
|
ota: ota.zigbeeOTA,
|
|
2638
2647
|
},
|
|
2648
|
+
{
|
|
2649
|
+
zigbeeModel: ['929003045601_01', '929003045601_02'],
|
|
2650
|
+
model: '8719514338142',
|
|
2651
|
+
vendor: 'Philips',
|
|
2652
|
+
description: 'Hue White ambiance Runner double spotlight',
|
|
2653
|
+
meta: {turnsOffAtBrightness1: true},
|
|
2654
|
+
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
2655
|
+
ota: ota.zigbeeOTA,
|
|
2656
|
+
},
|
|
2639
2657
|
{
|
|
2640
2658
|
zigbeeModel: ['5047230P6', '5047230P6'],
|
|
2641
2659
|
model: '5047230P6',
|
package/devices/tuya.js
CHANGED
|
@@ -592,7 +592,7 @@ module.exports = [
|
|
|
592
592
|
},
|
|
593
593
|
},
|
|
594
594
|
{
|
|
595
|
-
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_aqnazj70'}],
|
|
595
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_aqnazj70'}, {modelID: 'TS0601', manufacturerName: 'TZE200_k6jhsr0q'}],
|
|
596
596
|
model: 'TS0601_switch_4_gang',
|
|
597
597
|
vendor: 'TuYa',
|
|
598
598
|
description: '4 gang switch',
|
|
@@ -712,6 +712,7 @@ module.exports = [
|
|
|
712
712
|
{modelID: 'TS0502B', manufacturerName: '_TZ3210_ijsj2evj'},
|
|
713
713
|
{modelID: 'TS0502B', manufacturerName: '_TZ3210_pgq2qvyv'},
|
|
714
714
|
{modelID: 'TS0502B', manufacturerName: '_TZ3210_nvaik6gk'},
|
|
715
|
+
{modelID: 'TS0502B', manufacturerName: '_TZ3000_armwcncd'},
|
|
715
716
|
],
|
|
716
717
|
model: 'TS0502B',
|
|
717
718
|
vendor: 'TuYa',
|
|
@@ -1417,7 +1418,10 @@ module.exports = [
|
|
|
1417
1418
|
.withDescription('Plug LED indicator mode'), e.child_lock()],
|
|
1418
1419
|
},
|
|
1419
1420
|
{
|
|
1420
|
-
fingerprint: [
|
|
1421
|
+
fingerprint: [
|
|
1422
|
+
{modelID: 'TS011F', manufacturerName: '_TZ3000_gjnozsaz', applicationVersion: 74},
|
|
1423
|
+
{modelID: 'TS011F', manufacturerName: '_TZ3000_cehuw1lw', applicationVersion: 74},
|
|
1424
|
+
]
|
|
1421
1425
|
.concat(...TS011Fplugs.map((manufacturerName) => {
|
|
1422
1426
|
return [69, 68, 65, 64].map((applicationVersion) => {
|
|
1423
1427
|
return {modelID: 'TS011F', manufacturerName, applicationVersion};
|
|
@@ -2350,4 +2354,20 @@ module.exports = [
|
|
|
2350
2354
|
onEvent: tuya.onEventSetLocalTime,
|
|
2351
2355
|
exposes: [e.temperature(), e.humidity(), e.battery()],
|
|
2352
2356
|
},
|
|
2357
|
+
{
|
|
2358
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_3towulqd'}],
|
|
2359
|
+
model: 'ZG-204ZL',
|
|
2360
|
+
vendor: 'TuYa',
|
|
2361
|
+
description: 'Luminance motion sensor',
|
|
2362
|
+
fromZigbee: [fz.ZG204ZL_lms],
|
|
2363
|
+
toZigbee: [tz.ZG204ZL_lms],
|
|
2364
|
+
exposes: [
|
|
2365
|
+
e.occupancy(), e.illuminance(), e.battery(),
|
|
2366
|
+
exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high'])
|
|
2367
|
+
.withDescription('PIR sensor sensitivity (refresh and update only while active)'),
|
|
2368
|
+
exposes.enum('keep_time', ea.ALL, ['10', '30', '60', '120'])
|
|
2369
|
+
.withDescription('PIR keep time in seconds (refresh and update only while active)'),
|
|
2370
|
+
],
|
|
2371
|
+
},
|
|
2372
|
+
|
|
2353
2373
|
];
|
package/devices/xiaomi.js
CHANGED
|
@@ -884,7 +884,8 @@ module.exports = [
|
|
|
884
884
|
description: 'Aqara T1 human body movement and illuminance sensor',
|
|
885
885
|
fromZigbee: [fz.aqara_occupancy_illuminance, fz.aqara_opple, fz.battery],
|
|
886
886
|
toZigbee: [tz.aqara_detection_interval],
|
|
887
|
-
exposes: [e.occupancy(), e.
|
|
887
|
+
exposes: [e.occupancy(), e.illuminance_lux().withProperty('illuminance'),
|
|
888
|
+
e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'),
|
|
888
889
|
exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
889
890
|
.withDescription('Time interval for detecting actions'), e.temperature(), e.battery()],
|
|
890
891
|
meta: {battery: {voltageToPercentage: '3V_2850_3000_log'}},
|
package/lib/tuya.js
CHANGED
|
@@ -686,6 +686,12 @@ const dataPoints = {
|
|
|
686
686
|
tshpsIlluminanceLux: 104,
|
|
687
687
|
tshpsCLI: 103, // not recognize
|
|
688
688
|
tshpsSelfTest: 6, // not recognize
|
|
689
|
+
// TuYa Luminance Motion sensor
|
|
690
|
+
lmsState: 1,
|
|
691
|
+
lmsBattery: 4,
|
|
692
|
+
lmsSensitivity: 9,
|
|
693
|
+
lmsKeepTime: 10,
|
|
694
|
+
lmsIlluminance: 12,
|
|
689
695
|
};
|
|
690
696
|
|
|
691
697
|
const thermostatWeekFormat = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zigbee-herdsman-converters",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.513",
|
|
4
4
|
"description": "Collection of device converters to be used with zigbee-herdsman",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"buffer-crc32": "^0.2.13",
|
|
39
39
|
"https-proxy-agent": "^5.0.1",
|
|
40
40
|
"tar-stream": "^2.2.0",
|
|
41
|
-
"zigbee-herdsman": "^0.14.
|
|
41
|
+
"zigbee-herdsman": "^0.14.28"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"eslint": "*",
|