|
- using BPASmartClient.Message;
- using NModbus;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Sockets;
- using System.Threading;
- using System.Threading.Tasks;
-
- namespace BPASmartClient.Modbus
- {
- public class ModbusTcp
- {
-
- //private volatile static ModbusTcp _Instance;
- //public static ModbusTcp GetInstance => _Instance ?? (_Instance = new ModbusTcp());
- //private ModbusTcp() { }
-
- private ModbusFactory modbusFactory;
- private IModbusMaster master;
- private TcpClient tcpClient;
- private string IPAdress;
- private int Port;
-
- //public Action ConnectOk { get; set; }
-
- /// <summary>
- /// 判断是否连接成功
- /// </summary>
- public bool Connected => tcpClient == null ? false : tcpClient.Connected;
-
- /// <summary>
- /// ModbusTcp 连接设备
- /// </summary>
- /// <param name="ip">ip 地址</param>
- /// <param name="port">端口号,默认502</param>
- public void ModbusTcpConnect(string ip, int port = 502)
- {
- MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接中。。。。");
- IPAdress = ip;
- Port = port;
- modbusFactory = new ModbusFactory();
- Connect();
- master.Transport.ReadTimeout = 2000;//读取超时时间
- master.Transport.WriteTimeout = 2000;//写入超时时间
- master.Transport.Retries = 10;//重试次数
- MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接成功");
- }
-
- private void Connect()
- {
- bool ErrorFlag = false;
- while (!Connected)
- {
- try
- {
- tcpClient = new TcpClient(IPAdress, Port);
- master = modbusFactory.CreateMaster(tcpClient);
- }
- catch (Exception ex)
- {
- if (!ErrorFlag)
- {
- MessageLog.GetInstance.ShowEx($"ModbusTcp 连接失败,IP = {IPAdress},Port = {Port}");
- MessageLog.GetInstance.ShowEx(ex.ToString());
- ErrorFlag = true;
- }
- Thread.Sleep(3000);
- }
- }
- MessageLog.GetInstance.Show("ModbusTcp 连接成功!");
- }
-
- /// <summary>
- /// 获取 M 区 和 VW 区的Modbus的地址
- /// </summary>
- /// <param name="address"></param>
- /// <returns></returns>
- public int GetAddress(string address)
- {
- if (address == null) return -1;
- if (address.Length > 0)
- {
- if (address.ToUpper().Contains("M") && address.Length >= 4)
- {
- var res = address.Substring(1).Split('.');
- if (res != null && res.Length == 2)
- {
- if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress))
- {
- if (ExitAddress >= 0 && ExitAddress <= 7)
- {
- return (firstAddress * 8) + 320 + ExitAddress;
- }
- }
- }
- }
- else if (address.ToUpper().Contains("VW") && address.Length >= 3)
- {
- var res = address.Substring(2);
- if (res != null && int.TryParse(res, out int tempAddress))
- {
- return (tempAddress / 2) + 100;
- }
- }
- }
- return -1;
- }
-
- //public void Readbool(ushort startAddress, ushort len, Action<bool[]> action)
- //{
- // object result;
- // result = Read(startAddress, CommandType.Coils, len);
- // if (result != null)
- // {
- // if (result is bool[] bools)
- // {
- // if (bools.Length == len)
- // {
- // action(bools);
- // }
- // }
- // else if (result is bool bl)
- // {
- // List<bool> boolLists = new List<bool>();
- // boolLists.Add(bl);
- // action(boolLists.ToArray());
- // }
- // }
- //}
-
- public object Read(string address, ushort len = 1, byte slaveAddress = 1)
- {
- if (address == null || tcpClient == null) return default(object);
- ushort startAddress = (ushort)GetAddress(address);
- CommandType commandType = CommandType.Coils;
- try
- {
- if (address.ToUpper().Contains("M"))
- {
- commandType = CommandType.Coils;
- return master.ReadCoils(slaveAddress, startAddress, len);
- }
- else if (address.ToUpper().Contains("VW"))
- {
- commandType = CommandType.HoldingRegisters;
- return master.ReadHoldingRegisters(slaveAddress, startAddress, len);
- }
- else if (address.ToUpper().Contains("I"))
- {
- commandType = CommandType.Inputs;
- return master.ReadInputs(slaveAddress, startAddress, len);
- }
- }
- catch (Exception ex)
- {
- MessageLog.GetInstance.ShowEx($"读取地址:【{address}:= {startAddress}】,读取类型:【{commandType.ToString()}】出错,{ex.ToString()}");
- if (ex.InnerException is SocketException)
- {
- tcpClient = null;
- Connect();
- }
- }
- return default(object);
- }
-
- public void Write<T>(string address, T value, byte slaveAddress = 1)
- {
- if (address == null || tcpClient == null) return;
- ushort startAddress = (ushort)GetAddress(address);
- CommandType commandType = CommandType.Coils;
- try
- {
- if (address.ToUpper().Contains("M"))
- {
- commandType = CommandType.Coils;
- if (value is bool boolValue)
- master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
- else if (value is bool[] boolsValue)
- master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
- }
- else if (address.ToUpper().Contains("VW"))
- {
- commandType = CommandType.HoldingRegisters;
- if (value is ushort ushortValue)
- master.WriteSingleRegister(slaveAddress, startAddress, ushortValue);
- else if (value is ushort[] ushortsValue)
- {
- int len = 100;
- if (ushortsValue.Length > len)
- {
- List<ushort[]> ushortLists = new List<ushort[]>();
- for (int i = 0; i < ushortsValue.Length / len; i++)
- {
- ushortLists.Add(ushortsValue.Skip(0).Take(len).ToArray());
- }
- int y = ushortsValue.Length % len;
-
- if (y > 0)
- {
- ushortLists.Add(ushortsValue.Skip(ushortsValue.Length - y).Take(y).ToArray());
- }
- foreach (var item in ushortLists)
- {
- master.WriteMultipleRegisters(slaveAddress, startAddress, item);
- startAddress += (ushort)item.Length;
- }
- }
- else
- {
- master.WriteMultipleRegisters(slaveAddress, startAddress, ushortsValue);
- }
- }
- }
- else if (address.ToUpper().Contains("I"))
- {
- commandType = CommandType.Inputs;
- }
- }
- catch (Exception ex)
- {
- MessageLog.GetInstance.ShowEx($"读写入地址:【{address}:= {startAddress}】,写入类型:【{commandType.ToString()}】出错,{ex.ToString()}");
- if (ex.InnerException is SocketException)
- {
- tcpClient = null;
- Connect();
- }
- }
- }
-
- //public object Read(ushort startAddress, CommandType readType, ushort num = 1, byte slaveAddress = 1)
- //{
- // object result = new object();
- // if (tcpClient == null) return result;
- // if (num <= 0) return result;
- // try
- // {
- // switch (readType)
- // {
- // case CommandType.Coils:
- // result = master.ReadCoils(slaveAddress, startAddress, num);
- // break;
- // case CommandType.Inputs:
- // result = master.ReadInputs(slaveAddress, startAddress, num);
- // break;
- // case CommandType.HoldingRegisters:
- // result = master.ReadHoldingRegisters(slaveAddress, startAddress, num);
- // break;
- // case CommandType.InputRegisters:
- // result = master.ReadInputRegisters(slaveAddress, startAddress, num);
- // break;
- // default:
- // break;
- // }
- // if (result == null) return new object();
- // if (result is bool[] bools)
- // {
- // if (bools.Length == 1)
- // return bools[0];
- // else
- // return bools;
- // }
- // if (result is ushort[] ushorts)
- // {
- // if (ushorts.Length == 1)
- // return ushorts[0];
- // else
- // return ushorts;
- // }
- // }
- // catch (Exception ex)
- // {
- // MessageLog.GetInstance.ShowEx($"读取地址:【{startAddress}】,读取类型:【{readType}】出错,{ex.ToString()}");
- // if (ex.InnerException is SocketException)
- // {
- // tcpClient = null;
- // Connect();
- // }
- // }
- // return result;
- //}
-
- //public bool Write(ushort startAddress, CommandType writeType, object InputValue, byte slaveAddress = 1)
- //{
- // bool result = false;
- // if (tcpClient == null) return result;
- // if (!(InputValue is bool || InputValue is bool[] || InputValue is ushort || InputValue is ushort[])) return result;
- // try
- // {
- // switch (writeType)
- // {
- // case CommandType.Coils:
- // if (InputValue is bool boolValue)
- // master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
-
- // if (InputValue is bool[] boolsValue)
- // master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
- // break;
- // case CommandType.HoldingRegisters:
- // if (InputValue is ushort ushortValue)
- // master.WriteSingleRegister(slaveAddress, startAddress, ushortValue);
-
- // if (InputValue is ushort[] ushortsValue)
- // {
- // int len = 100;
- // if (ushortsValue.Length > len)
- // {
- // List<ushort[]> ushortLists = new List<ushort[]>();
- // for (int i = 0; i < ushortsValue.Length / len; i++)
- // {
- // ushortLists.Add(ushortsValue.Skip(0).Take(len).ToArray());
- // }
- // int y = ushortsValue.Length % len;
-
- // if (y > 0)
- // {
- // ushortLists.Add(ushortsValue.Skip(ushortsValue.Length - y).Take(y).ToArray());
- // }
- // foreach (var item in ushortLists)
- // {
- // master.WriteMultipleRegisters(slaveAddress, startAddress, item);
- // startAddress += (ushort)item.Length;
- // }
- // }
- // else
- // {
- // master.WriteMultipleRegisters(slaveAddress, startAddress, ushortsValue);
- // }
-
- // }
-
- // break;
- // default:
- // break;
- // }
- // }
- // catch (Exception ex)
- // {
- // MessageLog.GetInstance.ShowEx(ex.ToString());
- // if (ex.InnerException is SocketException)
- // {
- // tcpClient = null;
- // Connect();
- // }
- // return false;
- // }
- // return true;
- //}
-
-
- #region 批量数据读取
- /// <summary>
- /// 读取多个线圈
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="num"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public bool[] ReadCoils(ushort startAddress, ushort num, byte slaveAddress = 1)
- {
- return master.ReadCoils(slaveAddress, startAddress, num);
- }
-
- /// <summary>
- /// 读取多个输入线圈
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="num"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public bool[] ReadInputs(ushort startAddress, ushort num, byte slaveAddress = 1)
- {
- return master.ReadInputs(slaveAddress, startAddress, num);
- }
-
- /// <summary>
- /// 读取多个保持寄存器
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="num"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public ushort[] ReadHoldingRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
- {
- return master.ReadHoldingRegisters(slaveAddress, startAddress, num);
- }
-
- /// <summary>
- /// 读取多个输入寄存器
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="num"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public ushort[] ReadInputRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
- {
- return master.ReadInputRegisters(slaveAddress, startAddress, num);
- }
- #endregion
-
- #region 批量数据写入
- /// <summary>
- /// 写入多个线圈
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="value"></param>
- /// <param name="slaveAddress"></param>
- public void WriteMultipleCoils(ushort startAddress, bool[] value, byte slaveAddress = 1)
- {
- master.WriteMultipleCoils(slaveAddress, startAddress, value);
- }
-
- /// <summary>
- /// 写入多个寄存器
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="value"></param>
- /// <param name="slaveAddress"></param>
- public void WriteMultipleRegisters(ushort startAddress, ushort[] value, byte slaveAddress = 1)
- {
- master.WriteMultipleRegisters(slaveAddress, startAddress, value);
- }
- #endregion
-
- #region 单个数据读取
- /// <summary>
- /// 读取单个线圈
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public bool ReadCoils(ushort startAddress, byte slaveAddress = 1)
- {
- var result = master.ReadCoils(slaveAddress, startAddress, 1);
- if (result == null) return false;
- if (result.Length == 1) return result[0];
- return false;
- //return master.ReadCoils(slaveAddress, startAddress, 1)[0];
- }
-
- /// <summary>
- /// 读取单个输入线圈
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public bool ReadInputs(ushort startAddress, byte slaveAddress = 1)
- {
- var result = master.ReadInputs(slaveAddress, startAddress, 1);
- if (result == null) return false;
- if (result.Length == 1) return result[0];
- return false;
- //return master.ReadInputs(slaveAddress, startAddress, 1)[0];
- }
-
- /// <summary>
- /// 读取单个保持寄存器
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public ushort ReadHoldingRegisters(ushort startAddress, byte slaveAddress = 1)
- {
- if (tcpClient == null) return 0;
- ushort[] result = null;
- try
- {
- result = master.ReadHoldingRegisters(slaveAddress, startAddress, 1);
- }
- catch (Exception ex)
- {
- MessageLog.GetInstance.Show(ex.ToString());
- tcpClient = null;
- Connect();
- }
-
- if (result == null) return 0;
- if (result.Length == 1) return result[0];
- return 0;
- //return master.ReadHoldingRegisters(slaveAddress, startAddress, 1)[0];
- }
-
- /// <summary>
- /// 读取单个输入寄存器
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="slaveAddress"></param>
- /// <returns></returns>
- public ushort ReadInputRegisters(ushort startAddress, byte slaveAddress = 1)
- {
- var result = master.ReadInputRegisters(slaveAddress, startAddress, 1);
- if (result == null) return 0;
- if (result.Length == 1) return result[0];
- return 0;
- //return master.ReadInputRegisters(slaveAddress, startAddress, 1)[0];
- }
- #endregion
-
- #region 单个数据写入
- /// <summary>
- /// 写入单个线圈
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="value"></param>
- /// <param name="slaveAddress"></param>
- public void WriteSingleCoil(ushort startAddress, bool value, byte slaveAddress = 1)
- {
- master.WriteSingleCoil(slaveAddress, startAddress, value);
- }
-
- /// <summary>
- /// 写入单个寄存器
- /// </summary>
- /// <param name="startAddress"></param>
- /// <param name="value"></param>
- /// <param name="slaveAddress"></param>
- public void WriteSingleRegister(ushort startAddress, ushort value, byte slaveAddress = 1)
- {
- master.WriteSingleRegister(slaveAddress, startAddress, value);
- }
- #endregion
- }
-
- public enum CommandType
- {
- /// <summary>
- /// 线圈操作
- /// </summary>
- Coils,
- /// <summary>
- /// 输入线圈操作
- /// </summary>
- Inputs,
- /// <summary>
- /// 保持寄存器操作
- /// </summary>
- HoldingRegisters,
- /// <summary>
- /// 输入寄存器操作
- /// </summary>
- InputRegisters,
- }
-
- }
|