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,
///
/// 发送退款信息油机命令字
///
SEND_REFUND = 0x1A,
}
public enum ErrorType
{
DISCONNECT,
TIMEOUT
}
///
/// 包头 0xFA
///
public Byte Head { get; set; } = 0xFA;
///
/// 目标地址
///
public Byte DestinationAddr { get; set; } = 0xFF;
///
/// 源地址
///
public Byte SourceAddr { get; set; } = 0xE0;
///
/// 帧号
///
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 ErrorType TheErrorType { get; set; }
///
/// 错误信息(与油机协议无关)
///
public string ErrorMessage { get; set; }
public CommonMessage getBaseData(byte[] data)
{
this.Head = 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;
}
///
/// 将数值转为byte[]
///
/// 数值
/// 数组长度,不够高位补0
///
///
public static byte[] NumberToByteArrayWithPadding(int value, int length)
{
if (length < 0)
{
throw new ArgumentException("Length must be non-negative.");
}
// 创建一个指定长度的字节数组
byte[] paddedBytes = new byte[length];
// 确保是大端序
for (int i = 0; i < length && i < 4; i++)
{
paddedBytes[length - 1 - i] = (byte)(value >> (i * 8));
}
return paddedBytes;
}
///
/// 将时间转为 BCD
///
///
///
public static byte[] ConvertDateTimeToByteArray(DateTime dateTime)
{
// 创建byte数组
byte[] result = new byte[7];
// 年份处理
int year = dateTime.Year;
result[0] = (byte)((year / 1000) * 16 + (year / 100) % 10); // 千年和百年
result[1] = (byte)((year / 10) % 10 * 16 + year % 10); // 十年和个年
// 月、日、小时、分钟、秒直接转换为BCD
result[2] = (byte)(dateTime.Month / 10 * 16 + dateTime.Month % 10);
result[3] = (byte)(dateTime.Day / 10 * 16 + dateTime.Day % 10);
result[4] = (byte)(dateTime.Hour / 10 * 16 + dateTime.Hour % 10);
result[5] = (byte)(dateTime.Minute / 10 * 16 + dateTime.Minute % 10);
result[6] = (byte)(dateTime.Second / 10 * 16 + dateTime.Second % 10);
return result;
}
public static byte[] FormatDecimal(decimal value)
{
// 四舍五入到两位小数
decimal roundedValue = Math.Round(value, 2, MidpointRounding.AwayFromZero);
int valueInt = (int)(roundedValue * 100m);
return NumberToByteArrayWithPadding(valueInt, 3); ;
}
}
}