Skip to content

Instantly share code, notes, and snippets.

@industrialinternet
Last active August 29, 2015 14:02
Show Gist options
  • Save industrialinternet/54c2fe757801babc0b5b to your computer and use it in GitHub Desktop.
Save industrialinternet/54c2fe757801babc0b5b to your computer and use it in GitHub Desktop.
Node-Red EnOcean Radio telegram functions
These are very basic Node-Red funtions I will in time convert to NR nodes.
They require the ENO300 USB module and use nr-serail-in
57600 8 None 1
Split input: after fixed timeout 50ms
and deliver: binary buffers
I've done all my testing on Raspberry PI.
Please note the send switch funtion need you to set a Base ID to support 128 ID else it will only use the chip ID which means only 1 channel. That said any EnOcean-ers out thier that can help get chip ID working would love your help :)
Will add a standalone setBaseID.js node.js that sp you can configure from command line.
[{"id":"42ec8800.bd1378","type":"serial-port","serialport":"/dev/ttyUSB0","serialbaud":"57600","databits":"8","parity":"none","stopbits":"1","newline":"50","bin":"bin","out":"time","addchar":"false"},{"id":"312bf663.ced40a","type":"serial in","name":"enocean","serial":"42ec8800.bd1378","x":92,"y":105,"z":"a853296f.57acd8","wires":[["9d8d2bd7.6272d8"]]},{"id":"9d8d2bd7.6272d8","type":"function","name":"Enocean - Decode","func":"// EnOcean in v0.1\n// Only supports: Packet Type 1: RADIO \n// Only supports: RPS Switch and 4Byte Telegrams\n\nvar data = msg.payload;\n//console.log('telgram in: ' + data.toString('hex')+' len:'+data.length);\n// handel RPS and 4BS telegrams \nif( toHex(data[0]) == \"55\" && (data.length >=12 && toHex(data[6]) ==\"f6\") || (data.length >=15 && toHex(data[6]) ==\"a5\")){\t\n\tpacket = data.toString('hex');\n\tif(toHex(data[6]) == \"f6\"){\n\t\tENOreciveSW(toHex(data[7]),packet);\n\t\tmsg.not4bs = true;\n\t}\t\t\t\t\n\telse if(toHex(data[6]) == \"a5\"){\n\t\tENOrecive4BS(packet);\n\t}\n\telse {\n\t\tmsg.payload = null;\n\t}\n}\n// handle responce from CO_RD_IDBASE - read base id\nif(toHex(data[0]) == \"55\" && toHex(data[4]) ==\"2\" && toHex(data[6]) ==\"0\" && data.length >=12){\n\t//console.log(\"read base ID responce:\"+ data.toString('hex'));\n\tvar d= new Date();\n\tvar utc = d.toUTCString();\n\tvar baseID = toHex(data[7])+toHex(data[8])+toHex(data[9])+toHex(data[10]);\n\tvar noOfWritesLeft = toHex(data[11]);\n\t//msg.payload= {\"baseID\":\"\"+baseID+\"\",\"noOfWritesLeft\":+\"\"+\"\"};\n\tmsg.payload= {\"baseID\":\"\"+baseID+\"\",\"noOfWritesLeft\":+noOfWritesLeft,\"utc\":\"\"+utc+\"\"};\n\tmsg.not4bs = true;\n\tmsg.baseID= baseID;\n\tmsg.noOfWritesLeft = noOfWritesLeft;\n\tmsg.fileName=\"enoWrites.json\";\n\tmsg.utc=utc;\n}\t\n// handle responce from CO_WR_IDBASE - write base id\nif( toHex(data[2]) == \"1\" && toHex(data[4]) == \"2\"){\n\tif(toHex(data[6]) == \"0\"){\n\t\tmsg.ENOresponce= 'OK';\n\t} else if (toHex(data[6]) == \"2\"){\n\t\tmsg.ENOresponce= 'Error: baseID not surported';\n\t} else if (toHex(data[6]) == \"82\"){\n\t\tmsg.ENOresponce= 'Error: writing baseID to flash!';\n\t} else if (toHex(data[6]) == \"90\"){\n\t\tmsg.writeBaseRes= 'Error: baseID out of range!';\n\t} else if (toHex(data[6]) == \"91\"){\n\t\tmsg.ENOresponces= \"Eoor: can't write baseID no more changes allowed!\";\n\t} \n}\n// complete\nreturn msg;\n\n// support funtions\nfunction toHex(s){\n\t return _s = s.toString(16);\n} \nfunction ENOreciveSW(swState,packet){\n\tmsg.type= \"F6: RPS Telegram\";\n\tif(swState == \"ff\"){ // invalid sw states\n\t\tmsg.payload= null;\n\t\tmsg.state= swState;\n\t\treturn;\n\t}\n\tif(swState == \"00\" || swState == \"0\"){ // Rocker released \n\t\tmsg.payload= packet.substring(16,24);\n\t\tmsg.state= \"released\";\n\t\treturn;\n\t}\n\tif(swState == \"10\" || swState == \"50\" || swState == \"30\" || swState == \"70\"){ // Rocker pressed 1 or 2 gang switch\n\t\tif(swState == \"10\" || swState == \"50\"){msg.state= true;}\n\t\tif(swState == \"30\" || swState == \"70\"){msg.state= false;}\n\t\tif(swState == \"10\" || swState == \"30\"){msg.rocker= \"b\";}\n\t\tif(swState == \"50\" || swState == \"70\"){msg.rocker= \"a\";}\t\t\t\n\t\tmsg.payload= packet.substring(16,24); \n\t\tmsg.dPID= msg.payload+\"_\"+msg.rocker;\n\t}\n}\nfunction ENOrecive4BS(packet){\n\tmsg.type = \"A5: 4BS Telegram\";\n\tmsg.DB3= packet.substring(14,16);\n\tmsg.DB2= packet.substring(16,18);\n\tmsg.DB1= packet.substring(18,20);\n\tmsg.DB0= packet.substring(20,22);\n\tmsg.DBall=[msg.DB0,msg.DB1,msg.DB2,msg.DB3];\n\tmsg.payload= packet.substring(22,30);\n\tmsg.dPID= msg.payload;\n}\n","outputs":"1","x":290,"y":105,"z":"a853296f.57acd8","wires":[["db22762c.24dd88","f39a026b.0c66","3fcf9af0.c03066"]]},{"id":"db22762c.24dd88","type":"debug","name":"","active":true,"console":"false","complete":"true","x":469,"y":63,"z":"a853296f.57acd8","wires":[]},{"id":"5b39c164.a4c64","type":"comment","name":"In","info":"","x":90,"y":67,"z":"a853296f.57acd8","wires":[]},{"id":"ad54be5d.52ab4","type":"comment","name":"EnOcean canvas v0.1","info":"","x":1050,"y":35,"z":"a853296f.57acd8","wires":[]},{"id":"3bb0ae8.fc44f52","type":"function","name":"Send telegramd","func":"var CRC8Table = [\n 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, \n 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, \n 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, \n 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, \n 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, \n 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, \n 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, \n 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, \n 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, \n 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, \n 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, \n 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, \n 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, \n 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, \n 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, \n 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, \n 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, \n 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, \n 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, \n 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, \n 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, \n 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, \n 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, \n 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, \n 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, \n 0x76, 0x71, 0x78, 0x7f, 0x6A, 0x6d, 0x64, 0x63, \n 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, \n 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, \n 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, \n 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8D, 0x84, 0x83, \n 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, \n 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3\n];\n// EnOcean telegram crc & functions\nfunction proccrc8(CRC, u8Data){ \n\treturn CRC8Table[(CRC ^ u8Data) & 0xff];\n}\nfunction ESP3HeaderCRC(telegramHeader){\n\tu8CRC = 0;\n\tu8CRC = proccrc8(u8CRC,telegramHeader[1]);\n\tu8CRC = proccrc8(u8CRC,telegramHeader[2]);\n\tu8CRC = proccrc8(u8CRC,telegramHeader[3]);\n\tu8CRC = proccrc8(u8CRC,telegramHeader[4]);\n\treturn u8CRC;\n}\nfunction ESP3DataCRC(telegramData){\n\tu8CRC = 0;\n\tfor (var dbyte in telegramData){\n\t\tu8CRC = proccrc8(u8CRC,telegramData[dbyte])\n\t}\n\treturn u8CRC;\n}\nfunction ESP3Header(packetType,packetData){\n\tpHeader = [0x55]; \t\t\t\t\t//sync\n\tpHeader.push(0x00); \t\t\t\t//MSB Data Length\n\tpHeader.push(packetData.length);\t//LSB Data Length\n\tpHeader.push(0x00); \t\t\t\t//optional data length\n\tpHeader.push(packetType); \t\t\t//packet type\n\tpHeader.push(ESP3HeaderCRC(pHeader));//Header CRC\n\treturn pHeader;\n}\n\nfunction sendESP3Packet_V2(packetType, packetData){\n\n\tpESP3Packet = ESP3Header(packetType,packetData);\n\tfor(pi=0; pi<packetData.length; pi++){\n\t\tpESP3Packet.push(packetData[pi]); \n\t}\t\n\tpESP3Packet.push(ESP3DataCRC(packetData)); \n\t//console.log(\"tel:\"+pESP3Packet.toString('hex'));\n\n\t//var stel = new Buffer ([0x55,0x00,0x07,0x00,0x01,0x11,0xF6,0x30,0xFF,0x8D,0x67,0x80,0x30,0xD7]); \n\t//var pk = ['syn','dlo','dl1','opl','pt','crc','org','sw','id0','id1','id2','id3','status','crc'];\n\tvar stel = new Buffer(pESP3Packet.length);\n\t\t\n\tfor(bi=0; bi<pESP3Packet.length; bi++){\n\t\t//var hexno = pESP3Packet[bi].toString(16);\n\t\tstel[bi]= pESP3Packet[bi];\n\t\t//console.log(\"stel[\"+bi+\"]\"+stel[bi]+\" hex:\"+hexno+\" dec:\"+pESP3Packet[bi]+\" pk:\"+pk[bi]);\t\t\t\t\n\t}\t\n\tmsg.payload=stel;\n\t//msg.payload=null;\n\tmsg.topic=\"send eno\";\n}\n\nfunction sendESP3Packet(packetType, packetData){\n\n\tpESP3Packet = ESP3Header(packetType,packetData);\n\tfor(pi=0; pi<7; pi++){\n\t\tpESP3Packet.push(packetData[pi]); \n\t}\t\n\tpESP3Packet.push(ESP3DataCRC(packetData)); \n\t//return pESP3Packet;\n\n\t//var stel = new Buffer ([0x55,0x00,0x07,0x00,0x01,0x11,0xF6,0x30,0xFF,0x8D,0x67,0x80,0x30,0xD7]); \n\t//var pk = ['syn','dlo','dl1','opl','pt','crc','org','sw','id0','id1','id2','id3','status','crc'];\n\tvar stel = new Buffer(14);\n\t\t\n\tfor(bi=0; bi<14; bi++){\n\t\t//var hexno = pESP3Packet[bi].toString(16);\n\t\tstel[bi]= pESP3Packet[bi];\n\t\t//console.log(\"stel[\"+bi+\"]\"+stel[bi]+\" hex:\"+hexno+\" dec:\"+pESP3Packet[bi]+\" pk:\"+pk[bi]);\t\t\t\t\n\t}\t\n\tmsg.payload=stel;\n\tmsg.topic=\"send eno\";\n}\nfunction toHex(s){\n return _s = s.toString(16);\n}\n\nfunction ENOsendSW(_ch,_state){\n\t// Note math only good for base + 78 channels re-wite to support 128\n\t//var x=parseInt(enoBaseIDlastByte);\n\tvar x=parseInt( enoBaseID[3]);\n\tvar z=x+_ch;\n\tvar channel = \"0x\"+z.toString(16);\n\tif(_state==true || _state==\"true\"){ \n\t\tsendESP3Packet_V2(0x01, [0xF6,0x10,enoBaseID[0],enoBaseID[1],enoBaseID[2],\"\"+channel+\"\",0x30]); // on/up/dim-up pressed\n\t} else {\t// Radio =01 RORG=F6 State BaseID Status \n\t\tsendESP3Packet_V2(0x01, [0xF6,0x30,enoBaseID[0],enoBaseID[1],enoBaseID[2],\"\"+channel+\"\",0x30]); // off/down/dim-down pressed\n\t}\n}\n// To use all 128 channels use setbase id\nvar enoBaseID= [0xFF,0xFF,0x46,0x80]; \n\n// Handel send switch\n// console.log(\"msg.state:\"+msg.state);\nif(msg.action == \"setSW\"){\n\tENOsendSW(msg.channel,msg.state);\n}\n\n// Handel set baseID WARNING you only write 10 times \nif(msg.action == \"setBaseID\"){\n\t// set baseID\n\tsendESP3Packet_V2(0x05, [0x07,enoBaseID[0],enoBaseID[1],enoBaseID[2],enoBaseID[3]]); // on/up/dim-up pressed\n}\nreturn msg;","outputs":1,"x":497,"y":233,"z":"a853296f.57acd8","wires":[["84af399d.7b50c8","5c7eb0b1.a3815"]]},{"id":"84af399d.7b50c8","type":"serial out","name":"enocean out","serial":"42ec8800.bd1378","x":719,"y":233,"z":"a853296f.57acd8","wires":[]},{"id":"e7800889.187ff8","type":"inject","name":"Toggle","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":110,"y":233,"z":"a853296f.57acd8","wires":[["ee5b7895.11a488"]]},{"id":"5c7eb0b1.a3815","type":"debug","name":"","active":false,"console":"false","complete":"true","x":703,"y":275,"z":"a853296f.57acd8","wires":[]},{"id":"b1acc523.4e5338","type":"comment","name":"Out","info":"","x":88,"y":194,"z":"a853296f.57acd8","wires":[]},{"id":"f39a026b.0c66","type":"function","name":"EnOcean - 4BS EEP","func":"// Convert 4Bs to equipment profile\n// Only supports profiles:\n// A5.02.05 & A5.10.03 \t\n\nif(msg.payload == null){\n\treturn;\n} else { \n\tvar ENOid = msg.payload;\n}\n\n// add the id & profile of your sensor below \nvar profileConfig = {\n\t\"0000deff\": {\n\t\t\"type\": \"A5.02.05\",\n\t\t \"name\": \"EnOcean: external temp\"\n\t}, \t\n\t\"0000de7b\": {\n\t\t\"type\": \"A5.10.03\",\n\t\t\"name\": \"EnOcean: office temp\",\n\t\t\"scaleSetpoint\" : [0,25]\t\t\n\t}\n};\n\nvar type = null;\nif(ENOid in profileConfig){\n\ttype = profileConfig[ENOid].type;\n} \n//console.log(\"ENOid\"+ENOid+\" DBall\"+msg.DBall+\" type:\"+type);\n\nENO_A5_4BS_profiles(ENOid,msg.DBall,type);\nreturn msg;\n\nfunction ENO_A5_4BS_profiles(ENOid,DBall,type){ \n\t// only supports profiles:\n\t// A5.02.05 & A5.10.03 \t\n\tswitch(type)\n\t\t{\n\t\tcase \"A5.02.02\":\n\t\t\tvar rawTmp= parseInt(DBall[1],16) * 0.3137254;\n\t\t\tvar tmp= 60.0 - rawTmp;\n\t\t\ttemprature= tmp.toFixed(1);\n\t\t\tmsg.type= \"A5.02.05\";\n\t\t\tmsg.DB1= temprature;\n\t\t\tbreak;\n\t\tcase \"A5.10.03\":\n\t\t\tvar rawTmp= parseInt(DBall[1],16) * 0.15686;\n\t\t\tvar tmp= 40.0 - rawTmp;\n\t\t\ttemprature= tmp.toFixed(1); \n\t\t\tmsg.type= \"A5.10.03\";\n\t\t\tmsg.DB2= DBall[2];\n\t\t\tmsg.DB1=temprature;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tmsg.type= \"No profile for id:\"+ENOid;\n\t\t\t//console.log('EnOcean: no profile match for sensor id:'+msg.payload);\n\t\t}\n}","outputs":1,"x":511,"y":105,"z":"a853296f.57acd8","wires":[[]]},{"id":"4a3a6496.b5c59c","type":"function","name":"get baseID","func":"var stel = new Buffer ([0x55,0x00,0x01,0x00,0x05,0x70,0x08,0x38]);\n // 55 00 01 00 05 70 08 38\nmsg.payload=stel;\nmsg.topic=\"get base id\";\nreturn msg;","outputs":1,"x":484,"y":519,"z":"a853296f.57acd8","wires":[["84af399d.7b50c8"]]},{"id":"aece928d.51317","type":"inject","name":"Get baseID","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":106,"y":519,"z":"a853296f.57acd8","wires":[["4a3a6496.b5c59c"]]},{"id":"ee5b7895.11a488","type":"function","name":"setSw ch:1","func":"context.state = context.state || false;\nif(context.state == false){\n context.state = true;\n} else {\n context.state = false;\n}\n// msg\nmsg.action = \"setSW\";\nmsg.channel = 0x01;\nmsg.state= context.state;\nreturn msg;","outputs":1,"x":243,"y":233,"z":"a853296f.57acd8","wires":[["3bb0ae8.fc44f52"]]},{"id":"c257ad31.3da85","type":"function","name":"setSw ch:2","func":"context.state = context.state || false;\nif(context.state == false){\n context.state = true;\n} else {\n context.state = false;\n}\n// msg\nmsg.action = \"setSW\";\nmsg.channel = 0x02;\nmsg.state= context.state;\nreturn msg;","outputs":1,"x":245,"y":281,"z":"a853296f.57acd8","wires":[["3bb0ae8.fc44f52"]]},{"id":"66cdd1e.f99323","type":"inject","name":"Toggle","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":108,"y":281,"z":"a853296f.57acd8","wires":[["c257ad31.3da85"]]},{"id":"991cf300.66e31","type":"inject","name":"Set baseID","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":106,"y":477,"z":"a853296f.57acd8","wires":[["76bdfc09.894204"]]},{"id":"c96627bb.3699d8","type":"function","name":"setBaseID","func":"// msg\nconsole.log(\"gateway:\"+msg.payload);\nmsg.action = \"setBaseID\";\nreturn msg;","outputs":1,"x":701,"y":477,"z":"a853296f.57acd8","wires":[["3bb0ae8.fc44f52"]]},{"id":"76bdfc09.894204","type":"file in","name":"","filename":"enoWrites.json","format":"utf8","x":281,"y":477,"z":"a853296f.57acd8","wires":[["c92fd527.36d028"]]},{"id":"bf96985e.406968","type":"file","name":"","filename":"enoWrites.json","appendNewline":false,"overwriteFile":true,"x":713,"y":552,"z":"a853296f.57acd8","wires":[]},{"id":"c92fd527.36d028","type":"json","name":"baseIDobj","x":483,"y":478,"z":"a853296f.57acd8","wires":[["c96627bb.3699d8"]]},{"id":"3fcf9af0.c03066","type":"switch","name":"write to file?","property":"fileName","rules":[{"t":"eq","v":"enoWrites.json"},{"t":"eq","v":""}],"checkall":"false","outputs":2,"x":487,"y":558,"z":"a853296f.57acd8","wires":[["bf96985e.406968"],[]]},{"id":"cbb799f8.344868","type":"comment","name":"Set & Manage baseID","info":"","x":121,"y":428,"z":"a853296f.57acd8","wires":[]}]
// EnOcean in v0.1
// Only supports: Packet Type 1: RADIO
// Only supports: RPS Switch and 4Byte Telegrams
var data = msg.payload;
//console.log('telgram in: ' + 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")){
packet = data.toString('hex');
if(toHex(data[6]) == "f6"){
ENOreciveSW(toHex(data[7]),packet);
}
else if(toHex(data[6]) == "a5"){
ENOrecive4BS(packet);
}
else {
msg.payload = null;
}
}
// handle responce from CO_RD_IDBASE - read base id
if(toHex(data[0]) == "55" && toHex(data[4]) =="2" && toHex(data[6]) =="0" && data.length >=12){
console.log("read base ID responce:"+ data.toString('hex'));
msg.payload= null;
msg.baseID= toHex(data[7])+toHex(data[8])+toHex(data[9])+toHex(data[10]);
msg.noOfWrites = +toHex(data[11]);
}
return msg;
function toHex(s){
return _s = s.toString(16);
}
function ENOreciveSW(swState,packet){
msg.type= "F6: RPS Telegram";
if(swState == "ff"){ // invalid sw states
msg.payload= null;
msg.state= swState;
return;
}
if(swState == "00" || swState == "0"){ // Rocker released
msg.payload= packet.substring(16,24);
msg.state= "released";
return;
}
if(swState == "10" || swState == "50" || swState == "30" || swState == "70"){ // Rocker pressed 1 or 2 gang switch
if(swState == "10" || swState == "50"){msg.state= true;}
if(swState == "30" || swState == "70"){msg.state= false;}
if(swState == "10" || swState == "30"){msg.rocker= "b";}
if(swState == "50" || swState == "70"){msg.rocker= "a";}
msg.payload= packet.substring(16,24);
msg.dPID= msg.payload+"_"+msg.rocker;
}
}
function ENOrecive4BS(packet){
msg.type = "A5: 4BS Telegram";
msg.DB3= packet.substring(14,16);
msg.DB2= packet.substring(16,18);
msg.DB1= packet.substring(18,20);
msg.DB0= packet.substring(20,22);
msg.DBall=[msg.DB0,msg.DB1,msg.DB2,msg.DB3];
msg.payload= packet.substring(22,30);
msg.dPID= msg.payload;
}
// Convert 4Bs to equipment profile
// Only supports profiles:
// A5.02.05 & A5.10.03
if(msg.payload == null){
return;
} else {
var ENOid = msg.payload;
}
// add the id & profile of your sensor below
var profileConfig = {
"0000deff": {
"type": "A5.02.05",
"name": "EnOcean: external temp"
},
"0000de7b": {
"type": "A5.10.03",
"name": "EnOcean: office temp",
"scaleSetpoint" : [0,25]
}
};
var type = null;
if(ENOid in profileConfig){
type = profileConfig[ENOid].type;
}
//console.log("ENOid"+ENOid+" DBall"+msg.DBall+" type:"+type);
ENO_A5_4BS_profiles(ENOid,msg.DBall,type);
return msg;
function ENO_A5_4BS_profiles(ENOid,DBall,type){
// only supports profiles:
// A5.02.05 & A5.10.03
switch(type)
{
case "A5.02.02":
var rawTmp= parseInt(DBall[1],16) * 0.3137254;
var tmp= 60.0 - rawTmp;
temprature= tmp.toFixed(1);
msg.type= "A5.02.05";
msg.DB1= temprature;
break;
case "A5.10.03":
var rawTmp= parseInt(DBall[1],16) * 0.15686;
var tmp= 40.0 - rawTmp;
temprature= tmp.toFixed(1);
msg.type= "A5.10.03";
msg.DB2= DBall[2];
msg.DB1=temprature;
break;
default:
msg.type= "No profile for id:"+ENOid;
//console.log('EnOcean: no profile match for sensor id:'+msg.payload);
}
}
var 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 telegram crc & functions
function proccrc8(CRC, u8Data){
return 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;
}
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]);
}
msg.payload=stel;
msg.topic="send eno";
}
function toHex(s){
return _s = s.toString(16);
}
function ENOsendSW(_ch,_state){
// Note math only good for base + 78 channels re-wite to support 128
//var x=parseInt(enoBaseIDlastByte);
var x=parseInt( enoBaseID[3]);
var z=x+_ch;
var channel = "0x"+z.toString(16);
if(_state==true || _state=="true"){
sendESP3Packet(0x01, [0xF6,0x10,enoBaseID[0],enoBaseID[1],enoBaseID[2],""+channel+"",0x30]); // on/up/dim-up pressed
} else {
sendESP3Packet(0x01, [0xF6,0x30,enoBaseID[0],enoBaseID[1],enoBaseID[2],""+channel+"",0x30]); // off/down/dim-down pressed
}
}
// To use all 128 channels use setbase id
var enoBaseID= [0xFF,0xFF,0x46,0x80];
// Simple inject toggle
context.state = context.state || false;
if(context.state == false){
ENOsendSW(0x01,true);
context.state = true;
} else {
ENOsendSW(0x01,false);
context.state = false;
}
return msg;
var stel = new Buffer ([0x55,0x00,0x01,0x00,0x05,0x70,0x08,0x38]);
// 55 00 01 00 05 70 08 38
msg.payload=stel;
msg.topic="get base id";
return msg;
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]);
}
msg.payload=stel;
msg.topic="send eno";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment