using Edge.Core.Parser; using Edge.Core.Parser.BinaryParser.MessageEntity; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace HengshanPaymentTerminal.MessageEntity { /// /// 与油机通讯的基础数据包对象 /// public abstract class CommonMessage: MessageTemplateBase { public enum Command { /// /// 通用应答命令字 /// COMMON = 0x55, /// /// 心跳命令字 /// HEART_BRET = 0x10, /// /// 油枪信息命令字 /// NOZZLE_INFO = 0x61, /// /// 油枪状态命令字 /// NOZZLE_STATE = 0x62, /// /// 发送二维码给油机命令字 /// SEND_QR_CODE = 0x63, /// /// 获取单价命令字 /// GET_PRICE = 0x64, /// /// 授权命令字 /// ACCREDIT = 0x65, /// /// 取消授权命令字 /// CANCEL_ACCREDIT = 0x66, /// /// 接收油机订单命令字 /// RECIEVE_TRANX = 0x18, /// /// 发送应付金额给油机命令字 /// SEND_NEED_AMOUNT = 0x19 } /// /// 包头 0xFA /// public Byte Head { get; set; } /// /// 目标地址 /// public Byte DestinationAddr { get; set; } /// /// 源地址 /// public Byte SourceAddr { get; set; } /// /// 帧号 /// public int FrameNum { get; set; } /// /// 有效数据长度,标识油机数据包中,有效数据的长度 /// public int DataLength { get; set; } /// /// 命令字,用来标识数据包传递的数据 /// public Byte Handle { get; set; } /// /// crc 校验值 /// public Byte[] CRC { get; set; } /// /// 是否为错误响应(与油机通讯协议无关) /// public bool IsError { get; set; } = false; /// /// 错误信息(与油机协议无关) /// public string ErrorMessage { get; set; } public CommonMessage getBaseData(byte[] data) { this.Handle = data[0]; this.DestinationAddr = data[1]; this.SourceAddr = data[2]; this.FrameNum = data[3]; this.DataLength = Bcd2Int(data[4], data[5]); this.Handle = data[6]; this.CRC = new byte[]{ data[data.Length - 2],data[data.Length - 1] }; return this; } /// /// 传入有效数据,拼接为要发送给油机包 /// /// /// public byte[] content2data(byte[] content) { List list = new List(); //目标地址,源地址,帧号 byte[] head = new byte[] { this.SourceAddr, this.DestinationAddr, (byte)this.FrameNum }; byte[] length = Int2BCD(content.Length); list.AddRange(head); list.AddRange(length); list.AddRange(content); byte[] crc = HengshanCRC16.ComputeChecksumToBytes(list.ToArray()); list.AddRange(crc); List addFAList = addFA(list); addFAList.Insert(0,0xFA); return addFAList.ToArray(); } public int Bcd2Int(byte byte1, byte byte2) { // 提取第一个字节的高四位和低四位 int digit1 = (byte1 >> 4) & 0x0F; // 高四位 int digit2 = byte1 & 0x0F; // 低四位 // 提取第二个字节的高四位和低四位 int digit3 = (byte2 >> 4) & 0x0F; // 高四位 int digit4 = byte2 & 0x0F; // 低四位 // 组合成一个整数 int result = digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4; return result; } public byte[] Int2BCD(int number) { // 提取千位、百位、十位和个位 int thousands = number / 1000; int hundreds = (number / 100) % 10; int tens = (number / 10) % 10; int units = number % 10; // 将千位和百位组合成一个字节(千位在高四位,百位在低四位) byte firstByte = (byte)((thousands * 16) + hundreds); // 乘以16相当于左移4位 // 将十位和个位组合成一个字节(十位在高四位,个位在低四位) byte secondByte = (byte)((tens * 16) + units); // 返回结果数组 return new byte[] { firstByte, secondByte }; } /// /// 数组转数字 /// /// 数组 /// 开始的截取的下标 /// 截取长度 /// public T Bytes2Number(byte[] datas,int startIndex,int length) where T: unmanaged { int sizeOfT = Unsafe.SizeOf(); Span span = datas.AsSpan(startIndex, length); // 如果 span 的长度不够,补足长度 if (span.Length < sizeOfT) { // 使用数组而不是 stackalloc,避免栈溢出 byte[] paddedArray = new byte[sizeOfT]; Span paddedSpan = paddedArray.AsSpan(); // 在前面补零 span.CopyTo(paddedSpan.Slice(sizeOfT - span.Length)); if (BitConverter.IsLittleEndian) { // 小端序:反转字节顺序 paddedSpan.Reverse(); } return MemoryMarshal.Read(paddedSpan); } // 如果长度足够,直接读取 if (BitConverter.IsLittleEndian) { // 小端序:反转字节顺序 span.Reverse(); } return MemoryMarshal.Read(span); } public List addFA(List list) { List result = new List(); foreach (byte b in list) { if (b == 0xFA) { result.Add(0xFA); result.Add(0xFA); } else { result.Add(b); } } return result; } public DateTime bytes2DateTime(byte[] timeBytes) { string formate = "yyyyMMddHHmmss"; string timeStr = BitConverter.ToString(timeBytes).Replace("-", ""); DateTime parsedDateTime; bool success = DateTime.TryParseExact(timeStr, formate, null, System.Globalization.DateTimeStyles.None, out parsedDateTime); return success ? parsedDateTime : DateTime.Now; } } }