You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
21 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
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<RflyFactory> _logger;
private readonly TcpClient _tcpClient = new TcpClient();
private readonly StringChange _stringChange;
public RflyFactory(ILogger<RflyFactory> logger,StringChange stringChange)
{
_logger = logger;
_stringChange = stringChange;
}
/// <summary>
/// 建立连接
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public override bool Connect(string ip, int port)
{
try
{
_tcpClient.Setup(new TouchSocketConfig().SetRemoteIPHost($"{ip}:{port}"));
_tcpClient.Connect();
return true;
}
catch (Exception e)
{
throw new InvalidOperationException($"设备连接异常:{e.Message}");
}
}
/// <summary>
/// 按时间段盘点
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public override List<TagInfo> 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<TagInfo> tagInfoList = Device_DealTagInfoList(resultBuffer);
return tagInfoList;
}
catch (Exception e)
{
throw new InvalidOperationException($"按时间段盘点异常:{e.Message}");
}
}
#region 标签解析
/// <summary>
/// 状态机函数
/// </summary>
/// <param name="buffer"></param>
/// <param name="iLen"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
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();
/// <summary>
/// 解析函数
/// </summary>
/// <param name="AutoDealReportData"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public List<TagInfo> Device_DealTagInfoList(byte[] AutoDealReportData)
{
List<TagInfo> tagInfoList = new List<TagInfo>();
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}");
}
}
/// <summary>
/// 根据PC获取EPC长度
/// </summary>
/// <param name="pcValue"></param>
/// <returns></returns>
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;
}
#endregion
}
}