New file |
| | |
| | | using System; |
| | | using System.Net.Sockets; |
| | | using System.Net; |
| | | using Microsoft.Owin.BuilderProperties; |
| | | using System.Web.Services.Description; |
| | | using Org.BouncyCastle.Utilities.Net; |
| | | using System.Web.UI.WebControls.WebParts; |
| | | using System.Linq; |
| | | |
| | | using TcpClient = System.Net.Sockets.TcpClient; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.device { |
| | | // 定义Modbus通讯接口 |
| | | public interface IModbusCommunicator : IDisposable { |
| | | bool IsConnected { get; } |
| | | |
| | | void Link(string ipAddress, int port); |
| | | void Disconnect(); |
| | | void ReconnectAll(); |
| | | |
| | | // 常用的Modbus功能码方法 |
| | | /// <summary> |
| | | /// 读一个或多个线圈,返回一个bit真假数组 |
| | | /// </summary> |
| | | /// <param name="startingAddress"></param> |
| | | /// <param name="quantity"></param> |
| | | /// <returns></returns> |
| | | bool[] ReadCoils(int startingAddress, int quantity); |
| | | /// <summary> |
| | | /// 读一个或多个离散输入,返回一个bit真假数组 |
| | | /// </summary> |
| | | /// <param name="startingAddress"></param> |
| | | /// <param name="quantity"></param> |
| | | /// <returns></returns> |
| | | bool[] ReadDiscreteInputs(int startingAddress, int quantity); |
| | | /// <summary> |
| | | /// 批量读取或单独读取保持寄存器,返回的是32位int数组 |
| | | /// </summary> |
| | | /// <param name="startingAddress"></param> |
| | | /// <param name="quantity"></param> |
| | | /// <returns></returns> |
| | | int[] ReadHoldingRegisters(int startingAddress, int quantity); |
| | | /// <summary> |
| | | /// 读一个或多个输入寄存器,返回一个int32位数组 |
| | | /// </summary> |
| | | /// <param name="startingAddress"></param> |
| | | /// <param name="quantity"></param> |
| | | /// <returns></returns> |
| | | int[] ReadInputRegisters(int startingAddress, int quantity); |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="coilAddress"></param> |
| | | /// <param name="value"></param> |
| | | bool WriteSingleCoil(int coilAddress, bool value); |
| | | bool WriteSingleRegister(int registerAddress, ushort value); |
| | | bool WriteMultipleCoils(int startingAddress, bool[] values); |
| | | bool WriteMultipleRegisters(int startingAddress, int[] values); |
| | | } |
| | | |
| | | // Modbus通讯方式枚举 |
| | | public enum ModbusCommunicationType { |
| | | EasyModbus, |
| | | TcpSocket |
| | | } |
| | | |
| | | // Modbus通讯工厂类 |
| | | public static class ModbusFactory { |
| | | public static IModbusCommunicator CreateCommunicator(ModbusCommunicationType type) { |
| | | switch (type) { |
| | | case ModbusCommunicationType.EasyModbus: |
| | | return new EasyModbusCommunicator(); |
| | | case ModbusCommunicationType.TcpSocket: |
| | | return new TcpSocketCommunicator(); |
| | | default: |
| | | //throw new ArgumentException("不支持的Modbus通信方式:请选择EasyModbus或TcpSocket"); |
| | | LogHelper.Info("不支持的Modbus通信方式:请选择EasyModbus或TcpSocket"); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | static void Test() { |
| | | var communicator = ModbusFactory.CreateCommunicator(ModbusCommunicationType.TcpSocket); |
| | | } |
| | | } |
| | | |
| | | // EasyModbus实现 |
| | | public class EasyModbusCommunicator : IModbusCommunicator { |
| | | private EasyModbus.ModbusClient _modbusClient; |
| | | |
| | | public bool IsConnected => _modbusClient?.Connected ?? false; |
| | | |
| | | public void Link(string ipAddress, int port) { |
| | | if (IsConnected) { |
| | | LogHelper.Info($"(ip:{ipAddress}, port:{port})已经连接"); |
| | | return; |
| | | } |
| | | |
| | | _modbusClient = new EasyModbus.ModbusClient(ipAddress, port); |
| | | _modbusClient.Connect(); |
| | | |
| | | if (IsConnected) { |
| | | LogHelper.Info($"连接成功:{ipAddress}:{port}"); |
| | | } |
| | | else { |
| | | LogHelper.Info($"连接失败:{ipAddress}:{port}"); |
| | | } |
| | | } |
| | | |
| | | public void Disconnect() { |
| | | if (!IsConnected) { |
| | | LogHelper.Info($"当前没有要断开的连接"); |
| | | return; |
| | | } |
| | | |
| | | _modbusClient?.Disconnect(); |
| | | |
| | | if (IsConnected) { |
| | | LogHelper.Info($"连接成功:{_modbusClient.IPAddress}:{_modbusClient.Port}"); |
| | | } |
| | | else { |
| | | LogHelper.Info($"连接失败:{_modbusClient.IPAddress} : {_modbusClient.Port}"); |
| | | } |
| | | } |
| | | |
| | | public void ReconnectAll() { |
| | | if (_modbusClient != null) { |
| | | var ip = _modbusClient.IPAddress; |
| | | var port = _modbusClient.Port; |
| | | Disconnect(); |
| | | Link(ip, port); |
| | | } |
| | | } |
| | | |
| | | public bool[] ReadCoils(int startingAddress, int quantity) { |
| | | bool[] res = new bool[0]; |
| | | if (_modbusClient != null && IsConnected) { |
| | | try { |
| | | res = _modbusClient.ReadCoils(startingAddress, quantity); |
| | | if (res.Length != 0) { |
| | | //读取成功 |
| | | LogHelper.Info($"读取成功:ReadCoils"); |
| | | } |
| | | else { |
| | | //读取失败 |
| | | LogHelper.Info($"读取失败:ReadCoils"); |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex); |
| | | } |
| | | } |
| | | else { |
| | | LogHelper.Info($"设备未连接,读取失败:ReadCoils"); |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | public bool[] ReadDiscreteInputs(int startingAddress, int quantity) { |
| | | bool[] res = new bool[0]; |
| | | if (_modbusClient != null && IsConnected) { |
| | | try { |
| | | res = _modbusClient.ReadDiscreteInputs(startingAddress, quantity); |
| | | if (res.Length != 0) { |
| | | //读取成功 |
| | | LogHelper.Info($"读取成功:ReadDiscreteInputs"); |
| | | } |
| | | else { |
| | | //读取失败 |
| | | LogHelper.Info($"读取失败:ReadDiscreteInputs"); |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex); |
| | | } |
| | | } |
| | | else { |
| | | LogHelper.Info($"设备未连接,读取失败:ReadDiscreteInputs"); |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | public int[] ReadHoldingRegisters(int startingAddress, int quantity) { |
| | | int[] res = new int[0]; |
| | | var client = _modbusClient; |
| | | var ip = client.IPAddress; |
| | | var port = client.Port; |
| | | if (client != null && client.Connected) { |
| | | try { |
| | | //一个寄存器是16位,返回2个int类型 |
| | | res = client.ReadHoldingRegisters(startingAddress, quantity); |
| | | 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 int[] ReadInputRegisters(int startingAddress, int quantity) { |
| | | int[] res = new int[0]; |
| | | var client = _modbusClient; |
| | | var ip = client.IPAddress; |
| | | var port = client.Port; |
| | | if (client != null && client.Connected) { |
| | | try { |
| | | res = client.ReadInputRegisters(startingAddress, quantity); |
| | | if (res.Length != 0) { |
| | | //读取成功 |
| | | } |
| | | else { |
| | | //读取失败 |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | |
| | | } |
| | | } |
| | | else { |
| | | |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | public bool WriteSingleCoil(int coilAddress, bool value) { |
| | | var res = false; |
| | | var client = _modbusClient; |
| | | var ip = client.IPAddress; |
| | | var port = client.Port; |
| | | if (client != null && client.Connected) { |
| | | try { |
| | | client.WriteSingleCoil(coilAddress, value); |
| | | res = value == client.ReadCoils(coilAddress, 1)[0]; |
| | | if (res) { |
| | | //写入成功 |
| | | } |
| | | else { |
| | | //写入失败 |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | |
| | | } |
| | | } |
| | | else { |
| | | |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | public bool WriteSingleRegister(int registerAddress, ushort value) { |
| | | var res = false; |
| | | var client = _modbusClient; |
| | | var ip = client.IPAddress; |
| | | var port = client.Port; |
| | | if (client != null && client.Connected) { |
| | | try { |
| | | client.WriteSingleRegister(registerAddress, value); |
| | | res = value == client.ReadHoldingRegisters(registerAddress, 1)[0]; |
| | | if (res) { |
| | | //写入成功 |
| | | } |
| | | else { |
| | | //写入失败 |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | |
| | | } |
| | | } |
| | | else { |
| | | |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | public bool WriteMultipleCoils(int startingAddress, bool[] values) { |
| | | var res = false; |
| | | var client = _modbusClient; |
| | | var ip = client.IPAddress; |
| | | var port = client.Port; |
| | | if (client != null && client.Connected) { |
| | | try { |
| | | client.WriteMultipleCoils(startingAddress, values); |
| | | var dataRead = client.ReadCoils(startingAddress, values.Length); |
| | | res = values.SequenceEqual(dataRead); |
| | | if (res) { |
| | | //写入成功 |
| | | } |
| | | else { |
| | | //写入失败 |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | |
| | | } |
| | | } |
| | | else { |
| | | |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | public bool WriteMultipleRegisters(int startingAddress, int[] values) { |
| | | var res = false; |
| | | var client = _modbusClient; |
| | | var ip = client.IPAddress; |
| | | var port = client.Port; |
| | | var log = string.Join(",", values.Select(x => x.ToString())); |
| | | if (client != null && client.Connected) { |
| | | try { |
| | | client.WriteMultipleRegisters(startingAddress, values); |
| | | var dataRead = client.ReadHoldingRegisters(startingAddress, 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; |
| | | } |
| | | |
| | | public void Dispose() { |
| | | //_modbusClient?.Dispose(); |
| | | } |
| | | } |
| | | |
| | | // TCPSocket实现 |
| | | public class TcpSocketCommunicator : IModbusCommunicator { |
| | | private System.Net.Sockets.TcpClient _tcpClient; |
| | | private NetworkStream _networkStream; |
| | | |
| | | //public bool IsConnected => _tcpClient?.Connected ?? false; |
| | | public bool IsConnected { get { if (_tcpClient != null) { return true; } else { return false; } } } |
| | | |
| | | public void Link(string ipAddress, int port) { |
| | | _tcpClient = new System.Net.Sockets.TcpClient(); |
| | | _tcpClient.Connect(ipAddress, port); |
| | | _networkStream = _tcpClient.GetStream(); |
| | | } |
| | | |
| | | public void Disconnect() { |
| | | _networkStream?.Close(); |
| | | _tcpClient?.Close(); |
| | | } |
| | | |
| | | public void ReconnectAll() { |
| | | if (_tcpClient != null) { |
| | | var ip = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Address.ToString(); |
| | | var port = ((IPEndPoint)_tcpClient.Client.RemoteEndPoint).Port; |
| | | Disconnect(); |
| | | Link(ip, port); |
| | | } |
| | | } |
| | | |
| | | // 以下方法需要根据你的Modbus TCP协议具体实现 |
| | | public bool[] ReadCoils(int startingAddress, int quantity) { |
| | | // 实现TCP方式读取线圈 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public bool[] ReadDiscreteInputs(int startingAddress, int quantity) { |
| | | // 实现TCP方式读取离散输入 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public int[] ReadHoldingRegisters(int startingAddress, int quantity) { |
| | | // 实现TCP方式读取保持寄存器 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public int[] ReadInputRegisters(int startingAddress, int quantity) { |
| | | // 实现TCP方式读取输入寄存器 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public bool WriteSingleCoil(int coilAddress, bool value) { |
| | | // 实现TCP方式写入单个线圈 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public bool WriteSingleRegister(int registerAddress, ushort value) { |
| | | // 实现TCP方式写入单个寄存器 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public bool WriteMultipleCoils(int startingAddress, bool[] values) { |
| | | // 实现TCP方式写入多个线圈 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public bool WriteMultipleRegisters(int startingAddress, int[] values) { |
| | | // 实现TCP方式写入多个寄存器 |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | public void Dispose() { |
| | | _networkStream?.Dispose(); |
| | | //_tcpClient?.Dispose(); |
| | | } |
| | | } |
| | | } |