UNPKG

node-red-contrib-kbr-ebus

Version:

KBR Gmbh - nodes for accessing ebus devices

196 lines (168 loc) 6.61 kB
const ebus = { //Ermittelt die Checksumme für ein eBus-Telex calcEbusTelexCRC: (ebusTelexByteArray) => { var crc=0; ebusTelexByteArray.forEach(function(byteVal) { crc ^= byteVal; }); return crc; }, //Erzeugt ein eBus-Telex als (byte)Buffer createTelex:(fromAddress,toAddress,data)=>{ data=Buffer.from(data); var lot=(5+data.length) & 0xFF; var buffer=Buffer.alloc(lot+2); var pos=0; buffer.writeUInt8(0x02,pos++); buffer.writeUInt8(lot,pos++); buffer.writeUInt16BE(toAddress,pos); pos+=2; buffer.writeUInt16BE(fromAddress,pos); pos+=2; data.copy(buffer,pos,0,data.length); pos+=data.length; var telexWithoutCRC=buffer.slice(0,buffer.length-1); var crc = ebus.calcEbusTelexCRC(telexWithoutCRC); buffer.writeUInt8(crc,pos); return buffer; }, EbusTelexSOT:{ NONE:0, STX:2, ACK:6, NAK:0x15, CAN:0x18, WAIT:0xE1 }, //Ermittelt aus einem byte-Array das nächste Telex, oder eine Ein-Byte-Telex-Antwort //Liefert detectEbusTelexFromBuffer:(telexbuffer)=>{ //console.log("Eval",telexbuffer); if(!Buffer.isBuffer(telexbuffer) || telexbuffer.length===0) return null; var telex={ id:new Date(), stx:ebus.EbusTelexSOT.NONE, lot:0, to:0, from:0, data:null, error:null, bufferBefore:Buffer.allocUnsafe(0), bufferAfter:Buffer.allocUnsafe(0), raw:Buffer.allocUnsafe(0), getClassid:()=>{ } }; var pos=0; if(Buffer.isBuffer(telexbuffer) && telexbuffer.length>0){ var bufferBefore=[]; //First byte var currentTelexByte=telexbuffer.readUInt8(0); var isAnswer=false; do{ switch(currentTelexByte){ case ebus.EbusTelexSOT.STX: case ebus.EbusTelexSOT.ACK: case ebus.EbusTelexSOT.NAK: case ebus.EbusTelexSOT.CAN: case ebus.EbusTelexSOT.WAIT: isAnswer=true; break; } if(isAnswer){ break; } else{ bufferBefore.push(currentTelexByte); telexbuffer=telexbuffer.slice(1,telexbuffer.length); } if(telexbuffer.length===0) break; //Next byte currentTelexByte=telexbuffer.readUInt8(0); }while(!isAnswer); telex.bufferBefore=Buffer.from(bufferBefore); if(!isAnswer) return null; telex.stx=currentTelexByte; //Check if this is a valid telex start if(telex.stx===ebus.EbusTelexSOT.STX){ //Ensure 8 bytes minimum length of a telex if(telexbuffer.length<8) return null; pos=1; //Get telex length telex.lot=telexbuffer[pos++]; //Ensure that all bytes of telex are available if((telexbuffer.length-2)<telex.lot){ return null; } //Verify checksum var telexCrc=telexbuffer[telex.lot+1]; var allTelexBytesWithoutChecksum=telexbuffer.slice(0,telex.lot+1); var checkCrc=ebus.calcEbusTelexCRC(allTelexBytesWithoutChecksum); if(telexCrc!=checkCrc){ telex.bufferAfter=telexbuffer.slice(telex.lot+2); telex.error="Telex checksum error"; return telex; } //Get telex content telex.to=telexbuffer.readUInt16BE(pos); pos+=2; telex.from=telexbuffer.readUInt16BE(pos); pos+=2; telex.data=telexbuffer.slice(pos,telex.lot+1); telex.raw=telexbuffer.slice(0,telex.lot+2); telex.bufferAfter=telexbuffer.slice(telex.lot+2); //console.log("TLX OK",telex); return telex; } else{ telex.raw=telexbuffer.slice(0,1); telex.bufferAfter=telexbuffer.slice(1); //console.log("TLX OK",telex); return telex; } } return null; }, TelexDetector:function(){ var _globalBuffer=Buffer.from([]); return{ _debugLog:false, log:function(...args){ if(this._debugLog) console.log(...args); }, getBuffer:function(){ return _globalBuffer; }, clearBuffer:function(){ _globalBuffer=[]; this.log("Closing"); }, detect:function(data,callback,done){ if(!Buffer.isBuffer(data)){ this.log("Data is no buffer!"); return; } //Concat buffer data var list=[]; list.push(_globalBuffer); list.push(Buffer.from(data)); _globalBuffer=Buffer.concat(list); var result=[]; var telex=ebus.detectEbusTelexFromBuffer(_globalBuffer); while(telex!==null){ this.log("Telex detected",telex); if(callback) callback(telex); _globalBuffer=Buffer.from(telex.bufferAfter); telex=ebus.detectEbusTelexFromBuffer(_globalBuffer); } if(done) done(); } } } } module.exports = ebus;