using NModbus; using System.Net.Sockets; using VOL.Data.IServices.modbus; using VOL.Core.Utils; using VOL.Core.Extensions; using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; namespace VOL.Data.Services.modbus { public class ModbusTcpService : IModbusService { // IP private string ip { set; get; } = "127.0.0.1"; // 端口 private int port { set; get; } = 502; // 从站地址 private int slaveNo { set; get; } = 1; private TcpClient client; private IModbusMaster modbusMaster; public ModbusTcpService(string ip, int port) { this.ip = ip; this.port = port; this.client = new TcpClient(ip, port); this.createModbusClient(); } public void createModbusClient() { ModbusFactory modbusFactory = new(); modbusMaster = modbusFactory.CreateMaster(client); modbusMaster.Transport.ReadTimeout = 3000; //读超时 modbusMaster.Transport.WriteTimeout = 3000;//写超时 modbusMaster.Transport.Retries = 3; modbusMaster.Transport.WaitToRetryMilliseconds = 500;//尝试重复连接间隔 } // 是否已连接 public bool isConnected { get => client.Connected; } // 写寄存器数据 public void writeData(byte slaveAddress, ushort startAddress, object data) { var type = data.GetType().Name.ToLower(); dynamic val ; ushort[]? units; // 单元数 switch (type) { case "int16": val = data.ToShort(); units = new ushort[1]; DataConvertUtil.SetShort(units, 0, val); break; case "int32": val = data.ToInt(); units = new ushort[2]; DataConvertUtil.SetInt(units, 0, val); break; case "single": val = data.ToFloat(); units = new ushort[2]; DataConvertUtil.SetReal(units, 0, val); break; case "string": val = data.ToString(); int length = (int) Math.Ceiling((double) val.Length / 2); units = new ushort[length]; // 先不考虑中文字符,一个寄存器地址存放两个字符 DataConvertUtil.SetString(units, 0, val); // units 25690 25690 break; default: throw new ArgumentException("暂未实现写入此类型:"+ type); } if (units != null) { this.WriteMultipleRegisters(slaveAddress, startAddress, units); } } // 读寄存器数据 public dynamic readData(byte slaveAddress, ushort startAddress, string type, int units = 1) { type = type.ToLower(); ushort[]? source; dynamic? data = null; switch (type) { case "int16": source = this.ReadHoldingRegisters(slaveAddress, startAddress, 1); data = DataConvertUtil.GetShort(source, 0); break; case "int32": source = this.ReadHoldingRegisters(slaveAddress, startAddress, 2); data = DataConvertUtil.GetInt(source, 0); break; case "single": source = this.ReadHoldingRegisters(slaveAddress, startAddress, 2); data = DataConvertUtil.GetReal(source, 0); break; case "string": //units = val.Length * 2; // 先不考虑中文字符 source = this.ReadHoldingRegisters(slaveAddress, startAddress, (ushort) units); // 25690 25690 0 0 data = DataConvertUtil.GetString(source, 0, units); break; default: throw new ArgumentException("暂未实现读取此类型:" + type); } return data; } // 读线圈 0x01 0x public bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort num) { return modbusMaster.ReadCoils(slaveAddress, startAddress, num); } // 读离散输入 0x02 1x public bool[] ReadInputs(byte slaveAddress, ushort startAddress, ushort num) { return modbusMaster.ReadInputs(slaveAddress, startAddress, num); } // 读保持寄存器 0x03 4x public ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort num) { return modbusMaster.ReadHoldingRegisters(slaveAddress, startAddress, num); } // 读输入寄存器 0x04 3x public ushort[] ReadInputRegisters(byte slaveAddress, ushort startAddress, ushort num) { return modbusMaster.ReadInputRegisters(slaveAddress, startAddress, num); } // 写单个线圈 0x05 public void WriteSingleCoil(byte slaveAddress, ushort startAddress, bool value) { modbusMaster.WriteSingleCoil(slaveAddress, startAddress, value); } // 写单个保持寄存器 0x06 public void WriteSingleRegister(byte slaveAddress, ushort startAddress, ushort value) { modbusMaster.WriteSingleRegister(slaveAddress, startAddress, value); } // 写多个线圈 0x0F public void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] value) { modbusMaster.WriteMultipleCoils(slaveAddress, startAddress, value); } // 写多个保持寄存器 0x10 public void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] value) { modbusMaster.WriteMultipleRegisters(slaveAddress, startAddress, value); } // 关闭Socket public void disConnent() { client.Close(); modbusMaster.Dispose(); } } }