using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EasyModbus;
namespace HH.WCS.Mobox3.DSZSH.device {
///
/// modbus tcp 用第三方的包
///
public class ModbusHelper {
// 内存,连接上的 Modbus 通讯对象
private static Dictionary _ipPort_ModbusClient = new Dictionary();
public ModbusHelper(string ip, int port = 502, byte slaveId = 1) {
Init(ip, port, slaveId);
}
///
/// Modbus 启动初始化
///
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);
}
}
///
/// 重连所有 Modbus 设备
///
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);
}
}
///
/// 连接 Modbus 下位机(私有,内部调用)
///
///
private static void Link(ModbusClient modbusClient) {
try {
modbusClient.Disconnect();
modbusClient.Connect();
if (modbusClient.Connected) {
//连接上
}
else {
//没连上
}
}
catch (Exception ex) {
LogHelper.InfoEx(ex);
}
}
///
/// 读一个或多个线圈,返回一个bit真假数组
///
///
///
///
///
///
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;
}
///
/// 写入单个线圈
///
///
///
///
///
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;
}
///
/// 写入多个线圈
///
///
///
///
///
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;
}
///
/// 批量读取或单独读取保持寄存器,返回的是32位int数组
///
/// 读取起始位
/// 读取的数量
/// IP地址
/// 端口号
///
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;
}
///
/// 写入单个寄存器数据
///
///
///
///
///
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;
}
///
/// 写入多个寄存器数据
///
///
///
///
///
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;
}
///
/// 读一个或多个离散输入,返回一个bit真假数组
///
///
///
///
///
///
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;
}
///
/// 读一个或多个输入寄存器,返回一个int32位数组
///
///
///
///
///
///
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
///
/// 获取 Modbus 通讯对象(私有,内部调用)
///
///
///
///
///
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;
//}
}
}
}