Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OOPS - forget this, Kevin: Zone Change handling #8

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 4 additions & 22 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ var ElkConnection = function(opts) {
if(!that.useSecure) that.emit('connect');

// assuming the above passes, we parse the elk message and emit
var msg = parser.parseMessage(data);
var msg = parser.parseMessage(data)
msg.time = new Date();
msg.host = that._connection.address().address;
msg.port = that.port;
msg.remotePort = that._connection.address().port;

that.emit('any', msg);
that.emit(msg.commandCode, msg);

});

// error event handler
Expand Down Expand Up @@ -168,26 +170,6 @@ ElkConnection.prototype.speak = function(message) {
}
}

ElkConnection.prototype.zoneDefinitionRequest = function(callback) {
if(callback && typeof callback === 'function') {
callback = safereturn(callback, this.responseTimeout);
this.once('ZD', function(data){
callback(null, data);
});
}
this._connection.write(messaging.writeAscii('zd'));
}

ElkConnection.prototype.textDescriptionRequest = function(type, address, callback) {
if(callback && typeof callback === 'function') {
callback = safereturn(callback, this.responseTimeout);
this.once('SD', function(data){
callback(null, data);
});
}
this._connection.write(messaging.writeTextDescriptionsMessage('sd', type, address));
}

/*********************************/
/* exports */
/*********************************/
Expand All @@ -196,4 +178,4 @@ module.exports.createConnection = function(opts) {
return new ElkConnection(opts);
}

module.exports.version = '0.0.2';
module.exports.version = '0.0.2';
8 changes: 0 additions & 8 deletions lib/messaging.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@ var writeArmingMessage = function(cmd, opts) {
return msg;
}

var writeTextDescriptionsMessage = function(cmd, type, address) {
type = ('00' + type).substr(-2);
address = ('000' + address).substr(-3);
var msg = writeAscii(cmd + type.toString() + address.toString());
return msg;
}

var writeAscii = function(command) {
var ascii;
var len;
Expand Down Expand Up @@ -88,6 +81,5 @@ var calcChecksum = function(string) {

module.exports.getWordCommands = getWordCommands;
module.exports.writeArmingMessage = writeArmingMessage;
module.exports.writeTextDescriptionsMessage = writeTextDescriptionsMessage;
module.exports.writeAscii = writeAscii;
module.exports.calcChecksum = calcChecksum;
94 changes: 9 additions & 85 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,9 @@ var parseMessage = function(msg) {
msgData = parseArmingStatusData(msgData);
break;
case 'ZC':
msgData = parseZoneChangeData(msgData);
msgData = parseZoneChange(msgData);
break;
case 'CC':
msgData = parseControlOutputData(msgData);
break;
case 'UA':
msgData = parseRequestValidUserCodeData(msgData);
break;
case 'PC':
msgData = parsePowerLineCarrierData(msgData);
break;
case 'SD':
msgData = parseTextDescriptionsData(msgData);
}
}
return msgData;
}

Expand Down Expand Up @@ -89,77 +78,12 @@ var parseArmingStatusData = function(msgData) {
return msgData;
}

var parseZoneChangeData = function(msgData) {
msgData.data.zoneNumber = parseInt(msgData.dataRaw.substring(0,3));
msgData.data.zoneStatus = msgData.dataRaw.substring(3,4);
if(protocol.zoneStatuses[msgData.data.zoneStatus.toString()]) {
msgData.data.zoneStatus = protocol.zoneStatuses[msgData.data.zoneStatus.toString()];
} else {
msgData.data.zoneStatus = 'Unknown zone status message';
}

return msgData;
}

var parseControlOutputData = function(msgData) {
msgData.data.outputNumber = parseInt(msgData.dataRaw.substring(0,3));
msgData.data.outputState = parseInt(msgData.dataRaw.substring(3,4));
if(protocol.outputStates[msgData.data.outputState.toString()]) {
msgData.data.outputState = protocol.outputStates[msgData.data.outputState.toString()];
} else {
msgData.data.outputState = 'Unknown output state message';
}

return msgData;
}

