using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
|
using EasyModbus;
|
|
namespace HH.WCS.Mobox3.DSZSH.device {
|
/// <summary>
|
/// modbus tcp 用第三方的包
|
/// </summary>
|
public class ModbusHelper {
|
// 内存,连接上的 Modbus 通讯对象
|
private static Dictionary<string, ModbusClient> _ipPort_ModbusClient = new Dictionary<string, ModbusClient>();
|
|
public ModbusHelper(string ip, int port = 502, byte slaveId = 1) {
|
Init(ip, port, slaveId);
|
}
|
|
/// <summary>
|
/// Modbus 启动初始化
|
/// </summary>
|
public static void Init(string ip, int port = 502, byte slaveId = 1) {
|
// 配置文件读取所有的 Modbus 进行初始化
|
try {
|
if (ip == null || ip.Trim() == "") {
|
// 读取配置信息失败
|
LogHelper.Info("Modbus:读取配置信息失败");
|
return;
|
}
|
|
var modbusClient = new ModbusClient(ip, port);
|
_ipPort_ModbusClient.Add($"{ip}:{port}({slaveId})", modbusClient);
|
Link(modbusClient);
|
}
|
catch (Exception ex) {
|
LogHelper.InfoEx(ex);
|
}
|
}
|
|
/// <summary>
|
/// 重连所有 Modbus 设备
|
/// </summary>
|
public static void Relink() {
|
try {
|
if (_ipPort_ModbusClient.Count == 0) {
|
return;
|
}
|
|
foreach (var item in _ipPort_ModbusClient) {
|
if (!item.Value.Connected) {
|
Link(item.Value);
|
}
|
}
|
}
|
catch (Exception ex) {
|
LogHelper.InfoEx(ex);
|
}
|
}
|
|
/// <summary>
|
/// 连接 Modbus 下位机(私有,内部调用)
|
/// </summary>
|
/// <param name="modbusClient"></param>
|
private static void Link(ModbusClient modbusClient) {
|
try {
|
modbusClient.Disconnect();
|
modbusClient.Connect();
|
if (modbusClient.Connected) {
|
//连接上
|
}
|
else {
|
//没连上
|
}
|
}
|
catch (Exception ex) {
|
LogHelper.InfoEx(ex);
|
}
|
}
|
|
/// <summary>
|
/// 读一个或多个线圈,返回一个bit真假数组
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="qty"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <returns></returns>
|
public static bool[] ReadCoils(int address, int qty, string ip, int port = 502) {
|
bool[] res = new bool[0];
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
res = client.ReadCoils(address, qty);
|
if (res.Length != 0) {
|
//读取成功
|
}
|
else {
|
//读取失败
|
}
|
}
|
catch (Exception ex) {
|
LogHelper.InfoEx(ex);
|
}
|
}
|
else {
|
|
}
|
return res;
|
}
|
|
/// <summary>
|
/// 写入单个线圈
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="value"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
public static bool WriteSingleCoil(int address, bool value, string ip, int port = 502) {
|
var res = false;
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
client.WriteSingleCoil(address, value);
|
res = value == client.ReadCoils(address, 1)[0];
|
if (res) {
|
//写入成功
|
}
|
else {
|
//写入失败
|
}
|
}
|
catch (Exception ex) {
|
|
}
|
}
|
else {
|
|
}
|
return res;
|
}
|
/// <summary>
|
/// 写入多个线圈
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="values"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
public static bool WriteMultipleCoils(int address, bool[] values, string ip, int port = 502) {
|
var res = false;
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
client.WriteMultipleCoils(address, values);
|
var dataRead = client.ReadCoils(address, values.Length);
|
res = values.SequenceEqual(dataRead);
|
if (res) {
|
//写入成功
|
}
|
else {
|
//写入失败
|
}
|
}
|
catch (Exception ex) {
|
|
}
|
}
|
else {
|
|
}
|
return res;
|
|
}
|
|
/// <summary>
|
/// 批量读取或单独读取保持寄存器,返回的是32位int数组
|
/// </summary>
|
/// <param name="address">读取起始位</param>
|
/// <param name="qty">读取的数量</param>
|
/// <param name="ip">IP地址</param>
|
/// <param name="port">端口号</param>
|
/// <returns></returns>
|
public static int[] ReadHoldingRegisters(int address, int qty, string ip, int port = 502) {
|
int[] res = new int[0];
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
//一个寄存器是16位,返回2个int类型
|
res = client.ReadHoldingRegisters(address, qty);
|
if (res.Length != 0) {
|
//读取成功
|
}
|
else {
|
//读取失败
|
}
|
}
|
catch (Exception ex) {
|
//如果请求数量超出保持寄存器的最大数据行数,会报错
|
LogHelper.Info($"发生了异常:{ex.Message},IP:{ip},Port:{port}", "Error");
|
}
|
}
|
else {
|
LogHelper.Info($"未找到Modbus设备实例对象:IP:{ip},Port:{port}");
|
}
|
return res;
|
}
|
|
/// <summary>
|
/// 写入单个寄存器数据
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="value"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
public static bool WriteSingleRegister(int address, int value, string ip, int port = 502) {
|
var res = false;
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
client.WriteSingleRegister(address, value);
|
res = value == client.ReadHoldingRegisters(address, 1)[0];
|
if (res) {
|
//写入成功
|
}
|
else {
|
//写入失败
|
}
|
}
|
catch (Exception ex) {
|
|
}
|
}
|
else {
|
|
}
|
return res;
|
}
|
|
/// <summary>
|
/// 写入多个寄存器数据
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="values"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
public static bool WriteMultipleRegisters(int address, int[] values, string ip, int port = 502) {
|
var res = false;
|
var client = GetModbusClient(ip, port);
|
var log = string.Join(",", values.Select(x => x.ToString()));
|
if (client != null && client.Connected) {
|
try {
|
client.WriteMultipleRegisters(address, values);
|
var dataRead = client.ReadHoldingRegisters(address, values.Length);
|
res = values.SequenceEqual(dataRead);
|
if (res) {
|
LogHelper.Info($"写入成功,IP:{ip},Port:{port},{log}");
|
}
|
else {
|
LogHelper.Info($"写入失败,IP:{ip},Port:{port},{log}");
|
}
|
}
|
catch (Exception ex) {
|
LogHelper.Info($"发生了异常:{ex.Message},IP:{ip},Port:{port},{log}", "Error");
|
}
|
}
|
else {
|
LogHelper.Info($"未配置的设备信息,IP:{ip},Port:{port},{log}");
|
}
|
return res;
|
}
|
|
/// <summary>
|
/// 读一个或多个离散输入,返回一个bit真假数组
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="qty"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <returns></returns>
|
public static bool[] ReadDiscreteInputs(int address, int qty, string ip, int port = 502) {
|
bool[] res = new bool[0];
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
res = client.ReadDiscreteInputs(address, qty);
|
if (res.Length != 0) {
|
//读取成功
|
}
|
else {
|
//读取失败
|
}
|
}
|
catch (Exception ex) {
|
|
}
|
}
|
else {
|
|
}
|
return res;
|
|
}
|
|
/// <summary>
|
/// 读一个或多个输入寄存器,返回一个int32位数组
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="qty"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <returns></returns>
|
public static int[] ReadInputRegisters(int address, int qty, string ip, int port = 502) {
|
int[] res = new int[0];
|
var client = GetModbusClient(ip, port);
|
if (client != null && client.Connected) {
|
try {
|
res = client.ReadInputRegisters(address, qty);
|
if (res.Length != 0) {
|
//读取成功
|
}
|
else {
|
//读取失败
|
}
|
}
|
catch (Exception ex) {
|
|
}
|
}
|
else {
|
|
}
|
return res;
|
}
|
|
public static string ReadHoldingRegistersToString(int address, int qty, string ip, int port = 502) {
|
var readArray = ReadHoldingRegisters(address, qty, ip, port);
|
return RegistersToString(readArray);
|
}
|
|
#region Modbus 协议读写字符串
|
// 将字符串转换为 Modbus 寄存器数组(int[] 形式,每个int存一个16位值)
|
private static int[] StringToRegisters(string text) {
|
// 填充为偶数长度
|
if (text.Length % 2 != 0) {
|
text += '\0';
|
}
|
|
byte[] bytes = Encoding.ASCII.GetBytes(text);
|
int[] registers = new int[bytes.Length / 2];
|
|
for (int i = 0; i < registers.Length; i++) {
|
// 大端序:高位字节在前
|
registers[i] = (bytes[i * 2] << 8) | bytes[i * 2 + 1];
|
}
|
|
return registers;
|
}
|
|
// 将 Modbus 寄存器数组(int[])转换为字符串
|
private static string RegistersToString(int[] registers) {
|
byte[] bytes = new byte[registers.Length * 2];
|
|
for (int i = 0; i < registers.Length; i++) {
|
// 提取低16位(忽略高16位)
|
ushort registerValue = (ushort)(registers[i] & 0xFFFF);
|
|
// 解析大端序
|
bytes[i * 2] = (byte)(registerValue >> 8); // 高位字节
|
bytes[i * 2 + 1] = (byte)(registerValue & 0xFF); // 低位字节
|
}
|
|
// 去除填充的空字符
|
string result = Encoding.ASCII.GetString(bytes).TrimEnd('\0');
|
return result;
|
}
|
#endregion
|
|
/// <summary>
|
/// 获取 Modbus 通讯对象(私有,内部调用)
|
/// </summary>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <param name="slaveId"></param>
|
/// <returns></returns>
|
private static ModbusClient GetModbusClient(string ip, int port = 502, byte slaveId = 1) {
|
if (_ipPort_ModbusClient.TryGetValue($"{ip}:{port}({slaveId})", out var modbusClient)) {
|
return modbusClient;
|
}
|
return null;
|
|
//if (_ipPort_ModbusClient.ContainsKey($"{ip}:{port}({slaveId})")) {
|
// return _ipPort_ModbusClient[$"{ip}:{port}({slaveId})"];
|
//}
|
//else {
|
// return null;
|
//}
|
}
|
}
|
}
|