using Modbus.Device;
|
using MyCommunicators;
|
using RJCP.IO.Ports;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.IO.Ports;
|
using System.Linq;
|
using System.Net;
|
using System.Net.Http;
|
using System.Net.Sockets;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace MyProcesses.Communicators
|
{
|
public class ModbusRTU : BaseCommunicator
|
{
|
SerialPort SerialPort = null;
|
|
ModbusSerialMaster ModbusRTUMaster = null;
|
|
ushort startAddress
|
{
|
get
|
{
|
ushort addr = 0;
|
if (CommunicatorConnections.Contains("首地址"))
|
{
|
ushort.TryParse(CommunicatorConnections["首地址"].ToString(), out addr);
|
}
|
return addr;
|
}
|
}
|
ushort numRegisters
|
{
|
get
|
{
|
ushort num = 100;
|
if (CommunicatorConnections.Contains("寄存器个数"))
|
{
|
ushort.TryParse(CommunicatorConnections["寄存器个数"].ToString(), out num);
|
}
|
return num;
|
}
|
}
|
|
public ModbusRTU(string name = "ModbusRTU主站")
|
{
|
CommunicatorConnections.Add("地址", "COM1");
|
CommunicatorConnections.Add("端口", "9600");
|
CommunicatorConnections.Add("首地址", "0");
|
CommunicatorConnections.Add("寄存器个数", "100");
|
CommunicatorBrand = CommunicatorBrand.ModbusRTUMaster;
|
CommunicatorName = name;
|
}
|
|
/// <summary>
|
/// 配置串口参数
|
/// </summary>
|
/// <param name="portName"></param>
|
/// <param name="baudRate"></param>
|
/// <param name="parity"></param>
|
/// <param name="dataBits"></param>
|
/// <param name="stopBits"></param>
|
public void SetConfigure(string portName, int baudRate = 9600, System.IO.Ports.Parity parity = System.IO.Ports.Parity.None,
|
int dataBits = 8, System.IO.Ports.StopBits stopBits = System.IO.Ports.StopBits.One)
|
{
|
Disconnect();
|
SerialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
|
}
|
|
public override bool Connect()
|
{
|
try
|
{
|
Disconnect();
|
|
//波特率
|
int PORT = 0;
|
if (!int.TryParse(this.CommunicatorConnections["端口"].ToString(), out PORT))
|
{
|
Msg = string.Format("端口未设置");
|
return false;
|
}
|
if (!CommunicatorConnections.Contains("地址"))
|
{
|
Msg = string.Format("地址未设置");
|
return false;
|
}
|
//串口号
|
string IP = CommunicatorConnections["地址"].ToString();
|
|
if (!SerialPort.IsOpen)
|
{
|
SerialPort = new SerialPort();
|
SetConfigure(IP, PORT);
|
SerialPort.Open();
|
bConnected = true;
|
|
// 启动心跳线程
|
bHeart = true;
|
//heartbeatThread = new Thread(SendHeartbeat);
|
//heartbeatThread.IsBackground = true;
|
//heartbeatThread.Start();
|
|
// 启动接收线程
|
Task.Run(HandleServerComm);
|
return true;
|
}
|
else
|
{
|
Msg = $"原串口关闭失败无法重新打开";
|
return false;
|
}
|
}
|
catch (Exception ex)
|
{
|
Msg = $"失败,服务器未启动: {ex.Message}";
|
return false;
|
}
|
}
|
|
public override bool Disconnect()
|
{
|
try
|
{
|
bConnected = false;
|
if (SerialPort == null)
|
{
|
SerialPort = new SerialPort();
|
return true;
|
}
|
|
if (SerialPort.IsOpen)
|
SerialPort.Close(); // 关闭串口
|
|
SerialPort = new SerialPort();
|
return true;
|
}
|
catch (Exception ex)
|
{
|
bConnected = false;
|
Msg = $"断开串口时出错: {ex.Message}";
|
return true;
|
}
|
}
|
|
string lastReceiveMsg = "";
|
|
private async Task HandleServerComm()
|
{
|
while (bConnected)
|
{
|
|
try
|
{
|
await Task.Delay(25); // 等待 25ms 后再尝试检查数据
|
|
byte[] buffer = new byte[1024];
|
// 主站轮询从站数据
|
int bytesRead = 0;//= _networkStream.Read(buffer, 0, buffer.Length);
|
if (bytesRead > 0)
|
{
|
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
if (message != null)
|
{
|
strReceiveMsg = message;
|
// 从站数据发生变化时触发消息接收事件
|
if (lastReceiveMsg != strReceiveMsg)
|
{
|
lastReceiveMsg = strReceiveMsg;
|
try
|
{
|
TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg); // 触发运行事件
|
}
|
catch { }
|
try
|
{
|
MessageReceived?.Invoke(strReceiveMsg); // 触发回调
|
}
|
catch { }
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
bHeart = false;
|
Debug.WriteLine($"接收消息时发生错误: {ex.Message}");
|
}
|
}
|
}
|
|
// 发送消息到服务器
|
public override bool SendMessage(string message)
|
{
|
if (!bConnected)
|
{
|
Msg = "尚未连接到服务器";
|
return false;
|
}
|
|
try
|
{
|
//空消息不发送
|
if (string.IsNullOrEmpty(message) || message.Trim() == "")
|
return true;
|
|
// slaveAddress是目标设备的地址,address是要写入的寄存器地址,value是要写入的数据
|
ModbusRTUMaster.WriteSingleRegisterAsync(1, 0, ushort.Parse(message));
|
|
//_writer.Flush(); // 强制将缓冲区中的数据写入网络流
|
return true;
|
}
|
catch (Exception ex)
|
{
|
bHeart = false;
|
Msg = $"发送消息时发生错误: {ex.Message}";
|
return false;
|
}
|
}
|
}
|
}
|