/// <summary> /// Send ESP3 frame to serial port associated to the EnOcean USB gateway /// /// The sender address must be in the range 00.00.00.00 and 00.00.00.7F because the EnOcean gateway can emulate 128 sender addresses from the Base_Id /// For example, if the Base_Id is FF.56.2A.80 and the sender address is 00.0.00.46, the resultant address is FF.56.2A.C6 /// </summary> private void SendToSerial(CancellationToken token) { string frame; while (!token.IsCancellationRequested) { try { while (udpToSerialQueue.TryDequeue(out frame)) { WriteError("Frame : " + frame); byte[] buffer = Tools.HexStringToByteArray(frame); WriteError("Buffer : " + Tools.ByteArrayToHexString(buffer)); int dataLength = Convert.ToInt32(frame.Substring(3, 5).Replace("-", ""), 16); WriteError("dataLength : " + dataLength.ToString()); buffer[6 + dataLength - 5] = gwBaseId[0]; buffer[7 + dataLength - 5] = gwBaseId[1]; buffer[8 + dataLength - 5] = gwBaseId[2]; buffer[9 + dataLength - 5] |= gwBaseId[3]; // Logical OR between the lower byte of the Base_Id and the lower byte of the sender address WriteError("Buffer : " + Tools.ByteArrayToHexString(buffer)); CRC8.SetAllCRC8(ref buffer); archiveQueue.Enqueue(DateTime.Now.MyDateTimeFormat() + " [TX] " + Tools.ByteArrayToHexString(buffer)); serialPort.Write(buffer, 0, buffer.Length); } } catch (Exception ex) { WriteError("SendToSerial Exception: " + ex.Message); System.ServiceProcess.ServiceController svc = new System.ServiceProcess.ServiceController("EnoGateway"); svc.Stop(); } System.Threading.Thread.Sleep(100); } WriteInfo(" Bye from task SendToSerial"); }
/// <summary> /// Receive bytes from the serial port associated to the EnOcean USB gateway and extract valid ESP3 frame /// </summary> /// <param name="sender"></param> /// <param name="e"></param> /// This code apply to EnOcean Serial Protocol 3.0 (ESP3) ESP3 Packet: ----Sync Byte ------------------------- /// ----Header----------------------------- /// As soon as a Sync-Byte (value 0x55) is identified, the subsequent -------Data Length -------------------- /// 4 byte-Header is compared with the corresponding CRC8H value. ------ Optional Data Length ----------- /// If the result is a match the Sync-Byte is correct. Consequently, -------Packet Type -------------------- /// the ESP3 packet is detected properly and the subsequent data will -------CRC8 Header -------------------- /// be passed. If the header does not match the CRC8H, the value 0x55 ----Data ------------------------------ /// does not correspond to a Sync-Byte. The next 0x55 withing the data ----Optional Data --------------------- /// stream is picked and the verification is repeated. ----CRC8 Data ------------------------- /// private void ReceiveFromSerial(CancellationToken token) { while (!token.IsCancellationRequested) { try { while (serialPort.BytesToRead > 0) { recBuffer[ptrBuffer] = (byte)serialPort.ReadByte(); // Read one byte if (ptrBuffer == 0 && recBuffer[ptrBuffer] != 0x55) { return; // Wait for the Sync Byte } if (ptrBuffer == 5) // Wait for the Header of the frame (6 bytes received) { if (CRC8.GetCRC8Header(recBuffer) != recBuffer[5]) // Bad CRC8H { ShiftRecBuffer(); // Shift left the header trying to find a new Sync Byte return; } } if (ptrBuffer >= 5) // CRC8H is Ok. Analyse the frame length { uint dataLength = recBuffer[1] * (uint)256 + recBuffer[2]; uint optionalDataLength = recBuffer[3]; if (ptrBuffer == (dataLength + optionalDataLength + 6)) // Wait for receiving the full frame { if (CRC8.GetCRC8Data(recBuffer, ptrBuffer) != recBuffer[ptrBuffer]) // Bad CRC8D { ShiftRecBuffer(); // Shift left the frame trying to find a new Sync Byte return; } byte[] frame = new byte[ptrBuffer + 1]; for (int i = 0; i < (ptrBuffer + 1); i++) { frame[i] = recBuffer[i]; recBuffer[i] = 0; } serialToUdpQueue.Enqueue(Tools.ByteArrayToHexString(frame)); ptrBuffer = 0; } else { ptrBuffer++; } } else { ptrBuffer++; } } } catch (Exception ex) { WriteError("ReceiveFromSerial Exception: " + ex.Message); System.ServiceProcess.ServiceController svc = new System.ServiceProcess.ServiceController("EnoGateway"); svc.Stop(); } System.Threading.Thread.Sleep(100); } WriteInfo(" Bye from task ReceiveFromSerial"); }