|
|
using System;
|
|
|
using System.Buffers.Text;
|
|
|
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.Runtime.InteropServices;
|
|
|
using System.Runtime.Remoting.Messaging;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Windows;
|
|
|
using System.Windows.Controls;
|
|
|
using System.Windows.Input;
|
|
|
using System.Windows.Markup;
|
|
|
using System.Windows.Media;
|
|
|
using System.Windows.Media.Imaging;
|
|
|
using System.Windows.Shapes;
|
|
|
using System.Xml;
|
|
|
using GalaSoft.MvvmLight.Command;
|
|
|
using Google.Protobuf.WellKnownTypes;
|
|
|
using K4os.Compression.LZ4.Streams.Abstractions;
|
|
|
using Mesnac.Log;
|
|
|
using Microsoft.Xaml.Behaviors.Core;
|
|
|
using Mysqlx.Crud;
|
|
|
using Org.BouncyCastle.Utilities;
|
|
|
using Org.BouncyCastle.Utilities.Encoders;
|
|
|
using TouchSocket.Core;
|
|
|
using TouchSocket.Sockets;
|
|
|
using ZstdSharp.Unsafe;
|
|
|
|
|
|
namespace SocketExample
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// MultiClientsWindow.xaml 的交互逻辑
|
|
|
/// </summary>
|
|
|
public partial class TCPWindowV2 : Window
|
|
|
{
|
|
|
|
|
|
public class PanelItem : INotifyPropertyChanged //实现组件更改的接口
|
|
|
{
|
|
|
#region 变量定义
|
|
|
IPAddress ip;
|
|
|
int port;
|
|
|
TcpClient client;
|
|
|
public string option;//命令选项
|
|
|
public ICommand TextChangedCommand { get; }
|
|
|
public ICommand SelectionChangedCommand { get; }
|
|
|
public ICommand SendTextChangedCommand { get; }
|
|
|
|
|
|
public ICommand GPOSelectionChangedCommand { get; }
|
|
|
|
|
|
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; }//端口文本框
|
|
|
private string _messagetext;
|
|
|
|
|
|
public int Borderwidth { get => _borderwidth; set { _borderwidth = value; OnPropertyChanged(); } }
|
|
|
private int _borderwidth { get; set; }
|
|
|
public string MessageText { get => _messagetext; set { _messagetext = value; OnPropertyChanged(); } }//发送框
|
|
|
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(); } }
|
|
|
|
|
|
public string LinkButtonText { get => _linkbuttontext; set { _linkbuttontext = value; OnPropertyChanged(); } }
|
|
|
private string _linkbuttontext { get; set; }
|
|
|
|
|
|
private string _infotext;//信息框
|
|
|
public string Infotext
|
|
|
{
|
|
|
get => _infotext; set
|
|
|
{
|
|
|
_infotext = value;
|
|
|
OnPropertyChanged(); // 通知 UI 更新
|
|
|
}
|
|
|
}
|
|
|
public string _actiontype;//触发动作
|
|
|
public string ActionType { get => _actiontype; set { _actiontype = value; OnPropertyChanged(); } }
|
|
|
|
|
|
public string _timeout;//时间段盘点
|
|
|
public string TimeOut { get => _timeout; set { _timeout = value; OnPropertyChanged(); } }
|
|
|
|
|
|
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
|
|
|
|
|
|
private int[] _portComboBox;
|
|
|
private string[] _gpoComboBox;
|
|
|
private string[] _sendtextComboBox;//下拉框数据源
|
|
|
|
|
|
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(); } }
|
|
|
public int[] PortComboBox { get => _portComboBox; set { _portComboBox = value; OnPropertyChanged(); } }
|
|
|
public string[] GPOComboBox { get => _gpoComboBox; set { _gpoComboBox = value; OnPropertyChanged(); } }
|
|
|
public string[] SendTextComboBox { get => _sendtextComboBox; set { _sendtextComboBox = 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 { if (_gpi1 != value && _gpi1 != null) { _gpi1 = value; OnPropertyChanged(); } else { _gpi1 = value; OnPropertyChanged(); } } }
|
|
|
public string GPI2 { get => _gpi2; set { if (_gpi2 != value && _gpi1 != null) { _gpi2 = value; OnPropertyChanged(); } else { _gpi2 = value; OnPropertyChanged(); } } }
|
|
|
public string GPI3 { get => _gpi3; set { if (_gpi3 != value && _gpi1 != null) { _gpi3 = value; OnPropertyChanged(); } else { _gpi3 = value; OnPropertyChanged(); } } }
|
|
|
public string GPI4 { get => _gpi4; set { if (_gpi4 != value && _gpi1 != null) { _gpi4 = value; OnPropertyChanged(); } else { _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 LinkCommand stopreadingcomn;//停止连续读取功能
|
|
|
|
|
|
public LinkCommand sendactioncomn;
|
|
|
|
|
|
public LinkCommand powerselectchanged;
|
|
|
|
|
|
Thread GPIOthread;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
public PanelItem(int index)
|
|
|
{
|
|
|
Text = $"客户端{index + 1}";
|
|
|
linkcomn = new LinkCommand(Button_Link);//绑定按钮的链接事件
|
|
|
readcomn = new LinkCommand(Button_Read);
|
|
|
stopreadingcomn = new LinkCommand(Button_StopReading);
|
|
|
sendcomn = new LinkCommand(Button_Click_Send);//绑定发送按钮的事件
|
|
|
sendactioncomn = new LinkCommand(Button_SendActionComn);
|
|
|
disconnectcomn = new LinkCommand(Button_disconnect);//绑定断连按钮的事件
|
|
|
clearcomn = new LinkCommand(Button_clear);//绑定清空按钮的事件
|
|
|
setpowercomn = new LinkCommand(Button_SetPower);
|
|
|
getpowercomn = new LinkCommand(Button_GetPower);
|
|
|
SelectionChangedCommand = new RelayCommand<ComboBox>(ComboBox_SelectChanged);
|
|
|
GPOSelectionChangedCommand = new RelayCommand<ComboBox>(GPOComboBox_SelectChanged);
|
|
|
SendTextChangedCommand = new RelayCommand<ComboBox>(SendTextComboBox_SelectChanged);
|
|
|
TextChangedCommand = new RelayCommand<ScrollViewer>(TextBlock_SelectChanged);
|
|
|
|
|
|
//页面初始化
|
|
|
int[] Powerdatasource = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 };
|
|
|
string[] GPOdatasource = { "高", "低" };
|
|
|
string[] SendTextdatasource = { "单次盘点", "时间段盘点" };
|
|
|
|
|
|
Borderwidth = GetTerminalWidth(); //动态生成界面宽度
|
|
|
MessageText = string.Empty;
|
|
|
IPtext = "192.168.0.7";//默认IP
|
|
|
Porttext = "20108";//默认端口
|
|
|
LinkButtonText = "连接";
|
|
|
StateColour = "Red";
|
|
|
LinkState = "未连接";
|
|
|
RSSIinfo = "##";
|
|
|
Countinfo = "00";
|
|
|
EPCASC = "###";
|
|
|
EPCinfo = "###";
|
|
|
PortComboBox = Powerdatasource;
|
|
|
GPOComboBox = GPOdatasource;
|
|
|
SendTextComboBox = SendTextdatasource;
|
|
|
GPO1 = "低";
|
|
|
GPO2 = "低";
|
|
|
GPO3 = "低";
|
|
|
GPO4 = "低";
|
|
|
GPI1 = "低";
|
|
|
GPI2 = "低";
|
|
|
GPI3 = "低";
|
|
|
GPI4 = "低";
|
|
|
}
|
|
|
#region 界面功能绑定定义
|
|
|
public LinkCommand _powerselectchanged { get { return powerselectchanged; } }
|
|
|
|
|
|
public LinkCommand _linkcomn { get { return linkcomn; } }
|
|
|
|
|
|
public LinkCommand _readcomn { get { return readcomn; } }
|
|
|
|
|
|
public LinkCommand _stopreadingcomn { get { return stopreadingcomn; } }
|
|
|
|
|
|
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; } }
|
|
|
public LinkCommand _sendactioncomn { get { return sendactioncomn; } }
|
|
|
#endregion
|
|
|
|
|
|
#region socket事件
|
|
|
|
|
|
private Task onSend(ITcpClient client, ReceivedDataEventArgs e)
|
|
|
{
|
|
|
|
|
|
return EasyTask.CompletedTask;
|
|
|
}
|
|
|
|
|
|
|
|
|
private Task onRecieved(ITcpClient client, ReceivedDataEventArgs e) //接收事件
|
|
|
{
|
|
|
Text = Text.Replace(" ", "");
|
|
|
path = "";
|
|
|
string time = DateTime.Now.ToString();
|
|
|
string currentTime = DateTime.Now.ToString("T");
|
|
|
var mes = e.ByteBlock.Span.ToString(Encoding.UTF8);
|
|
|
byte[] data = e.ByteBlock.Span.ToArray();
|
|
|
string hexString = BitConverter.ToString(data).Replace("-", " ");
|
|
|
|
|
|
//读取状态
|
|
|
string readStateString = hexString.Replace(" ", "");//去掉字符串中空格
|
|
|
string dataLength = readStateString.Substring(4, 2);//获取字符串中内容长度
|
|
|
string commandState = readStateString.Substring(6, 2);//获取命令
|
|
|
|
|
|
if (commandState != "81")
|
|
|
Infotext += $"\n({currentTime})客户端接收到信息:\n{hexString}\n";
|
|
|
|
|
|
int i = Convert.ToInt32(dataLength, 16);
|
|
|
if (i != 0)
|
|
|
{
|
|
|
switch (commandState)
|
|
|
{
|
|
|
case "01":
|
|
|
try
|
|
|
{
|
|
|
byte[] newData = new byte[data.Length + 1];
|
|
|
Array.Copy(data, 0, newData, 0, 5); // 复制前半部分 // 插入新值
|
|
|
Array.Copy(data, 5, newData, 5, 4);
|
|
|
Array.Copy(data, 5, newData, 6, data.Length - 5);
|
|
|
Timeinfo = $"{time}";//获取时间
|
|
|
|
|
|
//Infotext += $"({currentTime})客户端接收到EPC信息:\n{EPCASC}\n\n";
|
|
|
|
|
|
List<TagInfo> taglist = GetTagInfos(newData);
|
|
|
ObservableCollection<TagItem> items = new ObservableCollection<TagItem>();
|
|
|
for (int j = 0; j < taglist.Count; j++)
|
|
|
{
|
|
|
EPCinfo = BitConverter.ToString(taglist[j].EPC).Replace("-", "");
|
|
|
items.Add(new TagItem(hexString, taglist[j].EPCstring, EPCinfo, taglist[j].RSSI.ToString(), taglist[j].Count.ToString(), Timeinfo));
|
|
|
string year = DateTime.Now.ToString("yyyy-MM-dd");
|
|
|
EnsureFolderExists($"日志文件夹/{year}/{Text}");
|
|
|
path = $"日志文件夹/{year}/{Text}/" + Text + "标签(" + IPtext + ")" + ".txt";
|
|
|
EnsureTxtExists(path, Text, IPtext, Porttext);
|
|
|
writeToTxt(path, $"接收消息:{hexString}\nEPC:{taglist[j].EPCstring}\nHEX:{EPCinfo}\nRSSI:{taglist[j].RSSI.ToString()} Count:{taglist[j].Count.ToString()} Time:{Timeinfo}\n____________________________");
|
|
|
path = "";
|
|
|
|
|
|
//LogService.Instance.Debug("");
|
|
|
}
|
|
|
|
|
|
TagItems = items;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "02":
|
|
|
try
|
|
|
{
|
|
|
Timeinfo = $"{time}";//获取时间
|
|
|
//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++)
|
|
|
{
|
|
|
EPCinfo = BitConverter.ToString(taglist[j].EPC).Replace("-", "");
|
|
|
items.Add(new TagItem(hexString, taglist[j].EPCstring, EPCinfo, taglist[j].RSSI.ToString(), taglist[j].Count.ToString(), Timeinfo));
|
|
|
string year = DateTime.Now.ToString("yyyy-MM-dd");
|
|
|
EnsureFolderExists($"日志文件夹/{year}/{Text}");
|
|
|
path = $"日志文件夹/{year}/{Text}/" + Text + "标签(" + IPtext + ")" + ".txt";
|
|
|
EnsureTxtExists(path, Text, IPtext, Porttext);
|
|
|
writeToTxt(path, $"接收消息:{hexString}\nEPC:{taglist[j].EPCstring}\nHEX:{EPCinfo}\nRSSI:{taglist[j].RSSI.ToString()} Count:{taglist[j].Count.ToString()} Time:{Timeinfo}\n____________________________");
|
|
|
path = "";
|
|
|
|
|
|
//LogService.Instance.Debug("");
|
|
|
}
|
|
|
|
|
|
TagItems = items;
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "81":
|
|
|
//获取GPIO状态,16进制转二进制
|
|
|
string GPIBinInfo = Convert.ToString(Convert.ToInt32(readStateString.Substring(12, 2), 16), 2).PadLeft(8, '0');
|
|
|
string GPOBinInfo = Convert.ToString(Convert.ToInt32(readStateString.Substring(10, 2), 16), 2).PadLeft(8, '0');
|
|
|
bool GPIchange = false;
|
|
|
string GPI1string = "";
|
|
|
string GPI2string = "";
|
|
|
string GPI3string = "";
|
|
|
string GPI4string = "";
|
|
|
string GPIyear = DateTime.Now.ToString("yyyy-MM-dd");
|
|
|
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")
|
|
|
{
|
|
|
if (GPI4 != "低")
|
|
|
{
|
|
|
GPI4 = "低";
|
|
|
GPI4string = "GPI4:" + GPIChangeLog(GPI4);
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
if (GPI4 != "高")
|
|
|
{
|
|
|
GPI4 = "高";
|
|
|
GPI4string = "GPI4:" + GPIChangeLog(GPI4);
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case 5:
|
|
|
if (GPOBinInfo.Substring(j, 1) == "1")
|
|
|
GPO3 = "高";
|
|
|
else
|
|
|
GPO3 = "低";
|
|
|
|
|
|
if (GPIBinInfo.Substring(j, 1) == "1")
|
|
|
{
|
|
|
if (GPI3 != "低")
|
|
|
{
|
|
|
GPI3 = "低";
|
|
|
GPI3string = "GPI3:" + GPIChangeLog(GPI3) + " ";
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
if (GPI3 != "高")
|
|
|
{
|
|
|
GPI3 = "高";
|
|
|
GPI3string = "GPI3:" + GPIChangeLog(GPI3) + " ";
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case 6:
|
|
|
if (GPOBinInfo.Substring(j, 1) == "1")
|
|
|
GPO2 = "高";
|
|
|
else
|
|
|
GPO2 = "低";
|
|
|
|
|
|
if (GPIBinInfo.Substring(j, 1) == "1")
|
|
|
{
|
|
|
if (GPI2 != "低")
|
|
|
{
|
|
|
GPI2 = "低";
|
|
|
GPI2string = "GPI2:" + GPIChangeLog(GPI2) + " ";
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
if (GPI2 != "高")
|
|
|
{
|
|
|
GPI2 = "高";
|
|
|
GPI2string = "GPI2:" + GPIChangeLog(GPI2) + " ";
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
break;
|
|
|
case 7:
|
|
|
if (GPOBinInfo.Substring(j, 1) == "1")
|
|
|
GPO1 = "高";
|
|
|
else
|
|
|
GPO1 = "低";
|
|
|
|
|
|
if (GPIBinInfo.Substring(j, 1) == "1")
|
|
|
{
|
|
|
if (GPI1 != "低")
|
|
|
{
|
|
|
GPI1 = "低";
|
|
|
GPI1string = "GPI1:" + GPIChangeLog(GPI1) + " ";
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
if (GPI1 != "高")
|
|
|
{
|
|
|
GPI1 = "高";
|
|
|
GPI1string = "GPI1:" + GPIChangeLog(GPI1) + " ";
|
|
|
GPIchange = true;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
if (GPIchange == true)
|
|
|
{
|
|
|
EnsureFolderExists($"日志文件夹/{GPIyear}/{Text}");
|
|
|
string temppath = $"日志文件夹/{GPIyear}/{Text}/" + Text + "GPI" + "(" + IPtext + ")" + ".txt";
|
|
|
EnsureTxtExists(temppath, Text, IPtext, Porttext);
|
|
|
string currenttime = DateTime.Now.ToString();
|
|
|
writeToTxt(temppath, $"{GPI1string}{GPI2string}{GPI3string}{GPI4string}\n当前状态:GPI1:{GPI1} GPI2:{GPI2} GPI3:{GPI3} GPI4:{GPI4}\n当前时间:{currenttime}\n ______________________________");
|
|
|
GPIchange = false;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "72":
|
|
|
//获取功率信息
|
|
|
try
|
|
|
{
|
|
|
for (int n = 0; n < (Convert.ToInt32(dataLength, 16) / 5); n++)
|
|
|
{
|
|
|
switch (n)
|
|
|
{
|
|
|
case 0:
|
|
|
Port1ReadText = $"{(Convert.ToInt32(readStateString.Substring(12 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
Port1WriteText = $"{(Convert.ToInt32(readStateString.Substring(16 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
break;
|
|
|
case 1:
|
|
|
Port2ReadText = $"{(Convert.ToInt32(readStateString.Substring(12 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
Port2WriteText = $"{(Convert.ToInt32(readStateString.Substring(16 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
break;
|
|
|
case 2:
|
|
|
Port3ReadText = $"{(Convert.ToInt32(readStateString.Substring(12 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
Port3WriteText = $"{(Convert.ToInt32(readStateString.Substring(16 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
break;
|
|
|
case 3:
|
|
|
Port4ReadText = $"{(Convert.ToInt32(readStateString.Substring(12 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
Port4WriteText = $"{(Convert.ToInt32(readStateString.Substring(16 + 10 * n, 4), 16) / 100).ToString()}";
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
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 "01":
|
|
|
case "02":
|
|
|
Infotext += "未读取到\n";
|
|
|
RSSIinfo = "No Read";//未读取到数值时清空数据为初始值
|
|
|
Countinfo = "00";
|
|
|
EPCASC = "No Read";
|
|
|
EPCinfo = "No Read";
|
|
|
Timeinfo = $" {time}";//获取时间
|
|
|
ObservableCollection<TagItem> items = new ObservableCollection<TagItem>();
|
|
|
items.Add(new TagItem(hexString, EPCASC, EPCinfo, RSSIinfo, Countinfo, Timeinfo));
|
|
|
TagItems = items;
|
|
|
string year = DateTime.Now.ToString("yyyy-MM-dd");
|
|
|
EnsureFolderExists($"日志文件夹/{year}/{Text}");
|
|
|
path = $"日志文件夹/{year}/{Text}/" + Text + "标签(" + IPtext + ")" + ".txt";
|
|
|
EnsureTxtExists(path, Text, IPtext, Porttext);
|
|
|
writeToTxt(path, $"接收消息:{hexString}\nEPC:{EPCASC}\nHEX:{EPCinfo}\nRSSI:{RSSIinfo} Count:{Countinfo} Time:{Timeinfo}\n____________________________");
|
|
|
path = "";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return EasyTask.CompletedTask;
|
|
|
}
|
|
|
|
|
|
private Task onConnected(ITcpClient client, ConnectedEventArgs e)//连接后初始化
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
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 72 72 0D");//获取功率状态
|
|
|
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 07 D0 D7 0D");//获取1000ms内标签信息
|
|
|
client.Send(data);
|
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
|
|
GPIOthread = new Thread(new ThreadStart(delegate () { while (true) { byte[] data = strToToHexByte("AA 55 00 81 81 0D"); client.Send(data); Thread.Sleep(1000); } }));
|
|
|
GPIOthread.Start();//心跳获取GPIO状态
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += $"连接时报错,错误内容:{ex}!\n";
|
|
|
}
|
|
|
|
|
|
return EasyTask.CompletedTask;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 辅助功能
|
|
|
|
|
|
private string GPIChangeLog(string gpiInfo)
|
|
|
{
|
|
|
if (gpiInfo == "低")
|
|
|
{
|
|
|
return "高 => 低";
|
|
|
}
|
|
|
else if (gpiInfo == "高")
|
|
|
{
|
|
|
return "低 => 高";
|
|
|
}
|
|
|
throw new NotImplementedException();
|
|
|
}
|
|
|
|
|
|
public int GetTerminalWidth()
|
|
|
{
|
|
|
int number = 4;
|
|
|
int width = ((int)SystemParameters.PrimaryScreenWidth - 60) / number;
|
|
|
while(width<360 || width > 700){
|
|
|
if (width < 360)
|
|
|
{
|
|
|
number--;
|
|
|
}
|
|
|
else if(width >700)
|
|
|
{
|
|
|
number++;
|
|
|
}
|
|
|
width = ((int)SystemParameters.PrimaryScreenWidth - 60) / number;
|
|
|
}
|
|
|
return width;
|
|
|
}
|
|
|
|
|
|
static void GetGPIOThread(ITcpClient client)
|
|
|
{
|
|
|
byte[] data = strToToHexByte("AA 55 00 81 81 0D");//获取GPIO状态
|
|
|
client.Send(data);
|
|
|
}
|
|
|
|
|
|
public byte GetXor(byte[] data, int m)
|
|
|
{
|
|
|
byte CheckCode = 0;
|
|
|
int len = data.Length;
|
|
|
for (int i = m; i < len; i++)
|
|
|
{
|
|
|
CheckCode ^= data[i];
|
|
|
}
|
|
|
return CheckCode;
|
|
|
}
|
|
|
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();
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 动态界面控件功能
|
|
|
async void Button_Link()//链接按钮的事件
|
|
|
{
|
|
|
if (LinkButtonText == "连接")
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
|
|
|
ip = IPAddress.Parse(IPtext);
|
|
|
port = int.Parse(Porttext);
|
|
|
Infotext += $"{Text}";
|
|
|
client = new TcpClient();
|
|
|
|
|
|
//连接事件
|
|
|
client.Connected += onConnected;
|
|
|
//断连事件
|
|
|
client.Closed = (client, e) => { try { GPIOthread.Abort(); Infotext += "已断开!\n"; StateColour = "Red"; LinkState = "未连接"; } catch (Exception ex) { Infotext += ex; } 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";
|
|
|
}
|
|
|
LinkButtonText = "断开";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
client.Close();
|
|
|
LinkButtonText = "连接";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void Button_Read()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
byte[] data = strToToHexByte("AA 55 02 02 07 D0 D7 0D");//获取2000ms内标签信息
|
|
|
client.Send(data);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += $"发送读取命令时出错: {ex.Message}\n";
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void Button_StopReading()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
byte[] data = strToToHexByte("AA 55 02 12 00 00 10 0D");//停止连续盘点
|
|
|
client.Send(data);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += $"发送读取命令时出错: {ex.Message}\n";
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
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位数,最后两位两位隔开
|
|
|
byte[] powerdata = strToToHexByte(setPowerString);
|
|
|
byte xor = GetXor(powerdata, 2);//计算校验位
|
|
|
setPowerString += Convert.ToString(xor, 16) + " 0D";//校验位需转成16进制字符串,命令结尾
|
|
|
byte[] data = strToToHexByte(setPowerString);
|
|
|
client.Send(data);
|
|
|
Infotext += setPowerString;
|
|
|
data = strToToHexByte("AA 55 00 72 72 0D");//获取功率
|
|
|
client.Send(data);
|
|
|
}
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
Infotext += $"处理请求时出错: {e.Message}\n";
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void Button_GetPower()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
byte[] data = strToToHexByte("AA 55 00 72 72 0D");//获取功率
|
|
|
client.Send(data);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex.Message;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
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进制数据
|
|
|
}
|
|
|
MessageText = "";
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += $"处理请求时出错: {ex.Message}\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void Button_SendActionComn()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
string message = ActionType;
|
|
|
if (message == string.Empty || message == null)
|
|
|
{
|
|
|
MessageBox.Show("请选择触发动作!");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
byte[] data = null;
|
|
|
switch (message)
|
|
|
{
|
|
|
case "单次盘点":
|
|
|
ActionType = "单次盘点";
|
|
|
data = strToToHexByte(CheckForOnce());//单次
|
|
|
break;
|
|
|
/*
|
|
|
case "连续读取":
|
|
|
ActionType = "连续读取";
|
|
|
data = strToToHexByte("AA 55 02 11 00 00 13 0D");//连续
|
|
|
break;
|
|
|
*/
|
|
|
case "时间段盘点":
|
|
|
ActionType = "时间段盘点";
|
|
|
data = strToToHexByte(CheckDuringTime());
|
|
|
break;
|
|
|
}
|
|
|
client.Send(data);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex.Message;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
}
|
|
|
void Button_disconnect()
|
|
|
{
|
|
|
client.Close();//断开连接
|
|
|
}
|
|
|
|
|
|
void Button_clear()
|
|
|
{
|
|
|
Infotext = string.Empty;//清空信息框
|
|
|
}
|
|
|
|
|
|
void TextBlock_SelectChanged(ScrollViewer scrollViewer)
|
|
|
{
|
|
|
scrollViewer.ScrollToVerticalOffset(scrollViewer.ExtentHeight);
|
|
|
}
|
|
|
|
|
|
void ComboBox_SelectChanged(ComboBox sender)
|
|
|
{
|
|
|
string comboxname = sender.Name;
|
|
|
try
|
|
|
{
|
|
|
switch (comboxname)
|
|
|
{
|
|
|
case "Port1ReadComboBox":
|
|
|
Port1ReadText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port2ReadComboBox":
|
|
|
Port2ReadText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port3ReadComboBox":
|
|
|
Port3ReadText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port4ReadComboBox":
|
|
|
Port4ReadText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port1WriteComboBox":
|
|
|
Port1WriteText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port2WriteComboBox":
|
|
|
Port2WriteText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port3WriteComboBox":
|
|
|
Port3WriteText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
case "Port4WriteComboBox":
|
|
|
Port4WriteText = sender.SelectedItem?.ToString();
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
sender.SelectedItem = null;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex.Message;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void GPOComboBox_SelectChanged(ComboBox sender)
|
|
|
{
|
|
|
string Order = "AA 55 04 51 ";
|
|
|
string comboxname = sender.Name;
|
|
|
try
|
|
|
{
|
|
|
if (sender.SelectedItem == null)
|
|
|
return;
|
|
|
switch (comboxname)
|
|
|
{
|
|
|
case "GPO1ComboBox":
|
|
|
GPO1 = sender.SelectedItem?.ToString();
|
|
|
Order += "01 ";
|
|
|
break;
|
|
|
case "GPO2ComboBox":
|
|
|
GPO2 = sender.SelectedItem?.ToString();
|
|
|
Order += "02 ";
|
|
|
break;
|
|
|
case "GPO3ComboBox":
|
|
|
GPO3 = sender.SelectedItem?.ToString();
|
|
|
Order += "03 ";
|
|
|
break;
|
|
|
case "GPO4ComboBox":
|
|
|
GPO4 = sender.SelectedItem?.ToString();
|
|
|
Order += "04 ";
|
|
|
break;
|
|
|
}
|
|
|
if (sender.SelectedItem?.ToString() == "高")
|
|
|
Order += "01 ";
|
|
|
else if (sender.SelectedItem?.ToString() == "低")
|
|
|
Order += "00 ";
|
|
|
Order += "00 00 ";
|
|
|
Order += Convert.ToString(GetXor(strToToHexByte(Order), 2), 16) + " 0D";
|
|
|
//Infotext += Order+"\n";
|
|
|
byte[] data = strToToHexByte(Order);
|
|
|
client.Send(data);
|
|
|
data = strToToHexByte("AA 55 00 81 81 0D");//获取GPIO状态
|
|
|
client.Send(data);
|
|
|
sender.SelectedIndex = -1;
|
|
|
//SaveCommand();
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex.Message;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void SendTextComboBox_SelectChanged(ComboBox sender)
|
|
|
{
|
|
|
string selcetion = sender.SelectedItem?.ToString();
|
|
|
try
|
|
|
{
|
|
|
//byte[] data = null;
|
|
|
switch (selcetion)
|
|
|
{
|
|
|
case "单次盘点":
|
|
|
ActionType = "单次盘点";
|
|
|
//data = strToToHexByte("AA 55 02 01 00 64 67 0D");//单次
|
|
|
break;
|
|
|
/*
|
|
|
case "连续读取":
|
|
|
ActionType = "连续读取";
|
|
|
data = strToToHexByte("AA 55 02 11 00 00 13 0D");//连续
|
|
|
break;
|
|
|
*/
|
|
|
case "时间段盘点":
|
|
|
ActionType = "时间段盘点";
|
|
|
//data = strToToHexByte(CheckDuringTime());
|
|
|
break;
|
|
|
}
|
|
|
//client.Send(data);
|
|
|
sender.SelectedItem = null;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Infotext += ex.Message;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public void dispose()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
if (client != null)
|
|
|
client.Close();
|
|
|
if (GPIOthread != null)
|
|
|
GPIOthread.Abort();
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
string CheckForOnce()
|
|
|
{
|
|
|
string actionstring = "AA 55 02 01 ";
|
|
|
if (TimeOut != "" && TimeOut != null)
|
|
|
actionstring += Convert.ToInt32(TimeOut).ToString("X").PadLeft(4, '0').Insert(2, " ") + " ";
|
|
|
else
|
|
|
actionstring += "00 00 ";
|
|
|
actionstring += Convert.ToString(GetXor(strToToHexByte(actionstring), 2), 16).PadLeft(2, '0').ToUpper() + " 0D";
|
|
|
return actionstring;
|
|
|
}
|
|
|
string CheckDuringTime()
|
|
|
{
|
|
|
string actionstring = "AA 55 02 02 ";
|
|
|
if (TimeOut != "" && TimeOut != null)
|
|
|
actionstring += Convert.ToInt32(TimeOut).ToString("X").PadLeft(4, '0').Insert(2, " ") + " ";
|
|
|
else
|
|
|
actionstring += "00 00 ";
|
|
|
actionstring += Convert.ToString(GetXor(strToToHexByte(actionstring), 2), 16).PadLeft(2, '0') + " 0D";
|
|
|
return actionstring;
|
|
|
}
|
|
|
void SaveCommand()
|
|
|
{
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
//组件属性更改事件
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
|
{
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
}
|
|
|
|
|
|
/* 标签文本修改事件
|
|
|
protected void LabelPropertyChanged([CallerMemberName] string propertyName = null)
|
|
|
{
|
|
|
if(GPI1 == "" || GPI2 == ""|| GPI3 == ""|| GPI4 == "" || GPI1 ==null || GPI2 == null || GPI3 == null || GPI4 == null ||client == null)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
string year = DateTime.Now.ToString("yyyy-MM-dd");
|
|
|
EnsureFolderExists($"日志文件夹/{year}/{Text}");
|
|
|
string temppath = $"日志文件夹/{year}/{Text}/" + Text + "GPI"+"(" + IPtext + ")" + ".txt";
|
|
|
EnsureTxtExists(temppath, Text, IPtext, Porttext);
|
|
|
string currenttime = DateTime.Now.ToString();
|
|
|
string GPIname = "";
|
|
|
string front = "";
|
|
|
string back = "";
|
|
|
switch (propertyName)
|
|
|
{
|
|
|
case "GPI1":
|
|
|
GPIname = "GPI1";
|
|
|
back = GPI1;
|
|
|
break;
|
|
|
case "GPI2":
|
|
|
GPIname = "GPI2";
|
|
|
back = GPI2;
|
|
|
break;
|
|
|
case "GPI3":
|
|
|
GPIname = "GPI3";
|
|
|
back = GPI3;
|
|
|
break;
|
|
|
case "GPI4":
|
|
|
GPIname = "GPI4";
|
|
|
back = GPI4;
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
if (back == "高")
|
|
|
front = "低";
|
|
|
else
|
|
|
front = "高";
|
|
|
writeToTxt(temppath,$"{GPIname}:{front} => {back}\n当前状态:GPI1:{GPI1} GPI2:{GPI2} GPI3:{GPI3} GPI4:{GPI4}\n当前时间:{currenttime}\n ______________________________");
|
|
|
}
|
|
|
*/
|
|
|
public class TagItem : INotifyPropertyChanged
|
|
|
{
|
|
|
private string _originmessage;//原始数据
|
|
|
public string OriginMessage { get => _originmessage; set { _originmessage = value; OnPropertyChanged(); } }
|
|
|
|
|
|
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 _infocolor;
|
|
|
public string InfoColor { get => _infocolor; set { _infocolor = 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 originMessage, string infoEPC, string ascEPC, string RSSI, string count, string time)
|
|
|
{
|
|
|
OriginMessage = originMessage;
|
|
|
EPCinfo = infoEPC;
|
|
|
EPCASC = ascEPC;
|
|
|
RSSIinfo = RSSI;
|
|
|
Countinfo = count;
|
|
|
Timeinfo = time;
|
|
|
if (infoEPC == "No Read")
|
|
|
{
|
|
|
InfoColor = "Red";
|
|
|
}
|
|
|
else
|
|
|
InfoColor = "Green";
|
|
|
}
|
|
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
|
{
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#region 主界面参数
|
|
|
int currentcount = 0;//目前客户端的数量
|
|
|
|
|
|
List<PanelItem> items = new List<PanelItem>();//客户端组件列表
|
|
|
|
|
|
public static double? WindowLeft { get; set; }
|
|
|
public static double? WindowTop { get; set; }
|
|
|
public static double? WindowWidth { get; set; }
|
|
|
public static double? WindowHeight { get; set; }
|
|
|
public static WindowState? OriginWindowState { get; set; }
|
|
|
public static int? Buttonflag { get; set; }
|
|
|
public TCPWindowV2()
|
|
|
{
|
|
|
InitializeComponent();
|
|
|
EnsureFolderExists("日志文件夹");
|
|
|
this.Closing += TCPWindowV2_Closing;
|
|
|
SaveWindowSettings();
|
|
|
Buttonflag = 0;
|
|
|
}
|
|
|
#endregion
|
|
|
//结束所有线程,防止心跳线程冗余
|
|
|
private void TCPWindowV2_Closing(object sender, CancelEventArgs e)
|
|
|
{
|
|
|
System.Environment.Exit(0);
|
|
|
}
|
|
|
|
|
|
#region 主界面按钮事件
|
|
|
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);
|
|
|
}
|
|
|
Welcome_StackPanel.Visibility = Visibility.Visible;
|
|
|
NewTerminal_StackPanel.Visibility = Visibility.Collapsed;
|
|
|
}
|
|
|
|
|
|
private void Shutdown_Button_Click(object sender, RoutedEventArgs e)
|
|
|
{
|
|
|
Application.Current.Shutdown();
|
|
|
}
|
|
|
private void CreateTerminal_Button_Click(object sender, RoutedEventArgs e)
|
|
|
{
|
|
|
Welcome_StackPanel.Visibility = Visibility.Collapsed;
|
|
|
NewTerminal_StackPanel.Visibility = Visibility.Visible;
|
|
|
}
|
|
|
|
|
|
private void Maxmize_Button_Click(object sender, RoutedEventArgs e)
|
|
|
{
|
|
|
if (Buttonflag == 0)
|
|
|
{
|
|
|
this.WindowState = WindowState.Maximized;
|
|
|
MaxMinImage.Source = new BitmapImage(new Uri(@"/取消全屏.png",UriKind.Relative));
|
|
|
Buttonflag = 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
LoadWindowSettings();
|
|
|
MaxMinImage.Source = new BitmapImage(new Uri(@"/全屏.png", UriKind.Relative));
|
|
|
Buttonflag = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void Minimize_Button_Click(object sender, RoutedEventArgs e)
|
|
|
{
|
|
|
this.WindowState = WindowState.Minimized;
|
|
|
}
|
|
|
private void ClearButton_Click(object sender, RoutedEventArgs e)//清空客户端
|
|
|
{
|
|
|
foreach (PanelItem item in items)
|
|
|
{
|
|
|
item.dispose();
|
|
|
}
|
|
|
items = new List<PanelItem>();
|
|
|
PanelContainer.ItemsSource = null;
|
|
|
currentcount = 0;
|
|
|
}
|
|
|
#endregion
|
|
|
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 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;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void EnsureTxtExists(string txtPath, string MachineName, string IPinfo, string Portinfo)
|
|
|
{
|
|
|
// 检查指定的txt路径对应的txt是否已经存在
|
|
|
if (!File.Exists(txtPath))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
StreamWriter streamWriter = new StreamWriter(txtPath, true);
|
|
|
streamWriter.WriteLineAsync($"设备名称:{MachineName}\nIP地址:{IPinfo}\n端口号:{Portinfo}\n____________________________");
|
|
|
streamWriter.Close();
|
|
|
}
|
|
|
catch (IOException ex)
|
|
|
{
|
|
|
// 如果在创建文件夹过程中出现IOException异常(比如权限不足、磁盘已满等原因导致无法创建文件夹)
|
|
|
// 这里通过消息框向用户展示创建文件夹失败的异常信息,方便用户知晓问题所在
|
|
|
MessageBox.Show($"创建txt {txtPath} 失败,异常信息: {ex.Message}");
|
|
|
// 重新抛出异常,让调用这个方法的上层代码知道创建文件夹出现了问题,以便进行进一步的处理,比如终止程序或者尝试其他恢复操作
|
|
|
throw;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
|
|
|
{
|
|
|
if (e.ChangedButton == MouseButton.Left)
|
|
|
{
|
|
|
this.DragMove();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void LoadWindowSettings()
|
|
|
{
|
|
|
if (WindowLeft.HasValue && WindowTop.HasValue)
|
|
|
{
|
|
|
this.Left = WindowLeft.Value;
|
|
|
this.Top = WindowTop.Value;
|
|
|
}
|
|
|
if (WindowWidth.HasValue && WindowHeight.HasValue)
|
|
|
{
|
|
|
this.Width = WindowWidth.Value;
|
|
|
this.Height = WindowHeight.Value;
|
|
|
}
|
|
|
if (OriginWindowState.HasValue)
|
|
|
{
|
|
|
this.WindowState = OriginWindowState.Value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void SaveWindowSettings()
|
|
|
{
|
|
|
WindowLeft = this.Left;
|
|
|
WindowTop = this.Top;
|
|
|
WindowWidth = this.Width;
|
|
|
WindowHeight = this.Height;
|
|
|
OriginWindowState = this.WindowState;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|