You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
6.2 KiB

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