zigbee2mqtt/lib/zigbee.js

132 lines
3.9 KiB
JavaScript
Raw Normal View History

2018-04-18 09:25:40 -07:00
const ZShepherd = require('zigbee-shepherd');
const logger = require('./util/logger');
const settings = require('./util/settings');
const deviceMapping = require('./devices');
const shepherdSettings = {
net: {panId: 0x1a62},
dbPath: `${__dirname}/../data/database.db`
};
class Zigbee {
constructor() {
this.handleReady = this.handleReady.bind(this);
this.handleMessage = this.handleMessage.bind(this);
}
start(onMessage, callback) {
logger.info(`Starting zigbee-shepherd`);
this.shepherd = new ZShepherd(settings.get().serial.port, shepherdSettings);
this.shepherd.start((error) => {
if (error) {
logger.error('Error while starting zigbee-shepherd!');
} else {
logger.info('zigbee-shepherd started');
}
callback(error);
});
// Register callbacks.
this.shepherd.on('ready', this.handleReady);
this.shepherd.on('ind', this.handleMessage);
this.onMessage = onMessage;
}
stop(callback) {
this.shepherd.stop((error) => {
2018-04-18 11:53:22 -07:00
logger.info('zigbee-shepherd stopped')
2018-04-18 09:25:40 -07:00
callback(error);
});
}
handleReady() {
logger.info('zigbee-shepherd ready');
const devices = this.getAllClients();
2018-04-18 09:25:40 -07:00
logger.info(`Currently ${devices.length} devices are joined:`);
2018-04-18 10:09:59 -07:00
devices.forEach((device) => logger.info(this.getDeviceLogMessage(device)));
2018-04-18 09:25:40 -07:00
// Set all Xiaomi devices (manufId === 4151) to be online, so shepherd won't try
// to query info from devices (which would fail because they go tosleep).
devices.forEach((device) => {
if (device.manufId === 4151) {
this.shepherd.find(device.ieeeAddr, 1).getDevice().update({
status: 'online',
joinTime: Math.floor(Date.now()/1000)
});
}
});
}
2018-04-18 09:25:40 -07:00
permitJoin(permit) {
if (permit) {
logger.info('Zigbee: allowing new devices to join.');
} else {
logger.info('Zigbee: disabling joining new devices.');
2018-04-18 09:25:40 -07:00
}
this.shepherd.permitJoin(permit ? 255 : 0, (error) => {
2018-04-18 09:25:40 -07:00
if (error) {
logger.info(error);
}
});
}
getAllClients() {
return this.shepherd.list().filter((device) => device.type !== 'Coordinator');
}
2018-04-18 09:25:40 -07:00
handleMessage(message) {
if (this.onMessage) {
this.onMessage(message);
}
}
getDeviceLogMessage(device) {
let friendlyName = 'unknown';
let friendlyDevice = {model: 'unkown', description: 'unknown'};
if (deviceMapping[device.modelId]) {
friendlyDevice = deviceMapping[device.modelId];
}
2018-04-25 10:29:03 -07:00
if (settings.getDevice(device.ieeeAddr)) {
friendlyName = settings.getDevice(device.ieeeAddr).friendly_name
2018-04-18 09:25:40 -07:00
}
2018-04-18 12:01:42 -07:00
return `${friendlyName} (${device.ieeeAddr}): ${friendlyDevice.model} - ${friendlyDevice.vendor} ${friendlyDevice.description}`;
2018-04-18 09:25:40 -07:00
}
2018-04-27 14:58:46 -07:00
getDevice(deviceID) {
return this.shepherd.list().find((d) => d.ieeeAddr === deviceID);
}
publish(deviceID, cId, cmd, zclData, ep, callback) {
2018-04-18 09:25:40 -07:00
// Find device in zigbee-shepherd
2018-04-27 14:58:46 -07:00
let device = this.getDevice(deviceID);
if (!device || !device.epList || !device.epList.length) {
logger.error(`Zigbee cannot determine endpoint for '${deviceID}'`);
return;
}
2018-04-27 14:58:46 -07:00
ep = ep ? ep : device.epList[0];
device = this.shepherd.find(deviceID, ep);
2018-04-18 09:25:40 -07:00
if (!device) {
logger.error(`Zigbee cannot publish message to device because '${deviceID}' is not known by zigbee-shepherd`);
2018-04-18 12:55:00 -07:00
return;
2018-04-18 09:25:40 -07:00
}
2018-04-27 14:58:46 -07:00
logger.info(`Zigbee publish to '${deviceID}', ${cId} - ${cmd} - ${JSON.stringify(zclData)} - ${ep}`);
2018-04-18 09:25:40 -07:00
device.functional(cId, cmd, zclData, callback);
}
}
module.exports = Zigbee;