From e56162d222008dbd64305479c4c0ed0c1f8ab7ef Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Mon, 9 Apr 2018 18:36:32 +0200 Subject: [PATCH] Switch: support single, double, triple, quadruple and long clicks. #2 --- index.js | 21 +++++++++++++++------ parsers.js | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index a358a2e7f..c5455f4b6 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ const debug = require('debug')('xiaomi-zb2mqtt') const util = require("util"); -const perfy = require('perfy'); const ZShepherd = require('zigbee-shepherd'); const mqtt = require('mqtt') const fs = require('fs'); @@ -113,14 +112,24 @@ function handleMessage(msg) { return; } - // Parse the message. + // Parse generic information from message. const friendlyName = settings.devices[device.ieeeAddr].friendly_name; - const payload = parser.parse(msg).toString(); const topic = `${settings.mqtt.base_topic}/${friendlyName}/${parser.topic}`; - // Send the message. - console.log(`MQTT publish, topic: '${topic}', payload: '${payload}'`); - client.publish(topic, payload); + // Define publih function. + const publish = (payload) => { + console.log(`MQTT publish, topic: '${topic}', payload: '${payload}'`); + client.publish(topic, payload.toString()); + } + + // Get payload for the message. + // - If a payload is returned publish it to the MQTT broker + // - If NO payload is returned do nothing. This is for non-standard behaviour + // for e.g. click switches where we need to count number of clicks and detect long presses. + const payload = parser.parse(msg, publish); + if (payload) { + publish(payload); + } } function handleQuit() { diff --git a/parsers.js b/parsers.js index 7095b2868..c37661637 100644 --- a/parsers.js +++ b/parsers.js @@ -1,10 +1,42 @@ +const perfy = require('perfy'); + +const clickLookup = { + 2: 'double', + 3: 'triple', + 4: 'quadruple', +} + module.exports = [ { supportedDevices: [260], description: 'WXKG01LM switch (260)', topic: 'switch', - parse: (msg) => { - return msg.data.data['onOff'] === 0 ? 'on' : 'off'; + parse: (msg, publish) => { + const deviceID = msg.endpoints[0].device.ieeeAddr; + const state = msg.data.data['onOff']; + + // 0 = click down, 1 = click up, else = multiple clicks + if (state === 0) { + perfy.start(deviceID); + setTimeout(() => { + if (perfy.exists(deviceID)) { + publish('long'); + perfy.end(deviceID); + } + }, 300); // After 300 seconds of not releasing we assume long click. + } else if (state === 1) { + if (perfy.exists(deviceID)) { + perfy.end(deviceID); + publish('single'); + } + } else { + const clicks = msg.data.data['32768']; + if (clickLookup[clicks]) { + publish(clickLookup[clicks]); + } else { + publish('many'); + } + } } }, ]