using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using SlnMesnac.Common; using SlnMesnac.Model.dto; using SlnMesnac.Rfid.Dto; using SlnMesnac.Rfid.Enum; using TouchSocket.Core; using TouchSocket.Sockets; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- * 版权所有 (c) 2024 WenJY 保留所有权利。 * CLR版本:4.0.30319.42000 * 机器名称:LAPTOP-E0N2L34V * 命名空间:SlnMesnac.Rfid.Factory * 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82 * * 创建者:WenJY * 电子邮箱:wenjy@mesnac.com * 创建时间:2024-03-27 21:58:35 * 版本:V1.0.0 * 描述: * *-------------------------------------------------------------------- * 修改人: * 时间: * 修改说明: * * 版本:V1.0.0 *--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> namespace SlnMesnac.Rfid.Factory { public class RflyFactory:RfidAbsractFactory { private ILogger _logger; public readonly TcpClient _tcpClient = new TcpClient(); private readonly StringChange _stringChange; public RflyFactory(ILogger logger,StringChange stringChange) { _logger = logger; _stringChange = stringChange; } /// /// 建立连接 /// /// /// /// /// public override bool Connect(string ip, int port) { try { _tcpClient.Setup(new TouchSocketConfig().SetRemoteIPHost($"{ip}:{port}")); _tcpClient.Connect(); return true; } catch (Exception e) { _logger.LogError($"RFID设备{ip}连接异常:{e.Message}"); return false; } } /// /// 按时间段盘点 /// /// /// /// public override List TimePeriodRead(int timeout = 5000) { byte[] u16byte = new byte[2]; byte[] bCRC = new byte[4]; try { #region 指令封装 MessagePack pMessagePack = new MessagePack(); pMessagePack.m_pData = new byte[8]; pMessagePack.m_pData[0] = 0xAA; pMessagePack.m_pData[1] = 0x55; pMessagePack.m_pData[2] = 0x02; pMessagePack.m_pData[3] = 0x02; u16byte = BitConverter.GetBytes(timeout); //超时时间 u16byte = _stringChange.Swap16Bytes(u16byte); //协议里为大端在前 Array.Copy(u16byte, 0, pMessagePack.m_pData, 4, 2); Array.Copy(pMessagePack.m_pData, 2, bCRC, 0, 4); pMessagePack.m_pData[6] = _stringChange.CalculateVerify(bCRC, bCRC.Length); pMessagePack.m_pData[7] = 0x0D; #endregion var waitClient = _tcpClient.CreateWaitingClient(new WaitingOptions() { FilterFunc = response => { return true; } }); byte[] reciveBuffer = waitClient.SendThenReturn(pMessagePack.m_pData, timeout); _logger.LogInformation($"接收原始报文:{_stringChange.bytesToHexStr(reciveBuffer,reciveBuffer.Length)}"); byte[] resultBuffer = PareReceiveBufferData(reciveBuffer,reciveBuffer.Length); List tagInfoList = Device_DealTagInfoList(resultBuffer); return tagInfoList; } catch (Exception e) { throw new InvalidOperationException($"按时间段盘点异常:{e.Message}"); } } /// /// 异步按时间段盘点 /// /// /// /// public override async Task> GetRFIDAsync(int timeout = 5000) { byte[] u16byte = new byte[2]; byte[] bCRC = new byte[4]; try { #region 指令封装 MessagePack pMessagePack = new MessagePack(); pMessagePack.m_pData = new byte[8]; pMessagePack.m_pData[0] = 0xAA; pMessagePack.m_pData[1] = 0x55; pMessagePack.m_pData[2] = 0x02; pMessagePack.m_pData[3] = 0x02; u16byte = BitConverter.GetBytes(timeout); //超时时间 u16byte = _stringChange.Swap16Bytes(u16byte); //协议里为大端在前 Array.Copy(u16byte, 0, pMessagePack.m_pData, 4, 2); Array.Copy(pMessagePack.m_pData, 2, bCRC, 0, 4); pMessagePack.m_pData[6] = _stringChange.CalculateVerify(bCRC, bCRC.Length); pMessagePack.m_pData[7] = 0x0D; #endregion var waitClient = _tcpClient.CreateWaitingClient(new WaitingOptions() { FilterFunc = response => { return true; } }); byte[] reciveBuffer =await waitClient.SendThenReturnAsync(pMessagePack.m_pData, timeout); _logger.LogInformation($"接收原始报文:{_stringChange.bytesToHexStr(reciveBuffer, reciveBuffer.Length)}"); byte[] resultBuffer = PareReceiveBufferData(reciveBuffer, reciveBuffer.Length); List tagInfoList = Device_DealTagInfoList(resultBuffer); return tagInfoList; } catch (Exception e) { throw new InvalidOperationException($"按时间段盘点异常:{e.Message}"); } } #region 标签解析 /// /// 状态机函数 /// /// /// /// /// private byte[] PareReceiveBufferData(byte[] buffer, int iLen) { RecvState enumRecvState = RecvState.WaitingBeginChar1_State; int m_iPosition = 0; UInt16 m_iFullMessageLength = 0; int iBarcodeLength = 0;//条码长度 ArrayList m_FrecvData = new ArrayList(); byte m_iVerify = 0; try { var bufferStr = _stringChange.bytesToHexStr(buffer, iLen); byte[] m_szFullMessage = new byte[iLen]; for (int i = 0; i < iLen; i++) { switch (enumRecvState) { case RecvState.WaitingBeginChar1_State: //开始接受数据帧1 0xBB Array.Clear(m_szFullMessage, 0, iLen);//清空为0 if (buffer[i] == 0xBB) { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; enumRecvState = RecvState.WaitingBeginChar2_State; } else { m_iFullMessageLength = 0; m_iPosition = 0; enumRecvState = RecvState.WaitingBeginChar1_State; } break; case RecvState.WaitingBeginChar2_State: //开始接受数据帧1 0xDD if (buffer[i] == 0xDD) { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; enumRecvState = RecvState.WaitingForBarcodeLength_State; } else { m_iFullMessageLength = 0; m_iPosition = 0; enumRecvState = RecvState.WaitingBeginChar1_State; } break; case RecvState.WaitingForBarcodeLength_State: //开始接受数据长度(TagCount - EPC) m_szFullMessage[m_iPosition] = buffer[i]; iBarcodeLength = buffer[i]; //单组标签:18;两组标签:35 m_iPosition++; enumRecvState = RecvState.WaitingForCode_State; break; case RecvState.WaitingForCode_State: //开始接受指令编号 if (buffer[i] == 0x02) { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; enumRecvState = RecvState.WaitingForStus_State; } else if (buffer[i] == 0x90) // 如果是心跳BB DD 01 90 00 1F 8E 0D { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; enumRecvState = RecvState.WaitingForEndChar_State; } else if (buffer[i] == 0xBF) // 如果是心跳BB DD 04 BF 00 00 00 F9 0B 49 0D { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; enumRecvState = RecvState.WaitingForEndChar_State; } else { m_iFullMessageLength = 0; m_iPosition = 0; enumRecvState = RecvState.WaitingBeginChar1_State; } break; case RecvState.WaitingForStus_State: //开始接受状态码 if (buffer[i] == 0x00) { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; enumRecvState = RecvState.WaitingForTagCount_State; } else if (buffer[i] == 0x40) { m_szFullMessage[m_iPosition] = buffer[i]; //LogService.Instance.Debug("RFU620等待接受WaitingForEndChar_State:Noread"); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_iPosition = 0; i = iLen; enumRecvState = RecvState.WaitingBeginChar1_State; //LogService.Instance.Debug("RFly-I160状态机结束。"); } break; case RecvState.WaitingForTagCount_State: //开始接受标签组数 Array.Copy(buffer, i, m_szFullMessage, m_iPosition, iBarcodeLength);//m_iPosition = 5 byte[] tempData = new byte[iBarcodeLength]; Array.Clear(tempData, 0, iBarcodeLength); Array.Copy(buffer, i, tempData, 0, iBarcodeLength); m_iPosition = m_iPosition + iBarcodeLength; //m_iPosition = 39 i = i + iBarcodeLength - 1; //i = 39 enumRecvState = RecvState.WaitingForXor_State; break; case RecvState.WaitingForXor_State: //开始比对校验位 Rfly160 byte[] m_CRCVerify = new byte[1024]; //此数组用于校验位计算 Array.Clear(m_CRCVerify, 0, m_CRCVerify.Length); Array.Copy(m_szFullMessage, 2, m_CRCVerify, 0, iBarcodeLength + 3); //校验位计算是从Length - EPC 结束 m_szFullMessage[m_iPosition] = buffer[i]; m_iVerify = m_szFullMessage[m_iPosition]; if (m_iVerify == _stringChange.CalculateVerify(m_CRCVerify, m_CRCVerify.Length)) { m_iPosition++; enumRecvState = RecvState.WaitingForEndChar_State; } else //如果校验不成功 { m_iFullMessageLength = 0; m_iPosition = 0; enumRecvState = RecvState.WaitingBeginChar1_State; } break; case RecvState.WaitingForEndChar_State: if (buffer[0] == 0xBB && buffer[1] == 0xDD && buffer[2] == 0x00 && buffer[3] != 0x90) //此处为Noread数据显示 { m_szFullMessage[0] = 0xBB; m_szFullMessage[1] = 0xDD; m_szFullMessage[2] = 0x00; lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_iPosition = 0; i = iLen; enumRecvState = RecvState.WaitingBeginChar1_State; } else if (buffer[0] == 0xBB && buffer[1] == 0xDD && buffer[2] == 0x04 && buffer[3] == 0xBF) { Array.Copy(buffer, 0, m_szFullMessage, 0, 11); i = 11; lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } i = iLen; } else if (buffer[i] == 0x00) //获取温度 { Array.Copy(buffer, 0, m_szFullMessage, 0, 8); i = 8; lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } i = iLen; } else if (buffer[i] == 0x11) { Array.Copy(buffer, 0, m_szFullMessage, 0, 7); i = 7; lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } } else if (buffer[i] == 0x01) { Array.Copy(buffer, 0, m_szFullMessage, 0, 8); i = 8; lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } } else { m_szFullMessage[m_iPosition] = buffer[i]; m_iPosition++; if (buffer[i] == 0x0D) { lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } } } m_iPosition = 0; enumRecvState = RecvState.WaitingBeginChar1_State; break; } } return m_szFullMessage; } catch (Exception e) { throw new InvalidOperationException($"状态机逻辑处理异常:{e.Message}"); } } private Mutex mutauto = new Mutex(); /// /// 解析函数 /// /// /// /// public List Device_DealTagInfoList(byte[] AutoDealReportData) { List tagInfoList = new List(); byte[] bResultEPC_Data = new byte[14]; byte[] m_AutoReadEPC = null; int m_readEPCDataLen = 0; try { mutauto.WaitOne(); int iFirstCountPos = 6; //第一次读取标签次数位置 int iFirstRSSIPos = 7; //第一次读取标签强度位置 int iFirstAnt = 8; int iFirstPC = 9; //第一次读取标签天线位置 int iFirstLeftBarcketPos = 11;//EPC数据起始位置 UInt16 tempDataCount = 0; int tempDataRSSI = 0; UInt16 tempDataANT = 0; int iBarcodeGroupCount = Convert.ToInt32(AutoDealReportData[5].ToString()); //标签组数 int iBarcodeLength = 16; //标签长度 int iCommonSecondFlag = 0; for (int j = 0; j < iBarcodeGroupCount; j++) { TagInfo tag = new TagInfo(); byte[] tempPCByte = new byte[2]; //取出PC Array.Clear(tempPCByte, 0, 2); Array.Copy(AutoDealReportData, iFirstPC, tempPCByte, 0, 2); int pc = Convert.ToInt32(tempPCByte[0].ToString("X")); int epcLength = EPCLengthByPC(pc); iBarcodeLength = epcLength; byte[] tempDataByte = new byte[epcLength]; Array.Clear(tempDataByte, 0, iBarcodeLength); Array.Copy(AutoDealReportData, iFirstLeftBarcketPos, tempDataByte, 0, iBarcodeLength); byte[] tempCountByte = new byte[1]; //取出标签次数 Array.Clear(tempCountByte, 0, 1); Array.Copy(AutoDealReportData, iFirstCountPos, tempCountByte, 0, 1); tempDataCount = tempCountByte[0]; byte[] tempRSSIByte = new byte[1]; //取出标签强度 Array.Clear(tempRSSIByte, 0, 1); Array.Copy(AutoDealReportData, iFirstRSSIPos, tempRSSIByte, 0, 1); tempDataRSSI = _stringChange.HexStringToNegative(_stringChange.bytesToHexStr(tempRSSIByte, 1)); #region add by wenjy 20220829 取出天线号 byte[] tempAntByte = new byte[1]; //取出天线号 Array.Clear(tempAntByte, 0, 1); Array.Copy(AutoDealReportData, iFirstAnt, tempAntByte, 0, 1); tempDataANT = tempAntByte[0]; #endregion tag.Count = tempDataCount; tag.RSSI = tempDataRSSI; tag.EPC = tempDataByte; if (pc == 24) { tag.EPCstring = _stringChange.bytesToHexStr(tempDataByte, tempDataByte.Length).Substring(0, 7); } else { tag.EPCstring = Encoding.ASCII.GetString(tempDataByte); } tag.PC = tempPCByte; tag.Antana = tempDataANT; tagInfoList.Add(tag); int iBarcodeListLen = tagInfoList.Count; //特别注意,必须这样,要不然会多一条数据 iFirstCountPos = iFirstCountPos + iBarcodeLength + 5; //次数 iFirstRSSIPos = iFirstCountPos + 1; //强度 iFirstAnt = iFirstRSSIPos + 1; //天线 iFirstPC = iFirstAnt + 1; iFirstLeftBarcketPos = iFirstLeftBarcketPos + iBarcodeLength + 5; _logger.LogInformation("----函数调用:Device_DealTagInfoList 第[" + (iCommonSecondFlag + 1) + "]次数据解析为:" + tag.EPCstring + ",读取标签次数:[" + tempDataCount + "],标签信号强度:[" + tempDataRSSI + "],天线号:[" + tempDataANT + "]"); iCommonSecondFlag++; if (iCommonSecondFlag == iBarcodeGroupCount) { mutauto.ReleaseMutex(); _logger.LogInformation("《《《返回标签数据!"); return tagInfoList; } } return tagInfoList; } catch (Exception ex) { mutauto.ReleaseMutex(); throw new InvalidOperationException($"Device_AutoDealContent 自动处理函数异常:{ex.Message}"); } } /// /// 根据PC获取EPC长度 /// /// /// private int EPCLengthByPC(int pcValue) { int epcLength = 0; if (pcValue >= 10 && pcValue < 20) { epcLength = 4; } else if (pcValue >= 20 && pcValue < 30) { epcLength = 8; } else if (pcValue >= 30 && pcValue < 40) { epcLength = 12; } else if (pcValue >= 40 && pcValue < 50) { epcLength = 16; } else if (pcValue >= 50 && pcValue < 60) { epcLength = 20; } else if (pcValue >= 60 && pcValue < 70) { epcLength = 24; } else if (pcValue >= 70 && pcValue < 80) { epcLength = 28; } else if (pcValue >= 80 && pcValue < 90) { epcLength = 30; } return epcLength; } public override void RefreshStatus() { if (_tcpClient != null) { this.IsConnected = _tcpClient.Online; } else { this.IsConnected = false; } } #endregion } }