mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-07-02 10:01:37 +00:00
Enforce code style. #45
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
node_modules/*
|
||||
support/*
|
||||
+5
-12
@@ -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 }]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ install:
|
||||
|
||||
script:
|
||||
- npm run verify-homeassistant-mapping
|
||||
- npm run eslint
|
||||
|
||||
after_success:
|
||||
- ".travis/docker.sh"
|
||||
|
||||
@@ -7,4 +7,4 @@ process.on('SIGINT', handleQuit);
|
||||
|
||||
function handleQuit() {
|
||||
controller.stop(() => process.exit());
|
||||
}
|
||||
}
|
||||
|
||||
+25
-13
@@ -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;
|
||||
module.exports = Controller;
|
||||
|
||||
@@ -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;
|
||||
module.exports = converters;
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
+1
-1
@@ -156,6 +156,6 @@ const devices = {
|
||||
description: 'WeMo smart LED bulb',
|
||||
supports: 'on/off, brightness',
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = devices;
|
||||
|
||||
+27
-27
@@ -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',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+3
-4
@@ -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!`);
|
||||
|
||||
+3
-4
@@ -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),
|
||||
};
|
||||
|
||||
+3
-3
@@ -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;
|
||||
|
||||
+16
-16
@@ -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),
|
||||
}
|
||||
};
|
||||
|
||||
+6
-5
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Generated
+21
-15
@@ -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",
|
||||
|
||||
+4
-2
@@ -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": "*"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user