同步框架

master
smartwyy 6 months ago
parent 25ee45142e
commit a8a8e4fc02

@ -15,10 +15,11 @@ public static class BitUtls
/// <param name="scale">精度</param>
/// <param name="round">保留几位小数</param>
/// <param name="offset">位偏移</param>
/// <param name="unSign">对float和double 默认无符号</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
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);
@ -44,17 +45,16 @@ public static class BitUtls
if (propertyType == FLOAT)
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)
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);
if (propertyType == STRING)
{
return Convert.ChangeType(Encoding.ASCII.GetString(bytes, start, length), propertyType);
return Convert.ChangeType(Encoding.ASCII.GetString(bytes, start, length/8), propertyType);
}
if (propertyType == BYTEARRAY)
@ -221,23 +221,23 @@ public static class BitUtls
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)
{
int d = Byte2Int16(bytes, startBit, length);
int d =unSign ? Byte2UInt16(bytes, startBit, length) : Byte2Int16(bytes, startBit, length);
return (float)(d * factor);
}
else
{
var d = Byte2Int32(bytes, startBit, length);
Int64 d = unSign ? Byte2UInt32(bytes, startBit, length) : Byte2Int32(bytes, startBit, length) ;
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);
}

@ -91,7 +91,7 @@ public static class ModbusDecoder
}
case ModbusProperty<float> floatProperty:
{
SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes);
SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes, true);
// SetPropertyValue(floatProperty.RegisterNo, floatProperty, decodeUseBytes);
break;
}
@ -112,7 +112,7 @@ public static class ModbusDecoder
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 start = field.Start;
@ -134,7 +134,7 @@ public static class ModbusDecoder
_ => 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;
}
}

@ -12,7 +12,7 @@ public class 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";
@ -23,6 +23,11 @@ public class ModbusTcpMaster
public int Duration { get; set; } = 1000;
public bool Connected { get; set; }
/// <summary>
/// 自动重连开关
/// </summary>
public bool AutoReConnect { get; set; }
public string connectId { get; set; }
public MyReadAction? ReadAction { get; set; }
@ -36,8 +41,8 @@ public class ModbusTcpMaster
public bool Connect()
{
Thread.Sleep(Duration);
GetLog().Info($"begin to connect {Ip}:{Port}");
try
{
if (ModbusTcpNet == null)
@ -55,12 +60,20 @@ public class ModbusTcpMaster
else
{
GetLog().Info($"connect {Ip}:{Port} failed {result.Message}");
if (AutoReConnect)
{
return Connect();
}
}
}
}
catch (Exception e)
{
GetLog().Error($"connect {Ip}:{Port} exception {e.Message}");
if (AutoReConnect)
{
return Connect();
}
}
return Connected;
@ -112,7 +125,7 @@ public class ModbusTcpMaster
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);
if (result.IsSuccess) return result.Content;
@ -120,6 +133,58 @@ public class ModbusTcpMaster
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)
{
var value = property.Value;

@ -30,6 +30,6 @@ public class ModbusSession
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 DotNetty.Buffers;
using DotNetty.Transport.Channels;
using log4net;
@ -16,10 +17,17 @@ public class SessionMgr
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 null;
}
public static List<IoSession> GetSessionList()
{
return Dictionary.Values.ToList();

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

Loading…
Cancel
Save