You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

593 lines
24 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Eventing.Reader;
using System.IO.Ports;
using System.Linq;
using System.Net;
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 Org.BouncyCastle.Utilities.Encoders;
using TouchSocket.Core;
using TouchSocket.Sockets;
using static SocketExample.TCPWindow;
namespace SocketExample
{
/// <summary>
/// MultiClientsWindow.xaml 的交互逻辑
/// </summary>
public partial class TCPWindow : Window
{
public class PanelItem : INotifyPropertyChanged //实现组件更改的接口
{
IPAddress ip;
int port;
TcpClient client;
public string option;//命令选项
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 _gpio1;
private string _gpio2;
private string _gpio3;
private string _gpio4;//GPIO1-4状态
public string GPIO1 { get => _gpio1; set { _gpio1 = value; OnPropertyChanged(); } }
public string GPIO2 { get => _gpio2; set { _gpio2 = value; OnPropertyChanged(); } }
public string GPIO3 { get => _gpio3; set { _gpio3 = value; OnPropertyChanged(); } }
public string GPIO4 { get => _gpio4; set { _gpio4 = 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 LinkCommand linkcomn;//链接命令
public LinkCommand sendcomn;//发送命令
public LinkCommand disconnectcomn;//断连命令
public LinkCommand clearcomn;//清空命令
public PanelItem(int index)
{
Text = $"客户端{index + 1}";
linkcomn = new LinkCommand(Button_Link);//绑定按钮的链接事件
sendcomn = new LinkCommand(Button_Click_Send);//绑定发送按钮的事件
disconnectcomn = new LinkCommand(Button_disconnect);//绑定断连按钮的事件
clearcomn = new LinkCommand(Button_clear);//绑定清空按钮的事件
//页面初始化
MessageText = string.Empty;
IPtext = "192.168.0.7";//默认IP
Porttext = "20108";//默认端口
StateColour = "Red";
LinkState = "未连接";
RSSIinfo = "##";
Countinfo = "00";
EPCASC = "###";
EPCinfo = "###";
GPIO1 = "低";
GPIO2 = "低";
GPIO3 = "低";
GPIO4 = "低";
}
public LinkCommand _linkcomn { get { return linkcomn; } }
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, 5);
var mes = e.ByteBlock.Span.ToString(Encoding.UTF8);
byte[] data = e.ByteBlock.Span.ToArray();
string hexString = BitConverter.ToString(data).Replace("-", " ");
//Infotext += $"({currentTime})客户端接收到信息:\n{mes}\n\n";
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":
List<TagInfo>taglist = GetTagInfos(data);
RSSIinfo = Convert.ToInt32(readStateString.Substring(14, 2), 16).ToString();//RSSI
Countinfo = Convert.ToInt32(readStateString.Substring(12, 2), 16).ToString();//Count
Timeinfo = $" {currentTime}\n{time.Substring(0, 10)}";//获取时间
string Temp = readStateString.Substring(22, 34);
byte[] Tempbytes = HextoByte(Temp);//16进制转byte数组
EPCASC = Encoding.ASCII.GetString(Tempbytes);//byte数组转String
EPCinfo = hexString.Substring(33, 50);//16进制原数据
//Infotext += $"({currentTime})客户端接收到EPC信息\n{EPCASC}\n\n";
break;
case "81":
//获取GPIO状态16进制转二进制
string GPIOBinInfo = Convert.ToString(Convert.ToInt32(readStateString.Substring(12, 2), 16), 2).PadLeft(4, '0');
for (int j = 0; j < GPIOBinInfo.Length; j++)
{
//按位判断GPIO状态
switch (j)
{
case 0:
if (GPIOBinInfo.Substring(j, 1) == "1")
GPIO4 = "高";
else
GPIO4 = "低";
break;
case 1:
if (GPIOBinInfo.Substring(j, 1) == "1")
GPIO3 = "高";
else
GPIO3 = "低";
break;
case 2:
if (GPIOBinInfo.Substring(j, 1) == "1")
GPIO2 = "高";
else
GPIO2 = "低";
break;
case 3:
if (GPIOBinInfo.Substring(j, 1) == "1")
GPIO1 = "高";
else
GPIO1 = "低";
break;
default:
break;
}
}
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";
break;
case "03":
motherboardHardware = Encoding.ASCII.GetString(HextoByte(readStateString.Substring(10, Convert.ToInt32(dataLength, 16) * 2)));
//Infotext += $"({currentTime})客户端接收到hardware信息\n{motherboardHardware}\n\n";
break;
case "04":
motherboardFirmware = Encoding.ASCII.GetString(HextoByte(readStateString.Substring(10, Convert.ToInt32(dataLength, 16) * 2)));
//Infotext += $"({currentTime})客户端接收到firmware信息\n{motherboardFirmware}\n\n";
option = "";
break;
}
break;
default:
break;
}
}
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 = "已连接";
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 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;
}
async void Button_Link()//链接按钮的事件
{
try
{
ip = IPAddress.Parse(IPtext);
port = int.Parse(Porttext);
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_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 TCPWindow()
{
InitializeComponent();
}
int currentcount = 0;//目前客户端的数量
List<PanelItem> items = new List<PanelItem>();//客户端组件列表
private void GenerateButton_Click(object sender, RoutedEventArgs e)//添加客户端框体
{
if (int.TryParse(CountTextBox.Text, out int count) && count > 0)
{
//var items = new List<PanelItem>();
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;
public LinkCommand(Action action) {
_excute = 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<TagInfo> GetTagInfos(byte[] AutoDealReportData)
{
List<TagInfo> tagInfoList = new List<TagInfo>();
try
{
//mutauto.WaitOne();
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++)
{
//int EPCLength = dataLength - (6 * iBarcodeGroupCount);
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;
//int pc = Convert.ToInt32(tempPCByte[0].ToString());
//int epcLength = EPCLengthByPC(pc);
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;
//if (pc == 24)
//{
// tag.EPCstring = StringChange.bytesToHexStr(tempDataByte, tempDataByte.Length).Substring(0, 7);
//}
//else
//{
// tag.EPCstring = System.Text.Encoding.ASCII.GetString(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;
// LogInfo.Info("----函数调用:Device_AutoDealContent 第[" + (iCommonSecondFlag + 1) + "]次数据解析为:" + StringChange.bytesToHexStr(tempDataByte, tempDataByte.Length) + ",读取标签次数:[" + tempDataCount + "],标签信号强度:[" + tempDataRSSI + "],天线号:[" + tempDataANT + "]");
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;
}
/// <summary>
/// 将byte数组转换成十六进制字符串 //e.g. { 0x01, 0x01} ---> " 01 01"
/// </summary>
/// <param name="bytes">byte数组</param>
/// <param name="iLen">数组长度</param>
/// <returns>十六进制字符串</returns>
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;
}
}
}