zigbee-herdsman-converters 14.0.314 → 14.0.318
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 +199 -0
- package/converters/toZigbee.js +138 -5
- package/devices/aurora_lighting.js +29 -22
- package/devices/bitron.js +1 -1
- package/devices/centralite.js +4 -2
- package/devices/develco.js +16 -3
- package/devices/ecozy.js +2 -1
- package/devices/elko.js +1 -1
- package/devices/eurotronic.js +2 -1
- package/devices/hgkg.js +1 -1
- package/devices/hive.js +51 -0
- package/devices/ikea.js +37 -5
- package/devices/innr.js +24 -0
- package/devices/javis.js +21 -1
- package/devices/leedarson.js +40 -1
- package/devices/leviton.js +2 -1
- package/devices/lidl.js +19 -1
- package/devices/livolo.js +29 -0
- package/devices/miboxer.js +7 -0
- package/devices/moes.js +4 -3
- package/devices/philips.js +64 -1
- package/devices/saswell.js +2 -1
- package/devices/schneider_electric.js +1 -1
- package/devices/tuya.js +82 -5
- package/devices/zen.js +2 -2
- package/lib/constants.js +12 -0
- package/lib/exposes.js +3 -2
- package/lib/utils.js +1 -1
- package/npm-shrinkwrap.json +167 -154
- package/package.json +2 -2
package/converters/fromZigbee.js
CHANGED
|
@@ -648,6 +648,26 @@ const converters = {
|
|
|
648
648
|
return payload;
|
|
649
649
|
},
|
|
650
650
|
},
|
|
651
|
+
develco_metering: {
|
|
652
|
+
cluster: 'seMetering',
|
|
653
|
+
type: ['attributeReport', 'readResponse'],
|
|
654
|
+
convert: (model, msg, publish, options, meta) => {
|
|
655
|
+
const result = {};
|
|
656
|
+
if (msg.data.hasOwnProperty('develcoPulseConfiguration')) {
|
|
657
|
+
result[postfixWithEndpointName('pulse_configuration', msg, model)] =
|
|
658
|
+
msg.data['develcoPulseConfiguration'];
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (msg.data.hasOwnProperty('develcoInterfaceMode')) {
|
|
662
|
+
result[postfixWithEndpointName('interface_mode', msg, model)] =
|
|
663
|
+
constants.develcoInterfaceMode.hasOwnProperty(msg.data['develcoInterfaceMode']) ?
|
|
664
|
+
constants.develcoInterfaceMode[msg.data['develcoInterfaceMode']] :
|
|
665
|
+
msg.data['develcoInterfaceMode'];
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return result;
|
|
669
|
+
},
|
|
670
|
+
},
|
|
651
671
|
electrical_measurement: {
|
|
652
672
|
/**
|
|
653
673
|
* When using this converter also add the following to the configure method of the device:
|
|
@@ -2485,6 +2505,22 @@ const converters = {
|
|
|
2485
2505
|
}
|
|
2486
2506
|
},
|
|
2487
2507
|
},
|
|
2508
|
+
livolo_curtain_switch_state: {
|
|
2509
|
+
cluster: 'genPowerCfg',
|
|
2510
|
+
type: ['raw'],
|
|
2511
|
+
convert: (model, msg, publish, options, meta) => {
|
|
2512
|
+
const stateHeader = Buffer.from([122, 209]);
|
|
2513
|
+
if (msg.data.indexOf(stateHeader) === 0) {
|
|
2514
|
+
if (msg.data[10] === 5) {
|
|
2515
|
+
const status = msg.data[14];
|
|
2516
|
+
return {
|
|
2517
|
+
state_left: status === 1 ? 'ON' : 'OFF',
|
|
2518
|
+
state_right: status === 0 ? 'ON' : 'OFF',
|
|
2519
|
+
};
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
},
|
|
2523
|
+
},
|
|
2488
2524
|
livolo_dimmer_state: {
|
|
2489
2525
|
cluster: 'genPowerCfg',
|
|
2490
2526
|
type: ['raw'],
|
|
@@ -2592,16 +2628,24 @@ const converters = {
|
|
|
2592
2628
|
[124,210,21,216,128, 199,147,3,24,0,75,18,0, 19,7,0] after interview
|
|
2593
2629
|
[122,209, 199,147,3,24,0,75,18,0, 7,1,6,1,0,11] off
|
|
2594
2630
|
[122,209, 199,147,3,24,0,75,18,0, 7,1,6,1,1,11] on
|
|
2631
|
+
|
|
2595
2632
|
new switch
|
|
2596
2633
|
[124,210,21,216,128, 228,41,3,24,0,75,18,0, 19,1,0] after interview
|
|
2597
2634
|
[122,209, 228,41,3,24,0,75,18,0, 7,1,0,1,0,11] off
|
|
2598
2635
|
[122,209, 228,41,3,24,0,75,18,0, 7,1,0,1,1,11] on
|
|
2636
|
+
|
|
2599
2637
|
old switch
|
|
2600
2638
|
[124,210,21,216,128, 170, 10,2,24,0,75,18,0, 17,0,1] after interview
|
|
2601
2639
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,0] left: 0, right: 0
|
|
2602
2640
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,1] left: 1, right: 0
|
|
2603
2641
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,2] left: 0, right: 1
|
|
2604
2642
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,3] left: 1, right: 1
|
|
2643
|
+
|
|
2644
|
+
curtain switch
|
|
2645
|
+
[124,210,21,216,128, 110,74,116,33,0,75,18,0, 19,5,0] after interview
|
|
2646
|
+
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,2,11] left: 0, right: 0 (off)
|
|
2647
|
+
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,1,11] left: 1, right: 0 (left on)
|
|
2648
|
+
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,0,11] left: 0, right: 1 (right on)
|
|
2605
2649
|
*/
|
|
2606
2650
|
const malformedHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x00]);
|
|
2607
2651
|
const infoHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x80]);
|
|
@@ -2630,6 +2674,12 @@ const converters = {
|
|
|
2630
2674
|
meta.device.modelID = 'TI0001-switch-2gang';
|
|
2631
2675
|
meta.device.save();
|
|
2632
2676
|
}
|
|
2677
|
+
if (msg.data.includes(Buffer.from([19, 5, 0]), 13)) {
|
|
2678
|
+
if (meta.logger) meta.logger.debug('Detected Livolo Curtain Switch');
|
|
2679
|
+
// curtain switch, hack
|
|
2680
|
+
meta.device.modelID = 'TI0001-curtain-switch';
|
|
2681
|
+
meta.device.save();
|
|
2682
|
+
}
|
|
2633
2683
|
if (msg.data.includes(Buffer.from([19, 20, 0]), 13)) {
|
|
2634
2684
|
// new dimmer, hack
|
|
2635
2685
|
meta.device.modelID = 'TI0001-dimmer';
|
|
@@ -4245,6 +4295,79 @@ const converters = {
|
|
|
4245
4295
|
}
|
|
4246
4296
|
},
|
|
4247
4297
|
},
|
|
4298
|
+
ikea_air_purifier: {
|
|
4299
|
+
cluster: 'manuSpecificIkeaAirPurifier',
|
|
4300
|
+
type: ['attributeReport', 'readResponse'],
|
|
4301
|
+
options: [exposes.options.precision('pm25'), exposes.options.calibration('pm25')],
|
|
4302
|
+
convert: (model, msg, publish, options, meta) => {
|
|
4303
|
+
const state = {};
|
|
4304
|
+
|
|
4305
|
+
if (msg.data.hasOwnProperty('particulateMatter25Measurement')) {
|
|
4306
|
+
const pm25Property = postfixWithEndpointName('pm25', msg, model);
|
|
4307
|
+
let pm25 = parseFloat(msg.data['particulateMatter25Measurement']);
|
|
4308
|
+
|
|
4309
|
+
// Air Quality Scale (ikea app):
|
|
4310
|
+
// 0-35=Good, 35-80=OK, 80+=Not Good
|
|
4311
|
+
let airQuality;
|
|
4312
|
+
const airQualityProperty = postfixWithEndpointName('air_quality', msg, model);
|
|
4313
|
+
if (pm25 <= 35) {
|
|
4314
|
+
airQuality = 'good';
|
|
4315
|
+
} else if (pm25 <= 80) {
|
|
4316
|
+
airQuality = 'ok';
|
|
4317
|
+
} else if (pm25 < 65535) {
|
|
4318
|
+
airQuality = 'not_good';
|
|
4319
|
+
} else {
|
|
4320
|
+
airQuality = 'unknown';
|
|
4321
|
+
}
|
|
4322
|
+
|
|
4323
|
+
// calibrate and round pm25 unless invalid
|
|
4324
|
+
pm25 = (pm25 == 65535) ? -1 : calibrateAndPrecisionRoundOptions(pm25, options, 'pm25');
|
|
4325
|
+
|
|
4326
|
+
state[pm25Property] = calibrateAndPrecisionRoundOptions(pm25, options, 'pm25');
|
|
4327
|
+
state[airQualityProperty] = airQuality;
|
|
4328
|
+
}
|
|
4329
|
+
|
|
4330
|
+
if (msg.data.hasOwnProperty('filterRunTime')) {
|
|
4331
|
+
// Filter needs to be replaced after 6 months
|
|
4332
|
+
state['replace_filter'] = (parseInt(msg.data['filterRunTime']) >= 259200);
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4335
|
+
if (msg.data.hasOwnProperty('controlPanelLight')) {
|
|
4336
|
+
state['led_enable'] = (msg.data['controlPanelLight'] == 0);
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
if (msg.data.hasOwnProperty('childLock')) {
|
|
4340
|
+
state['child_lock'] = (msg.data['childLock'] > 0 ? 'LOCK' : 'UNLOCK');
|
|
4341
|
+
}
|
|
4342
|
+
|
|
4343
|
+
if (msg.data.hasOwnProperty('fanSpeed')) {
|
|
4344
|
+
let fanSpeed = msg.data['fanSpeed'];
|
|
4345
|
+
if (fanSpeed >= 10) {
|
|
4346
|
+
fanSpeed = (((fanSpeed - 5) * 2) / 10);
|
|
4347
|
+
} else {
|
|
4348
|
+
fanSpeed = 0;
|
|
4349
|
+
}
|
|
4350
|
+
|
|
4351
|
+
state['fan_speed'] = fanSpeed;
|
|
4352
|
+
}
|
|
4353
|
+
|
|
4354
|
+
if (msg.data.hasOwnProperty('fanMode')) {
|
|
4355
|
+
let fanMode = msg.data['fanMode'];
|
|
4356
|
+
if (fanMode >= 10) {
|
|
4357
|
+
fanMode = (((fanMode - 5) * 2) / 10).toString();
|
|
4358
|
+
} else if (fanMode == 1) {
|
|
4359
|
+
fanMode = 'auto';
|
|
4360
|
+
} else {
|
|
4361
|
+
fanMode = 'off';
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4364
|
+
state['fan_mode'] = fanMode;
|
|
4365
|
+
state['fan_state'] = (fanMode === 'off' ? 'OFF' : 'ON');
|
|
4366
|
+
}
|
|
4367
|
+
|
|
4368
|
+
return state;
|
|
4369
|
+
},
|
|
4370
|
+
},
|
|
4248
4371
|
E1524_E1810_levelctrl: {
|
|
4249
4372
|
cluster: 'genLevelCtrl',
|
|
4250
4373
|
type: [
|
|
@@ -5962,6 +6085,11 @@ const converters = {
|
|
|
5962
6085
|
};
|
|
5963
6086
|
|
|
5964
6087
|
const data = utf8FromStr(msg['data']['16896']);
|
|
6088
|
+
|
|
6089
|
+
clearTimeout(globalStore.getValue(msg.endpoint, 'timer'));
|
|
6090
|
+
const timer = setTimeout(() => publish({action: 'lock', state: 'LOCK'}), 2 * 1000);
|
|
6091
|
+
globalStore.putValue(msg.endpoint, 'timer', timer);
|
|
6092
|
+
|
|
5965
6093
|
return {
|
|
5966
6094
|
action: 'unlock',
|
|
5967
6095
|
action_user: data[3],
|
|
@@ -5970,6 +6098,77 @@ const converters = {
|
|
|
5970
6098
|
};
|
|
5971
6099
|
},
|
|
5972
6100
|
},
|
|
6101
|
+
javis_microwave_sensor: {
|
|
6102
|
+
cluster: 'manuSpecificTuya',
|
|
6103
|
+
type: ['commandSetDataResponse', 'commandGetData'],
|
|
6104
|
+
convert: (model, msg, publish, options, meta) => {
|
|
6105
|
+
const dp = msg.data.dp;
|
|
6106
|
+
const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
|
|
6107
|
+
const lookup = {
|
|
6108
|
+
0: 'no_motion',
|
|
6109
|
+
1: 'big_motion',
|
|
6110
|
+
2: 'minor_motion',
|
|
6111
|
+
3: 'breathing',
|
|
6112
|
+
4: 'abnormal_state',
|
|
6113
|
+
5: 'initializing',
|
|
6114
|
+
6: 'initialization_completed',
|
|
6115
|
+
};
|
|
6116
|
+
switch (dp) {
|
|
6117
|
+
case 1:
|
|
6118
|
+
return {
|
|
6119
|
+
states: lookup[value],
|
|
6120
|
+
occupancy: (0 < value && value < 5) ? true: false,
|
|
6121
|
+
};
|
|
6122
|
+
case 2:
|
|
6123
|
+
return {
|
|
6124
|
+
sensitivity: value,
|
|
6125
|
+
};
|
|
6126
|
+
case 101:
|
|
6127
|
+
return {
|
|
6128
|
+
illuminance_lux: value,
|
|
6129
|
+
};
|
|
6130
|
+
case 102:
|
|
6131
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6132
|
+
return {
|
|
6133
|
+
illuminance_calibration: value,
|
|
6134
|
+
};
|
|
6135
|
+
} else {
|
|
6136
|
+
return {
|
|
6137
|
+
keep_time: value,
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
6140
|
+
case 103:
|
|
6141
|
+
return {
|
|
6142
|
+
led_enable: value == 1 ? true : false,
|
|
6143
|
+
};
|
|
6144
|
+
case 104:
|
|
6145
|
+
return {illuminance_lux: value};
|
|
6146
|
+
case 105:
|
|
6147
|
+
return {
|
|
6148
|
+
illuminance_calibration: value,
|
|
6149
|
+
};
|
|
6150
|
+
case 106:
|
|
6151
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6152
|
+
return {
|
|
6153
|
+
keep_time: value,
|
|
6154
|
+
};
|
|
6155
|
+
} else {
|
|
6156
|
+
break;
|
|
6157
|
+
}
|
|
6158
|
+
case 107:
|
|
6159
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6160
|
+
return {
|
|
6161
|
+
led_enable: value == 1 ? true : false,
|
|
6162
|
+
};
|
|
6163
|
+
} else {
|
|
6164
|
+
break;
|
|
6165
|
+
}
|
|
6166
|
+
default:
|
|
6167
|
+
meta.logger.warn(`zigbee-herdsman-converters:javis_microwave_sensor: NOT RECOGNIZED ` +
|
|
6168
|
+
`DP #${dp} with data ${JSON.stringify(msg.data)}`);
|
|
6169
|
+
}
|
|
6170
|
+
},
|
|
6171
|
+
},
|
|
5973
6172
|
diyruz_freepad_config: {
|
|
5974
6173
|
cluster: 'genOnOffSwitchCfg',
|
|
5975
6174
|
type: ['readResponse'],
|
package/converters/toZigbee.js
CHANGED
|
@@ -15,7 +15,9 @@ const manufacturerOptions = {
|
|
|
15
15
|
osram: {manufacturerCode: herdsman.Zcl.ManufacturerCode.OSRAM},
|
|
16
16
|
eurotronic: {manufacturerCode: herdsman.Zcl.ManufacturerCode.JENNIC},
|
|
17
17
|
danfoss: {manufacturerCode: herdsman.Zcl.ManufacturerCode.DANFOSS},
|
|
18
|
+
develco: {manufacturerCode: herdsman.Zcl.ManufacturerCode.DEVELCO},
|
|
18
19
|
hue: {manufacturerCode: herdsman.Zcl.ManufacturerCode.PHILIPS},
|
|
20
|
+
ikea: {manufacturerCode: herdsman.Zcl.ManufacturerCode.IKEA_OF_SWEDEN},
|
|
19
21
|
sinope: {manufacturerCode: herdsman.Zcl.ManufacturerCode.SINOPE_TECH},
|
|
20
22
|
/*
|
|
21
23
|
* Ubisys doesn't accept a manufacturerCode on some commands
|
|
@@ -1910,6 +1912,71 @@ const converters = {
|
|
|
1910
1912
|
await entity.read('genBasic', [0x0033], manufacturerOptions.hue);
|
|
1911
1913
|
},
|
|
1912
1914
|
},
|
|
1915
|
+
ikea_air_purifier_fan_mode: {
|
|
1916
|
+
key: ['fan_mode', 'fan_state'],
|
|
1917
|
+
convertSet: async (entity, key, value, meta) => {
|
|
1918
|
+
if (key == 'fan_state' && value.toLowerCase() == 'on') {
|
|
1919
|
+
value = utils.getMetaValue(entity, meta.mapped, 'fanStateOn', 'allEqual', 'on');
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
let fanMode;
|
|
1923
|
+
switch (value.toLowerCase()) {
|
|
1924
|
+
case 'off':
|
|
1925
|
+
fanMode = 0;
|
|
1926
|
+
break;
|
|
1927
|
+
case 'auto':
|
|
1928
|
+
fanMode = 1;
|
|
1929
|
+
break;
|
|
1930
|
+
default:
|
|
1931
|
+
fanMode = parseInt(((parseInt(value) / 2.0) * 10) + 5);
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
await entity.write('manuSpecificIkeaAirPurifier', {'fanMode': fanMode}, manufacturerOptions.ikea);
|
|
1935
|
+
return {state: {fan_mode: value.toLowerCase(), fan_state: value.toLowerCase() === 'off' ? 'OFF' : 'ON'}};
|
|
1936
|
+
},
|
|
1937
|
+
convertGet: async (entity, key, meta) => {
|
|
1938
|
+
await entity.read('manuSpecificIkeaAirPurifier', ['fanMode']);
|
|
1939
|
+
},
|
|
1940
|
+
},
|
|
1941
|
+
ikea_air_purifier_fan_speed: {
|
|
1942
|
+
key: ['fan_speed'],
|
|
1943
|
+
convertGet: async (entity, key, meta) => {
|
|
1944
|
+
await entity.read('manuSpecificIkeaAirPurifier', ['fanSpeed']);
|
|
1945
|
+
},
|
|
1946
|
+
},
|
|
1947
|
+
ikea_air_purifier_pm25: {
|
|
1948
|
+
key: ['pm25', 'air_quality'],
|
|
1949
|
+
convertGet: async (entity, key, meta) => {
|
|
1950
|
+
await entity.read('manuSpecificIkeaAirPurifier', ['particulateMatter25Measurement']);
|
|
1951
|
+
},
|
|
1952
|
+
},
|
|
1953
|
+
ikea_air_purifier_replace_filter: {
|
|
1954
|
+
key: ['replace_filter'],
|
|
1955
|
+
convertGet: async (entity, key, meta) => {
|
|
1956
|
+
await entity.read('manuSpecificIkeaAirPurifier', ['filterRunTime']);
|
|
1957
|
+
},
|
|
1958
|
+
},
|
|
1959
|
+
ikea_air_purifier_child_lock: {
|
|
1960
|
+
key: ['child_lock'],
|
|
1961
|
+
convertSet: async (entity, key, value, meta) => {
|
|
1962
|
+
await entity.write('manuSpecificIkeaAirPurifier', {'childLock': ((value.toLowerCase() === 'lock') ? 1 : 0)},
|
|
1963
|
+
manufacturerOptions.ikea);
|
|
1964
|
+
return {state: {child_lock: ((value.toLowerCase() === 'lock') ? 'LOCK' : 'UNLOCK')}};
|
|
1965
|
+
},
|
|
1966
|
+
convertGet: async (entity, key, meta) => {
|
|
1967
|
+
await entity.read('manuSpecificIkeaAirPurifier', ['childLock']);
|
|
1968
|
+
},
|
|
1969
|
+
},
|
|
1970
|
+
ikea_air_purifier_led_enable: {
|
|
1971
|
+
key: ['led_enable'],
|
|
1972
|
+
convertSet: async (entity, key, value, meta) => {
|
|
1973
|
+
await entity.write('manuSpecificIkeaAirPurifier', {'controlPanelLight': ((value) ? 0 : 1)}, manufacturerOptions.ikea);
|
|
1974
|
+
return {state: {led_enable: ((value) ? true : false)}};
|
|
1975
|
+
},
|
|
1976
|
+
convertGet: async (entity, key, meta) => {
|
|
1977
|
+
await entity.read('manuSpecificIkeaAirPurifier', ['controlPanelLight']);
|
|
1978
|
+
},
|
|
1979
|
+
},
|
|
1913
1980
|
RTCGQ13LM_motion_sensitivity: {
|
|
1914
1981
|
key: ['motion_sensitivity'],
|
|
1915
1982
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -2569,6 +2636,34 @@ const converters = {
|
|
|
2569
2636
|
await entity.read('haDiagnostic', ['danfossMultimasterRole'], manufacturerOptions.danfoss);
|
|
2570
2637
|
},
|
|
2571
2638
|
},
|
|
2639
|
+
develco_pulse_configuration: {
|
|
2640
|
+
key: ['pulse_configuration'],
|
|
2641
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2642
|
+
await entity.write('seMetering', {'develcoPulseConfiguration': value}, manufacturerOptions.develco);
|
|
2643
|
+
return {readAfterWriteTime: 200, state: {'pulse_configuration': value}};
|
|
2644
|
+
},
|
|
2645
|
+
convertGet: async (entity, key, meta) => {
|
|
2646
|
+
await entity.read('seMetering', ['develcoPulseConfiguration'], manufacturerOptions.develco);
|
|
2647
|
+
},
|
|
2648
|
+
},
|
|
2649
|
+
develco_interface_mode: {
|
|
2650
|
+
key: ['interface_mode'],
|
|
2651
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2652
|
+
const payload = {'develcoInterfaceMode': utils.getKey(constants.develcoInterfaceMode, value, undefined, Number)};
|
|
2653
|
+
await entity.write('seMetering', payload, manufacturerOptions.develco);
|
|
2654
|
+
return {readAfterWriteTime: 200, state: {'interface_mode': value}};
|
|
2655
|
+
},
|
|
2656
|
+
convertGet: async (entity, key, meta) => {
|
|
2657
|
+
await entity.read('seMetering', ['develcoInterfaceMode'], manufacturerOptions.develco);
|
|
2658
|
+
},
|
|
2659
|
+
},
|
|
2660
|
+
develco_current_summation: {
|
|
2661
|
+
key: ['current_summation'],
|
|
2662
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2663
|
+
await entity.write('seMetering', {'develcoCurrentSummation': value}, manufacturerOptions.develco);
|
|
2664
|
+
return {state: {'current_summation': value}};
|
|
2665
|
+
},
|
|
2666
|
+
},
|
|
2572
2667
|
ZMCSW032D_cover_position: {
|
|
2573
2668
|
key: ['position', 'tilt'],
|
|
2574
2669
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -2762,9 +2857,9 @@ const converters = {
|
|
|
2762
2857
|
await tuya.sendDataPointBool(entity, tuya.dataPoints.tvChildLock, value === 'LOCK');
|
|
2763
2858
|
break;
|
|
2764
2859
|
case 'local_temperature_calibration':
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvTempCalibration, value
|
|
2860
|
+
if (value > 0) value = value*10;
|
|
2861
|
+
if (value < 0) value = value*10 + 0x100000000;
|
|
2862
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvTempCalibration, value);
|
|
2768
2863
|
break;
|
|
2769
2864
|
case 'current_heating_setpoint':
|
|
2770
2865
|
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvHeatingSetpoint, value * 10);
|
|
@@ -5264,8 +5359,6 @@ const converters = {
|
|
|
5264
5359
|
saswell_thermostat_calibration: {
|
|
5265
5360
|
key: ['local_temperature_calibration'],
|
|
5266
5361
|
convertSet: async (entity, key, value, meta) => {
|
|
5267
|
-
if (value > 6) value = 6;
|
|
5268
|
-
if (value < -6) value = -6;
|
|
5269
5362
|
if (value < 0) value = 0xFFFFFFFF + value + 1;
|
|
5270
5363
|
await tuya.sendDataPointValue(entity, tuya.dataPoints.saswellTempCalibration, value);
|
|
5271
5364
|
},
|
|
@@ -6108,6 +6201,46 @@ const converters = {
|
|
|
6108
6201
|
}
|
|
6109
6202
|
},
|
|
6110
6203
|
},
|
|
6204
|
+
javis_microwave_sensor: {
|
|
6205
|
+
key: [
|
|
6206
|
+
'illuminance_calibration', 'led_enable',
|
|
6207
|
+
'sensitivity', 'keep_time',
|
|
6208
|
+
],
|
|
6209
|
+
convertSet: async (entity, key, value, meta) => {
|
|
6210
|
+
switch (key) {
|
|
6211
|
+
case 'illuminance_calibration':// (10--100) sensor illuminance sensitivity
|
|
6212
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6213
|
+
await tuya.sendDataPointRaw(entity, 102, [value]);
|
|
6214
|
+
break;
|
|
6215
|
+
} else {
|
|
6216
|
+
tuya.sendDataPointRaw(entity, 105, [value]);
|
|
6217
|
+
break;
|
|
6218
|
+
}
|
|
6219
|
+
case 'led_enable':// OK (value true/false or 1/0)
|
|
6220
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6221
|
+
await tuya.sendDataPointRaw(entity, 107, [value ? 1 : 0]);
|
|
6222
|
+
break;
|
|
6223
|
+
} else {
|
|
6224
|
+
await tuya.sendDataPointRaw(entity, 103, [value ? 1 : 0]);
|
|
6225
|
+
break;
|
|
6226
|
+
}
|
|
6227
|
+
|
|
6228
|
+
case 'sensitivity':// value: 25, 50, 75, 100
|
|
6229
|
+
await tuya.sendDataPointRaw(entity, 2, [value]);
|
|
6230
|
+
break;
|
|
6231
|
+
case 'keep_time': // value 0 --> 7 corresponding 5s, 30s, 1, 3, 5, 10, 20, 30 min
|
|
6232
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6233
|
+
await tuya.sendDataPointRaw(entity, 106, [value]);
|
|
6234
|
+
break;
|
|
6235
|
+
} else {
|
|
6236
|
+
await tuya.sendDataPointRaw(entity, 102, [value]);
|
|
6237
|
+
break;
|
|
6238
|
+
}
|
|
6239
|
+
default: // Unknown key
|
|
6240
|
+
throw new Error(`Unhandled key ${key}`);
|
|
6241
|
+
}
|
|
6242
|
+
},
|
|
6243
|
+
},
|
|
6111
6244
|
moes_thermostat_tv: {
|
|
6112
6245
|
key: [
|
|
6113
6246
|
'system_mode', 'window_detection', 'frost_detection', 'child_lock',
|
|
@@ -5,6 +5,31 @@ const reporting = require('../lib/reporting');
|
|
|
5
5
|
const extend = require('../lib/extend');
|
|
6
6
|
const e = exposes.presets;
|
|
7
7
|
|
|
8
|
+
const batteryRotaryDimmer = (...endpointsIds) => ({
|
|
9
|
+
fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
|
|
10
|
+
toZigbee: [],
|
|
11
|
+
exposes: [e.battery(), e.action([
|
|
12
|
+
'on', 'off', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'])],
|
|
13
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
14
|
+
const endpoints = endpointsIds.map((endpoint) => device.getEndpoint(endpoint));
|
|
15
|
+
|
|
16
|
+
// Battery level is only reported on first endpoint
|
|
17
|
+
await reporting.batteryVoltage(endpoints[0]);
|
|
18
|
+
|
|
19
|
+
for await (const endpoint of endpoints) {
|
|
20
|
+
logger.debug(`processing endpoint ${endpoint.ID}`);
|
|
21
|
+
await reporting.bind(endpoint, coordinatorEndpoint,
|
|
22
|
+
['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl']);
|
|
23
|
+
|
|
24
|
+
// The default is for the device to also report the on/off and
|
|
25
|
+
// brightness at the same time as sending on/off and step commands.
|
|
26
|
+
// Disable the reporting by setting the max interval to 0xFFFF.
|
|
27
|
+
await reporting.brightness(endpoint, {max: 0xFFFF});
|
|
28
|
+
await reporting.onOff(endpoint, {max: 0xFFFF});
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
8
33
|
module.exports = [
|
|
9
34
|
{
|
|
10
35
|
zigbeeModel: ['TWGU10Bulb50AU'],
|
|
@@ -167,38 +192,20 @@ module.exports = [
|
|
|
167
192
|
model: 'AU-A1ZBR1GW',
|
|
168
193
|
vendor: 'Aurora Lighting',
|
|
169
194
|
description: 'AOne one gang wireless battery rotary dimmer',
|
|
170
|
-
fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
|
|
171
|
-
toZigbee: [],
|
|
172
|
-
exposes: [e.battery(), e.action([
|
|
173
|
-
'on', 'off', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'])],
|
|
174
195
|
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
await reporting.bind(endpoint1, coordinatorEndpoint,
|
|
178
|
-
['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'genPowerCfg']);
|
|
179
|
-
await reporting.batteryVoltage(endpoint1);
|
|
180
|
-
},
|
|
196
|
+
// One gang battery rotary dimmer with endpoint ID 1
|
|
197
|
+
...batteryRotaryDimmer(1),
|
|
181
198
|
},
|
|
182
199
|
{
|
|
183
200
|
zigbeeModel: ['2GBatteryDimmer50AU'],
|
|
184
201
|
model: 'AU-A1ZBR2GW',
|
|
185
202
|
vendor: 'Aurora Lighting',
|
|
186
203
|
description: 'AOne two gang wireless battery rotary dimmer',
|
|
187
|
-
fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
|
|
188
|
-
toZigbee: [],
|
|
189
|
-
exposes: [e.battery(), e.action([
|
|
190
|
-
'on', 'off', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'])],
|
|
191
204
|
meta: {multiEndpoint: true, battery: {voltageToPercentage: '3V_2100'}},
|
|
192
205
|
endpoint: (device) => {
|
|
193
206
|
return {'right': 1, 'left': 2};
|
|
194
207
|
},
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
await reporting.bind(endpoint1, coordinatorEndpoint,
|
|
198
|
-
['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'genPowerCfg']);
|
|
199
|
-
await reporting.batteryVoltage(endpoint1);
|
|
200
|
-
const endpoint2 = device.getEndpoint(2);
|
|
201
|
-
await reporting.bind(endpoint2, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl']);
|
|
202
|
-
},
|
|
208
|
+
// Two gang battery rotary dimmer with endpoint IDs 1 and 2
|
|
209
|
+
...batteryRotaryDimmer(1, 2),
|
|
203
210
|
},
|
|
204
211
|
];
|
package/devices/bitron.js
CHANGED
|
@@ -190,7 +190,7 @@ module.exports = [
|
|
|
190
190
|
tz.thermostat_running_state, tz.thermostat_temperature_display_mode, tz.thermostat_keypad_lockout, tz.thermostat_system_mode],
|
|
191
191
|
exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 0.5).withLocalTemperature()
|
|
192
192
|
.withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat', 'cool'])
|
|
193
|
-
.withLocalTemperatureCalibration(), e.keypad_lockout()],
|
|
193
|
+
.withLocalTemperatureCalibration(-20, 20, 1), e.keypad_lockout()],
|
|
194
194
|
meta: {battery: {voltageToPercentage: '3V_2500_3200'}},
|
|
195
195
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
196
196
|
const endpoint = device.getEndpoint(1);
|
package/devices/centralite.js
CHANGED
|
@@ -154,7 +154,8 @@ module.exports = [
|
|
|
154
154
|
exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 10, 30, 1).withLocalTemperature()
|
|
155
155
|
.withSystemMode(['off', 'heat', 'cool', 'emergency_heating'])
|
|
156
156
|
.withRunningState(['idle', 'heat', 'cool', 'fan_only']).withFanMode(['auto', 'on'])
|
|
157
|
-
.withSetpoint('occupied_cooling_setpoint', 10, 30, 1)
|
|
157
|
+
.withSetpoint('occupied_cooling_setpoint', 10, 30, 1)
|
|
158
|
+
.withLocalTemperatureCalibration(-20, 20, 1)],
|
|
158
159
|
meta: {battery: {voltageToPercentage: '3V_1500_2800'}},
|
|
159
160
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
160
161
|
const endpoint = device.getEndpoint(1);
|
|
@@ -179,7 +180,8 @@ module.exports = [
|
|
|
179
180
|
exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 10, 30, 1).withLocalTemperature()
|
|
180
181
|
.withSystemMode(['off', 'heat', 'cool', 'emergency_heating'])
|
|
181
182
|
.withRunningState(['idle', 'heat', 'cool', 'fan_only']).withFanMode(['auto', 'on'])
|
|
182
|
-
.withSetpoint('occupied_cooling_setpoint', 10, 30, 1)
|
|
183
|
+
.withSetpoint('occupied_cooling_setpoint', 10, 30, 1)
|
|
184
|
+
.withLocalTemperatureCalibration(-20, 20, 1)],
|
|
183
185
|
meta: {battery: {voltageToPercentage: '3V_1500_2800'}},
|
|
184
186
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
185
187
|
const endpoint = device.getEndpoint(1);
|
package/devices/develco.js
CHANGED
|
@@ -297,15 +297,28 @@ module.exports = [
|
|
|
297
297
|
model: 'ZHEMI101',
|
|
298
298
|
vendor: 'Develco',
|
|
299
299
|
description: 'Energy meter',
|
|
300
|
-
fromZigbee: [fz.metering],
|
|
301
|
-
toZigbee: [],
|
|
300
|
+
fromZigbee: [fz.metering, fz.develco_metering],
|
|
301
|
+
toZigbee: [tz.develco_pulse_configuration, tz.develco_interface_mode, tz.develco_current_summation],
|
|
302
|
+
endpoint: (device) => {
|
|
303
|
+
return {'default': 2};
|
|
304
|
+
},
|
|
302
305
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
303
306
|
const endpoint = device.getEndpoint(2);
|
|
304
307
|
await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
|
|
305
308
|
await reporting.instantaneousDemand(endpoint);
|
|
306
309
|
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
307
310
|
},
|
|
308
|
-
exposes: [
|
|
311
|
+
exposes: [
|
|
312
|
+
e.power(),
|
|
313
|
+
e.energy(),
|
|
314
|
+
exposes.numeric('pulse_configuration', ea.ALL).withValueMin(0).withValueMax(65535)
|
|
315
|
+
.withDescription('Pulses per kwh. Default 1000 imp/kWh. Range 0 to 65535'),
|
|
316
|
+
exposes.enum('interface_mode', ea.ALL,
|
|
317
|
+
['electricity', 'gas', 'water', 'kamstrup-kmp', 'linky', 'IEC62056-21', 'DSMR-2.3', 'DSMR-4.0'])
|
|
318
|
+
.withDescription('Operating mode/probe'),
|
|
319
|
+
exposes.numeric('current_summation', ea.SET)
|
|
320
|
+
.withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh'),
|
|
321
|
+
],
|
|
309
322
|
},
|
|
310
323
|
{
|
|
311
324
|
zigbeeModel: ['SMRZB-332'],
|
package/devices/ecozy.js
CHANGED
|
@@ -18,7 +18,8 @@ module.exports = [
|
|
|
18
18
|
tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_relay_status_log,
|
|
19
19
|
tz.thermostat_pi_heating_demand, tz.thermostat_running_state],
|
|
20
20
|
exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 1).withLocalTemperature()
|
|
21
|
-
.withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat'])
|
|
21
|
+
.withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat'])
|
|
22
|
+
.withLocalTemperatureCalibration(-20, 20, 1)
|
|
22
23
|
.withPiHeatingDemand(ea.STATE_GET)],
|
|
23
24
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
24
25
|
const endpoint = device.getEndpoint(3);
|
package/devices/elko.js
CHANGED
|
@@ -41,7 +41,7 @@ module.exports = [
|
|
|
41
41
|
'(quick) wooden floors.'),
|
|
42
42
|
exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 50, 1)
|
|
43
43
|
.withLocalTemperature(ea.STATE)
|
|
44
|
-
.withLocalTemperatureCalibration()
|
|
44
|
+
.withLocalTemperatureCalibration(-20, 20, 1)
|
|
45
45
|
.withSystemMode(['off', 'heat']).withRunningState(['idle', 'heat'])
|
|
46
46
|
.withSensor(['air', 'floor', 'supervisor_floor']),
|
|
47
47
|
exposes.numeric('floor_temp', ea.STATE_GET).withUnit('°C')
|
package/devices/eurotronic.js
CHANGED
|
@@ -19,7 +19,8 @@ module.exports = [
|
|
|
19
19
|
tz.thermostat_remote_sensing, tz.thermostat_local_temperature, tz.thermostat_running_state,
|
|
20
20
|
tz.eurotronic_current_heating_setpoint, tz.eurotronic_trv_mode, tz.eurotronic_valve_position],
|
|
21
21
|
exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 30, 0.5).withLocalTemperature()
|
|
22
|
-
.withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat'])
|
|
22
|
+
.withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat'])
|
|
23
|
+
.withLocalTemperatureCalibration(-20, 20, 1)
|
|
23
24
|
.withPiHeatingDemand(),
|
|
24
25
|
exposes.enum('trv_mode', exposes.access.ALL, [1, 2])
|
|
25
26
|
.withDescription('Select between direct control of the valve via the `valve_position` or automatic control of the '+
|
package/devices/hgkg.js
CHANGED
|
@@ -17,7 +17,7 @@ module.exports = [
|
|
|
17
17
|
tz.moes_thermostat_deadzone_temperature, tz.moes_thermostat_max_temperature_limit],
|
|
18
18
|
exposes: [e.child_lock(), e.deadzone_temperature(), e.max_temperature_limit(),
|
|
19
19
|
exposes.climate().withSetpoint('current_heating_setpoint', 5, 30, 1, ea.STATE_SET)
|
|
20
|
-
.withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(ea.STATE_SET)
|
|
20
|
+
.withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-20, 20, 1, ea.STATE_SET)
|
|
21
21
|
.withSystemMode(['off', 'cool'], ea.STATE_SET).withRunningState(['idle', 'heat', 'cool'], ea.STATE)
|
|
22
22
|
.withPreset(['hold', 'program']).withSensor(['IN', 'AL', 'OU'], ea.STATE_SET)],
|
|
23
23
|
onEvent: tuya.onEventSetLocalTime,
|