Files
huabe-sitondao/SLC1-N/ModbusTCP_28.cs
2025-11-14 16:12:32 +08:00

953 lines
32 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using NetWorkHelper;
using NetWorkHelper.IModels;
using NetWorkHelper.TCP;
using SLC1_N;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;
namespace SLC1_N
{
public class ModbusTCP_28 // 28仪器线程类
{
private Thread RunThread; // 线程
public bool[] ArrCoil = new bool[10];
public uint[] ArrRegister = new uint[100];
public OriginClient chxclient;
public string IP; // ip
public bool isthread = true; // 线程标志位
private bool disposed = false; // 添加IDisposable接口
public bool isRunning { get; set; } // 运行标志位
private string CHX4; // 记录站号的4位十六进制
//public bool isReadRegister = false; // 读取寄存器开关标志位
public ModbusTCP_28(int CH)
{
isRunning = false;
CHX4 = CH.ToString("X4");
//Console.WriteLine($"将地址转为4位十六进制: {CHX4}和{CHX4.Substring(2, 2)}01");
// 初始化数组
for (int i = 0; i < ArrCoil.Length; i++)
{
ArrCoil[i] = false;
}
// 初始化数组
for (int i = 0; i < ArrRegister.Length; i++)
{
ArrRegister[i] = 0;
}
chxclient = new OriginClient(CH);
}
// 连接
public void Connect(string ip)
{
try
{
IP = ip;
// 先取消事件订阅
if (chxclient != null)
{
chxclient.OnDataReceived -= Slot_CH1DataReceived;
chxclient.Disconnect();
}
// 新连接
chxclient.Connect("2000", IP, "9999");
chxclient.OnDataReceived += Slot_CH1DataReceived;
}
catch (Exception ex)
{
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}]重连失败: {ex.Message}");
}
}
// 断开
public void Disconnect()
{
if (chxclient.IsConnect)
{
chxclient.Disconnect();
}
}
/*
* 连接标志位仅检查TCP连接是否建立
* 但Modbus设备可能还未准备好通信设备启动延迟、端口未完全初始化等
* 加点延时
*/
// 启动通信线程
public void Start()
{
if (RunThread == null || !RunThread.IsAlive)
{
isthread = true;
RunThread = new Thread(() =>
{
Thread.Sleep(500); // 首次启动延迟(重要)
run();
});
RunThread.IsBackground = true; // 设为后台线程
RunThread.Start();
}
}
~ModbusTCP_28()
{
Dispose(false);
}
// 通信主循环
private void run()
{
int sleepcount = 2;
while (isthread)
{
try
{
if (chxclient.IsConnect)
{
//Console.WriteLine($"{CHX4}-[读取]主循环 T: {chxclient.IsConnect}");
if (sleepcount > 0) // 防止刚开始连接 不稳定 加延时
{
sleepcount--;
Thread.Sleep(250);
}
Thread.Sleep(250);
readCoil();
Thread.Sleep(250);
readRegister();
}
else
{
//Console.WriteLine($"{CHX4}-[读取]主循环 F: {chxclient.IsConnect}");
isRunning = false;
}
}
catch
{
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}]-[读取] 异常: {chxclient.IsConnect}");
isRunning = false;
Thread.Sleep(1000);
}
}
}
// 停止方法
public void Stop()
{
isthread = false;
if (RunThread != null && RunThread.IsAlive)
{
RunThread.Join(1000); // 等待线程结束最多1秒
}
}
// 实现IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// 释放资源
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
Stop();
Disconnect();
chxclient?.Dispose();
}
disposed = true;
}
}
// 接收函数
private void Slot_CH1DataReceived(string str, int idata)
{
//Console.WriteLine($"{CHX4}-[接收]数据:{str} idata:{idata}");
isRunning = true; // 收到数据才算通讯正常。可以排除ip正确但通道不正确的情况
if (str.Length > 6 && str.Substring(0, 4) == $"{CHX4.Substring(2, 2)}01")
{
ParseCoilResponse(str, ref ArrCoil);
}
else if (str.Length > 6 && str.Substring(0, 4) == $"{CHX4.Substring(2, 2)}03")
{
ParseRegisterResponse(str, ref ArrRegister);
}
}
// 解析线圈状态响应
private void ParseCoilResponse(string response, ref bool[] targetArray)
{
try
{
if (response.Length < 6 || !response.StartsWith($"{CHX4.Substring(2, 2)}01"))
return;
int byteCount = Convert.ToInt32(response.Substring(4, 2), 16); // 提取字节数第3字节
int dataIndex = 6; // 提取线圈数据从第4字节开始
for (int i = 0; i < byteCount; i++)
{
if (dataIndex + 2 > response.Length) break;
byte coilData = Convert.ToByte(response.Substring(dataIndex, 2), 16);
dataIndex += 2;
// 解析每个Bit8个线圈
for (int bit = 0; bit < 8; bit++)
{
int coilIndex = i * 8 + bit; // 计算线圈全局索引
if (coilIndex >= targetArray.Length) break;
targetArray[coilIndex] = (coilData & (1 << bit)) != 0 ? true : false;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"解析线圈状态出错: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 解析线圈状态出错", ex);
}
}
// 解析寄存器响应
private void ParseRegisterResponse(string response, ref uint[] targetArray)
{
try
{
if (response.Length < 250 || !response.StartsWith($"{CHX4.Substring(2, 2)}03")) // 实际正常收到长度254
return;
int dataIndex = 6; // 数据开始位置
int registerIndex = 0;
while (dataIndex + 4 <= response.Length && registerIndex < targetArray.Length)
{
// 每2字节4个十六进制字符表示一个寄存器值
targetArray[registerIndex++] = Convert.ToUInt32(response.Substring(dataIndex, 4), 16);
dataIndex += 4;
}
}
catch (Exception ex)
{
Console.WriteLine($"解析寄存器值出错: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 解析寄存器值出错", ex);
}
}
// 读取线圈
public void readCoil()
{
if (!chxclient.IsConnect)
return;
chxclient?.SendData($"{CHX4.Substring(2, 2)} 01 00 00 00 07"); // 0开始读7个
}
// 读取寄存器
private void readRegister()
{
if (!chxclient.IsConnect)
return;
chxclient?.SendData($"{CHX4.Substring(2, 2)} 03 03 E8 00 3D "); // 读取 1000 - 1061
}
// 读取浮点
public string readFloat(int index) // addr 是十进制地址(如 1013
{
try
{
ushort low = (ushort)ArrRegister[index]; // 低位
ushort high = (ushort)ArrRegister[index + 1]; // 高位
float fdata = TwoUInt16ToFloat(high, low);
return fdata.ToString(); // 返回字符串形式的浮点数
}
catch (Exception ex)
{
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 解析浮点数出错", ex);
}
return "0";
}
// 读取浮点
public string readFloatF2(int index) // addr 是十进制地址(如 1013
{
try
{
ushort low = (ushort)ArrRegister[index]; // 低位
ushort high = (ushort)ArrRegister[index + 1]; // 高位
float fdata = TwoUInt16ToFloat(high, low);
return fdata.ToString("F2"); // 返回字符串形式的浮点数
}
catch (Exception ex)
{
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 解析浮点数出错", ex);
}
return "0";
}
// 写线圈
public void writeCoil(string straddress, bool bdata)
{
if (!chxclient.IsConnect)
return;
try
{
int address = Convert.ToInt32(straddress);
string hexAddress = address.ToString("X4"); // 将地址转为4位十六进制如 "1" → "0001"
if(bdata)
{
chxclient?.SendData($"{CHX4.Substring(2, 2)} 05 00 {hexAddress.Substring(2, 2)} FF 00");
}
else
{
chxclient?.SendData($"{CHX4.Substring(2, 2)} 05 00 {hexAddress.Substring(2, 2)} 00 00");
}
}
catch (Exception ex)
{
MessageBox.Show($"输入错误: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] writeCoil输入错误", ex);
}
}
// 写入单个保持寄存器
public void writeRegister(int address, int value)
{
if (!chxclient.IsConnect)
return;
try
{
string hexAddress = address.ToString("X4"); // 将地址转为4位十六进制如 "1" → "0001"
string hexValue = value.ToString("X4");
string message = $"{CHX4.Substring(2, 2)} 06 {hexAddress.Substring(0, 2)} {hexAddress.Substring(2, 2)} {hexValue.Substring(0, 2)} {hexValue.Substring(2, 2)}";
chxclient?.SendData(message);
}
catch (Exception ex)
{
MessageBox.Show($"输入错误: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] writeRegister输入错误", ex);
}
}
//// 写入多个保持寄存器功能码16每个int占用2个寄存器32位
//public void writeRegisters(int address, int[] values)
//{
// if (!chxclient.IsConnect || values == null || values.Length == 0)
// return;
// try
// {
// string hexAddress = address.ToString("X4");
// int regCount = values.Length * 2; // 每个int占2个寄存器
// string message = $"{CHX4.Substring(2, 2)} 10 " + // 站号 + 功能码
// $"{hexAddress.Substring(0, 2)} {hexAddress.Substring(2, 2)} " + // 地址
// //$"{(regCount >> 8):X2} {(regCount & 0xFF):X2} " + // 寄存器数量
// $"{(regCount * 2):X2}"; // 字节数
// foreach (int val in values)
// {
// byte[] bytes = BitConverter.GetBytes(val);
// if (BitConverter.IsLittleEndian)
// Array.Reverse(bytes); // 转为大端序
// message += $" {bytes[0]:X2}{bytes[1]:X2}{bytes[2]:X2}{bytes[3]:X2}";
// }
// chxclient.SendData(message);
// }
// catch (Exception ex)
// {
// Console.WriteLine($"写入多寄存器(int)失败: {ex.Message}");
// }
//}
// 修改为写入多个保持寄存器功能码16每个int对应1个寄存器
public void writeRegisters(int address, int[] values)
{
if (!chxclient.IsConnect || values == null || values.Length == 0)
return;
try
{
string hexAddress = address.ToString("X4");
int regCount = values.Length; // 修正每个int对应1个寄存器
int byteCount = regCount * 2;
// 构建报文头
string message = $"{CHX4.Substring(2, 2)} 10 " + // 站号 + 功能码
$"{hexAddress.Substring(0, 2)} {hexAddress.Substring(2, 2)} " + // 地址
$"{(regCount >> 8):X2} {(regCount & 0xFF):X2} " + // 寄存器数量(关键修复!)
$"{byteCount:X2} "; // 字节数
// 添加所有数据
foreach (int val in values)
{
// 将int拆分为两个字节大端序
ushort value = (ushort)val; // 只取低16位
message += $"{(value >> 8):X2} {(value & 0xFF):X2} ";
}
Console.WriteLine($"多个保持寄存器 writeRegisters(): {message}");
chxclient?.SendData(message.Replace(" ", "")); // 移除空格
}
catch (Exception ex)
{
Console.WriteLine($"写入多寄存器失败: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 写入多寄存器失败", ex);
}
}
/*
高16位(1014): 0x4048
低16位(1013): 0xF5C3
完整32位: 0x4048F5C3
*/
// 写入浮点
public void writeFloat(int address, float value)
{
if (!chxclient.IsConnect)
return;
try
{
byte[] floatBytes = BitConverter.GetBytes(value); // float转换为4字节IEEE 754格式
ushort highRegister = BitConverter.ToUInt16(floatBytes, 2); // 高16位
ushort lowRegister = BitConverter.ToUInt16(floatBytes, 0); // 低16位
string hexAddress = address.ToString("X4"); // 4位十六进制地址
string message = string.Format(
"{0} 10 {1} {2} 00 02 04 {3:X2}{4:X2} {5:X2}{6:X2}",
CHX4.Substring(2, 2), // 站号
hexAddress.Substring(0, 2), // 起始地址高字节
hexAddress.Substring(2, 2), // 起始地址低字节
(byte)(lowRegister >> 8), // 低寄存器高字节
(byte)lowRegister, // 低寄存器低字节
(byte)(highRegister >> 8), // 高寄存器高字节
(byte)highRegister // 高寄存器低字节
);
// 4. 自动添加CRC校验假设SendData会自动添加
chxclient?.SendData(message);
//Console.WriteLine($"writeFloat: {message}");
//chxclient.SendData("01 10 03 F7 00 02 04 F5 C3 40 48"); // 数据是3.14 站号1功能101015写两个字节 1015-F5C3 1016-4048
}
catch (Exception ex)
{
MessageBox.Show($"写入浮点数失败: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 写入浮点数失败", ex);
}
}
// 写入多个浮点数功能码16每个float占用2个寄存器32位
public void writeFloats(int address, float[] values)
{
if (!chxclient.IsConnect || values == null || values.Length == 0)
return;
try
{
// 构造报文头
string hexAddress = address.ToString("X4");
int regCount = values.Length * 2; // 每个float占2个寄存器
string message = $"{CHX4.Substring(2, 2)} 10 " + // 站号 + 功能码
$"{hexAddress.Substring(0, 2)} {hexAddress.Substring(2, 2)} " + // 地址
$"{(regCount >> 8):X2} {(regCount & 0xFF):X2} " + // 寄存器数量
$"{(regCount * 2):X2}"; // 字节数
foreach (float val in values)
{
byte[] bytes = BitConverter.GetBytes(val);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes); // 转为大端序
// 拆分为两个16位寄存器高16位在前
ushort high = BitConverter.ToUInt16(bytes, 0);
ushort low = BitConverter.ToUInt16(bytes, 2);
message += $" {(high >> 8):X2}{(high & 0xFF):X2} {(low >> 8):X2}{(low & 0xFF):X2}";
}
chxclient?.SendData(message); // 假设自动添加CRC
}
catch (Exception ex)
{
Console.WriteLine($"写入多浮点数失败: {ex.Message}");
mxlLog.Instance.Error($"ModbusTCP_28[{CHX4}] 写入多浮点数失败", ex);
}
}
//UInt16转float
public static float TwoUInt16ToFloat(UInt16 high, UInt16 low)
{
Int32 sum = (high << 16) + (low & 0xFFFF);
byte[] bs = BitConverter.GetBytes(sum);
float fs = BitConverter.ToSingle(bs, 0);
return fs;
}
}
public enum _28Addr
{
[Description("参数编号")]
ParameterNumber = 1000, // 03E8
[Description("当前参数名称")]
CurrentParameterName1 = 1001, // 3E9
[Description("当前参数名称")]
CurrentParameterName2 = 1002, // 3EA
[Description("当前参数名称")]
CurrentParameterName3 = 1003, // 3EB
[Description("当前参数名称")]
CurrentParameterName4 = 1004, // 3EC
[Description("当前参数名称")]
CurrentParameterName5 = 1005, // 3ED
[Description("充气时间")]
InflationTime = 1006, // 3EE
[Description("平衡时间")]
BalanceTime = 1007, // 3EF
[Description("检测时间")]
DetectionTime = 1008, // 3F0
[Description("排气时间")]
ExhaustTime = 1009, // 3F1
[Description("解除输出2时间")]
ReleaseOutput2Time = 1010, // 3F2
[Description("延时1")]
Delay1 = 1011, // 3F3
[Description("延时2")]
Delay2 = 1012, // 3F4
[Description("充气压力上限低位")]
InflationPressureUpperLimitLow = 1013, // 3F5
[Description("充气压力上限高位")]
InflationPressureUpperLimitHigh = 1014, // 3F6
[Description("充气压力下限低位")]
InflationPressureLowerLimitLow = 1015, // 3F7
[Description("充气压力下限高位")]
InflationPressureLowerLimitHigh = 1016, // 3F8
[Description("平衡压差上限低位")]
BalancePressureDiffUpperLimitLow = 1017, // 3F9
[Description("平衡压差上限高位")]
BalancePressureDiffUpperLimitHigh = 1018, // 3FA
[Description("平衡压差下限低位")]
BalancePressureDiffLowerLimitLow = 1019, // 3FB
[Description("平衡压差下限高位")]
BalancePressureDiffLowerLimitHigh = 1020, // 3FC
[Description("允许泄漏量上限低位")]
AllowableLeakageUpperLimitLow = 1021, // 3FD
[Description("允许泄漏量上限高位")]
AllowableLeakageUpperLimitHigh = 1022, // 3FE
[Description("允许泄漏量下限低位")]
AllowableLeakageLowerLimitLow = 1023, // 3FF
[Description("允许泄漏量下限高位")]
AllowableLeakageLowerLimitHigh = 1024, // 400
[Description("等效容积低位")]
EquivalentVolumeLow = 1025, // 401
[Description("等效容积高位")]
EquivalentVolumeHigh = 1026, // 402
[Description("压力单位")]
PressureUnit = 1027, // 403
[Description("泄漏量单位")]
LeakageUnit = 1028, // 404
[Description("仪器状态")]
DeviceStatus = 1034, // 40A
[Description("大漏泄漏量低位(平衡压差)")]
LargeLeakageLow = 1035, // 40B
[Description("大漏泄漏量高位(平衡压差)")]
LargeLeakageHigh = 1036, // 40C
[Description("大漏泄漏量单位(压差单位)")]
LargeLeakageUnit = 1037, // 40D
[Description("微漏泄漏量低位(泄漏量)")]
MicroLeakageLow = 1038, // 40E
[Description("微漏泄漏量高位(泄漏量)")]
MicroLeakageHigh = 1039, // 40F
[Description("微漏泄漏量单位(泄漏量)")]
MicroLeakageUnit = 1040, // 410
[Description("测试结果")]
TestResult = 1041, // 411
[Description("后台压力低位")]
BackgroundPressureLow = 1048, // 418
[Description("后台压力高位")]
BackgroundPressureHigh = 1049, // 419
[Description("后台压差低位")]
BackgroundPressureDiffLow = 1050, // 41A
[Description("后台压差高位")]
BackgroundPressureDiffHigh = 1051, // 41B
[Description("记录-测试压力低位")]
RecordTestPressureLow = 1057, // 421
[Description("记录-测试压力高位")]
RecordTestPressureHigh = 1058, // 422
[Description("记录-压力单位")]
RecordPressureUnit1 = 1059, // 423
[Description("记录-压力单位")]
RecordPressureUnit2 = 1060, // 424
[Description("记录-压力单位")]
RecordPressureUnit3 = 1061, // 0425
// 下面地址无法读取
[Description("记录-测试泄漏量低位")]
RecordTestLeakageLow = 1062, // 426
[Description("记录-测试泄漏量高位")]
RecordTestLeakageHigh = 1063, // 427
[Description("记录-泄漏量单位")]
RecordLeakageUnit1 = 1064, // 428
[Description("记录-泄漏量单位")]
RecordLeakageUnit2 = 1065, // 429
[Description("记录-泄漏量单位")]
RecordLeakageUnit3 = 1066, // 42A
[Description("记录-泄漏量单位")]
RecordLeakageUnit4 = 1067 // 42B
}
// 原FrmClient类
#region FrmClient类
public class OriginClient
{
private SocketState _connectState { get; set; }// 连接状态
private ITcpClient _client { get; set; }// 连接对象
private System.Timers.Timer _timer { get; set; } // 定时器
public bool IsConnect { get; private set; } = false;// 连接状态标志
public int ChannelId { get; private set; }// 通道标识
public event Action<string, int> OnDataReceived;// 数据接收事件
public event Action<bool, int> OnConnectionStateChanged;// 连接状态变化事件
/// <summary>
/// 初始化客户端
/// </summary>
/// <param name="channelId">通道标识</param>
public OriginClient(int channelId)
{
ChannelId = channelId;
InitializeClient();
}
private void InitializeClient()
{
_client = new ITcpClient
{
IsReconnection = true
};
_client.OnStateInfo += Client_OnStateInfo;
_client.OnRecevice += Client_OnRecevice;
_client.OnErrorMsg += Client_OnErrorMsg;
}
/// <summary>
/// 将字符串转换为十六进制字节数组
/// </summary>
private static byte[] StrtoHexbyte(string hexstring)
{
int i;
hexstring = hexstring.Replace(" ", "");
if ((hexstring.Length % 2) != 0)
{
byte[] returnbytes = new byte[(hexstring.Length + 1) / 2];
for (i = 0; i < (hexstring.Length - 1) / 2; i++)
{
returnbytes[i] = Convert.ToByte(hexstring.Substring(i * 2, 2), 16);
}
returnbytes[returnbytes.Length - 1] = Convert.ToByte(hexstring.Substring(hexstring.Length - 1, 1).PadLeft(2, '0'), 16);
return returnbytes;
}
else
{
byte[] returnBytes = new byte[hexstring.Length / 2];
for (i = 0; i < returnBytes.Length; i++)
{
returnBytes[i] = Convert.ToByte(hexstring.Substring(i * 2, 2), 16);
}
return returnBytes;
}
}
/// <summary>
/// 计算CRC冗余码
/// </summary>
private int Crc16_Modbus(byte[] modbusdata, int length)
{
int i, j;
int crc = 0xffff; // 0xffff or 0
for (i = 0; i < length; i++)
{
crc ^= modbusdata[i] & 0xff;
for (j = 0; j < 8; j++)
{
if ((crc & 0x01) == 1)
{
crc = (crc >> 1) ^ 0xa001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
/// <summary>
/// 连接服务器
/// connectinterval:心跳包发送间隔 0不发
/// </summary>
public void Connect(string connectinterval, string ipaddress, string port)
{
try
{
if (!_client.IsStart)
{
_client.IsReconnection = true;
int interval = int.Parse(connectinterval);
_timer = new System.Timers.Timer
{
Interval = 1000 * interval
};
_timer.Elapsed += Timer_Elapsed;
_timer.Start();
_client.ServerIp = ipaddress;
_client.ServerPort = int.Parse(port);
_client.StartConnect();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
MessageBox.Show(ex.StackTrace);
Disconnect();
throw;
}
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// 可以在这里实现定时发送逻辑
}
/// <summary>
/// 连接错误处理
/// </summary>
private void Client_OnErrorMsg(object sender, NetWorkHelper.ICommond.TcpClientErrorEventArgs e)
{
IsConnect = false;
OnConnectionStateChanged?.Invoke(IsConnect, ChannelId);
}
/// <summary>
/// 接收数据处理
/// </summary>
private void Client_OnRecevice(object sender, NetWorkHelper.ICommond.TcpClientReceviceEventArgs e)
{
var len = e.Data.Length;
if (len > 0)
{
string returnStr = "";
for (int i = 0; i < len; i++)
{
returnStr += e.Data[i].ToString("X2");
}
var message = returnStr;
string value = message.Replace(" ", "");
OnDataReceived?.Invoke(message, ChannelId);
}
}
/// <summary>
/// 连接状态处理
/// </summary>
private void Client_OnStateInfo(object sender, NetWorkHelper.ICommond.TcpClientStateEventArgs e)
{
_connectState = e.State;
if (e.StateInfo.Contains("已断开服务器连接"))
{
Disconnect();
}
else if (e.StateInfo.Contains("已连接"))
{
IsConnect = true;
OnConnectionStateChanged?.Invoke(IsConnect, ChannelId);
}
else
{
IsConnect = false;
OnConnectionStateChanged?.Invoke(IsConnect, ChannelId);
}
}
object sendLock = new object();
/// <summary>
/// 发送数据
/// </summary>
public void SendData(string sendMsg)
{
if (!string.IsNullOrWhiteSpace(sendMsg) && IsConnect)
{
try
{
byte[] byt = StrtoHexbyte(sendMsg);
int str2 = Crc16_Modbus(byt, byt.Length);
string str3 = Convert.ToString((str2 >> 8) & 0xff, 16);
string str4 = Convert.ToString(str2 & 0xff, 16);
if (str3.Length == 1)
{
str3 = "0" + str3;
}
if (str4.Length == 1)
{
str4 = "0" + str4;
}
sendMsg = sendMsg + str4 + str3;
var message = StrtoHexbyte(sendMsg);
if (_client != null)
{
lock (sendLock)
{
_client?.SendData(message);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
MessageBox.Show(ex.StackTrace);
throw;
}
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
if (_timer != null)
{
_timer.Stop();
_timer.Dispose();
_timer = null;
}
if (_client != null)
{
_client.IsReconnection = false;
_client.StopConnect();
_client.Dispose();
}
IsConnect = false;
OnConnectionStateChanged?.Invoke(IsConnect, ChannelId);
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
Disconnect();
}
}
#endregion
}