|
|
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
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// MultiClientsWindow.xaml 的交互逻辑
|
|
|
/// </summary>
|
|
|
public partial class TCPWindowV2 : Window
|
|
|
{
|
|
|
|
|
|
public class PanelItem : INotifyPropertyChanged //实现组件更改的接口
|
|
|
{
|
|
|
IPAddress ip;
|
|
|
int port;
|
|
|
TcpClient client;
|
|
|
public string option;//命令选项
|
|
|
private ObservableCollection<TagItem> _tagItems;
|
|
|
public ObservableCollection<TagItem> 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 _port1readtext;
|
|
|
private string _port2readtext;
|
|
|
private string _port3readtext;
|
|
|
private string _port4readtext;//设置读功率1-4
|
|
|
|
|
|
private string _port1writetext;
|
|
|
private string _port2writetext;
|
|
|
private string _port3writetext;
|
|
|
private string _port4writetext;//设置读功率1-4
|
|
|
|
|
|
public string Port1ReadText { get => _port1readtext; set { _port1readtext = value; OnPropertyChanged(); } }
|
|
|
public string Port2ReadText { get => _port2readtext; set { _port2readtext = value; OnPropertyChanged(); } }
|
|
|
public string Port3ReadText { get => _port3readtext; set { _port3readtext = value; OnPropertyChanged(); } }
|
|
|
public string Port4ReadText { get => _port4readtext; set { _port4readtext = value; OnPropertyChanged(); } }
|
|
|
|
|
|
public string Port1WriteText { get => _port1writetext; set { _port1writetext = value; OnPropertyChanged(); } }
|
|
|
public string Port2WriteText { get => _port2writetext; set { _port2writetext = value; OnPropertyChanged(); } }
|
|
|
public string Port3WriteText { get => _port3writetext; set { _port3writetext = value; OnPropertyChanged(); } }
|
|
|
public string Port4WriteText { get => _port4writetext; set { _port4writetext = 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 LinkCommand setpowercomn; //设置功率
|
|
|
|
|
|
public LinkCommand getpowercomn;//获取功率
|
|
|
|
|
|
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);//绑定清空按钮的事件
|
|
|
setpowercomn = new LinkCommand(Button_SetPower);
|
|
|
getpowercomn = new LinkCommand(Button_GetPower);
|
|
|
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; } }
|
|
|
public LinkCommand _setpowercomn { get { return setpowercomn; } }
|
|
|
public LinkCommand _getpowercomn { get { return getpowercomn; } }
|
|
|
|
|
|
|
|
|
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<TagInfo> taglist = GetTagInfos(data);
|
|
|
ObservableCollection<TagItem> items = new ObservableCollection<TagItem>();
|
|
|
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 += $"端口{n+1}:{(Convert.ToInt32(readStateString.Substring(12+10*n,4),16)/100).ToString()} ";
|
|
|
tempWritestate += $"端口{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_SetPower()
|
|
|
{
|
|
|
|
|
|
try
|
|
|
{
|
|
|
if(_port1readtext == null || _port1writetext == null|| _port2readtext == null || _port2writetext == null || _port3readtext == null || _port3writetext == null || _port4readtext == null || _port4writetext == null)
|
|
|
{
|
|
|
MessageBox.Show("数值不可为空!");
|
|
|
return;
|
|
|
}
|
|
|
string setPowerString = "AA 55 14 42 ";//设置命令开头
|
|
|
int[] powers = new int[8] {int.Parse(_port1readtext),int.Parse(_port2readtext), int.Parse(_port3readtext), int.Parse(_port4readtext),
|
|
|
int.Parse(_port1writetext),int.Parse(_port2writetext),int.Parse(_port3writetext),int.Parse(_port4writetext)};
|
|
|
for (int i = 0; i < powers.Length/2; i++) {
|
|
|
setPowerString += $"0{i+1} {(powers[i]*100).ToString("X").PadLeft(4,'0').Insert(2," ")} {(powers[i+4] * 100).ToString("X").PadLeft(4, '0').Insert(2, " ")} ";
|
|
|
}//功率设置时为两位数,乘100后再转换为16进制字符串,再填满左侧保证4位数,最后两位两位隔开
|
|
|
setPowerString += "52 0D";//命令结尾
|
|
|
byte[] data = strToToHexByte(setPowerString);
|
|
|
client.Send(data);
|
|
|
|
|
|
byte[] confirmdata1 = strToToHexByte("AA 55 05 5F ");//保存命令
|
|
|
byte[] confirmdata2 = System.Text.Encoding.UTF8.GetBytes("\"SAVE\" ");
|
|
|
byte[] confirmdata3 = strToToHexByte("01 5A 0D");
|
|
|
|
|
|
byte[] confirmdata = new byte[confirmdata1.Length+ confirmdata2.Length+ confirmdata3.Length];
|
|
|
confirmdata1.CopyTo(confirmdata,0);
|
|
|
confirmdata2.CopyTo(confirmdata,confirmdata1.Length);
|
|
|
confirmdata3.CopyTo(confirmdata,confirmdata1.Length+ confirmdata2.Length);//保存命令拼接
|
|
|
client.Send(confirmdata);
|
|
|
data = strToToHexByte("AA 55 00 72 72 0D");//获取功率
|
|
|
client.Send(data);
|
|
|
}
|
|
|
catch(Exception e)
|
|
|
{
|
|
|
Infotext += $"处理请求时出错: {e.Message}\n";
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void Button_GetPower()
|
|
|
{
|
|
|
byte[] data = strToToHexByte("AA 55 00 72 72 0D");//获取功率
|
|
|
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<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;
|
|
|
|
|
|
private Action<int> _excutewithindex;
|
|
|
|
|
|
public LinkCommand(Action action) {
|
|
|
_excute = action;
|
|
|
}
|
|
|
|
|
|
public LinkCommand(Action<int> 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<TagInfo> GetTagInfos(byte[] AutoDealReportData)
|
|
|
{
|
|
|
List<TagInfo> tagInfoList = new List<TagInfo>();
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
/// <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;
|
|
|
}
|
|
|
|
|
|
private static void EnsureFolderExists(string folderPath)
|
|
|
{
|
|
|
// 检查指定的文件夹路径对应的文件夹是否已经存在
|
|
|
if (!Directory.Exists(folderPath))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
// 如果文件夹不存在,则尝试创建该文件夹
|
|
|
Directory.CreateDirectory(folderPath);
|
|
|
}
|
|
|
catch (IOException ex)
|
|
|
{
|
|
|
// 如果在创建文件夹过程中出现IOException异常(比如权限不足、磁盘已满等原因导致无法创建文件夹)
|
|
|
// 这里通过消息框向用户展示创建文件夹失败的异常信息,方便用户知晓问题所在
|
|
|
MessageBox.Show($"创建文件夹 {folderPath} 失败,异常信息: {ex.Message}");
|
|
|
// 重新抛出异常,让调用这个方法的上层代码知道创建文件夹出现了问题,以便进行进一步的处理,比如终止程序或者尝试其他恢复操作
|
|
|
throw;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|