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();
|
}
|
}
|
}
|