From 6a4504bc05d2b1aac60715a72c436747274637d4 Mon Sep 17 00:00:00 2001 From: Jeffrey Stone Date: Wed, 27 Apr 2022 15:18:04 -0400 Subject: [PATCH] Adding External Converters --- config/zigbee2mqtt/aqara.js | 64 +++++++++++++++ config/zigbee2mqtt/easyiot.js | 27 +++++++ config/zigbee2mqtt/smartwings.js | 27 +++++++ config/zigbee2mqtt/third_reality.js | 116 ++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+) create mode 100755 config/zigbee2mqtt/aqara.js create mode 100755 config/zigbee2mqtt/easyiot.js create mode 100755 config/zigbee2mqtt/smartwings.js create mode 100755 config/zigbee2mqtt/third_reality.js diff --git a/config/zigbee2mqtt/aqara.js b/config/zigbee2mqtt/aqara.js new file mode 100755 index 0000000..35fb596 --- /dev/null +++ b/config/zigbee2mqtt/aqara.js @@ -0,0 +1,64 @@ +const exposes = require('zigbee-herdsman-converters/lib/exposes'); +const fz = {...require('zigbee-herdsman-converters/converters/fromZigbee'), legacy: require('zigbee-herdsman-converters/lib/legacy').fromZigbee}; +const tz = require('zigbee-herdsman-converters/converters/toZigbee'); +const ota = require('zigbee-herdsman-converters/lib/ota'); +const constants = require('zigbee-herdsman-converters/lib/constants'); +const reporting = require('zigbee-herdsman-converters/lib/reporting'); +const extend = require('zigbee-herdsman-converters/lib/extend'); +const e = exposes.presets; +const ea = exposes.access; +const globalStore = require('zigbee-herdsman-converters/lib/store'); + +const xiaomiExtend = { + light_onoff_brightness_colortemp: (options={disableColorTempStartup: true}) => ({ + ...extend.light_onoff_brightness_colortemp(options), + fromZigbee: extend.light_onoff_brightness_colortemp(options).fromZigbee.concat([ + fz.xiaomi_bulb_interval, fz.ignore_occupancy_report, fz.ignore_humidity_report, + fz.ignore_pressure_report, fz.ignore_temperature_report, + ]), + }), +}; + +const preventReset = async (type, data, device) => { + if ( + // options.allow_reset || + type !== 'message' || + data.type !== 'attributeReport' || + data.cluster !== 'genBasic' || + !data.data[0xfff0] || + // eg: [0xaa, 0x10, 0x05, 0x41, 0x87, 0x01, 0x01, 0x10, 0x00] + !data.data[0xFFF0].slice(0, 5).equals(Buffer.from([0xaa, 0x10, 0x05, 0x41, 0x87])) + ) { + return; + } + const options = {manufacturerCode: 0x115f}; + const payload = {[0xfff0]: { + value: [0xaa, 0x10, 0x05, 0x41, 0x47, 0x01, 0x01, 0x10, 0x01], + type: 0x41, + }}; + await device.getEndpoint(1).write('genBasic', payload, options); +}; + +module.exports = [ + { + zigbeeModel: ['lumi.motion.ac02'], + model: 'RTCGQ14LM', + vendor: 'Xiaomi', + whiteLabel: [{vendor: 'Xiaomi', model: 'MS-S02'}], + description: 'Aqara P1 human body movement and illuminance sensor', + fromZigbee: [fz.RTCGQ12LM_occupancy_illuminance, fz.aqara_opple, fz.battery], + toZigbee: [tz.aqara_detection_interval, tz.aqara_motion_sensitivity], + exposes: [e.occupancy(), e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'), + exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']), + exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s') + .withDescription('Time interval for detecting actions'), e.temperature(), e.battery()], + meta: {battery: {voltageToPercentage: '3V_2850_3000_log'}}, + configure: async (device, coordinatorEndpoint, logger) => { + const endpoint = device.getEndpoint(1); + await endpoint.read('genPowerCfg', ['batteryVoltage']); + await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f}); + await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f}); + }, + ota: ota.zigbeeOTA, + }, +]; diff --git a/config/zigbee2mqtt/easyiot.js b/config/zigbee2mqtt/easyiot.js new file mode 100755 index 0000000..ddccc41 --- /dev/null +++ b/config/zigbee2mqtt/easyiot.js @@ -0,0 +1,27 @@ +const exposes = require('zigbee-herdsman-converters/lib/exposes'); +const fz = {...require('zigbee-herdsman-converters/converters/fromZigbee'), legacy: require('zigbee-herdsman-converters/lib/legacy').fromZigbee}; +const tz = require('zigbee-herdsman-converters/converters/toZigbee'); +const reporting = require('zigbee-herdsman-converters/lib/reporting'); +const extend = require('zigbee-herdsman-converters/lib/extend'); +const e = exposes.presets; + +module.exports = [ + { + zigbeeModel: ['UT-02'], + model: 'EFR32MG21', + vendor: 'easyiot', + description: 'EFR32MG21 Silabs Router', + fromZigbee: [], + toZigbee: [], + exposes: [], + }, + { + zigbeeModel: ['UT-01'], + model: 'EFR32MG21', + vendor: 'easyiot', + description: 'EFR32MG21 Zigbee Bridge Router', + fromZigbee: [], + toZigbee: [], + exposes: [], + }, +]; \ No newline at end of file diff --git a/config/zigbee2mqtt/smartwings.js b/config/zigbee2mqtt/smartwings.js new file mode 100755 index 0000000..fdd9c05 --- /dev/null +++ b/config/zigbee2mqtt/smartwings.js @@ -0,0 +1,27 @@ +const fz = require('zigbee-herdsman-converters/converters/fromZigbee'); +const tz = require('zigbee-herdsman-converters/converters/toZigbee'); +const exposes = require('zigbee-herdsman-converters/lib/exposes'); +const reporting = require('zigbee-herdsman-converters/lib/reporting'); +const e = exposes.presets; + + +module.exports = [ + { + zigbeeModel: ['WM25/L-Z'], + model: 'WM25L-Z', + vendor: 'Smartwings', + description: 'Roller Shade', + fromZigbee: [fz.cover_position_tilt, fz.battery], + toZigbee: [tz.cover_state, tz.cover_position_tilt], + meta: {battery: {dontDividePercentage: true}}, + configure: async (device, coordinatorEndpoint, logger) => { + const endpoint = device.getEndpoint(1); + await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']); + await reporting.batteryPercentageRemaining(endpoint); + await reporting.currentPositionLiftPercentage(endpoint); + device.powerSource = 'Battery'; + device.save(); + }, + exposes: [e.cover_position(), e.battery()], + }, +]; diff --git a/config/zigbee2mqtt/third_reality.js b/config/zigbee2mqtt/third_reality.js new file mode 100755 index 0000000..fc9b201 --- /dev/null +++ b/config/zigbee2mqtt/third_reality.js @@ -0,0 +1,116 @@ +const fz = require('zigbee-herdsman-converters/converters/fromZigbee'); +const tz = require('zigbee-herdsman-converters/converters/toZigbee'); +const exposes = require('zigbee-herdsman-converters/lib/exposes'); +const reporting = require('zigbee-herdsman-converters/lib/reporting'); +const extend = require('zigbee-herdsman-converters/lib/extend'); +const e = exposes.presets; + +module.exports = [ + { + zigbeeModel: ['3RSS009Z'], + model: '3RSS009Z', + vendor: 'Third Reality', + description: 'Smart switch Gen3', + fromZigbee: [fz.on_off, fz.battery], + toZigbee: [tz.on_off, tz.ignore_transition], + exposes: [e.switch(), e.battery_voltage()], + }, + { + zigbeeModel: ['3RSS008Z'], + model: '3RSS008Z', + vendor: 'Third Reality', + description: 'RealitySwitch Plus', + fromZigbee: [fz.on_off], + toZigbee: [tz.on_off, tz.ignore_transition], + exposes: [e.switch()], + }, + { + zigbeeModel: ['3RSS007Z'], + model: '3RSS007Z', + vendor: 'Third Reality', + description: 'Smart light switch', + extend: extend.switch(), + meta: {disableDefaultResponse: true}, + configure: async (device, coordinatorEndpoint, logger) => { + const endpoint = device.getEndpoint(1); + await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']); + await reporting.onOff(endpoint); + }, + }, + { + zigbeeModel: ['3RSL011Z'], + model: '3RSL011Z', + vendor: 'Third Reality', + description: 'Smart light A19', + extend: extend.light_onoff_brightness_colortemp(), + }, + { + zigbeeModel: ['3RSL012Z'], + model: '3RSL012Z', + vendor: 'Third Reality', + description: 'Smart light BR30', + extend: extend.light_onoff_brightness_colortemp(), + }, + { + zigbeeModel: ['3RWS18BZ'], + model: '3RWS18BZ', + vendor: 'Third Reality', + description: 'Water sensor', + fromZigbee: [fz.ias_water_leak_alarm_1, fz.battery], + meta: {battery: {dontDividePercentage: true}}, + toZigbee: [], + exposes: [e.water_leak(), e.battery_low(), e.battery(), e.battery_voltage()], + configure: async (device, coordinatorEndpoint, logger) => { + device.powerSource = 'Battery'; + device.save(); + }, + }, + { + zigbeeModel: ['3RMS16BZ'], + model: '3RMS16BZ', + vendor: 'Third Reality', + description: 'Wireless motion sensor', + fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery], + toZigbee: [], + meta: {battery: {dontDividePercentage: true}}, + exposes: [e.occupancy(), e.battery_low(), e.battery(), e.battery_voltage()], + }, + { + zigbeeModel: ['3RDS17BZ'], + model: '3RDS17BZ', + vendor: 'Third Reality', + description: 'Door sensor', + fromZigbee: [fz.ias_contact_alarm_1, fz.battery], + toZigbee: [], + meta: {battery: {dontDividePercentage: true}}, + exposes: [e.contact(), e.battery_low(), e.battery(), e.battery_voltage()], + }, + { + zigbeeModel: ['3RSP019BZ'], + model: '3RSP019BZ', + vendor: 'Third Reality', + description: 'Zigbee / BLE smart plug', + extend: extend.switch(), + configure: async (device, coordinatorEndpoint, logger) => { + const endpoint = device.getEndpoint(1); + await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']); + await reporting.onOff(endpoint); + }, + }, + { + zigbeeModel: ['3RSB015BZ'], + model: '3RSB015BZ', + vendor: 'Third Reality', + description: 'Roller Shade', + fromZigbee: [fz.cover_position_tilt, fz.battery], + toZigbee: [tz.cover_state, tz.cover_position_tilt], + meta: {battery: {dontDividePercentage: false}}, + configure: async (device, coordinatorEndpoint, logger) => { + const endpoint = device.getEndpoint(1); + await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']); + await reporting.batteryPercentageRemaining(endpoint); + await reporting.currentPositionLiftPercentage(endpoint); + }, + exposes: [e.cover_position(), e.battery()], + }, +];