云平台默认不等待返回 modbus修改大小端处理方案

master
smartwyy 6 months ago
parent 28dfb76bc3
commit 55ef020fcf

@ -11,6 +11,8 @@
<ProjectReference Include="..\HybirdFrameworkCore\HybirdFrameworkCore.csproj"/>
<ProjectReference Include="..\HybirdFrameworkDriver\HybirdFrameworkDriver.csproj"/>
<ProjectReference Include="..\Entity\Entity.csproj"/>
<ProjectReference Include="..\Repository\Repository.csproj" />
<ProjectReference Include="..\Service\Service.csproj" />
</ItemGroup>
<ItemGroup>

@ -0,0 +1,39 @@
namespace HybirdFrameworkCore.Const;
/// <summary>
/// 大小端常量c#默认小端 DCBA
/// </summary>
public class EndingConst
{
/// <summary>
/// 字节序,C# 默认BA
/// </summary>
public enum ByteSeq
{
/// <summary>
///
/// </summary>
AB,
/// <summary>
///
/// </summary>
BA
}
/// <summary>
/// 字序 c# 默认DC
/// </summary>
public enum WordSeq
{
/// <summary>
///
/// </summary>
CD,
/// <summary>
///
/// </summary>
DC
}
}

@ -1,4 +1,5 @@
using System.Text;
using HybirdFrameworkCore.Const;
namespace HybirdFrameworkCore.Utils;
@ -130,6 +131,65 @@ public static class BitUtls
#region Func
/// <summary>
/// 按字节序反序
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static byte[] ReverseByteSeq(byte[] bytes)
{
byte[] result = new byte [bytes.Length];
for (int i = 0, count = bytes.Length - 1; i < count; i += 2)
{
result[i] = bytes[i + 1];
result[i + 1] = bytes[i];
}
return result;
}
/// <summary>
/// 按字序反序
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static byte[] ReverseWordSeq(byte[] bytes)
{
byte[] result = new byte [bytes.Length];
for (int i = 0, count = bytes.Length - 3; i < count; i += 4)
{
result[i] = bytes[i + 2];
result[i + 1] = bytes[i+3];
result[i + 2] = bytes[i];
result[i + 3] = bytes[i+1];
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
/// <param name="byteSeq"></param>
/// <param name="wordSeq"></param>
/// <returns></returns>
public static byte[] ProcessEnding(byte[] bytes, EndingConst.ByteSeq byteSeq, EndingConst.WordSeq wordSeq)
{
if (byteSeq == EndingConst.ByteSeq.BA)
{
bytes = ReverseByteSeq(bytes);
}
if (wordSeq == EndingConst.WordSeq.DC)
{
bytes = ReverseWordSeq(bytes);
}
return bytes;
}
public static string Bytes2BinaryString(byte[] bytes)
{
return string.Join(" ", bytes.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')));

@ -73,10 +73,6 @@ public class MsgPair<TReq, TResp>
{
_lock.WaitOne(timeSpan.Value);
}
else
{
_lock.WaitOne();
}
return _resp;
}

@ -1,20 +1,25 @@
using HslCommunication.Core;
using HybirdFrameworkCore.Const;
using HybirdFrameworkCore.Utils;
using HybirdFrameworkDriver.Common;
using log4net;
namespace HybirdFrameworkDriver.ModbusTcpMaster;
/// <summary>
///
/// </summary>
public static class ModbusDecoder
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusDecoder));
public static T Decode<T>(byte[] bytes) where T : class, new()
{
T t = new T();
return Decode<T>(bytes, t);
}
public static T Decode<T>(byte[] bytes, T t) where T : class, new()
public static T Decode<T>(byte[] bytes, T t, EndingConst.ByteSeq byteSeq = EndingConst.ByteSeq.AB, EndingConst.WordSeq wordSeq = EndingConst.WordSeq.CD) where T : class, new()
{
var fields = t.GetType().GetProperties()
.Where(it => it.PropertyType.GetGenericTypeDefinition() == typeof(ModbusProperty<>))
@ -29,19 +34,15 @@ public static class ModbusDecoder
}
var decodeUseBytes = new byte[bytes.Length];
switch (ModbusTcpMaster.DataFormat)
if (byteSeq == EndingConst.ByteSeq.AB)
{
case DataFormat.ABCD:
for (var i = 0; i < bytes.Length; i++)
if (i % 2 == 0)
decodeUseBytes[i + 1] = bytes[i];
else
decodeUseBytes[i - 1] = bytes[i];
decodeUseBytes = BitUtls.ReverseByteSeq(bytes);
}
break;
case DataFormat.BADC:
decodeUseBytes = bytes;
break;
if (wordSeq == EndingConst.WordSeq.CD)
{
decodeUseBytes = BitUtls.ReverseWordSeq(bytes);
}
foreach (var field in fields)
@ -112,7 +113,8 @@ public static class ModbusDecoder
return t;
}
private static void SetPropertyValue<T>(int startRegisterNo, ModbusProperty<T> field, byte[] bytes, bool unSign = true)
private static void SetPropertyValue<T>(int startRegisterNo, ModbusProperty<T> field, byte[] bytes,
bool unSign = true)
{
var registerNo = field.RegisterNo;
var start = field.Start;

@ -1,5 +1,9 @@
namespace HybirdFrameworkDriver.ModbusTcpMaster;
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
public class ModbusProperty<T> : IModbusProperty
{
/// <summary>

@ -1,6 +1,6 @@
using HslCommunication;
using HslCommunication.Core;
using HslCommunication.ModBus;
using HybirdFrameworkCore.Const;
using HybirdFrameworkCore.Utils;
using log4net;
@ -18,7 +18,15 @@ public class ModbusTcpMaster
public int Port { get; set; } = 502;
public static DataFormat DataFormat { get; set; } = DataFormat.ABCD;
/// <summary>
/// 字节序
/// </summary>
public EndingConst.ByteSeq ByteSeq { get; set; } = EndingConst.ByteSeq.AB;
/// <summary>
/// 字序
/// </summary>
public EndingConst.WordSeq WordSeq { get; set; } = EndingConst.WordSeq.CD;
public int Duration { get; set; } = 1000;
public bool Connected { get; set; }
@ -48,7 +56,6 @@ public class ModbusTcpMaster
if (ModbusTcpNet == null)
{
ModbusTcpNet = new ModbusTcpNet(Ip, Port);
ModbusTcpNet.DataFormat = DataFormat;
var result = ModbusTcpNet.ConnectServer();
connectId = ModbusTcpNet.ConnectionId;
if (result.IsSuccess)
@ -231,14 +238,13 @@ public class ModbusTcpMaster
OperateResult<byte[]> readResultRegister = ModbusTcpNet.Read("x=3;" + registerNo, 1);
if (readResultRegister.IsSuccess)
{
switch (DataFormat)
if (ByteSeq == EndingConst.ByteSeq.AB)
{
readResultRegister.Content[1] = setValue[0];
}
else
{
case DataFormat.ABCD:
readResultRegister.Content[1] = setValue[0];
break;
case DataFormat.BADC:
readResultRegister.Content[0] = setValue[0];
break;
readResultRegister.Content[0] = setValue[0];
}
operateResult = ModbusTcpNet.Write("x=16;" + registerNo, readResultRegister.Content);
@ -248,22 +254,7 @@ public class ModbusTcpMaster
//其他类型 String 占用几个寄存器 直接补0
else
{
var preWriteCont = new byte[length * 2];
switch (DataFormat)
{
case DataFormat.ABCD:
for (var i = 0; i < setValue.Length; i++)
if (i % 2 == 0)
preWriteCont[i + 1] = setValue[i];
else
preWriteCont[i - 1] = setValue[i];
break;
case DataFormat.BADC:
Array.Copy(setValue, preWriteCont, setValue.Length);
break;
}
var preWriteCont = BitUtls.ProcessEnding(setValue, ByteSeq, WordSeq);
operateResult = ModbusTcpNet.Write("x=16;" + registerNo, preWriteCont);
result = operateResult.IsSuccess;
@ -271,23 +262,7 @@ public class ModbusTcpMaster
}
else if (setValue.Length == length * 2)
{
var preWriteCont = new byte[setValue.Length];
switch (DataFormat)
{
case DataFormat.ABCD:
for (var i = 0; i < setValue.Length; i++)
if (i % 2 == 0)
preWriteCont[i + 1] = setValue[i];
else
preWriteCont[i - 1] = setValue[i];
break;
case DataFormat.BADC:
//Array.Copy(setValue, preWriteCont, setValue.Length);
break;
}
var preWriteCont = BitUtls.ProcessEnding(setValue, ByteSeq, WordSeq);
operateResult = ModbusTcpNet.Write("x=16;" + registerNo, preWriteCont);
result = operateResult.IsSuccess;
}

@ -35,7 +35,7 @@ public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
public Action? ChannelInActiveAction { get; set; }
public TcpServer()
public void InitBootstrap()
{
if (LogLevel != null)
@ -131,6 +131,7 @@ public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
{
_port = port;
Log.Info(" Start Listen");
InitBootstrap();
Task<IChannel>? channel = bootstrap?.BindAsync(_port);
Log.Info($"netty success listen {_port}");
}

@ -1,6 +1,7 @@
using System.Text;
using Autofac;
using Autofac.Core;
using Common.Util;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
using HybirdFrameworkDriver.Common;
@ -15,13 +16,13 @@ using MQTTnet.Client.Receiving;
using MQTTnet.Formatter;
using MQTTnet.Protocol;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Service.Cloud.Handler;
using Service.Cloud.Msg;
using Service.Cloud.Msg.Cloud.Req;
using Service.Cloud.Msg.Cloud.Resp;
using Service.Cloud.Msg.Host.Req;
using Service.Init;
namespace Service.Cloud.Client;
@ -38,7 +39,7 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
public string ClientId { get; set; }
public string? Username { get; set; }
public string? Password { get; set; }
public int KeepalivePeriod { get; set; } = 30;
public int KeepalivePeriod { get; set; } = 3000;
public int Timeout { get; set; } = 60;
public string Version { get; set; } = "5.0.16";
public bool IsCleanSession { get; set; } = false;
@ -191,7 +192,15 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs)
{
await DoSubTopic(SubTopic);
Publish(new SignIn());
SendSignIn(new SignIn()
{
sn = StaticStationInfo.StationNo,
st = "01",
ss = StaticStationInfo.StationStatus,
en = 1,
cn = 7
});
}
private async Task DoSubTopic(string topic)
@ -223,18 +232,24 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
chipherFlag = Encrypt,
id = GetIncrementId(),
sid = StationNo,
timeStamp = DateTime.Now.Millisecond
timeStamp = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000
},
body = data
};
model.dataSign = SignData(model);
var settings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateFormatString = "yyyy-MM-dd HH:mm:ss",
NullValueHandling = NullValueHandling.Ignore
};
var appMsg = new MqttApplicationMessage
{
Topic = PubTopic,
Payload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(model)),
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
Payload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(model, settings)),
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
Retain = false
};
@ -242,16 +257,20 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
var result = task.Result;
if (result.ReasonCode == MqttClientPublishReasonCode.Success)
{
Log.Info($"send {JsonConvert.SerializeObject(model)} success");
Log.Info($"send {JsonConvert.SerializeObject(model, settings)} success");
}
}
private string SignData<T>(Model<T> model) where T : ICmd
{
IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
timeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
string body = JsonConvert.SerializeObject(model.body, timeConverter);
return body + ":" + model.Header.timeStamp + ":" + model.Header.id;
var settings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateFormatString = "yyyy-MM-dd HH:mm:ss",
NullValueHandling = NullValueHandling.Ignore
};
string body = JsonConvert.SerializeObject(model.body, settings);
return MD5Util.MD5Encrypt32(body + ":" + model.Header.timeStamp + ":" + model.Header.id).ToLower();
}
/// <summary>
@ -310,10 +329,6 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
{
Log.Info("cloud disconnect");
Connected = false;
if (AutoReConnect)
{
return Task.Run(Connect);
}
return Task.CompletedTask;
}
@ -358,7 +373,7 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
#region 主动发送CMD
public VehicleCertificationResp? SendVehicleCertification(VehicleCertification vehicleCertification,
TimeSpan timeSpan)
TimeSpan? timeSpan = null)
{
Log.Info(vehicleCertification);
this.CarAuth.Req = vehicleCertification;
@ -421,8 +436,8 @@ public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageR
this.Publish(reportingDeviceList);
return ReportingDevice.GetResp(timeSpan);
}
public SignInResp? SendReportingDeviceList(SignIn signIn,
TimeSpan timeSpan)
public SignInResp? SendSignIn(SignIn signIn,
TimeSpan? timeSpan=null)
{
this.Sign.Req = signIn;
this.Publish(signIn);

@ -28,6 +28,6 @@ public class CloudClientMgr
CloudClient.InitHandler();
//Task.Run(() => CloudClient.Connect());
Task.Run(() => CloudClient.Connect());
}
}
Loading…
Cancel
Save