Node JS controller
initial commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
:100000000C9461000C947E000C947E000C947E0095
|
||||
:100010000C947E000C947E000C947E000C947E0068
|
||||
:100020000C947E000C947E000C947E000C947E0058
|
||||
:100030000C947E000C947E000C947E000C947E0048
|
||||
:100040000C949A000C947E000C947E000C947E001C
|
||||
:100050000C947E000C947E000C947E000C947E0028
|
||||
:100060000C947E000C947E00000000002400270009
|
||||
:100070002A0000000000250028002B0000000000DE
|
||||
:1000800023002600290004040404040404040202DA
|
||||
:100090000202020203030303030301020408102007
|
||||
:1000A0004080010204081020010204081020000012
|
||||
:1000B0000007000201000003040600000000000029
|
||||
:1000C000000011241FBECFEFD8E0DEBFCDBF11E08E
|
||||
:1000D000A0E0B1E0E4E5F4E002C005900D92A030AC
|
||||
:1000E000B107D9F711E0A0E0B1E001C01D92A9303D
|
||||
:1000F000B107E1F70E9418020C9428020C9400004A
|
||||
:1001000087E061E00E94C4016AEF70E080E090E067
|
||||
:100110000E941D0187E060E00E94C4016AEF70E068
|
||||
:1001200080E090E00E941D01089587E061E00E9458
|
||||
:10013000850108951F920F920FB60F9211242F93ED
|
||||
:100140003F938F939F93AF93BF93809104019091BE
|
||||
:100150000501A0910601B0910701309108010196B7
|
||||
:10016000A11DB11D232F2D5F2D3720F02D57019696
|
||||
:10017000A11DB11D209308018093040190930501F6
|
||||
:10018000A0930601B09307018091000190910101B5
|
||||
:10019000A0910201B09103010196A11DB11D8093B0
|
||||
:1001A000000190930101A0930201B0930301BF915C
|
||||
:1001B000AF919F918F913F912F910F900FBE0F9014
|
||||
:1001C0001F901895789484B5826084BD84B5816051
|
||||
:1001D00084BD85B5826085BD85B5816085BDEEE64F
|
||||
:1001E000F0E0808181608083E1E8F0E0108280812E
|
||||
:1001F00082608083808181608083E0E8F0E080819C
|
||||
:1002000081608083E1EBF0E0808184608083E0EBBB
|
||||
:10021000F0E0808181608083EAE7F0E080818460A3
|
||||
:1002200080838081826080838081816080838081FF
|
||||
:10023000806880831092C1000895EF92FF920F931F
|
||||
:100240001F93CF93DF937B018C013FB7F89480918C
|
||||
:10025000000190910101A0910201B091030126B526
|
||||
:10026000A89B05C02F3F19F00196A11DB11D3FBFEE
|
||||
:10027000BA2FA92F982F8827820F911DA11DB11D7C
|
||||
:1002800052E0880F991FAA1FBB1F5A95D1F7EC01A6
|
||||
:1002900030C00E9427023FB7F894809100019091EE
|
||||
:1002A0000101A0910201B091030126B5A89B05C0F0
|
||||
:1002B0002F3F19F00196A11DB11D3FBFBA2FA92FE5
|
||||
:1002C000982F8827820F911DA11DB11D32E0880F44
|
||||
:1002D000991FAA1FBB1F3A95D1F78C1B9D0B885EF7
|
||||
:1002E0009340B8F20894E108F10801091109C851D6
|
||||
:1002F000DC4FE114F1040105110559F6DF91CF91AE
|
||||
:100300001F910F91FF90EF900895CF93DF93482FA7
|
||||
:1003100050E0CA0186569F4FFC0134914A575F4F07
|
||||
:10032000FA018491882369F190E0880F991FFC01FC
|
||||
:10033000E859FF4FA591B491FC01EE58FF4FC591CC
|
||||
:10034000D491662351F42FB7F8948C91932F909504
|
||||
:1003500089238C93888189230BC0623061F42FB785
|
||||
:10036000F8948C91932F909589238C938881832B7B
|
||||
:1003700088832FBF06C09FB7F8948C91832B8C93F2
|
||||
:100380009FBFDF91CF910895482F50E0CA01825559
|
||||
:100390009F4FFC012491CA0186569F4FFC01949106
|
||||
:1003A0004A575F4FFA013491332309F440C02223A6
|
||||
:1003B00051F1233071F0243028F42130A1F02230A3
|
||||
:1003C00011F514C02630B1F02730C1F02430D9F433
|
||||
:1003D00004C0809180008F7703C0809180008F7D62
|
||||
:1003E0008093800010C084B58F7702C084B58F7D64
|
||||
:1003F00084BD09C08091B0008F7703C08091B000A8
|
||||
:100400008F7D8093B000E32FF0E0EE0FFF1FEE58DA
|
||||
:10041000FF4FA591B4912FB7F894662321F48C91E6
|
||||
:100420009095892302C08C91892B8C932FBF0895BE
|
||||
:10043000CF93DF930E94E2000E949500C0E0D0E0DD
|
||||
:100440000E9480002097E1F30E940000F9CF0895F8
|
||||
:04045000F894FFCF4E
|
||||
:00000001FF
|
||||
@@ -0,0 +1,71 @@
|
||||
:100000000C9461000C947E000C947E000C947E0095
|
||||
:100010000C947E000C947E000C947E000C947E0068
|
||||
:100020000C947E000C947E000C947E000C947E0058
|
||||
:100030000C947E000C947E000C947E000C947E0048
|
||||
:100040000C949A000C947E000C947E000C947E001C
|
||||
:100050000C947E000C947E000C947E000C947E0028
|
||||
:100060000C947E000C947E00000000002400270009
|
||||
:100070002A0000000000250028002B0000000000DE
|
||||
:1000800023002600290004040404040404040202DA
|
||||
:100090000202020203030303030301020408102007
|
||||
:1000A0004080010204081020010204081020000012
|
||||
:1000B0000007000201000003040600000000000029
|
||||
:1000C000000011241FBECFEFD8E0DEBFCDBF11E08E
|
||||
:1000D000A0E0B1E0E4E5F4E002C005900D92A030AC
|
||||
:1000E000B107D9F711E0A0E0B1E001C01D92A9303D
|
||||
:1000F000B107E1F70E9418020C9428020C9400004A
|
||||
:1001000086E061E00E94C4016AEF70E080E090E068
|
||||
:100110000E941D0186E060E00E94C4016AEF70E069
|
||||
:1001200080E090E00E941D01089586E061E00E9459
|
||||
:10013000850108951F920F920FB60F9211242F93ED
|
||||
:100140003F938F939F93AF93BF93809104019091BE
|
||||
:100150000501A0910601B0910701309108010196B7
|
||||
:10016000A11DB11D232F2D5F2D3720F02D57019696
|
||||
:10017000A11DB11D209308018093040190930501F6
|
||||
:10018000A0930601B09307018091000190910101B5
|
||||
:10019000A0910201B09103010196A11DB11D8093B0
|
||||
:1001A000000190930101A0930201B0930301BF915C
|
||||
:1001B000AF919F918F913F912F910F900FBE0F9014
|
||||
:1001C0001F901895789484B5826084BD84B5816051
|
||||
:1001D00084BD85B5826085BD85B5816085BDEEE64F
|
||||
:1001E000F0E0808181608083E1E8F0E0108280812E
|
||||
:1001F00082608083808181608083E0E8F0E080819C
|
||||
:1002000081608083E1EBF0E0808184608083E0EBBB
|
||||
:10021000F0E0808181608083EAE7F0E080818460A3
|
||||
:1002200080838081826080838081816080838081FF
|
||||
:10023000806880831092C1000895EF92FF920F931F
|
||||
:100240001F93CF93DF937B018C013FB7F89480918C
|
||||
:10025000000190910101A0910201B091030126B526
|
||||
:10026000A89B05C02F3F19F00196A11DB11D3FBFEE
|
||||
:10027000BA2FA92F982F8827820F911DA11DB11D7C
|
||||
:1002800052E0880F991FAA1FBB1F5A95D1F7EC01A6
|
||||
:1002900030C00E9427023FB7F894809100019091EE
|
||||
:1002A0000101A0910201B091030126B5A89B05C0F0
|
||||
:1002B0002F3F19F00196A11DB11D3FBFBA2FA92FE5
|
||||
:1002C000982F8827820F911DA11DB11D32E0880F44
|
||||
:1002D000991FAA1FBB1F3A95D1F78C1B9D0B885EF7
|
||||
:1002E0009340B8F20894E108F10801091109C851D6
|
||||
:1002F000DC4FE114F1040105110559F6DF91CF91AE
|
||||
:100300001F910F91FF90EF900895CF93DF93482FA7
|
||||
:1003100050E0CA0186569F4FFC0134914A575F4F07
|
||||
:10032000FA018491882369F190E0880F991FFC01FC
|
||||
:10033000E859FF4FA591B491FC01EE58FF4FC591CC
|
||||
:10034000D491662351F42FB7F8948C91932F909504
|
||||
:1003500089238C93888189230BC0623061F42FB785
|
||||
:10036000F8948C91932F909589238C938881832B7B
|
||||
:1003700088832FBF06C09FB7F8948C91832B8C93F2
|
||||
:100380009FBFDF91CF910895482F50E0CA01825559
|
||||
:100390009F4FFC012491CA0186569F4FFC01949106
|
||||
:1003A0004A575F4FFA013491332309F440C02223A6
|
||||
:1003B00051F1233071F0243028F42130A1F02230A3
|
||||
:1003C00011F514C02630B1F02730C1F02430D9F433
|
||||
:1003D00004C0809180008F7703C0809180008F7D62
|
||||
:1003E0008093800010C084B58F7702C084B58F7D64
|
||||
:1003F00084BD09C08091B0008F7703C08091B000A8
|
||||
:100400008F7D8093B000E32FF0E0EE0FFF1FEE58DA
|
||||
:10041000FF4FA591B4912FB7F894662321F48C91E6
|
||||
:100420009095892302C08C91892B8C932FBF0895BE
|
||||
:10043000CF93DF930E94E2000E949500C0E0D0E0DD
|
||||
:100440000E9480002097E1F30E940000F9CF0895F8
|
||||
:04045000F894FFCF4E
|
||||
:00000001FF
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,617 @@
|
||||
const gwType = 'Ethernet';
|
||||
const gwAddress = '10.0.1.99';
|
||||
const gwPort = 9999;
|
||||
|
||||
//const gwType = 'Serial';
|
||||
//const gwPort = 'COM4';
|
||||
//const gwBaud = 115200;
|
||||
|
||||
const dbAddress = '127.0.0.1';
|
||||
const dbPort = 27017;
|
||||
const dbName = 'MySensorsDb';
|
||||
|
||||
const fwHexFiles = [ 'BlinkRed.hex', 'BlinkGreen.hex', 'DallasTemperatureSensor.cpp.hex' ];
|
||||
const fwDefaultType = 2; // index of hex file from array above
|
||||
|
||||
const FIRMWARE_BLOCK_SIZE = 16;
|
||||
const BROADCAST_ADDRESS = 255;
|
||||
const NODE_SENSOR_ID = 255;
|
||||
|
||||
const C_PRESENTATION = 0;
|
||||
const C_SET = 1;
|
||||
const C_REQ = 2;
|
||||
const C_INTERNAL = 3;
|
||||
const C_STREAM = 4;
|
||||
|
||||
const V_TEMP = 0;
|
||||
const V_HUM = 1;
|
||||
const V_LIGHT = 2;
|
||||
const V_DIMMER = 3;
|
||||
const V_PRESSURE = 4;
|
||||
const V_FORECAST = 5;
|
||||
const V_RAIN = 6;
|
||||
const V_RAINRATE = 7;
|
||||
const V_WIND = 8;
|
||||
const V_GUST = 9;
|
||||
const V_DIRECTION = 10;
|
||||
const V_UV = 11;
|
||||
const V_WEIGHT = 12;
|
||||
const V_DISTANCE = 13;
|
||||
const V_IMPEDANCE = 14;
|
||||
const V_ARMED = 15;
|
||||
const V_TRIPPED = 16;
|
||||
const V_WATT = 17;
|
||||
const V_KWH = 18;
|
||||
const V_SCENE_ON = 19;
|
||||
const V_SCENE_OFF = 20;
|
||||
const V_HEATER = 21;
|
||||
const V_HEATER_SW = 22;
|
||||
const V_LIGHT_LEVEL = 23;
|
||||
const V_VAR1 = 24;
|
||||
const V_VAR2 = 25;
|
||||
const V_VAR3 = 26;
|
||||
const V_VAR4 = 27;
|
||||
const V_VAR5 = 28;
|
||||
const V_UP = 29;
|
||||
const V_DOWN = 30;
|
||||
const V_STOP = 31;
|
||||
const V_IR_SEND = 32;
|
||||
const V_IR_RECEIVE = 33;
|
||||
const V_FLOW = 34;
|
||||
const V_VOLUME = 35;
|
||||
const V_LOCK_STATUS = 36;
|
||||
|
||||
const I_BATTERY_LEVEL = 0;
|
||||
const I_TIME = 1;
|
||||
const I_VERSION = 2;
|
||||
const I_ID_REQUEST = 3;
|
||||
const I_ID_RESPONSE = 4;
|
||||
const I_INCLUSION_MODE = 5;
|
||||
const I_CONFIG = 6;
|
||||
const I_PING = 7;
|
||||
const I_PING_ACK = 8;
|
||||
const I_LOG_MESSAGE = 9;
|
||||
const I_CHILDREN = 10;
|
||||
const I_SKETCH_NAME = 11;
|
||||
const I_SKETCH_VERSION = 12;
|
||||
const I_REBOOT = 13;
|
||||
|
||||
const S_DOOR = 0;
|
||||
const S_MOTION = 1;
|
||||
const S_SMOKE = 2;
|
||||
const S_LIGHT = 3;
|
||||
const S_DIMMER = 4;
|
||||
const S_COVER = 5;
|
||||
const S_TEMP = 6;
|
||||
const S_HUM = 7;
|
||||
const S_BARO = 8;
|
||||
const S_WIND = 9;
|
||||
const S_RAIN = 10;
|
||||
const S_UV = 11;
|
||||
const S_WEIGHT = 12;
|
||||
const S_POWER = 13;
|
||||
const S_HEATER = 14;
|
||||
const S_DISTANCE = 15;
|
||||
const S_LIGHT_LEVEL = 16;
|
||||
const S_ARDUINO_NODE = 17;
|
||||
const S_ARDUINO_REPEATER_NODE = 18;
|
||||
const S_LOCK = 19;
|
||||
const S_IR = 20;
|
||||
const S_WATER = 21;
|
||||
const S_AIR_QUALITY = 22;
|
||||
|
||||
const ST_FIRMWARE_CONFIG_REQUEST = 0;
|
||||
const ST_FIRMWARE_CONFIG_RESPONSE = 1;
|
||||
const ST_FIRMWARE_REQUEST = 2;
|
||||
const ST_FIRMWARE_RESPONSE = 3;
|
||||
const ST_SOUND = 4;
|
||||
const ST_IMAGE = 5;
|
||||
|
||||
const P_STRING = 0;
|
||||
const P_BYTE = 1;
|
||||
const P_INT16 = 2;
|
||||
const P_UINT16 = 3;
|
||||
const P_LONG32 = 4;
|
||||
const P_ULONG32 = 5;
|
||||
const P_CUSTOM = 6;
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
function crcUpdate(old, value) {
|
||||
var c = old ^ value;
|
||||
for (var i = 0; i < 8; ++i) {
|
||||
if ((c & 1) > 0)
|
||||
c = ((c >> 1) ^ 0xA001);
|
||||
else
|
||||
c = (c >> 1);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function pullWord(arr, pos) {
|
||||
return arr[pos] + 256 * arr[pos + 1];
|
||||
}
|
||||
|
||||
function pushWord(arr, val) {
|
||||
arr.push(val & 0x00FF);
|
||||
arr.push((val >> 8) & 0x00FF);
|
||||
}
|
||||
|
||||
function pushDWord(arr, val) {
|
||||
arr.push(val & 0x000000FF);
|
||||
arr.push((val >> 8) & 0x000000FF);
|
||||
arr.push((val >> 16) & 0x000000FF);
|
||||
arr.push((val >> 24) & 0x000000FF);
|
||||
}
|
||||
|
||||
function loadFirmware(fwtype, fwversion, filename, db) {
|
||||
console.log("loading firmware: " + filename);
|
||||
fwdata = [];
|
||||
var start = 0;
|
||||
var end = 0;
|
||||
var pos = 0;
|
||||
var hex = fs.readFileSync(filename).toString().split("\n");
|
||||
for(l in hex) {
|
||||
line = hex[l].trim();
|
||||
if (line.length > 0) {
|
||||
while (line.substring(0, 1) != ":")
|
||||
line = line.substring(1);
|
||||
var reclen = parseInt(line.substring(1, 3), 16);
|
||||
var offset = parseInt(line.substring(3, 7), 16);
|
||||
var rectype = parseInt(line.substring(7, 9), 16);
|
||||
var data = line.substring(9, 9 + 2 * reclen);
|
||||
var chksum = parseInt(line.substring(9 + (2 * reclen), 9 + (2 * reclen) + 2), 16);
|
||||
if (rectype == 0) {
|
||||
if ((start == 0) && (end == 0)) {
|
||||
if (offset % 128 > 0)
|
||||
throw new Error("error loading hex file - offset can't be devided by 128");
|
||||
start = offset;
|
||||
end = offset;
|
||||
}
|
||||
if (offset < end)
|
||||
throw new Error("error loading hex file - offset lower than end");
|
||||
while (offset > end) {
|
||||
fwdata.push(255);
|
||||
pos++;
|
||||
end++;
|
||||
}
|
||||
for (var i = 0; i < reclen; i++) {
|
||||
fwdata.push(parseInt(data.substring(i * 2, (i * 2) + 2), 16));
|
||||
pos++;
|
||||
}
|
||||
end += reclen;
|
||||
}
|
||||
}
|
||||
}
|
||||
var pad = end % 128; // ATMega328 has 64 words per page / 128 bytes per page
|
||||
for (var i = 0; i < 128 - pad; i++) {
|
||||
fwdata.push(255);
|
||||
pos++;
|
||||
end++;
|
||||
}
|
||||
var blocks = (end - start) / FIRMWARE_BLOCK_SIZE;
|
||||
var crc = 0xFFFF;
|
||||
for (var i = 0; i < blocks * FIRMWARE_BLOCK_SIZE; ++i) {
|
||||
var v = crc;
|
||||
crc = crcUpdate(crc, fwdata[i]);
|
||||
}
|
||||
db.collection('firmware', function(err, c) {
|
||||
c.update({
|
||||
'type': fwtype,
|
||||
'version': fwversion
|
||||
}, {
|
||||
$set: {
|
||||
'filename': filename,
|
||||
'blocks': blocks,
|
||||
'crc': crc,
|
||||
'data': fwdata
|
||||
}
|
||||
}, {
|
||||
upsert: true
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error writing firmware to database');
|
||||
});
|
||||
});
|
||||
console.log("loading firmware done. blocks: " + blocks + " / crc: " + crc);
|
||||
}
|
||||
|
||||
/*
|
||||
function decode(msg) {
|
||||
var msgs = msg.toString().split(";");
|
||||
rsender = +msgs[0];
|
||||
rsensor = +msgs[1];
|
||||
rcommand = +msgs[2];
|
||||
rtype = +msgs[3];
|
||||
var pl = msgs[4].trim();
|
||||
rpayload = [];
|
||||
for (var i = 0; i < pl.length; i+=2) {
|
||||
var b = parseInt(pl.substring(i, i + 2), 16);
|
||||
rpayload.push(b);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function encode(destination, sensor, command, acknowledge, type, payload) {
|
||||
var msg = destination.toString(10) + ";" + sensor.toString(10) + ";" + command.toString(10) + ";" + acknowledge.toString(10) + ";" + type.toString(10) + ";";
|
||||
if (command == 4) {
|
||||
for (var i = 0; i < payload.length; i++) {
|
||||
if (payload[i] < 16)
|
||||
msg += "0";
|
||||
msg += payload[i].toString(16);
|
||||
}
|
||||
} else {
|
||||
msg += payload;
|
||||
}
|
||||
msg += '\n';
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
function saveProtocol(sender, payload, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$set: {
|
||||
'protocol': payload
|
||||
}
|
||||
}, {
|
||||
upsert: true
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing protocol to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveValue(sender, sensor, type, payload, db) {
|
||||
var cn = "Value-" + sender.toString() + "-" + sensor.toString();
|
||||
db.createCollection(cn, function(err, c) {
|
||||
c.save({
|
||||
'timestamp': new Date().getTime(),
|
||||
'type': type,
|
||||
'value': payload
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing value to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveBatteryLevel(sender, payload, db) {
|
||||
var cn = "BatteryLevel-" + sender.toString();
|
||||
db.createCollection(cn, function(err, c) {
|
||||
c.save({
|
||||
'timestamp': new Date().getTime(),
|
||||
'value': payload
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing battery level to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveSketchName(sender, payload, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$set: {
|
||||
'sketchName': payload
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing sketch name to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveSketchVersion(sender, payload, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$set: {
|
||||
'sketchVersion': payload
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing sketch version to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendTime(destination, sensor, gw) {
|
||||
var payload = new Date().getTime();
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_TIME;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
function sendNextAvailableSensorId(db, gw) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.find({
|
||||
$query: { },
|
||||
$orderby: {
|
||||
'id': 1
|
||||
}
|
||||
}).toArray(function(err, results) {
|
||||
if (err)
|
||||
console.log('Error finding nodes');
|
||||
var id = 1;
|
||||
for (var i = 0; i < results.length; i++)
|
||||
if (results[i].id > i + 1) {
|
||||
id = i + 1;
|
||||
break;
|
||||
}
|
||||
if (id < 255) {
|
||||
c.save({
|
||||
'id': id
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error writing node to database');
|
||||
var destination = BROADCAST_ADDRESS;
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_ID_RESPONSE;
|
||||
var payload = id;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendConfig(destination, gw) {
|
||||
var payload = "M";
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_CONFIG;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
function sendFirmwareConfigResponse(destination, fwtype, fwversion, db, gw) {
|
||||
// keep track of type/versin info for each node
|
||||
// at the same time update the last modified date
|
||||
// could be used to remove nodes not seen for a long time etc.
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': destination
|
||||
}, {
|
||||
$set: {
|
||||
'type': fwtype,
|
||||
'version': fwversion
|
||||
}
|
||||
}, {
|
||||
upsert: true
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing node type and version to database");
|
||||
});
|
||||
});
|
||||
if (fwtype == 0xFFFF) {
|
||||
// sensor does not know which type / blank EEPROM
|
||||
// take predefined type (ideally selected in UI prior to connection of new sensor)
|
||||
if (fwDefaultType == 0xFFFF)
|
||||
throw new Error('No default sensor type defined');
|
||||
fwtype = fwDefaultType;
|
||||
}
|
||||
db.collection('firmware', function(err, c) {
|
||||
c.findOne({
|
||||
$query: {
|
||||
'type': fwtype
|
||||
},
|
||||
$orderby: {
|
||||
'version': -1
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error finding firmware for type ' + fwtype);
|
||||
if (!result)
|
||||
console.log('No firmware found for type ' + fwtype);
|
||||
var payload = [];
|
||||
pushWord(payload, result.type);
|
||||
pushWord(payload, result.version);
|
||||
pushWord(payload, result.blocks);
|
||||
pushWord(payload, result.crc);
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_STREAM;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = 1; // I_FIRMWARE_CONFIG_RESPONSE
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendFirmwareResponse(destination, fwtype, fwversion, fwblock, db, gw) {
|
||||
db.collection('firmware', function(err, c) {
|
||||
c.findOne({
|
||||
'type': fwtype,
|
||||
'version': fwversion
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error finding firmware version ' + fwversion + ' for type ' + fwtype);
|
||||
var payload = [];
|
||||
pushWord(payload, result.type);
|
||||
pushWord(payload, result.version);
|
||||
pushWord(payload, fwblock);
|
||||
for (var i = 0; i < FIRMWARE_BLOCK_SIZE; i++)
|
||||
payload.push(result.data[fwblock * FIRMWARE_BLOCK_SIZE + i]);
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_STREAM;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = ST_FIRMWARE_RESPONSE;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function rebootNode(destination, gw) {
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_REBOOT;
|
||||
var payload = "";
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
function rfReceived(data, db, gw) {
|
||||
if ((data != null) && (data != "")) {
|
||||
console.log('<- ' + data);
|
||||
// decoding message
|
||||
var datas = data.toString().split(";");
|
||||
var sender = +datas[0];
|
||||
var sensor = +datas[1];
|
||||
var command = +datas[2];
|
||||
var type = +datas[3];
|
||||
var rawpayload = datas[4].trim();
|
||||
var payload;
|
||||
if (command == 4) {
|
||||
payload = [];
|
||||
for (var i = 0; i < rawpayload.length; i+=2)
|
||||
payload.push(parseInt(rawpayload.substring(i, i + 2), 16));
|
||||
} else {
|
||||
payload = rawpayload;
|
||||
}
|
||||
// decision on appropriate response
|
||||
switch (command) {
|
||||
case C_PRESENTATION:
|
||||
saveProtocol(sender, payload, db);
|
||||
break;
|
||||
case C_SET:
|
||||
saveValue(sender, sensor, type, payload, db);
|
||||
break;
|
||||
case C_REQ:
|
||||
break;
|
||||
case C_INTERNAL:
|
||||
switch (type) {
|
||||
case I_BATTERY_LEVEL:
|
||||
saveBatteryLevel(sender, payload, db);
|
||||
break;
|
||||
case I_TIME:
|
||||
sendTime(sender, sensor, gw);
|
||||
break;
|
||||
case I_VERSION:
|
||||
break;
|
||||
case I_ID_REQUEST:
|
||||
sendNextAvailableSensorId(db, gw);
|
||||
break;
|
||||
case I_ID_RESPONSE:
|
||||
break;
|
||||
case I_INCLUSION_MODE:
|
||||
break;
|
||||
case I_CONFIG:
|
||||
sendConfig(sender, gw);
|
||||
break;
|
||||
case I_PING:
|
||||
break;
|
||||
case I_PING_ACK:
|
||||
break;
|
||||
case I_LOG_MESSAGE:
|
||||
break;
|
||||
case I_CHILDREN:
|
||||
break;
|
||||
case I_SKETCH_NAME:
|
||||
saveSketchName(sender, payload, db);
|
||||
break;
|
||||
case I_SKETCH_VERSION:
|
||||
saveSketchVersion(sender, payload, db);
|
||||
break;
|
||||
case I_REBOOT:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case C_STREAM:
|
||||
switch (type) {
|
||||
case ST_FIRMWARE_CONFIG_REQUEST:
|
||||
var fwtype = pullWord(payload, 0);
|
||||
var fwversion = pullWord(payload, 2);
|
||||
sendFirmwareConfigResponse(sender, fwtype, fwversion, db, gw);
|
||||
break;
|
||||
case ST_FIRMWARE_CONFIG_RESPONSE:
|
||||
break;
|
||||
case ST_FIRMWARE_REQUEST:
|
||||
var fwtype = pullWord(payload, 0);
|
||||
var fwversion = pullWord(payload, 2);
|
||||
var fwblock = pullWord(payload, 4);
|
||||
sendFirmwareResponse(sender, fwtype, fwversion, fwblock, db, gw);
|
||||
break;
|
||||
case ST_FIRMWARE_RESPONSE:
|
||||
break;
|
||||
case ST_SOUND:
|
||||
break;
|
||||
case ST_IMAGE:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dbc = require('mongodb').MongoClient;
|
||||
dbc.connect('mongodb://' + dbAddress + ':' + dbPort + '/' + dbName, function(err, db) {
|
||||
if(err) {
|
||||
console.log('Error connecting to database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
return;
|
||||
}
|
||||
console.log('Connected to database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
db.createCollection('node', function(err, collection) { });
|
||||
db.createCollection('firmware', function(err, collection) { });
|
||||
|
||||
// ToDo : check for new hex files / only load if new / get type and version from filename
|
||||
for (var i = 0; i < hexFiles.length; i++)
|
||||
loadFirmware(i, 1, hexFiles[i], db);
|
||||
|
||||
var gw;
|
||||
if (gwType == 'Ethernet') {
|
||||
gw = require('net').Socket();
|
||||
gw.connect(gwPort, gwAddress);
|
||||
gw.setEncoding('ascii');
|
||||
gw.on('connect', function() {
|
||||
console.log('connected to ethernet gateway at ' + gwAddress + ":" + gwPort);
|
||||
}).on('data', function(rd) {
|
||||
var rds = rd.toString().split('\n');
|
||||
for (var i = 0; i < rds.length; i++)
|
||||
rfReceived(rds[i].trim(), db, gw);
|
||||
}).on('end', function() {
|
||||
console.log('disconnected from gateway');
|
||||
}).on('error', function() {
|
||||
console.log('connection error - trying to reconnect');
|
||||
gw.connect(gwPort, gwAddress);
|
||||
gw.setEncoding('ascii');
|
||||
});
|
||||
} else if (gwType == 'Serial') {
|
||||
gw = require('serialport').SerialPort(gwPort, { baudrate: gwBaud }, false);
|
||||
gw.open();
|
||||
gw.on('open', function() {
|
||||
console.log('connected to serial gateway at ' + gwPort);
|
||||
}).on('data', function(rd) {
|
||||
var rds = rd.toString().split('\n');
|
||||
for (var i = 0; i < rds.length; i++)
|
||||
rfReceived(rds[i].trim(), db, gw);
|
||||
}).on('end', function() {
|
||||
console.log('disconnected from gateway');
|
||||
}).on('error', function() {
|
||||
console.log('connection error - trying to reconnect');
|
||||
gw.open();
|
||||
});
|
||||
} else {
|
||||
throw new Error('unknown Gateway type');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
var NodeIdToReboot = 1;
|
||||
|
||||
var gwType = 'Ethernet';
|
||||
var gwAddress = '10.0.1.99';
|
||||
var gwPort = 9999;
|
||||
|
||||
var BROADCAST_ADDRESS = 255;
|
||||
var NODE_SENSOR_ID = 255;
|
||||
|
||||
function encode(destination, sensor, command, acknowledge, type, payload, binary) {
|
||||
var msg = destination.toString(10) + ";" + sensor.toString(10) + ";" + command.toString(10) + ";" + acknowledge.toString(10) + ";" + type.toString(10) + ";";
|
||||
if (binary) {
|
||||
for (var i = 0; i < payload.length; i++) {
|
||||
if (payload[i] < 16)
|
||||
msg += "0";
|
||||
msg += payload[i].toString(16);
|
||||
}
|
||||
} else {
|
||||
msg += payload;
|
||||
}
|
||||
msg += '\n';
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
function rebootNode(destination, gw) {
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = 3; // C_INTERNAL
|
||||
var acknowledge = 0; // no ack
|
||||
var type = 13; // I_REBOOT
|
||||
var payload = "";
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload, false);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
var gw = require('net').Socket();
|
||||
gw.connect(gwPort, gwAddress);
|
||||
gw.setEncoding('ascii');
|
||||
gw.on('connect', function() {
|
||||
console.log('connected to ethernet gateway at ' + gwAddress + ":" + gwPort);
|
||||
rebootNode(NodeIdToReboot, gw);
|
||||
console.log('reboot request submitted for ' + NodeIdToReboot);
|
||||
}).on('end', function() {
|
||||
console.log('disconnected from gateway');
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "NodeJsController",
|
||||
"version": "0.0.1",
|
||||
"description": "MySensors Controller based on Node JS",
|
||||
"dependencies": {
|
||||
"net": "~1.0.2",
|
||||
"mongodb": "~1.4.7"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user