var parseRequestValidUserCodeData = function(msgData) {
msgData.data.userCode = msgData.dataRaw.substring(0,6);
msgData.data.userCodeDigitCount = parseInt(msgData.dataRaw.substring(16,17));
//handle leading zeros in user code
msgData.data.userCode = ('000000' + msgData.data.userCode).substr(-msgData.data.userCodeDigitCount);

msgData.data.userCodeValidAreas = new Array();
var validAreas = msgData.dataRaw.substring(6,8);
//convert to binary with leading zeros
validAreas = ('00000000' + parseInt(validAreas, 16).toString(2)).substr(-8);
//convert to areas
for(var i=7; i>=0; i--) {
if(validAreas[i] == 1)
msgData.data.userCodeValidAreas.push('area' + (8-i));
}

msgData.data.userCodeType = msgData.dataRaw.substring(17,18);
if(protocol.userCodeTypes[msgData.data.userCodeType.toString()]) {
msgData.data.userCodeType = protocol.userCodeTypes[msgData.data.userCodeType.toString()];
} else {
msgData.data.temperatureMode = 'Unknown user code type message';
}

msgData.data.temperatureMode = msgData.dataRaw.substring(18,19);
if(protocol.temperatureModes[msgData.data.temperatureMode.toString()]) {
msgData.data.temperatureMode = protocol.temperatureModes[msgData.data.temperatureMode.toString()];
} else {
msgData.data.temperatureMode = 'Unknown temperature mode message';
}

return msgData;
}

var parsePowerLineCarrierData = function(msgData) {
msgData.data.houseCode = msgData.dataRaw.substring(0,1);
msgData.data.unitCode = parseInt(msgData.dataRaw.substring(1,3));
msgData.data.lightLevel = parseInt(msgData.dataRaw.substring(3,5));
return msgData;
}

