using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.Eventing.Reader; using System.IO; using System.IO.Ports; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Xml; using K4os.Compression.LZ4.Streams.Abstractions; using Mesnac.Log; using Org.BouncyCastle.Utilities.Encoders; using TouchSocket.Core; using TouchSocket.Sockets; namespace SocketExample { /// /// MultiClientsWindow.xaml 的交互逻辑 /// public partial class TCPWindowV2 : Window { public class PanelItem : INotifyPropertyChanged //实现组件更改的接口 { IPAddress ip; int port; TcpClient client; public string option;//命令选项 private ObservableCollection _tagItems; public ObservableCollection TagItems { get => _tagItems; set { _tagItems = value; OnPropertyChanged(); } } public string Text { get; set; }//客户端编号 public string IPtext { get; set; }//IP文本框 public string Porttext { get; set; }//端口文本框 public string MessageText { get; set; }//发送框 private string _statecolour { get; set; }//状态指示灯 public string StateColour { get => _statecolour; set { _statecolour = value; OnPropertyChanged(); } } private string _linkstate;//链接状态文本 public string LinkState { get => _linkstate; set { _linkstate = value; OnPropertyChanged(); } } private string _infotext;//信息框 public string Infotext { get => _infotext; set { _infotext = value; OnPropertyChanged(); // 通知 UI 更新 } } private string _rssiinfo;//RSSI强度 public string RSSIinfo { get => _rssiinfo; set { _rssiinfo = value; OnPropertyChanged(); } } private string _countinfo;//count数值 public string Countinfo { get => _countinfo; set { _countinfo = value; OnPropertyChanged(); } } private string _timeinfo;//当前时间 public string Timeinfo { get => _timeinfo; set { _timeinfo = value; OnPropertyChanged(); } } private string _epcinfo;//EPC信息 private string _epcasc;//ASC2码 EPC信息 public string EPCinfo { get => _epcinfo; set { _epcinfo = value; OnPropertyChanged(); } } public string EPCASC { get => _epcasc; set { _epcasc = value; OnPropertyChanged(); } } private string _readpowerstate; public string ReadPowerState { get => _readpowerstate; set { _readpowerstate = value; OnPropertyChanged(); } } private string _writepowerstate; public string WritePowerState { get => _writepowerstate; set { _writepowerstate = value; OnPropertyChanged(); } } private string _gpo1; private string _gpo2; private string _gpo3; private string _gpo4;//GPO1-4状态 private string _gpi1; private string _gpi2; private string _gpi3; private string _gpi4;//GPIO1-4状态 public string GPO1 { get => _gpo1; set { _gpo1 = value; OnPropertyChanged(); } } public string GPO2 { get => _gpo2; set { _gpo2 = value; OnPropertyChanged(); } } public string GPO3 { get => _gpo3; set { _gpo3 = value; OnPropertyChanged(); } } public string GPO4 { get => _gpo4; set { _gpo4 = value; OnPropertyChanged(); } } public string GPI1 { get => _gpi1; set { _gpi1 = value; OnPropertyChanged(); } } public string GPI2 { get => _gpi2; set { _gpi2 = value; OnPropertyChanged(); } } public string GPI3 { get => _gpi3; set { _gpi3 = value; OnPropertyChanged(); } } public string GPI4 { get => _gpi4; set { _gpi4 = value; OnPropertyChanged(); } } private string _moduleinfo; private string _motherboardhardware; private string _motherboardfirmware;//设备信息 public string moduleInfo { get => _moduleinfo; set { _moduleinfo = value; OnPropertyChanged(); } } public string motherboardHardware { get => _motherboardhardware; set { _motherboardhardware = value; OnPropertyChanged(); } } public string motherboardFirmware { get => _motherboardfirmware; set { _motherboardfirmware = value; OnPropertyChanged(); } } public string path; public StreamWriter streamWriter; public LinkCommand linkcomn;//链接命令 public LinkCommand readcomn;//读取命令 public LinkCommand sendcomn;//发送命令 public LinkCommand disconnectcomn;//断连命令 public LinkCommand clearcomn;//清空命令 public PanelItem(int index) { Text = $"客户端{index + 1}"; linkcomn = new LinkCommand(Button_Link);//绑定按钮的链接事件 readcomn = new LinkCommand(Button_Read); sendcomn = new LinkCommand(Button_Click_Send);//绑定发送按钮的事件 disconnectcomn = new LinkCommand(Button_disconnect);//绑定断连按钮的事件 clearcomn = new LinkCommand(Button_clear);//绑定清空按钮的事件 try { path = Text + ".txt"; File.CreateText(path); } catch (Exception ex) { Infotext += ex; } //页面初始化 MessageText = string.Empty; IPtext = "192.168.0.7";//默认IP Porttext = "20108";//默认端口 StateColour = "Red"; LinkState = "未连接"; RSSIinfo = "##"; Countinfo = "00"; EPCASC = "###"; EPCinfo = "###"; GPO1 = "低"; GPO2 = "低"; GPO3 = "低"; GPO4 = "低"; GPI1 = "低"; GPI2 = "低"; GPI3 = "低"; GPI4 = "低"; } public LinkCommand _linkcomn { get { return linkcomn; } } public LinkCommand _readcomn { get { return readcomn; } } public LinkCommand _sendcomn { get { return sendcomn; } } public LinkCommand _disconnectcomn { get { return disconnectcomn; } } public LinkCommand _clearcomn { get { return clearcomn; } } private Task onSend(ITcpClient client, ReceivedDataEventArgs e) { return EasyTask.CompletedTask; } private Task onRecieved(ITcpClient client, ReceivedDataEventArgs e) //接收事件 { string time = DateTime.Now.ToString(); string currentTime = time.Substring(10, time.Length-10); var mes = e.ByteBlock.Span.ToString(Encoding.UTF8); byte[] data = e.ByteBlock.Span.ToArray(); string hexString = BitConverter.ToString(data).Replace("-", " "); Infotext += $"({currentTime})客户端接收到信息:\n{hexString}\n\n"; //读取状态 string readStateString = hexString.Replace(" ", "");//去掉字符串中空格 string dataLength = readStateString.Substring(4, 2);//获取字符串中内容长度 string commandState = readStateString.Substring(6, 2);//获取命令 int i = Convert.ToInt32(dataLength, 16); if (i != 0) { switch (commandState) { case "02": try { RSSIinfo = Convert.ToInt32(readStateString.Substring(14, 2), 16).ToString();//RSSI Countinfo = Convert.ToInt32(readStateString.Substring(12, 2), 16).ToString();//Count int TagNumber = Convert.ToInt32(readStateString.Substring(10,2),16); Timeinfo = $"{currentTime} {time.Substring(0, 10)}";//获取时间 int startTemp = 33; //Infotext += $"({currentTime})客户端接收到EPC信息:\n{EPCASC}\n\n"; List taglist = GetTagInfos(data); ObservableCollection items = new ObservableCollection(); for (int j = 0; j < taglist.Count; j++) { int TempLength = taglist[j].EPCstring.Length * 3 -1; EPCinfo = hexString.Substring(startTemp, TempLength); items.Add(new TagItem(taglist[j].EPCstring, EPCinfo, taglist[j].RSSI.ToString(), taglist[j].Count.ToString(), Timeinfo)); startTemp += 16 + TempLength; string year = DateTime.Now.ToString("yyyy-MM-dd"); EnsureFolderExists($"日志文件夹/{year}/{Text}"); path = $"日志文件夹/{year}/{Text}/" + path; writeToTxt(path, $"EPC:{taglist[j].EPCstring}\nHEX:{EPCinfo}\nRSSI:{taglist[j].RSSI.ToString()} Count:{taglist[j].Count.ToString()} Time:{Timeinfo}\n____________________________"); //LogService.Instance.Debug(""); } TagItems = items; } catch (Exception ex) { Infotext += ex; } break; case "81": //获取GPIO状态,16进制转二进制 string GPIBinInfo = Convert.ToString(Convert.ToInt32(readStateString.Substring(8, 2), 16), 2).PadLeft(8, '0'); string GPOBinInfo = Convert.ToString(Convert.ToInt32(readStateString.Substring(10, 2), 16), 2).PadLeft(8, '0'); for (int j = 4; j < GPOBinInfo.Length; j++) { //按位判断GPIO状态 switch (j) { case 4: if (GPOBinInfo.Substring(j, 1) == "1") GPO4 = "高"; else GPO4 = "低"; if (GPIBinInfo.Substring(j, 1) == "1") GPI4 = "高"; else GPI4 = "低"; break; case 5: if (GPOBinInfo.Substring(j, 1) == "1") GPO3 = "高"; else GPO3 = "低"; if (GPIBinInfo.Substring(j, 1) == "1") GPI3 = "高"; else GPI3 = "低"; break; case 6: if (GPOBinInfo.Substring(j, 1) == "1") GPO2 = "高"; else GPO2 = "低"; if (GPIBinInfo.Substring(j, 1) == "1") GPI2 = "高"; else GPI2 = "低"; break; case 7: if (GPOBinInfo.Substring(j, 1) == "1") GPO1 = "高"; else GPO1 = "低"; if (GPIBinInfo.Substring(j, 1) == "1") GPI1 = "高"; else GPI1 = "低"; break; default: break; } } break; case "72": //获取功率信息 try { string tempReadstate = ""; string tempWritestate = ""; for (int n = 0;n < (Convert.ToInt32(dataLength,16)/5);n++) { tempReadstate += $"A{n+1} : {(Convert.ToInt32(readStateString.Substring(12+10*n,4),16)/100).ToString()} "; tempWritestate += $"A{n + 1} : {(Convert.ToInt32(readStateString.Substring(16 + 10 * n, 4), 16) / 100).ToString()} "; } ReadPowerState = tempReadstate; WritePowerState = tempWritestate; tempReadstate = ""; tempWritestate = ""; } catch { } break; case "70": //获取设备信息 switch (option) { case "00": moduleInfo = Encoding.ASCII.GetString(HextoByte(readStateString.Substring(10, Convert.ToInt32(dataLength, 16) * 2))); //Infotext += $"({currentTime})客户端接收到module信息:\n{moduleInfo}\n\n"; writeToTxt(path, $"模块信息:{moduleInfo}"); break; case "03": motherboardHardware = Encoding.ASCII.GetString(HextoByte(readStateString.Substring(10, Convert.ToInt32(dataLength, 16) * 2))); //Infotext += $"({currentTime})客户端接收到hardware信息:\n{motherboardHardware}\n\n"; writeToTxt(path, $"硬件信息:{motherboardHardware}"); break; case "04": motherboardFirmware = Encoding.ASCII.GetString(HextoByte(readStateString.Substring(10, Convert.ToInt32(dataLength, 16) * 2))); //Infotext += $"({currentTime})客户端接收到firmware信息:\n{motherboardFirmware}\n\n"; writeToTxt(path, $"固件信息:{motherboardFirmware}"); option = ""; break; } break; default: Infotext += $"default"; break; } //streamWriter.Close(); } else { switch (commandState) { case "02": Infotext += "未读取到\n"; RSSIinfo = "##";//未读取到数值时清空数据为初始值 Countinfo = "00"; EPCASC = "###"; EPCinfo = "###"; Timeinfo = $" {currentTime}\n{time.Substring(0, 10)}";//获取时间 break; } } return EasyTask.CompletedTask; } private Task onConnected(ITcpClient client, ConnectedEventArgs e)//连接后初始化 { Infotext += "已连接!\n"; StateColour = "Green"; LinkState = "已连接"; //streamWriter = new StreamWriter(path); byte[] data = strToToHexByte("AA 55 01 70 00 71 0D");//获取模块信息 option = "00"; client.Send(data); Thread.Sleep(500); data = strToToHexByte("AA 55 01 70 03 72 0D");//获取主板硬件信息 option = "03"; client.Send(data); Thread.Sleep(500); data = strToToHexByte("AA 55 01 70 04 75 0D");//获取主板固件信息 option = "04"; client.Send(data); Thread.Sleep(500); data = strToToHexByte("AA 55 00 81 81 0D");//获取GPIO状态 client.Send(data); Thread.Sleep(500); data = strToToHexByte("AA 55 00 72 72 0D");//获取功率状态 client.Send(data); Thread.Sleep(500); data = strToToHexByte("AA 55 02 02 03 E8 EB 0D");//获取1000ms内标签信息 client.Send(data); return EasyTask.CompletedTask; } private static byte[] HextoByte(string Temp) { byte[] Tempbytes = new byte[Temp.Length / 2];//16进制转byte数组 for (int m = 0; m < Temp.Length; m += 2) { try { Tempbytes[m / 2] = Convert.ToByte(Temp.Substring(m, 2), 16); } catch (Exception excp) { } } return Tempbytes; } private static byte[] strToToHexByte(string hexString)//字符串转16进制 { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16); return returnBytes; } private static void writeToTxt(string path,string content) { StreamWriter streamWriter = new StreamWriter(path,true); streamWriter.WriteLineAsync(content); streamWriter.Close(); } async void Button_Link()//链接按钮的事件 { try { ip = IPAddress.Parse(IPtext); port = int.Parse(Porttext); Infotext += $"{Text}"; client = new TcpClient(); //连接事件 client.Connected += onConnected; //断连事件 client.Closed = (client, e) => { Infotext += "已断开!\n"; StateColour = "Red"; LinkState = "未连接"; return EasyTask.CompletedTask; }; //接收事件 client.Received += onRecieved; //设置连接属性 await client.SetupAsync(new TouchSocketConfig().SetRemoteIPHost($"{IPtext}:{Porttext}").ConfigureContainer(a => { a.AddConsoleLogger();//添加一个日志注入 })); //开启连接 await client.ConnectAsync(); } catch (Exception ex) { Infotext += $"处理请求时出错: {ex.Message}\n"; } } void Button_Read() { byte[] data = strToToHexByte("AA 55 02 02 03 E8 EB 0D");//获取1000ms内标签信息 client.Send(data); } void Button_Click_Send()//发送按钮的事件 { try { string message = MessageText; if (message == string.Empty) { MessageBox.Show("输入内容不能为空!"); } else { byte[] data = Encoding.UTF8.GetBytes(message); client.Send(data);//发送原始数据 client.Send(strToToHexByte(message));//发送16进制数据 } } catch (Exception ex) { Infotext += $"处理请求时出错: {ex.Message}\n"; } } void Button_disconnect() { client.Close();//断开连接 } void Button_clear() { Infotext = string.Empty;//清空信息框 } //组件属性更改事件 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public class TagItem : INotifyPropertyChanged { private string _rssiinfo;//RSSI强度 public string RSSIinfo { get => _rssiinfo; set { _rssiinfo = value; OnPropertyChanged(); } } private string _countinfo;//count数值 public string Countinfo { get => _countinfo; set { _countinfo = value; OnPropertyChanged(); } } private string _timeinfo;//当前时间 public string Timeinfo { get => _timeinfo; set { _timeinfo = value; OnPropertyChanged(); } } private string _epcinfo;//EPC信息 private string _epcasc;//ASC2码 EPC信息 public string EPCinfo { get => _epcinfo; set { _epcinfo = value; OnPropertyChanged(); } } public string EPCASC { get => _epcasc; set { _epcasc = value; OnPropertyChanged(); } } public TagItem(string infoEPC,string ascEPC,string RSSI,string count,string time) { EPCinfo = infoEPC; EPCASC = ascEPC; RSSIinfo = RSSI; Countinfo = count; Timeinfo = time; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } public TCPWindowV2() { InitializeComponent(); EnsureFolderExists("日志文件夹"); } int currentcount = 0;//目前客户端的数量 List items = new List();//客户端组件列表 private void GenerateButton_Click(object sender, RoutedEventArgs e)//添加客户端框体 { if (int.TryParse(CountTextBox.Text, out int count) && count > 0) { //var items = new List(); for (int i = 0; i < count; i++) { items.Add(new PanelItem(i + currentcount)); } currentcount += count; PanelContainer.ItemsSource = null;//刷新 PanelContainer.ItemsSource = items; } else { MessageBox.Show("请输入有效的正整数", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } public class LinkCommand : ICommand //command方法实现 { private Action _excute; private Action _excutewithindex; public LinkCommand(Action action) { _excute = action; } public LinkCommand(Action action) { _excutewithindex = action; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return true; } public void Execute(object parameter) { _excute(); } } private void ClearButton_Click(object sender, RoutedEventArgs e)//清空客户端 { items.Clear(); PanelContainer.ItemsSource = null; currentcount = 0; } private static List GetTagInfos(byte[] AutoDealReportData) { List tagInfoList = new List(); try { 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; int dataLength = Convert.ToInt32(AutoDealReportData[2].ToString()); 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); //PC转二进制取前五位转十进制 int epcLength = Convert.ToInt32(Convert.ToString(Convert.ToInt64(tempPCByte[0].ToString("X"), 16), 2).PadLeft(8, '0').Substring(0, 5), 2) * 2; 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 = HexStringToNegative(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; tag.EPCstring = System.Text.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; iCommonSecondFlag++; if (iCommonSecondFlag == iBarcodeGroupCount) { //mutauto.ReleaseMutex(); return tagInfoList; } } } catch (Exception ex) { //LogInfo.Info("----函数调用:Device_AutoDealContent 自动处理函数异常:" + ex.ToString()); //mutauto.ReleaseMutex(); } return tagInfoList; } public static int HexStringToNegative(string strNumber) { int iNegate = 0; int iNumber = Convert.ToInt32(strNumber, 16); if (iNumber > 127) { int iComplement = iNumber - 1; string strNegate = string.Empty; char[] binchar = Convert.ToString(iComplement, 2).PadLeft(8, '0').ToArray(); foreach (char ch in binchar) { if (Convert.ToInt32(ch) == 48) { strNegate += "1"; } else { strNegate += "0"; } } iNegate = -Convert.ToInt32(strNegate, 2); } return iNegate; } public class TagInfo { public byte[] PC = new byte[2]; public int Count; public int RSSI; public int Antana; public byte[] EPC; public byte[] Data; public string PCstring = null; public string EPCstring = null; public DateTime Time; } /// /// 将byte数组转换成十六进制字符串 //e.g. { 0x01, 0x01} ---> " 01 01" /// /// byte数组 /// 数组长度 /// 十六进制字符串 public static string bytesToHexStr(byte[] bytes, int iLen) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < iLen; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } private static void EnsureFolderExists(string folderPath) { // 检查指定的文件夹路径对应的文件夹是否已经存在 if (!Directory.Exists(folderPath)) { try { // 如果文件夹不存在,则尝试创建该文件夹 Directory.CreateDirectory(folderPath); } catch (IOException ex) { // 如果在创建文件夹过程中出现IOException异常(比如权限不足、磁盘已满等原因导致无法创建文件夹) // 这里通过消息框向用户展示创建文件夹失败的异常信息,方便用户知晓问题所在 MessageBox.Show($"创建文件夹 {folderPath} 失败,异常信息: {ex.Message}"); // 重新抛出异常,让调用这个方法的上层代码知道创建文件夹出现了问题,以便进行进一步的处理,比如终止程序或者尝试其他恢复操作 throw; } } } } }