Last active
August 29, 2015 14:01
-
-
Save industrialinternet/1f9444600517f8007b4c to your computer and use it in GitHub Desktop.
node-enocean basic enocean telegram handler used with USB300
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// node-enocean v0.0 | |
CRC8Table = [ | |
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, | |
0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, | |
0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, | |
0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, | |
0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, | |
0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, | |
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, | |
0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, | |
0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, | |
0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, | |
0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, | |
0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, | |
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, | |
0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, | |
0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, | |
0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, | |
0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, | |
0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, | |
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, | |
0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, | |
0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, | |
0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, | |
0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, | |
0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, | |
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, | |
0x76, 0x71, 0x78, 0x7f, 0x6A, 0x6d, 0x64, 0x63, | |
0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, | |
0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, | |
0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, | |
0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8D, 0x84, 0x83, | |
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, | |
0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 | |
]; | |
// EnOcean Serial Port Setup and API functions. | |
serialport = require("/home/pi/node_modules/serialport").SerialPort; | |
var portName = '/dev/ttyUSB0'; //This is the standard Raspberry Pi Serial port or /dev/ttyAMA0 | |
var readData = ''; //Array to hold the values read in from the port | |
var serialPortOpen = false, enoPacket0 = null, enoPacket1 = null, enoPacket2 = null, enoPacketCount = 0, enoBaseID = "0x80"; | |
var serialPort = new serialport(portName, { | |
baudRate: 56700, | |
dataBits: 8, | |
parity: 'none', | |
startBits: 1, | |
stopBits: 1, | |
flowControl: false, | |
}); | |
serialPort.on("open", function () { | |
serialPortOpen = true; | |
console.log('EnOcean: USB0 port open'); | |
serialPort.on('data', function(data) { | |
console.log('on data: ' + data.toString('hex')+' len:'+data.length); | |
if( toHex(data[0]) == "55" && (data.length >=12 && toHex(data[6]) =="f6") || (data.length >=15 && toHex(data[6]) =="a5")){ | |
//console.log('isEnO syn:'+toHex(data[0])+' org:'+toHex(data[6])+' swState:'+toHex(data[7])); | |
console.log('eno syn:'+toHex(data[0])+' lng:'+data.length+ ' org:'+toHex(data[6])); | |
packet = data.toString('hex'); | |
if(toHex(data[6]) == "f6"){ | |
ENOreciveSW(toHex(data[7]),packet); | |
} | |
if(toHex(data[6]) == "a5"){ | |
ENOrecive4BS(packet); | |
} | |
} else { // Fragmented telegram | |
if(enoPacketCount >= 2){ | |
enoPacket2 = enoPacket1+data.toString('hex'); | |
//console.log("no:"+enoPacketCount+' pkt:'+enoPacket2+' b6:'+enoPacket2.substring(14,16)+' @:'+new Date().toUTCString()); | |
if(enoPacket2.length >=25){ // Switch telegram | |
var rorg = enoPacket2.substring(12,14); | |
//console.log("pk2 rorg:"+enoPacket2.substring(12,14)+" rorg:"+rorg+" state:"+enoPacket2.substring(14,16)); | |
if(rorg == "f6"){ | |
ENOreciveSW(enoPacket2.substring(14,16),enoPacket2); | |
} | |
} | |
if(enoPacket2.length >=30){ // 4BS telegram | |
var rorg = enoPacket2.substring(12,14); | |
//console.log("pk2 rorg:"+enoPacket2.substring(12,14)+" rorg:"+rorg+" state:"+enoPacket2.substring(14,16)); | |
if(rorg == "a5"){ | |
ENOrecive4BS(enoPacket2); | |
} | |
} | |
packetReset(); | |
} | |
if(enoPacketCount == 1){ | |
enoPacketCount++; | |
enoPacket1 = enoPacket0+data.toString('hex'); | |
//console.log("no:"+enoPacketCount+' pkt:'+enoPacket1+' len:'+ enoPacket1.length); // b6:'+enoPacket1.substring(14,16)+' @:'+new Date().toUTCString()); | |
if(enoPacket1.length >=25){ // Switch telegram | |
var rorg = enoPacket1.substring(12,14); | |
//console.log("pk1 rorg:"+enoPacket1.substring(12,14)+" rorg:"+rorg+" state:"+enoPacket1.substring(14,16)); | |
if(rorg == "f6"){ | |
ENOreciveSW(enoPacket1.substring(14,16),enoPacket1); | |
packetReset(); | |
return; | |
} | |
} | |
if(enoPacket1.length >=30){ // 4BS telegram | |
var rorg = enoPacket1.substring(12,14); | |
//console.log("pk1 rorg:"+enoPacket1.substring(12,14)+" rorg:"+rorg+" state:"+enoPacket1.substring(14,16)); | |
if(rorg == "a5"){ | |
ENOrecive4BS(enoPacket1); | |
packetReset(); | |
} | |
} | |
} | |
if (toHex(data[0]) == "55"){ // Sync byte | |
enoPacket0 = data.toString('hex'); | |
//console.log("no:"+enoPacketCount+' pkt:'+enoPacket0+' @:'+new Date().toUTCString()); | |
enoPacketCount++; | |
} | |
} | |
}); | |
}); | |
// EnOcean telegram crc & functions | |
var EnOcean = require('./EnOceanRadio'); | |
function proccrc8(CRC, u8Data){ | |
return EnOcean.CRC8Table[(CRC ^ u8Data) & 0xff]; | |
} | |
function ESP3HeaderCRC(telegramHeader){ | |
u8CRC = 0; | |
u8CRC = proccrc8(u8CRC,telegramHeader[1]); | |
u8CRC = proccrc8(u8CRC,telegramHeader[2]); | |
u8CRC = proccrc8(u8CRC,telegramHeader[3]); | |
u8CRC = proccrc8(u8CRC,telegramHeader[4]); | |
return u8CRC; | |
} | |
function ESP3DataCRC(telegramData){ | |
u8CRC = 0; | |
for (var dbyte in telegramData){ | |
u8CRC = proccrc8(u8CRC,telegramData[dbyte]) | |
} | |
return u8CRC; | |
} | |
function ESP3Header(packetType,packetData){ | |
pHeader = [0x55]; //sync | |
pHeader.push(0x00); //MSB Data Length | |
pHeader.push(packetData.length); //LSB Data Length | |
pHeader.push(0x00); //optional data length | |
pHeader.push(packetType); //packet type | |
pHeader.push(ESP3HeaderCRC(pHeader));//Header CRC | |
return pHeader; | |
} | |
// WARNNING | |
// This function only sends Switch (RPS) telegram | |
// It needs to included the sending of 1 & 4 byte telegrams | |
function sendESP3Packet(packetType, packetData){ | |
pESP3Packet = ESP3Header(packetType,packetData); | |
for(pi=0; pi<7; pi++){ | |
pESP3Packet.push(packetData[pi]); | |
} | |
pESP3Packet.push(ESP3DataCRC(packetData)); | |
//return pESP3Packet; | |
//var stel = new Buffer ([0x55,0x00,0x07,0x00,0x01,0x11,0xF6,0x30,0xFF,0x8D,0x67,0x80,0x30,0xD7]); | |
//var pk = ['syn','dlo','dl1','opl','pt','crc','org','sw','id0','id1','id2','id3','status','crc']; | |
var stel = new Buffer(14); | |
for(bi=0; bi<14; bi++){ | |
var hexno = pESP3Packet[bi].toString(16); | |
stel[bi]= pESP3Packet[bi]; | |
//console.log("stel["+bi+"]"+stel[bi]+" hex:"+hexno+" dec:"+pESP3Packet[bi]+" pk:"+pk[bi]); | |
} | |
serialPort.write(stel, function(err, results) { | |
//console.log('err ' + err); | |
//console.log('transmitResult:' + results.toString(16)); | |
}); | |
} | |
function toHex(s){ | |
return _s = s.toString(16); | |
} | |
function packetReset(){ | |
enoPacketCount=0; | |
enoPacket0=null; | |
enoPacket1=null; | |
enoPacket2=null; | |
} | |
// EnOcean receive/send | |
// _dp is channel no 1 to 128 when using base id | |
function ENOsendSW(_dp,_state){ | |
var x =parseInt(enoBaseID, 16); | |
var y=parseInt(_dp, 16); | |
var z=x+y; | |
var dPID = "0x"+z.toString(16); | |
if(_state==true || _state=="true"){ | |
sendESP3Packet(0x01, [0xF6,0x10,0xFF,0xFF,0x46,""+dPID+"",0x30]); // on | |
sendESP3Packet(0x01, [0xF6,0x00,0xFF,0xFF,0x46,""+dPID+"",0x20]); // release | |
} else { | |
sendESP3Packet(0x01, [0xF6,0x30,0xFF,0xFF,0x46,""+dPID+"",0x30]); // off | |
sendESP3Packet(0x01, [0xF6,0x00,0xFF,0xFF,0x46,""+dPID+"",0x20]); // release | |
} | |
} | |
function ENOreciveSW(swState,packet){ | |
var state= null; | |
if( swState == "ff"){return;} | |
if(swState == "00" || swState == "0"){ | |
state =false; | |
} | |
if(swState == "10" || swState == "50" || swState == "30" || swState == "70"){ | |
var state = null; | |
var _rocker=null; | |
if(swState == "10" || swState == "50"){state =true;} | |
if(swState == "30" || swState == "70"){state =false;} | |
if(swState == "10" || swState == "30"){_rocker="b";} | |
if(swState == "50" || swState == "70"){_rocker="a";} | |
var dPID = packet.substring(16,24); // EnOCean id | |
// var dPID = packet.substring(16,24)+"_"+_rocker; // EnOcean id + Rocker id | |
console.log("SWT id:"+dPID+" rocker:"+_rcoker+" state:"+swState); | |
} | |
} | |
function ENOrecive4BS(packet){ | |
var data=packet.substring(14,22); | |
var DB3=packet.substring(14,16); | |
var DB2=packet.substring(16,18); | |
var DB1=packet.substring(18,20); | |
var DB0=packet.substring(20,22); | |
var dPID= packet.substring(22,30); | |
console.log("4BS id:"+dPID+" DB0:"+DB0+" DB1:"+DB1+" DB2:"+DB2+" DB3:"+DB3); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment