homebridge-rflink
Advanced tools
Comparing version 1.1.6 to 1.1.7
@@ -15,55 +15,4 @@ 'use strict'; | ||
} | ||
class RFLinkPlatform { | ||
constructor(log, config) { | ||
this.log = config.debug ? log : () => { }; | ||
this.config = config; | ||
this.subscribers = []; | ||
let device = config.device || "/dev/ttyACM0"; | ||
this.port = new SerialPort(device, { | ||
baudRate: 57600, | ||
}); | ||
this.port.on("error", (err) => { | ||
log(`error opening port: ${err.message}`); | ||
}); | ||
const parser = this.port.pipe(new Readline({ delimiter: "\r\n" })); | ||
parser.on("data", s => { | ||
this.log(`received ${s}`); | ||
const m = s.match(/^20;[^;]+;(?<proto>[^;]+);ID=(?<address>[^;]+);SWITCH=(?<button>[^;]+);CMD=(?<command>[^;]+);/); | ||
if (m) { | ||
const { proto, address, button, command } = m.groups; | ||
this.notify({ device: `${proto};${address};${button}`, command }); | ||
} | ||
}); | ||
} | ||
subscribe(callback) { | ||
this.subscribers.push(callback); | ||
} | ||
notify(message) { | ||
this.subscribers.forEach(callback => callback(message)); | ||
} | ||
accessories(callback) { | ||
return callback((this.config.accessories || []).map(acc => { | ||
acc.type = acc.type || "Outlet"; | ||
// Validate type. | ||
if (!Service[acc.type]) { | ||
throw Error(`Unknown device type '${acc.type}'`); | ||
} | ||
if (!acc.devices) { | ||
if (acc.device) { | ||
acc.devices = [acc.device]; | ||
delete acc.device; | ||
} | ||
else { | ||
throw new Error("No device provided"); | ||
} | ||
} | ||
this.log(`adding ${acc.type.toLowerCase()} '${acc.name}' (devices = ${acc.devices})`); | ||
return new RFLinkAccessory(acc, this.port, this.log, this.subscribe.bind(this)); | ||
})); | ||
} | ||
} | ||
class RFLinkAccessory { | ||
class RFLinkBaseAccessory { | ||
constructor(config, port, log, subscribe) { | ||
this.currentValue = false; | ||
this.currentLevel = 0; | ||
this.name = config.name; | ||
@@ -84,20 +33,44 @@ this.config = config; | ||
if (config.devices.includes(message.device)) { | ||
switch (message.command) { | ||
case "ON": | ||
this.updateValue(true); | ||
break; | ||
case "OFF": | ||
this.updateValue(false); | ||
break; | ||
default: | ||
if (config.dimmable && message.command.startsWith("SET_LEVEL")) { | ||
const level = Number(message.command.substr(10)); | ||
if (!isNaN(level)) { | ||
this.updateLevel(level); | ||
} | ||
} | ||
} | ||
this.onMessage(message); | ||
} | ||
}); | ||
} | ||
onMessage(message) { } | ||
getServices() { | ||
return [this.informationService, this.service]; | ||
} | ||
} | ||
class RFLinkContactSensorAccessory extends RFLinkBaseAccessory { | ||
constructor(config, port, log, subscribe) { | ||
super(config, port, log, subscribe); | ||
this.currentValue = false; | ||
this.service | ||
.getCharacteristic(Characteristic.ContactSensorState) | ||
.on("get", (callback) => { | ||
callback(null, this.currentValue); | ||
}); | ||
} | ||
onMessage(message) { | ||
if (message.command === "ON") { | ||
this.updateValue(true); | ||
} | ||
else if (message.command === "OFF") { | ||
this.updateValue(false); | ||
} | ||
else { | ||
throw new Error("Unsupported command"); | ||
} | ||
} | ||
updateValue(value) { | ||
this.log(`Updated state of ${this.config.type.toLowerCase()} '${this.config.name}' to ${value ? "on" : "off"}`); | ||
this.currentValue = value; | ||
this.service.setCharacteristic(Characteristic.ContactSensorState, value); | ||
} | ||
} | ||
class RFLinkLightbulbAccessory extends RFLinkBaseAccessory { | ||
constructor(config, port, log, subscribe) { | ||
super(config, port, log, subscribe); | ||
this.currentValue = false; | ||
this.currentLevel = 0; | ||
this.service | ||
.getCharacteristic(Characteristic.On) | ||
@@ -112,3 +85,3 @@ .on("set", (value, callback) => { | ||
const device = this.config.devices[0]; | ||
log(`switching ${config.type.toLowerCase()} '${config.name}' (device = ${device}) ${value ? "on" : "off"}`); | ||
log(`switching ${config.type.toLowerCase()} '${config.name}' (device = ${device}) to ${value ? "on" : "off"}`); | ||
this.port.write(`10;${device};${value ? "ON" : "OFF"}\r\n`, callback); | ||
@@ -140,2 +113,19 @@ }) | ||
} | ||
onMessage(message) { | ||
switch (message.command) { | ||
case "ON": | ||
this.updateValue(true); | ||
break; | ||
case "OFF": | ||
this.updateValue(false); | ||
break; | ||
default: | ||
if (this.config.dimmable && message.command.startsWith("SET_LEVEL")) { | ||
const level = Number(message.command.substr(10)); | ||
if (!isNaN(level)) { | ||
this.updateLevel(level); | ||
} | ||
} | ||
} | ||
} | ||
updateValue(value) { | ||
@@ -155,3 +145,59 @@ this.log(`Updated state of ${this.config.type.toLowerCase()} '${this.config.name}' to ${value ? "on" : "off"}`); | ||
} | ||
const AccessoryTypes = { | ||
Lightbulb: RFLinkLightbulbAccessory, | ||
ContactSensor: RFLinkContactSensorAccessory, | ||
}; | ||
class RFLinkPlatform { | ||
constructor(log, config) { | ||
this.log = config.debug ? log : () => { }; | ||
this.config = config; | ||
this.subscribers = []; | ||
let device = config.device || "/dev/ttyACM0"; | ||
this.port = new SerialPort(device, { | ||
baudRate: 57600, | ||
}); | ||
this.port.on("error", (err) => { | ||
log(`error opening port: ${err.message}`); | ||
}); | ||
const parser = this.port.pipe(new Readline({ delimiter: "\r\n" })); | ||
parser.on("data", s => { | ||
this.log(`received ${s}`); | ||
const m = s.match(/^20;[^;]+;(?<proto>[^;]+);ID=(?<address>[^;]+);SWITCH=(?<button>[^;]+);CMD=(?<command>[^;]+);/); | ||
if (m) { | ||
const { proto, address, button, command } = m.groups; | ||
this.notify({ device: `${proto};${address};${button}`, command }); | ||
} | ||
}); | ||
} | ||
subscribe(callback) { | ||
this.subscribers.push(callback); | ||
} | ||
notify(message) { | ||
this.subscribers.forEach(callback => callback(message)); | ||
} | ||
accessories(callback) { | ||
return callback((this.config.accessories || []).map(acc => { | ||
if (!acc.type) { | ||
throw new Error("Type not provided"); | ||
} | ||
// Validate type. | ||
if (!AccessoryTypes[acc.type]) { | ||
throw Error(`Unknown device type '${acc.type}'`); | ||
} | ||
if (!acc.devices) { | ||
if (acc.device) { | ||
acc.devices = [acc.device]; | ||
delete acc.device; | ||
} | ||
else { | ||
throw new Error("No device provided"); | ||
} | ||
} | ||
acc.devices = acc.devices.map(device => device.replace(/_|:/g, ";")); | ||
this.log(`adding ${acc.type.toLowerCase()} '${acc.name}' (devices = ${acc.devices})`); | ||
return new AccessoryTypes[acc.type](acc, this.port, this.log, this.subscribe.bind(this)); | ||
})); | ||
} | ||
} | ||
module.exports = index; |
@@ -11,55 +11,4 @@ import SerialPort from 'serialport'; | ||
} | ||
class RFLinkPlatform { | ||
constructor(log, config) { | ||
this.log = config.debug ? log : () => { }; | ||
this.config = config; | ||
this.subscribers = []; | ||
let device = config.device || "/dev/ttyACM0"; | ||
this.port = new SerialPort(device, { | ||
baudRate: 57600, | ||
}); | ||
this.port.on("error", (err) => { | ||
log(`error opening port: ${err.message}`); | ||
}); | ||
const parser = this.port.pipe(new Readline({ delimiter: "\r\n" })); | ||
parser.on("data", s => { | ||
this.log(`received ${s}`); | ||
const m = s.match(/^20;[^;]+;(?<proto>[^;]+);ID=(?<address>[^;]+);SWITCH=(?<button>[^;]+);CMD=(?<command>[^;]+);/); | ||
if (m) { | ||
const { proto, address, button, command } = m.groups; | ||
this.notify({ device: `${proto};${address};${button}`, command }); | ||
} | ||
}); | ||
} | ||
subscribe(callback) { | ||
this.subscribers.push(callback); | ||
} | ||
notify(message) { | ||
this.subscribers.forEach(callback => callback(message)); | ||
} | ||
accessories(callback) { | ||
return callback((this.config.accessories || []).map(acc => { | ||
acc.type = acc.type || "Outlet"; | ||
// Validate type. | ||
if (!Service[acc.type]) { | ||
throw Error(`Unknown device type '${acc.type}'`); | ||
} | ||
if (!acc.devices) { | ||
if (acc.device) { | ||
acc.devices = [acc.device]; | ||
delete acc.device; | ||
} | ||
else { | ||
throw new Error("No device provided"); | ||
} | ||
} | ||
this.log(`adding ${acc.type.toLowerCase()} '${acc.name}' (devices = ${acc.devices})`); | ||
return new RFLinkAccessory(acc, this.port, this.log, this.subscribe.bind(this)); | ||
})); | ||
} | ||
} | ||
class RFLinkAccessory { | ||
class RFLinkBaseAccessory { | ||
constructor(config, port, log, subscribe) { | ||
this.currentValue = false; | ||
this.currentLevel = 0; | ||
this.name = config.name; | ||
@@ -80,20 +29,44 @@ this.config = config; | ||
if (config.devices.includes(message.device)) { | ||
switch (message.command) { | ||
case "ON": | ||
this.updateValue(true); | ||
break; | ||
case "OFF": | ||
this.updateValue(false); | ||
break; | ||
default: | ||
if (config.dimmable && message.command.startsWith("SET_LEVEL")) { | ||
const level = Number(message.command.substr(10)); | ||
if (!isNaN(level)) { | ||
this.updateLevel(level); | ||
} | ||
} | ||
} | ||
this.onMessage(message); | ||
} | ||
}); | ||
} | ||
onMessage(message) { } | ||
getServices() { | ||
return [this.informationService, this.service]; | ||
} | ||
} | ||
class RFLinkContactSensorAccessory extends RFLinkBaseAccessory { | ||
constructor(config, port, log, subscribe) { | ||
super(config, port, log, subscribe); | ||
this.currentValue = false; | ||
this.service | ||
.getCharacteristic(Characteristic.ContactSensorState) | ||
.on("get", (callback) => { | ||
callback(null, this.currentValue); | ||
}); | ||
} | ||
onMessage(message) { | ||
if (message.command === "ON") { | ||
this.updateValue(true); | ||
} | ||
else if (message.command === "OFF") { | ||
this.updateValue(false); | ||
} | ||
else { | ||
throw new Error("Unsupported command"); | ||
} | ||
} | ||
updateValue(value) { | ||
this.log(`Updated state of ${this.config.type.toLowerCase()} '${this.config.name}' to ${value ? "on" : "off"}`); | ||
this.currentValue = value; | ||
this.service.setCharacteristic(Characteristic.ContactSensorState, value); | ||
} | ||
} | ||
class RFLinkLightbulbAccessory extends RFLinkBaseAccessory { | ||
constructor(config, port, log, subscribe) { | ||
super(config, port, log, subscribe); | ||
this.currentValue = false; | ||
this.currentLevel = 0; | ||
this.service | ||
.getCharacteristic(Characteristic.On) | ||
@@ -108,3 +81,3 @@ .on("set", (value, callback) => { | ||
const device = this.config.devices[0]; | ||
log(`switching ${config.type.toLowerCase()} '${config.name}' (device = ${device}) ${value ? "on" : "off"}`); | ||
log(`switching ${config.type.toLowerCase()} '${config.name}' (device = ${device}) to ${value ? "on" : "off"}`); | ||
this.port.write(`10;${device};${value ? "ON" : "OFF"}\r\n`, callback); | ||
@@ -136,2 +109,19 @@ }) | ||
} | ||
onMessage(message) { | ||
switch (message.command) { | ||
case "ON": | ||
this.updateValue(true); | ||
break; | ||
case "OFF": | ||
this.updateValue(false); | ||
break; | ||
default: | ||
if (this.config.dimmable && message.command.startsWith("SET_LEVEL")) { | ||
const level = Number(message.command.substr(10)); | ||
if (!isNaN(level)) { | ||
this.updateLevel(level); | ||
} | ||
} | ||
} | ||
} | ||
updateValue(value) { | ||
@@ -151,3 +141,59 @@ this.log(`Updated state of ${this.config.type.toLowerCase()} '${this.config.name}' to ${value ? "on" : "off"}`); | ||
} | ||
const AccessoryTypes = { | ||
Lightbulb: RFLinkLightbulbAccessory, | ||
ContactSensor: RFLinkContactSensorAccessory, | ||
}; | ||
class RFLinkPlatform { | ||
constructor(log, config) { | ||
this.log = config.debug ? log : () => { }; | ||
this.config = config; | ||
this.subscribers = []; | ||
let device = config.device || "/dev/ttyACM0"; | ||
this.port = new SerialPort(device, { | ||
baudRate: 57600, | ||
}); | ||
this.port.on("error", (err) => { | ||
log(`error opening port: ${err.message}`); | ||
}); | ||
const parser = this.port.pipe(new Readline({ delimiter: "\r\n" })); | ||
parser.on("data", s => { | ||
this.log(`received ${s}`); | ||
const m = s.match(/^20;[^;]+;(?<proto>[^;]+);ID=(?<address>[^;]+);SWITCH=(?<button>[^;]+);CMD=(?<command>[^;]+);/); | ||
if (m) { | ||
const { proto, address, button, command } = m.groups; | ||
this.notify({ device: `${proto};${address};${button}`, command }); | ||
} | ||
}); | ||
} | ||
subscribe(callback) { | ||
this.subscribers.push(callback); | ||
} | ||
notify(message) { | ||
this.subscribers.forEach(callback => callback(message)); | ||
} | ||
accessories(callback) { | ||
return callback((this.config.accessories || []).map(acc => { | ||
if (!acc.type) { | ||
throw new Error("Type not provided"); | ||
} | ||
// Validate type. | ||
if (!AccessoryTypes[acc.type]) { | ||
throw Error(`Unknown device type '${acc.type}'`); | ||
} | ||
if (!acc.devices) { | ||
if (acc.device) { | ||
acc.devices = [acc.device]; | ||
delete acc.device; | ||
} | ||
else { | ||
throw new Error("No device provided"); | ||
} | ||
} | ||
acc.devices = acc.devices.map(device => device.replace(/_|:/g, ";")); | ||
this.log(`adding ${acc.type.toLowerCase()} '${acc.name}' (devices = ${acc.devices})`); | ||
return new AccessoryTypes[acc.type](acc, this.port, this.log, this.subscribe.bind(this)); | ||
})); | ||
} | ||
} | ||
export default index; |
{ | ||
"name": "homebridge-rflink", | ||
"version": "1.1.6", | ||
"version": "1.1.7", | ||
"description": "RFLink support for Homebridge: https://github.com/nfarina/homebridge", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21876
537