From 3322d6cb20dbb38463655d1f0d636dcde1603ae8 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Tue, 24 Apr 2018 19:30:56 +0200 Subject: [PATCH] Allow settings permit_join via home assistant switch. --- lib/controller.js | 83 ++++++++++++++++++++++++++++++-------------- lib/homeassistant.js | 13 +++++++ lib/zigbee.js | 13 +++---- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/lib/controller.js b/lib/controller.js index 41ebcb6d2..71188cc31 100644 --- a/lib/controller.js +++ b/lib/controller.js @@ -5,6 +5,7 @@ const settings = require('./util/settings'); const deviceMapping = require('./devices'); const zigbee2mqtt = require('./converters/zigbee2mqtt'); const mqtt2zigbee = require('./converters/mqtt2zigbee'); +const homeassistant = require('./homeassistant'); class Controller { @@ -24,24 +25,45 @@ class Controller { logger.error('Failed to start'); } else { this.mqtt.connect(this.handleMQTTMessage, () => { - // Home assistant MQTT discovery on startup. - if (settings.get().homeassistant) { - const devices = this.zigbee.getAllClients(); - - devices.forEach((device) => { - const mappedModel = deviceMapping[device.modelId]; - - if (mappedModel && mappedModel.homeassistant && !this.hassDiscoveryCache[device.ieeeAddr]) { - this.homeassistantDiscover(mappedModel, device, settings.getDevice(device.ieeeAddr).friendly_name); - this.hassDiscoveryCache[device.ieeeAddr] = true; - } - }); - } + this.handleStarted(); }); } }); } + handleStarted() { + // Home assistant MQTT discovery on startup. + if (settings.get().homeassistant) { + // MQTT discovery of all paired devices on startup. + const devices = this.zigbee.getAllClients(); + devices.forEach((device) => { + const mappedModel = deviceMapping[device.modelId]; + + if (mappedModel && mappedModel.homeassistant && !this.hassDiscoveryCache[device.ieeeAddr]) { + this.homeassistantDiscover( + mappedModel.homeassistant, + device.ieeeAddr, + settings.getDevice(device.ieeeAddr).friendly_name + ); + + this.hassDiscoveryCache[device.ieeeAddr] = true; + } + }); + + // MQTT discovery of zigbee2mqtt permit join switch. + this.homeassistantDiscover([homeassistant.zigbee2mqtt_permit_join], 'zigbee2mqtt_permit_join', 'zigbee2mqtt_permit_join'); + this.mqtt.publish('permit_join', JSON.stringify({state: settings.get().permit_join ? '"ON"' : '"OFF"'}), true); + } + + // Enable zigbee join. + if (settings.get().permit_join) { + logger.warn('`permit_join` set to `true` in configuration.yaml.') + logger.warn('Allowing new devices to join.'); + logger.warn('Set `permit_join` to `false` once you joined all devices.'); + this.zigbee.permitJoin(true); + } + } + stop(callback) { this.mqtt.disconnect(); this.zigbee.stop(callback); @@ -98,7 +120,7 @@ class Controller { // Home assistant MQTT discovery if (settings.get().homeassistant && mappedModel.homeassistant && !this.hassDiscoveryCache[device.ieeeAddr]) { - this.homeassistantDiscover(mappedModel, device, friendlyName); + this.homeassistantDiscover(mappedModel.homeassistant, device.ieeeAddr, friendlyName); this.hassDiscoveryCache[device.ieeeAddr] = true; } @@ -148,13 +170,6 @@ class Controller { handleMQTTMessage(topic, message) { const friendlyName = topic.split('/')[1]; - // Map friendlyName to deviceID. - const deviceID = Object.keys(settings.get().devices).find((id) => settings.getDevice(id).friendly_name === friendlyName); - if (!deviceID) { - logger.error(`Cannot handle '${topic}' because deviceID of '${friendlyName}' cannot be found`); - return; - } - // Convert the MQTT message to a Zigbee message. let json = null; try { @@ -164,6 +179,20 @@ class Controller { json = {state: message.toString()}; } + // Check if permit_join + if (friendlyName === 'zigbee2mqtt_permit_join') { + this.zigbee.permitJoin(json.state === 'ON' ? true : false); + this.mqtt.publish(friendlyName, JSON.stringify({state: json.state}), true); + return; + } + + // Map friendlyName to deviceID. + const deviceID = Object.keys(settings.get().devices).find((id) => settings.getDevice(id).friendly_name === friendlyName); + if (!deviceID) { + logger.error(`Cannot handle '${topic}' because deviceID of '${friendlyName}' cannot be found`); + return; + } + Object.keys(json).forEach((key) => { // Find converter for this key. const converter = mqtt2zigbee[key]; @@ -188,16 +217,16 @@ class Controller { }); } - homeassistantDiscover(mappedModel, device, friendlyName) { - mappedModel.homeassistant.forEach((discover) => { - const topic = `${discover.type}/${device.ieeeAddr}/${discover.object_id}/config`; - const payload = discover.discovery_payload; + homeassistantDiscover(configurations, deviceID, friendlyName) { + configurations.forEach((config) => { + const topic = `${config.type}/${deviceID}/${config.object_id}/config`; + const payload = config.discovery_payload; payload.state_topic = `${settings.get().mqtt.base_topic}/${friendlyName}`; payload.availability_topic = `${settings.get().mqtt.base_topic}/bridge/state`; // Set unique names in cases this device produces multiple entities in homeassistant. - if (mappedModel.homeassistant.length > 1) { - payload.name = `${friendlyName}_${discover.object_id}`; + if (configurations.length > 1) { + payload.name = `${friendlyName}_${config.object_id}`; } else { payload.name = friendlyName; } diff --git a/lib/homeassistant.js b/lib/homeassistant.js index 5e987edc2..ac02d6669 100644 --- a/lib/homeassistant.js +++ b/lib/homeassistant.js @@ -128,6 +128,19 @@ const homeassistant = { command_topic: true } }, + + // zigbee2mqtt + 'zigbee2mqtt_permit_join': { + type: 'switch', + object_id: 'switch', + discovery_payload: { + payload_off: 'OFF', + payload_on: 'ON', + value_template: '{{ value_json.state }}', + command_topic: true, + icon: 'mdi:router-wireless', + } + }, }; module.exports = homeassistant; diff --git a/lib/zigbee.js b/lib/zigbee.js index 179e8c1d6..349c5a384 100644 --- a/lib/zigbee.js +++ b/lib/zigbee.js @@ -62,15 +62,16 @@ class Zigbee { }); } }); + } - // Allow or disallow new devices to join the network. - if (settings.get().permit_join) { - logger.warn('`permit_join` set to `true` in configuration.yaml.') - logger.warn('Allowing new devices to join.'); - logger.warn('Set `permit_join` to `false` once you joined all devices.'); + permitJoin(permit) { + if (permit) { + logger.info('Zigbee: allowing new devices to join.'); + } else { + logger.info('Zigbee: disabling joining new devices.'); } - this.shepherd.permitJoin(settings.get().permit_join ? 255 : 0, (error) => { + this.shepherd.permitJoin(permit ? 255 : 0, (error) => { if (error) { logger.info(error); }