var parseTextDescriptionsData = function(msgData) {
msgData.data.type = parseInt(msgData.dataRaw.substring(0,2));
msgData.data.typeName = protocol.textDescriptionsTypes[msgData.data.type];
msgData.data.address = parseInt(msgData.dataRaw.substring(2,5));
msgData.data.text = msgData.dataRaw.substring(5,21).trim();
return msgData;
var parseZoneChange = function(msgData){

var theState = msgData.dataRaw.substring(3,4);
msgData.data.zone = msgData.dataRaw.substring(0,3);
msgData.data.zoneStatus = protocol.zoneStates[msgData.dataRaw.substring(3,4)];
return msgData;
}


module.exports.parseMessage = parseMessage;
module.exports.parseMessage = parseMessage;
81 changes: 21 additions & 60 deletions lib/protocol.js
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,25 @@ var events = {
//7001 – 7208 = Output status, 1 = On
}

var zoneStates = {
'0': 'Unconfigured',
'1': 'Normal Open',
'2': 'Normal EOL',
'3': 'Normal Short',
'4': 'not used',
'5': 'Trouble Open',
'6': 'Trouble EOL',
'7': 'Trouble Short',
'8': 'not used',
'9': 'Violated Open',
'A': 'Violated EOL',
'B': 'Violated Short',
'C': 'Bypassed Open',
'D': 'Bypassed EOL',
'F': 'Bypassed Short'
}


var armStatuses = [
'Disarmed', 'Armed Away','Armed Stay','Armed Stay Instant',
'Armed to Night','Armed to Night Instant','Armed to Vacation'
Expand Down Expand Up @@ -1118,70 +1137,12 @@ var alarmStates = {
'B': 'Verify Fire'
}

var zoneStatuses = {
'0': 'Normal: Unconfigured',
'1': 'Normal: Open',
'2': 'Normal: EOL',
'3': 'Normal: Short',
'5': 'Trouble: Open',
'6': 'Trouble: EOL',
'7': 'Trouble: Short',
'9': 'Violated: Open',
'A': 'Violated: EOL',
'B': 'Violated: Short',
'D': 'Bypassed: Open',
'E': 'Bypassed: EOL',
'F': 'Bypassed: Short'
}

var outputStates = {
'0': 'Off',
'1': 'On'
}

var temperatureModes = {
'F': 'Fahrenheit',
'C': 'Celcius'
}

var userCodeTypes = {
'1': 'User',
'2': 'Master',
'3': 'Installer',
'4': 'ELKRP'
}

var textDescriptionsTypes = {
'0': 'Zone Name',
'1': 'Area Name',
'2': 'User Name',
'3': 'Keypad Name',
'4': 'Output Name',
'5': 'Task Name',
'6': 'Telephone Name',
'7': 'Light Name',
'8': 'Alarm Duration Name',
'9': 'Custom Settings',
'10': 'Counters Names',
'11': 'Thermostat Names',
'12': 'Function Key 1 Name',
'13': 'Function Key 2 Name',
'14': 'Function Key 3 Name',
'15': 'Function Key 4 Name',
'16': 'Function Key 5 Name',
'17': 'Function Key 6 Name',
'18': 'Audio Zone Name',
'19': 'Audio Source Name'
}

module.exports.commands = commands;
module.exports.words = words;
module.exports.events = events;
module.exports.zoneStates = zoneStates;
module.exports.armStatuses = armStatuses;
module.exports.armUpStates = armUpStates;
module.exports.alarmStates = alarmStates;
module.exports.zoneStatuses = zoneStatuses;
module.exports.outputStates = outputStates;
module.exports.temperatureModes = temperatureModes;
module.exports.userCodeTypes = userCodeTypes;
module.exports.textDescriptionsTypes = textDescriptionsTypes;
module.exports.alarmStates = alarmStates;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "elkington",
"description": "A node.js module for interfacing with the Elk M1 Gold automation controller",
"keywords": [ "elk", "home", "automation", "security", "hardware", "m1", "m1xep", "elkm1", "home"],
"version": "0.1.0",
"version": "0.0.2",
"repository": {
"type": "git",
"url": "git://github.com/kevinohara80/elkington.git"
Expand Down
7 changes: 0 additions & 7 deletions test/messaging.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,4 @@ describe('messaging', function(){

});

describe('#writeTextDescriptionsMessage', function(){
it('should return the right message formated for type and zone', function(done) {
messaging.writeTextDescriptionsMessage('sd', 1, 1).should.have.length(15);
done();
});

});
});
69 changes: 2 additions & 67 deletions test/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ var tests = [
{ ascii: '16XK5435226130412110006E', message: 'Request Ethernet test' },
{ ascii: '1EAS100000004000000030000000000E', message: 'Arming status report data' },
{ ascii: '0AZC006200CA', message: 'Zone change update' },
{ ascii: '16AR12345611340100110085', message: 'Alarm Reporting to Ethernet' },
{ ascii: '0AZC031900C5', message: 'Zone change update' },
{ ascii: '0ACC063000E0', message: 'Control output change update' },
{ ascii: '19UA000123C33036BC9A41F009F', message: 'User code areas report data' },
{ ascii: '0BPCA08010091', message: 'PLC change update' },
{ ascii: '1BSD01001Miller Res 0054', message: 'Text string description report data'}
{ ascii: '16AR12345611340100110085', message: 'Alarm Reporting to Ethernet' }
];

describe('parser', function(){
Expand Down Expand Up @@ -63,66 +58,6 @@ describe('parser', function(){
done();
});

it('should parse \'Zone change update\' message ok', function(done){
var results = parser.parseMessage(tests[4].ascii);
results.message.should.equal(tests[4].message);
results.length.should.equal(10);
results.dataRaw.should.equal('031900');
results.data.zoneNumber.should.equal(31);
results.data.zoneStatus.should.equal('Violated: Open');
done();
});

it('should parse \'Control output change update\' message ok', function(done){
var results = parser.parseMessage(tests[5].ascii);
results.message.should.equal(tests[5].message);
results.length.should.equal(10);
results.dataRaw.should.equal('063000');
results.data.outputNumber.should.equal(63);
results.data.outputState.should.equal('Off');
done();
});

it('should parse \'User code areas report data\' message ok', function(done){
var results = parser.parseMessage(tests[6].ascii);
results.message.should.equal(tests[6].message);
results.length.should.equal(25);
results.dataRaw.should.equal('000123C33036BC9A41F00');
results.data.userCode.should.equal('0123');
results.data.userCodeValidAreas.length.should.equal(4);
results.data.userCodeValidAreas[0].should.equal('area1');
results.data.userCodeValidAreas[1].should.equal('area2');
results.data.userCodeValidAreas[2].should.equal('area7');
results.data.userCodeValidAreas[3].should.equal('area8');
results.data.userCodeDigitCount.should.equal(4);
results.data.userCodeType.should.equal('User');
results.data.temperatureMode.should.equal('Fahrenheit');
done();
});

it('should parse \'PLC change update\' message ok', function(done){
var results = parser.parseMessage(tests[7].ascii);
results.message.should.equal(tests[7].message);
results.length.should.equal(11);
results.dataRaw.should.equal('A080100');
results.data.houseCode.should.equal('A');
results.data.unitCode.should.equal(8);
results.data.lightLevel.should.equal(1);
done();
});

it('should parse \'Text string description report data\' message ok', function(done){
var results = parser.parseMessage(tests[8].ascii);
results.message.should.equal(tests[8].message);
results.length.should.equal(27);
results.dataRaw.should.equal('01001Miller Res 00');
results.data.type.should.equal(1);
results.data.typeName.should.equal('Area Name');
results.data.address.should.equal(1);
results.data.text.should.equal('Miller Res');
done();
});

});

});
});