news 2025/12/24 7:28:01

c#字节处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
c#字节处理
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Markup; namespace HYTNewToolDemo.Tool { public class ByteProcessor { /// <summary> /// 将两个4位值合并为一个字节 /// </summary> /// <param name="highNibble">高4位值(0-15)</param> /// <param name="lowNibble">低4位值(0-15)</param> /// <returns>合并后的字节</returns> public static byte CombineByte(byte highNibble, byte lowNibble) { // 验证输入范围(0-15) if (highNibble > 0x0F || lowNibble > 0x0F) { throw new ArgumentOutOfRangeException("每个4位值必须在0-15范围内"); } // 将高4位左移4位,然后与低4位进行或运算 return (byte)((highNibble << 4) | (lowNibble & 0x0F)); } /// <summary> /// 获取字节的高4位 /// </summary> public static byte GetHighNibble(byte b) { return (byte)(b >> 4); } //type的bit7是状态为,有效位是0-6 public static int GetTypeValue(byte type) { int res = (type & 0x7F); return res; } /// <summary> /// 获取字节的低4位 /// </summary> public static byte GetLowNibble(byte b) { return (byte)(b & 0x0F); } //取字节的某一位 public static bool GetBitFromByte(byte b, int offset) { if (offset >= 0 && offset <= 7) { return (b & (int)Math.Pow(2, offset)) != 0; } else { throw new Exception("操作位数必须在0-7之间"); } } //给字节某个位设置值 public static byte SetBit(byte originalByte, int position, bool value) { if (position < 0 || position > 7) { return originalByte; } if (value) { // 设置指定位为 1 return (byte)(originalByte | (1 << position)); } else { // 设置指定位为 0 return (byte)(originalByte & ~(1 << position)); } } /// <summary> /// 将整数编码为可变长度字节数组(1-2字节)。 /// </summary> /// <param name="length">要编码的长度(0-16383)</param> /// <returns>编码后的字节数组</returns> public static byte[] EncodeLength(int length) { if (length < 0 || length > 0x3FFF) // 16383 throw new ArgumentOutOfRangeException(nameof(length), "Length must be between 0 and 16383."); if (length <= 0x7F) // 单字节(0-127) { return new byte[] { (byte)length }; } else // 双字节(128-16383) { byte highByte = (byte)(0x80 | ((length >> 7) & 0x7F)); // 高7位 + 标志位 byte lowByte = (byte)(length & 0x7F); // 低7位 return new byte[] { highByte, lowByte }; } } /// <summary> /// 从字节数组解码可变长度整数。 /// </summary> /// <param name="data">字节数组</param> /// <param name="bytesConsumed">实际读取的字节数</param> /// <returns>解码后的长度值</returns> public static int DecodeLength(byte[] data, out int bytesConsumed) { if (data == null || data.Length == 0) throw new ArgumentException("Data cannot be null or empty.", nameof(data)); bytesConsumed = 0; int length = 0; // 读取第一个字节 byte firstByte = data[0]; if ((firstByte & 0x80) == 0) // 单字节(bit7=0) { length = firstByte; bytesConsumed = 1; } else // 双字节(bit7=1) { if (data.Length < 2) throw new InvalidDataException("Invalid encoding: expected 2 bytes but only 1 available."); byte secondByte = data[1]; if ((secondByte & 0x80) != 0) // 第二个字节的bit7必须为0 throw new InvalidDataException("Invalid encoding: continuation byte must have bit7=0."); length = ((firstByte & 0x7F) << 7) | secondByte; bytesConsumed = 2; } return length; } } }
using HYTNewToolDemo.IServices; using HYTNewToolDemo.Manager; using HYTNewToolDemo.Models; using HYTNewToolDemo.Services; using HYTNewToolDemo.Tool; using ImTools; using Microsoft.Win32; using Prism.Commands; using Prism.Mvvm; using Rubyer; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; using System.Windows.Threading; using System.Xml.Linq; using static DryIoc.ServiceInfo; using static ImTools.ImMap; using static System.Net.Mime.MediaTypeNames; using Path = System.IO.Path; namespace HYTNewToolDemo.ViewModels { public class MainWindowViewModel : BindableBase { IMessageBoxService _messageBoxService; /// <summary> /// 可用的串口列表 /// </summary> public List<string> PortNameList { get; set; } /// <summary> /// 可用的波特率列表 /// </summary> public List<int> BaudRateList { get; set; } /// <summary> /// 可用的数组位列表 /// </summary> public List<int> DataBitsList { get; set; } /// <summary> /// 可用的校验位列表 /// </summary> public List<Parity> ParityList { get; set; } /// <summary> /// 可用的停止位列表 /// </summary> public List<StopBits> StopBitsList { get; set; } private readonly SerialPortManager _portManager; private CurrentSerialportParamter _currentSerialportParamter; private bool IsOpen { get; set; } = false; /// <summary> /// 当前选择的串口配置 /// </summary> public CurrentSerialportParamter CurrentSerialportParamter { get => _currentSerialportParamter; set { SetProperty(ref _currentSerialportParamter, value); } } public ObservableCollection<LogModel> LogList { get; set; } = new ObservableCollection<LogModel>(); public ObservableCollection<FileModel> FileList { get; set; } = new ObservableCollection<FileModel>(); private string _title = "协议调试工具"; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private string _openPortText = "打开串口"; public string OpenPortText { get { return _openPortText; } set { SetProperty(ref _openPortText, value); } } //发送的数据。 private string _sendDataText; public string SendDateText { get { return _sendDataText; } set { SetProperty(ref _sendDataText, value); } } private bool _isASCII = false; public bool ISASCII { get { return _isASCII; } set { SetProperty(ref _isASCII, value); } } public Task<string> GetUserInputAsync() { //一个未完成的task<string> var tcs = new TaskCompletionSource<string>(); Task.Run(() => { Thread.Sleep(3000); tcs.SetResult("abcd"); }); return tcs.Task; } public MainWindowViewModel(IMessageBoxService messageBoxService) { _messageBoxService = messageBoxService; //byte[] finish = { 0xA8, 0x01, 0x00, 0x06, 0x33, 0x74 }; //byte[] pduData = HYTFrameTool.FrameParseNoneLTV(finish); //byte[]lens = ByteProcessor.EncodeLength(127); //byte[]lens1 = ByteProcessor.EncodeLength(128); //byte[] bb = { 0xFF,0x7F}; //int value = ByteProcessor.DecodeLength(bb,out int number); _portManager = new SerialPortManager(); PortNameList = new List<string>(SerialPortManager.GetPortNames()); BaudRateList = new List<int>(){4800, 9600,14400, 19200, 28800, 38400,57600, 115200}; DataBitsList = new List<int>(){5, 6, 7, 8}; ParityList = new List<Parity>(); foreach (Parity o in Enum.GetValues(typeof(Parity))) { ParityList.Add(o); } StopBitsList = new List<StopBits>(); foreach (StopBits o in Enum.GetValues(typeof(StopBits))) { StopBitsList.Add(o); } //当前参数 _currentSerialportParamter = new CurrentSerialportParamter() { PortName = PortNameList[0], BaudRate = BaudRateList[1], DataBits = DataBitsList[3], Parity = ParityList[0], StopBits = StopBitsList[1], }; //SetLogs(); StartReceive(); //CancleToken(); //TestChannle(); } private async Task TestChannle() { // 创建容量为10的有界通道 var channel = Channel.CreateBounded<int>(10); // 生产者任务 var producer = Task.Run(async () => { for (int i = 0; i < 20; i++) { await channel.Writer.WriteAsync(i); Debug.WriteLine($"生产: {i}"); await Task.Delay(100); // 每100ms生产一个 } channel.Writer.Complete(); // 写入完成 }); // 消费者任务 var consumer = Task.Run(async () => { await foreach (var item in channel.Reader.ReadAllAsync()) { Debug.WriteLine($"消费: {item}"); await Task.Delay(200); // 每200ms消费一个 } }); await Task.WhenAll(producer, consumer); } private void CancleToken() { CancellationTokenSource cts = new CancellationTokenSource(5000); //注册一个线程取消后执行的逻辑 cts.Token.Register(() => { //这里执行线程被取消后的业务逻辑. Debug.WriteLine("-------------被取消后的业务逻辑---------------------"); }); Task.Run(() => { while (!cts.IsCancellationRequested) { Thread.Sleep(300); Debug.WriteLine("当前thread={0} 正在运行", Thread.CurrentThread.ManagedThreadId); } }, cts.Token); //线程休眠到指定时间后取消 Thread.Sleep(2000); cts.Cancel(); //延时取消 2s后自动取消 //cts.CancelAfter(new TimeSpan(0, 0, 0, 2)); } private void StartReceive() { Task.Factory.StartNew(async () => { while (true) { var buffer = await _portManager.TryGetMessageAsync(-1); if (buffer == null) continue; AddLog(buffer, LogType.Receive,"主动接受"); } }, TaskCreationOptions.LongRunning); //Task.Run(async () => //{ // while (true) // { // var buffer = await _portManager.TryGetMessageAsync(); // if (buffer == null) continue; // AddLog(buffer, LogType.Receive); // } //}); } public DelegateCommand OpenPortCmd => new DelegateCommand(() => { if (!IsOpen) { IsOpen = _portManager.OpenCom(CurrentSerialportParamter.PortName, CurrentSerialportParamter.BaudRate, CurrentSerialportParamter.DataBits, CurrentSerialportParamter.Parity, CurrentSerialportParamter.StopBits); if (IsOpen) { OpenPortText = "关闭串口"; } } else { IsOpen = false; _portManager.Close(); OpenPortText = "打开串口"; } }); public DelegateCommand ParseFrameCmd => new DelegateCommand(() => { //byte[] folderInfo = {0x28,0x01, 0x00, 0x3E, 0x17, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC5 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC1 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC8 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x48, 0x49 ,0x45, // 0x04, 0x04, 0x00, 0x00, 0x03, 0xC0 , 0x06, 0x05, 0x42, 0x41, 0x2D ,0x43, 0x45, 0x44, // 0xA2 }; //var model = HYTFrameTool.FrameParseNoneNode(folderInfo); //Debug.WriteLine($"CommandId:{model.PDU.CommandId}"); //foreach (var item in model.PDU.Childer) //{ // if (item.Type == 0x04) // { // Debug.WriteLine(item.ValueAsInt32); // } // if (item.Type == 0x05) // { // Debug.WriteLine(item.ValueAsString); // } //} //格式:[LT LTV LTV LTV LT LTV LTV] type=0x81,实际是01,有字节点所高位改1(byte type = (byte)(type | 0x80); // 129) byte[] folderInfo = {0x28,0x01, 0x00, 0x46, 0x11, 0x0E, 0x81, 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC5 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, 0x0E, 0x81, 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC1 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, 0x0E, 0x81, 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC8 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x48, 0x49 ,0x45, 0x0E, 0x81 , 0x04, 0x04, 0x00, 0x00, 0x03, 0xC0 , 0x06, 0x05, 0x42, 0x41, 0x2D ,0x43, 0x45, 0x44, 0xA2 }; var model = HYTFrameTool.FrameParseWithNode(folderInfo); Debug.WriteLine($"CommandId:{model.PDU.CommandId}"); foreach (var item in model.PDU.Childer) { foreach (var ltv in item.Children) { if (ltv.Type == 0x04) { Debug.WriteLine(ltv.ValueAsInt32); } if (ltv.Type == 0x05) { Debug.WriteLine(ltv.ValueAsString); } } } //格式:[LTV LTV LTV] type的bit7=0 //byte[] receiveByte = await _portManager.SendByCallBack(pack); //byte[] folderInfo = {0x28,0x01, 0x00, 0x3E, 0x17, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC5 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC1 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC8 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x48, 0x49 ,0x45, // 0x04, 0x04, 0x00, 0x00, 0x03, 0xC0 , 0x06, 0x05, 0x42, 0x41, 0x2D ,0x43, 0x45, 0x44, // 0xA2 }; //var model = HYTFrameTool.FrameParseWithNode(folderInfo); //Debug.WriteLine($"CommandId:{model.PDU.CommandId}"); //foreach (var item in model.PDU.Childer) //{ // Debug.WriteLine(item.ValueAsString); //} }); //发送指令 public DelegateCommand SendDataCmd => new DelegateCommand(async () => { if (!_portManager.IsOpen) { _messageBoxService.ShowMessageBox("提示", "串口未打开",MessageBoxButton.OK, MessageBoxImage.Stop); return; } var send = SendDateText?.Trim(); byte[] byteArray; if (ISASCII) { byteArray = Encoding.ASCII.GetBytes(send); } else { byteArray = send.Split(' ', StringSplitOptions.RemoveEmptyEntries) .Select(hex => { hex = hex.Trim(); return Convert.ToByte(hex, 16); }).ToArray(); } AddLog(byteArray, LogType.Send); SendDateText = ""; //byte[] receiveByte = await _portManager.SendAndReceive(byteArray); byte[] receiveByte = await _portManager.SendAwaitResponse(byteArray); if (receiveByte.IsNullOrEmpty()) { return; } string receive = ""; for (int i = 0; i < receiveByte.Length; i++) { receive = receive + receiveByte[i].ToString("X2") + " "; } AddLog(receiveByte, LogType.Receive); }); private void AddLog(byte[] data,LogType type,string logDesc="") { string text = PrintHelper.PrintByteArray(data); LogModel lm = new LogModel() { LogInfo = text, LogType = type, LogDesc = logDesc, LogTime = DateTime.Now }; System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { LogList.Add(lm); })); } /// <summary> /// 帧组装 /// </summary> /// <param name="serviceId">服务ID,短指令02 文件08</param> /// <param name="pduData">PDU数据</param> /// <param name="circle">循环号,默认为1,分包每次+1</param> /// <param name="status">状态字,根据实际情况修改,默认00</param> /// <returns>帧数据</returns> /// status->Bit0:应答标志,0表示请求,1代表应答 /// Bit1:广播标志,0表示非广播包;1代表广播包,不用回复。 /// Bit2:复位标志,0表示正常;1代表务服通讯复位 /// Bit3:加密标志,0表示指令包不加密;1代表指令包加密。 /// Bit4:分片标志,0表示非分片模式;1表示分片模式。 /// Bit5:分片模式下尾片标志,0表示最后一片;1代表后面还有。 /// bit6:保留位 /// bit7:扩展标志,0表示普通帧,帧长度1字节,CRC使用CRC8;1代表扩展帧,帧长度2字节,CRC使用CRC16。 private byte[] PackSendData(byte serviceId, byte[]pduData,int circle = 1,byte status = 0x00) { int pduLen = pduData.Length; int packLenNoCrc = 0; bool lenIsOneByte = true; if (pduLen <= 250) { packLenNoCrc = pduLen + 4; status.SetBitRef(7,false); } else { packLenNoCrc = pduLen + 5; lenIsOneByte = false; status.SetBitRef(7, true); } byte[] dataArray = new byte[packLenNoCrc]; byte start = ByteProcessor.CombineByte(0x0A, serviceId); //帧起始+服务ID dataArray[0] = start; //循环号 dataArray[1] = (byte)circle; //状态字 dataArray[2] = status; //帧长度>127使用2个字节。<127 一个字节 dataArray[3] = (byte)(lenIsOneByte? packLenNoCrc + 1: packLenNoCrc + 2); byte[] packData = null; if (lenIsOneByte) { status.SetBitRef(7, false); dataArray[2] = status; dataArray[3] = (byte)(packLenNoCrc + 1); for (int i = 0; i < pduLen; i++) { dataArray[4 + i] = pduData[i]; } //生成带CRC的数据 packData = CRCCalculate.CalculateCRC_8(dataArray); } else { status.SetBitRef(7, true); dataArray[2] = status; dataArray[3] = (byte)(((packLenNoCrc + 2) >> 8) & 0xFF); dataArray[4] = (byte)((packLenNoCrc + 2) & 0xFF); for (int i = 0; i < pduLen; i++) { dataArray[5 + i] = pduData[i]; } //生成带CRC的数据 packData = CRCCalculate.CalculateCRC_16(dataArray); } return packData; } //获取连接参数(commandID = 0x11) public DelegateCommand GetConnectParCmd => new DelegateCommand(async () => { byte[] pdu = { 0x11 }; byte[] pack = PackSendData(0x02, pdu); SendDateText = PrintHelper.PrintByteArray(pack); }); //设置设备日期 public DelegateCommand SetDateTimeCmd => new DelegateCommand(() => { //时间戳 long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); // 将long(8字节) byte[] longBytes = BitConverter.GetBytes(timestamp); LtvData timeStamp = new LtvData() { Length = longBytes.Length, Type = 0x01, Value = longBytes }; byte[] bb = { 0x01, 0xE0 }; LtvData timeSection = new LtvData() { Length = bb.Length, Type = 0x02, Value = bb }; byte[] cc = { 0x00 }; LtvData timeFormat = new LtvData() { Length = cc.Length, Type = 0x03, Value = cc }; List<LtvData> models = new List<LtvData>(); models.Add(timeStamp); models.Add(timeSection); models.Add(timeFormat); List<byte> ltvs = new List<byte>(); foreach (var model in models) { ltvs.AddRange(model.GetLTVByteArrray()); } byte[] pduData = new byte[ltvs.Count + 1]; //commandID pduData[0] = 0x12; for (int i = 0; i < ltvs.Count; i++) { pduData[i + 1] = ltvs[i]; } byte[] pack = PackSendData(0x02, pduData); SendDateText = PrintHelper.PrintByteArray(pack); }); //获取设备日期 public DelegateCommand GetDateTimCmd => new DelegateCommand(() => { byte[] pdu = { 0x13 }; byte[] pack = PackSendData(0x02, pdu); SendDateText = PrintHelper.PrintByteArray(pack); }); //获取固件信息 public DelegateCommand GetFirmwareInfoCmd => new DelegateCommand(() => { byte[] pdu = { 0x14 }; byte[] pack = PackSendData(0x02, pdu); SendDateText = PrintHelper.PrintByteArray(pack); }); //进入OTA升级 public DelegateCommand EnterOTACmd => new DelegateCommand(() => { LtvData coutPack = new LtvData() { Length = 2, Type = 0x01, Value = new byte[] { 0x12,0x08 } }; LtvData sizePack = new LtvData() { Length = 4, Type = 0x02, Value = new byte[] { 0x12,0x23,0x33,0x34 } }; List<byte> ltvs = new List<byte>(); ltvs.AddRange(coutPack.GetLTVByteArrray()); ltvs.AddRange(sizePack.GetLTVByteArrray()); byte[] pduData = new byte[ltvs.Count + 1]; //commandID pduData[0] = 0x91; for (int i = 0; i < ltvs.Count; i++) { pduData[i + 1] = ltvs[i]; } byte[] pack = PackSendData(0x08, pduData); SendDateText = PrintHelper.PrintByteArray(pack); }); //退出升级模式 private void ExistUpdateModel() { byte[] pdu = { 0x92 }; byte[] pack = PackSendData(0x08, pdu); SendDateText = PrintHelper.PrintByteArray(pack); } //读取文件列表 public DelegateCommand StartLoadFileCmd => new DelegateCommand(() => { //MakeFirmwareData(); GetFolderInfo(); }); //发送文件 public DelegateCommand SendFileCmd => new DelegateCommand(() => { SendFile(); }); //获取文件详情 public DelegateCommand GetFileDetailCmd => new DelegateCommand(async () => { await GetFileDetail(0x00,"log001.txt"); }); private async Task SendFile() { string filePath = ""; OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = false; //该值确定是否可以选择多个文件 dialog.Title = "文件发送"; dialog.Filter = "Bin File|*.txt"; if (dialog.ShowDialog() == true) { filePath = Path.GetFullPath(dialog.FileName); // 读取二进制文件 byte[] fileData = File.ReadAllBytes(filePath); //下发文件配置信息 await SendFileConfig(filePath, fileData); //SendFileData(firmwareData); } } private async Task SendFileConfig(string filePath, byte[] fileData) { //第1步------------------发送文件配置信息 //文件类型 LtvData typeM = new LtvData() { Length = 1, Type = 0x01, Value = new byte[] { 0x01 } }; //文件大小 int fileSize = fileData.Length; byte[] bytes = BitConverter.GetBytes(fileSize); LtvData sizeM = new LtvData() { Length = 4, Type = 0x02, Value = bytes }; byte[]crc32 = CRCCalculate.CalculateCRC_32(fileData); //文件CRC LtvData crcM = new LtvData() { Length = 4, Type = 0x03, Value = crc32 }; //文件名 string name = Path.GetFileName(filePath); byte[] names = Encoding.GetBytes(name); LtvData nameM = new LtvData() { Length = names.Length, Type = 0x04, Value = names }; List<byte> ltvs = new List<byte>(); ltvs.AddRange(typeM.GetLTVByteArrray()); ltvs.AddRange(sizeM.GetLTVByteArrray()); ltvs.AddRange(crcM.GetLTVByteArrray()); ltvs.AddRange(nameM.GetLTVByteArrray()); byte[] pduData = new byte[ltvs.Count + 1]; //commandID pduData[0] = 0x21; for (int i = 0; i < ltvs.Count; i++) { pduData[i + 1] = ltvs[i]; } byte[] pack = PackSendData(0x08, pduData); AddLog(pack, LogType.Send); byte[] receive = await _portManager.SendAwaitResponse(pack); if (receive.IsNullOrEmpty()) { return; } AddLog(receive, LogType.Receive); //第2步------------ 发送开始指令 byte[] pdu = { 0x22 }; byte[] startPack = PackSendData(0x08, pdu); AddLog(startPack, LogType.Send); receive = await _portManager.SendAwaitResponse(startPack); if (receive.IsNullOrEmpty()) { return; } AddLog(receive, LogType.Receive); //第3步------------开始发送文件----------- int packetSize = 1024; int totalBytes = fileData.Length; int offset = 0; int count = 1; while (offset < totalBytes) { //发送的数据大小 int bytesToSend = Math.Min(packetSize, totalBytes - offset); //PDU大小=数据+ commandID(1字节) + 偏移(4字节) int pduLen = bytesToSend + 5; //PDU包组装 // 创建一个子数组用于当前要发送的数据包 byte[] filePduData = new byte[pduLen]; //commandID filePduData[0] = 0x24; //偏移offset filePduData[1] = (byte)((offset >> 24) & 0xFF); filePduData[2] = (byte)((offset >> 16) & 0xFF); filePduData[3] = (byte)((offset >> 8) & 0xFF); filePduData[4] = (byte)(offset & 0xFF); Array.Copy(fileData, offset, filePduData, 5, bytesToSend); //状态字 byte status = 0x00; //bit4 = 1 分片模式 status.SetBitRef(4, true); if (bytesToSend < packetSize) { status.SetBitRef(5, false); } else { status.SetBitRef(5, true); } byte[] packFileData = PackSendData(0x08, filePduData, count++, status); AddLog(packFileData, LogType.Send); receive = await _portManager.SendAwaitResponse(packFileData); if (!receive.IsNullOrEmpty()) { AddLog(receive, LogType.Receive); } // 更新偏移量 offset += bytesToSend; Thread.Sleep(300); } //第4步------------发送文件完毕 byte[] fileOver = { 0x23 }; byte[] packOver = PackSendData(0x08, fileOver); AddLog(packOver, LogType.Send); receive = await _portManager.SendAwaitResponse(packOver); if (receive.IsNullOrEmpty()) { AddLog(receive, LogType.Receive,"超时指令"); } else { AddLog(receive, LogType.Receive); } } //开发发送文件 private void StartSendFile() { byte start = ByteProcessor.CombineByte(0x0A, 0x08); byte[] dataArray = new byte[5]; //帧起始+服务ID dataArray[0] = start; //循环号 dataArray[1] = 0x01; //状态字 dataArray[2] = 0x00; //帧长度>127使用2个字节。<127 一个字节 dataArray[3] = 6; //commandID dataArray[4] = 0x22; byte[] packData = CRCCalculate.CalculateCRC_8(dataArray); SendDateText = PrintHelper.PrintByteArray(packData); } private void SendFileData(byte[] fileDate) { int packetSize = 125; int totalBytes = fileDate.Length; int offset = 0; int count = 1; while (offset < totalBytes) { //发送的数据大小 int bytesToSend = Math.Min(packetSize, totalBytes - offset); //PDU大小=数据+ commandID(1字节) + 偏移(4字节) int pduLen = bytesToSend + 5; //PDU包组装 // 创建一个子数组用于当前要发送的数据包 byte[] pduData = new byte[pduLen]; //commandID pduData[0] = 0x24; //偏移offset pduData[1] = (byte)(offset & 0xFF); pduData[2] = (byte)((offset >> 8) & 0xFF); pduData[3] = (byte)((offset >> 16) & 0xFF); pduData[4] = (byte)((offset >> 24) & 0xFF); Array.Copy(fileDate, offset, pduData, 5, bytesToSend); //状态字 byte status = 0x00; //bit4 = 1 分片模式 status.SetBitRef(4, true); if (bytesToSend < packetSize) { status.SetBitRef(5, false); } else { status.SetBitRef(5, true); } byte[] pack = PackSendData(0x08, pduData,count++,status); SendDateText = PrintHelper.PrintByteArray(pack); // 更新偏移量 offset += bytesToSend; Thread.Sleep(300); } } //文件发送完成 private void FinishSendFile() { byte[] pdu = { 0x23 }; byte[] pack = PackSendData(0x08, pdu); SendDateText = PrintHelper.PrintByteArray(pack); } public Encoding Encoding { get; set; } = Encoding.UTF8; private void MakeFirmwareData() { string v1 = "1.11"; var buffer = Encoding.GetBytes(v1); //固件版本 LtvData model1 = new LtvData() { Type = 0x01, Length = buffer.Length, Value = buffer, }; v1 = "1.12"; buffer = Encoding.GetBytes(v1); //内核版本 LtvData model2 = new LtvData() { Type = 0x02, Length = buffer.Length, Value = buffer, }; v1 = "1.13"; buffer = Encoding.GetBytes(v1); //应用版本 LtvData model3 = new LtvData() { Type = 0x03, Length = buffer.Length, Value = buffer, }; v1 = "1.14"; buffer = Encoding.GetBytes(v1); //应用版本 LtvData model4 = new LtvData() { Type = 0x04, Length = buffer.Length, Value = buffer, }; v1 = "1.15"; buffer = Encoding.GetBytes(v1); //应用版本 LtvData model5 = new LtvData() { Type = 0x05, Length = buffer.Length, Value = buffer, }; v1 = "1.16"; buffer = Encoding.GetBytes(v1); //应用版本 LtvData model6 = new LtvData() { Type = 0x06, Length = buffer.Length, Value = buffer, }; v1 = "1.17"; buffer = Encoding.GetBytes(v1); //应用版本 LtvData model7 = new LtvData() { Type = 0x07, Length = buffer.Length, Value = buffer, }; List<byte> ltvs = new List<byte>(); ltvs.AddRange(model1.GetLTVByteArrray()); ltvs.AddRange(model2.GetLTVByteArrray()); ltvs.AddRange(model3.GetLTVByteArrray()); ltvs.AddRange(model4.GetLTVByteArrray()); ltvs.AddRange(model5.GetLTVByteArrray()); ltvs.AddRange(model6.GetLTVByteArrray()); ltvs.AddRange(model7.GetLTVByteArrray()); byte start = ByteProcessor.CombineByte(0x0A, 0x02); byte[] dataArray = new byte[5 +ltvs.Count]; //帧起始+服务ID dataArray[0] = start; //循环号 dataArray[1] = 0x01; byte status = 0x00; status.SetBitRef(0,true); //状态字 dataArray[2] = status; //帧长度>127使用2个字节。<127 一个字节 int allLen = 5 + 1 + ltvs.Count; dataArray[3] = (byte)allLen; //commandID dataArray[4] = 0x14; for (int i = 0; i < ltvs.Count; i++) { dataArray[5 + i] = ltvs[i]; } byte[] packData = CRCCalculate.CalculateCRC_8(dataArray); SendDateText = PrintHelper.PrintByteArray(packData); } //获取文件详情,type:文件类型,filename:文件名字 private async Task GetFileDetail(int type,string fileName) { Debug.WriteLine($"GetFileDetail---------开始--线程id{Thread.CurrentThread.ManagedThreadId}"); //第1步---------------- 触发文件上传 byte[] pdu = { 0x12, 0x01, 0x01, 0x01, 0x04, 0x02, 0x41, 0x42, 0x2D, 0x43 }; byte[] pack = PackSendData(0x08, pdu); AddLog(pack, LogType.Send,"触发文件上传"); byte[] rec = await _portManager.SendAwaitResponse(pack); if (rec.IsNullOrEmpty()) { return; } AddLog(rec, LogType.Receive,"收到文件上传回应"); Debug.WriteLine("GetFileDetail---------开始"); //第2步--------------------- 接受文件描述配置(文件类型、文件大小,文件CRC) byte[] fileConfig = await _portManager.TryGetMessageAsync(); AddLog(fileConfig, LogType.Receive,"获取到文件的配置信息"); byte[] response2 = { 0x31, 0x02, 0x7F, 0x27, 0x10 }; //响应给下位机 byte status = 0x00; status.SetBitRef(0, true); byte[] response2Pack = PackSendData(0x08, response2, status: status); _portManager.Send(response2Pack); AddLog(response2Pack, LogType.Send,"响应文件配置信息ok"); //第3步 ---------------上传文件开始 byte[] fileStart = await _portManager.TryGetMessageAsync(); AddLog(fileStart, LogType.Receive,"收到文件开始上传指令"); byte[] response3 = { 0x32, 0x02, 0x7F, 0x27, 0x10 }; //响应给下位机 byte[] response3Pack = PackSendData(0x08, response3); _portManager.Send(response3Pack); AddLog(response3Pack, LogType.Send, "响应开始上传指令"); //第4步---------------开始上传文件(0x34) while (true) { byte[] rec1 = await _portManager.TryGetMessageAsync(); if (rec1.IsNullOrEmpty()) { break; } AddLog(rec1, LogType.Receive, "收到文件数据"); byte[] pduData = HYTFrameTool.FrameParseNoneLTV(rec1); //上传结束的包CommandId = 0x33 //A8 01 00 06 33 74 if (pduData[0] == 0x33 || rec.IsNullOrEmpty()) { byte[] responseFinish = { 0x33, 0x02, 0x7F, 0x27, 0x10 }; //响应给下位机 byte[] resFinishPack = PackSendData(0x08, responseFinish); _portManager.Send(resFinishPack); AddLog(responseFinish, LogType.Send, "响应结束包指令"); //需要回应结束 break; } byte[] response8 = { 0x34, 0x02, 0x7F, 0x27, 0x10 }; //响应给下位机 byte[] response8Pack = PackSendData(0x08, response8); _portManager.Send(response8Pack); AddLog(response3Pack, LogType.Send, "响应收到数据指令"); Thread.Sleep(100); } } //获取文件集信息 private async void GetFolderInfo() { //文件类型 byte[] typeData = new byte[] { 0x01,0x01,0x01 }; //文件数量 byte[] countData = { 0x01,0x02,0x05}; //文件方向 byte[] directionData = { 0x01 ,0x03, 0x01 }; byte[] pdu = new byte[10]; pdu[0] = 0x11; Array.Copy(typeData,0, pdu,1,typeData.Length); Array.Copy(countData, 0, pdu,4, countData.Length); Array.Copy(directionData, 0, pdu,7, directionData.Length); byte[] pack = PackSendData(0x08, pdu); SendDateText = PrintHelper.PrintByteArray(pack); return; byte[] folderInfo = await _portManager.SendAwaitResponse(pack); //byte[] folderInfo = {0x28,0x01, 0x00, 0x3E, 0x17, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC5 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC1 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC8 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x48, 0x49 ,0x45, // 0x04, 0x04, 0x00, 0x00, 0x03, 0xC0 , 0x06, 0x05, 0x42, 0x41, 0x2D ,0x43, 0x45, 0x44, // 0xA2 }; //byte[] folderInfo = {0x11, // 0x0E, 0x01, 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC5 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x0E, 0x01, 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC1 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x43, 0x44 ,0x45, // 0x0E, 0x01, 0x04, 0x04 ,0x00, 0x00 ,0x03, 0xC8 , 0x06, 0x05 ,0x41, 0x42, 0x2D, 0x48, 0x49 ,0x45, // 0x0E, 0x01 , 0x04, 0x04, 0x00, 0x00, 0x03, 0xC0 , 0x06, 0x05, 0x42, 0x41, 0x2D ,0x43, 0x45, 0x44 }; if (!folderInfo.IsNullOrEmpty()) { var nodes = ParseHierarchicalLtv(folderInfo); foreach (var item in nodes) { FileModel fileM = new FileModel(); fileM.Type = "txt"; foreach (var node in item.Children) { if (node.Type == 0x04) { fileM.Size = node.ValueAsInt32; Debug.WriteLine(node.ValueAsInt32); } if (node.Type == 0x05) { fileM.Name = node.ValueAsString; } } FileList.Add(fileM); } } } public DelegateCommand ClearnLogCmd => new DelegateCommand(() => { LogList.Clear(); }); //带子节点的数据解析(首字节为commandId) // 0x11 [ID] //├─ 子节点A(0x0E 0x01) //│ ├─ 子节点A1(0x04 0x04 0x00 0x00 0x03 0xC8) //│ └─ 子节点A2(0x06 0x05 0x41 0x42 0x2D 0x43 0x44 0x45) //└─ 子节点B(0x0E 0x01) // ├─ 子节点B1(0x04 0x04 0x00 0x00 0x03 0xC8) // └─ 子节点B2(0x06 0x05 0x42 0x41 0x2D 0x43 0x45 0x44) public List<LtvData> ParseHierarchicalLtv(byte[] data) { var rootNodes = new List<LtvData>(); int index = 1; // 跳过0x11 while (index < data.Length) { // 解析父节点 (0x0E 0x01) var parentNode = new LtvData { Length = data[index++], Type = data[index++] }; int parentEndIndex = index + parentNode.Length; // 解析子节点 while (index < parentEndIndex) { var childNode = new LtvData { Length = data[index++], Type = data[index++], }; childNode.Value = new byte[childNode.Length]; Array.Copy(data, index, childNode.Value, 0, childNode.Length); index += childNode.Length; parentNode.Children.Add(childNode); } rootNodes.Add(parentNode); } return rootNodes; } //首字节为commandID public List<LtvData> ParseLtvData(byte[] data) { var result = new List<LtvData>(); int index = 1; while (index < data.Length) { if (index + 2 >= data.Length) break; // 防止越界 int length = data[index]; int countLen = 1; if (length > 127) { byte hig = data[index]; byte low = data[index + 1]; countLen = 2; length = (hig & 0x7F) * 128 + low; } byte type = data[index + countLen]; byte[] value = new byte[length]; // 检查是否有足够的数据 if (index + 1 + countLen + length > data.Length) throw new ArgumentException("Invalid LTV data: insufficient length"); Array.Copy(data, index + 1 + countLen, value, 0, length); result.Add(new LtvData { Length = length, Type = type, Value = value }); index += 1 + countLen + length; // 移动到下一个LTV } return result; } } }

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/23 14:13:09

JVM性能分析

CPU使用上升 top 查看cpu使用率高的进程 top -Hp pid查看进程下线程spu使用情况 CPU Profiling进行cpu使用情况统计&#xff08;或JProfiler&#xff09; 内存使用上升 通过分析dump 查找异常对象、不可达类分析、泄漏报表、线程使用情况、堆外内存分析 接口耗时上升 arthas分析…

作者头像 李华
网站建设 2025/12/23 10:31:52

商家福音!用PHP对接快递鸟接口,一键搞定单号所属快递识别

日常处理快递单时&#xff0c;C端用户查物流直接搜单号就行&#xff0c;但商家场景完全不同——每天面对成百上千个混杂着顺丰、中通、韵达等不同快递的单号&#xff0c;先搞清楚每个单号属于哪家快递&#xff0c;才能顺利发起物流追踪&#xff0c;这个环节要是靠人工比对&…

作者头像 李华
网站建设 2025/12/22 21:20:05

YT29B凿岩机吕梁精准检测稳定性能解析

近年来&#xff0c;国内凿岩设备市场呈现出明显的区域分化特征。以吕梁为代表的山西资源型城市&#xff0c;因矿山开采、隧道掘进及基础设施建设需求持续释放&#xff0c;对风动凿岩机、气腿式凿岩机等主力机型的采购活跃度居高不下。据2025年第三季度行业监测数据显示&#xf…

作者头像 李华
网站建设 2025/12/23 8:05:24

26、网络连接与安全全解析

网络连接与安全全解析 在当今数字化时代,网络连接和网络安全是我们日常使用计算机时不可忽视的重要方面。下面我们将详细探讨网络连接相关文件、网络安全的多个要点,包括密码安全、远程登录以及防火墙配置等内容。 网络连接相关文件问答 首先,我们来看一些关于连接互联网…

作者头像 李华
网站建设 2025/12/22 16:44:14

2025.12.16 HSRP双机热备

1&#xff09;拓扑图2&#xff09;实验步骤2.1 PC机配置PC0 PC1PC22.2 路由器配置2.3 交换机配置SW3 SW1SW22.4 测试PC0 ping PC1PC0 ping PC2

作者头像 李华
网站建设 2025/12/23 18:36:17

万全智能RFID模块设备他们产品档次怎么样

万全智能的RFID模块设备在行业内属于中高端档次&#xff0c;其产品特点主要体现在以下方面&#xff1a; 技术性能 读写能力 支持多协议兼容&#xff08;如EPC Class1 Gen2、ISO 18000-6C等&#xff09;&#xff0c;读写距离可达10米以上&#xff08;超高频型号&#xff09;&…

作者头像 李华