同步框架

master
smartwyy 6 months ago
parent 25ee45142e
commit a8a8e4fc02

@ -15,10 +15,11 @@ public static class BitUtls
/// <param name="scale">精度</param> /// <param name="scale">精度</param>
/// <param name="round">保留几位小数</param> /// <param name="round">保留几位小数</param>
/// <param name="offset">位偏移</param> /// <param name="offset">位偏移</param>
/// <param name="unSign">对float和double 默认无符号</param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentException"></exception>
public static object Bytes2Value(byte[] bytes, Type propertyType, int start, int length, public static object Bytes2Value(byte[] bytes, Type propertyType, int start, int length,
double scale, int round, double offset) double scale, int round, double offset, bool unSign = true)
{ {
if (propertyType == BOOLEAN) return Convert.ChangeType(Byte2Bit(bytes, start, length) == 1, propertyType); if (propertyType == BOOLEAN) return Convert.ChangeType(Byte2Bit(bytes, start, length) == 1, propertyType);
@ -44,17 +45,16 @@ public static class BitUtls
if (propertyType == FLOAT) if (propertyType == FLOAT)
return return
Convert.ChangeType(Math.Round(Byte2Float(bytes, start, length, scale) - offset, round), propertyType); Convert.ChangeType(Math.Round(Byte2Float(bytes, start, length, scale, unSign) - offset, round), propertyType);
if (propertyType == DOUBLE) if (propertyType == DOUBLE)
return return
Convert.ChangeType(Math.Round(Byte2Double(bytes, start, length, scale) - offset, round), Convert.ChangeType(Math.Round(Byte2Double(bytes, start, length, scale, unSign) - offset, round),
propertyType); propertyType);
if (propertyType == STRING) if (propertyType == STRING)
{ {
return Convert.ChangeType(Encoding.ASCII.GetString(bytes, start, length/8), propertyType);
return Convert.ChangeType(Encoding.ASCII.GetString(bytes, start, length), propertyType);
} }
if (propertyType == BYTEARRAY) if (propertyType == BYTEARRAY)
@ -221,23 +221,23 @@ public static class BitUtls
return list.ToArray(); return list.ToArray();
} }
public static float Byte2Float(byte[] bytes, int startBit, int length, double factor) public static float Byte2Float(byte[] bytes, int startBit, int length, double factor, bool unSign)
{ {
if (length < 17) if (length < 17)
{ {
int d = Byte2Int16(bytes, startBit, length); int d =unSign ? Byte2UInt16(bytes, startBit, length) : Byte2Int16(bytes, startBit, length);
return (float)(d * factor); return (float)(d * factor);
} }
else else
{ {
var d = Byte2Int32(bytes, startBit, length); Int64 d = unSign ? Byte2UInt32(bytes, startBit, length) : Byte2Int32(bytes, startBit, length) ;
return (float)(d * factor); return (float)(d * factor);
} }
} }
public static double Byte2Double(byte[] bytes, int startBit, int length, double factor) public static double Byte2Double(byte[] bytes, int startBit, int length, double factor, bool unSign)
{ {
var d = Byte2UInt32(bytes, startBit, length); Int64 d = unSign ? Byte2UInt32(bytes, startBit, length) : Byte2Int32(bytes, startBit, length);
return (float)(d * factor); return (float)(d * factor);
} }

@ -91,7 +91,7 @@ public static class ModbusDecoder
} }
case ModbusProperty<float> floatProperty: case ModbusProperty<float> floatProperty:
{ {
SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes); SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes, true);
// SetPropertyValue(floatProperty.RegisterNo, floatProperty, decodeUseBytes); // SetPropertyValue(floatProperty.RegisterNo, floatProperty, decodeUseBytes);
break; break;
} }
@ -112,7 +112,7 @@ public static class ModbusDecoder
return t; return t;
} }
private static void SetPropertyValue<T>(int startRegisterNo, ModbusProperty<T> field, byte[] bytes) private static void SetPropertyValue<T>(int startRegisterNo, ModbusProperty<T> field, byte[] bytes, bool unSign = true)
{ {
var registerNo = field.RegisterNo; var registerNo = field.RegisterNo;
var start = field.Start; var start = field.Start;
@ -134,7 +134,7 @@ public static class ModbusDecoder
_ => length _ => length
}; };
var value = BitUtls.Bytes2Value(bytes, valueType, start, length, scale, round, offset); var value = BitUtls.Bytes2Value(bytes, valueType, start, length, scale, round, offset, unSign);
field.Value = (T)value; field.Value = (T)value;
} }
} }

