Skip to content

Commit

Permalink
Bug fixes and refactorings to support increasing the number of device…
Browse files Browse the repository at this point in the history
…/packet types

[BREAKING CHANGE] Change lighting1 and lighting5 events to return a numeric subtype, instead of a string
  • Loading branch information
Maxwell Hadley committed Jan 18, 2016
1 parent 21e19ee commit d7ae7f6
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 131 deletions.
4 changes: 3 additions & 1 deletion AUTHOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ Nicholas Humfrey [njh](https://github.com/njh)

Ian Gregory [iangregory](https://github.com/iangregory)

bwired-nl [bwired-nl][https://github.com/bwired-nl)
bwired-nl [bwired-nl](https://github.com/bwired-nl)

Max Hadley [maxwellhadley](https://github.com/maxwellhadley)
4 changes: 2 additions & 2 deletions lib/curtain1.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Curtain1.prototype._sendCommand = function(deviceId, command, callback) {
buffer = [0x07, defines.CURTAIN1, 0x00, cmdId, device.houseCode, device.unitCode, command, 0];

if (self.rfxcom.options.debug) {
console.log("Sending %j", self.rfxcom.dumpHex(buffer));
console.log("[rfxcom] on " + self.rfxcom.device + " - " + "Sent : %s", self.rfxcom.dumpHex(buffer));
}
self.rfxcom.serialport.write(buffer, function(err, response) {
if (typeof callback === "function") {
Expand Down Expand Up @@ -67,7 +67,7 @@ Curtain1.prototype.stop = function(deviceId, callback) {
};

/*
* Open deviceId.
* Programme deviceId.
*/
Curtain1.prototype.program = function(deviceId, callback) {
return this._sendCommand(deviceId, defines.CURTAIN_PROGRAM, callback);
Expand Down
65 changes: 35 additions & 30 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports.Lighting2 = require('./lighting2');
exports.Lighting5 = require('./lighting5');
exports.Curtain1 = require('./curtain1');

// Bitmap definitions for 'supported protocols' message
exports.protocols = {
BLYSS: {bit: 0x01, msg: 3},
RUBICSON: {bit: 0x02, msg: 3},
Expand All @@ -30,6 +31,39 @@ exports.protocols = {
VISONIC: {bit: 0x80, msg: 5}
};

// Establish reflection mapping (BiMap) for an Array, or throw an error if the array is not reflectable
var reflect = function(array) {
for (var i = 0; i < array.length; i++) {
if (isFinite(array[i]) || array.hasOwnProperty(array[i])) {
throw new Error("Array cannot be reflected: invalid entry array[" + i + "] = " + array[i]);
}
array[array[i]] = i;
}
return array;
};

// Protocol subtype definitions for each protocol
exports.lighting1 = reflect(['X10', 'ARC', 'ELRO', 'WAVEMAN', 'CHACON', 'IMPULS', 'RISING_SUN',
'PHILIPS_SBC', 'ENERGENIE_ENER010', 'ENERGENIE_5_GANG', 'COCO']);
exports.lighting1.transmitter = exports.Lighting1;
Object.freeze(exports.lighting1);

exports.lighting2 = reflect(['AC', 'HOMEEASY_EU', 'ANSLUT', 'KAMBROOK']);
exports.lighting2.transmitter = exports.Lighting2;
Object.freeze(exports.lighting2);

exports.lighting5 = reflect(['LIGHTWAVERF', 'EMW100', 'BBSB', 'MDREMOTE', 'CONRAD', 'LIVOLO', 'TRC02']);
exports.lighting5.transmitter = exports.Lighting5;
Object.freeze(exports.lighting5);

exports.curtain1 = reflect(['HARRISON']);
exports.curtain1.transmitter = exports.Curtain1;
Object.freeze(exports.curtain1);

exports.elec23 = reflect(['ELEC23_UNUSED', 'CM119_160', 'CM180']);
Object.freeze(exports.elec23);

// Various definitions
exports.security = {
NORMAL: 0,
NORMAL_DELAYED: 1,
Expand All @@ -49,41 +83,12 @@ exports.humidity = {
WET: 3
};

exports.lighting2 = {
AC: 0,
HOMEEASY_EU: 1,
ANSLUT: 2
};

exports.elec23 = {
CM119_160: 1,
CM180: 2
}

exports.lighting5 = {
LIGHTWAVERF: 0,
EMW100: 1,
BBSB: 2
};

exports.lighting1 = {
X10: 0,
ARC: 1,
ELRO: 2,
WAVEMAN: 3,
CHACON: 4,
IMPULS: 5,
RISING_SUN: 6,
PHILIPS_SBC: 7,
ENERGENIE: 8
}

exports.forecast = {
NO_FORECAST: 0,
SUNNY: 1,
PARTLY_CLOUDY: 2,
CLOUDY: 3,
RAIN: 4,
RAIN: 4
};

exports.rfxsensor = {
Expand Down
23 changes: 17 additions & 6 deletions lib/lighting1.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module.exports = Lighting1;
/*jshint -W104 */
const defines = require('./defines');
const defines = require('./defines'),
index = require('./index'),
util = require('util');

/*
* This is a class for controlling Lighting1 lights.
Expand All @@ -22,24 +24,33 @@ function Lighting1(rfxcom, subtype) {
* TODO: Validate houseCode/unitCode.
*/
Lighting1.prototype._splitDeviceId = function(deviceId) {
var parts = deviceId.split(""),
houseCode = parts[0].charCodeAt(0),
var parts, houseCode, unitCode;
if (util.isArray(deviceId)) {
parts = deviceId;
if (parts.length !== 2) {
throw new Error("Invalid deviceId format");
}
unitCode = parseInt(parts[1]);
} else {
parts = deviceId.split("");
unitCode = parseInt(parts.slice(1).join(""));
}
houseCode = parts[0].toUpperCase().charCodeAt(0);
return {
houseCode: houseCode,
unitCode: unitCode
};
};

Lighting1.prototype._sendCommand = function(deviceId, command, callback) {
Lighting1.prototype._sendCommand = function (deviceId, command, callback) {
var self = this,
device = self._splitDeviceId(deviceId),
cmdId = self.rfxcom.getCmdNumber(),
buffer = [0x07, defines.LIGHTING1, self.subtype, cmdId,
device.houseCode, device.unitCode, command, 0];

if (self.rfxcom.options.debug) {
console.log("Sending %j", self.rfxcom.dumpHex(buffer));
console.log("[rfxcom] on " + self.rfxcom.device + " - " + "Sent : %s", self.rfxcom.dumpHex(buffer));
}
self.rfxcom.serialport.write(buffer, function(err, response) {
if (typeof callback === "function") {
Expand All @@ -50,7 +61,7 @@ Lighting1.prototype._sendCommand = function(deviceId, command, callback) {
};

/*
* Switch on deviceId/unitCode
* 'Chime' deviceId/unitCode
*/
Lighting1.prototype.chime = function(deviceId, callback) {
return this._sendCommand(deviceId, 0x07, callback);
Expand Down
25 changes: 14 additions & 11 deletions lib/lighting2.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module.exports = Lighting2;
/*jshint -W104 */
const defines = require('./defines');
const defines = require('./defines'),
index = require('./index'),
util = require('util');

/*
* This is a class for controlling Lighting2 lights.
Expand All @@ -24,32 +26,33 @@ function Lighting2(rfxcom, subtype) {
* correct length.
*/
Lighting2.prototype._splitDeviceId = function(deviceId) {
var parts = deviceId.split("/"),
idBytes;
if (parts.length !== 2) {
throw new Error("Invalid deviceId format.");
var parts, idBytes;
if (util.isArray(deviceId)) {
parts = deviceId;
} else {
parts = deviceId.split("/");
}
idBytes = this.rfxcom.stringToBytes(parts[0]);
if (idBytes.length !== 4) {
if (parts.length !== 2) {
throw new Error("Invalid deviceId format.");
}
idBytes = this.rfxcom.stringToBytes(parts[0], 4);
return {
idBytes: idBytes,
unitCode: parts[1],
idBytes: idBytes.bytes,
unitCode: parts[1]
};
};

Lighting2.prototype._sendCommand = function(deviceId, command, level, callback) {
var self = this,
device = self._splitDeviceId(deviceId),
cmdId = self.rfxcom.getCmdNumber(),
level = level || 0xf,
level = (level === undefined) ? 0xf : level, // Now works when level == 0
buffer = [0x0b, defines.LIGHTING2, self.subtype, cmdId, device.idBytes[0],
device.idBytes[1], device.idBytes[2], device.idBytes[3],
device.unitCode, command, level, 0];

if (self.rfxcom.options.debug) {
console.log("Sending %j", self.rfxcom.dumpHex(buffer));
console.log("[rfxcom] on " + self.rfxcom.device + " - " + "Sent : %s", self.rfxcom.dumpHex(buffer));
}
self.rfxcom.serialport.write(buffer, function(err, response) {
if (typeof callback === "function") {
Expand Down
18 changes: 13 additions & 5 deletions lib/lighting5.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module.exports = Lighting5;
/*jshint -W104 */
const defines = require('./defines');
const defines = require('./defines'),
index = require('./index'),
util = require('util');

/*
* This is a class for controlling LightwaveRF lights.
Expand All @@ -24,13 +26,19 @@ function Lighting5(rfxcom, subtype) {
* Throws an Error if the format is invalid.
*/
Lighting5.prototype._splitDeviceId = function(deviceId) {
var parts = deviceId.split("/");
var parts, id;
if (util.isArray(deviceId)) {
parts = deviceId;
} else {
parts = deviceId.split("/");
}
if (parts.length !== 2) {
throw new Error("Invalid deviceId format.");
}
id = this.rfxcom.stringToBytes(parts[0], 3);
return {
idBytes: this.rfxcom.stringToBytes(parts[0]),
unitCode: parts[1],
idBytes: id.bytes,
unitCode: parts[1]
};
};

Expand All @@ -39,7 +47,7 @@ Lighting5.prototype._sendCommand = function(deviceId, command, level, callback)
var self = this,
device = self._splitDeviceId(deviceId),
cmdId = self.rfxcom.getCmdNumber(),
level = level || 0x1f,
level = (level === undefined) ? 0x1f : level, // Now works when level == 0
buffer = [0x0a, defines.LIGHTING5, self.subtype, cmdId,
device.idBytes[0], device.idBytes[1], device.idBytes[2],
device.unitCode, command, level, 0];
Expand Down
Loading

0 comments on commit d7ae7f6

Please sign in to comment.