初始化版本
This commit is contained in:
952
SLC1-N/ModbusTCP_28.cs
Normal file
952
SLC1-N/ModbusTCP_28.cs
Normal file
@@ -0,0 +1,952 @@
|
||||
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;
|
||||
|
||||
// 解析每个Bit(8个线圈)
|
||||
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功能10,1015写两个字节 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
|
||||
}
|
||||
Reference in New Issue
Block a user