Use Xiaomi model ids. #2

This commit is contained in:
Koen Kanters
2018-04-11 19:55:54 +02:00
parent 1b6365b136
commit a8bbd85b15
3 changed files with 68 additions and 44 deletions
+20
View File
@@ -0,0 +1,20 @@
const devices = {
'lumi.sensor_switch': {
model: 'WXKG01LM',
description: 'MiJia wireless switch',
},
'lumi.sens': {
model: 'WSDCGQ01LM',
description: 'MiJia temperature & humidity sensor ',
},
'lumi.sensor_motion': {
model: 'RTCGQ01LM',
description: 'MiJia human body movement sensor',
},
'lumi.sensor_magnet': {
model: 'MCCGQ01LM',
description: 'MiJia door & window contact sensor',
},
}
module.exports = devices;
+43 -16
View File
@@ -4,6 +4,7 @@ const ZShepherd = require('zigbee-shepherd');
const mqtt = require('mqtt')
const fs = require('fs');
const parsers = require('./parsers');
const deviceMapping = require('./devices');
const config = require('yaml-config');
const configFile = `${__dirname}/data/configuration.yaml`
const settings = config.readConfig(configFile, 'user');
@@ -51,9 +52,7 @@ function handleReady() {
});
console.log(`Currently ${devices.length} devices are joined:`);
devices.forEach((device) => {
console.log(`${device.ieeeAddr} ${device.nwkAddr} ${device.modelId}`);
});
devices.forEach((device) => console.log(getDeviceLogMessage(device)));
// Set all Xiaomi devices to be online, so shepherd won't try
// to query info from devices (which would fail because they go tosleep).
@@ -81,7 +80,7 @@ function handleReady() {
}
function handleConnect() {
client.publish('xiaomiZb', 'Bridge online');
client.publish(`${settings.mqtt.base_topic}/bridge/state`, 'online');
}
function handleMessage(msg) {
@@ -90,31 +89,43 @@ function handleMessage(msg) {
}
const device = msg.endpoints[0].device;
// Check if new device, add to config if new.
// New device!
if (!settings.devices[device.ieeeAddr]) {
console.log(`Detected new device: ${device.ieeeAddr} ${device.nwkAddr} ${device.modelId}`);
console.log(`New device with address ${device.ieeeAddr} connected!`);
settings.devices[device.ieeeAddr] = {
friendly_name: device.ieeeAddr
};
writeConfig();
}
// Check if we have a parser for this type of message.
// We can't handle devices without modelId.
if (!device.modelId) {
return;
}
// Map modelID to Xiaomi model.
const modelID = msg.endpoints[0].device.modelId;
const deviceID = msg.endpoints[0].devId;
const mappedModel = deviceMapping[modelID];
if (!mappedModel) {
console.log(`
WARNING: Device with modelID '${modelID}' is not supported.
Please create an issue on https://github.com/Koenkk/xiaomi-zb2mqtt/issues
to add support for your device`);
}
// Find a parser for this modelID and cid.
const cid = msg.data.cid;
const parser = parsers.find((p) => {
const device = p.supportedDevices.find((device) => device[0] === deviceID && device[1] === modelID);
return device && p.cid === cid;
});
const parser = parsers.find((p) => p.devices.includes(mappedModel.model) && p.cid === cid);
if (!parser) {
console.log(`
WARNING: No parser available for (${deviceID}, '${modelID}') for cid: ${cid}
Please report on https://github.com/Koenkk/xiaomi-zb2mqtt/issues
to add support for your device`);
WARNING: No parser available for '${mappedModel.model}' with cid '${cid}'
Please create an issue on https://github.com/Koenkk/xiaomi-zb2mqtt/issues
with this message.`);
return;
}
@@ -146,6 +157,7 @@ function handleQuit() {
console.error('zigbee-shepherd stopped')
}
client.publish(`${settings.mqtt.base_topic}/bridge/state`, 'offline');
process.exit();
});
}
@@ -154,3 +166,18 @@ function handleQuit() {
function writeConfig() {
config.updateConfig(settings, configFile, 'user');
}
function getDeviceLogMessage(device) {
let friendlyName = 'unknown';
let friendlyDevice = {model: 'unkown', description: 'unknown'};
if (deviceMapping[device.modelId]) {
friendlyDevice = deviceMapping[device.modelId];
}
if (settings.devices[device.ieeeAddr]) {
friendlyName = settings.devices[device.ieeeAddr].friendly_name
}
return `${friendlyName} (${device.ieeeAddr}): ${friendlyDevice.model} - ${friendlyDevice.description}`;
}
+5 -28
View File
@@ -4,20 +4,12 @@ const clickLookup = {
4: 'quadruple',
}
// Used as reference: (DeviceID, ModelID, Description)
const documentation = [
[260, 'lumi.sensor_switch', 'WXKG01LM - button switch'],
[24321, 'lumi.sens', 'WSDCGQ01LM - temprature/humidity sensor'],
[260, 'lumi.sensor_motion', 'RTCGQ11LM - Human body sensor'],
[260, 'lumi.sensor_magnet', 'YTC4005CN - Magnet door/window sensor'],
]
// Global variable store that can be used by devices.
const store = {}
const parsers = [
{
supportedDevices: [[260, 'lumi.sensor_switch']],
devices: ['WXKG01LM'],
cid: 'genOnOff',
topic: 'switch',
parse: (msg, publish) => {
@@ -49,19 +41,19 @@ const parsers = [
}
},
{
supportedDevices: [[24321, 'lumi.sens']],
devices: ['WSDCGQ01LM'],
cid: 'msTemperatureMeasurement',
topic: 'temperature',
parse: (msg) => parseFloat(msg.data.data['measuredValue']) / 100.0
},
{
supportedDevices: [[24321, 'lumi.sens']],
devices: ['WSDCGQ01LM'],
cid: 'msRelativeHumidity',
topic: 'humidity',
parse: (msg) => parseFloat(msg.data.data['measuredValue']) / 100.0
},
{
supportedDevices: [[260, 'lumi.sensor_motion']],
devices: ['RTCGQ01LM'],
cid: 'msOccupancySensing',
topic: 'occupancy',
parse: (msg, publish) => {
@@ -85,26 +77,11 @@ const parsers = [
}
},
{
supportedDevices: [[260, 'lumi.sensor_magnet']],
devices: ['MCCGQ01LM'],
cid: 'genOnOff',
topic: 'state',
parse: (msg) => msg.data.data['onOff'] ? 'open' : 'closed'
}
];
// Ensure consistency of documentation.
parsers.forEach((parser) => {
parser.supportedDevices.forEach(device => {
const docs = documentation.filter(doc => {
return device[0] === doc[0] && device[1] === doc[1];
});
if (docs.length === 0) {
console.log("ERROR: Incosistent documentation");
console.log(`Please add [${device[0]}, '${device[1]}', 'Add description here'], to documentation`);
process.exit()
}
});
});
module.exports = parsers;