This commit is contained in:
rnchg
2026-07-14 21:29:27 +08:00
commit f7ad7e20aa
1773 changed files with 514155 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
using System.Net;
using UdpServer = Common.Net.Udp.UdpServer;
namespace FASS.Extend.Master
{
public class Command
{
public UdpServer Server { get; private set; }
public EndPoint Remote { get => Server.RemoteEndPoint; set => Server.RemoteEndPoint = value; }
public Command(IPEndPoint local)
{
Server = new UdpServer()
{
LocalEndPoint = local
};
}
public void SendState(byte command, byte state, ulong timeSpan, IPEndPoint remote)
{
var sendMessage = new SendQueryMessage().SetMessage(command, state, timeSpan);
var sendByteArray = sendMessage.GetByteArray();
Server.Send(sendByteArray, remote);
}
public static ReceiveStateMessage GetReceiveStateMessage(byte[] byteArray) => new ReceiveStateMessage().GetMessage(byteArray);
public static byte[] GetReceiveStateByteArray(ReceiveStateMessage message) => message.GetByteArray();
public void SendLightControls(byte taskNo, byte sectionCount, LightControlMessage[] lightControlMessages, ulong timeStamp, IPEndPoint remote)
{
var sendMessage = new SendControlMessage().SetMessage(taskNo, sectionCount, lightControlMessages, timeStamp);
var sendByteArray = sendMessage.GetByteArray();
Server.Send(sendByteArray, remote);
}
public static ReceiveControlRespMessage GetReceiveControlRespMessage(byte[] byteArray) => new ReceiveControlRespMessage().GetMessage(byteArray);
public static byte[] GetSendControlByteArray(SendControlMessage message) => message.GetByteArray();
public void SendPressedStateResponse(byte command, byte taskNo, byte lightNo, byte state, uint led, ulong timeSpan, IPEndPoint remote)
{
var sendMessage = new SendPressedStateRespMessage().SetMessage(command, taskNo, lightNo, state, led, timeSpan);
var sendByteArray = sendMessage.GetByteArray();
Server.Send(sendByteArray, remote);
}
public static SendPressedStateRespMessage GetPressedStateResponseMessage(byte[] byteArray) => new SendPressedStateRespMessage().GetMessage(byteArray);
public static byte[] GetPressedStateResponseByteArray(SendPressedStateRespMessage message) => message.GetByteArray();
public static ReceivePressedStateMessage GetReceivePressedStateMessage(byte[] byteArray) => new ReceivePressedStateMessage().GetMessage(byteArray);
}
}
+52
View File
@@ -0,0 +1,52 @@
namespace FASS.Extend.Master
{
public static class Crc32
{
private static readonly uint[] Table;
static Crc32()
{
// 初始化CRC32查找表
Table = new uint[256];
const uint poly = 0xEDB88320; // 标准CRC32多项式
for (uint i = 0; i < 256; i++)
{
var crc = i;
for (var j = 0; j < 8; j++)
{
crc = (crc & 1) == 1
? (crc >> 1) ^ poly
: crc >> 1;
}
Table[i] = crc;
}
}
public static uint Compute(byte[] data)
{
uint crc = 0xFFFFFFFF; // 初始值
foreach (byte b in data)
{
// 查表更新CRC值
crc = (crc >> 8) ^ Table[(crc ^ b) & 0xFF];
}
return crc ^ 0xFFFFFFFF; // 最终异或处理
}
public static byte[] LittleEndianComputeBytes(byte[] data)
{
uint crc = Compute(data);
return BitConverter.GetBytes(crc);
}
public static byte[] BigEndianComputeBytes(byte[] data)
{
uint crc = Compute(data);
var result = BitConverter.GetBytes(crc);
Array.Reverse(result);
return result;
}
}
}
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>2.4.2</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Common.Net" Version="2.4.2" />
</ItemGroup>
</Project>
@@ -0,0 +1,49 @@
namespace FASS.Extend.Master
{
public class LightControlMessage
{
public byte StartLightNo { get; set; }
public byte EndLightNo { get; set; }
public byte State { get; set; } = 0;
public uint Led { get; set; }
public byte Reserve { get; set; }
public LightControlMessage SetMessage(
byte startLightNo,
byte endLightNo,
byte state,
uint led)
{
StartLightNo = startLightNo;
EndLightNo = endLightNo;
State = state;
Led = led;
return this;
}
public LightControlMessage GetMessage(byte[] byteArray)
{
if (byteArray == null || byteArray.Length != 8) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
StartLightNo = byteArray[0];
EndLightNo = byteArray[1];
State = byteArray[2];
Led = BitConverter.ToUInt32(byteArray[3..7]);
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[8];
byteArray[0] = StartLightNo;
byteArray[1] = EndLightNo;
byteArray[2] = State;
var ledArr = BitConverter.GetBytes(Led);
byteArray[3] = ledArr[0];
byteArray[4] = ledArr[1];
byteArray[5] = ledArr[2];
byteArray[6] = ledArr[3];
return byteArray;
}
}
}
@@ -0,0 +1,33 @@
namespace FASS.Extend.Master
{
public class LightStateMessage
{
public byte Alarm { get; set; }
public byte State { get; set; }
public LightStateMessage SetMessage(
byte alarm,
byte state)
{
Alarm = alarm;
State = state;
return this;
}
public LightStateMessage GetMessage(byte[] byteArray)
{
if (byteArray == null || byteArray.Length < 2) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
Alarm = byteArray[0];
State = byteArray[1];
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[2];
byteArray[0] = Alarm;
byteArray[1] = State;
return byteArray;
}
}
}
@@ -0,0 +1,54 @@
namespace FASS.Extend.Master
{
public class ReceiveControlRespMessage
{
public byte Begin { get; set; } = 0xBB;
public byte Command { get; set; }
public string? Uuid { get; set; }
public byte TaskNo { get; set; }
public byte[] Reserve { get; set; } = new byte[6];
public byte[] Check { get; set; } = new byte[4];
public byte[] End { get; set; } = { 0xEE, 0xEE, 0xEE };
public ReceiveControlRespMessage SetMessage(
byte command,
string uuid,
byte taskNo)
{
Command = command;
Uuid = uuid;
TaskNo = taskNo;
return this;
}
public ReceiveControlRespMessage GetMessage(byte[] byteArray)
{
if (byteArray == null || byteArray.Length < 24) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[98] != Utility.XOR(byteArray[1..^2])) throw new Exception($"数据校验错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[0] != 0xBB || byteArray[99] != 0xEE) throw new Exception($"数据帧头尾错误:{Utility.ByteArrayToHexString(byteArray)}");
Begin = byteArray[0];
Command = byteArray[1];
Uuid = Utility.ByteArrayToHexString(byteArray[2..10]).ToLower();
TaskNo = byteArray[10];
Reserve = byteArray[11..17];
Check = byteArray[17..21];
End = byteArray[21..24];
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[24];
byteArray[0] = Begin;
byteArray[1] = Command;
var uuid = Utility.HexStringToBytes(Uuid!);
Array.Copy(uuid, 0, byteArray, 2, uuid.Length);
byteArray[10] = TaskNo;
Array.Copy(Reserve, 0, byteArray, 11, Reserve.Length);
var crc32Check = Crc32.LittleEndianComputeBytes(byteArray[1..^7]);
Array.Copy(crc32Check, 0, byteArray, 17, crc32Check.Length);
Array.Copy(End, 0, byteArray, 21, End.Length);
return byteArray;
}
}
}
@@ -0,0 +1,59 @@
namespace FASS.Extend.Master
{
public class ReceivePressedStateMessage
{
public byte Begin { get; set; } = 0xBB;
public byte Command { get; set; }
public string? Uuid { get; set; }
public byte TaskNo { get; set; }
public byte LightNo { get; set; }
public byte[] Reserve { get; set; } = new byte[6];
public byte[] Check { get; set; } = new byte[4];
public byte[] End { get; set; } = { 0xEE, 0xEE, 0xEE };
public ReceivePressedStateMessage SetMessage(
byte command,
string uuid,
byte taskNo,
byte lightNo)
{
Command = command;
Uuid = uuid;
TaskNo = taskNo;
LightNo = lightNo;
return this;
}
public ReceivePressedStateMessage GetMessage(byte[] byteArray)
{
if (byteArray == null || byteArray.Length < 24) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[98] != Utility.XOR(byteArray[1..^2])) throw new Exception($"数据校验错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[0] != 0xBB || byteArray[99] != 0xEE) throw new Exception($"数据帧头尾错误:{Utility.ByteArrayToHexString(byteArray)}");
Begin = byteArray[0];
Command = byteArray[1];
Uuid = Utility.ByteArrayToHexString(byteArray[2..10]).ToLower();
TaskNo = byteArray[10];
LightNo = byteArray[11];
Reserve = byteArray[12..17];
Check = byteArray[17..21];
End = byteArray[21..24];
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[24];
byteArray[0] = Begin;
byteArray[1] = Command;
var uuid = Utility.HexStringToBytes(Uuid!);
Array.Copy(uuid, 0, byteArray, 2, uuid.Length);
byteArray[10] = TaskNo;
byteArray[11] = LightNo;
Array.Copy(Reserve, 0, byteArray, 12, Reserve.Length);
var crc32Check = Crc32.LittleEndianComputeBytes(byteArray[1..^7]);
Array.Copy(crc32Check, 0, byteArray, 17, crc32Check.Length);
Array.Copy(End, 0, byteArray, 21, End.Length);
return byteArray;
}
}
}
@@ -0,0 +1,92 @@
namespace FASS.Extend.Master
{
public class ReceiveStateMessage
{
public byte Begin { get; set; } = 0xBB;
public byte Command { get; set; }
public string? Uuid { get; set; }
public string? SoftwareVersion { get; set; }
public string? HardwareVersion { get; set; }
public uint Alarm { get; set; }
public byte Count { get; set; }
public LightStateMessage[] LightMessages { get; set; } = new LightStateMessage[128];
public byte[] Reserve { get; set; } = new byte[14];
public byte[] Check { get; set; } = new byte[4];
public byte[] End { get; set; } = { 0xEE, 0xEE, 0xEE };
public ReceiveStateMessage SetMessage(
byte command,
string uuid,
string softwareVersion,
string hardwareVersion,
uint alarm,
byte count,
LightStateMessage[] lightMessages)
{
Command = command;
Uuid = uuid;
SoftwareVersion = softwareVersion;
HardwareVersion = hardwareVersion;
Alarm = alarm;
Count = count;
Array.Copy(lightMessages, 0, LightMessages, 0, lightMessages.Length);
return this;
}
public ReceiveStateMessage GetMessage(byte[] byteArray)
{
if (byteArray == null || byteArray.Length < 300) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[98] != Utility.XOR(byteArray[1..^2])) throw new Exception($"数据校验错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[0] != 0xBB || byteArray[99] != 0xEE) throw new Exception($"数据帧头尾错误:{Utility.ByteArrayToHexString(byteArray)}");
Begin = byteArray[0];
Command = byteArray[1];
Uuid = Utility.ByteArrayToHexString(byteArray[2..10]).ToLower();
HardwareVersion = $"{byteArray[11]}.{byteArray[12]}.{byteArray[13]}";
SoftwareVersion = $"{byteArray[15]}.{byteArray[16]}.{byteArray[17]}";
Alarm = BitConverter.ToUInt32(byteArray[18..22]);
Count = byteArray[22];
for (var i = 0; i < 128; i++)
{
var start = i * 2 + 23;
var end = start + 2;
LightMessages[i] = new LightStateMessage().GetMessage(byteArray[start..end]);
}
Reserve = byteArray[279..293];
Check = byteArray[293..297];
End = byteArray[297..300];
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[300];
byteArray[0] = Begin;
byteArray[1] = Command;
var uuid = Utility.HexStringToBytes(Uuid!);
Array.Copy(uuid, 0, byteArray, 2, uuid.Length);
//硬件版本
var hardVersion = HardwareVersion!.Split('.');
byteArray[11] = byte.Parse(hardVersion[0]);
byteArray[12] = byte.Parse(hardVersion[1]);
byteArray[13] = byte.Parse(hardVersion[2]);
//软件版本
var softVersion = SoftwareVersion!.Split('.');
byteArray[15] = byte.Parse(softVersion[0]);
byteArray[16] = byte.Parse(softVersion[1]);
byteArray[17] = byte.Parse(softVersion[2]);
var alarm = BitConverter.GetBytes(Alarm);
byteArray[18] = alarm[0];
byteArray[19] = alarm[1];
byteArray[20] = alarm[2];
byteArray[21] = alarm[3];
var count = Count;
var ligthMessages = LightMessages.SelectMany(e => e.GetByteArray()).ToArray();
Array.Copy(ligthMessages, 0, byteArray, 23, ligthMessages.Length);
Array.Copy(Reserve, 0, byteArray, 279, Reserve.Length);
var crc32Check = Crc32.LittleEndianComputeBytes(byteArray[1..^7]);
Array.Copy(crc32Check, 0, byteArray, 293, crc32Check.Length);
Array.Copy(End, 0, byteArray, 297, End.Length);
return byteArray;
}
}
}
@@ -0,0 +1,88 @@
namespace FASS.Extend.Master
{
public class SendControlMessage
{
public byte Begin { get; set; } = 0xBB;
public byte Command { get; set; } = 0x01;
public byte TaskNo { get; set; }
public byte SectionCount { get; set; }
public List<LightControlMessage> LightControlMessages { get; set; } = new List<LightControlMessage>();
public ulong TimeStamp { get; set; }
public byte[] Reserve { get; set; } = new byte[5];
public byte[] Check { get; set; } = new byte[4];
public byte[] End { get; set; } = { 0xEE, 0xEE, 0xEE };
public SendControlMessage SetMessage(
byte taskNo,
byte sectionCount,
LightControlMessage[] lightControlMessages,
ulong timeStamp)
{
TaskNo = taskNo;
SectionCount = sectionCount;
TimeStamp = timeStamp;
LightControlMessages.AddRange(lightControlMessages);
return this;
}
public SendControlMessage GetMessage(byte[] byteArray)
{
//最少一个灯范围控制
if (byteArray == null || byteArray.Length < 32) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[298] != Utility.XOR(byteArray[1..^2])) throw new Exception($"数据校验错误:{Utility.ByteArrayToHexString(byteArray)}");
Begin = byteArray[0];
Command = byteArray[1];
TaskNo = byteArray[2];
SectionCount = byteArray[3];
if (SectionCount == 0)
{
throw new Exception($"数据长度错误,控制段个数错误:{Utility.ByteArrayToHexString(byteArray)}");
}
if (SectionCount > 60)
{
throw new Exception($"数据长度错误,控制段个数超出限制:{Utility.ByteArrayToHexString(byteArray)}");
}
var length = SectionCount * 8 + 24;
if (byteArray.Length != length) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
for (var i = 0; i < SectionCount; i++)
{
var start = i * 8 + 4;
var end = start + 8;
LightControlMessages.Add(new LightControlMessage().GetMessage(byteArray[start..end]));
}
Reserve = byteArray[(4 + 8 * SectionCount)..(9 + 8 * SectionCount)];
TimeStamp = BitConverter.ToUInt64(byteArray[(9 + 8 * SectionCount)..(17 + 8 * SectionCount)]);
Check = byteArray[(17 + 8 * SectionCount)..(21 + 8 * SectionCount)];
End = byteArray[(21 + 8 * SectionCount)..(24 + 8 * SectionCount)];
return this;
}
public byte[] GetByteArray()
{
var length = 24 + 8 * SectionCount;
var byteArray = new byte[length];
byteArray[0] = Begin;
byteArray[1] = Command;
byteArray[2] = TaskNo;
byteArray[3] = SectionCount;
var lightControlMessages = LightControlMessages.SelectMany(e => e.GetByteArray()).ToArray();
Array.Copy(lightControlMessages, 0, byteArray, 4, lightControlMessages.Length);
Array.Copy(Reserve, 0, byteArray, 4 + 8 * SectionCount, Reserve.Length);
var date = new DateTime(1970, 1, 1, 8, 0, 0).AddMilliseconds(TimeStamp);
byteArray[9 + 8 * SectionCount] = (byte)(date.Year - 1970);
byteArray[10 + 8 * SectionCount] = (byte)(date.Month);
byteArray[11 + 8 * SectionCount] = (byte)(date.Day);
byteArray[12 + 8 * SectionCount] = (byte)(date.Hour);
byteArray[13 + 8 * SectionCount] = (byte)(date.Minute);
byteArray[14 + 8 * SectionCount] = (byte)(date.Second);
var millisecond = BitConverter.GetBytes((ushort)(date.Millisecond));
byteArray[15 + 8 * SectionCount] = millisecond[0];
byteArray[16 + 8 * SectionCount] = millisecond[1];
var crc32Check = Crc32.LittleEndianComputeBytes(byteArray[1..^7]);
Array.Copy(crc32Check, 0, byteArray, 17 + 8 * SectionCount, crc32Check.Length);
Array.Copy(End, 0, byteArray, 21 + 8 * SectionCount, End.Length);
return byteArray;
}
}
}
@@ -0,0 +1,78 @@
namespace FASS.Extend.Master
{
public class SendPressedStateRespMessage
{
public byte Begin { get; set; } = 0xBB;
public byte Command { get; set; } = 0x82;
public byte TaskNo { get; set; }
public byte LightNo { get; set; }
public byte State { get; set; }
public uint Led { get; set; }
public ulong TimeStamp { get; set; }
public byte[] Check { get; set; } = new byte[4];
public byte[] End { get; set; } = { 0xEE, 0xEE, 0xEE };
public SendPressedStateRespMessage SetMessage(
byte command,
byte taskNo,
byte lightNo,
byte state,
uint led,
ulong param)
{
Command = command;
TaskNo = taskNo;
LightNo = lightNo;
State = state;
Led = led;
TimeStamp = param;
return this;
}
public SendPressedStateRespMessage GetMessage(byte[] byteArray)
{
if (byteArray == null || byteArray.Length != 24) throw new Exception($"数据长度错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[98] != Utility.XOR(byteArray[1..^2])) throw new Exception($"数据校验错误:{Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[0] != 0xBB || byteArray[99] != 0xEE) throw new Exception($"数据帧头尾错误:{Utility.ByteArrayToHexString(byteArray)}");
Begin = byteArray[0];
Command = byteArray[1];
TaskNo = byteArray[2];
LightNo = byteArray[3];
State = byteArray[4];
Led = BitConverter.ToUInt32(byteArray[5..9]);
TimeStamp = BitConverter.ToUInt64(byteArray[9..17]);
Check = byteArray[17..21];
End = byteArray[21..24];
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[24];
byteArray[0] = Begin;
byteArray[1] = Command;
byteArray[2] = TaskNo;
byteArray[3] = LightNo;
byteArray[4] = State;
var ledArr = BitConverter.GetBytes(Led);
byteArray[5] = ledArr[0];
byteArray[6] = ledArr[1];
byteArray[7] = ledArr[2];
byteArray[8] = ledArr[3];
var date = new DateTime(1970, 1, 1, 8, 0, 0).AddMilliseconds(TimeStamp);
byteArray[9] = (byte)(date.Year - 1970);
byteArray[10] = (byte)(date.Month);
byteArray[11] = (byte)(date.Day);
byteArray[12] = (byte)(date.Hour);
byteArray[13] = (byte)(date.Minute);
byteArray[14] = (byte)(date.Second);
var millisecond = BitConverter.GetBytes((ushort)(date.Millisecond));
byteArray[15] = millisecond[0];
byteArray[16] = millisecond[1];
var crc32Check = Crc32.LittleEndianComputeBytes(byteArray[1..^7]);
Array.Copy(crc32Check, 0, byteArray, 17, crc32Check.Length);
Array.Copy(End, 0, byteArray, 21, End.Length);
return byteArray;
}
}
}
@@ -0,0 +1,61 @@
namespace FASS.Extend.Master
{
public class SendQueryMessage
{
public byte Begin { get; set; } = 0xBB;
public byte Command { get; set; } = 0x00;
public byte State { get; set; } = 0x00;
public byte[] Reserve { get; set; } = new byte[6];
public ulong TimeStamp { get; set; }
public byte[] Check { get; set; } = new byte[4];
public byte[] End { get; set; } = { 0xEE, 0xEE, 0xEE };
public SendQueryMessage SetMessage(
byte command,
byte state,
ulong param)
{
Command = command;
TimeStamp = param;
State = state;
return this;
}
public SendQueryMessage GetMessage(byte[] byteArray)
{
if (byteArray is null || byteArray.Length < 24) throw new Exception($"数据长度错误: {Utility.ByteArrayToHexString(byteArray)}");
//if (byteArray[48] != Utility.XOR(byteArray[1..^2])) throw new Exception($"数据校验错误:{Utility.ByteArrayToHexString(byteArray)}");
Begin = byteArray[0];
Command = byteArray[1];
State = byteArray[2];
Reserve = byteArray[3..9];
TimeStamp = BitConverter.ToUInt64(byteArray[9..17]);
Check = byteArray[17..21];
End = byteArray[21..24];
return this;
}
public byte[] GetByteArray()
{
var byteArray = new byte[24];
byteArray[0] = Begin;
byteArray[1] = Command;
byteArray[2] = State;
Array.Copy(Reserve, 0, byteArray, 3, Reserve.Length);
var date = new DateTime(1970, 1, 1, 8, 0, 0).AddMilliseconds(TimeStamp);
byteArray[9] = (byte)(date.Year - 1970);
byteArray[10] = (byte)(date.Month);
byteArray[11] = (byte)(date.Day);
byteArray[12] = (byte)(date.Hour);
byteArray[13] = (byte)(date.Minute);
byteArray[14] = (byte)(date.Second);
var millisecond = BitConverter.GetBytes((ushort)(date.Millisecond));
byteArray[15] = millisecond[0];
byteArray[16] = millisecond[1];
var crc32Check = Crc32.LittleEndianComputeBytes(byteArray[1..^7]);
Array.Copy(crc32Check, 0, byteArray, 17, crc32Check.Length);
Array.Copy(End, 0, byteArray, 21, End.Length);
return byteArray;
}
}
}
+328
View File
@@ -0,0 +1,328 @@
using System.Text.RegularExpressions;
namespace FASS.Extend.Master
{
public static class Utility
{
public static string ByteArrayToHexString(byte[]? byteArray, string separator = "")
{
if (byteArray is null)
{
return string.Empty;
}
return string.Join(separator, byteArray.Select(t => t.ToString("X2")));
}
public static byte XOR(byte[] byteArray)
{
byte xor = 0;
for (int i = 0; i < byteArray.Length; i++)
{
xor ^= byteArray[i];
}
return xor;
}
public static byte[] GetCRC16(byte[] data)
{
byte b = byte.MaxValue;
byte b2 = byte.MaxValue;
byte b3 = 1;
byte b4 = 160;
for (int i = 0; i < data.Length; i++)
{
b = (byte)(b ^ data[i]);
for (int j = 0; j <= 7; j++)
{
byte b5 = b2;
byte b6 = b;
b2 = (byte)(b2 >> 1);
b = (byte)(b >> 1);
if ((b5 & 1) == 1)
{
b = (byte)(b | 0x80u);
}
if ((b6 & 1) == 1)
{
b2 = (byte)(b2 ^ b4);
b = (byte)(b ^ b3);
}
}
}
return new byte[2]
{
b,b2
};
}
public static byte[] HexStringToBytes(string hex)
{
if (string.IsNullOrEmpty(hex))
throw new ArgumentException("输入字符串不能为空");
// 清理字符串中的非十六进制字符
string cleanHex = Regex.Replace(hex, "[^0-9A-Fa-f]", "");
if (cleanHex.Length % 2 != 0)
throw new FormatException("十六进制字符串长度必须为偶数");
return Convert.FromHexString(cleanHex);
}
public static List<byte[]> SplitByMarkers(byte[] source, byte head, byte[] tail)
{
List<byte[]> result = new List<byte[]>();
int startIndex = 0;
int tailLength = tail.Length;
if (tailLength != 3)
throw new ArgumentException("Tail marker must be 3 bytes");
while (startIndex < source.Length)
{
// 查找头字节
int headPos = Array.IndexOf(source, head, startIndex);
if (headPos == -1) break;
// 检查尾部空间是否足够
int minTailStart = headPos + 1;
int maxPossibleTailStart = source.Length - tailLength;
bool tailFound = false;
int tailStart = minTailStart;
// 从最小可能位置开始查找尾部
while (tailStart <= maxPossibleTailStart)
{
// 检查连续三个字节是否匹配尾部
if (source[tailStart] == tail[0] &&
source[tailStart + 1] == tail[1] &&
source[tailStart + 2] == tail[2] && ((tailStart + 2 == source.Length-1) ||(source[tailStart + 3] == head)))//找到尾部是整条报文的末尾、或者是下一帧报文的包头
{
tailFound = true;
break;
}
tailStart++;
}
if (!tailFound) break;
// 计算完整数据块(包含头尾)
int chunkEnd = tailStart + tailLength - 1;
int chunkSize = chunkEnd - headPos + 1;
byte[] chunk = new byte[chunkSize];
Array.Copy(source, headPos, chunk, 0, chunkSize);
result.Add(chunk);
// 更新起始点为尾部之后
startIndex = chunkEnd + 1;
}
return result;
}
public static bool[] ByteToBoolArray(byte b)
{
// 创建长度为8的布尔数组(一个字节=8位)
bool[] result = new bool[8];
// 从高位到低位遍历(索引0对应最高位,索引7对应最低位)
for (int i = 0; i < 8; i++)
{
// 通过位掩码检查每一位的值
result[i] = (b & (1 << (7 - i))) != 0;
}
return result;
}
public static byte BoolArrayToByte(bool[] bools)
{
if (bools.Length != 8)
throw new ArgumentException("数组长度必须为 8");
byte result = 0;
for (int i = 0; i < 8; i++)
{
if (bools[i])
{
// 选择位序:
// 低位优先(第一个元素对应 byte 的最低位,即 bit0)
//result |= (byte)(1 << i);
// 高位优先(第一个元素对应 byte 的最高位,即 bit7)
result |= (byte)(1 << (7 - i));
}
}
return result;
}
public static byte SetLightColour(string value, bool ledOpen)
{
var lightValue = byte.Parse(value);
var boolArr = ByteToBoolArray(lightValue);
boolArr[1] = ledOpen;
return BoolArrayToByte(boolArr);
}
/// <summary>
/// 设置红灯
/// </summary>
/// <returns></returns>
public static byte SetLightRed()
{
return LightStateControl(false, false, false, true, false, false, false, false);
}
/// <summary>
/// 设置红灯闪烁
/// </summary>
/// <returns></returns>
public static byte SetLightRedWithFlash()
{
return LightStateControl(false, false, true, true, false, false, false, false);
}
/// <summary>
/// 设置绿灯+数显
/// </summary>
/// <returns></returns>
public static byte SetLightGreenWithLed()
{
return LightStateControl(false, true, false, false, false, true, false, false);
}
/// <summary>
/// 设置绿灯
/// </summary>
/// <returns></returns>
public static byte SetLightGreen()
{
return LightStateControl(false, false, false, false, false, true, false, false);
}
/// <summary>
/// 设置黄灯
/// </summary>
/// <returns></returns>
public static byte SetLightYellow()
{
return LightStateControl(false, false, false, true, false, true, false, false);
}
/// <summary>
/// 设置洋红色灯
/// </summary>
/// <returns></returns>
public static byte SetLightMagenta()
{
return LightStateControl(false, false, false, true, false, false, false, true);
}
/// <summary>
/// 设置洋红灯+数显
/// </summary>
/// <returns></returns>
public static byte SetLightMagentaWithLed()
{
return LightStateControl(false, true, false, true, false, false, false, true);
}
/// <summary>
/// 灭灯
/// </summary>
/// <returns></returns>
public static byte SetLightOff()
{
return LightStateControl(false, false, false, false, false, false, false, false);
}
/// <summary>
/// 设置显示灯地址
/// </summary>
/// <returns></returns>
public static byte SetDisplayLightAddress()
{
return LightStateControl(true, false, false, false, false, false, false, false);
}
/// <summary>
/// 设置灯状态
/// </summary>
/// <param name="fd">数码管闪烁</param>
/// <param name="sd">数码管开关</param>
/// <param name="fr">红色闪烁</param>
/// <param name="sr">红</param>
/// <param name="fg">绿色闪烁</param>
/// <param name="sg">绿</param>
/// <param name="fb">蓝色闪烁</param>
/// <param name="sb">蓝</param>
/// <returns></returns>
public static byte LightStateControl(bool fd = false, bool sd = false, bool fr = false, bool sr = false, bool fg = false, bool sg = false, bool fb = false, bool sb = false)
{
bool[] bools = new bool[8] { fd, sd, fr, sr, fg, sg, fb, sb };
return BoolArrayToByte(bools);
}
/// <summary>
/// 十进制转bcb
/// </summary>
/// <param name="decimalNumber"></param>
/// <returns></returns>
public static byte DecimalToBcd(byte decimalNumber)
{
int tens = decimalNumber / 10; // 获取十位数字‌
int ones = decimalNumber % 10; // 获取个位数字‌
return (byte)((tens << 4) | ones); // 合并为BCD码‌
}
/// <summary>
/// 设置数码管显示值
/// </summary>
/// <param name="maxTaskNum">最大合单数</param>
/// <param name="list">各包车的数值</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static byte[] GetLedBytes(int maxTaskNum, List<int> list)
{
var byteArr = new byte[4];
if (list.Count < maxTaskNum)
{
throw new ArgumentException();
}
if (maxTaskNum == 1)
{
byteArr[1] = DecimalToBcd((byte)list[0]);
}
else if (maxTaskNum == 2)
{
byteArr[1] = DecimalToBcd((byte)list[0]);
byteArr[0] = DecimalToBcd((byte)list[1]);
}
else if (maxTaskNum == 3)
{
string str1 = DecimalToBcd((byte)list[0]).ToString("X2");
string str2 = DecimalToBcd((byte)list[1]).ToString("X2");
string str3 = DecimalToBcd((byte)list[2]).ToString("X2");
var appedStr = str1.Substring(str1.Length - 1) + str2.Substring(str2.Length - 1) + str3.Substring(str3.Length - 1) + "0";
byte[] hexArr = HexStringToBytes(appedStr);
byteArr[1] = hexArr[0];
byteArr[0] = hexArr[1];
}
else
{
string str1 = DecimalToBcd((byte)list[0]).ToString("X2");
string str2 = DecimalToBcd((byte)list[1]).ToString("X2");
string str3 = DecimalToBcd((byte)list[2]).ToString("X2");
string str4 = DecimalToBcd((byte)list[3]).ToString("X2");
var appedStr = str1.Substring(str1.Length - 1) + str2.Substring(str2.Length - 1) + str3.Substring(str3.Length - 1) + str4.Substring(str4.Length - 1);
byte[] hexArr = HexStringToBytes(appedStr);
byteArr[1] = hexArr[0];
byteArr[0] = hexArr[1];
}
return byteArr;
}
}
}