953 lines
32 KiB
C#
953 lines
32 KiB
C#
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
|
||
}
|