Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightCentralizedControlManagement
This commit is contained in:
commit
379db4b738
4 files changed
+762
-84
No files matched your search
@@ -119,6 +119,7 @@
|
|||||||
<Compile Include="Login.xaml.cs">
|
<Compile Include="Login.xaml.cs">
|
||||||
<DependentUpon>Login.xaml</DependentUpon>
|
<DependentUpon>Login.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="UserClass\AsyncSerialPortClient.cs" />
|
||||||
<Compile Include="UserClass\AsyncTcpClient.cs" />
|
<Compile Include="UserClass\AsyncTcpClient.cs" />
|
||||||
<Compile Include="UserClass\ClsLock.cs" />
|
<Compile Include="UserClass\ClsLock.cs" />
|
||||||
<Compile Include="UserClass\CRCcheck16.cs" />
|
<Compile Include="UserClass\CRCcheck16.cs" />
|
||||||
@@ -133,6 +134,7 @@
|
|||||||
<Compile Include="UserClass\NetFwManger.cs" />
|
<Compile Include="UserClass\NetFwManger.cs" />
|
||||||
<Compile Include="UserClass\NumericTextColumn .cs" />
|
<Compile Include="UserClass\NumericTextColumn .cs" />
|
||||||
<Compile Include="UserClass\PID.cs" />
|
<Compile Include="UserClass\PID.cs" />
|
||||||
|
<Compile Include="UserClass\RS485MasterStation.cs" />
|
||||||
<Compile Include="UserClass\SYSInfo.cs" />
|
<Compile Include="UserClass\SYSInfo.cs" />
|
||||||
<Compile Include="UserClass\PressKey.cs" />
|
<Compile Include="UserClass\PressKey.cs" />
|
||||||
<Compile Include="UserClass\SqliteHelper.cs" />
|
<Compile Include="UserClass\SqliteHelper.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TouchSocket.Core;
|
||||||
|
using TouchSocket.SerialPorts;
|
||||||
|
using TouchSocket.Sockets;
|
||||||
|
|
||||||
|
namespace SunlightCentralizedControlManagement_SCCM_.UserClass
|
||||||
|
{
|
||||||
|
public class AsyncSerialPortClient
|
||||||
|
{
|
||||||
|
public static async Task PortClient(SerialPortClient portclient, string com, int BAUD)
|
||||||
|
{
|
||||||
|
//var client = new SerialPortClient();
|
||||||
|
portclient.Connecting = (client, e) => { return EasyTask.CompletedTask; };//即将连接到端口
|
||||||
|
portclient.Connected = (client, e) => { return EasyTask.CompletedTask; };//成功连接到端口
|
||||||
|
portclient.Closing = (client, e) => { return EasyTask.CompletedTask; };//即将从端口断开连接。此处仅主动断开才有效。
|
||||||
|
portclient.Closed = (client, e) => { return EasyTask.CompletedTask; };//从端口断开连接,当连接不成功时不会触发。
|
||||||
|
portclient.Received = async (c, e) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
await Console.Out.WriteLineAsync(e.ByteBlock.Span.ToString(Encoding.UTF8));
|
||||||
|
};
|
||||||
|
|
||||||
|
await portclient.SetupAsync(new TouchSocketConfig()
|
||||||
|
.SetSerialPortOption(new SerialPortOption()
|
||||||
|
{
|
||||||
|
BaudRate = BAUD,//波特率
|
||||||
|
DataBits = 8,//数据位
|
||||||
|
Parity = System.IO.Ports.Parity.None,//校验位
|
||||||
|
PortName = com,//COM
|
||||||
|
StopBits = System.IO.Ports.StopBits.One,//停止位
|
||||||
|
})
|
||||||
|
.SetSerialDataHandlingAdapter(() => new PeriodPackageAdapter() { CacheTimeout = TimeSpan.FromMilliseconds(100) })
|
||||||
|
.ConfigurePlugins(a =>
|
||||||
|
{
|
||||||
|
//a.Add<MyPlugin>();
|
||||||
|
}));
|
||||||
|
|
||||||
|
await portclient.ConnectAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,617 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TouchSocket.Core;
|
||||||
|
using TouchSocket.SerialPorts;
|
||||||
|
using TouchSocket.Sockets;
|
||||||
|
|
||||||
|
namespace SunlightCentralizedControlManagement_SCCM_.UserClass
|
||||||
|
{
|
||||||
|
#region 基础数据结构
|
||||||
|
/// <summary>
|
||||||
|
/// 485 设备地址
|
||||||
|
/// </summary>
|
||||||
|
public struct DeviceAddress
|
||||||
|
{
|
||||||
|
public byte Value { get; }
|
||||||
|
|
||||||
|
public DeviceAddress(byte address)
|
||||||
|
{
|
||||||
|
if (address == 0) throw new ArgumentException("设备地址不能为0(广播地址)");
|
||||||
|
Value = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator byte(DeviceAddress address) => address.Value;
|
||||||
|
public static implicit operator DeviceAddress(byte address) => new DeviceAddress(address);
|
||||||
|
|
||||||
|
public override string ToString() => $"0x{Value:X2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 485 命令帧
|
||||||
|
/// </summary>
|
||||||
|
public class CommandFrame
|
||||||
|
{
|
||||||
|
public DeviceAddress DeviceAddress { get; set; }
|
||||||
|
public byte FunctionCode { get; set; }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
public ushort CRC { get; set; }
|
||||||
|
|
||||||
|
public byte[] ToBytes()
|
||||||
|
{
|
||||||
|
// 实现帧序列化逻辑,包括CRC计算
|
||||||
|
var dataLength = Data?.Length ?? 0;
|
||||||
|
var frame = new byte[3 + dataLength + 2]; // 地址+功能码+数据+CRC
|
||||||
|
|
||||||
|
frame[0] = DeviceAddress;
|
||||||
|
frame[1] = FunctionCode;
|
||||||
|
|
||||||
|
if (dataLength > 0)
|
||||||
|
Array.Copy(Data, 0, frame, 2, dataLength);
|
||||||
|
|
||||||
|
// 计算CRC (这里使用Modbus CRC算法示例)
|
||||||
|
CRC = CalculateCRC(frame, 0, frame.Length - 2);
|
||||||
|
frame[frame.Length - 2] = (byte)(CRC & 0xFF);
|
||||||
|
frame[frame.Length - 1] = (byte)(CRC >> 8);
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ushort CalculateCRC(byte[] data, int offset, int length)
|
||||||
|
{
|
||||||
|
// 简化的CRC计算示例,实际应根据协议实现
|
||||||
|
ushort crc = 0xFFFF;
|
||||||
|
for (int i = offset; i < offset + length; i++)
|
||||||
|
{
|
||||||
|
crc ^= data[i];
|
||||||
|
for (int j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
if ((crc & 0x0001) != 0)
|
||||||
|
{
|
||||||
|
crc >>= 1;
|
||||||
|
crc ^= 0xA001;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crc >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 响应帧
|
||||||
|
/// </summary>
|
||||||
|
public class ResponseFrame
|
||||||
|
{
|
||||||
|
public DeviceAddress DeviceAddress { get; set; }
|
||||||
|
public byte FunctionCode { get; set; }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
public ushort CRC { get; set; }
|
||||||
|
public bool IsValid { get; set; }
|
||||||
|
public string Error { get; set; }
|
||||||
|
|
||||||
|
public static ResponseFrame FromBytes(byte[] data)
|
||||||
|
{
|
||||||
|
// 实现帧解析逻辑,包括CRC验证
|
||||||
|
var frame = new ResponseFrame();
|
||||||
|
|
||||||
|
if (data.Length < 4) // 最小帧长度
|
||||||
|
{
|
||||||
|
frame.IsValid = false;
|
||||||
|
frame.Error = "帧长度不足";
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.DeviceAddress = data[0];
|
||||||
|
frame.FunctionCode = data[1];
|
||||||
|
|
||||||
|
// 检查CRC
|
||||||
|
ushort receivedCRC = (ushort)(data[data.Length - 1] << 8 | data[data.Length - 2]);
|
||||||
|
ushort calculatedCRC = CalculateCRC(data, 0, data.Length - 2);
|
||||||
|
|
||||||
|
if (receivedCRC != calculatedCRC)
|
||||||
|
{
|
||||||
|
frame.IsValid = false;
|
||||||
|
frame.Error = "CRC校验失败";
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取数据部分
|
||||||
|
if (data.Length > 4)
|
||||||
|
{
|
||||||
|
frame.Data = new byte[data.Length - 4];
|
||||||
|
Array.Copy(data, 2, frame.Data, 0, frame.Data.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.IsValid = true;
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ushort CalculateCRC(byte[] data, int offset, int length)
|
||||||
|
{
|
||||||
|
// 与CommandFrame相同的CRC算法
|
||||||
|
ushort crc = 0xFFFF;
|
||||||
|
for (int i = offset; i < offset + length; i++)
|
||||||
|
{
|
||||||
|
crc ^= data[i];
|
||||||
|
for (int j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
if ((crc & 0x0001) != 0)
|
||||||
|
{
|
||||||
|
crc >>= 1;
|
||||||
|
crc ^= 0xA001;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crc >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通信任务
|
||||||
|
/// </summary>
|
||||||
|
public class CommunicationTask
|
||||||
|
{
|
||||||
|
public DeviceAddress DeviceAddress { get; set; }
|
||||||
|
public CommandFrame Command { get; set; }
|
||||||
|
public TaskCompletionSource<ResponseFrame> CompletionSource { get; set; }
|
||||||
|
public int TimeoutMs { get; set; } = 1000;
|
||||||
|
public int RetryCount { get; set; } = 3;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 异常类
|
||||||
|
public class RS485CommunicationException : Exception
|
||||||
|
{
|
||||||
|
public DeviceAddress DeviceAddress { get; }
|
||||||
|
public byte FunctionCode { get; }
|
||||||
|
|
||||||
|
public RS485CommunicationException(DeviceAddress address, byte functionCode, string message)
|
||||||
|
: base($"设备 {address} 功能码 0x{functionCode:X2} 通信失败: {message}")
|
||||||
|
{
|
||||||
|
DeviceAddress = address;
|
||||||
|
FunctionCode = functionCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RS485TimeoutException : RS485CommunicationException
|
||||||
|
{
|
||||||
|
public RS485TimeoutException(DeviceAddress address, byte functionCode)
|
||||||
|
: base(address, functionCode, "响应超时")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RS485CRCException : RS485CommunicationException
|
||||||
|
{
|
||||||
|
public RS485CRCException(DeviceAddress address, byte functionCode)
|
||||||
|
: base(address, functionCode, "CRC校验失败")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 主站实现
|
||||||
|
/// <summary>
|
||||||
|
/// 485 主站实现
|
||||||
|
/// </summary>
|
||||||
|
public class RS485MasterStation : IDisposable
|
||||||
|
{
|
||||||
|
private readonly SerialPortClient _serialPortClient;
|
||||||
|
private readonly ConcurrentDictionary<DeviceAddress, DeviceState> _deviceStates;
|
||||||
|
private readonly ConcurrentQueue<CommunicationTask> _taskQueue;
|
||||||
|
private readonly CancellationTokenSource _cancellationTokenSource;
|
||||||
|
private Task _processingTask;
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
|
// 响应超时时间(毫秒)
|
||||||
|
public int ResponseTimeout { get; set; } = 1000;
|
||||||
|
|
||||||
|
// 帧间延迟(毫秒)
|
||||||
|
public int InterFrameDelay { get; set; } = 10;
|
||||||
|
|
||||||
|
// 最大重试次数
|
||||||
|
public int MaxRetries { get; set; } = 3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备状态
|
||||||
|
/// </summary>
|
||||||
|
private class DeviceState
|
||||||
|
{
|
||||||
|
public DeviceAddress Address { get; set; }
|
||||||
|
public DateTime LastCommunication { get; set; }
|
||||||
|
public bool IsOnline { get; set; }
|
||||||
|
public int TimeoutCount { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public RS485MasterStation(string portName, int baudRate = 9600)
|
||||||
|
{
|
||||||
|
_serialPortClient = new SerialPortClient();
|
||||||
|
_deviceStates = new ConcurrentDictionary<DeviceAddress, DeviceState>();
|
||||||
|
_taskQueue = new ConcurrentQueue<CommunicationTask>();
|
||||||
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
// 配置串口
|
||||||
|
_serialPortClient.Setup(new TouchSocketConfig()
|
||||||
|
.SetSerialPortOption(new SerialPortOption()
|
||||||
|
{
|
||||||
|
PortName = portName,
|
||||||
|
BaudRate = baudRate,
|
||||||
|
DataBits = 8,
|
||||||
|
Parity = Parity.None,
|
||||||
|
StopBits = StopBits.One
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 注册数据接收事件
|
||||||
|
_serialPortClient.Received = OnDataReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启动主站
|
||||||
|
/// </summary>
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_serialPortClient.Connect();
|
||||||
|
_processingTask = Task.Run(ProcessQueue, _cancellationTokenSource.Token);
|
||||||
|
Console.WriteLine("485主站已启动");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 停止主站
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
_cancellationTokenSource.Cancel();
|
||||||
|
_serialPortClient.Close();
|
||||||
|
Console.WriteLine("485主站已停止");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加设备到监控列表
|
||||||
|
/// </summary>
|
||||||
|
public void AddDevice(DeviceAddress address)
|
||||||
|
{
|
||||||
|
_deviceStates[address] = new DeviceState
|
||||||
|
{
|
||||||
|
Address = address,
|
||||||
|
LastCommunication = DateTime.MinValue,
|
||||||
|
IsOnline = false,
|
||||||
|
TimeoutCount = 0
|
||||||
|
};
|
||||||
|
Console.WriteLine($"已添加设备: {address}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从监控列表移除设备
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveDevice(DeviceAddress address)
|
||||||
|
{
|
||||||
|
_deviceStates.TryRemove(address, out _);
|
||||||
|
Console.WriteLine($"已移除设备: {address}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送命令到设备
|
||||||
|
/// </summary>
|
||||||
|
public Task<ResponseFrame> SendCommandAsync(DeviceAddress address, byte functionCode, byte[] data = null, int timeoutMs = 1000, int retryCount = 3)
|
||||||
|
{
|
||||||
|
var command = new CommandFrame
|
||||||
|
{
|
||||||
|
DeviceAddress = address,
|
||||||
|
FunctionCode = functionCode,
|
||||||
|
Data = data ?? new byte[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
var task = new CommunicationTask
|
||||||
|
{
|
||||||
|
DeviceAddress = address,
|
||||||
|
Command = command,
|
||||||
|
CompletionSource = new TaskCompletionSource<ResponseFrame>(),
|
||||||
|
TimeoutMs = timeoutMs,
|
||||||
|
RetryCount = retryCount
|
||||||
|
};
|
||||||
|
|
||||||
|
_taskQueue.Enqueue(task);
|
||||||
|
return task.CompletionSource.Task;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取保持寄存器
|
||||||
|
/// </summary>
|
||||||
|
public async Task<byte[]> ReadHoldingRegistersAsync(DeviceAddress address, ushort startAddress, ushort numberOfRegisters)
|
||||||
|
{
|
||||||
|
var data = new byte[4];
|
||||||
|
data[0] = (byte)(startAddress >> 8); // 起始地址高字节
|
||||||
|
data[1] = (byte)(startAddress & 0xFF); // 起始地址低字节
|
||||||
|
data[2] = (byte)(numberOfRegisters >> 8); // 寄存器数量高字节
|
||||||
|
data[3] = (byte)(numberOfRegisters & 0xFF); // 寄存器数量低字节
|
||||||
|
|
||||||
|
var response = await SendCommandAsync(address, 0x03, data);
|
||||||
|
|
||||||
|
if (!response.IsValid)
|
||||||
|
throw new RS485CommunicationException(address, 0x03, response.Error);
|
||||||
|
|
||||||
|
return response.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写入单个寄存器
|
||||||
|
/// </summary>
|
||||||
|
public async Task WriteSingleRegisterAsync(DeviceAddress address, ushort registerAddress, ushort value)
|
||||||
|
{
|
||||||
|
var data = new byte[4];
|
||||||
|
data[0] = (byte)(registerAddress >> 8); // 寄存器地址高字节
|
||||||
|
data[1] = (byte)(registerAddress & 0xFF); // 寄存器地址低字节
|
||||||
|
data[2] = (byte)(value >> 8); // 值高字节
|
||||||
|
data[3] = (byte)(value & 0xFF); // 值低字节
|
||||||
|
|
||||||
|
var response = await SendCommandAsync(address, 0x06, data);
|
||||||
|
|
||||||
|
if (!response.IsValid)
|
||||||
|
throw new RS485CommunicationException(address, 0x06, response.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理任务队列
|
||||||
|
/// </summary>
|
||||||
|
private async Task ProcessQueue()
|
||||||
|
{
|
||||||
|
while (!_cancellationTokenSource.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (_taskQueue.TryDequeue(out var task))
|
||||||
|
{
|
||||||
|
await ProcessTask(task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 队列为空,执行设备轮询
|
||||||
|
await PollDevices();
|
||||||
|
await Task.Delay(100, _cancellationTokenSource.Token); // 短暂休眠
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理单个通信任务
|
||||||
|
/// </summary>
|
||||||
|
private async Task ProcessTask(CommunicationTask task)
|
||||||
|
{
|
||||||
|
int retryCount = 0;
|
||||||
|
ResponseFrame response = null;
|
||||||
|
|
||||||
|
while (retryCount < task.RetryCount && !_cancellationTokenSource.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 发送命令
|
||||||
|
var commandData = task.Command.ToBytes();
|
||||||
|
_serialPortClient.Send(commandData);
|
||||||
|
|
||||||
|
// 等待响应
|
||||||
|
var timeoutTask = Task.Delay(task.TimeoutMs, _cancellationTokenSource.Token);
|
||||||
|
var responseTask = task.CompletionSource.Task;
|
||||||
|
|
||||||
|
var completedTask = await Task.WhenAny(responseTask, timeoutTask);
|
||||||
|
|
||||||
|
if (completedTask == responseTask)
|
||||||
|
{
|
||||||
|
response = await responseTask;
|
||||||
|
if (response.IsValid)
|
||||||
|
{
|
||||||
|
UpdateDeviceState(task.DeviceAddress, true);
|
||||||
|
task.CompletionSource.SetResult(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RS485CRCException(task.DeviceAddress, task.Command.FunctionCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RS485TimeoutException(task.DeviceAddress, task.Command.FunctionCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (RS485CommunicationException ex)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
UpdateDeviceState(task.DeviceAddress, false);
|
||||||
|
|
||||||
|
if (retryCount >= task.RetryCount)
|
||||||
|
{
|
||||||
|
task.CompletionSource.SetException(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待一段时间后重试
|
||||||
|
await Task.Delay(InterFrameDelay, _cancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 轮询所有设备状态
|
||||||
|
/// </summary>
|
||||||
|
private async Task PollDevices()
|
||||||
|
{
|
||||||
|
foreach (var deviceState in _deviceStates.Values.ToList())
|
||||||
|
{
|
||||||
|
// 检查设备是否需要轮询(例如,超过一定时间未通信)
|
||||||
|
if ((DateTime.Now - deviceState.LastCommunication).TotalSeconds > 30)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 发送诊断命令(如读取设备状态)
|
||||||
|
await ReadHoldingRegistersAsync(deviceState.Address, 0, 1);
|
||||||
|
Console.WriteLine($"设备 {deviceState.Address} 轮询成功");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"设备 {deviceState.Address} 轮询失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加帧间延迟
|
||||||
|
await Task.Delay(InterFrameDelay, _cancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据接收处理
|
||||||
|
/// </summary>
|
||||||
|
private Task OnDataReceived(ISerialPortClient client, ReceivedDataEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 解析响应帧
|
||||||
|
var response = ResponseFrame.FromBytes(e.ByteBlock.ReadBytesPackage());
|
||||||
|
|
||||||
|
if (response.IsValid)
|
||||||
|
{
|
||||||
|
// 查找匹配的任务并设置结果
|
||||||
|
foreach (var task in _taskQueue.Where(t => t.DeviceAddress.Value == response.DeviceAddress.Value))
|
||||||
|
{
|
||||||
|
task.CompletionSource.TrySetResult(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDeviceState(response.DeviceAddress, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"收到无效响应: {response.Error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理接收数据时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新设备状态
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateDeviceState(DeviceAddress address, bool communicationSuccess)
|
||||||
|
{
|
||||||
|
if (_deviceStates.TryGetValue(address, out var state))
|
||||||
|
{
|
||||||
|
state.LastCommunication = DateTime.Now;
|
||||||
|
|
||||||
|
if (communicationSuccess)
|
||||||
|
{
|
||||||
|
state.IsOnline = true;
|
||||||
|
state.TimeoutCount = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.TimeoutCount++;
|
||||||
|
if (state.TimeoutCount > MaxRetries)
|
||||||
|
{
|
||||||
|
state.IsOnline = false;
|
||||||
|
Console.WriteLine($"设备 {address} 已离线");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有设备状态
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<DeviceAddress, bool> GetDeviceStatuses()
|
||||||
|
{
|
||||||
|
return _deviceStates.ToDictionary(
|
||||||
|
kvp => kvp.Key,
|
||||||
|
kvp => kvp.Value.IsOnline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源释放
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
_isDisposed = true;
|
||||||
|
_cancellationTokenSource.Cancel();
|
||||||
|
_serialPortClient.SafeDispose();
|
||||||
|
_cancellationTokenSource.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 使用示例
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
// 创建485主站实例
|
||||||
|
using (var master = new RS485MasterStation("COM1", 9600))
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 添加要监控的设备
|
||||||
|
master.AddDevice(0x01);
|
||||||
|
master.AddDevice(0x02);
|
||||||
|
master.AddDevice(0x03);
|
||||||
|
|
||||||
|
// 启动主站
|
||||||
|
master.Start();
|
||||||
|
|
||||||
|
// 等待一段时间让主站初始化
|
||||||
|
await Task.Delay(1000);
|
||||||
|
|
||||||
|
// 示例1: 读取设备1的保持寄存器
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = await master.ReadHoldingRegistersAsync(0x01, 0, 10);
|
||||||
|
Console.WriteLine($"成功读取设备1的寄存器数据: {BitConverter.ToString(data)}");
|
||||||
|
}
|
||||||
|
catch (RS485CommunicationException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 示例2: 向设备2写入寄存器值
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await master.WriteSingleRegisterAsync(0x02, 0x1000, 0x1234);
|
||||||
|
Console.WriteLine("成功向设备2写入寄存器值");
|
||||||
|
}
|
||||||
|
catch (RS485CommunicationException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示所有设备状态
|
||||||
|
var statuses = master.GetDeviceStatuses();
|
||||||
|
foreach (var status in statuses)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"设备 {status.Key}: {(status.Value ? "在线" : "离线")}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保持运行
|
||||||
|
Console.WriteLine("按任意键退出...");
|
||||||
|
Console.ReadKey();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
master.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -32,10 +32,11 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using TouchSocket.Core;
|
using TouchSocket.Core;
|
||||||
using TouchSocket.Sockets;
|
|
||||||
using TouchSocket.SerialPorts;
|
using TouchSocket.SerialPorts;
|
||||||
|
using TouchSocket.Sockets;
|
||||||
using static MaterialDesignThemes.Wpf.Theme;
|
using static MaterialDesignThemes.Wpf.Theme;
|
||||||
using static SunlightCentralizedControlManagement_SCCM_.UserClass.SqliteHelper;
|
using static SunlightCentralizedControlManagement_SCCM_.UserClass.SqliteHelper;
|
||||||
|
using static SunlightCentralizedControlManagement_SCCM_.View.MachinesView;
|
||||||
using static SunlightCentralizedControlManagement_SCCM_.ViewModel.ManualDyelotModel;
|
using static SunlightCentralizedControlManagement_SCCM_.ViewModel.ManualDyelotModel;
|
||||||
using static System.Net.WebRequestMethods;
|
using static System.Net.WebRequestMethods;
|
||||||
using static System.Windows.Forms.AxHost;
|
using static System.Windows.Forms.AxHost;
|
||||||
@@ -120,6 +121,8 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
UPort();//启动串口
|
UPort();//启动串口
|
||||||
CountDown();
|
CountDown();
|
||||||
TcpClientNEW();
|
TcpClientNEW();
|
||||||
|
PortClientNEW();
|
||||||
|
ClientNEW();
|
||||||
SQL_LINK();
|
SQL_LINK();
|
||||||
}
|
}
|
||||||
public static void USERCapacity(string user) //权限
|
public static void USERCapacity(string user) //权限
|
||||||
@@ -361,7 +364,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
"AND EndTime >'" + DateTime.Now.AddHours(-8).ToString("yyyy/MM/dd HH:mm:ss") + "'", null).Tables[0]; //读取表写入缓存
|
"AND EndTime >'" + DateTime.Now.AddHours(-8).ToString("yyyy/MM/dd HH:mm:ss") + "'", null).Tables[0]; //读取表写入缓存
|
||||||
for (int k = 0; k < WorkOrderstepdata.Rows.Count; k++)
|
for (int k = 0; k < WorkOrderstepdata.Rows.Count; k++)
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "Type", "ID='" + k + "'").ToString() == "838")
|
if (Convert.ToBoolean(Selet_Machines(Machines, "Type", "ID='" + k + "'")))
|
||||||
{
|
{
|
||||||
string WorkOrderdata_m = WorkOrderstepdata.Select()[k].Field<object>("Machines").ToString();
|
string WorkOrderdata_m = WorkOrderstepdata.Select()[k].Field<object>("Machines").ToString();
|
||||||
DataTable dataTable = WorkOrderSQL.ExecuteDataSet("select * from WorkorderSteps where WorkOrder='" +
|
DataTable dataTable = WorkOrderSQL.ExecuteDataSet("select * from WorkorderSteps where WorkOrder='" +
|
||||||
@@ -375,7 +378,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
WorkOrderSQL.Update("WorkOrder", new Dictionary<string, object> { { "State", 112 } },
|
WorkOrderSQL.Update("WorkOrder", new Dictionary<string, object> { { "State", 112 } },
|
||||||
"WorkOrder ='" + WorkOrderstepdata.Select()[k].Field<object>("WorkOrder").ToString() + "'", null);
|
"WorkOrder ='" + WorkOrderstepdata.Select()[k].Field<object>("WorkOrder").ToString() + "'", null);
|
||||||
}
|
}
|
||||||
else if (Selet_Machines(Machines, "Type", "ID='" + k + "'").ToString() == "828")
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -385,7 +388,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
"AND EndTime >'" + DateTime.Now.AddHours(-8).ToString("yyyy/MM/dd HH:mm:ss") + "'", null).Tables[0]; //读取表写入缓存
|
"AND EndTime >'" + DateTime.Now.AddHours(-8).ToString("yyyy/MM/dd HH:mm:ss") + "'", null).Tables[0]; //读取表写入缓存
|
||||||
for (int k = 0; k < WorkOrderdata.Rows.Count; k++)
|
for (int k = 0; k < WorkOrderdata.Rows.Count; k++)
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "Type", "ID='" + k + "'").ToString() == "838")
|
if (Convert.ToBoolean( Selet_Machines(Machines, "Type", "ID='" + k + "'")))
|
||||||
{
|
{
|
||||||
string WorkOrderdata_m = WorkOrderdata.Select()[k].Field<object>("Machines").ToString();
|
string WorkOrderdata_m = WorkOrderdata.Select()[k].Field<object>("Machines").ToString();
|
||||||
string State = Selet_Machines(Machines, "State", "Name='" + WorkOrderdata_m + "'").ToString();
|
string State = Selet_Machines(Machines, "State", "Name='" + WorkOrderdata_m + "'").ToString();
|
||||||
@@ -410,7 +413,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
"WorkOrder ='" + WorkOrderdata.Select()[k].Field<object>("WorkOrder").ToString() + "'", null);
|
"WorkOrder ='" + WorkOrderdata.Select()[k].Field<object>("WorkOrder").ToString() + "'", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Selet_Machines(Machines, "Type", "ID='" + k + "'").ToString() == "828")
|
else
|
||||||
{
|
{
|
||||||
string WorkOrderdata_m = WorkOrderdata.Select()[k].Field<object>("Machines").ToString();
|
string WorkOrderdata_m = WorkOrderdata.Select()[k].Field<object>("Machines").ToString();
|
||||||
string State = Selet_Machines(Machines, "State", "Name='" + WorkOrderdata_m + "'").ToString();
|
string State = Selet_Machines(Machines, "State", "Name='" + WorkOrderdata_m + "'").ToString();
|
||||||
@@ -442,7 +445,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
"AND EndTime >'" + DateTime.Now.AddHours(-8).ToString("yyyy/MM/dd HH:mm:ss") + "'", null).Tables[0]; //读取表写入缓存
|
"AND EndTime >'" + DateTime.Now.AddHours(-8).ToString("yyyy/MM/dd HH:mm:ss") + "'", null).Tables[0]; //读取表写入缓存
|
||||||
for (int k = 0; k < WorkOrderset_.Rows.Count; k++)
|
for (int k = 0; k < WorkOrderset_.Rows.Count; k++)
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "Type", "ID='" + k + "'").ToString() == "838")
|
if (Convert.ToBoolean(Selet_Machines(Machines, "Type", "ID='" + k + "'")))
|
||||||
{
|
{
|
||||||
string WorkOrderset_m = WorkOrderset_.Select()[k].Field<object>("Machines").ToString();
|
string WorkOrderset_m = WorkOrderset_.Select()[k].Field<object>("Machines").ToString();
|
||||||
string WorkOrderset_w = WorkOrderset_.Select()[k].Field<object>("WorkOrder").ToString();
|
string WorkOrderset_w = WorkOrderset_.Select()[k].Field<object>("WorkOrder").ToString();
|
||||||
@@ -462,7 +465,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
WorkOrderSQL.Update("WorkOrder", new Dictionary<string, object> { { "State", 110 } },
|
WorkOrderSQL.Update("WorkOrder", new Dictionary<string, object> { { "State", 110 } },
|
||||||
"WorkOrder ='" + WorkOrderdata.Select()[k].Field<object>("WorkOrder").ToString() + "'", null);
|
"WorkOrder ='" + WorkOrderdata.Select()[k].Field<object>("WorkOrder").ToString() + "'", null);
|
||||||
}
|
}
|
||||||
else if (Selet_Machines(Machines, "Type", "ID='" + k + "'").ToString() == "828")
|
else
|
||||||
{
|
{
|
||||||
string WorkOrderset_m = WorkOrderset_.Select()[k].Field<object>("Machines").ToString();
|
string WorkOrderset_m = WorkOrderset_.Select()[k].Field<object>("Machines").ToString();
|
||||||
string WorkOrderset_w = WorkOrderset_.Select()[k].Field<object>("WorkOrder").ToString();
|
string WorkOrderset_w = WorkOrderset_.Select()[k].Field<object>("WorkOrder").ToString();
|
||||||
@@ -490,26 +493,26 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
//系统时间
|
//系统时间
|
||||||
Sys_Time = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
|
Sys_Time = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
|
||||||
//更新机台状态与发送指令
|
//更新机台状态与发送指令
|
||||||
for (int i = 0; i < Machinesdata_Count; i++)
|
foreach (DataRow MachinesRow in Machines.Rows)
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "Type", "ID='" + i + "'").ToString() == "838")
|
if (Convert.ToBoolean(MachinesRow["Type"]))
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "State", "ID='" + i + "'").ToString() == "802")
|
if (MachinesRow["State"].ToString() == "802")
|
||||||
{
|
{
|
||||||
stringQueue.Enqueue(new QueueString
|
stringQueue.Enqueue(new QueueString
|
||||||
{
|
{
|
||||||
ID = i,
|
ID = Convert.ToInt16( MachinesRow["ID"]),
|
||||||
DAT = "SC830" + Selet_Machines(Machines, "SYSKEY", "ID='" + i + "'").ToString()
|
DAT = "SC830" + MachinesRow["SYSKEY"]
|
||||||
});//信息插入队列
|
});//信息插入队列
|
||||||
|
|
||||||
bool mode = Machines.Select("ID='" + i + "'").First().Field<bool>("LOCK");//发送锁定状态
|
bool mode =Convert.ToBoolean( MachinesRow["LOCK"]) ;//发送锁定状态
|
||||||
if (mode)
|
if (mode)
|
||||||
{
|
{
|
||||||
Dictionary<string, object> dat_829 = new Dictionary<string, object>();
|
Dictionary<string, object> dat_829 = new Dictionary<string, object>();
|
||||||
dat_829.Clear();
|
dat_829.Clear();
|
||||||
dat_829.Add("NAME", "LOCK");
|
dat_829.Add("NAME", "LOCK");
|
||||||
dat_829.Add("VALUE", "True");
|
dat_829.Add("VALUE", "True");
|
||||||
DataRow drEmployee = Machines.Select("ID='" + i + "'").First();
|
DataRow drEmployee = Machines.Select("ID='" + MachinesRow["ID"] + "'").First();
|
||||||
int index = Convert.ToInt16(drEmployee.Field<object>("ID"));
|
int index = Convert.ToInt16(drEmployee.Field<object>("ID"));
|
||||||
stringQueue.Enqueue(new QueueString
|
stringQueue.Enqueue(new QueueString
|
||||||
{
|
{
|
||||||
@@ -518,98 +521,93 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "101");
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "101");
|
||||||
}
|
}
|
||||||
int m_run = (int)Selet_Machines(Machines, "WORK_RUN", "ID='" + i + "'");
|
int m_run =Convert.ToInt16( MachinesRow["WORK_RUN"]);
|
||||||
if (m_run == 0)
|
if (m_run == 0)
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "101");//停止状态
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "101");//停止状态
|
||||||
}
|
}
|
||||||
else if (m_run == 1)
|
else if (m_run == 1)
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "101");//暂停状态
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "101");//暂停状态
|
||||||
}
|
}
|
||||||
else if (m_run == 2)
|
else if (m_run == 2)
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "202");//运行
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "202");//运行
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bool)Selet_Machines(Machines, "ERR", "ID='" + i + "'"))
|
if (Convert.ToBoolean(MachinesRow["ERR"]))
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "309");//错误
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "309");//错误
|
||||||
}
|
}
|
||||||
|
|
||||||
string mac_s = Selet_Machines(Machines, "State", "ID='" + i + "'").ToString();
|
string mac_s = MachinesRow["State"].ToString();
|
||||||
if ((mac_s == "101") || (mac_s == "201") || (mac_s == "202") || (mac_s == "301") || (mac_s == "309"))//获取信息
|
if ((mac_s == "101") || (mac_s == "201") || (mac_s == "202") || (mac_s == "301") || (mac_s == "309"))//获取信息
|
||||||
{
|
{
|
||||||
stringQueueinf.Enqueue(new QueueString
|
stringQueueinf.Enqueue(new QueueString
|
||||||
{
|
{
|
||||||
ID = i,
|
ID = Convert.ToInt16( MachinesRow["ID"]),
|
||||||
DAT = "SC830" + Selet_Machines(Machines, "SYSKEY", "ID='" + i + "'").ToString()
|
DAT = "SC830" + MachinesRow["SYSKEY"]
|
||||||
});//信息插入队列
|
});//信息插入队列
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Selet_Machines(Machines, "Type", "ID='" + i + "'").ToString() == "828")
|
else
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "State", "ID='" + i + "'").ToString() == "800")
|
if (MachinesRow["State"].ToString() == "800")
|
||||||
{//串口发送
|
{//串口发送
|
||||||
string POR = Selet_Machines(Machines, "Serial", "ID='" + i + "'").ToString();
|
string POR = MachinesRow["Serial"].ToString();
|
||||||
|
|
||||||
stringQueueSerial.Enqueue(new QueueSerial
|
stringQueueSerial.Enqueue(new QueueSerial
|
||||||
{
|
{
|
||||||
ID = POR,
|
ID = POR,
|
||||||
DAT = "SC830[" +
|
DAT = "SC830[" + MachinesRow["Station"] + "]"
|
||||||
Selet_Machines(Machines, "Station", "ID='" + i + "'") + "]"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
bool mode = Machines.Select("ID='" + i + "'").First().Field<bool>("LOCK");//发送锁定状态
|
bool mode =Convert.ToBoolean( MachinesRow["LOCK"]);//发送锁定状态
|
||||||
if (mode)
|
if (mode)
|
||||||
{
|
{
|
||||||
Dictionary<string, object> dat_829 = new Dictionary<string, object>();
|
Dictionary<string, object> dat_829 = new Dictionary<string, object>();
|
||||||
dat_829.Clear();
|
dat_829.Clear();
|
||||||
dat_829.Add("NAME", "LOCK");
|
dat_829.Add("NAME", "LOCK");
|
||||||
dat_829.Add("VALUE", "True");
|
dat_829.Add("VALUE", "True");
|
||||||
DataRow drEmployee = Machines.Select("ID='" + i + "'").First();
|
|
||||||
stringQueueSerial.Enqueue(new QueueSerial
|
stringQueueSerial.Enqueue(new QueueSerial
|
||||||
{
|
{
|
||||||
ID = POR,
|
ID = POR,
|
||||||
DAT = "SC829[" +
|
DAT = "SC829[" + MachinesRow["Station"] + "]" + dat_829.ToJsonString()
|
||||||
Selet_Machines(Machines, "Station", "ID='" + i + "'") + "]" +
|
|
||||||
dat_829.ToJsonString()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "101");
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "101");
|
||||||
}
|
}
|
||||||
|
|
||||||
int m_run = (int)Selet_Machines(Machines, "WORK_RUN", "ID='" + i + "'");
|
int m_run =Convert.ToInt16( MachinesRow["WORK_RUN"]);
|
||||||
if (m_run == 0)
|
if (m_run == 0)
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "101");//停止状态
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "101");//停止状态
|
||||||
}
|
}
|
||||||
else if (m_run == 1)
|
else if (m_run == 1)
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "101");//暂停状态
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "101");//暂停状态
|
||||||
}
|
}
|
||||||
else if (m_run == 2)
|
else if (m_run == 2)
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "202");//运行
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "202");//运行
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bool)Selet_Machines(Machines, "ERR", "ID='" + i + "'"))
|
if (Convert.ToBoolean(MachinesRow["ERR"]))
|
||||||
{
|
{
|
||||||
Updata_Machines(Machines, "State", "ID='" + i + "'", "309");//错误
|
Updata_Machines(Machines, "State", "ID='" + MachinesRow["ID"] + "'", "309");//错误
|
||||||
}
|
}
|
||||||
|
|
||||||
string mac_s = Selet_Machines(Machines, "State", "ID='" + i + "'").ToString();
|
string mac_s = MachinesRow["State"].ToString();
|
||||||
if ((mac_s == "101") || (mac_s == "201") || (mac_s == "202") || (mac_s == "301") || (mac_s == "309"))//获取信息
|
if ((mac_s == "101") || (mac_s == "201") || (mac_s == "202") || (mac_s == "301") || (mac_s == "309"))//获取信息
|
||||||
{
|
{
|
||||||
string POR = Selet_Machines(Machines, "Serial", "ID='" + i + "'").ToString();
|
string POR = MachinesRow["Serial"].ToString();
|
||||||
stringQueueSerial.Enqueue(new QueueSerial
|
stringQueueSerial.Enqueue(new QueueSerial
|
||||||
{
|
{
|
||||||
ID = POR,
|
ID = POR,
|
||||||
DAT = "SC830[" +
|
DAT = "SC830[" + MachinesRow["Station"] + "]"
|
||||||
Selet_Machines(Machines, "Station", "ID='" + i + "'") + "]"
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -630,59 +628,58 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
}
|
}
|
||||||
async void Tick_Event_5S()//Tick_Event周期执行事件5S
|
async void Tick_Event_5S()//Tick_Event周期执行事件5S
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Machinesdata_Count; i++)
|
foreach (DataRow MachinesRow in Machines.Rows)
|
||||||
{/**发送800指令**/
|
{
|
||||||
if (Selet_Machines(Machines, "State", "ID='" + i + "'").ToString() == "801")
|
/**发送800指令**/
|
||||||
|
if (MachinesRow["State"].ToString() == "801")
|
||||||
{
|
{
|
||||||
stringQueue.Enqueue(new QueueString
|
stringQueue.Enqueue(new QueueString
|
||||||
{
|
{
|
||||||
ID = i,
|
ID = Convert.ToInt16(MachinesRow["ID"]),
|
||||||
DAT = "SC800:SCCM[" + Selet_Machines(Machines, "IP", "ID='" + i + "'") + ";" +
|
DAT = "SC800:SCCM[" + MachinesRow["IP"] + ";" + MachinesRow["Prot"] + "]"
|
||||||
Selet_Machines(Machines, "Prot", "ID='" + i + "'") + "]"
|
|
||||||
});//信息插入队列
|
});//信息插入队列
|
||||||
}
|
}
|
||||||
|
|
||||||
/**染机用户信息**/
|
/**染机用户信息**/
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ((int)Selet_Machines(Machines, "UserInfoStart", "ID='" + i + "'") == 901)//打开用户提示信息
|
if (MachinesRow["UserInfoStart"].ToString() == "901")//打开用户提示信息
|
||||||
{
|
{
|
||||||
MainWindow.InfData.Rows.Add(new object[] {
|
MainWindow.InfData.Rows.Add(new object[] {
|
||||||
Selet_Machines(Machines, "Name", "ID='" + i + "'"),
|
MachinesRow["Name"],Properties.Resources.Pequest + MachinesRow["UserInfo"],
|
||||||
Properties.Resources.Pequest + Selet_Machines(Machines, "UserInfo", "ID='" + i + "'"),
|
MachinesRow["SYSKEY"],MachinesRow["ID"]});
|
||||||
Selet_Machines(Machines, "SYSKEY", "ID='" + i + "'"),
|
|
||||||
Selet_Machines(Machines, "ID", "ID='" + i + "'")});
|
Updata_Machines(Machines, "UserInfoStart", "ID='" + MachinesRow["ID"] + "'", "900");
|
||||||
Updata_Machines(Machines, "UserInfoStart", "ID='" + i + "'", "900");
|
|
||||||
}
|
}
|
||||||
if (Selet_Machines(Machines, "UserInfoStart", "ID='" + i + "'").ToString() == "902")//删除用户提示信息
|
if (MachinesRow["UserInfoStart"].ToString() == "902")//删除用户提示信息
|
||||||
{
|
{
|
||||||
MainWindow.InfData.Select("ID='" + i + "'").First().Delete();
|
MainWindow.InfData.Select("ID='" + MachinesRow["ID"] + "'").First().Delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception EX) { LogGing.ERRDATA(EX); }
|
catch (Exception EX) { LogGing.ERRDATA(EX); }
|
||||||
/**染机呼叫状态**/
|
/**染机呼叫状态**/
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ((bool)Selet_Machines(Machines, "CALL", "ID='" + i + "'"))
|
if (Convert.ToBoolean(MachinesRow["CALL"]))
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "Type", "ID='" + i + "'").ToString() == "828")
|
if (Convert.ToBoolean(MachinesRow["Type"]))
|
||||||
{
|
{
|
||||||
string POR = Selet_Machines(Machines, "Serial", "ID='" + i + "'").ToString();
|
stringQueue.Enqueue(new QueueString
|
||||||
|
{
|
||||||
|
ID = Convert.ToInt16(MachinesRow["ID"]),
|
||||||
|
DAT = "SC827" + MachinesRow["SYSKEY"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string POR = MachinesRow["Serial"].ToString();
|
||||||
|
|
||||||
stringQueueSerial.Enqueue(new QueueSerial
|
stringQueueSerial.Enqueue(new QueueSerial
|
||||||
{
|
{
|
||||||
ID = POR,
|
ID = POR,
|
||||||
DAT = "SC827[" +
|
DAT = "SC827[" + MachinesRow["Station"]
|
||||||
Selet_Machines(Machines, "Station", "ID='" + i + "'") + "]"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (Selet_Machines(Machines, "Type", "ID='" + i + "'").ToString() == "838")
|
|
||||||
{
|
|
||||||
stringQueue.Enqueue(new QueueString
|
|
||||||
{
|
|
||||||
ID = i,
|
|
||||||
DAT = "SC827" + Selet_Machines(Machines, "SYSKEY", "ID='" + i + "'")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,8 +740,8 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
"' AND ReDye = " + dataRow.Field<int>("ReDye") +
|
"' AND ReDye = " + dataRow.Field<int>("ReDye") +
|
||||||
" AND StepNumber = " + dataRow.Field<int>("Step"));
|
" AND StepNumber = " + dataRow.Field<int>("Step"));
|
||||||
|
|
||||||
foreach (DataRow Row in Dyelot_CALL.Select("Dyelot='"+ dataRow["Dyelot"]+ "' and Redye ='"+
|
foreach (DataRow Row in Dyelot_CALL.Select("Dyelot='" + dataRow["Dyelot"] + "' and Redye ='" +
|
||||||
dataRow["Redye"]+ "' AND Step = '"+ dataRow["Step"] + "'"))
|
dataRow["Redye"] + "' AND Step = '" + dataRow["Step"] + "'"))
|
||||||
{
|
{
|
||||||
if (dr.Rows.Count > 0)
|
if (dr.Rows.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -766,7 +763,7 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(dt.Select("DyeState = 309").Count() > 0)
|
else if (dt.Select("DyeState = 309").Count() > 0)
|
||||||
{
|
{
|
||||||
foreach (DataRow Row in Dyelot_CALL.Select("Dyelot='" + dataRow["Dyelot"] + "' and Redye ='" +
|
foreach (DataRow Row in Dyelot_CALL.Select("Dyelot='" + dataRow["Dyelot"] + "' and Redye ='" +
|
||||||
dataRow["Redye"] + "' AND Step = '" + dataRow["Step"] + "'"))
|
dataRow["Redye"] + "' AND Step = '" + dataRow["Step"] + "'"))
|
||||||
@@ -927,11 +924,13 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
catch (Exception EX) { LogGing.ERRDATA(EX); }
|
catch (Exception EX) { LogGing.ERRDATA(EX); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Tick_Event_30S()
|
void Tick_Event_30S()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Machines.Rows.Count; i++)
|
/*曲线图*/
|
||||||
|
for (int i = 0; i < Machines.Rows.Count; i++)//曲线图
|
||||||
{
|
{
|
||||||
if (Selet_Machines(Machines, "State", "ID='" + i + "'").ToString() !="800")
|
if (Selet_Machines(Machines, "State", "ID='" + i + "'").ToString() !="800")
|
||||||
{
|
{
|
||||||
@@ -946,13 +945,8 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
|
|
||||||
public static TcpClient[] MachiensTcpClient = new TcpClient[999];
|
public static TcpClient[] MachiensTcpClient = new TcpClient[999];
|
||||||
public static DataRow[] machinesdata = new DataRow[999];
|
public static DataRow[] machinesdata = new DataRow[999];
|
||||||
public int Machinesdata_Count;
|
public void ClientNEW()
|
||||||
public void TcpClientNEW()
|
|
||||||
{
|
{
|
||||||
// bool Machine_ ;
|
|
||||||
machinesdata = Machines.Select("PORT>0 AND IP<>''", "id asc");//获取连接有效的组
|
|
||||||
Machinesdata_Count = machinesdata.Count();
|
|
||||||
|
|
||||||
foreach (DataRow dataRow in Machines.Rows)
|
foreach (DataRow dataRow in Machines.Rows)
|
||||||
{
|
{
|
||||||
dataRow.BeginEdit();
|
dataRow.BeginEdit();
|
||||||
@@ -967,12 +961,32 @@ namespace SunlightCentralizedControlManagement_SCCM_.ViewModel
|
|||||||
dataRow["UserInfoStart"] = 900;
|
dataRow["UserInfoStart"] = 900;
|
||||||
dataRow.EndEdit();
|
dataRow.EndEdit();
|
||||||
dataRow.AcceptChanges();
|
dataRow.AcceptChanges();
|
||||||
|
}
|
||||||
MachiensTcpClient[Convert.ToInt16(dataRow["ID"])]= new TcpClient();
|
}
|
||||||
|
public void TcpClientNEW()
|
||||||
|
{
|
||||||
|
foreach (DataRow dataRow in Machines.Rows)
|
||||||
|
{
|
||||||
|
if (Convert.ToBoolean(dataRow["Type"]))
|
||||||
|
{
|
||||||
|
MachiensTcpClient[Convert.ToInt16(dataRow["ID"])] = new TcpClient();
|
||||||
_ = AsyncTcpClient.TcpClient(MachiensTcpClient[Convert.ToInt16(dataRow["ID"])] //建立tcp连接
|
_ = AsyncTcpClient.TcpClient(MachiensTcpClient[Convert.ToInt16(dataRow["ID"])] //建立tcp连接
|
||||||
, dataRow["IP"].ToString(), dataRow["PORT"].ToString());
|
, dataRow["IP"].ToString(), dataRow["PORT"].ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
public void PortClientNEW()
|
||||||
|
{
|
||||||
|
foreach (DataRow dataRow in Machines.Rows)
|
||||||
|
{
|
||||||
|
if (!Convert.ToBoolean(dataRow["Type"]))
|
||||||
|
{
|
||||||
|
// MachiensTcpClient[Convert.ToInt16(dataRow["ID"])] = new TcpClient();
|
||||||
|
// _ = AsyncTcpClient.TcpClient(MachiensTcpClient[Convert.ToInt16(dataRow["ID"])] //建立tcp连接
|
||||||
|
// , dataRow["IP"].ToString(), dataRow["PORT"].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string SYS_WorkNumder; //工单号
|
public static string SYS_WorkNumder; //工单号
|
||||||
public static int SYS_AT1; //附缸1-3
|
public static int SYS_AT1; //附缸1-3
|
||||||
|
|||||||
Reference in new issue
Block a user