diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..16bcf0b2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +node_modules/* +support/* diff --git a/.eslintrc.json b/.eslintrc.json index a96cffa9..540026c9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,24 +1,17 @@ { "env": { - "browser": true, - "commonjs": true, - "es6": true, "node": true }, + "extends": ["eslint:recommended", "google"], "parserOptions": { "ecmaFeatures": { - "jsx": true, "experimentalObjectRestSpread": true }, "sourceType": "module" }, "rules": { - "no-const-assign": "warn", - "no-this-before-super": "warn", - "no-undef": "warn", - "no-unreachable": "warn", - "no-unused-vars": "warn", - "constructor-super": "warn", - "valid-typeof": "warn" + "require-jsdoc": "off", + "indent": ["error", 4], + "max-len": ["error", { "code": 120 }] } -} \ No newline at end of file +} diff --git a/.travis.yml b/.travis.yml index 39faccea..83b3a170 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ install: script: - npm run verify-homeassistant-mapping + - npm run eslint after_success: - ".travis/docker.sh" diff --git a/index.js b/index.js index 6accf7ba..9f509b9e 100644 --- a/index.js +++ b/index.js @@ -7,4 +7,4 @@ process.on('SIGINT', handleQuit); function handleQuit() { controller.stop(() => process.exit()); -} \ No newline at end of file +} diff --git a/lib/controller.js b/lib/controller.js index 123d3ad3..a390b0a9 100644 --- a/lib/controller.js +++ b/lib/controller.js @@ -6,14 +6,15 @@ const deviceMapping = require('./devices'); const zigbee2mqtt = require('./converters/zigbee2mqtt'); const mqtt2zigbee = require('./converters/mqtt2zigbee'); const homeassistant = require('./homeassistant'); -const debug = require('debug')('zigbee2mqtt') +const debug = require('debug')('zigbee2mqtt'); const mqttConfigRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/config/\\w+`, 'g'); const mqttDeviceRegex = new RegExp(`${settings.get().mqtt.base_topic}/\\w+/set`, 'g'); const mqttDevicePrefixRegex = new RegExp(`${settings.get().mqtt.base_topic}/\\w+/\\w+/set`, 'g'); -class Controller { +const issueLink = 'https://github.com/Koenkk/zigbee2mqtt/issues'; +class Controller { constructor() { this.zigbee = new Zigbee(); this.mqtt = new MQTT(); @@ -36,7 +37,7 @@ class Controller { const subscriptions = [ `${settings.get().mqtt.base_topic}/+/set`, `${settings.get().mqtt.base_topic}/+/+/set`, - `${settings.get().mqtt.base_topic}/bridge/config/+` + `${settings.get().mqtt.base_topic}/bridge/config/+`, ]; this.mqtt.connect(this.handleMQTTMessage, subscriptions, () => this.handleStarted()); } @@ -56,7 +57,7 @@ class Controller { // Enable zigbee join. if (settings.get().permit_join) { - logger.warn('`permit_join` set to `true` in configuration.yaml.') + 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); @@ -77,10 +78,11 @@ class Controller { } if (settings.getDevice(device.ieeeAddr)) { - friendlyName = settings.getDevice(device.ieeeAddr).friendly_name + friendlyName = settings.getDevice(device.ieeeAddr).friendly_name; } - return `${friendlyName} (${device.ieeeAddr}): ${friendlyDevice.model} - ${friendlyDevice.vendor} ${friendlyDevice.description}`; + return `${friendlyName} (${device.ieeeAddr}): ${friendlyDevice.model} - ` + + `${friendlyDevice.vendor} ${friendlyDevice.description}`; } handleZigbeeMessage(message) { @@ -121,7 +123,7 @@ class Controller { if (!mappedModel) { logger.warn(`Device with modelID '${modelID}' is not supported.`); - logger.warn('Please create an issue on https://github.com/Koenkk/zigbee2mqtt/issues to add support for your device'); + logger.warn(`Please create an issue on ${issueLink} to add support for your device`); return; } @@ -137,11 +139,15 @@ class Controller { // Find a conveter for this message. const cid = message.data.cid; - const converters = zigbee2mqtt.filter((c) => c.devices.includes(mappedModel.model) && c.cid === cid && c.type === message.type); + const converters = zigbee2mqtt.filter((c) => + c.devices.includes(mappedModel.model) && c.cid === cid && c.type === message.type + ); if (!converters.length) { - logger.warn(`No converter available for '${mappedModel.model}' with cid '${cid}' and type '${message.type}'`); - logger.warn('Please create an issue on https://github.com/Koenkk/zigbee2mqtt/issues with this message.'); + logger.warn( + `No converter available for '${mappedModel.model}' with cid '${cid}' and type '${message.type}'` + ); + logger.warn(`Please create an issue on ${issueLink} with this message.`); return; } @@ -151,7 +157,10 @@ class Controller { // - 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. converters.forEach((converter) => { - const publish = (payload) => this.mqttPublishDeviceState(device.ieeeAddr, payload, converter.disableCache !== true); + const publish = (payload) => this.mqttPublishDeviceState( + device.ieeeAddr, payload, converter.disableCache !== true + ); + const payload = converter.convert(message, publish, settings.getDevice(device.ieeeAddr)); if (payload) { @@ -185,7 +194,10 @@ class Controller { const topicPrefix = withPrefix ? topic.split('/')[2] : ''; // Map friendlyName to deviceID. - const deviceID = Object.keys(settings.get().devices).find((id) => settings.getDevice(id).friendly_name === friendlyName); + 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; @@ -247,4 +259,4 @@ class Controller { } } -module.exports = Controller; \ No newline at end of file +module.exports = Controller; diff --git a/lib/converters/mqtt2zigbee.js b/lib/converters/mqtt2zigbee.js index 80f33d22..00391cf7 100644 --- a/lib/converters/mqtt2zigbee.js +++ b/lib/converters/mqtt2zigbee.js @@ -1,12 +1,12 @@ const converters = { - "state": (value) => { + 'state': (value) => { return { cid: 'genOnOff', cmd: value.toLowerCase(), zclData: {}, - } + }; }, - "brightness": (value) => { + 'brightness': (value) => { return { cid: 'genLevelCtrl', cmd: 'moveToLevel', @@ -14,9 +14,9 @@ const converters = { level: value, transtime: 0, }, - } + }; }, - "color_temp": (value) => { + 'color_temp': (value) => { return { cid: 'lightingColorCtrl', cmd: 'moveToColorTemp', @@ -24,9 +24,9 @@ const converters = { colortemp: value, transtime: 0, }, - } + }; }, - "color": (value) => { + 'color': (value) => { return { cid: 'lightingColorCtrl', cmd: 'moveToColor', @@ -35,8 +35,8 @@ const converters = { colory: value.y * 65535, transtime: 0, }, - } + }; }, -} +}; -module.exports = converters; \ No newline at end of file +module.exports = converters; diff --git a/lib/converters/zigbee2mqtt.js b/lib/converters/zigbee2mqtt.js index ba31db96..96d4dac8 100644 --- a/lib/converters/zigbee2mqtt.js +++ b/lib/converters/zigbee2mqtt.js @@ -3,12 +3,12 @@ const clickLookup = { 2: 'double', 3: 'triple', 4: 'quadruple', -} +}; const battery3V = { min: 2500, max: 3000, -} +}; const WXKG02LM = { 1: 'left', @@ -32,20 +32,23 @@ const toPercentage = (value, min, max) => { const normalised = (value - min) / (max - min); return (normalised * 100).toFixed(2); -} +}; const precisionRound = (number, precision) => { const factor = Math.pow(10, precision); return Math.round(number * factor) / factor; -} +}; // Global variable store that can be used by devices. -const store = {} +const store = {}; const parsers = [ { - devices: ['WXKG01LM', 'RTCGQ01LM', 'WSDCGQ01LM', 'MCCGQ01LM', 'WXKG11LM', 'MCCGQ11LM', 'RTCGQ11LM', 'WSDCGQ11LM', 'SJCGQ11LM', 'MFKZQ01LM', 'JTYJ-GD-01LM/BW', 'WXKG02LM', 'WXKG03LM'], + devices: [ + 'WXKG01LM', 'RTCGQ01LM', 'WSDCGQ01LM', 'MCCGQ01LM', 'WXKG11LM', 'MCCGQ11LM', 'RTCGQ11LM', 'WSDCGQ11LM', + 'SJCGQ11LM', 'MFKZQ01LM', 'JTYJ-GD-01LM/BW', 'WXKG02LM', 'WXKG03LM', + ], cid: 'genBasic', type: 'attReport', convert: (msg) => { @@ -58,9 +61,9 @@ const parsers = [ } if (voltage) { - return {battery: toPercentage(voltage, battery3V.min, battery3V.max)} + return {battery: toPercentage(voltage, battery3V.min, battery3V.max)}; } - } + }, }, { devices: ['WXKG01LM'], @@ -71,7 +74,7 @@ const parsers = [ const deviceID = msg.endpoints[0].device.ieeeAddr; const state = msg.data.data['onOff']; - // 0 = click down, 1 = click up, else = multiple clicks + // 0 = click down, 1 = click up, else = multiple clicks if (state === 0) { store[deviceID] = setTimeout(() => { publish({click: 'long'}); @@ -88,13 +91,15 @@ const parsers = [ const payload = clickLookup[clicks] ? clickLookup[clicks] : 'many'; publish({click: payload}); } - } + }, }, { devices: ['WSDCGQ01LM', 'WSDCGQ11LM'], cid: 'msTemperatureMeasurement', type: 'attReport', - convert: (msg) => {return {temperature: parseFloat(msg.data.data['measuredValue']) / 100.0}} + convert: (msg) => { + return {temperature: parseFloat(msg.data.data['measuredValue']) / 100.0}; + }, }, { devices: ['MFKZQ01LM'], @@ -122,31 +127,19 @@ const parsers = [ presentValue = x + 256 = push/slide cube while side x is on top presentValue = x + 512 = double tap while side x is on top */ - var v = msg.data.data['presentValue']; - switch (true) { - case (v == 0): - return {action: 'shake'} - break; - case (v == 2): - return {action: 'wakeup'} - break; - case (v == 3): - return {action: 'fall'} - break; - case (v >= 512): // double tap - return {action: 'tap'} - break; - case (v >= 256): // slide - return {action: 'slide'} - break; - case (v >= 128): // 180 flip - return {action: 'flip180'} - break; - case (v >= 64): // 90 flip - return {action: 'flip90'} - break; - } - } + const value = msg.data.data['presentValue']; + let action = null; + + if (value === 0) action = 'shake'; + else if (value === 2) action = 'wakeup'; + else if (value === 3) action = 'fall'; + else if (value >= 512) action = 'tap'; + else if (value >= 256) action = 'slide'; + else if (value >= 128) action = 'flip180'; + else if (value >= 64) action = 'flip90'; + + return action ? {'action': action} : null; + }, }, { devices: ['MFKZQ01LM'], @@ -158,19 +151,17 @@ const parsers = [ Source: https://github.com/kirovilya/ioBroker.zigbee presentValue = rotation angel left < 0, rigth > 0 */ - var v = msg.data.data['presentValue']; - if (v < 0) { - return {action: 'rotate_left'} - } else { - return {action: 'rotate_right'} - } - } + const value = msg.data.data['presentValue']; + return {action: value < 0 ? 'rotate_left' : 'rotate_right'}; + }, }, { devices: ['WSDCGQ01LM', 'WSDCGQ11LM'], cid: 'msRelativeHumidity', type: 'attReport', - convert: (msg) => {return {humidity: parseFloat(msg.data.data['measuredValue']) / 100.0}} + convert: (msg) => { + return {humidity: parseFloat(msg.data.data['measuredValue']) / 100.0}; + }, }, { devices: ['RTCGQ01LM', 'RTCGQ11LM'], @@ -189,23 +180,27 @@ const parsers = [ } store[deviceID] = setTimeout(() => { - publish({occupancy: false}) + publish({occupancy: false}); store[deviceID] = null; }, timeout * 1000); return {occupancy: true}; - } + }, }, { devices: ['MCCGQ01LM', 'MCCGQ11LM'], cid: 'genOnOff', type: 'attReport', - convert: (msg) => {return {contact: msg.data.data['onOff'] === 0}} + convert: (msg) => { + return {contact: msg.data.data['onOff'] === 0}; + }, }, { devices: ['LED1545G12', '7146060PH', 'LED1537R6', 'LED1623G12', 'LED1650R5', 'LED1536G5', 'F7C033'], cid: 'genLevelCtrl', type: 'devChange', - convert: (msg) => {return {brightness: msg.data.data['currentLevel']}}, + convert: (msg) => { + return {brightness: msg.data.data['currentLevel']}; + }, }, { devices: ['LED1545G12', '7146060PH', 'LED1537R6', 'LED1536G5'], @@ -222,7 +217,7 @@ const parsers = [ result.color = { x: precisionRound(msg.data.data['currentX'] / 65535, 3), y: precisionRound(msg.data.data['currentY'] / 65535, 3), - } + }; } return result; @@ -246,57 +241,73 @@ const parsers = [ if (clickLookup[clicks]) { return {click: clickLookup[clicks]}; } - } + }, }, { devices: ['RTCGQ11LM'], cid: 'msIlluminanceMeasurement', type: 'attReport', - convert: (msg) => {return {illuminance: msg.data.data['measuredValue']}} + convert: (msg) => { + return {illuminance: msg.data.data['measuredValue']}; + }, }, { devices: ['WSDCGQ11LM'], cid: 'msPressureMeasurement', type: 'attReport', - convert: (msg) => {return {pressure: msg.data.data['measuredValue']}} + convert: (msg) => { + return {pressure: msg.data.data['measuredValue']}; + }, }, { devices: ['WXKG02LM'], cid: 'genOnOff', type: 'attReport', disableCache: true, - convert: (msg) => {return {click: WXKG02LM[msg.endpoints[0].epId]}} + convert: (msg) => { + return {click: WXKG02LM[msg.endpoints[0].epId]}; + }, }, { devices: ['WXKG03LM'], cid: 'genOnOff', type: 'attReport', disableCache: true, - convert: () => {return {click: 'single'}} + convert: () => { + return {click: 'single'}; + }, }, { devices: ['SJCGQ11LM'], cid: 'genBasic', type: 'attReport', - convert: (msg) => {return {water_leak: msg.data.data['65281']['100'] === 1}} + convert: (msg) => { + return {water_leak: msg.data.data['65281']['100'] === 1}; + }, }, { devices: ['SJCGQ11LM'], cid: 'ssIasZone', type: 'statusChange', - convert: (msg) => {return {water_leak: msg.data.zoneStatus === 1}} + convert: (msg) => { + return {water_leak: msg.data.zoneStatus === 1}; + }, }, { devices: ['ZNCZ02LM', 'QBCZ11LM'], cid: 'genOnOff', type: 'attReport', - convert: (msg) => {return {state: msg.data.data['onOff'] === 1 ? "ON" : "OFF"}} + convert: (msg) => { + return {state: msg.data.data['onOff'] === 1 ? 'ON' : 'OFF'}; + }, }, { devices: ['ZNCZ02LM', 'QBCZ11LM'], cid: 'genAnalogInput', type: 'attReport', - convert: (msg) => {return {power: precisionRound(msg.data.data['presentValue'], 2)}} + convert: (msg) => { + return {power: precisionRound(msg.data.data['presentValue'], 2)}; + }, }, { devices: ['QBKG04LM'], @@ -304,9 +315,9 @@ const parsers = [ type: 'attReport', convert: (msg) => { if (msg.data.data['61440']) { - return {state: msg.data.data['onOff'] === 1 ? "ON" : "OFF"} + return {state: msg.data.data['onOff'] === 1 ? 'ON' : 'OFF'}; } - } + }, }, { devices: ['QBKG03LM'], @@ -316,78 +327,86 @@ const parsers = [ if (msg.data.data['61440']) { const key = `state_${QBKG03LM[msg.endpoints[0].epId]}`; const payload = {}; - payload[key] = msg.data.data['onOff'] === 1 ? "ON" : "OFF" + payload[key] = msg.data.data['onOff'] === 1 ? 'ON' : 'OFF'; return payload; } - } + }, }, { devices: ['JTYJ-GD-01LM/BW'], cid: 'ssIasZone', type: 'statusChange', - convert: (msg) => {return {smoke: msg.data.zoneStatus === 1}} + convert: (msg) => { + return {smoke: msg.data.zoneStatus === 1}; + }, }, // Ignore parsers (these message dont need parsing). { - devices: ['WXKG11LM', 'MCCGQ11LM', 'MCCGQ01LM', 'WXKG01LM', 'LED1545G12', '7146060PH', 'LED1537R6', 'ZNCZ02LM', 'QBCZ11LM', 'QBKG04LM', 'QBKG03LM', 'LED1623G12', 'LED1650R5', 'LED1536G5', 'F7C033'], + devices: [ + 'WXKG11LM', 'MCCGQ11LM', 'MCCGQ01LM', 'WXKG01LM', 'LED1545G12', '7146060PH', 'LED1537R6', 'ZNCZ02LM', + 'QBCZ11LM', 'QBKG04LM', 'QBKG03LM', 'LED1623G12', 'LED1650R5', 'LED1536G5', 'F7C033', + ], cid: 'genOnOff', type: 'devChange', - convert: () => null + convert: () => null, }, { - devices: ['WXKG11LM', 'MCCGQ11LM', 'RTCGQ11LM', 'WSDCGQ11LM', 'SJCGQ11LM', 'MCCGQ01LM', 'RTCGQ01LM', 'WXKG01LM', 'WSDCGQ01LM', 'JTYJ-GD-01LM/BW'], + devices: [ + 'WXKG11LM', 'MCCGQ11LM', 'RTCGQ11LM', 'WSDCGQ11LM', 'SJCGQ11LM', 'MCCGQ01LM', 'RTCGQ01LM', 'WXKG01LM', + 'WSDCGQ01LM', 'JTYJ-GD-01LM/BW', + ], cid: 'genBasic', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['RTCGQ11LM'], cid: 'msIlluminanceMeasurement', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['RTCGQ11LM'], cid: 'msOccupancySensing', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['WSDCGQ11LM'], cid: 'msTemperatureMeasurement', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['WSDCGQ11LM'], cid: 'msRelativeHumidity', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['WSDCGQ11LM'], cid: 'msPressureMeasurement', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['ZNCZ02LM', 'QBCZ11LM'], cid: 'genAnalogInput', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['MFKZQ01LM'], cid: 'genMultistateInput', type: 'devChange', - convert: () => null + convert: () => null, }, { devices: ['MFKZQ01LM'], cid: 'genAnalogInput', type: 'devChange', - convert: () => null + convert: () => null, }, ]; diff --git a/lib/devices.js b/lib/devices.js index 532965bc..289bf04f 100644 --- a/lib/devices.js +++ b/lib/devices.js @@ -156,6 +156,6 @@ const devices = { description: 'WeMo smart LED bulb', supports: 'on/off, brightness', }, -} +}; module.exports = devices; diff --git a/lib/homeassistant.js b/lib/homeassistant.js index 50116298..81dd65d7 100644 --- a/lib/homeassistant.js +++ b/lib/homeassistant.js @@ -10,8 +10,8 @@ const configurations = { payload_off: false, value_template: '{{ value_json.occupancy }}', device_class: 'motion', - json_attributes: ['battery'] - } + json_attributes: ['battery'], + }, }, 'binary_sensor_contact': { type: 'binary_sensor', @@ -21,8 +21,8 @@ const configurations = { payload_off: true, value_template: '{{ value_json.contact }}', device_class: 'door', - json_attributes: ['battery'] - } + json_attributes: ['battery'], + }, }, 'binary_sensor_water_leak': { type: 'binary_sensor', @@ -32,8 +32,8 @@ const configurations = { payload_off: false, value_template: '{{ value_json.water_leak }}', device_class: 'moisture', - json_attributes: ['battery'] - } + json_attributes: ['battery'], + }, }, 'binary_sensor_smoke': { type: 'binary_sensor', @@ -43,8 +43,8 @@ const configurations = { payload_off: false, value_template: '{{ value_json.smoke }}', device_class: 'smoke', - json_attributes: ['battery'] - } + json_attributes: ['battery'], + }, }, // Sensor @@ -56,7 +56,7 @@ const configurations = { icon: 'mdi:theme-light-dark', value_template: '{{ value_json.illuminance }}', json_attributes: ['battery'], - } + }, }, 'sensor_humidity': { type: 'sensor', @@ -66,7 +66,7 @@ const configurations = { icon: 'mdi:water-percent', value_template: '{{ value_json.humidity }}', json_attributes: ['battery'], - } + }, }, 'sensor_temperature': { type: 'sensor', @@ -76,7 +76,7 @@ const configurations = { icon: 'mdi:temperature-celsius', value_template: '{{ value_json.temperature }}', json_attributes: ['battery'], - } + }, }, 'sensor_pressure': { type: 'sensor', @@ -86,7 +86,7 @@ const configurations = { icon: 'mdi:speedometer', value_template: '{{ value_json.pressure }}', json_attributes: ['battery'], - } + }, }, 'sensor_click': { type: 'sensor', @@ -95,7 +95,7 @@ const configurations = { icon: 'mdi:toggle-switch', value_template: '{{ value_json.click }}', json_attributes: ['battery'], - } + }, }, 'sensor_power': { type: 'sensor', @@ -104,7 +104,7 @@ const configurations = { unit_of_measurement: 'Watt', icon: 'mdi:flash', value_template: '{{ value_json.power }}', - } + }, }, 'sensor_action': { type: 'sensor', @@ -113,7 +113,7 @@ const configurations = { icon: 'mdi:cube', value_template: '{{ value_json.action }}', json_attributes: ['battery'], - } + }, }, // Light @@ -125,8 +125,8 @@ const configurations = { color_temp: true, xy: true, platform: 'mqtt_json', - command_topic: true - } + command_topic: true, + }, }, 'light_brightness_colortemp': { type: 'light', @@ -135,8 +135,8 @@ const configurations = { brightness: true, color_temp: true, platform: 'mqtt_json', - command_topic: true - } + command_topic: true, + }, }, 'light_brightness': { type: 'light', @@ -144,8 +144,8 @@ const configurations = { discovery_payload: { brightness: true, platform: 'mqtt_json', - command_topic: true - } + command_topic: true, + }, }, // Switch @@ -156,8 +156,8 @@ const configurations = { payload_off: 'OFF', payload_on: 'ON', value_template: '{{ value_json.state }}', - command_topic: true - } + command_topic: true, + }, }, 'switch_l1': { type: 'switch', @@ -167,8 +167,8 @@ const configurations = { payload_on: 'ON', value_template: '{{ value_json.state_l1 }}', command_topic: true, - command_topic_prefix: 'l1' - } + command_topic_prefix: 'l1', + }, }, 'switch_l2': { type: 'switch', @@ -178,8 +178,8 @@ const configurations = { payload_on: 'ON', value_template: '{{ value_json.state_l2 }}', command_topic: true, - command_topic_prefix: 'l2' - } + command_topic_prefix: 'l2', + }, }, }; diff --git a/lib/mqtt.js b/lib/mqtt.js index ad6daa7b..14b382ff 100644 --- a/lib/mqtt.js +++ b/lib/mqtt.js @@ -3,7 +3,6 @@ const logger = require('./util/logger'); const settings = require('./util/settings'); class MQTT { - constructor() { this.handleConnect = this.handleConnect.bind(this); this.handleMessage = this.handleMessage.bind(this); @@ -63,9 +62,9 @@ class MQTT { } } - publish(topic, payload, options, callback, base_topic) { - base_topic = base_topic ? base_topic : settings.get().mqtt.base_topic; - topic = `${base_topic}/${topic}`; + publish(topic, payload, options, callback, baseTopic) { + baseTopic = baseTopic ? baseTopic : settings.get().mqtt.base_topic; + topic = `${baseTopic}/${topic}`; if (!this.client || this.client.reconnecting) { logger.error(`Not connected to MQTT server!`); diff --git a/lib/util/data.js b/lib/util/data.js index b50cadf4..3357f336 100644 --- a/lib/util/data.js +++ b/lib/util/data.js @@ -4,12 +4,11 @@ let dataPath = null; if (process.env.ZIGBEE2MQTT_DATA) { dataPath = process.env.ZIGBEE2MQTT_DATA; -} -else { +} else { dataPath = path.join(__dirname, '..', '..', 'data'); dataPath = path.normalize(dataPath); } module.exports = { - joinPath: (file) => path.join(dataPath, file) -} + joinPath: (file) => path.join(dataPath, file), +}; diff --git a/lib/util/logger.js b/lib/util/logger.js index c1935fa0..9eb800d9 100644 --- a/lib/util/logger.js +++ b/lib/util/logger.js @@ -17,9 +17,9 @@ const logger = new (winston.Logger)({ winston.config.colorize(options.level, options.level.toUpperCase()) + ' ' + (options.message ? options.message : '') + (options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' ); - } - }) - ] + }, + }), + ], }); module.exports = logger; diff --git a/lib/util/settings.js b/lib/util/settings.js index 54e39486..aafd76a0 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -9,17 +9,17 @@ let yawn = read(); // Migrate configuration. if (!yawn.json.advanced) { // 1: Add advanced section to configuration.yaml - logger.info("Migrating configuration.yaml to version 1..."); - yawn.yaml += "\n\n" + - "# Advanced configuration\n" + - "advanced:\n" + - " version: 1\n" + - " pan_id: 0x1a62\n"; + logger.info('Migrating configuration.yaml to version 1...'); + yawn.yaml += '\n\n' + + '# Advanced configuration\n' + + 'advanced:\n' + + ' version: 1\n' + + ' pan_id: 0x1a62\n'; - write_read(); + writeRead(); } -function write_read() { +function writeRead() { write(); yawn = read(); } @@ -34,12 +34,12 @@ function read() { function addDevice(id) { if (!yawn.json.devices) { - const first = "\n" + - "# List of devices, automatically updates when new devices join, E.G.:\n" + - "# '0x00158d0001d8e1d2':\n" + - "# friendly_name: bedroom_switch # Friendly name to be used in MQTT topic\n" + - "# retain: true # Retain MQTT messages\n" + - "devices:\n" + + const first = '\n' + + '# List of devices, automatically updates when new devices join, E.G.:\n' + + `# '0x00158d0001d8e1d2':\n` + + '# friendly_name: bedroom_switch # Friendly name to be used in MQTT topic\n' + + '# retain: true # Retain MQTT messages\n' + + 'devices:\n' + ` '${id}':\n` + ` friendly_name: '${id}'\n` + ` retain: false`; @@ -51,7 +51,7 @@ function addDevice(id) { yawn.json = {...yawn.json, devices: devices}; } - write_read(); + writeRead(); } module.exports = { @@ -59,4 +59,4 @@ module.exports = { write: () => write(), getDevice: (id) => yawn.json.devices ? yawn.json.devices[id] : false, addDevice: (id) => addDevice(id), -} +}; diff --git a/lib/zigbee.js b/lib/zigbee.js index 0fa2920d..c16fe0f6 100644 --- a/lib/zigbee.js +++ b/lib/zigbee.js @@ -5,11 +5,10 @@ const data = require('./util/data'); const shepherdSettings = { net: {panId: settings.get().advanced.pan_id}, - dbPath: data.joinPath('database.db') + dbPath: data.joinPath('database.db'), }; class Zigbee { - constructor() { this.handleReady = this.handleReady.bind(this); this.handleMessage = this.handleMessage.bind(this); @@ -39,7 +38,7 @@ class Zigbee { stop(callback) { this.shepherd.stop((error) => { - logger.info('zigbee-shepherd stopped') + logger.info('zigbee-shepherd stopped'); callback(error); }); } @@ -52,7 +51,7 @@ class Zigbee { if (device.manufId === 4151) { this.shepherd.find(device.ieeeAddr, 1).getDevice().update({ status: 'online', - joinTime: Math.floor(Date.now()/1000) + joinTime: Math.floor(Date.now() / 1000), }); } }); @@ -100,7 +99,9 @@ class Zigbee { device = this.shepherd.find(deviceID, ep); if (!device) { - logger.error(`Zigbee cannot publish message to device because '${deviceID}' is not known by zigbee-shepherd`); + logger.error( + `Zigbee cannot publish message to device because '${deviceID}' is not known by zigbee-shepherd` + ); return; } diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 30f44a0c..1bd06288 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -569,6 +569,12 @@ } } }, + "eslint-config-google": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", + "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==", + "dev": true + }, "eslint-scope": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", @@ -753,7 +759,7 @@ "glob-parent": "3.1.0", "is-negated-glob": "1.0.0", "ordered-read-streams": "1.0.1", - "pumpify": "1.5.0", + "pumpify": "1.5.1", "readable-stream": "2.3.6", "remove-trailing-separator": "1.1.0", "to-absolute-glob": "2.0.2", @@ -1038,7 +1044,7 @@ "resolved": "https://registry.npmjs.org/json2yaml/-/json2yaml-1.1.0.tgz", "integrity": "sha1-VBTZB/mBZYa4DFE+wuOusquBmmw=", "requires": { - "remedial": "1.0.7" + "remedial": "1.0.8" } }, "jsonify": { @@ -1137,9 +1143,9 @@ } }, "mqtt": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-2.17.0.tgz", - "integrity": "sha512-eYeK5G/GQcdP/AOrGQMUULX7QvBXt3I9bfmgNkzMTsdSR1ywJQhK1iCYPrhh+rtRl3eUSJwEbO+oZx/Q51uHaw==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-2.18.0.tgz", + "integrity": "sha512-d4hXWziT6tLMjaQs5TVh8uHWS072GBfmBIABezbWZ8W0nNzgMUm6iEmXDLvxkj5YVgl8qDdM0pWQ2NwRwhU7nA==", "requires": { "commist": "1.0.0", "concat-stream": "1.6.2", @@ -1147,7 +1153,7 @@ "help-me": "1.1.0", "inherits": "2.0.3", "minimist": "1.2.0", - "mqtt-packet": "5.5.0", + "mqtt-packet": "5.6.0", "pump": "3.0.0", "readable-stream": "2.3.6", "reinterval": "1.1.0", @@ -1157,9 +1163,9 @@ } }, "mqtt-packet": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-5.5.0.tgz", - "integrity": "sha512-kR+Uw+r9rjUFSLZutmaAhjL4Y1asKLMTwE++PP0iuApJuc+zItE5v2LluQN2K3Pri5e2+K4V++QDjqGTgle/+A==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-5.6.0.tgz", + "integrity": "sha512-QECe2ivqcR1LRsPobRsjenEKAC3i1a5gmm+jNKJLrsiq9PaSQ18LlKFuxvhGxWkvGEPadWv6rKd31O4ICqS1Xw==", "requires": { "bl": "1.2.2", "inherits": "2.0.3", @@ -1365,9 +1371,9 @@ } }, "pumpify": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.0.tgz", - "integrity": "sha512-UWi0klDoq8xtVzlMRgENV9F7iCTZExaJQSQL187UXsxpk9NnrKGqTqqUNYAKGOzucSOxs2+jUnRNI+rLviPhJg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "requires": { "duplexify": "3.6.0", "inherits": "2.0.3", @@ -1416,9 +1422,9 @@ "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" }, "remedial": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.7.tgz", - "integrity": "sha1-1mdEE6ZWdgB74A3UAJgJh7LDAME=" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", + "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==" }, "remove-trailing-separator": { "version": "1.1.0", diff --git a/package.json b/package.json index e5bbb645..04e8f9af 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "scripts": { "start": "node index.js", "docgen": "node support/docgen.js", - "verify-homeassistant-mapping": "node support/verify-homeassistant-mapping.js" + "verify-homeassistant-mapping": "node support/verify-homeassistant-mapping.js", + "eslint": "node_modules/.bin/eslint ." }, "author": "Koen Kanters", "license": "GPL-3.0", @@ -36,6 +37,7 @@ "yawn-yaml": "*" }, "devDependencies": { - "eslint": "*" + "eslint": "*", + "eslint-config-google": "*" } }