UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

198 lines (195 loc) • 8.33 kB
const exposes = require('../lib/exposes'); const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee}; const tz = require('../converters/toZigbee'); const globalStore = require('../lib/store'); const extend = require('../lib/extend'); const e = exposes.presets; const ea = exposes.access; const poll = async (device) => { try { const endpoint = device.getEndpoint(6); const options = {transactionSequenceNumber: 0, srcEndpoint: 8, disableResponse: true, disableRecovery: true}; await endpoint.command('genOnOff', 'toggle', {}, options); } catch (error) { // device is lost, need to permit join } }; module.exports = [ { zigbeeModel: ['TI0001 '], model: 'TI0001', description: 'Zigbee switch (1 and 2 gang)', vendor: 'Livolo', exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right')], fromZigbee: [fz.livolo_switch_state, fz.livolo_switch_state_raw], toZigbee: [tz.livolo_switch_on_off], endpoint: (device) => { return {'left': 6, 'right': 6}; }, configure: poll, onEvent: async (type, data, device) => { if (type === 'stop') { clearInterval(globalStore.getValue(device, 'interval')); globalStore.clearValue(device, 'interval'); } if (['start', 'deviceAnnounce'].includes(type)) { await poll(device); if (!globalStore.hasValue(device, 'interval')) { const interval = setInterval(async () => await poll(device), 300*1000); globalStore.putValue(device, 'interval', interval); } } }, }, { zigbeeModel: ['TI0001-switch'], model: 'TI0001-switch', description: 'Zigbee switch 1 gang', vendor: 'Livolo', fromZigbee: [fz.livolo_new_switch_state], toZigbee: [tz.livolo_socket_switch_on_off], extend: extend.switch(), configure: poll, onEvent: async (type, data, device) => { if (type === 'stop') { clearInterval(globalStore.getValue(device, 'interval')); globalStore.clearValue(device, 'interval'); } if (['start', 'deviceAnnounce'].includes(type)) { await poll(device); if (!globalStore.hasValue(device, 'interval')) { const interval = setInterval(async () => { await poll(device); }, 300*1000); // Every 300 seconds globalStore.putValue(device, 'interval', interval); } } }, }, { zigbeeModel: ['TI0001-switch-2gang'], model: 'TI0001-switch-2gang', description: 'Zigbee Switch 2 gang', vendor: 'Livolo', fromZigbee: [fz.livolo_new_switch_state_2gang], toZigbee: [tz.livolo_socket_switch_on_off], exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right')], configure: poll, endpoint: (device) => { return {'left': 6, 'right': 6}; }, onEvent: async (type, data, device) => { if (type === 'stop') { clearInterval(globalStore.getValue(device, 'interval')); globalStore.clearValue(device, 'interval'); } if (['start', 'deviceAnnounce'].includes(type)) { await poll(device); if (!globalStore.hasValue(device, 'interval')) { const interval = setInterval(async () => { await poll(device); }, 300*1000); // Every 300 seconds globalStore.putValue(device, 'interval', interval); } } }, }, { zigbeeModel: ['TI0001-socket'], model: 'TI0001-socket', description: 'Zigbee socket', vendor: 'Livolo', extend: extend.switch(), fromZigbee: [fz.livolo_socket_state], toZigbee: [tz.livolo_socket_switch_on_off], configure: poll, onEvent: async (type, data, device) => { if (type === 'stop') { clearInterval(globalStore.getValue(device, 'interval')); globalStore.clearValue(device, 'interval'); } if (['start', 'deviceAnnounce'].includes(type)) { await poll(device); if (!globalStore.hasValue(device, 'interval')) { const interval = setInterval(async () => { await poll(device); }, 300*1000); // Every 300 seconds globalStore.putValue(device, 'interval', interval); } } }, }, { zigbeeModel: ['TI0001-dimmer'], model: 'TI0001-dimmer', description: 'Zigbee dimmer', vendor: 'Livolo', fromZigbee: [fz.livolo_dimmer_state], toZigbee: [tz.livolo_socket_switch_on_off, tz.livolo_dimmer_level], exposes: [e.light_brightness()], configure: poll, onEvent: async (type, data, device) => { if (type === 'stop') { clearInterval(globalStore.getValue(device, 'interval')); globalStore.clearValue(device, 'interval'); } if (!globalStore.hasValue(device, 'interval')) { await poll(device); const interval = setInterval(async () => { await poll(device); }, 300*1000); // Every 300 seconds globalStore.putValue(device, 'interval', interval); } }, }, { zigbeeModel: ['TI0001-cover'], model: 'TI0001-cover', description: 'Zigbee roller blind motor', vendor: 'Livolo', fromZigbee: [fz.livolo_cover_state, fz.command_off], toZigbee: [tz.livolo_cover_state, tz.livolo_cover_position, tz.livolo_cover_options], exposes: [ e.cover_position().setAccess('position', ea.STATE_SET), exposes.composite('options', 'options') .withDescription('Motor options') .withFeature(exposes.numeric('motor_speed', ea.STATE_SET) .withValueMin(20) .withValueMax(40) .withDescription('Motor speed') .withUnit('rpm')) .withFeature(exposes.enum('motor_direction', ea.STATE_SET, ['FORWARD', 'REVERSE']) .withDescription('Motor direction')), exposes.binary('moving', ea.STATE) .withDescription('Motor is moving'), ], configure: poll, onEvent: async (type, data, device) => { if (type === 'stop') { clearInterval(globalStore.getValue(device, 'interval')); globalStore.clearValue(device, 'interval'); } if (!globalStore.hasValue(device, 'interval')) { await poll(device); const interval = setInterval(async () => { await poll(device); }, 300*1000); // Every 300 seconds globalStore.putValue(device, 'interval', interval); } // This is needed while pairing in order to let the device know that the interview went right and prevent // it from disconnecting from the Zigbee network. if (data.cluster === 'genPowerCfg' && data.type === 'raw') { const dp = data.data[10]; if (data.data[0] === 0x7a && data.data[1] === 0xd1) { const endpoint = device.getEndpoint(6); if (dp === 0x02) { const options = {manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true, reservedBits: 3, direction: 1, writeUndiv: true}; const payload = {0x0802: {value: [data.data[3], 0, 0, 0, 0, 0, 0], type: data.data[2]}}; await endpoint.readResponse('genPowerCfg', 0xe9, payload, options); } } } }, }, ];