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功能码方法
///
/// 读一个或多个线圈,返回一个bit真假数组
///
///
///
///
bool[] ReadCoils(int startingAddress, int quantity);
///
/// 读一个或多个离散输入,返回一个bit真假数组
///
///
///
///
bool[] ReadDiscreteInputs(int startingAddress, int quantity);
///
/// 批量读取或单独读取保持寄存器,返回的是32位int数组
///
///
///
///
int[] ReadHoldingRegisters(int startingAddress, int quantity);
///
/// 读一个或多个输入寄存器,返回一个int32位数组
///
///
///
///
int[] ReadInputRegisters(int startingAddress, int quantity);
///
///
///
///
///
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();
}
}
}