初始化设备
This commit is contained in:
parent
691d894a12
commit
7adb7db2b8
12
BOB.sln
12
BOB.sln
@ -5,8 +5,6 @@ VisualStudioVersion = 17.14.36221.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BOB", "BOB\BOB.csproj", "{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logger", "Logger\Logger.csproj", "{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ORM", "ORM\ORM.csproj", "{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}"
|
||||
@ -17,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csp
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Command", "Command\Command.csproj", "{49D249DE-CB09-4390-89DC-6165965C3933}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceCommand", "DeviceCommand\DeviceCommand.csproj", "{94177FB3-45E4-466E-BB9F-761295736D35}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -27,10 +27,6 @@ Global
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@ -51,6 +47,10 @@ Global
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@ -45,8 +45,8 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Command\Command.csproj" />
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
<ProjectReference Include="..\DeviceCommand\DeviceCommand.csproj" />
|
||||
<ProjectReference Include="..\Logger\Logger.csproj" />
|
||||
<ProjectReference Include="..\Model\Model.csproj" />
|
||||
<ProjectReference Include="..\ORM\ORM.csproj" />
|
||||
<ProjectReference Include="..\Service\Service.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
43
BOB/Models/DeviceConfigModel.cs
Normal file
43
BOB/Models/DeviceConfigModel.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class DeviceConfigModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string DeviceName { get; set; }
|
||||
public string DeviceType { get; set; }
|
||||
public string Remark { get; set; }
|
||||
public ICommunicationConfig CommunicationConfig { get; set; }
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
}
|
||||
public class TcpConfig : ICommunicationConfig
|
||||
{
|
||||
public string IPAddress { get; set; }
|
||||
public int Port { get; set; }
|
||||
public int ReadTimeout { get; set; }
|
||||
public int WriteTimeout { get; set; }
|
||||
}
|
||||
public class SerialPortConfig : ICommunicationConfig
|
||||
{
|
||||
public string COMPort { get; set; }
|
||||
public int BaudRate { get; set; }
|
||||
public int DataBit { get; set; } = 8;
|
||||
public StopBits StopBit { get; set; } = StopBits.One;
|
||||
public Parity ParityBit { get; set; } = Parity.None;
|
||||
public int ReadTimeout { get; set; }
|
||||
public int WriteTimeout { get; set; }
|
||||
}
|
||||
public interface ICommunicationConfig
|
||||
{
|
||||
int ReadTimeout { get; set; }
|
||||
int WriteTimeout { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using Logger;
|
||||
using BOB.Models;
|
||||
using Logger;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
@ -29,7 +30,7 @@ namespace BOB
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string SystemPath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "BOB系统");
|
||||
public string SystemPath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "BOB");
|
||||
|
||||
public int PerformanceLevel { get; set; } = 50;
|
||||
|
||||
@ -38,38 +39,9 @@ namespace BOB
|
||||
public string SubProgramFilePath { get; set; } = @"D:\BOB\子程序\";
|
||||
|
||||
public string DefaultSubProgramFilePath { get; set; } = "";
|
||||
public List<DeviceConfigModel> DeviceList { get; set; } = new();
|
||||
|
||||
// 配置加载方法
|
||||
public void LoadFromFile()
|
||||
{
|
||||
string configPath = Path.Combine(SystemPath, "system.config");
|
||||
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(Instance, Formatting.Indented);
|
||||
File.WriteAllText(configPath, json);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(configPath);
|
||||
var loadedConfig = JsonConvert.DeserializeObject<SystemConfig>(json);
|
||||
|
||||
// 复制所有可写属性(排除JsonIgnore属性)
|
||||
PropertyInfo[] properties = typeof(SystemConfig).GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite && !Attribute.IsDefined(prop, typeof(JsonIgnoreAttribute)))
|
||||
{
|
||||
prop.SetValue(this, prop.GetValue(loadedConfig));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"配置加载失败: {ex.Message}",ex.StackTrace);
|
||||
}
|
||||
}
|
||||
#region 配置加载方法
|
||||
public void SaveToFile()
|
||||
{
|
||||
lock (_lock)
|
||||
@ -79,8 +51,14 @@ namespace BOB
|
||||
if (!Directory.Exists(SystemPath))
|
||||
Directory.CreateDirectory(SystemPath);
|
||||
|
||||
string configPath = Path.Combine(SystemPath, "system.config");
|
||||
string json = JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
string configPath = Path.Combine(SystemPath, "system.json");
|
||||
|
||||
// 支持接口多态序列化
|
||||
string json = JsonConvert.SerializeObject(this, Formatting.Indented,
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = TypeNameHandling.All
|
||||
});
|
||||
|
||||
File.WriteAllText(configPath, json);
|
||||
|
||||
@ -92,5 +70,45 @@ namespace BOB
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFromFile()
|
||||
{
|
||||
string configPath = Path.Combine(SystemPath, "system.json");
|
||||
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
// 文件不存在则保存当前配置
|
||||
SaveToFile();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(configPath);
|
||||
|
||||
// 支持接口多态反序列化
|
||||
var loadedConfig = JsonConvert.DeserializeObject<SystemConfig>(json,
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = TypeNameHandling.All
|
||||
});
|
||||
|
||||
// 复制所有可写属性(排除 JsonIgnore 属性)
|
||||
PropertyInfo[] properties = typeof(SystemConfig).GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite && !Attribute.IsDefined(prop, typeof(JsonIgnoreAttribute)))
|
||||
{
|
||||
prop.SetValue(this, prop.GetValue(loadedConfig));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"配置加载失败: {ex.Message}", ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,10 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Ports" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
146
DeviceCommand/Base/ModbusTcp.cs
Normal file
146
DeviceCommand/Base/ModbusTcp.cs
Normal file
@ -0,0 +1,146 @@
|
||||
using NModbus;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Base
|
||||
{
|
||||
public class ModbusTcp
|
||||
{
|
||||
public string IPAddress { get; set; } = "127.0.0.1";
|
||||
public int Port { get; set; } = 502;
|
||||
public int SendTimeout { get; set; } = 3000;
|
||||
public int ReceiveTimeout { get; set; } = 3000;
|
||||
public TcpClient TcpClient { get; set; } = new();
|
||||
public IModbusMaster Modbus { get; set; }
|
||||
|
||||
public ModbusTcp CreateDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
||||
{
|
||||
IPAddress = ipAddress;
|
||||
Port = port;
|
||||
SendTimeout = sendTimeout;
|
||||
ReceiveTimeout = receiveTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void ChangeDeviceConfig(ModbusTcp modbusTcp, string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
||||
{
|
||||
modbusTcp.IPAddress = ipAddress;
|
||||
modbusTcp.Port = port;
|
||||
if (sendTimeout > 0) modbusTcp.SendTimeout = sendTimeout;
|
||||
if (receiveTimeout > 0) modbusTcp.ReceiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
public static async Task<bool> ConnectAsync(ModbusTcp modbusTcp, CancellationToken ct = default)
|
||||
{
|
||||
if (!modbusTcp.TcpClient.Connected)
|
||||
{
|
||||
modbusTcp.TcpClient.Close();
|
||||
modbusTcp.TcpClient.Dispose();
|
||||
modbusTcp.TcpClient = new TcpClient();
|
||||
await modbusTcp.TcpClient.ConnectAsync(modbusTcp.IPAddress, modbusTcp.Port, ct);
|
||||
modbusTcp.Modbus = new ModbusFactory().CreateMaster(modbusTcp.TcpClient);
|
||||
}
|
||||
else
|
||||
{
|
||||
var remoteEndPoint = (IPEndPoint)modbusTcp.TcpClient.Client.RemoteEndPoint!;
|
||||
var ip = remoteEndPoint.Address.MapToIPv4().ToString();
|
||||
bool isSameAddress = ip.Equals(modbusTcp.IPAddress);
|
||||
bool isSamePort = remoteEndPoint.Port == modbusTcp.Port;
|
||||
if (!isSameAddress || !isSamePort)
|
||||
{
|
||||
modbusTcp.TcpClient.Close();
|
||||
modbusTcp.TcpClient.Dispose();
|
||||
modbusTcp.TcpClient = new TcpClient();
|
||||
await modbusTcp.TcpClient.ConnectAsync(modbusTcp.IPAddress, modbusTcp.Port, ct);
|
||||
modbusTcp.Modbus = new ModbusFactory().CreateMaster(modbusTcp.TcpClient);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ModbusTcpInitialize(ModbusTcp modbusTcp)
|
||||
{
|
||||
if (!modbusTcp.TcpClient.Connected)
|
||||
{
|
||||
modbusTcp.TcpClient = new TcpClient();
|
||||
modbusTcp.TcpClient.SendTimeout = modbusTcp.SendTimeout;
|
||||
modbusTcp.TcpClient.ReceiveTimeout = modbusTcp.ReceiveTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Close(ModbusTcp modbusTcp)
|
||||
{
|
||||
if (modbusTcp.TcpClient.Connected)
|
||||
{
|
||||
modbusTcp.TcpClient.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<ushort[]> ReadHoldingRegistersAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default)
|
||||
{
|
||||
var readTask = modbusTcp.Modbus.ReadHoldingRegistersAsync(slaveAddress, startAddress, numberOfPoints).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP读取保持寄存器超时");
|
||||
return await readTask;
|
||||
}
|
||||
|
||||
public static async Task WriteSingleRegisterAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort registerAddress, ushort value, CancellationToken ct = default)
|
||||
{
|
||||
var sendTask = modbusTcp.Modbus.WriteSingleRegisterAsync(slaveAddress, registerAddress, value).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP写单寄存器超时");
|
||||
}
|
||||
|
||||
public static async Task WriteMultipleRegistersAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort startAddress, ushort[] values, CancellationToken ct = default)
|
||||
{
|
||||
var sendTask = modbusTcp.Modbus.WriteMultipleRegistersAsync(slaveAddress, startAddress, values).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP写多寄存器超时");
|
||||
}
|
||||
|
||||
public static async Task<bool[]> ReadCoilAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default)
|
||||
{
|
||||
var readTask = modbusTcp.Modbus.ReadCoilsAsync(slaveAddress, startAddress, numberOfPoints).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP读取线圈超时");
|
||||
return await readTask;
|
||||
}
|
||||
|
||||
public static async Task WriteSingleCoilAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort coilAddress, bool value, CancellationToken ct = default)
|
||||
{
|
||||
var sendTask = modbusTcp.Modbus.WriteSingleCoilAsync(slaveAddress, coilAddress, value).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP写单线圈超时");
|
||||
}
|
||||
|
||||
public static async Task WriteMultipleCoilsAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort startAddress, bool[] values, CancellationToken ct = default)
|
||||
{
|
||||
var sendTask = modbusTcp.Modbus.WriteMultipleCoilsAsync(slaveAddress, startAddress, values).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP写多线圈超时");
|
||||
}
|
||||
|
||||
public static void ModbusTcpStopNow(ModbusTcp modbusTcp)
|
||||
{
|
||||
if (modbusTcp.TcpClient.Connected) modbusTcp.TcpClient.Close();
|
||||
}
|
||||
|
||||
public static async Task<ushort[]> ReadInputRegisterAsync(ModbusTcp modbusTcp, byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default)
|
||||
{
|
||||
var readTask = modbusTcp.Modbus.ReadInputRegistersAsync(slaveAddress, startAddress, numberOfPoints).WaitAsync(ct);
|
||||
var timeoutTask = Task.Delay(modbusTcp.ReceiveTimeout, ct);
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"ModbusTCP读取输入寄存器超时");
|
||||
return await readTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
160
DeviceCommand/Base/Serial_Port.cs
Normal file
160
DeviceCommand/Base/Serial_Port.cs
Normal file
@ -0,0 +1,160 @@
|
||||
using System.Text;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace DeviceCommand.Base
|
||||
{
|
||||
public class Serial_Port
|
||||
{
|
||||
public string PortName { get; set; } = "COM1";
|
||||
public int BaudRate { get; set; } = 9600;
|
||||
public int DataBits { get; set; } = 8;
|
||||
public StopBits StopBits { get; set; } = StopBits.One;
|
||||
public Parity Parity { get; set; } = Parity.None;
|
||||
public int ReadTimeout { get; set; } = 3000;
|
||||
public int WriteTimeout { get; set; } = 3000;
|
||||
public SerialPort _SerialPort { get; set; } = new SerialPort();
|
||||
|
||||
public Serial_Port CreateDevice(string portName, int baudRate, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, int readTimeout = 3000, int writeTimeout = 3000)
|
||||
{
|
||||
PortName = portName;
|
||||
BaudRate = baudRate;
|
||||
DataBits = dataBits;
|
||||
StopBits = stopBits;
|
||||
Parity = parity;
|
||||
ReadTimeout = readTimeout;
|
||||
WriteTimeout = writeTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void ChangeDeviceConfig(Serial_Port serialPort, string PortName, int BaudRate, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, int ReadTimeout = 3000, int WriteTimeout = 3000)
|
||||
{
|
||||
serialPort.PortName = PortName;
|
||||
serialPort.BaudRate = BaudRate;
|
||||
serialPort.DataBits = dataBits;
|
||||
serialPort.StopBits = stopBits;
|
||||
serialPort.Parity = parity;
|
||||
if (ReadTimeout > 0) serialPort.ReadTimeout = ReadTimeout;
|
||||
if (WriteTimeout > 0) serialPort.WriteTimeout = WriteTimeout;
|
||||
}
|
||||
|
||||
public static async Task<bool> ConnectAsync(Serial_Port serialPort, CancellationToken ct = default)
|
||||
{
|
||||
if (serialPort._SerialPort.PortName != serialPort.PortName
|
||||
|| serialPort._SerialPort.BaudRate != serialPort.BaudRate
|
||||
|| serialPort._SerialPort.Parity != serialPort.Parity
|
||||
|| serialPort._SerialPort.DataBits != serialPort.DataBits
|
||||
|| serialPort._SerialPort.StopBits != serialPort.StopBits
|
||||
|| serialPort._SerialPort.ReadTimeout != serialPort.ReadTimeout
|
||||
|| serialPort._SerialPort.WriteTimeout != serialPort.WriteTimeout)
|
||||
{
|
||||
serialPort._SerialPort.Close();
|
||||
serialPort._SerialPort.PortName = serialPort.PortName;
|
||||
serialPort._SerialPort.BaudRate = serialPort.BaudRate;
|
||||
serialPort._SerialPort.Parity = serialPort.Parity;
|
||||
serialPort._SerialPort.DataBits = serialPort.DataBits;
|
||||
serialPort._SerialPort.StopBits = serialPort.StopBits;
|
||||
serialPort._SerialPort.ReadTimeout = serialPort.ReadTimeout;
|
||||
serialPort._SerialPort.WriteTimeout = serialPort.WriteTimeout;
|
||||
serialPort._SerialPort.Open();
|
||||
}
|
||||
else if (!serialPort._SerialPort.IsOpen)
|
||||
{
|
||||
serialPort._SerialPort.Open();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Close(Serial_Port serialPort)
|
||||
{
|
||||
if (serialPort._SerialPort.IsOpen) serialPort._SerialPort.Close();
|
||||
}
|
||||
|
||||
public static async Task SendAsync(Serial_Port serialPort, byte[] bytes, CancellationToken ct = default)
|
||||
{
|
||||
if (!serialPort._SerialPort.IsOpen) return;
|
||||
var timeoutMs = serialPort.WriteTimeout;
|
||||
if (timeoutMs <= 0)
|
||||
{
|
||||
serialPort._SerialPort.Write(bytes, 0, bytes.Length);
|
||||
return;
|
||||
}
|
||||
var sendTask = Task.Run(() => serialPort._SerialPort.Write(bytes, 0, bytes.Length), ct);
|
||||
var timeoutTask = Task.Delay(timeoutMs, ct);
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"串口通讯异常:写入操作在 {timeoutMs} ms内未完成");
|
||||
await sendTask;
|
||||
}
|
||||
|
||||
public static async Task SendAsync(Serial_Port serialPort, string str, CancellationToken ct = default)
|
||||
{
|
||||
if (!serialPort._SerialPort.IsOpen) return;
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(str);
|
||||
await SendAsync(serialPort, bytes, ct);
|
||||
}
|
||||
|
||||
public static async Task<byte[]> ReadAsync(Serial_Port serialPort, byte[] buffer, CancellationToken ct = default)
|
||||
{
|
||||
if (!serialPort._SerialPort.IsOpen) return null;
|
||||
var timeoutMs = serialPort.ReadTimeout;
|
||||
var readTask = ReadByte(serialPort, buffer, ct);
|
||||
if (timeoutMs <= 0) return await readTask;
|
||||
var timeoutTask = Task.Delay(timeoutMs, ct);
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"串口通讯异常:读取操作在 {timeoutMs} ms内未完成");
|
||||
return await readTask;
|
||||
}
|
||||
|
||||
public static async Task<byte[]> ReadByte(Serial_Port serialPort, byte[] buffer, CancellationToken ct)
|
||||
{
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < buffer.Length)
|
||||
{
|
||||
if (serialPort._SerialPort.BytesToRead > 0)
|
||||
{
|
||||
bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static async Task<string> ReadAsync(Serial_Port serialPort, string delimiter = "\n", CancellationToken ct = default)
|
||||
{
|
||||
if (!serialPort._SerialPort.IsOpen) return null;
|
||||
var timeoutMs = serialPort.ReadTimeout;
|
||||
var readTask = ReadDefaultString(serialPort, delimiter, ct);
|
||||
if (timeoutMs <= 0) return await readTask;
|
||||
var timeoutTask = Task.Delay(timeoutMs, ct);
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"串口通讯异常:读取操作在 {timeoutMs} ms内未完成");
|
||||
return await readTask;
|
||||
}
|
||||
|
||||
private static async Task<string> ReadDefaultString(Serial_Port serialPort, string delimiter, CancellationToken ct)
|
||||
{
|
||||
delimiter ??= "\n";
|
||||
MemoryStream memoryStream = new();
|
||||
byte[] buffer = new byte[2048];
|
||||
string data = string.Empty;
|
||||
await Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (ct.IsCancellationRequested) return;
|
||||
if (serialPort._SerialPort.BytesToRead > 0)
|
||||
{
|
||||
int bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length);
|
||||
memoryStream.Write(buffer, 0, bytesRead);
|
||||
data = Encoding.UTF8.GetString(memoryStream.ToArray());
|
||||
int lineEndIndex = data.IndexOf(delimiter);
|
||||
if (lineEndIndex >= 0)
|
||||
{
|
||||
data = data.Substring(0, lineEndIndex).Trim();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ct);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
169
DeviceCommand/Base/TCP.cs
Normal file
169
DeviceCommand/Base/TCP.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Base
|
||||
{
|
||||
public class Tcp
|
||||
{
|
||||
public string IPAddress { get; set; } = "127.0.0.1";
|
||||
public int Port { get; set; } = 502;
|
||||
public int SendTimeout { get; set; } = 3000;
|
||||
public int ReceiveTimeout { get; set; } = 3000;
|
||||
public TcpClient TcpClient { get; set; } = new();
|
||||
|
||||
public Tcp CreateDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
||||
{
|
||||
IPAddress = ipAddress;
|
||||
Port = port;
|
||||
SendTimeout = sendTimeout;
|
||||
ReceiveTimeout = receiveTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void ChangeDeviceConfig(Tcp tcp, string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
||||
{
|
||||
tcp.IPAddress = ipAddress;
|
||||
tcp.Port = port;
|
||||
if (sendTimeout > 0) tcp.SendTimeout = sendTimeout;
|
||||
if (receiveTimeout > 0) tcp.ReceiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
public static async Task<bool> ConnectAsync(Tcp tcp, CancellationToken ct = default)
|
||||
{
|
||||
if (!tcp.TcpClient.Connected)
|
||||
{
|
||||
tcp.TcpClient.Close();
|
||||
tcp.TcpClient.Dispose();
|
||||
tcp.TcpClient = new TcpClient();
|
||||
await tcp.TcpClient.ConnectAsync(tcp.IPAddress, tcp.Port, ct);
|
||||
}
|
||||
else
|
||||
{
|
||||
var remoteEndPoint = (IPEndPoint)tcp.TcpClient.Client.RemoteEndPoint!;
|
||||
var ip = remoteEndPoint.Address.MapToIPv4().ToString();
|
||||
bool isSameAddress = ip.Equals(tcp.IPAddress);
|
||||
bool isSamePort = remoteEndPoint.Port == tcp.Port;
|
||||
|
||||
if (!isSameAddress || !isSamePort)
|
||||
{
|
||||
tcp.TcpClient.Close();
|
||||
tcp.TcpClient.Dispose();
|
||||
tcp.TcpClient = new TcpClient();
|
||||
await tcp.TcpClient.ConnectAsync(tcp.IPAddress, tcp.Port, ct);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Close(Tcp tcp)
|
||||
{
|
||||
tcp.TcpClient.Close();
|
||||
}
|
||||
|
||||
public static async Task SendAsync(Tcp tcp, byte[] bytes, CancellationToken ct = default)
|
||||
{
|
||||
var timeoutMs = tcp.SendTimeout;
|
||||
if (timeoutMs <= 0)
|
||||
{
|
||||
await tcp.TcpClient.Client.SendAsync(bytes, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
var sendTask = tcp.TcpClient.Client.SendAsync(bytes, ct).AsTask();
|
||||
var timeoutTask = Task.Delay(timeoutMs, ct);
|
||||
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask)
|
||||
throw new TimeoutException($"TCP通讯异常:写入操作在 {timeoutMs} ms内未完成");
|
||||
|
||||
await sendTask;
|
||||
}
|
||||
|
||||
public static async Task SendAsync(Tcp tcp, string str, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync(tcp, Encoding.UTF8.GetBytes(str), ct);
|
||||
}
|
||||
|
||||
public static async Task<byte[]> ReadAsync(Tcp tcp, byte[] buffer, CancellationToken ct = default)
|
||||
{
|
||||
if (!tcp.TcpClient.Connected) return null;
|
||||
|
||||
var timeoutMs = tcp.ReceiveTimeout;
|
||||
if (timeoutMs <= 0)
|
||||
return await ReadBytes(tcp, buffer, ct);
|
||||
|
||||
var readTask = ReadBytes(tcp, buffer, ct);
|
||||
var timeoutTask = Task.Delay(timeoutMs, ct);
|
||||
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask)
|
||||
throw new TimeoutException($"TCP通讯异常:读取操作在 {timeoutMs} ms内未完成");
|
||||
|
||||
return await readTask;
|
||||
}
|
||||
|
||||
private static async Task<byte[]> ReadBytes(Tcp tcp, byte[] buffer, CancellationToken ct)
|
||||
{
|
||||
NetworkStream stream = tcp.TcpClient.GetStream();
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < buffer.Length)
|
||||
{
|
||||
int read = await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead, ct);
|
||||
if (read == 0) return null;
|
||||
bytesRead += read;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static async Task<string> ReadAsync(Tcp tcp, string delimiter = "\n", CancellationToken ct = default)
|
||||
{
|
||||
delimiter ??= "\n";
|
||||
var timeoutMs = tcp.ReceiveTimeout;
|
||||
if (timeoutMs <= 0)
|
||||
return await ReadString(tcp, delimiter, ct);
|
||||
|
||||
var readTask = ReadString(tcp, delimiter, ct);
|
||||
var timeoutTask = Task.Delay(timeoutMs, ct);
|
||||
|
||||
var completedTask = await Task.WhenAny(readTask, timeoutTask);
|
||||
if (completedTask == timeoutTask)
|
||||
throw new TimeoutException($"TCP通讯异常:读取操作在 {timeoutMs} ms内未完成");
|
||||
|
||||
return await readTask;
|
||||
}
|
||||
|
||||
private static async Task<string> ReadString(Tcp tcp, string delimiter, CancellationToken ct)
|
||||
{
|
||||
NetworkStream stream = tcp.TcpClient.GetStream();
|
||||
MemoryStream memoryStream = new();
|
||||
byte[] buffer = new byte[2048];
|
||||
|
||||
int bytesRead;
|
||||
while ((bytesRead = await stream.ReadAsync(buffer, ct)) > 0)
|
||||
{
|
||||
memoryStream.Write(buffer, 0, bytesRead);
|
||||
string data = Encoding.UTF8.GetString(memoryStream.ToArray());
|
||||
int lineEndIndex = data.IndexOf(delimiter);
|
||||
if (lineEndIndex >= 0)
|
||||
return data[..lineEndIndex].Trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<string> WriteRead(Tcp tcp, string str, string endstr, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync(tcp, str, ct);
|
||||
return await ReadAsync(tcp, endstr, ct);
|
||||
}
|
||||
|
||||
public async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||||
{
|
||||
return await ConnectAsync(this, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/E36233A.cs
Normal file
13
DeviceCommand/Device/E36233A.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class E36233A:Tcp
|
||||
{
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/EAEL9080.cs
Normal file
13
DeviceCommand/Device/EAEL9080.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class EAEL9080:ModbusTcp
|
||||
{
|
||||
}
|
||||
}
|
||||
14
DeviceCommand/Device/IT6724C.cs
Normal file
14
DeviceCommand/Device/IT6724C.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class IT6724C: Serial_Port
|
||||
{
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/LQ7500-D.cs
Normal file
13
DeviceCommand/Device/LQ7500-D.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class LQ7500_D: Tcp
|
||||
{
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/PSB11000.cs
Normal file
13
DeviceCommand/Device/PSB11000.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class PSB11000: ModbusTcp
|
||||
{
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/SQ0030G1D.cs
Normal file
13
DeviceCommand/Device/SQ0030G1D.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class SQ0030G1D: Tcp
|
||||
{
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/WS-68030-380T.cs
Normal file
13
DeviceCommand/Device/WS-68030-380T.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class WS_68030_380T:ModbusTcp
|
||||
{
|
||||
}
|
||||
}
|
||||
13
DeviceCommand/Device/ZXKS.cs
Normal file
13
DeviceCommand/Device/ZXKS.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Device
|
||||
{
|
||||
public class ZXKS:ModbusTcp
|
||||
{
|
||||
}
|
||||
}
|
||||
14
DeviceCommand/DeviceCommand.csproj
Normal file
14
DeviceCommand/DeviceCommand.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NModbus" Version="3.0.81" />
|
||||
<PackageReference Include="System.IO.Ports" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -12,7 +12,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Logger\Logger.csproj" />
|
||||
<ProjectReference Include="..\Model\Model.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Logger\Logger.csproj" />
|
||||
<ProjectReference Include="..\Model\Model.csproj" />
|
||||
<ProjectReference Include="..\ORM\ORM.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user