Support tradfri light bulbs.

This commit is contained in:
Koen Kanters
2018-04-16 21:41:24 +02:00
parent 49f37047cc
commit 7057b2f9d7
4 changed files with 105 additions and 5 deletions
+31
View File
@@ -0,0 +1,31 @@
const commands = {
"state": (value) => {
return {
cId: 'genOnOff',
cmd: value.toLowerCase(),
zclData: {},
}
},
"brightness": (value) => {
return {
cId: 'genLevelCtrl',
cmd: 'moveToLevel',
zclData: {
level: value,
transtime: 1,
},
}
},
"color_temp": (value) => {
return {
cId: 'lightingColorCtrl',
cmd: 'moveToColorTemp',
zclData: {
colortemp: value,
transtime: 1,
},
}
},
}
module.exports = commands;
+10
View File
@@ -1,24 +1,34 @@
const devices = {
'lumi.sensor_switch': {
model: 'WXKG01LM',
vendor: 'Xiaomi',
description: 'MiJia wireless switch',
supports: 'single, double, triple, quadruple, many and long click',
},
'lumi.sens': {
model: 'WSDCGQ01LM',
vendor: 'Xiaomi',
description: 'MiJia temperature & humidity sensor ',
supports: 'temperature and humidity',
},
'lumi.sensor_motion': {
model: 'RTCGQ01LM',
vendor: 'Xiaomi',
description: 'MiJia human body movement sensor',
supports: 'occupancy, motion and no motion'
},
'lumi.sensor_magnet': {
model: 'MCCGQ01LM',
vendor: 'Xiaomi',
description: 'MiJia door & window contact sensor',
supports: 'open and closed state',
},
'TRADFRI bulb E27 WS opal 980lm': {
model: 'LED1545G12',
vendor: 'IKEA',
description: 'TRADFRI LED bulb E27 980 lumen, dimmable, white spectrum, opal white',
supports: 'on/off, dimming, color temperature',
},
}
module.exports = devices;
+49 -5
View File
@@ -1,9 +1,9 @@
const debug = require('debug')('xiaomi-zb2mqtt')
const util = require("util");
const ZShepherd = require('zigbee-shepherd');
const mqtt = require('mqtt')
const fs = require('fs');
const parsers = require('./parsers');
const commands = require('./commands');
const deviceMapping = require('./devices');
const config = require('yaml-config');
const configFile = `${__dirname}/data/configuration.yaml`;
@@ -51,6 +51,7 @@ const shepherd = new ZShepherd(
// Register callbacks
client.on('connect', handleConnect);
client.on('message', handleMqttMessage);
shepherd.on('ready', handleReady);
shepherd.on('ind', handleMessage);
process.on('SIGINT', handleQuit);
@@ -76,9 +77,7 @@ shepherd.start((err) => {
function handleReady() {
logger.info('zigbee-shepherd ready');
const devices = shepherd.list().filter((device) => {
return device.manufId === 4151 && device.type === 'EndDevice'
});
const devices = shepherd.list().filter((device) => device.type !== 'Coordinator');
logger.info(`Currently ${devices.length} devices are joined:`);
devices.forEach((device) => logger.info(getDeviceLogMessage(device)));
@@ -108,10 +107,11 @@ function handleReady() {
function handleConnect() {
mqttPublish(`${settings.mqtt.base_topic}/bridge/state`, 'online', true);
client.subscribe(`${settings.mqtt.base_topic}/+/set`)
}
function handleMessage(msg) {
if (msg.type !== 'attReport') {
if (!msg.endpoints) {
return;
}
@@ -227,3 +227,47 @@ function getDeviceLogMessage(device) {
return `${friendlyName} (${device.ieeeAddr}): ${friendlyDevice.model} - ${friendlyDevice.description}`;
}
function handleMqttMessage(topic, message) {
const friendlyName = topic.split('/')[1];
// Find device id of this friendlyName
const deviceID = Object.keys(settings.devices).find((id) => settings.devices[id].friendly_name === friendlyName);
if (!deviceID) {
logger.error(`Cannot handle '${topic}' because ID of '${friendlyName}' cannot be found`);
}
// Find device in zigbee-shepherd
const device = shepherd.find(deviceID, 1);
if (!device) {
logger.error(`Cannot handle '${topic}' because '${deviceID}' is not known by zigbee-shepherd`);
}
logger.info(`Executing '${topic}' '${message.toString()}' `)
const json = JSON.parse(message);
// Iterate over all keys in the json.
Object.keys(json).forEach((key) => {
// Find parser for this key
const parser = commands[key];
if (!parser) {
logger.error(`No parser available for '${key}' (${json[key]})`);
return;
}
const parsed = parser(json[key]);
const callback = (err, rsp) => {
// Devices do not report when they go off.
// Ensure state (on/off) is always in sync.
if (!err && key === 'state') {
mqttPublish(
`${settings.mqtt.base_topic}/${friendlyName}`,
JSON.stringify({state: json[key]}),
true
);
}
};
device.functional(parsed.cId, parsed.cmd, parsed.zclData, callback);
});
}
+15
View File
@@ -105,6 +105,21 @@ const parsers = [
devices: ['MCCGQ01LM'],
cid: 'genOnOff',
parse: (msg) => {return {state: msg.data.data['onOff'] ? 'open' : 'closed'}}
},
{
devices: ['LED1545G12'],
cid: 'genOnOff',
parse: (msg) => null
},
{
devices: ['LED1545G12'],
cid: 'genLevelCtrl',
parse: (msg) => {return {brightness: msg.data.data['currentLevel']}},
},
{
devices: ['LED1545G12'],
cid: 'lightingColorCtrl',
parse: (msg) => {return {color_temp: msg.data.data['colorTemperature']}},
}
];