603 lines
25 KiB
C#
603 lines
25 KiB
C#
using System;
|
|
using System.IO.Ports;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using Xylem.Common.Utils.Crc16Ccitt;
|
|
using Xylem.Common.Utils.Logging;
|
|
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
|
|
using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments;
|
|
using NLog;
|
|
|
|
namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts
|
|
{
|
|
/// <inheritdoc />
|
|
public class RfidSerialPort : BaseSerialPort
|
|
{
|
|
/// <inheritdoc />
|
|
public override event EventHandler<BasePortDataEventArgs> OnRawRecordReceived;
|
|
|
|
private const Byte RfidFrameStartId = 0x01;
|
|
private const Byte RfidFrameTxLength = 0x12;
|
|
private const Byte RfidFrameRxLength = 0x0C;
|
|
private const Byte RfidFrameExpectedRxLength = 0x0A;
|
|
private const Byte RfidFramePayloadDataMarker = 0x7D;
|
|
private const Byte RfidRxModeMarker = 0x7E;
|
|
private const Byte RfidFramePollingByte = 0x03;
|
|
|
|
private const Int32 RfidRxStartSyncPosition = 0;
|
|
private const Int32 RfidRxLengthPosition = 1;
|
|
private const Int32 RfidRxModePosition = 4;
|
|
private const Int32 RfidRxDataPosition = 5;
|
|
private const Int32 RfidRxDataMarkerPosition = 11;
|
|
private const Int32 RfidRxCrcLowPosition = 12;
|
|
private const Int32 RfidRxCrcHighPosition = 13;
|
|
private const Int32 RfidRxBccPosition = 14;
|
|
private const Int32 RfidCommRetries = 4;
|
|
private const Int32 RfidStartPatternLength = 10;
|
|
//additional frame length for start, length and BCC added to frame length
|
|
//being in the length itself
|
|
private const Int32 RfidProtAddLength = 3;
|
|
private const Int32 RfidRxLength = RfidFrameRxLength + RfidProtAddLength;
|
|
private const Int32 RfidTxLength = RfidFrameTxLength + RfidProtAddLength;
|
|
|
|
//first byte is fixed to 0x7D (data mode) at the Tx or the last byte behind
|
|
//the payload at Rx, the others are from the device protocol (the payload),
|
|
//this byte needs to be included into the CRC calculation
|
|
private const Int32 RfidPayLoadLength = 7;
|
|
private const Int32 RfidRawPayLoadLength = 6;
|
|
|
|
//the raw payload to add to RFID transmit buffer, it has a start Id, a length position
|
|
//and some additional length needed to add to the raw Rx length
|
|
private Byte[] _rawTxPayLoad;
|
|
private Int32 _rawRxLength;
|
|
private Byte[] _rawRxPayLoad;
|
|
|
|
|
|
//create RFID payload
|
|
private Byte[] _rfidTxPayLoad;
|
|
private Int32 _payLoadTxCounterPosition;
|
|
private Int32 _payLoadRxCounterPosition;
|
|
//remind send state
|
|
private Boolean _txIsActive;
|
|
//marker for first protocol containing the start id and the length
|
|
private Boolean _waitRawStartSyncPattern;
|
|
//this is the RFID raw buffer being sent to the serial port
|
|
private Byte[] _rfidTxBuffer = new Byte[RfidTxLength];
|
|
private Byte[] _rfidRxBuffer = new Byte[RfidRxLength];
|
|
private Int32 _rfidCommRetryCounter = RfidCommRetries;
|
|
private RfidRxState _rfidRxState;
|
|
|
|
private readonly ILogger _logger;
|
|
|
|
//communication counter for debug for application layer
|
|
private Int32 _commCounter;
|
|
|
|
/// <inheritdoc />
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public RfidSerialPort(String ident, SerialPort serialPort, TransmitPortSettings setting)
|
|
: base(ident, serialPort, setting)
|
|
{
|
|
_logger = NLogHelper.CreateOrGetMultiLogger(ident, "", "RfidSerialPort", "COMBase", "BaseSerialPort");
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Not needed and therefor deactivated by overwriting
|
|
/// </remarks>
|
|
public override void PhysicalDataReceived(Object sender, SerialDataReceivedEventArgs e)
|
|
{
|
|
//remove registration of delegate
|
|
GetBaseComport().DataReceived -= PhysicalDataReceived;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
/// <summary>
|
|
/// Overwritten routine, kicks off the first communication,
|
|
/// handles the communication state machine
|
|
/// </summary>
|
|
/// <param name="tx"></param>
|
|
/// <remarks date="2017-Dec-15" author="R.Drabesch">
|
|
/// - Not needed and therefor deactivated by overwriting
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-17" author="T.Wiedebusch">
|
|
/// - communication scheduler removed, call directly the stats machine
|
|
/// </remarks>
|
|
/// <remarks date="2019-Apr-11" author="T.Wiedebusch">
|
|
/// - Hide data in logging for e.g. passwords
|
|
/// </remarks>
|
|
protected override void SpecificPortWrite(Byte[] tx)
|
|
{
|
|
//raw protocol before wrapped into RFID
|
|
SendDataViaRfid(tx);
|
|
|
|
RfidRxState rfidState;
|
|
|
|
//call state machine until ready
|
|
do
|
|
{
|
|
rfidState = RfidCommStateMachine();
|
|
|
|
} while (RfidRxState.CommunicationFinished != rfidState &&
|
|
RfidRxState.CommunicationFailed != rfidState);
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Send data via RFID
|
|
/// </summary>
|
|
/// <param name="data">data to be transferred via RFID</param>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-15" author="T.Wiedebusch">
|
|
/// - Receive size removed, will be automatically extracted from underlay-protocol (raw)
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-17" author="T.Wiedebusch">
|
|
/// - Raw buffer increased to communication retries * raw packet size.
|
|
/// </remarks>
|
|
public void SendDataViaRfid(Byte[] data)
|
|
{
|
|
if (data.Length < RfidRawPayLoadLength) return;
|
|
//length is unknown before receiving the first raw data, setup to x packets size for
|
|
//receive routine
|
|
_rawRxLength = RfidRawPayLoadLength * _rfidCommRetryCounter;
|
|
_rawRxPayLoad = new Byte[_rawRxLength];
|
|
_waitRawStartSyncPattern = true;
|
|
//start with sending of data
|
|
_txIsActive = true;
|
|
//allow retries during communication
|
|
_rfidCommRetryCounter = RfidCommRetries;
|
|
//reset running counters
|
|
_payLoadTxCounterPosition = 0;
|
|
_payLoadRxCounterPosition = 0;
|
|
_commCounter = 0;
|
|
|
|
//copy part of the huge payload buffer (containing the entire data) to small
|
|
//6 byte chunks being able to transmit within one RFID communication
|
|
_rfidTxPayLoad = null;
|
|
_rfidTxPayLoad = new Byte[RfidRawPayLoadLength];
|
|
_rawTxPayLoad = new Byte[data.Length];
|
|
_rawTxPayLoad = data;
|
|
for (var i = 0; i < RfidRawPayLoadLength; i++)
|
|
{
|
|
_rfidTxPayLoad[i] = _rawTxPayLoad[_payLoadTxCounterPosition];
|
|
_payLoadTxCounterPosition++;
|
|
}
|
|
//assemble the RFID transmit buffer
|
|
PrepareRfidTxBuffer(ref _rfidTxBuffer, _rfidTxPayLoad);
|
|
//kick off first communication
|
|
_rfidRxState = RfidComm(ref _rfidRxBuffer, _rfidTxBuffer);
|
|
}
|
|
/// <summary>
|
|
/// RFID Tx buffer content
|
|
/// </summary>
|
|
/// <returns>array of RFID Tx buffer content</returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Byte[] GetRfidTxBuffer()
|
|
{
|
|
return _rfidTxBuffer;
|
|
}
|
|
/// <summary>
|
|
/// RFID Rx buffer content
|
|
/// </summary>
|
|
/// <returns>array of RFID Rx buffer content</returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Byte[] GetRfidRxBuffer()
|
|
{
|
|
return _rfidRxBuffer;
|
|
}
|
|
|
|
/// <summary>
|
|
/// read out the received data from RFID
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Byte[] GetDecodedDataFromRfid()
|
|
{
|
|
return _rawRxPayLoad;
|
|
}
|
|
/// <summary>
|
|
/// feedback of communication counter
|
|
/// </summary>
|
|
/// <returns>number of RFID communications</returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Int32 GetRfidComCounter()
|
|
{
|
|
return _commCounter;
|
|
}
|
|
|
|
/// <summary>
|
|
/// communication state machine
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-15" author="T.Wiedebusch">
|
|
/// - Extract length information from raw protocol
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-17" author="T.Wiedebusch">
|
|
/// - Return of communication failed on missing start sync pattern of raw protocol
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-19" author="T.Wiedebusch">
|
|
/// - New modes implemented to differ between sending / waiting for Rx start
|
|
/// and receiving
|
|
/// </remarks>
|
|
/// <remarks date="2018-Feb-21" author="T.Wiedebusch">
|
|
/// - Time stamp added
|
|
/// </remarks>
|
|
/// <remarks date="2019-Apr-12" author="T.Wiedebusch">
|
|
/// - Hide data in logging for e.g. passwords
|
|
/// </remarks>
|
|
public RfidRxState RfidCommStateMachine()
|
|
{
|
|
//check the receive status
|
|
switch (_rfidRxState)
|
|
{
|
|
case RfidRxState.EchoRxProtocolOk:
|
|
//clear payload buffer to force filling with polling pattern
|
|
_rfidTxPayLoad = null;
|
|
//send loop
|
|
if (_txIsActive)
|
|
{
|
|
if (_payLoadTxCounterPosition < _rawTxPayLoad.Length)
|
|
{
|
|
//assign new Tx buffer
|
|
Int32 arraySize;
|
|
if (_payLoadTxCounterPosition + RfidRawPayLoadLength <
|
|
_rawTxPayLoad.Length)
|
|
arraySize = RfidRawPayLoadLength;
|
|
else
|
|
arraySize = _rawTxPayLoad.Length - _payLoadTxCounterPosition;
|
|
_rfidTxPayLoad = new Byte[arraySize];
|
|
//fill payload buffer with remaining payload bytes
|
|
for (var i = 0; i < arraySize; i++)
|
|
{
|
|
if (_payLoadTxCounterPosition >= _rawTxPayLoad.Length) continue;
|
|
_rfidTxPayLoad[i] = _rawTxPayLoad[_payLoadTxCounterPosition];
|
|
_payLoadTxCounterPosition++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//switch receive loop active
|
|
_txIsActive = false;
|
|
}
|
|
}
|
|
//reset retry counter
|
|
_rfidCommRetryCounter = RfidCommRetries;
|
|
//assemble new RFID transmit buffer
|
|
PrepareRfidTxBuffer(ref _rfidTxBuffer, _rfidTxPayLoad);
|
|
//start communication
|
|
_rfidRxState = RfidComm(ref _rfidRxBuffer, _rfidTxBuffer);
|
|
break;
|
|
|
|
case RfidRxState.DataRxProtocolOk:
|
|
//receive loop with polling pattern sending
|
|
for (var i = 0; i < RfidRawPayLoadLength; i++)
|
|
{
|
|
//avoid out of bounce access
|
|
if (_payLoadRxCounterPosition >= _rawRxLength) continue;
|
|
_rawRxPayLoad[_payLoadRxCounterPosition] =
|
|
_rfidRxBuffer[i + RfidRxDataPosition];
|
|
_payLoadRxCounterPosition++;
|
|
}
|
|
//check for entire message received
|
|
if (_payLoadRxCounterPosition >= _rawRxLength)
|
|
{
|
|
//assign time stamp of received record
|
|
var readDateTimePc = DateTimeOffset.UtcNow;
|
|
|
|
//communication finished, return data to caller
|
|
//RawRecordReceived(this, _rawRxPayLoad, readDateTimePc);
|
|
var byteList = _rawRxPayLoad.ToList();
|
|
OnRawRecordReceived?.Invoke(this, new ListBytePortDataEventArgs(byteList, readDateTimePc));
|
|
|
|
//log the RFID payload, RFID protocol is removed
|
|
//_logger.Trace($"{Ident} Read({BitConverter.ToString(_rawRxPayLoad)})");
|
|
|
|
return _waitRawStartSyncPattern ? RfidRxState.CommunicationFailed :
|
|
RfidRxState.CommunicationFinished;
|
|
}
|
|
//reset retry counter
|
|
_rfidCommRetryCounter = RfidCommRetries;
|
|
//start communication with polling pattern, has been assembled in last send run
|
|
_rfidRxState = RfidComm(ref _rfidRxBuffer, _rfidTxBuffer);
|
|
break;
|
|
|
|
case RfidRxState.Idle:
|
|
break;
|
|
|
|
default:
|
|
//RFID or device is not ready or protocol error, start retry
|
|
if (_rfidCommRetryCounter > 0)
|
|
{
|
|
_logger.Trace($"{Ident} Internal RFID retry");
|
|
_rfidCommRetryCounter--;
|
|
|
|
//send the same RFID message again
|
|
_rfidRxState = RfidComm(ref _rfidRxBuffer, _rfidTxBuffer);
|
|
}
|
|
else
|
|
{
|
|
//communication failed because of exceeded internal RFID retry counter
|
|
_rfidRxState = RfidRxState.CommunicationFailed;
|
|
_logger.Trace($"{Ident} Internal RFID communication failed, RFID retry counter exceeded");
|
|
}
|
|
break;
|
|
}
|
|
return _rfidRxState;
|
|
}
|
|
/// <summary>
|
|
/// send and receive
|
|
/// </summary>
|
|
/// <param name="rxBuffer"></param>
|
|
/// <param name="txBuffer"></param>
|
|
/// <returns>RfidRxState</returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-18" author="T.Wiedebusch">
|
|
/// - Communication timeout activated.
|
|
/// </remarks>
|
|
/// <remarks date="2019-Apr-12" author="T.Wiedebusch">
|
|
/// - Hide data in logging for e.g. passwords
|
|
/// </remarks>
|
|
private RfidRxState RfidComm(ref Byte[] rxBuffer, Byte[] txBuffer)
|
|
{
|
|
var rfidRxState = RfidRxState.CommPortError;
|
|
|
|
if (!IsOpen()) return rfidRxState;
|
|
|
|
Clear();
|
|
//_logger.Trace($"{Ident} RFID raw sent({BitConverter.ToString(txBuffer)})");
|
|
PhysicalWrite(txBuffer);
|
|
_commCounter++;
|
|
//set timeout for receive exit, take 5 records of 6 byte chunks as base
|
|
var commTimeoutMs = PortSettingsForTransmitProtocol.ResponseTimeoutMs / 5;
|
|
while (commTimeoutMs > 0 && BytesToRead() < RfidRxLength)
|
|
{
|
|
Thread.Sleep(1);
|
|
commTimeoutMs--;
|
|
}
|
|
var i = 0;
|
|
//test if something is in input buffer
|
|
if (RfidRxLength > BytesToRead())
|
|
{
|
|
_logger.Trace($"{Ident} Internal RFID read timeout({PortSettingsForTransmitProtocol.ResponseTimeoutMs}ms)");
|
|
return RfidRxState.RxTimeout;
|
|
}
|
|
while (BytesToRead() > 0 && i < RfidRxLength)
|
|
{
|
|
rxBuffer[i] = (Byte)ReadByte();
|
|
i++;
|
|
}
|
|
if (i != RfidRxLength) return rfidRxState;
|
|
|
|
//all expected bytes received
|
|
//_logger.Trace($"{Ident} RFID raw read({BitConverter.ToString(rxBuffer)})");
|
|
rfidRxState = CheckRfidRxBuffer(rxBuffer);
|
|
|
|
return rfidRxState;
|
|
}
|
|
/// <summary>
|
|
/// check the received buffer CRC, BCC and
|
|
/// </summary>
|
|
/// <param name="rfidRxBuffer"></param>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2017-Dec-19" author="T.Wiedebusch">
|
|
/// - New modes implemented to differ between sending / waiting for Rx start
|
|
/// and receiving
|
|
/// </remarks>
|
|
/// <returns>RfidRxState</returns>
|
|
private RfidRxState CheckRfidRxBuffer(Byte[] rfidRxBuffer)
|
|
{
|
|
//retry required by start sync error
|
|
if (RfidFrameStartId != rfidRxBuffer[RfidRxStartSyncPosition])
|
|
return RfidRxState.StartSyncError;
|
|
//retry required by length error
|
|
if (RfidFrameRxLength != rfidRxBuffer[RfidRxLengthPosition])
|
|
return RfidRxState.LengthError;
|
|
|
|
//data marked as useful data
|
|
if (RfidRxModeMarker != rfidRxBuffer[RfidRxModePosition] ||
|
|
RfidFramePayloadDataMarker != rfidRxBuffer[RfidRxDataMarkerPosition])
|
|
return RfidRxState.RetryRequired;
|
|
//BCC check transfer entire receive buffer, this will automatically handled
|
|
if (rfidRxBuffer[RfidRxBccPosition] != BuildRfidBcc(rfidRxBuffer))
|
|
return RfidRxState.BccError;
|
|
|
|
//extract the 6 data (payload) bytes and the data frame marker
|
|
var testBuffer = new Byte[RfidPayLoadLength];
|
|
for (var i = 0; i < RfidPayLoadLength; i++)
|
|
testBuffer[i] = rfidRxBuffer[i + RfidRxDataPosition];
|
|
//CRC with LSB first
|
|
var buildCrc = Crc16Ccitt.CalculateLsb0408(testBuffer);
|
|
UInt16 receivedCrc = rfidRxBuffer[RfidRxCrcHighPosition];
|
|
receivedCrc <<= 8;
|
|
receivedCrc &= 0xFF00;
|
|
receivedCrc += rfidRxBuffer[RfidRxCrcLowPosition];
|
|
if (receivedCrc != buildCrc) return RfidRxState.DataCrcError;
|
|
//send loop is active
|
|
if (_txIsActive) return RfidRxState.EchoRxProtocolOk;
|
|
//if the start sync byte has been detected the normal receive mode is active
|
|
if (!_waitRawStartSyncPattern) return RfidRxState.DataRxProtocolOk;
|
|
//search for raw protocol start sync Id to extract length information,
|
|
//if start Id hasn't been found the wait for Rx start mode is active
|
|
//forcing the retry loop being active (default switch)
|
|
if (PortSettingsForTransmitProtocol.ProtSyncByte != _rfidRxBuffer[RfidRxDataPosition])
|
|
return RfidRxState.WaitRxStartProtocolOk;
|
|
//here the Rx mode is going to be activated, first data received including
|
|
//start sync Id and length information
|
|
_waitRawStartSyncPattern = false;
|
|
_rawRxLength = _rfidRxBuffer[RfidRxDataPosition +
|
|
(PortSettingsForTransmitProtocol.ProtLengthIndex.HasValue ?
|
|
PortSettingsForTransmitProtocol.ProtLengthIndex.Value : 0)] +
|
|
PortSettingsForTransmitProtocol.ProtAddLength;
|
|
_rawRxPayLoad = new Byte[_rawRxLength];
|
|
return RfidRxState.DataRxProtocolOk;
|
|
}
|
|
/// <summary>
|
|
/// assemble the RFID transmit buffer as bytes
|
|
/// </summary>
|
|
/// <param name="rfidTxBuffer"></param>
|
|
/// <param name="payLoad"></param>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private static void PrepareRfidTxBuffer(ref Byte[] rfidTxBuffer, Byte[] payLoad)
|
|
{
|
|
RfidTxProtocol rfidTxStruct;
|
|
rfidTxStruct.StartPattern = new Byte[]
|
|
{
|
|
RfidFrameStartId, //start identifier 0x01
|
|
RfidFrameTxLength, //length, start behind length without BCC
|
|
0xE8, 0x90, 0x00, //CMD 1, 2, 3
|
|
0x00, 0x32, 0x00, 0x11, //Power 1 and 2
|
|
0x48 //TX bits
|
|
};
|
|
//the default data is the polling pattern 0x03
|
|
rfidTxStruct.PayLoad = new[] { RfidFramePayloadDataMarker,
|
|
RfidFramePollingByte, RfidFramePollingByte, RfidFramePollingByte,
|
|
RfidFramePollingByte, RfidFramePollingByte, RfidFramePollingByte};
|
|
|
|
//fill the payload with real data
|
|
var i = 0;
|
|
if (payLoad != null)
|
|
{
|
|
//put payload behind RFID frame payload data marker
|
|
for (; i < payLoad.Length; i++)
|
|
rfidTxStruct.PayLoad[i + 1] = payLoad[i];
|
|
}
|
|
rfidTxStruct.ExpectedRxBytes = RfidFrameExpectedRxLength;
|
|
|
|
//fill transmit buffer with constant start pattern for RFID communication
|
|
i = 0;
|
|
for (; i < RfidStartPatternLength; i++)
|
|
{
|
|
rfidTxBuffer[i] = rfidTxStruct.StartPattern[i];
|
|
}
|
|
//add payload to buffer, first byte is constant 0x7D (data mode)
|
|
var c = 0;
|
|
for (; i < RfidStartPatternLength + RfidPayLoadLength; i++)
|
|
{
|
|
rfidTxBuffer[i] = rfidTxStruct.PayLoad[c];
|
|
c++;
|
|
}
|
|
//add data CRC, LSB first
|
|
rfidTxStruct.DataCrc = Crc16Ccitt.CalculateLsb0408(rfidTxStruct.PayLoad);
|
|
rfidTxBuffer[i] = (Byte)(rfidTxStruct.DataCrc & 0xFF);
|
|
i++;
|
|
rfidTxBuffer[i] = (Byte)((rfidTxStruct.DataCrc & 0xFF00) >> 8);
|
|
//add expected receive bytes
|
|
i++;
|
|
rfidTxBuffer[i] = rfidTxStruct.ExpectedRxBytes;
|
|
//add BCC
|
|
rfidTxStruct.Bcc = BuildRfidBcc(rfidTxBuffer);
|
|
i++;
|
|
rfidTxBuffer[i] = rfidTxStruct.Bcc;
|
|
}
|
|
|
|
/// <summary>
|
|
/// build simple byte by byte XOR'ed checksum called BCC for RFID
|
|
/// </summary>
|
|
/// <param name="rfidRawBuffer"></param>
|
|
/// <returns>BCC code</returns>
|
|
/// <remarks date="2017-Dec-14" author="T.Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private static Byte BuildRfidBcc(Byte[] rfidRawBuffer)
|
|
{
|
|
//remove the "start byte" and the BCC itself
|
|
var maxCounts = rfidRawBuffer.Length - 1;
|
|
//start behind the "start byte"
|
|
var i = 1;
|
|
Byte bcc = rfidRawBuffer[i];
|
|
//take the second value
|
|
i++;
|
|
for (; i < maxCounts; i++)
|
|
{
|
|
bcc ^= rfidRawBuffer[i];
|
|
}
|
|
return bcc;
|
|
}
|
|
|
|
private struct RfidTxProtocol
|
|
{
|
|
public Byte[] StartPattern;
|
|
public Byte[] PayLoad;
|
|
public UInt16 DataCrc;
|
|
public Byte ExpectedRxBytes;
|
|
public Byte Bcc;
|
|
}
|
|
}
|
|
|
|
public enum RfidRxState
|
|
{
|
|
/// <summary>
|
|
/// No communication is ongoing
|
|
/// </summary>
|
|
Idle,
|
|
/// <summary>
|
|
/// Echo of sent protocol is received successfully back
|
|
/// </summary>
|
|
EchoRxProtocolOk,
|
|
/// <summary>
|
|
/// Waiting for switch from transmitting to receiving
|
|
/// </summary>
|
|
WaitRxStartProtocolOk,
|
|
/// <summary>
|
|
/// Received data message is valid
|
|
/// </summary>
|
|
DataRxProtocolOk,
|
|
/// <summary>
|
|
/// Communication port assignment error
|
|
/// </summary>
|
|
CommPortError,
|
|
/// <summary>
|
|
/// Start of synchronization error
|
|
/// </summary>
|
|
StartSyncError,
|
|
/// <summary>
|
|
/// Length error
|
|
/// </summary>
|
|
LengthError,
|
|
/// <summary>
|
|
/// Retry required
|
|
/// </summary>
|
|
RetryRequired,
|
|
/// <summary>
|
|
/// CRC error of data in payload field
|
|
/// </summary>
|
|
DataCrcError,
|
|
/// <summary>
|
|
/// BCC (special checksum) error of RFID
|
|
/// </summary>
|
|
BccError,
|
|
/// <summary>
|
|
/// Receive timeout
|
|
/// </summary>
|
|
RxTimeout,
|
|
/// <summary>
|
|
/// Communication to RFID failed, record cannot be assembled
|
|
/// </summary>
|
|
CommunicationFailed,
|
|
/// <summary>
|
|
/// Communication to RFID successfully executed
|
|
/// </summary>
|
|
CommunicationFinished
|
|
}
|
|
}
|