@ -12,7 +12,7 @@ public class ModbusTcpMaster
private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusTcpMaster)); private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusTcpMaster));
private ModbusTcpNet ModbusTcpNet; private ModbusTcpNet? ModbusTcpNet;
public string Ip { get; set; } = "127.0.0.1"; public string Ip { get; set; } = "127.0.0.1";
@ -23,6 +23,11 @@ public class ModbusTcpMaster
public int Duration { get; set; } = 1000; public int Duration { get; set; } = 1000;
public bool Connected { get; set; } public bool Connected { get; set; }
/// <summary>
/// 自动重连开关
/// </summary>
public bool AutoReConnect { get; set; }
public string connectId { get; set; } public string connectId { get; set; }
public MyReadAction? ReadAction { get; set; } public MyReadAction? ReadAction { get; set; }
@ -36,8 +41,8 @@ public class ModbusTcpMaster
public bool Connect() public bool Connect()
{ {
Thread.Sleep(Duration);
GetLog().Info($"begin to connect {Ip}:{Port}"); GetLog().Info($"begin to connect {Ip}:{Port}");
try try
{ {
if (ModbusTcpNet == null) if (ModbusTcpNet == null)
@ -55,12 +60,20 @@ public class ModbusTcpMaster
else else
{ {
GetLog().Info($"connect {Ip}:{Port} failed {result.Message}"); GetLog().Info($"connect {Ip}:{Port} failed {result.Message}");
if (AutoReConnect)
{
return Connect();
}
} }
} }
} }
catch (Exception e) catch (Exception e)
{ {
GetLog().Error($"connect {Ip}:{Port} exception {e.Message}"); GetLog().Error($"connect {Ip}:{Port} exception {e.Message}");
if (AutoReConnect)
{
return Connect();
}
} }
return Connected; return Connected;
@ -112,7 +125,7 @@ public class ModbusTcpMaster
return null; return null;
} }
public byte[]? BatchRead(int registerNo, int length) public byte[]? BatchReadHolderRegister(int registerNo, int length)
{ {
OperateResult<byte[]> result = ModbusTcpNet.Read("x=3;" + registerNo, (ushort)length); OperateResult<byte[]> result = ModbusTcpNet.Read("x=3;" + registerNo, (ushort)length);
if (result.IsSuccess) return result.Content; if (result.IsSuccess) return result.Content;
@ -120,6 +133,58 @@ public class ModbusTcpMaster
return null; return null;
} }
public byte[]? BatchReadInputRegister(int registerNo, int length)
{
OperateResult<byte[]> result = ModbusTcpNet.Read("x=4;" + registerNo, (ushort)length);
if (result.IsSuccess) return result.Content;
return null;
}
/// <summary>
/// 读取线圈,需要指定起始地址,如果富文本地址不指定,默认使用的功能码是 0x01<br />
/// To read the coil, you need to specify the start address. If the rich text address is not specified, the default function code is 0x01.
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <returns>带有成功标志的bool对象</returns>
public OperateResult<bool> ReadCoil(string address) => ModbusTcpNet.ReadBool(address);
/// <summary>
/// 批量的读取线圈,需要指定起始地址,读取长度,如果富文本地址不指定,默认使用的功能码是 0x01<br />
/// For batch reading coils, you need to specify the start address and read length. If the rich text address is not specified, the default function code is 0x01.
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <param name="length">读取长度</param>
/// <returns>带有成功标志的bool数组对象</returns>
public OperateResult<bool[]> ReadCoil(string address, ushort length)
{
return ModbusTcpNet.ReadBool(address, length);
}
/// <summary>
/// 读取输入线圈,需要指定起始地址,如果富文本地址不指定,默认使用的功能码是 0x02<br />
/// To read the input coil, you need to specify the start address. If the rich text address is not specified, the default function code is 0x02.
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <returns>带有成功标志的bool对象</returns>
public OperateResult<bool> ReadDiscrete(string address)
{
return ModbusTcpNet.ReadDiscrete(address);
}
/// <summary>
/// 批量的读取输入点,需要指定起始地址,读取长度,如果富文本地址不指定,默认使用的功能码是 0x02<br />
/// To read input points in batches, you need to specify the start address and read length. If the rich text address is not specified, the default function code is 0x02
/// </summary>
/// <param name="address">起始地址,格式为"1234"</param>
/// <param name="length">读取长度</param>
/// <returns>带有成功标志的bool数组对象</returns>
public OperateResult<bool[]> ReadDiscrete(string address, ushort length)
{
return ModbusTcpNet.ReadDiscrete(address, length);
}
public bool WriteValue<T>(ModbusProperty<T> property) public bool WriteValue<T>(ModbusProperty<T> property)
{ {
var value = property.Value; var value = property.Value;

@ -30,6 +30,6 @@ public class ModbusSession
public byte[]? Read(int registerNo, int length) public byte[]? Read(int registerNo, int length)
{ {
return ModbusTcpMaster.BatchRead(registerNo, length); return ModbusTcpMaster.BatchReadHolderRegister(registerNo, length);
} }
} }

@ -1,4 +1,5 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using DotNetty.Buffers;
using DotNetty.Transport.Channels; using DotNetty.Transport.Channels;
using log4net; using log4net;
@ -16,10 +17,17 @@ public class SessionMgr
public static IoSession? GetSession(string key) public static IoSession? GetSession(string key)
{ {
Dictionary.TryGetValue(key, out IoSession? value); if (Dictionary.ContainsKey(key))
{
IoSession? value;
Dictionary.TryGetValue(key, out value);
return value; return value;
} }
return null;
}
public static List<IoSession> GetSessionList() public static List<IoSession> GetSessionList()
{ {
return Dictionary.Values.ToList(); return Dictionary.Values.ToList();

@ -1,3 +1,4 @@
using System.Net;
using System.Reflection; using System.Reflection;
using Autofac; using Autofac;
using Autofac.Core; using Autofac.Core;
@ -138,7 +139,7 @@ public class TcpClient<TH, TD, TE> : IDisposable where TH : IChannelHandler
{ {
try try
{ {
Task<IChannel> task = _bootstrap!.ConnectAsync(Host, Port); Task<IChannel> task = _bootstrap!.ConnectAsync(new IPEndPoint(IPAddress.Parse(Host), Port));
Channel = task.Result; Channel = task.Result;
Connected = Channel.Open; Connected = Channel.Open;
} }

Loading…
Cancel
Save