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;
}
}
}
}
}