diff --git a/JiShe.CollectBus.sln b/JiShe.CollectBus.sln index 6bc2bee..c3ad8a0 100644 --- a/JiShe.CollectBus.sln +++ b/JiShe.CollectBus.sln @@ -19,10 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Host", "we EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Common", "shared\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj", "{AD2F1928-4411-4511-B564-5FB996EC08B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Protocol", "protocols\JiShe.CollectBus.Protocol\JiShe.CollectBus.Protocol.csproj", "{C62EFF95-5C32-435F-BD78-6977E828F894}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Protocol.Contracts", "protocols\JiShe.CollectBus.Protocol.Contracts\JiShe.CollectBus.Protocol.Contracts.csproj", "{38C1808B-009A-418B-B17B-AB3626341B5D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.DbMigrator", "services\JiShe.CollectBus.DbMigrator\JiShe.CollectBus.DbMigrator.csproj", "{8BA01C3D-297D-42DF-BD63-EF07202A0A67}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.FreeSql", "modules\JiShe.CollectBus.FreeSql\JiShe.CollectBus.FreeSql.csproj", "{FE0457D9-4038-4A17-8808-DCAD06CFC0A0}" @@ -49,10 +45,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5.Shared", "5.Shared", "{EB EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Kafka.Test", "modules\JiShe.CollectBus.Kafka.Test\JiShe.CollectBus.Kafka.Test.csproj", "{6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "6.External", "6.External", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "6", "6", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.PluginFileWatcher", "external\JiShe.CollectBus.PluginFileWatcher\JiShe.CollectBus.PluginFileWatcher.csproj", "{F767D1C3-6807-4AE3-996A-3A28FE8124C2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T1882018", "protocols\JiShe.CollectBus.Protocol.T1882018\JiShe.CollectBus.Protocol.T1882018.csproj", "{430D298B-377E-49B8-83AA-ADC7C0EBDB0F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T37612012", "protocols\JiShe.CollectBus.Protocol.T37612012\JiShe.CollectBus.Protocol.T37612012.csproj", "{8A61DF78-069B-40B5-8811-614E2960443E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol", "protocols\JiShe.CollectBus.Protocol\JiShe.CollectBus.Protocol.csproj", "{E27377CC-E2D3-4237-060F-96EA214D3129}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.T6452007", "protocols\JiShe.CollectBus.Protocol.T6452007\JiShe.CollectBus.Protocol.T6452007.csproj", "{75B7D419-C261-577D-58D6-AA3ACED9129F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -91,14 +95,6 @@ Global {AD2F1928-4411-4511-B564-5FB996EC08B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD2F1928-4411-4511-B564-5FB996EC08B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD2F1928-4411-4511-B564-5FB996EC08B9}.Release|Any CPU.Build.0 = Release|Any CPU - {C62EFF95-5C32-435F-BD78-6977E828F894}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C62EFF95-5C32-435F-BD78-6977E828F894}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C62EFF95-5C32-435F-BD78-6977E828F894}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C62EFF95-5C32-435F-BD78-6977E828F894}.Release|Any CPU.Build.0 = Release|Any CPU - {38C1808B-009A-418B-B17B-AB3626341B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {38C1808B-009A-418B-B17B-AB3626341B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {38C1808B-009A-418B-B17B-AB3626341B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {38C1808B-009A-418B-B17B-AB3626341B5D}.Release|Any CPU.Build.0 = Release|Any CPU {8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Debug|Any CPU.Build.0 = Debug|Any CPU {8BA01C3D-297D-42DF-BD63-EF07202A0A67}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -135,6 +131,22 @@ Global {F767D1C3-6807-4AE3-996A-3A28FE8124C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {F767D1C3-6807-4AE3-996A-3A28FE8124C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {F767D1C3-6807-4AE3-996A-3A28FE8124C2}.Release|Any CPU.Build.0 = Release|Any CPU + {430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {430D298B-377E-49B8-83AA-ADC7C0EBDB0F}.Release|Any CPU.Build.0 = Release|Any CPU + {8A61DF78-069B-40B5-8811-614E2960443E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A61DF78-069B-40B5-8811-614E2960443E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A61DF78-069B-40B5-8811-614E2960443E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A61DF78-069B-40B5-8811-614E2960443E}.Release|Any CPU.Build.0 = Release|Any CPU + {E27377CC-E2D3-4237-060F-96EA214D3129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E27377CC-E2D3-4237-060F-96EA214D3129}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E27377CC-E2D3-4237-060F-96EA214D3129}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E27377CC-E2D3-4237-060F-96EA214D3129}.Release|Any CPU.Build.0 = Release|Any CPU + {75B7D419-C261-577D-58D6-AA3ACED9129F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75B7D419-C261-577D-58D6-AA3ACED9129F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -148,8 +160,6 @@ Global {077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94} {35829A15-4127-4F69-8BDE-9405DEAACA9A} = {A02F7D8A-04DC-44D6-94D4-3F65712D6B94} {AD2F1928-4411-4511-B564-5FB996EC08B9} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B} - {C62EFF95-5C32-435F-BD78-6977E828F894} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} - {38C1808B-009A-418B-B17B-AB3626341B5D} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} {8BA01C3D-297D-42DF-BD63-EF07202A0A67} = {BA4DA3E7-9AD0-47AD-A0E6-A0BB6700DA23} {FE0457D9-4038-4A17-8808-DCAD06CFC0A0} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59} {C06C4082-638F-2996-5FED-7784475766C1} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59} @@ -159,6 +169,10 @@ Global {443B4549-0AC0-4493-8F3E-49C83225DD76} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59} {6D6A2A58-7406-9C8C-7B23-3E442CCE3E6B} = {2E0FE301-34C3-4561-9CAE-C7A9E65AEE59} {F767D1C3-6807-4AE3-996A-3A28FE8124C2} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {430D298B-377E-49B8-83AA-ADC7C0EBDB0F} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} + {8A61DF78-069B-40B5-8811-614E2960443E} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} + {E27377CC-E2D3-4237-060F-96EA214D3129} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} + {75B7D419-C261-577D-58D6-AA3ACED9129F} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/JiShe.CollectBus.Protocol.Contracts.csproj b/protocols/JiShe.CollectBus.Protocol.Contracts/JiShe.CollectBus.Protocol.Contracts.csproj deleted file mode 100644 index 495dbf1..0000000 --- a/protocols/JiShe.CollectBus.Protocol.Contracts/JiShe.CollectBus.Protocol.Contracts.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - - - - - - - - - - - diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/CJT 188-2018 户用计量仪表数据传输技术条件.pdf b/protocols/JiShe.CollectBus.Protocol.T1882018/CJT 188-2018 户用计量仪表数据传输技术条件.pdf new file mode 100644 index 0000000..ce3fb6a Binary files /dev/null and b/protocols/JiShe.CollectBus.Protocol.T1882018/CJT 188-2018 户用计量仪表数据传输技术条件.pdf differ diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj b/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj new file mode 100644 index 0000000..4866985 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/JiShe.CollectBus.Protocol.T1882018.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + diff --git a/protocols/JiShe.CollectBus.Protocol/JiSheCollectBusProtocolModule.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/JiSheCollectBusProtocolT1882018Module.cs similarity index 96% rename from protocols/JiShe.CollectBus.Protocol/JiSheCollectBusProtocolModule.cs rename to protocols/JiShe.CollectBus.Protocol.T1882018/JiSheCollectBusProtocolT1882018Module.cs index 6b08805..6cb202a 100644 --- a/protocols/JiShe.CollectBus.Protocol/JiSheCollectBusProtocolModule.cs +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/JiSheCollectBusProtocolT1882018Module.cs @@ -16,11 +16,11 @@ using Volo.Abp.Modularity; namespace JiShe.CollectBus.Protocol { - public class JiSheCollectBusProtocolModule : AbpModule + public class JiSheCollectBusProtocolT1882018Module : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddKeyedSingleton(nameof(StandardProtocolPlugin)); + context.Services.AddKeyedSingleton(nameof(T1882018ProtocolPlugin)); //RegisterProtocolAnalysis(context.Services); LoadAnalysisStrategy(context.Services); } @@ -28,7 +28,7 @@ namespace JiShe.CollectBus.Protocol public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) { Console.WriteLine("StandardProtocolPlugin OnApplicationInitializationAsync"); - var standardProtocol = context.ServiceProvider.GetRequiredKeyedService(nameof(StandardProtocolPlugin)); + var standardProtocol = context.ServiceProvider.GetRequiredKeyedService(nameof(T1882018ProtocolPlugin)); await standardProtocol.LoadAsync(); } diff --git a/protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketBuilder.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs similarity index 77% rename from protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketBuilder.cs rename to protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs index a7faf67..e5dabab 100644 --- a/protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketBuilder.cs +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketBuilder.cs @@ -10,30 +10,30 @@ namespace JiShe.CollectBus.Protocol.SendData /// /// 构建645-2007下发报文 /// - public static class Telemetry645PacketBuilder + public static class Telemetry1882018PacketBuilder { /// /// 构建报文的委托 /// /// /// - public delegate Telemetry645PacketResponse T645Delegate(Telemetry645PacketRequest request); + public delegate Telemetry1882018PacketResponse T6452007Delegate(Telemetry1882018PacketRequest request); /// /// 编码与方法的映射表 /// - public static readonly Dictionary T645ControlHandlers = new(); + public static readonly Dictionary T645ControlHandlers = new(); - static Telemetry645PacketBuilder() + static Telemetry1882018PacketBuilder() { // 初始化时自动注册所有符合命名规则的方法 - var methods = typeof(Telemetry645PacketBuilder).GetMethods(BindingFlags.Static | BindingFlags.Public); + var methods = typeof(Telemetry1882018PacketBuilder).GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (var method in methods) { if (method.Name.StartsWith("C") && method.Name.EndsWith("_Send")) { string code = method.Name; - var delegateInstance = (T645Delegate)Delegate.CreateDelegate(typeof(T645Delegate), method); + var delegateInstance = (T6452007Delegate)Delegate.CreateDelegate(typeof(T6452007Delegate), method); T645ControlHandlers[code] = delegateInstance; } } @@ -46,7 +46,7 @@ namespace JiShe.CollectBus.Protocol.SendData /// /// /// - public static Telemetry645PacketResponse C1C_01_Send(Telemetry645PacketRequest request) + public static Telemetry1882018PacketResponse C1C_01_Send(Telemetry1882018PacketRequest request) { var itemCodeArr = request.ItemCode.Split('_'); var c_data = itemCodeArr[0]; @@ -68,7 +68,7 @@ namespace JiShe.CollectBus.Protocol.SendData var dataUnit = strSJY.Replace(" ", "").StringToPairs(); var dataList = Build645SendData.Build645SendCommand(request.MeterAddress, c_data, dataUnit); - return new Telemetry645PacketResponse() { Data = dataList }; + return new Telemetry1882018PacketResponse() { Data = dataList }; } @@ -77,7 +77,7 @@ namespace JiShe.CollectBus.Protocol.SendData /// /// /// - public static Telemetry645PacketResponse C1C_03_Send(Telemetry645PacketRequest request) + public static Telemetry1882018PacketResponse C1C_03_Send(Telemetry1882018PacketRequest request) { var itemCodeArr = request.ItemCode.Split('_'); var c_data = itemCodeArr[0]; @@ -99,7 +99,7 @@ namespace JiShe.CollectBus.Protocol.SendData var dataUnit = strSJY.Replace(" ", "").StringToPairs(); var dataList = Build645SendData.Build645SendCommand(request.MeterAddress, c_data, dataUnit); - return new Telemetry645PacketResponse() { Data = dataList }; + return new Telemetry1882018PacketResponse() { Data = dataList }; } #endregion } diff --git a/protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketRequest.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketRequest.cs similarity index 91% rename from protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketRequest.cs rename to protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketRequest.cs index fd90322..ef51ea1 100644 --- a/protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketRequest.cs +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketRequest.cs @@ -3,7 +3,7 @@ /// /// 构建645报文参数 /// - public class Telemetry645PacketRequest + public class Telemetry1882018PacketRequest { /// /// 表地址 diff --git a/protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketResponse.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketResponse.cs similarity index 83% rename from protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketResponse.cs rename to protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketResponse.cs index 7731e0f..90e6e62 100644 --- a/protocols/JiShe.CollectBus.Protocol/SendData/Telemetry645PacketResponse.cs +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/SendData/Telemetry1882018PacketResponse.cs @@ -3,7 +3,7 @@ /// /// 返回645报文结果 /// - public class Telemetry645PacketResponse + public class Telemetry1882018PacketResponse { /// /// 报文体 diff --git a/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs new file mode 100644 index 0000000..3b392e2 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T1882018/T1882018ProtocolPlugin.cs @@ -0,0 +1,506 @@ +using JiShe.CollectBus.Common.BuildSendDatas; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.Common.Enums; +using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.Common.Helpers; +using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.Enums; +using JiShe.CollectBus.IotSystems.Devices; +using JiShe.CollectBus.IotSystems.MessageReceiveds; +using JiShe.CollectBus.IotSystems.Protocols; +using JiShe.CollectBus.Kafka.Producer; +using JiShe.CollectBus.Protocol.Contracts.Abstracts; +using JiShe.CollectBus.Protocol.Contracts.Models; +using JiShe.CollectBus.Protocol.Contracts.SendData; +using JiShe.CollectBus.Protocol.SendData; +using Mapster; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using TouchSocket.Sockets; +using Volo.Abp.Domain.Repositories; + +namespace JiShe.CollectBus.Protocol +{ + public class T1882018ProtocolPlugin : T37612012ProtocolPlugin + { + private readonly ILogger _logger; + + private readonly IProducerService _producerService; + + private readonly IRepository _deviceRepository; + private readonly ITcpService _tcpService; + + public readonly Dictionary T3761AFNHandlers; + public readonly Dictionary T645ControlHandlers; + + /// + /// Initializes a new instance of the class. + /// + /// The service provider. + public T1882018ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger, ITcpService tcpService) : base(serviceProvider, logger) + { + _logger = logger; + //_logger = serviceProvider.GetRequiredService>(); + _producerService = serviceProvider.GetRequiredService(); + _deviceRepository = serviceProvider.GetRequiredService>(); + _tcpService = tcpService; + T3761AFNHandlers = Telemetry3761PacketBuilder.T3761AFNHandlers; + T645ControlHandlers = Telemetry1882018PacketBuilder.T645ControlHandlers; + } + + public sealed override ProtocolInfo Info => new(nameof(T1882018ProtocolPlugin), "376.1", "TCP", "376.1协议", "DTS1980"); + + public override async Task AnalyzeAsync(ITcpSessionClient client, string messageReceived, Action? sendAction = null) + { + TB3761? tB3761 = Analysis3761(messageReceived); + if (tB3761 != null) + { + if (tB3761.AFN_FC?.AFN == (int)AFN.链路接口检测) + { + if (tB3761.A == null || tB3761.A.Code.IsNullOrWhiteSpace() || tB3761.A.A3?.D1_D7 == null || tB3761.SEQ?.PSEQ == null) + { + _logger.LogError($"解析AFN.链路接口检测报文失败,报文:{messageReceived},TB3761:{tB3761.Serialize()}"); + } + else + { + if (tB3761.DT?.Fn == (int)FN.登录) + { + // 登录回复 + if (tB3761.SEQ.CON == (int)CON.需要对该帧进行确认) + await LoginAsync(client, messageReceived, tB3761.A.Code, tB3761.A.A3?.D1_D7, tB3761.SEQ?.PSEQ); + } + else if (tB3761.DT?.Fn == (int)FN.心跳) + { + // 心跳回复 + //心跳帧有两种情况: + //1. 集中器先有登录帧,再有心跳帧 + //2. 集中器没有登录帧,只有心跳帧 + await HeartbeatAsync(client, messageReceived, tB3761.A.Code, tB3761.A.A3?.D1_D7, tB3761.SEQ?.PSEQ); + } + } + + } + await OnTcpNormalReceived(client, tB3761); + } + return (tB3761 as T)!; + } + + /// + /// 正常帧处理,将不同的AFN进行分发 + /// + /// + /// + /// + /// + private async Task OnTcpNormalReceived(ITcpSessionClient tcpSessionClient, TB3761 tB3761) + { + //string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, aFn); + //todo 如何确定时标?目前集中器的采集频率,都是固定,数据上报的时候,根据当前时间,往后推测出应当采集的时间点作为时标。但是如果由于网络问题,数据一直没上报的情况改怎么计算? + //await _producerBus.PublishAsync(ProtocolConst.SubscriberReceivedEventName, new MessageReceived + //{ + // ClientId = client.Id, + // ClientIp = client.IP, + // ClientPort = client.Port, + // MessageHexString = messageHexString, + // DeviceNo = deviceNo, + // MessageId = NewId.NextGuid().ToString() + //}); + + if (tB3761.AFN_FC.BaseHexMessage == null || tB3761.DT.BaseHexMessage == null || tB3761.BaseHexMessage.HexMessageString==null) + { + _logger.LogError("376.1协议解析AFN失败"); + return; + } + // 登录心跳已做了处理,故需要忽略登录和心跳帧 + if (tB3761.DT.Fn == (int)FN.登录 || tB3761.DT.Fn == (int)FN.心跳) + return; + //TODO:根据AFN进行分流推送到kafka + string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, tB3761.AFN_FC.AFN.ToString().PadLeft(2, '0')); + + MessageProtocolAnalysis messageReceivedAnalysis = new MessageProtocolAnalysis() + { + ClientId = tcpSessionClient.Id, + ClientIp = tcpSessionClient.IP, + ClientPort = tcpSessionClient.Port, + MessageHexString = tB3761.BaseHexMessage.HexMessageString!, + DeviceNo = tB3761.A.Code!, + MessageId = Guid.NewGuid().ToString(), + ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), + Data = tB3761 + }; + + List topics = ProtocolConstExtensions.GetAllTopicNamesByReceived(); + if (topics.Contains(topicName)) + await _producerService.ProduceAsync(topicName, messageReceivedAnalysis); + else + { + _logger.LogError($"不支持的上报kafka主题:{topicName}"); + await _producerService.ProduceAsync(ProtocolConst.SubscriberReceivedEventName, messageReceivedAnalysis); + } + + } + + + /// + /// 登录回复 + /// + /// + /// + /// + /// + /// + public async Task LoginAsync(ITcpSessionClient client, string messageReceived, string code, int? msa, int? pseq) + { + string oldClientId = $"{client.Id}"; + await client.ResetIdAsync(code); + var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); + if (deviceInfoList != null && deviceInfoList.Count > 1) + { + //todo 推送集中器编号重复预警 + _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); + return; + } + + var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); + if (entity == null) + { + await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); + } + else + { + entity.UpdateByLoginAndHeartbeat(oldClientId); + await _deviceRepository.UpdateAsync(entity); + } + + var messageReceivedLoginEvent = new MessageReceivedLogin + { + ClientId = code, + ClientIp = client.IP, + ClientPort = client.Port, + MessageHexString = messageReceived, + DeviceNo = code, + MessageId = Guid.NewGuid().ToString(), + ReceivedTime=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + }; + await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginReceivedEventName, messageReceivedLoginEvent); + var reqParam = new ReqParameter2 + { + AFN = AFN.确认或否认, + FunCode = (int)CFromStationFunCode.链路数据, + PRM = PRM.从动站报文, + A = code, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.需要对该帧进行确认, + PRSEQ = pseq!.Value + }, + MSA = msa!.Value, + Pn = 0, + Fn = 1 + }; + var bytes = Build3761SendData.BuildSendCommandBytes(reqParam); + var issuedEventMessage = new IssuedEventMessage + { + ClientId = messageReceivedLoginEvent.ClientId, + DeviceNo = messageReceivedLoginEvent.DeviceNo, + Message = bytes, + Type = IssuedEventType.Login, + MessageId = messageReceivedLoginEvent.MessageId + }; + if (_tcpService.ClientExists(issuedEventMessage.ClientId)) + { + await _tcpService.SendAsync(issuedEventMessage.ClientId, issuedEventMessage.Message); + _logger.LogInformation($"集中器地址{issuedEventMessage.ClientId} 登录回复下发内容:{Convert.ToHexString(bytes)}"); + await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginIssuedEventName, issuedEventMessage); + } + } + + /// + /// 心跳帧解析 + /// + /// + /// + /// + /// + /// + public async Task HeartbeatAsync(ITcpSessionClient client, string messageReceived, string code, int? msa, int? pseq) + { + + string clientId = code; + string oldClientId = $"{client.Id}"; + var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code); + if (deviceInfoList != null && deviceInfoList.Count > 1) + { + //todo 推送集中器编号重复预警 + _logger.LogError($"集中器编号:{code},存在多个集中器,请检查集中器编号是否重复"); + return; + } + + var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code); + if (entity == null) //没有登录帧的设备,只有心跳帧 + { + await client.ResetIdAsync(clientId); + await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online)); + } + else + { + if (clientId != oldClientId) + { + entity.UpdateByLoginAndHeartbeat(oldClientId); + } + else + { + entity.UpdateByLoginAndHeartbeat(); + } + + await _deviceRepository.UpdateAsync(entity); + } + + var messageReceivedHeartbeatEvent = new MessageReceivedHeartbeat + { + ClientId = clientId, + ClientIp = client.IP, + ClientPort = client.Port, + MessageHexString = messageReceived, + DeviceNo = code, + MessageId = Guid.NewGuid().ToString(), + ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + }; + await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatReceivedEventName, messageReceivedHeartbeatEvent); + + var reqParam = new ReqParameter2() + { + AFN = AFN.确认或否认, + FunCode = (int)CFromStationFunCode.链路数据, + PRM = PRM.从动站报文, + A = code, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.不需要对该帧进行确认, + PRSEQ = pseq!.Value, + }, + MSA = msa!.Value, + Pn = 0, + Fn = 1 + }; + var bytes = Build3761SendData.BuildSendCommandBytes(reqParam); + + IssuedEventMessage issuedEventMessage = new IssuedEventMessage + { + ClientId = messageReceivedHeartbeatEvent.ClientId, + DeviceNo = messageReceivedHeartbeatEvent.DeviceNo, + Message = bytes, + Type = IssuedEventType.Heartbeat, + MessageId = messageReceivedHeartbeatEvent.MessageId + }; + if (_tcpService.ClientExists(issuedEventMessage.ClientId)) + { + await _tcpService.SendAsync(issuedEventMessage.ClientId, bytes); + _logger.LogWarning($"集中器地址{issuedEventMessage.ClientId} 心跳回复下发内容:{Convert.ToHexString(bytes)}"); + await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatIssuedEventName, issuedEventMessage); + } + + + } + + + + /// + /// 组装报文 + /// + /// 报文构建参数 + /// + public override async Task BuildAsync(ProtocolBuildRequest request) + { + if (request == null) + { + throw new Exception($"{nameof(T1882018ProtocolPlugin)} 报文构建失败,参数为空"); + } + var itemCodeArr = request.ItemCode.Split('_'); + var aFNStr = itemCodeArr[0]; + var aFN = (AFN)aFNStr.HexToDec(); + var fn = int.Parse(itemCodeArr[1]); + Telemetry3761PacketResponse builderResponse = null; + + List dataUnit = new List(); + //数据转发场景 10H_F1_1CH + if (aFNStr == "10" && request.SubProtocolRequest != null && string.IsNullOrWhiteSpace(request.SubProtocolRequest.ItemCode) == false) + { + var t645PacketHandlerName = $"C{request.SubProtocolRequest.ItemCode}_Send"; + Telemetry1882018PacketResponse t645PacketResponse = null; + + if (T645ControlHandlers != null && T645ControlHandlers.TryGetValue(t645PacketHandlerName + , out var t645PacketHandler)) + { + t645PacketResponse = t645PacketHandler(new Telemetry1882018PacketRequest() + { + MeterAddress = request.SubProtocolRequest.MeterAddress, + Password = request.SubProtocolRequest.Password, + ItemCode = request.SubProtocolRequest.ItemCode, + }); + } + + if (t645PacketResponse != null) + { + dataUnit = t645PacketResponse.Data; + } + } + + string afnMethonCode = $"AFN{aFNStr}_Fn_Send"; + if (T3761AFNHandlers != null && T3761AFNHandlers.TryGetValue(afnMethonCode + , out var handler)) + { + builderResponse = handler(new Telemetry3761PacketRequest() + { + FocusAddress = request.FocusAddress, + Fn = fn, + Pn = request.Pn, + DataUnit = dataUnit, + }); + } + + if (builderResponse == null) + { + return new ProtocolBuildResponse(); + } + + var result = builderResponse.Adapt(); + result.IsSuccess = true; + + return await Task.FromResult(result); + } + + + #region 上行命令 + + //68 + //32 00 + //32 00 + //68 + //C9 1100'1001. 控制域C。 + // D7=1, (终端发送)上行方向。 + // D6=1, 此帧来自启动站。 + // D5=0, (上行方向)要求访问位。表示终端无事件数据等待访问。 + // D4=0, 保留 + // D3~D0=9, 功能码。链路测试 + + //20 32 行政区划码 + //90 26 终端地址 + //00 主站地址和组地址标志。终端为单地址。 //3220 09 87 2 + // 终端启动的发送帧的 MSA 应为 0, 其主站响应帧的 MSA 也应为 0. + //02 应用层功能码。AFN=2, 链路接口检测 + //70 0111'0000. 帧序列域。无时间标签、单帧、需要确认。 + //00 00 信息点。DA1和DA2全为“0”时,表示终端信息点。 + //01 00 信息类。F1, 登录。 + //44 帧尾,包含用户区数据校验和 + //16 帧结束标志 + + /// + /// 解析上行命令 + /// + /// + /// + public CommandReulst? AnalysisCmd(string cmd) + { + CommandReulst? commandReulst = null; + var hexStringList = cmd.StringToPairs(); + + if (hexStringList.Count < hearderLen) + { + return commandReulst; + } + //验证起始字符 + if (!hexStringList[0].IsStartStr() || !hexStringList[5].IsStartStr()) + { + return commandReulst; + } + + var lenHexStr = $"{hexStringList[2]}{hexStringList[1]}"; + var lenBin = lenHexStr.HexToBin(); + var len = lenBin.Remove(lenBin.Length - 2).BinToDec(); + //验证长度 + if (hexStringList.Count - 2 != hearderLen + len) + return commandReulst; + + var userDataIndex = hearderLen; + var c = hexStringList[userDataIndex];//控制域 1字节 + userDataIndex += 1; + + var aHexList = hexStringList.Skip(userDataIndex).Take(5).ToList();//地址域 5字节 + var a = AnalysisA(aHexList); + var a3Bin = aHexList[4].HexToBin().PadLeft(8, '0'); + var mSA = a3Bin.Substring(0, 7).BinToDec(); + userDataIndex += 5; + + var aFN = (AFN)hexStringList[userDataIndex].HexToDec();//1字节 + userDataIndex += 1; + + var seq = hexStringList[userDataIndex].HexToBin().PadLeft(8, '0'); + var tpV = (TpV)Convert.ToInt32(seq.Substring(0, 1)); + var fIRFIN = (FIRFIN)Convert.ToInt32(seq.Substring(1, 2)); + var cON = (CON)Convert.ToInt32(seq.Substring(3, 1)); + var prseqBin = seq.Substring(4, 4); + userDataIndex += 1; + + // (DA2 - 1) * 8 + DA1 = pn + var da1Bin = hexStringList[userDataIndex].HexToBin(); + var da1 = da1Bin == "0" ? 0 : da1Bin.Length; + userDataIndex += 1; + var da2 = hexStringList[userDataIndex].HexToDec(); + var pn = da2 == 0 ? 0 : (da2 - 1) * 8 + da1; + userDataIndex += 1; + //(DT2*8)+DT1=fn + var dt1Bin = hexStringList[userDataIndex].HexToBin(); + var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0; + userDataIndex += 1; + var dt2 = hexStringList[userDataIndex].HexToDec(); + var fn = dt2 * 8 + dt1; + userDataIndex += 1; + + //数据单元 + var datas = hexStringList.Skip(userDataIndex).Take(len + hearderLen - userDataIndex).ToList(); + + //EC + //Tp + commandReulst = new CommandReulst() + { + A = a, + MSA = mSA, + AFN = aFN, + Seq = new Seq() + { + TpV = tpV, + FIRFIN = fIRFIN, + CON = cON, + PRSEQ = prseqBin.BinToDec(), + }, + CmdLength = len, + Pn = pn, + Fn = fn, + HexDatas = datas + }; + + return commandReulst; + } + + /// + /// 解析地址 + /// + /// + /// + private string AnalysisA(List aHexList) + { + var a1 = aHexList[1] + aHexList[0]; + var a2 = aHexList[3] + aHexList[2]; + var a2Dec = a2.HexToDec(); + var a3 = aHexList[4]; + var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}"; + return a; + } + #endregion + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin_bak.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Abstracts/BaseProtocolPlugin_bak.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin_bak.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Abstracts/BaseProtocolPlugin_bak.cs diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/Abstracts/T37612012ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Abstracts/T37612012ProtocolPlugin.cs new file mode 100644 index 0000000..772ab4e --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/Abstracts/T37612012ProtocolPlugin.cs @@ -0,0 +1,405 @@ +using JiShe.CollectBus.Common.BuildSendDatas; +using JiShe.CollectBus.Common.Enums; +using System; +using System.Reflection; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.FreeRedis; +using JiShe.CollectBus.IotSystems.Protocols; +using JiShe.CollectBus.Protocol.Contracts.Interfaces; +using JiShe.CollectBus.Protocol.Contracts.Models; +using JiShe.CollectBus.Protocol.Contracts.SendData; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using TouchSocket.Sockets; +using Volo.Abp.Domain.Repositories; + +namespace JiShe.CollectBus.Protocol.Contracts.Abstracts +{ + public abstract class T37612012ProtocolPlugin : IProtocolPlugin + { + //头部字节长度 + public const int hearderLen = 6; + + public const int tPLen = 6; + + public const string errorData = "EE"; + + private readonly ILogger _logger; + private readonly IRepository _protocolInfoRepository; + private readonly IFreeRedisProvider _redisProvider; + + public T37612012ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger) + { + _logger = logger; + _protocolInfoRepository = serviceProvider.GetRequiredService>(); + _redisProvider = serviceProvider.GetRequiredService(); + } + + + public abstract ProtocolInfo Info { get; } + + public virtual async Task GetAsync() => await Task.FromResult(Info); + + public virtual async Task LoadAsync() + { + if (Info == null) + { + throw new ArgumentNullException(nameof(Info)); + } + + await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name); + await _protocolInfoRepository.InsertAsync(Info); + await _redisProvider.Instance.HDelAsync($"{RedisConst.ProtocolKey}", Info.Name); + await _redisProvider.Instance.HSetAsync($"{RedisConst.ProtocolKey}", Info.Name, Info); + } + + public abstract Task AnalyzeAsync(ITcpSessionClient client, string messageReceived, Action? receivedAction = null) where T : class; + + + /// + /// 解析376.1帧 + /// + /// + /// + public virtual TB3761? Analysis3761(string messageReceived) + { + try + { + var hexStringList = messageReceived.StringToPairs(); + // 初步校验 + if (hexStringList.Count < 6 || hexStringList.FirstOrDefault() != "68" || hexStringList.Skip(5).Take(1).FirstOrDefault() != "68" || hexStringList.Count < 18 || hexStringList.LastOrDefault() != "16") + { + _logger.LogError($"解析Analysis3761校验不通过,报文:{messageReceived}"); + } + else + { + TB3761 tB3761 = new TB3761 + { + BaseHexMessage = new BaseHexMessage + { + HexMessageString = messageReceived, + HexMessageList = hexStringList + }, + C = Analysis_C(hexStringList), + A = Analysis_A(hexStringList), + AFN_FC = Analysis_AFN_FC(hexStringList), + SEQ = Analysis_SEQ(hexStringList), + UnitData = Analysis_UnitData(hexStringList), + DA = Analysis_DA(hexStringList), + DT = Analysis_DT(hexStringList) + }; + return tB3761; + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis3761错误,报文:{messageReceived},异常:{ex.Message}"); + } + return null; + } + + /// + /// 控制域C解析 + /// + /// + public virtual C Analysis_C(List hexStringList) + { + C c = new C(); + try + { + if (hexStringList.Count > 6) + { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList.GetRange(6, 1) // 控制域 1字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + if (baseHexMessage.HexMessageList.Count == 0) + return null; + string binStr = baseHexMessage.HexMessageString.HexTo4BinZero(); + c = new C + { + BaseHexMessage = baseHexMessage, + FC = binStr.Substring(binStr.Length - 4, 4).BinToDec(), + FCV = binStr.Substring(3, 1).BinToDec(), + FCB = binStr.Substring(2, 1).BinToDec(), + PRM = binStr.Substring(1, 1).BinToDec(), + DIR = binStr.Substring(0, 1).BinToDec() + }; + return c; + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_C错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + + return c; + } + + /// + /// 地址域A解析 + /// + /// + /// + public virtual A Analysis_A(List hexStringList) + { + A a = new A(); + try + { + if (hexStringList.Count > 7) + { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList.GetRange(7, 5) // 地址域 5个字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + a = new A + { + BaseHexMessage = baseHexMessage, + A1 = baseHexMessage.HexMessageList.ListReverseToStr(0, 2),//.DataConvert(10);//行政区划码A1 + A2 = baseHexMessage.HexMessageList.ListReverseToStr(2, 2).PadLeft(5, '0').HexToDec(),//终端地址A2 + A3 = Analysis_A3(baseHexMessage.HexMessageList) //主站地址和组地址标志A3 + }; + a.Code = $"{a.A1.PadLeft(4, '0')}{a.A2.ToString()!.PadLeft(5, '0')}"; + + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_A错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + + return a; + + } + + /// + /// 站地址和组地址标志A3 + /// + /// 地址域A集合 + /// + public virtual A3 Analysis_A3(List hexAList) + { + A3 a3 = new A3(); + try + { + if (hexAList.Count != 0) + { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexAList.GetRange(4, 1) // 站地址和组地址标志A3 1个字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + var binStr = baseHexMessage.HexMessageString.HexTo4BinZero(); + a3 = new A3 + { + BaseHexMessage = baseHexMessage, + D0 = binStr.Substring(binStr.Length - 1, 1).BinToDec(), + D1_D7 = binStr.Substring(0, binStr.Length - 1).BinToDec() + }; + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_A3错误,报文:{string.Join("", hexAList)},异常:{ex.Message}"); + } + + return a3; + } + + /// + /// AFN_FC功能码 + /// + /// + public virtual AFN_FC Analysis_AFN_FC(List hexStringList) + { + AFN_FC aFN_FC = new AFN_FC(); + try + { + if (hexStringList.Count == 0) + { + + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList.GetRange(12, 1) //AFN功能码 1个字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + + aFN_FC = new AFN_FC + { + BaseHexMessage = baseHexMessage, + AFN = baseHexMessage.HexMessageString.HexToDec(), + }; + } + + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_AFN_FC错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + + return aFN_FC; + } + + /// + /// 解析帧序列域SEQ + /// + /// + public virtual SEQ Analysis_SEQ(List hexStringList) + { + SEQ seq = new SEQ(); + try + { + if (hexStringList.Count != 0) + { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList.GetRange(13, 1) //帧序列域 SEQ 1个字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + var binStr = baseHexMessage.HexMessageString.HexTo4BinZero(); + seq = new SEQ + { + PSEQ = binStr.Substring(binStr.Length - 4, 4).BinToDec(), + CON = binStr.Substring(3, 1).BinToDec(), + FIN = binStr.Substring(2, 1).BinToDec(), + FIR = binStr.Substring(1, 1).BinToDec(), + TpV = binStr.Substring(0, 1).BinToDec() + }; + } + + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_SEQ错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + return seq; + } + + + /// + /// 数据单元标识及数据单元数据 + /// + public virtual UnitData Analysis_UnitData(List hexStringList) + { + UnitData unitData = new UnitData(); + try + { + if (hexStringList.Count != 0) + { + unitData = new UnitData + { + HexMessageList = hexStringList.GetRange(14, hexStringList.Count - 14 - 2) //总数字节数-固定长度报文头-控制域C-地址域A-校验和CS-结束字符(16H) + }; + unitData.HexMessageString = string.Join("", unitData.HexMessageList); + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_UnitData错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + return unitData; + } + + /// + /// 信息点DA Pn + /// + /// + public virtual DA Analysis_DA(List hexStringList) + { + DA da = new DA(); + try + { + if (hexStringList.Count != 0) + { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList.GetRange(14, 2) //信息点DA Pn 2个字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + var da1 = baseHexMessage.HexMessageList[0]; + var da2 = baseHexMessage.HexMessageList[1]; + da = new DA() + { + BaseHexMessage = baseHexMessage, + Pn = CalculatePn(da1, da2) + }; + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_DA错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + return da; + } + + /// + /// 信息类DT Fn + /// + /// + public virtual DT Analysis_DT(List hexStringList) + { + DT dt = new DT(); + try + { + if (hexStringList.Count != 0) + { + BaseHexMessage baseHexMessage = new BaseHexMessage + { + HexMessageList = hexStringList.GetRange(16, 2) //信息类DT Fn 2个字节 + }; + baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList); + var dt1 = baseHexMessage.HexMessageList[0]; + var dt2 = baseHexMessage.HexMessageList[1]; + dt = new DT() + { + BaseHexMessage = baseHexMessage, + Fn = CalculateFn(dt1, dt2) + }; + } + } + catch (Exception ex) + { + _logger.LogError($"解析Analysis_DT错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}"); + } + + return dt; + + } + + + /// + /// 计算Pn + /// + /// + /// + /// + public static int CalculatePn(string da1, string da2) => (da2.HexToDec() - 1) * 8 + (8 - da1.HexTo4BinZero().IndexOf(da1.Equals("00") ? "0" : "1")); + + + /// + /// 计算Fn + /// + /// + /// + /// + public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1")); + + #region 下行命令构建 + + /// + /// 组装报文 + /// + /// + /// 设备数据实体 + /// 映射读取执行方法的Code,例如10_1,表示 10H_F1_00000,10H_F1_00001,统一英文下划线分隔 + /// + public abstract Task BuildAsync(ProtocolBuildRequest request); + + #endregion + + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Adapters/StandardFixedHeaderDataHandlingAdapter.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Adapters/StandardFixedHeaderDataHandlingAdapter.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Adapters/StandardFixedHeaderDataHandlingAdapter.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Adapters/StandardFixedHeaderDataHandlingAdapter.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/AnalysisData/Appendix.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/Appendix.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/AnalysisData/Appendix.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/Appendix.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/AnalysisStrategyContext.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisStrategyContext.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/AnalysisStrategyContext.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisStrategyContext.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Attributes/ProtocolNameAttribute.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Attributes/ProtocolNameAttribute.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Attributes/ProtocolNameAttribute.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Attributes/ProtocolNameAttribute.cs diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs new file mode 100644 index 0000000..d3005df --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/CollectBusProtocolT37612012Module.cs @@ -0,0 +1,18 @@ +using JiShe.CollectBus.FreeRedis.Options; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace JiShe.CollectBus.Protocol.Contracts +{ + public class CollectBusProtocolT37612012Module : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + + } + } +} + + + diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Interfaces/IAnalysisStrategy.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Interfaces/IAnalysisStrategy.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Interfaces/IAnalysisStrategy.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Interfaces/IAnalysisStrategy.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Interfaces/IProtocolPlugin.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Interfaces/IProtocolPlugin.cs diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj b/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj new file mode 100644 index 0000000..2c074cd --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/JiShe.CollectBus.Protocol.T37612012.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Models/CustomFixedHeaderRequestInfo.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Models/CustomFixedHeaderRequestInfo.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Models/CustomFixedHeaderRequestInfo.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Models/CustomFixedHeaderRequestInfo.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Models/TB3761.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Models/TB3761.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Models/TB3761.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Models/TB3761.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN10_F10_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN10_F10_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN10_F10_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN10_F10_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN10_F66_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN10_F66_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN10_F66_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN10_F66_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F129_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F129_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F129_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F129_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F130_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F130_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F130_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F130_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F131_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F131_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F131_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F131_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F132_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F132_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F132_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F132_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F145_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F145_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F145_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F145_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F149_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F149_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F149_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F149_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F188_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F188_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F188_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F188_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F25_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F25_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F25_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F25_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F2_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F2_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F2_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F2_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F33_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F33_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F33_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F33_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F49_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F49_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN12_F49_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN12_F49_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN9_F1_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN9_F1_AnalysisDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AFN9_F1_AnalysisDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AFN9_F1_AnalysisDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AnalysisBaseDto.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AnalysisBaseDto.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/AnalysisBaseDto.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/AnalysisBaseDto.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/UnitDataAnalysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/UnitDataAnalysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Protocol/Dto/UnitDataAnalysis.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/Protocol/Dto/UnitDataAnalysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/QGDW3761Config.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/QGDW3761Config.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/QGDW3761Config.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/QGDW3761Config.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/SendData/Telemetry3761PacketBuilder.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketBuilder.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/SendData/Telemetry3761PacketBuilder.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketBuilder.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/SendData/Telemetry3761PacketRequest.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketRequest.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/SendData/Telemetry3761PacketRequest.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketRequest.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/SendData/Telemetry3761PacketResponse.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketResponse.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/SendData/Telemetry3761PacketResponse.cs rename to protocols/JiShe.CollectBus.Protocol.T37612012/SendData/Telemetry3761PacketResponse.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_00H/AFN0_F1_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_09H/AFN9_F1_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_09H/AFN9_F9_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0AH/AFN10_F10_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0AH/AFN10_F66_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0AH/AFN10_F68_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F33_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_02800002.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_02800002.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_02800002.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_02800002.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000201.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000201.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000201.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000201.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000202.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000202.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000202.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000202.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000203.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000203.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000203.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000203.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000204.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000204.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04000204.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04000204.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010000.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010000.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010000.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010000.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010001.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010001.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010001.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010001.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010002.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010002.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010002.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010002.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010003.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010003.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010003.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010003.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010004.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010004.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010004.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010004.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010005.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010005.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010005.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010005.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010006.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010006.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010006.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010006.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010007.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010007.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010007.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010007.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010008.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010008.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_04010008.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_04010008.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A1.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A1.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A1.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A1.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A11.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A11.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A11.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A11.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A13.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A13.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A13.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A13.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A14.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A14.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A14.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A14.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A15.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A15.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A15.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A15.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A17.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A17.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A17.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A17.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A23.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A23.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A23.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A23.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A25.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A25.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A25.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A25.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A5.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A5.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A5.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A5.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A7.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A7.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A7.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A7.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A9.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A9.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Appendix/Appendix_A9.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Appendix/Appendix_A9.cs diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj b/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj new file mode 100644 index 0000000..e19a7e0 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/JiShe.CollectBus.Protocol.T6452007.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + preview + + + + + + + + + + + + + + + + + + + diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/JiSheCollectBusProtocolT6452007Module.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/JiSheCollectBusProtocolT6452007Module.cs new file mode 100644 index 0000000..767a2d3 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/JiSheCollectBusProtocolT6452007Module.cs @@ -0,0 +1,111 @@ +using JiShe.CollectBus.Kafka.Internal; +using JiShe.CollectBus.Protocol.AnalysisData; +using JiShe.CollectBus.Protocol.Contracts; +using JiShe.CollectBus.Protocol.Contracts.Abstracts; +using JiShe.CollectBus.Protocol.Contracts.Interfaces; +using JiShe.CollectBus.Protocol.Contracts.Models; +using JiShe.CollectBus.Protocol.Dto; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Serilog.Core; +using System; +using System.Reflection; +using Volo.Abp; +using Volo.Abp.Modularity; + +namespace JiShe.CollectBus.Protocol +{ + public class JiSheCollectBusProtocolT6452007Module : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddKeyedSingleton(nameof(T6452007ProtocolPlugin)); + //RegisterProtocolAnalysis(context.Services); + LoadAnalysisStrategy(context.Services); + } + + public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + Console.WriteLine("StandardProtocolPlugin OnApplicationInitializationAsync"); + var standardProtocol = context.ServiceProvider.GetRequiredKeyedService(nameof(T6452007ProtocolPlugin)); + await standardProtocol.LoadAsync(); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + Console.WriteLine("StandardProtocolPlugin OnApplicationShutdown"); + base.OnApplicationShutdown(context); + } + + public void LoadAnalysisStrategy(IServiceCollection services) + { + var assembly = Assembly.GetExecutingAssembly(); + var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>))); + foreach (var analysisStrategyType in analysisStrategyTypes) + { + var service = analysisStrategyType.GetInterfaces().First(); + services.AddKeyedSingleton(service, analysisStrategyType.Name,analysisStrategyType); + } + } + + public void RegisterProtocolAnalysis(IServiceCollection services) + { + // 扫描并注册所有策略 + var strategyMetadata = new Dictionary<(string, Type, Type), Type>(); + services.AddTransient(); + + // 批量注册 + var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); + if (string.IsNullOrWhiteSpace(assemblyPath)) + { + return; + } + var dllFiles = Directory.GetFiles(Path.Combine(assemblyPath, "Plugins") , "*.dll"); + foreach (var file in dllFiles) + { + // 跳过已加载的程序集 + var assemblyName = AssemblyName.GetAssemblyName(file); + var existingAssembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName); + var assembly = existingAssembly ?? Assembly.LoadFrom(file); + // 实现IAnalysisStrategy接口 + var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>))); + if (!analysisStrategyTypes.Any()) + continue; + foreach (var analysisStrategyType in analysisStrategyTypes) + { + // 通过反射获取静态元数据 + var strategyType = analysisStrategyType.Name; + var genericArgs = analysisStrategyType.GetInterface($"IAnalysisStrategy`2")!.GetGenericArguments(); + var inputType = genericArgs[0]; + var resultType = genericArgs[1]; + // 注册策略实现 + services.AddTransient(analysisStrategyType); + strategyMetadata[(strategyType, inputType, resultType)] = analysisStrategyType; + } + } + + // 注册元数据字典 + services.AddSingleton(strategyMetadata); + + // 注册策略解析工厂 + services.AddTransient>(provider => (name, inputType, resultType) => + { + var metadata = provider.GetRequiredService>(); + if (metadata.TryGetValue((name, inputType, resultType), out var strategyType)) + { + return provider.GetRequiredService(strategyType); + } + else + { + var logger= provider.GetRequiredService>(); + logger.LogWarning($"未能找到解析策略:{name}-{inputType}-{resultType}"); + return null; + } + }); + + + } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol3761Extensions.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/Protocol3761Extensions.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol/Protocol3761Extensions.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/Protocol3761Extensions.cs diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs new file mode 100644 index 0000000..6c3e69a --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketBuilder.cs @@ -0,0 +1,106 @@ +using FreeSql; +using JiShe.CollectBus.Common.BuildSendDatas; +using JiShe.CollectBus.Common.Enums; +using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.Common.Models; +using System.Reflection; + +namespace JiShe.CollectBus.Protocol.SendData +{ + /// + /// 构建645-2007下发报文 + /// + public static class Telemetry6452007PacketBuilder + { + /// + /// 构建报文的委托 + /// + /// + /// + public delegate Telemetry6452007PacketResponse T6452007Delegate(Telemetry6452007PacketRequest request); + + /// + /// 编码与方法的映射表 + /// + public static readonly Dictionary T645ControlHandlers = new(); + + static Telemetry6452007PacketBuilder() + { + // 初始化时自动注册所有符合命名规则的方法 + var methods = typeof(Telemetry6452007PacketBuilder).GetMethods(BindingFlags.Static | BindingFlags.Public); + foreach (var method in methods) + { + if (method.Name.StartsWith("C") && method.Name.EndsWith("_Send")) + { + string code = method.Name; + var delegateInstance = (T6452007Delegate)Delegate.CreateDelegate(typeof(T6452007Delegate), method); + T645ControlHandlers[code] = delegateInstance; + } + } + } + + #region 1CH 跳合闸、报警、保电 + + /// + /// 1CH 跳合闸 + /// + /// + /// + public static Telemetry6452007PacketResponse C1C_01_Send(Telemetry6452007PacketRequest request) + { + var itemCodeArr = request.ItemCode.Split('_'); + var c_data = itemCodeArr[0]; + var n_data = itemCodeArr[1]; + string password = request.Password; + string pwdLevel = "02"; + + if (!string.IsNullOrWhiteSpace(password) && password.Contains("|")) + { + var sp = password.Split('|'); + password = sp[0]; + pwdLevel = sp[1]; + } + + var strDate = DateTime.Now.AddYears(3).ToString("000012ddMMyy").StrAddSpan();//命令有效截止时间 + + var strP = password.StrAddSpan().StrReverseOrder(); + var strSJY = " " + pwdLevel + " " + strP + " 01 00 00 00 " + n_data + " 00 " + strDate; + var dataUnit = strSJY.Replace(" ", "").StringToPairs(); + + var dataList = Build645SendData.Build645SendCommand(request.MeterAddress, c_data, dataUnit); + return new Telemetry6452007PacketResponse() { Data = dataList }; + } + + + /// + /// 1CH 保电 + /// + /// + /// + public static Telemetry6452007PacketResponse C1C_03_Send(Telemetry6452007PacketRequest request) + { + var itemCodeArr = request.ItemCode.Split('_'); + var c_data = itemCodeArr[0]; + var n_data = itemCodeArr[1]; + string password = request.Password; + + if (!string.IsNullOrWhiteSpace(password) && password.Contains("|")) + { + var sp = password.Split('|'); + password = sp[0]; + } + + var strDate = (n_data + DateTime.Now.AddDays(1).ToString("00000012ddMMyy")).StrAddSpan(); + + var strP = password.StrAddSpan().StrReverseOrder(); + + var strSJY = " 02 " + strP + " 01 00 00 00 " + strDate; + + var dataUnit = strSJY.Replace(" ", "").StringToPairs(); + + var dataList = Build645SendData.Build645SendCommand(request.MeterAddress, c_data, dataUnit); + return new Telemetry6452007PacketResponse() { Data = dataList }; + } + #endregion + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs new file mode 100644 index 0000000..b4b45b7 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketRequest.cs @@ -0,0 +1,23 @@ +namespace JiShe.CollectBus.Protocol.SendData +{ + /// + /// 构建645报文参数 + /// + public class Telemetry6452007PacketRequest + { + /// + /// 表地址 + /// + public required string MeterAddress { get; set; } + + /// + /// 密码 + /// + public required string Password { get; set; } + + /// + /// 操作码 + /// + public required string ItemCode { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketResponse.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketResponse.cs new file mode 100644 index 0000000..6d8f90d --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/SendData/Telemetry6452007PacketResponse.cs @@ -0,0 +1,13 @@ +namespace JiShe.CollectBus.Protocol.SendData +{ + /// + /// 返回645报文结果 + /// + public class Telemetry6452007PacketResponse + { + /// + /// 报文体 + /// + public List Data { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs similarity index 96% rename from protocols/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs rename to protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs index 4201d04..e0e9fc3 100644 --- a/protocols/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol.T6452007/T6452007ProtocolPlugin.cs @@ -21,9 +21,9 @@ using Volo.Abp.Domain.Repositories; namespace JiShe.CollectBus.Protocol { - public class StandardProtocolPlugin : ProtocolPlugin + public class T6452007ProtocolPlugin : ProtocolPlugin { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IProducerService _producerService; @@ -31,13 +31,13 @@ namespace JiShe.CollectBus.Protocol private readonly ITcpService _tcpService; public readonly Dictionary T3761AFNHandlers; - public readonly Dictionary T645ControlHandlers; + public readonly Dictionary T645ControlHandlers; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The service provider. - public StandardProtocolPlugin(IServiceProvider serviceProvider, ILogger logger, ITcpService tcpService) : base(serviceProvider, logger) + public T6452007ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger, ITcpService tcpService) : base(serviceProvider, logger) { _logger = logger; //_logger = serviceProvider.GetRequiredService>(); @@ -45,10 +45,10 @@ namespace JiShe.CollectBus.Protocol _deviceRepository = serviceProvider.GetRequiredService>(); _tcpService = tcpService; T3761AFNHandlers = Telemetry3761PacketBuilder.T3761AFNHandlers; - T645ControlHandlers = Telemetry645PacketBuilder.T645ControlHandlers; + T645ControlHandlers = Telemetry6452007PacketBuilder.T645ControlHandlers; } - public sealed override ProtocolInfo Info => new(nameof(StandardProtocolPlugin), "376.1", "TCP", "376.1协议", "DTS1980"); + public sealed override ProtocolInfo Info => new(nameof(T6452007ProtocolPlugin), "376.1", "TCP", "376.1协议", "DTS1980"); public override async Task AnalyzeAsync(ITcpSessionClient client, string messageReceived, Action? sendAction = null) { @@ -318,7 +318,7 @@ namespace JiShe.CollectBus.Protocol { if (request == null) { - throw new Exception($"{nameof(StandardProtocolPlugin)} 报文构建失败,参数为空"); + throw new Exception($"{nameof(T6452007ProtocolPlugin)} 报文构建失败,参数为空"); } var itemCodeArr = request.ItemCode.Split('_'); var aFNStr = itemCodeArr[0]; @@ -331,12 +331,12 @@ namespace JiShe.CollectBus.Protocol if (aFNStr == "10" && request.SubProtocolRequest != null && string.IsNullOrWhiteSpace(request.SubProtocolRequest.ItemCode) == false) { var t645PacketHandlerName = $"C{request.SubProtocolRequest.ItemCode}_Send"; - Telemetry645PacketResponse t645PacketResponse = null; + Telemetry6452007PacketResponse t645PacketResponse = null; if (T645ControlHandlers != null && T645ControlHandlers.TryGetValue(t645PacketHandlerName , out var t645PacketHandler)) { - t645PacketResponse = t645PacketHandler(new Telemetry645PacketRequest() + t645PacketResponse = t645PacketHandler(new Telemetry6452007PacketRequest() { MeterAddress = request.SubProtocolRequest.MeterAddress, Password = request.SubProtocolRequest.Password, diff --git a/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj b/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj index bfc186f..c3be8a6 100644 --- a/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj +++ b/protocols/JiShe.CollectBus.Protocol.Test/JiShe.CollectBus.Protocol.Test.csproj @@ -17,7 +17,6 @@ - diff --git a/protocols/JiShe.CollectBus.Protocol/Abstracts/BaseProtocolPlugin_bak.cs b/protocols/JiShe.CollectBus.Protocol/Abstracts/BaseProtocolPlugin_bak.cs new file mode 100644 index 0000000..923f9ba --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Abstracts/BaseProtocolPlugin_bak.cs @@ -0,0 +1,1177 @@ +using FreeRedis; +using JiShe.CollectBus.Common.Enums; +using JiShe.CollectBus.Common.Extensions; +using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.Protocol.Contracts.Interfaces; +using Microsoft.Extensions.Logging; +using JiShe.CollectBus.Protocol.Contracts.Models; +using Volo.Abp.Domain.Repositories; +using JiShe.CollectBus.Common.BuildSendDatas; +using JiShe.CollectBus.Protocol.Contracts.AnalysisData; +using Microsoft.Extensions.DependencyInjection; +using JiShe.CollectBus.IotSystems.MessageReceiveds; +using JiShe.CollectBus.IotSystems.Protocols; +using JiShe.CollectBus.Kafka.Producer; +using JiShe.CollectBus.Common.Consts; +using JiShe.CollectBus.FreeRedis; + +namespace JiShe.CollectBus.Protocol.Contracts.Abstracts +{ + public abstract class BaseProtocolPlugin_bak //: IProtocolPlugin + { + private readonly IProducerService _producerService; + private readonly ILogger _logger; + private readonly IRepository _protocolInfoRepository; + private readonly IFreeRedisProvider _redisProvider; + + //头部字节长度 + public const int hearderLen = 6; + + public const int tPLen = 6; + + public const string errorData = "EE"; + + /// + /// Initializes a new instance of the class. + /// + /// The service provider. + protected BaseProtocolPlugin_bak(IServiceProvider serviceProvider) + { + + _logger = serviceProvider.GetRequiredService>(); + _protocolInfoRepository = serviceProvider.GetRequiredService>(); + _producerService = serviceProvider.GetRequiredService(); + _redisProvider = serviceProvider.GetRequiredService(); + } + + public abstract ProtocolInfo Info { get; } + + public virtual async Task GetAsync() => await Task.FromResult(Info); + + public virtual async Task LoadAsync() + { + if (Info == null) + { + throw new ArgumentNullException(nameof(Info)); + } + + await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name); + await _protocolInfoRepository.InsertAsync(Info); + await _redisProvider.Instance.HDelAsync($"{RedisConst.ProtocolKey}", Info.Name); + await _redisProvider.Instance.HSetAsync($"{RedisConst.ProtocolKey}", Info.Name, Info); + } + + public abstract Task AnalyzeAsync(MessageReceived messageReceived, Action? sendAction = null) where T : TB3761; + + /// + /// 登录帧解析 + /// + /// 报文 + /// + public virtual async Task LoginAsync(MessageReceivedLogin messageReceived) + { + var hexStringList = messageReceived.MessageHexString.StringToPairs(); + var aTuple = (Tuple)hexStringList.GetAnalyzeValue(CommandChunkEnum.A); + var seq = (Seq)hexStringList.GetAnalyzeValue(CommandChunkEnum.SEQ); + var reqParam = new ReqParameter2 + { + AFN = AFN.确认或否认, + FunCode = (int)CFromStationFunCode.链路数据, + PRM = PRM.从动站报文, + A = aTuple.Item1, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.需要对该帧进行确认, + PRSEQ = seq.PRSEQ + }, + MSA = aTuple.Item2, + Pn = 0, + Fn = 1 + }; + var bytes = Build3761SendData.BuildSendCommandBytes(reqParam); + //await _producerBus.PublishAsync(ProtocolConst.SubscriberLoginIssuedEventName, new IssuedEventMessage { ClientId = messageReceived.ClientId, DeviceNo = messageReceived.DeviceNo, Message = bytes, Type = IssuedEventType.Login, MessageId = messageReceived.MessageId }); + + await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginIssuedEventName, new IssuedEventMessage { ClientId = messageReceived.ClientId, DeviceNo = messageReceived.DeviceNo, Message = bytes, Type = IssuedEventType.Login, MessageId = messageReceived.MessageId }); + //await _producerBus.Publish(new IssuedEventMessage { ClientId = messageReceived.ClientId, DeviceNo = messageReceived.DeviceNo, Message = bytes, Type = IssuedEventType.Login, MessageId = messageReceived.MessageId }); + } + + /// + /// 心跳帧解析 + /// + /// 报文 + /// + public virtual async Task HeartbeatAsync(MessageReceivedHeartbeat messageReceived) + { + var hexStringList = messageReceived.MessageHexString.StringToPairs(); + var aTuple = (Tuple)hexStringList.GetAnalyzeValue(CommandChunkEnum.A); + var seq = (Seq)hexStringList.GetAnalyzeValue(CommandChunkEnum.SEQ); + if (seq.TpV == TpV.附加信息域中带时间标签) + { + //解析 + + } + if (seq.CON == CON.需要对该帧进行确认) + { + var reqParam = new ReqParameter2() + { + AFN = AFN.确认或否认, + FunCode = (int)CFromStationFunCode.链路数据, + PRM = PRM.从动站报文, + A = aTuple.Item1, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.不需要对该帧进行确认, + PRSEQ = seq.PRSEQ, + }, + MSA = aTuple.Item2, + Pn = 0, + Fn = 1 + }; + var bytes = Build3761SendData.BuildSendCommandBytes(reqParam); + //await _producerBus.PublishAsync(ProtocolConst.SubscriberHeartbeatIssuedEventName, new IssuedEventMessage { ClientId = messageReceived.ClientId, DeviceNo = messageReceived.DeviceNo, Message = bytes, Type = IssuedEventType.Heartbeat, MessageId = messageReceived.MessageId }); + + await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatIssuedEventName, new IssuedEventMessage { ClientId = messageReceived.ClientId, DeviceNo = messageReceived.DeviceNo, Message = bytes, Type = IssuedEventType.Heartbeat, MessageId = messageReceived.MessageId }); + + //await _producerBus.Publish(new IssuedEventMessage { ClientId = messageReceived.ClientId, DeviceNo = messageReceived.DeviceNo, Message = bytes, Type = IssuedEventType.Heartbeat, MessageId = messageReceived.MessageId }); + } + } + + /// + /// 解析确认或否认数据 + /// + /// + /// + /// + public virtual async Task AnalyzeAnswerDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexStringList = messageReceived.MessageHexString.StringToPairs(); + var fn = hexStringList.GetAnalyzeValue(CommandChunkEnum.FN); + //1:全部确认 + //2:全部否认 + //3:按数据单元表示确认和否认 + //4 硬件安全认证错误应答 + } + + /// + /// 解析电表档案读取数据 + /// + /// + /// + /// + public virtual List AnalyzeAmmeterParameterReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexData = GetHexData(messageReceived.MessageHexString); + + var meterList = new List(); + var count = (hexData[1] + hexData[0]).HexToDec(); + //if (2 + count * 27 != hexDatas.Count - pWLen - tPLen - 2) + // return; + var index = 2;//数量 + for (int i = 1; i <= count; i++) + { + var meterNumber = $"{hexData[index + 1]}{hexData[index]}".HexToDec(); + index += 2; + + var pn = $"{hexData[index + 1]}{hexData[index]}".HexToDec(); + index += 2; + + var baudRateAndPortBin = hexData[index].HexToBin().PadLeft(8, '0'); + var baudRate = baudRateAndPortBin.Substring(0, 3).BinToDec(); + var port = baudRateAndPortBin.Substring(3, 5).BinToDec(); + index += 1; + + var protocolType = (CommunicationProtocolType)hexData[index].HexToDec(); + index += 1; + + var addressHexList = hexData.Skip(index).Take(6).ToList(); + addressHexList.Reverse(); + var address = string.Join("", addressHexList); + index += 6; + + var pwdHexList = hexData.Skip(index).Take(6).ToList(); + pwdHexList.Reverse(); + var password = string.Join("", pwdHexList.Take(3).ToList()); + index += 6; + + var rateNumberBin = hexData[index].HexToBin().PadLeft(8, '0'); + var rateNumber = rateNumberBin.Substring(4).BinToDec(); + index += 1; + + var intBitAndDecBitNumberBin = hexData[index].HexToBin().PadLeft(8, '0'); + var intBitNumber = intBitAndDecBitNumberBin.Substring(4, 2).BinToDec() + 4; + var decBitNumber = intBitAndDecBitNumberBin.Substring(6, 2).BinToDec() + 1; + index += 1; + + // hexDatas.GetRange() + var collectorAddressHexList = hexData.Skip(index).Take(6).ToList(); + collectorAddressHexList.Reverse(); + var collectorAddress = string.Join("", collectorAddressHexList); + index += 6; + + var userClassNumberBin = hexData[index].HexToBin().PadLeft(8, '0'); + var userClass = userClassNumberBin.Substring(0, 4).BinToDec(); + var userSubClass = userClassNumberBin.Substring(4, 4).BinToDec(); + index += 1; + + meterList.Add(new AmmeterParameter() + { + Pn = pn, + BaudRate = baudRate, + Port = port, + ProtocolType = (int)protocolType, + Address = address, + Password = password, + RateNumber = rateNumber, + IntegerBitNumber = intBitNumber, + DecimalBitNumber = decBitNumber, + CollectorAddress = collectorAddress, + UserCategoryNumber = userClass, + UserSubclassNumber = userSubClass, + }); + } + + return meterList; + } + + /// + /// 解析当前正向有功电能示值抄读数据 + /// + /// 报文 + /// 发送委托 + /// + public virtual CurrentPositiveActiveEnergyAnalyze AnalyzeActivePowerIndicationReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexData = GetHexData(messageReceived.MessageHexString); + + var minute = Convert.ToInt32(hexData[0]); // 获取当前分钟数 + var hour = Convert.ToInt32(hexData[1]); // 获取当前小时数 + var day = Convert.ToInt32(hexData[2]); // 获取当前日期的日数 + var month = Convert.ToInt32(hexData[3]); // 获取当前月份 + var year = Convert.ToInt32(hexData[4]); // 获取当前日期的年份 + var dateTime = new DateTime(year, month, day, hour, minute, 0); + // 转换为本地时间 + var localDateTime = dateTime.ToLocalTime(); + + var rateNumber = Convert.ToInt32(hexData[5]); + var kwhTotal = hexData.Skip(5).Take(5).ToList(); + var kwhList = new List(); + var index = 11; + for (int i = 0; i < rateNumber; i++) + { + var kwhHexList = hexData.Skip(index).Take(5).ToList(); + kwhHexList.Reverse(); + var integerStr = $"{kwhHexList.Take(0)}{kwhHexList.Take(1)}{kwhHexList.Take(2)}"; + var decimalValStr = $"{kwhHexList[3]}{kwhHexList[4]}"; + var val = decimal.Parse($"{integerStr}{decimalValStr}"); + kwhList.Add(new PositiveActiveEnergyItem() + { + Name = $"费率{i + 1}正向有功总电能示值", + Value = val + }); + index += 5; + } + + return new CurrentPositiveActiveEnergyAnalyze() + { + ReadingTime = localDateTime, + RateNumber = rateNumber, + Items = kwhList + }; + } + + /// + /// 解析日冻结正向有功电能示值抄读数据 + /// + /// + /// + /// + public virtual void AnalyzeDailyFrozenReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexData = GetHexData(messageReceived.MessageHexString); + //附录A.20 日月年 + var td_dHex = hexData.Take(3).ToList(); + //附录A.15 分时日月年 + var readingTimeHex = hexData.Skip(3).Take(5).ToList(); + var rateNumberHex = hexData.Skip(8).Take(1).FirstOrDefault().HexToDec(); + + var datas = new List(); + //附录A.14 kWh 5字节 + for (int i = 0; i < rateNumberHex; i++) + { + var skipCount = 9 + i * 5; + var dataHexs = hexData.Skip(skipCount).Take(5).ToList(); + var data = AnalyzeDataAccordingToA14(dataHexs[0], dataHexs[1], dataHexs[2], dataHexs[3], dataHexs[4]); + datas.Add(data); + } + + } + + //接收<2024/11/7 17:34:42>: 68 3E 01 3E 01 68 + //控制域 88 + //地址域 20 32 90 26 1A + //AFN 0C + //Seq 62 + //pn 01 01 + //fn 01 03 + + //F0 16 + + //报文解析:计量点1数据 + //++++++++ F25:当前三相及总有/无功功率功率因数 三相电压电流 零序电流 ++++++++ + //终端抄表时间:2024年11月07日17时34分 34 17 07 11 24 + //当前总有功功率:-0.0028 kW 28 00 80 + //当前A相有功功率:0 kW 00 00 80 + //当前B相有功功率:0 kW 00 00 80 + //当前C相有功功率:-0.0027 kW 27 00 80 + //当前总无功功率:-0.0047 kW 47 00 80 + //当前A相无功功率:0 kW 00 00 00 + //当前B相无功功率:0 kW 00 00 00 + //当前C相无功功率:-0.0047 kW 47 00 80 + //当前总功率因数:-51.8 % 18 85 + //当前A相功率因数:0 % 00 80 + //当前B相功率因数:0 % 00 80 + //当前C相功率因数:-50 % 00 85 + //当前A相电压:0.1 V 01 00 + //当前B相电压:0.2 V 02 00 + //当前C相电压:239 V 90 23 + //当前A相电流:0 A 00 00 80 + //当前B相电流:0 A 00 00 80 + //当前C相电流:-0.024 A 24 00 80 + //当前零序电流:Error: 数据不符合BCD码格式 A EE EE EE + //当前总视在功率:Error: 数据不符合BCD码格式 kVA EE EE EE + //当前A相视在功率:Error: 数据不符合BCD码格式 kVA EE EE EE + //当前B相视在功率:Error: 数据不符合BCD码格式 kVA EE EE EE + //当前C相视在功率:Error: 数据不符合BCD码格式 kVA EE EE EE + //++++++++++++++++++++++++++++++++++++ + /// + /// 当前三相及总有/无功功率、功率因数、三相电压、电流、零序电流、视在功率 + /// + /// + /// + /// //F25ReadingAnalyze + public virtual Analyze3761Data AnalyzeF25ReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexData = GetHexData(messageReceived.MessageHexString); + //A.15 分时日月年 + var readingTimeHex = hexData.Take(5).ToList(); + var readingTime = AnalyzeDataAccordingToA15(readingTimeHex[0], readingTimeHex[1], readingTimeHex[2], readingTimeHex[3], readingTimeHex[4]); + + //A.9 kW + var crntTotalActivePowerHexs = hexData.Skip((int)F25DataItemEnum.CrntTotalActivePower).Take(3).ToList(); + var crntTotalActivePower = AnalyzeDataAccordingToA09(crntTotalActivePowerHexs[0], crntTotalActivePowerHexs[1], crntTotalActivePowerHexs[2]); + + var crntActivePowerOfAHexs = hexData.Skip((int)F25DataItemEnum.CrntActivePowerOfA).Take(3).ToList(); + var crntActivePowerOfA = AnalyzeDataAccordingToA09(crntActivePowerOfAHexs[0], crntActivePowerOfAHexs[1], crntActivePowerOfAHexs[2]); + + var crntActivePowerOfBHexs = hexData.Skip((int)F25DataItemEnum.CrntActivePowerOfB).Take(3).ToList(); + var crntActivePowerOfB = AnalyzeDataAccordingToA09(crntActivePowerOfBHexs[0], crntActivePowerOfBHexs[1], crntActivePowerOfBHexs[2]); + + var crntActivePowerOfCHexs = hexData.Skip((int)F25DataItemEnum.CrntActivePowerOfC).Take(3).ToList(); + var crntActivePowerOfC = AnalyzeDataAccordingToA09(crntActivePowerOfCHexs[0], crntActivePowerOfCHexs[1], crntActivePowerOfCHexs[2]); + + var crntTotalReactivePowerHexs = hexData.Skip((int)F25DataItemEnum.CrntTotalReactivePower).Take(3).ToList(); + var crntTotalReactivePower = AnalyzeDataAccordingToA09(crntTotalReactivePowerHexs[0], crntTotalReactivePowerHexs[1], crntTotalReactivePowerHexs[2]); + + var crntReactivePowerOfAHexs = hexData.Skip((int)F25DataItemEnum.CrntReactivePowerOfA).Take(3).ToList(); + var crntReactivePowerOfA = AnalyzeDataAccordingToA09(crntReactivePowerOfAHexs[0], crntReactivePowerOfAHexs[1], crntReactivePowerOfAHexs[2]); + + var crntReactivePowerOfBHexs = hexData.Skip((int)F25DataItemEnum.CrntReactivePowerOfB).Take(3).ToList(); + var crntReactivePowerOfB = AnalyzeDataAccordingToA09(crntReactivePowerOfBHexs[0], crntReactivePowerOfBHexs[1], crntReactivePowerOfBHexs[2]); + + var crntReactivePowerOfCHexs = hexData.Skip((int)F25DataItemEnum.CrntReactivePowerOfC).Take(2).ToList(); + var crntReactivePowerOfC = AnalyzeDataAccordingToA09(crntReactivePowerOfCHexs[0], crntReactivePowerOfCHexs[1], crntReactivePowerOfCHexs[2]); + + //A.5 % + var crntTotalPowerFactorHexs = hexData.Skip((int)F25DataItemEnum.CrntTotalPowerFactor).Take(2).ToList(); + var crntTotalPowerFactor = AnalyzeDataAccordingToA05(crntTotalPowerFactorHexs[0], crntTotalPowerFactorHexs[1]); + + var crntPowerFactorOfAHexs = hexData.Skip((int)F25DataItemEnum.CrntPowerFactorOfA).Take(2).ToList(); + var crntPowerFactorOfA = AnalyzeDataAccordingToA05(crntPowerFactorOfAHexs[0], crntPowerFactorOfAHexs[1]); + + var crntPowerFactorOfBHexs = hexData.Skip((int)F25DataItemEnum.CrntPowerFactorOfB).Take(2).ToList(); + var crntPowerFactorOfB = AnalyzeDataAccordingToA05(crntPowerFactorOfBHexs[0], crntPowerFactorOfBHexs[1]); + + var crntPowerFactorOfCHexs = hexData.Skip((int)F25DataItemEnum.CrntPowerFactorOfC).Take(2).ToList(); + var crntPowerFactorOfC = AnalyzeDataAccordingToA05(crntPowerFactorOfCHexs[0], crntPowerFactorOfCHexs[1]); + + //A.7 V + var crntVoltageOfAHexs = hexData.Skip((int)F25DataItemEnum.CrntVoltageOfA).Take(2).ToList(); + var crntVoltageOfA = AnalyzeDataAccordingToA07(crntVoltageOfAHexs[0], crntVoltageOfAHexs[1]); + + var crntVoltageOfBHexs = hexData.Skip((int)F25DataItemEnum.CrntVoltageOfB).Take(2).ToList(); + var crntVoltageOfB = AnalyzeDataAccordingToA07(crntVoltageOfBHexs[0], crntVoltageOfBHexs[1]); + + var crntVoltageOfCHexs = hexData.Skip((int)F25DataItemEnum.CrntVoltageOfC).Take(2).ToList(); + var crntVoltageOfC = AnalyzeDataAccordingToA07(crntVoltageOfCHexs[0], crntVoltageOfCHexs[1]); + + //A.25 A + var crntCurrentOfAHexs = hexData.Skip((int)F25DataItemEnum.CrntCurrentOfA).Take(3).ToList(); + var crntCurrentOfA = AnalyzeDataAccordingToA25(crntCurrentOfAHexs[0], crntCurrentOfAHexs[1], crntCurrentOfAHexs[2]); + + var crntCurrentOfBHexs = hexData.Skip((int)F25DataItemEnum.CrntCurrentOfB).Take(3).ToList(); + var crntCurrentOfB = AnalyzeDataAccordingToA25(crntCurrentOfBHexs[0], crntCurrentOfBHexs[1], crntCurrentOfBHexs[2]); + + var crntCurrentOfCHexs = hexData.Skip((int)F25DataItemEnum.CrntCurrentOfC).Take(3).ToList(); + var crntCurrentOfC = AnalyzeDataAccordingToA25(crntCurrentOfCHexs[0], crntCurrentOfCHexs[1], crntCurrentOfCHexs[2]); + + var crntZeroSequenceCurrentHexs = hexData.Skip((int)F25DataItemEnum.CrntZeroSequenceCurrent).Take(3).ToList(); + var crntZeroSequenceCurrent = AnalyzeDataAccordingToA25(crntZeroSequenceCurrentHexs[0], crntZeroSequenceCurrentHexs[1], crntZeroSequenceCurrentHexs[2]); + + //A.9 kVA + var crntTotalApparentPowerHexs = hexData.Skip((int)F25DataItemEnum.CrntTotalApparentPower).Take(3).ToList(); + var crntTotalApparentPower = AnalyzeDataAccordingToA09(crntTotalApparentPowerHexs[0], crntTotalApparentPowerHexs[1], crntTotalApparentPowerHexs[2]); + + var crntApparentPowerOfAHexs = hexData.Skip((int)F25DataItemEnum.CrntApparentPowerOfA).Take(3).ToList(); + var crntApparentPowerOfA = AnalyzeDataAccordingToA09(crntApparentPowerOfAHexs[0], crntApparentPowerOfAHexs[1], crntApparentPowerOfAHexs[2]); + + var crntApparentPowerOfBHexs = hexData.Skip((int)F25DataItemEnum.CrntApparentPowerOfB).Take(3).ToList(); + var crntApparentPowerOfB = AnalyzeDataAccordingToA09(crntApparentPowerOfBHexs[0], crntApparentPowerOfBHexs[1], crntApparentPowerOfBHexs[2]); + + var crntApparentPowerOfCHexs = hexData.Skip((int)F25DataItemEnum.CrntApparentPowerOfC).Take(3).ToList(); + var crntApparentPowerOfC = AnalyzeDataAccordingToA09(crntApparentPowerOfCHexs[0], crntApparentPowerOfCHexs[1], crntApparentPowerOfCHexs[2]); + + return new Analyze3761Data() + { + AFN = 12, + FN = 25, + Text = "当前三相及总有/无功功率功率因数", + DataUpChilds = new List() + { + new Analyze3761DataUpChild(1,"终端抄表时间",readingTime.ToString(),1), + new Analyze3761DataUpChild(2,"当前总有功功率",crntTotalActivePower.ToString(),2), + new Analyze3761DataUpChild(3,"当前A相有功功率",crntActivePowerOfA.ToString(),3), + new Analyze3761DataUpChild(4,"当前B相有功功率",crntActivePowerOfB.ToString(),4), + new Analyze3761DataUpChild(5,"当前C相有功功率",crntActivePowerOfC.ToString(),5), + new Analyze3761DataUpChild(6,"当前总无功功率",crntTotalReactivePower.ToString(),6), + new Analyze3761DataUpChild(7,"当前A相无功功率",crntReactivePowerOfA.ToString(),7), + new Analyze3761DataUpChild(8,"当前B相无功功率",crntReactivePowerOfB.ToString(),8), + new Analyze3761DataUpChild(9,"当前C相无功功率",crntReactivePowerOfC.ToString(),9), + new Analyze3761DataUpChild(10,"当前总功率因数",crntTotalPowerFactor.ToString(),10), + new Analyze3761DataUpChild(11,"当前A相功率因数",crntPowerFactorOfA.ToString(),11), + new Analyze3761DataUpChild(12,"当前B相功率因数",crntPowerFactorOfB.ToString(),12), + new Analyze3761DataUpChild(13,"当前C相功率因数",crntPowerFactorOfC.ToString(),13), + new Analyze3761DataUpChild(14,"当前A相电压",crntVoltageOfA.ToString(),14), + new Analyze3761DataUpChild(15,"当前B相电压",crntVoltageOfB.ToString(),15), + new Analyze3761DataUpChild(16,"当前C相电压",crntVoltageOfC.ToString(),16), + new Analyze3761DataUpChild(17,"当前A相电流",crntCurrentOfA.ToString(),17), + new Analyze3761DataUpChild(18,"当前B相电流",crntCurrentOfB.ToString(),18), + new Analyze3761DataUpChild(19,"当前C相电流",crntCurrentOfC.ToString(),19), + new Analyze3761DataUpChild(20,"当前零序电流",crntZeroSequenceCurrent.ToString(),20), + new Analyze3761DataUpChild(21,"当前总视在功率",crntTotalApparentPower.ToString(),21), + new Analyze3761DataUpChild(22,"当前A相视在功率",crntApparentPowerOfA.ToString(),22), + new Analyze3761DataUpChild(23,"当前B相视在功率",crntApparentPowerOfB.ToString(),23), + new Analyze3761DataUpChild(24,"当前C相视在功率",crntApparentPowerOfC.ToString(),24), + } + }; + + //var f25ReadingAnalyze = new F25ReadingAnalyze() + //{ + // ReadingTime = readingTime.ToLocalTime(), + // CrntTotalActivePower = crntTotalActivePower, + // CrntActivePowerOfA = crntActivePowerOfA, + // CrntActivePowerOfB = crntActivePowerOfB, + // CrntActivePowerOfC = crntActivePowerOfC, + // CrntTotalReactivePower = crntTotalReactivePower, + // CrntReactivePowerOfA = crntReactivePowerOfA, + // CrntReactivePowerOfB = crntReactivePowerOfB, + // CrntReactivePowerOfC = crntReactivePowerOfC, + // CrntTotalPowerFactor = crntTotalPowerFactor, + // CrntPowerFactorOfA = crntPowerFactorOfA, + // CrntPowerFactorOfB = crntPowerFactorOfB, + // CrntPowerFactorOfC = crntPowerFactorOfC, + // CrntVoltageOfA = crntVoltageOfA, + // CrntVoltageOfB = crntVoltageOfB, + // CrntVoltageOfC = crntVoltageOfC, + // CrntCurrentOfA = crntCurrentOfA, + // CrntCurrentOfB = crntCurrentOfB, + // CrntCurrentOfC = crntCurrentOfC, + // CrntZeroSequenceCurrent = crntZeroSequenceCurrent, + // CrntTotalApparentPower = crntTotalApparentPower, + // CrntApparentPowerOfA = crntApparentPowerOfA, + // CrntApparentPowerOfB = crntApparentPowerOfB, + // CrntApparentPowerOfC = crntApparentPowerOfC + //}; + + //return f25ReadingAnalyze; + + } + + /// + /// 解析终端版本信息抄读 + /// + /// + /// + /// //TerminalVersionInfoAnalyze + public virtual Analyze3761Data AnalyzeTerminalVersionInfoReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexData = GetHexData(messageReceived.MessageHexString); + + var makerNo = string.Join("",hexData.Take(4).Select(s => (char)s.HexToDec()));//厂商代码 + var deviceNo = string.Join("", hexData.Skip((int)TerminalVersionInfoEnum.DeviceNo).Take(8).Select(s => (char)s.HexToDec()));//设备编号 + var softwareVersionNo = string.Join("", hexData.Skip((int)TerminalVersionInfoEnum.SoftwareVersionNo).Take(4).Select(s => (char)s.HexToDec()));//软件版本号 + var softwareReleaseDateList = hexData.Skip((int)TerminalVersionInfoEnum.SoftwareReleaseDate).Take(3).ToList(); + var softwareReleaseDate = $"20{AnalyzeDataAccordingToA20(softwareReleaseDateList[0], softwareReleaseDateList[1], softwareReleaseDateList[2])}";//软件发布日期 + var capacityInformationCode = string.Join("", hexData.Skip((int)TerminalVersionInfoEnum.CapacityInformationCode).Take(11).Select(s => (char)s.HexToDec()));//容量信息码 + var protocolVersionNo = string.Join("", hexData.Skip((int)TerminalVersionInfoEnum.ProtocolVersionNo).Take(4).Select(s => (char)s.HexToDec()));//通信协议编号 + var hardwareVersionNo = string.Join("", hexData.Skip((int)TerminalVersionInfoEnum.HardwareVersionNo).Take(4).Select(s => (char)s.HexToDec()));//硬件版本号 + var hardwareReleaseDateList = hexData.Skip((int)TerminalVersionInfoEnum.HardwareReleaseDate).Take(3).ToList(); + var hardwareReleaseDate = $"20{AnalyzeDataAccordingToA20(hardwareReleaseDateList[0], hardwareReleaseDateList[1], hardwareReleaseDateList[2])}";//软件发布日期 + + return new Analyze3761Data() + { + AFN = 09, + FN = 1, + Text = "终端版本信息", + DataUpChilds = new List() + { + new Analyze3761DataUpChild(1,"厂商代码",makerNo.ToString(),1), + new Analyze3761DataUpChild(2,"设备编号",deviceNo.ToString(),2), + new Analyze3761DataUpChild(3,"软件版本号",softwareVersionNo.ToString(),3), + new Analyze3761DataUpChild(4,"软件发布日期",softwareReleaseDate.ToString(),4), + new Analyze3761DataUpChild(5,"容量信息码",capacityInformationCode.ToString(),5), + new Analyze3761DataUpChild(6,"通信协议编号",protocolVersionNo.ToString(),6), + new Analyze3761DataUpChild(7,"硬件版本号",hardwareVersionNo.ToString(),7), + new Analyze3761DataUpChild(8,"软件发布日期",hardwareReleaseDate.ToString(),8), + } + }; + //return new TerminalVersionInfoAnalyze() + //{ + // MakerNo = makerNo, + // DeviceNo = deviceNo, + // SoftwareVersionNo = softwareVersionNo, + // SoftwareReleaseDate = DateTime.Parse(softwareReleaseDate).ToLocalTime(), + // CapacityInformationCode = capacityInformationCode, + // ProtocolVersionNo = protocolVersionNo, + // HardwareVersionNo = hardwareVersionNo, + // HardwareReleaseDate = DateTime.Parse(hardwareReleaseDate).ToLocalTime() + //}; + } + + /// + /// 解析相位角 + /// + /// + /// + /// + public virtual Analyze3761Data AnalyzeATypeOfDataItems49ReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexData = GetHexData(messageReceived.MessageHexString); + + var uabUaList = hexData.Take(2).ToList(); + var uabUa = AnalyzeDataAccordingToA05(uabUaList[0], uabUaList[1]); //单位 度 + + var ubList = hexData.Skip((int)ATypeOfDataItems49.Ub).Take(2).ToList(); + var ub = AnalyzeDataAccordingToA05(ubList[0], ubList[1]); + + var ucbUcList = hexData.Skip((int)ATypeOfDataItems49.UcbUc).Take(2).ToList(); + var ucbUc = AnalyzeDataAccordingToA05(ucbUcList[0], ucbUcList[1]); + + var iaList = hexData.Skip((int)ATypeOfDataItems49.Ia).Take(2).ToList(); + var ia = AnalyzeDataAccordingToA05(iaList[0], iaList[1]); + + var ibList = hexData.Skip((int)ATypeOfDataItems49.Ib).Take(2).ToList(); + var ib = AnalyzeDataAccordingToA05(ibList[0], ibList[1]); + + var icList = hexData.Skip((int)ATypeOfDataItems49.Ic).Take(2).ToList(); + var ic = AnalyzeDataAccordingToA05(icList[0], icList[1]); + + return new Analyze3761Data() + { + AFN = 12, + FN = 49, + Text = "相位角", + DataUpChilds = + [ + new Analyze3761DataUpChild(1, "UabUa相位角", uabUa.ToString(), 1), + new Analyze3761DataUpChild(2, "Ub相位角", ub.ToString(), 2), + new Analyze3761DataUpChild(3, "UcbUc相位角", ucbUc.ToString(), 3), + new Analyze3761DataUpChild(4, "Ia相位角", ia.ToString(), 4), + new Analyze3761DataUpChild(5, "Ib相位角", ib.ToString(), 5), + new Analyze3761DataUpChild(6, "Ic相位角", ic.ToString(), 6) + ] + }; + } + + /// + /// 解析终端时间抄读 + /// + /// + /// + + public virtual void AnalyzeTerminalTimeReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexDatas = GetHexData(messageReceived.MessageHexString); + var time = Appendix.Appendix_A1(hexDatas.Take(6).ToList()); + } + + ///// + ///// 通用解析 + ///// + ///// + ///// + ///// + //public virtual TB3761 AnalyzeReadingDataAsync(MessageReceived messageReceived, + // Action? sendAction = null) + //{ + // var hexStringList = messageReceived.MessageHexString.StringToPairs(); + // var afn = (AFN)hexStringList.GetAnalyzeValue(CommandChunkEnum.AFN); + // var fn = (int)hexStringList.GetAnalyzeValue(CommandChunkEnum.FN); + + // var tb3761 = QGDW3761Config.CommandList.FirstOrDefault(it => it.Afn == afn); + // if (tb3761 == null) return null; + + // var tb3761Fn = tb3761.FnList.FirstOrDefault(it => it.Fn == fn); + // if (tb3761Fn == null) return null; + + // var analyzeValue = (List)hexStringList.GetAnalyzeValue(CommandChunkEnum.Data); + + // var m = 0; + // var rateNumberUpSort = -1; + // var rateNumberUp = tb3761Fn.UpList.FirstOrDefault(it => it.Name.Contains("费率数M")); + // if (rateNumberUp != null) + // { + // var rateNumber = analyzeValue.Skip(rateNumberUp.DataIndex).Take(rateNumberUp.DataCount).FirstOrDefault(); + // m = Convert.ToInt32(rateNumber); + // rateNumberUpSort = rateNumberUp.Sort; + // } + + // foreach (var up in tb3761Fn.UpList) + // { + // var dataIndex = up.DataIndex; + // if (dataIndex == 0 && up.Sort > rateNumberUpSort) + // { + // var sum1 = tb3761Fn.UpList.Where(it => it.Sort < up.Sort) + // .Sum(it => it.DataCount); + // var sum2 = tb3761Fn.UpList.Where(it => it.Sort < up.Sort && it.Tb3761UpChildlList.Count > 0) + // .Sum(it => it.Tb3761UpChildlList.Sum(c=> m * c.DataCount)); + // dataIndex = sum1 + sum2; + // } + + // var value = AnalyzeDataAccordingDataType(analyzeValue, dataIndex, up.DataCount, up.DataType); + // if (value != null) + // { + // up.Value = value.ToString(); + // } + // if (up.Tb3761UpChildlList.Count > 0) //复费率根据费率数来解析 + // { + // var repeatCount = m; + // foreach (var upChild in up.Tb3761UpChildlList) + // { + // for (var j = 0; j < repeatCount; j++) + // { + // var val = AnalyzeDataAccordingDataType(analyzeValue, dataIndex, upChild.DataCount, upChild.DataType); + // if (val != null) + // { + // upChild.Name = string.Format(upChild.Name, j + 1); + // upChild.Value = val.ToString(); + // } + // dataIndex += upChild.DataCount; + // } + // } + + // } + // } + + // return tb3761; + //} + + ///// + ///// 通用解析 日冻结曲线类 + ///// + ///// + ///// + ///// + //public virtual TB3761 AnalyzeReadingTdcDataAsync(MessageReceived messageReceived, + // Action? sendAction = null) + //{ + + // var hexStringList = messageReceived.MessageHexString.StringToPairs(); + // var afn = (AFN)hexStringList.GetAnalyzeValue(CommandChunkEnum.AFN); + // var fn = (int)hexStringList.GetAnalyzeValue(CommandChunkEnum.FN); + + // var tb3761 = QGDW3761Config.CommandTdcList.FirstOrDefault(it => it.Afn == afn); + // if (tb3761 == null) return null; + + // var tb3761Fn = tb3761.FnList.FirstOrDefault(it => it.Fn == fn); + // if (tb3761Fn == null) return null; + + // var analyzeValue = (List)hexStringList.GetAnalyzeValue(CommandChunkEnum.Data); + + // foreach (var up in tb3761Fn.UpList) + // { + // var value = AnalyzeDataAccordingDataType(analyzeValue, up.DataIndex, up.DataCount, up.DataType); + // if (value != null) + // { + // up.Value = value.ToString(); + + // if (up.Tb3761UpChildlList.Count > 0) + // { + // var dataIndex = up.DataIndex; + // var repeatCount = (int)value; + // foreach (var upChild in up.Tb3761UpChildlList) + // { + // for (var j = 0; j < repeatCount; j++) + // { + // var val = AnalyzeDataAccordingDataType(analyzeValue, dataIndex, upChild.DataCount, upChild.DataType); + // if (val != null) + // { + // upChild.Value = val.ToString(); + // upChild.Name = string.Format(upChild.Name, j + 1); + // } + // dataIndex += upChild.DataCount; + // } + // } + // } + // } + // } + + // return tb3761; + // //var freezeDensity = (FreezeDensity)Convert.ToInt32(hexDatas.Skip(5).Take(1)); + // //var addMinute = 0; + // //switch (freezeDensity) + // //{ + // // case FreezeDensity.No:break; + // // case FreezeDensity.Min15: + // // addMinute = 15; + // // break; + // // case FreezeDensity.Min30: + // // addMinute = 30; + // // break; + // // case FreezeDensity.Min60: + // // addMinute = 60; + // // break; + // // case FreezeDensity.Min5: break; + // // addMinute = 5; + // // case FreezeDensity.Min1: + // // addMinute = 1; + // // break; + // // } + //} + + private object? AnalyzeDataAccordingDataType(List analyzeValue, int dataIndex,int dataCount,string dataType) + { + var valueList = analyzeValue.Skip(dataIndex).Take(dataCount).ToList(); + object? value = null; + switch (dataType) + { + case "BIN": + value = Convert.ToInt32(valueList[0]); + break; + case "A05": + if (valueList.Count == 2) + { + value = AnalyzeDataAccordingToA05(valueList[0], valueList[1]); + } + break; + case "A09": + if (valueList.Count == 3) + { + value = AnalyzeDataAccordingToA09(valueList[0], valueList[1], valueList[2]); + } + break; + case "A14": + if (valueList.Count == 5) + { + value = AnalyzeDataAccordingToA15(valueList[0], valueList[1], valueList[2], valueList[3], valueList[4]); + } + break; + case "A15": + if (valueList.Count == 5) + { + //var minutes = Convert.ToInt32(analyzeValue[0]); // 获取当前分钟数 + //var hours = Convert.ToInt32(analyzeValue[1]); // 获取当前小时数 + //var day = Convert.ToInt32(analyzeValue[2]); // 获取当前日期的日数 + //var month = Convert.ToInt32(analyzeValue[3]); // 获取当前月份 + //var year = Convert.ToInt32(analyzeValue[4]); // 获取当前日期的年份 + value = AnalyzeDataAccordingToA15(valueList[0], valueList[1], valueList[2], valueList[3], valueList[4]); + } + break; + case "ATd_d": + var day = valueList[0]; + var month = valueList[1]; + var year = valueList[2]; + break; + case "ATd_m": + var tdmMonth = valueList[0]; + var tdmYear = valueList[1]; + break; + } + + return value; + } + + /// + /// 解析透明转发 应答 + /// + /// + /// + /// + public virtual async Task AnalyzeTransparentForwardingAnswerAsync(MessageReceived messageReceivedEvent, Action? sendAction = null) + { + var hexDatas = GetHexData(messageReceivedEvent.MessageHexString); + + var port = hexDatas[0].HexToDec(); + + var count = hexDatas[1].HexToDec(); + + var dataList = hexDatas.Skip(2).Take(count).ToList(); + + //645 + if (dataList[0].IsStartStr() && dataList[hearderLen - 1].IsStartStr()) + { + + } + else if (dataList[0].IsStartStr())//188 水表只有开头是68 + { + AnalyzeWaterMeterReadData(dataList); + } + } + + /// + /// 解析透明转发 应答结果 + /// + /// + /// + /// + public virtual async Task AnalyzeTransparentForwardingAnswerResultAsync(MessageReceived messageReceived, Action? sendAction = null) + { + var hexDatas = GetHexData(messageReceived.MessageHexString); + + var port = hexDatas[0].HexToDec(); + + //A.12 + var a = hexDatas.Skip(1).Take(6).ToList(); + + var result = hexDatas.Skip(7).Take(1).FirstOrDefault().HexToDec(); + var transparentForwardingFlag = (TransparentForwardingFlagEnum)result; + } + + /// + /// 获取命令数据单元-数据体 + /// + /// + /// + public static List GetHexData(string messageHexString) + { + var hexStringList = messageHexString.StringToPairs(); + var analyzeValue = (List)hexStringList.GetAnalyzeValue(CommandChunkEnum.Data); + return analyzeValue; + } + + /// + /// 解析时间标签 + /// + /// + public void AnalysisTp(List hexData) + { + var pFC = hexData[0].HexToDec();//启动帧帧序号计数器 + var seconds = Convert.ToInt32(hexData[1]); // 获取当前秒数 + var minutes = Convert.ToInt32(hexData[2]); // 获取当前分钟数 + var hours = Convert.ToInt32(hexData[3]); // 获取当前小时数 + var day = Convert.ToInt32(hexData[4]); // 获取当前日期的日数 + var delayTime = hexData[5].HexToDec();//延迟时间 min + } + + #region 报文指定的数据格式 + + /// + /// 根据A05解析数据 + /// + /// 个位和十分位 + /// 百位和十位 + /// + public decimal AnalyzeDataAccordingToA05(string singleDigitNumberAndDeciles, string hundredDigitNumbersAndTenDigitNumber) + { + if (singleDigitNumberAndDeciles.IsErrorData() && hundredDigitNumbersAndTenDigitNumber.IsErrorData()) + { + return 0; + } + var bin1 = hundredDigitNumbersAndTenDigitNumber.HexToBin().PadLeft(8, '0'); + var hundredDigitNumbers = bin1.Substring(1, 3).BinToDec();//百位 + var tenDigitNumber = bin1.Substring(4).BinToDec();//十位 + + var bin2 = singleDigitNumberAndDeciles.HexToBin().PadLeft(8, '0'); + var singleDigitNumber = bin1.Substring(0, 4).BinToDec();//个位 + var deciles = bin1.Substring(4).BinToDec();//十分位 + + var value = decimal.Parse($"{hundredDigitNumbers}{tenDigitNumber}{singleDigitNumber}.{deciles}"); + return value; + } + + /// + /// 数据格式07 + /// + /// 个位、十分位 + /// 百位、十位 + /// + public decimal AnalyzeDataAccordingToA07(string singleDigitNumberAndDeciles, string hundredDigitNumbersAndTenDigitNumber) + { + if (singleDigitNumberAndDeciles.IsErrorData() && hundredDigitNumbersAndTenDigitNumber.IsErrorData()) + { + return 0; + } + var bin1 = hundredDigitNumbersAndTenDigitNumber.HexToBin().PadLeft(8, '0'); + var hundredDigitNumbers = bin1.Substring(1, 3).BinToDec();//百位 + var tenDigitNumber = bin1.Substring(4).BinToDec();//十位 + + var bin2 = singleDigitNumberAndDeciles.HexToBin().PadLeft(8, '0'); + var singleDigitNumber = bin2.Substring(0, 4).BinToDec();//个位 + var deciles = bin2.Substring(4).BinToDec();//十分位 + + var value = decimal.Parse($"{hundredDigitNumbers}{tenDigitNumber}{singleDigitNumber}.{deciles}"); + return value; + } + + /// + /// 数据格式09 + /// + /// 千分位和万分位 + /// 十分位和百分位 + /// 十位和个位 + /// + public decimal AnalyzeDataAccordingToA09(string thousandthPercentileAndTenThousandPositions, string decilesAndPercentile, string tenAndSingleDigit) + { + if (thousandthPercentileAndTenThousandPositions.IsErrorData() && decilesAndPercentile.IsErrorData() && tenAndSingleDigit.IsErrorData()) + { + return 0; + } + + var bin3 = tenAndSingleDigit.HexToBin().PadLeft(8, '0'); + var tenDigitNumber = bin3.Substring(1, 3).BinToDec();//十位 + var singleDigitNumber = bin3.Substring(4).BinToDec();//个位 + + var value = decimal.Parse($"{tenDigitNumber}{singleDigitNumber}.{decilesAndPercentile}{thousandthPercentileAndTenThousandPositions}"); + return value; + + //var bin3 = hex3.HexToBin().PadLeft(8, '0'); + //var thousandthPercentile = bin3.Substring(0, 4).BinToDec();//千分位 + //var tenThousandPositions = bin3.Substring(4).BinToDec();//万分位 + + //var bin2 = hex2.HexToBin().PadLeft(8, '0'); + //var deciles = bin2.Substring(0, 4).BinToDec();//十分位 + //var percentile = bin2.Substring(4).BinToDec();//百分位 + + + } + + /// + /// 数据格式12 + /// + /// 十位 个位 + /// 千位 百位 + /// 十万位 万位 + /// 千万位 百万位 + /// 十亿位 亿位 + /// 千亿位 百亿位 + /// + public string AnalyzeDataAccordingToA12(string tenDigitAndSingleDigitNumber, string thousandAndHundredsOfPosition, string hundredThousandAndTenThousandOfPosition, + string millionsAndMillionOfPosition, string hundredMillionAndBillionOfPosition, string hundredBillionsAndBillionsOfPosition) + { + var value = $"{hundredBillionsAndBillionsOfPosition}{hundredMillionAndBillionOfPosition}{millionsAndMillionOfPosition}" + + $"{hundredThousandAndTenThousandOfPosition}{thousandAndHundredsOfPosition}{tenDigitAndSingleDigitNumber}"; + + return value; + } + + /// + /// 数据格式14 + /// + /// 千分,万分 + /// 十分、百分 + /// 十位、个位 + /// 千位、百位 + /// 十万位、万位 + /// + public decimal AnalyzeDataAccordingToA14(string tenThousandPositionsAndThousandthPercentile, string decilesAndPercentile, + string tenDigitNumberAndSingleDigitNumber, string thousandAndHundredsOfPosition, string hundredThousandAndTenThousandOfPosition) + { + if (tenThousandPositionsAndThousandthPercentile.IsErrorData() && decilesAndPercentile.IsErrorData() && tenDigitNumberAndSingleDigitNumber.IsErrorData() + && thousandAndHundredsOfPosition.IsErrorData() && hundredThousandAndTenThousandOfPosition.IsErrorData()) + return 0; + + var value = decimal.Parse($"{hundredThousandAndTenThousandOfPosition}{thousandAndHundredsOfPosition}" + + $"{tenDigitNumberAndSingleDigitNumber}.{decilesAndPercentile}{tenThousandPositionsAndThousandthPercentile}"); + + return value; + } + + /// + /// 数据格式A.15 + /// + /// + /// + /// + /// + /// + /// + public DateTime AnalyzeDataAccordingToA15(string minuteHex, string hourHex, string dayHex, string monthHex, string yearHex) + { + var centuryString = (DateTime.Now.Year / 100).ToString(); + var time = DateTime.Parse($"{centuryString}{yearHex}-{monthHex}-{dayHex} {hourHex}:{minuteHex}:00"); + return time; + //正常转换方式 + //var bin1 = hex1.HexToBin().PadLeft(8, '0'); + //var tenDigitNumberOfMinute = bin1.Substring(0, 4).BinToDec();//十位 + //var singleDigitNumberOfMinute = bin1.Substring(4).BinToDec();//个位 + //var minute = Convert.ToInt32($"{tenDigitNumberOfMinute}{singleDigitNumberOfMinute}"); + + //var bin2 = hex2.HexToBin().PadLeft(8, '0'); + //var tenDigitNumberOfHour = bin2.Substring(0, 4).BinToDec();//十位 + //var singleDigitNumberOfHour = bin2.Substring(4).BinToDec();//个位 + + //var bin3 = hex3.HexToBin().PadLeft(8, '0'); + //var tenDigitNumberOfDay = bin3.Substring(0, 4).BinToDec();//十位 + //var singleDigitNumberOfDay = bin3.Substring(4).BinToDec();//个位 + + //var bin4 = hex4.HexToBin().PadLeft(8, '0'); + //var tenDigitNumberOfMonth = bin4.Substring(0, 4).BinToDec();//十位 + //var singleDigitNumberOfMonth = bin4.Substring(4).BinToDec();//个位 + + //var bin5 = hex5.HexToBin().PadLeft(8, '0'); + //var tenDigitNumberOfYear = bin5.Substring(0, 4).BinToDec();//十位 + //var singleDigitNumberOfYear = bin5.Substring(4).BinToDec();//个位 + } + + + /// + /// 数据格式20 + /// + /// + /// + /// + /// + public DateTime AnalyzeDataAccordingToA20(string dayHex, string monthHex, string yearHex) + { + var centuryString = (DateTime.Now.Year / 100).ToString(); + var time = DateTime.Parse($"{centuryString}{yearHex}-{monthHex}-{dayHex}"); + return time; + + } + + /// + /// 数据格式25 + /// + /// 百分、千分位 + /// 个位、十分位 + /// 百位、十位 + /// + + public decimal AnalyzeDataAccordingToA25(string percentileAndThousandthPercentile, string singleDigitNumberAndDeciles, string hundredDigitNumbersAndTenDigitNumber) + { + if (percentileAndThousandthPercentile.IsErrorData() && singleDigitNumberAndDeciles.IsErrorData() && hundredDigitNumbersAndTenDigitNumber.IsErrorData()) + return 0; + + var bin1 = hundredDigitNumbersAndTenDigitNumber.HexToBin().PadLeft(8, '0'); + var hundredDigitNumbers = bin1.Substring(1, 3).BinToDec();//百位 + var tenDigitNumber = bin1.Substring(4).BinToDec();//十位 + + var bin2 = singleDigitNumberAndDeciles.HexToBin().PadLeft(8, '0'); + var singleDigitNumber = bin2.Substring(0, 4).BinToDec();//个位 + var deciles = bin1.Substring(4).BinToDec();//十分位 + + var value = decimal.Parse($"{hundredDigitNumbers}{tenDigitNumber}{singleDigitNumber}.{deciles}{percentileAndThousandthPercentile}"); + return value; + } + + #endregion + + #region 645 + /// + /// 解析读取表地址 + /// + /// + /// + public List AnalyzeAmmeterReadMeterAddress_10_105(List dataList) + { + var values = new List(); + //表地址 + var addressList = dataList.GetRange(1, 6); + addressList.Reverse(); + var address = string.Join("", addressList); + values.Add(address); + //控制码 + var controlCode = dataList.GetRange(8, 1)[0]; + values.Add(controlCode); + //长度 + var len = dataList.GetRange(9, 1)[0].HexToDec(); + //values.Add(len.ToString()); + //数据域 + var dataField = dataList.GetRange(10, len); + if (dataField.Count > 0) + { + string dataMark = string.Join("", dataField.GetRange(0, 4).AddHex33()); + values.Add(dataMark);//数据标识 + var readValue = dataField.GetRange(4, len - 4).ReduceHex33();//值 + readValue.Reverse(); + //var valueData = GetValue>(readValue, (AppendixEnums)Enum.Parse(typeof(AppendixEnums), dataMark)); + values.AddRange(readValue); + } + return values; + } + + + public void AnalyzeAmmeterReadMeterAddress_10_103(List dataList) + { + var data = AnalyzeAmmeterReadMeterAddress_10_105(dataList); + var validData = data[2].Equals("94") ? true : false; + var remark = validData ? "成功" : "失败"; + } + + public void AnalyzeAutoUpSwtichRead_0A_68(List dataList) + { + var isOpen = dataList[4].Equals("55"); + } + + #endregion + + #region 188 + + public void AnalyzeWaterMeter188Data(List dataList) + { + var waterMeterType = dataList[(int)WaterMeterReadEnum.Type]; + var addressList = dataList.Skip((int)WaterMeterReadEnum.Address).Take(6).ToList(); + addressList.Reverse(); + var address = string.Join("", addressList); + address = address.Substring(address.Length - 12); + var controlCode = dataList[(int)WaterMeterReadEnum.ControlCode]; + switch (controlCode) + { + case "81": + AnalyzeWaterMeterReadData(dataList); + break; + case "84": + AnalyzeWaterMeterValueResult(dataList); + break; + } + + } + + /// + /// 解析水表读数据 + /// + /// + public void AnalyzeWaterMeterReadData(List dataList) + { + var accumulativeWaterflowList = dataList.Skip((int)WaterMeterReadEnum.AccumulativeWaterflow).Take(5).ToList(); + //xxxxxx.xx + var accumulativeWaterflow = decimal.Parse( + $"{accumulativeWaterflowList[3]}{accumulativeWaterflowList[2]}{accumulativeWaterflowList[1]}." + + $"{accumulativeWaterflowList[0]}"); + } + + /// + /// 解析水表阀控结果 + /// + /// + public bool AnalyzeWaterMeterValueResult(List dataList) + { + return true; + } + + #endregion + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Abstracts/ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol/Abstracts/ProtocolPlugin.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Abstracts/ProtocolPlugin.cs rename to protocols/JiShe.CollectBus.Protocol/Abstracts/ProtocolPlugin.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Adapters/StandardFixedHeaderDataHandlingAdapter.cs b/protocols/JiShe.CollectBus.Protocol/Adapters/StandardFixedHeaderDataHandlingAdapter.cs new file mode 100644 index 0000000..0984a8f --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Adapters/StandardFixedHeaderDataHandlingAdapter.cs @@ -0,0 +1,27 @@ +using JiShe.CollectBus.Protocol.Contracts.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Core; + +namespace JiShe.CollectBus.Protocol.Contracts.Adapters +{ + public class StandardFixedHeaderDataHandlingAdapter : CustomFixedHeaderDataHandlingAdapter + { + /// + /// 接口实现,指示固定包头长度 + /// + public override int HeaderLength => 3; + + /// + /// 获取新实例 + /// + /// + protected override CustomFixedHeaderRequestInfo GetInstance() + { + return new CustomFixedHeaderRequestInfo(); + } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisData/Appendix.cs b/protocols/JiShe.CollectBus.Protocol/AnalysisData/Appendix.cs new file mode 100644 index 0000000..f68268c --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/AnalysisData/Appendix.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JiShe.CollectBus.Common.Extensions; + +namespace JiShe.CollectBus.Protocol.Contracts.AnalysisData +{ + /// + /// 附录 + /// + public static class Appendix + { + /// + /// 附录1 A1格式 + /// + /// + public static string Appendix_A1(List data) + { + var seconds = data[0]; + var minutes = data[1]; + var hours = data[2]; + var day = data[3]; + var binString = data[4].HexToBin(); + var months = binString.Substring(3, 1).BinToDec() * 10 + Convert.ToInt32(binString.Substring(4, 4).BinToHex()); + var week = binString.Substring(0, 3).BinToHex(); + var year = $"{DateTime.Now.ToString("yyyy").Substring(0, 2)}{data[5]}"; + return $"{year}-{months.ToString().PadLeft(2, '0')}-{day} {hours}:{minutes}:{seconds}_{week}"; + } + + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs b/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs new file mode 100644 index 0000000..628934a --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/AnalysisStrategyContext.cs @@ -0,0 +1,33 @@ +using JiShe.CollectBus.Protocol.Contracts.Interfaces; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts +{ + + public class AnalysisStrategyContext(IServiceProvider provider) + { + private readonly IServiceProvider _provider = provider; + + /// + /// 执行策略 + /// + /// + /// + /// + /// + /// + public Task ExecuteAsync(string type, TInput input) + { + var factory = _provider.GetRequiredService>(); + var strategy = (IAnalysisStrategy)factory(type, typeof(TInput), typeof(TResult)); + return strategy.ExecuteAsync(input); + } + } + + +} diff --git a/protocols/JiShe.CollectBus.Protocol/Attributes/ProtocolNameAttribute.cs b/protocols/JiShe.CollectBus.Protocol/Attributes/ProtocolNameAttribute.cs new file mode 100644 index 0000000..a04af71 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Attributes/ProtocolNameAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace JiShe.CollectBus.Protocol.Contracts.Attributes +{ + [AttributeUsage(AttributeTargets.Class)] + public class ProtocolNameAttribute(string name) : Attribute + { + public string Name { get; set; } = name; + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/CollectBusProtocolModule.cs b/protocols/JiShe.CollectBus.Protocol/CollectBusProtocolModule.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/CollectBusProtocolModule.cs rename to protocols/JiShe.CollectBus.Protocol/CollectBusProtocolModule.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs b/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs new file mode 100644 index 0000000..dcd12fb --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Interfaces/IAnalysisStrategy.cs @@ -0,0 +1,15 @@ +using JiShe.CollectBus.Protocol.Contracts.Models; +using JiShe.CollectBus.Protocol.Dto; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Interfaces +{ + public interface IAnalysisStrategy + { + Task ExecuteAsync(TInput input); + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolService.cs b/protocols/JiShe.CollectBus.Protocol/Interfaces/IProtocolService.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolService.cs rename to protocols/JiShe.CollectBus.Protocol/Interfaces/IProtocolService.cs diff --git a/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj b/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj index 3a7cc07..495dbf1 100644 --- a/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj +++ b/protocols/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj @@ -4,24 +4,25 @@ net8.0 enable enable - - preview - - - + + + - - - + + + - - - + + + + + + diff --git a/protocols/JiShe.CollectBus.Protocol/Models/CustomFixedHeaderRequestInfo.cs b/protocols/JiShe.CollectBus.Protocol/Models/CustomFixedHeaderRequestInfo.cs new file mode 100644 index 0000000..61ea887 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Models/CustomFixedHeaderRequestInfo.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Core; + +namespace JiShe.CollectBus.Protocol.Contracts.Models +{ + public class CustomFixedHeaderRequestInfo : IFixedHeaderRequestInfo + { + /// + /// 报文开始前缀 + /// + public string StartPrefix { get; set; } = "68"; + + /// + /// 报文结束后缀 + /// + public string EndPrefix { get; set; } = "16"; + + /// + /// 头部长度 + /// + public int HeadLength = 5; + + /// + /// 固定长度 + /// + private const int FixedLength = 17; + + /// + /// 报文长度 + /// + public int PacketLength { get; set; } + + /// + /// 控制域 C + /// + public int ControlDomain { get; set; } + + public bool OnParsingHeader(ReadOnlySpan header) + { + //throw new NotImplementedException(); + return true; + } + + public bool OnParsingBody(ReadOnlySpan body) + { + //throw new NotImplementedException(); + return true; + + } + + public int BodyLength { get; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Models/ProtocolBuildRequest.cs b/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildRequest.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Models/ProtocolBuildRequest.cs rename to protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildRequest.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Models/ProtocolBuildResponse.cs b/protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildResponse.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Models/ProtocolBuildResponse.cs rename to protocols/JiShe.CollectBus.Protocol/Models/ProtocolBuildResponse.cs diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Models/SubProtocolBuildRequest.cs b/protocols/JiShe.CollectBus.Protocol/Models/SubProtocolBuildRequest.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Models/SubProtocolBuildRequest.cs rename to protocols/JiShe.CollectBus.Protocol/Models/SubProtocolBuildRequest.cs diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN10_F10_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN10_F10_AnalysisDto.cs new file mode 100644 index 0000000..46b7581 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN10_F10_AnalysisDto.cs @@ -0,0 +1,95 @@ +using JiShe.CollectBus.Protocol.Dto; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN10_F10_AnalysisDto + { + /// + /// 本次电能表/交流采样装置配置数量 n + /// + public int ConfigNum { get; set; } + + /// + /// 电能表/交流采样装置配置信息 + /// + public List AFN10F10Entitys { get; set; } = new List(); + } + + + public class AFN10F10Entity + { + /// + /// 电能表/交流采样装置序号 + /// + public int SerialNum { get; set; } + + /// + /// 所属测量点号 + /// + public int Point { get; set; } + + /// + /// 通信速率 + /// + public int BaudRate { get; set; } + + /// + /// 端口号 + /// + public int Port { get; set; } + + + /// + /// 通信协议类型 + /// + public string RuleType { get; set; } + + /// + /// 通信地址 + /// + public string ComAddress { get; set; } + + /// + /// 通信密码 + /// + public string ComPwd { get; set; } + + + /// + /// 电能费率个数 + /// + public int ElectricityRatesNum { get; set; } + + + /// + /// 有功电能示值整数位及小数位个数 + /// + public int IntegerBitsNum { get; set; } + + /// + /// 有功电能示值小数位个数 + /// + public int DecimalPlacesNum { get; set; } + + /// + /// 所属采集器通信地址 + /// + public string CollectorAddress{ get; set; } + + /// + /// 用户大类号 + /// + public int UserCategoryNum { get; set;} + + /// + /// 用户小类号 + /// + public int UserSubclassNum { get; set; } + } + +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN10_F66_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN10_F66_AnalysisDto.cs new file mode 100644 index 0000000..c3c8306 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN10_F66_AnalysisDto.cs @@ -0,0 +1,45 @@ +using JiShe.CollectBus.Protocol.Dto; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN10_F66_AnalysisDto + { + /// + /// 定时发送周期 + /// 1:用 D6~D7 编码表示,取值 0~3 依次表示分、时、日、月 + /// 2:用 D0~D5 表示,为定时上报数据的时间周期 + /// + public int Cycle { get; set; } + /// + /// 定时发送周期(单位) + /// + public int Unit { get; set; } + /// + /// 发送基准时间 + /// + public DateTime BaseTime { get; set; } + + /// + /// 曲线数据提取倍率 + /// + public int CurveRatio { get; set; } + + /// + /// 任务号 + /// + public int Pn { get; set; } + + public List Details { get; set; } = new List(); + } + + public class SetAutoItemCodeDetails + { + public int Pn { get; set; } + public int Fn { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F129_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F129_AnalysisDto.cs new file mode 100644 index 0000000..30719e9 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F129_AnalysisDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F129_AnalysisDto : AnalysisBaseDto + { + public DateTime ReadTime { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F130_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F130_AnalysisDto.cs new file mode 100644 index 0000000..9a9259b --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F130_AnalysisDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F130_AnalysisDto : AnalysisBaseDto + { + public DateTime ReadTime { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F131_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F131_AnalysisDto.cs new file mode 100644 index 0000000..edc5ca7 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F131_AnalysisDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F131_AnalysisDto: AnalysisBaseDto + { + public DateTime ReadTime { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F132_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F132_AnalysisDto.cs new file mode 100644 index 0000000..1625f15 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F132_AnalysisDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F132_AnalysisDto: AnalysisBaseDto + { + public DateTime ReadTime { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F145_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F145_AnalysisDto.cs new file mode 100644 index 0000000..96f0c37 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F145_AnalysisDto.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F145_AnalysisDto : AnalysisBaseDto + { + /// + /// 最大需量时标 + /// + public string TimeSpan { get; set; } + + public DateTime ReadingDate { get; set; } + } + +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F149_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F149_AnalysisDto.cs new file mode 100644 index 0000000..fb9dafe --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F149_AnalysisDto.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F149_AnalysisDto : AnalysisBaseDto + { + /// + /// 最大需量时标 + /// + public string TimeSpan { get; set; } + + public DateTime ReadingDate { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F188_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F188_AnalysisDto.cs new file mode 100644 index 0000000..1afb8ff --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F188_AnalysisDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F188_AnalysisDto : AnalysisBaseDto + { + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F25_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F25_AnalysisDto.cs new file mode 100644 index 0000000..ca8b8ff --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F25_AnalysisDto.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F25_AnalysisDto: AnalysisBaseDto + { + /// + /// 读取时间 + /// + public DateTime ReadTime { get; set; } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F2_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F2_AnalysisDto.cs new file mode 100644 index 0000000..e069382 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F2_AnalysisDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F2_AnalysisDto: AnalysisBaseDto + { + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F33_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F33_AnalysisDto.cs new file mode 100644 index 0000000..b917969 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F33_AnalysisDto.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F33_AnalysisDto + { + /// + /// 终端抄表时间 + /// + public string ReadTime { get; set; } + + /// + /// 费率数M(1≤M≤12) + /// + public int RatingCount { get; set; } + /// + /// 当前正向有功总电能示值 + /// + public ParentNodes F_A_Kwh { get; set; } + /// + /// 当前正向无功(组合无功1)总电能示值 + /// + public ParentNodes R_R_Kvarh { get; set; } + + /// + /// 当前一象限无功总电能示值 + /// + public ParentNodes Q1_R_Kvarh { get; set; } + /// + /// 当前四象限无功总电能示值 + /// + public ParentNodes Q4_R_Kvarh { get; set; } + } + + public class ParentNodes + { + /// + /// 总电能示值 + /// + public decimal Total_Value { get; set; } + public List childNodes { get; set; } + } + public class ChildNodes + { + /// + /// 费率总电能示值 + /// + public decimal Value { get; set; } + + } +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F49_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F49_AnalysisDto.cs new file mode 100644 index 0000000..ce0aeb7 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN12_F49_AnalysisDto.cs @@ -0,0 +1,15 @@ +using JiShe.CollectBus.Protocol.Dto; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN12_F49_AnalysisDto: AnalysisBaseDto + { + } + + +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN9_F1_AnalysisDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN9_F1_AnalysisDto.cs new file mode 100644 index 0000000..7b7bc3a --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AFN9_F1_AnalysisDto.cs @@ -0,0 +1,38 @@ +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AFN9_F1_AnalysisDto + { + public int FocusID { get; set; } + public string? AreaCode { get; set; } + public string? Address { get; set; } + + /// + /// 厂商代号 + /// + public string? MakerNo { get; set; } + /// + /// 设备编号 + /// + public string? DeviceNo { get; set; } + /// + /// 终端软件版本号 + /// + public string? SoftwareVersion { get; set; } + /// + /// 终端软件发布日期:日月年 + /// + public string? SoftwareReleaseDate { get; set; } + + /// + /// 硬件软件版本号 + /// + public string? HardwareVersion { get; set; } + /// + /// 硬件软件发布日期:日月年 + /// + public string? HardwareReleaseDate { get; set; } + + public string? AddDate { get; set; } + } + +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AnalysisBaseDto.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AnalysisBaseDto.cs new file mode 100644 index 0000000..49f9054 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/AnalysisBaseDto.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Protocol.Contracts.Protocol.Dto +{ + public class AnalysisBaseDto + { + + /// + /// 是否有效数据 + /// + public bool ValidData { get; set; } = true; + + /// + /// 数据类型 + /// + public string DataType { get; set; } + + /// + /// 错误码信息 + /// + public string ErrorCodeMsg { get; set; } + + /// + /// 字段名 + /// + public string FiledName { get; set; } + + /// + /// 字段描述 + /// + public string FiledDesc { get; set; } + } + + public class AnalysisBaseDto : AnalysisBaseDto + { + /// + /// 抄读值 + /// + public T? DataValue { get; set; } + } + +} diff --git a/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/UnitDataAnalysis.cs b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/UnitDataAnalysis.cs new file mode 100644 index 0000000..3a03923 --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/Protocol/Dto/UnitDataAnalysis.cs @@ -0,0 +1,36 @@ +namespace JiShe.CollectBus.Protocol.Dto +{ + public class UnitDataAnalysis + { + /// + /// 集中器地址 + /// + public string? Code { get; set; } + + /// + /// AFN功能码 + /// + public int AFN { get; set; } + + /// + /// 信息点 + /// + public int Pn { get; set; } + + /// + /// 信息类 + /// + public int Fn { get; set; } + + + } + + public class UnitDataAnalysis: UnitDataAnalysis + { + /// + /// 数据 + /// + public T? Data { get; set; } + } + +} diff --git a/protocols/JiShe.CollectBus.Protocol/QGDW3761Config.cs b/protocols/JiShe.CollectBus.Protocol/QGDW3761Config.cs new file mode 100644 index 0000000..88f6bcb --- /dev/null +++ b/protocols/JiShe.CollectBus.Protocol/QGDW3761Config.cs @@ -0,0 +1,70 @@ +using JiShe.CollectBus.Protocol.Contracts.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using JiShe.CollectBus.Common.Extensions; + +namespace JiShe.CollectBus.Protocol.Contracts +{ + public class QGDW3761Config + { + private static List _commandList = null; + public static List CommandList + { + get + { + if (_commandList == null) + { + var filePath = AppDomain.CurrentDomain.BaseDirectory + "cmd3761Matching.txt"; + + try + { + var fileStr = ""; + if (File.Exists(filePath)) + fileStr = File.ReadAllText(filePath, Encoding.UTF8); + + if (!string.IsNullOrWhiteSpace(fileStr)) + { + _commandList = fileStr.FromJson>(); + } + } + catch (Exception) + { + + } + } + return _commandList; + } + } + + private static List _commandTdcList = null; + public static List CommandTdcList + { + get + { + if (_commandTdcList == null) + { + var filePath = AppDomain.CurrentDomain.BaseDirectory + "cmd3761TdcMatching.txt"; + + try + { + var fileStr = ""; + if (File.Exists(filePath)) + fileStr = File.ReadAllText(filePath, Encoding.UTF8); + + if (!string.IsNullOrWhiteSpace(fileStr)) + { + _commandTdcList = fileStr.FromJson>(); + } + } + catch (Exception) + { + + } + } + return _commandTdcList; + } + } + } +} diff --git a/protocols/JiShe.CollectBus.Protocol.Contracts/Services/ProtocolService.cs b/protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs similarity index 100% rename from protocols/JiShe.CollectBus.Protocol.Contracts/Services/ProtocolService.cs rename to protocols/JiShe.CollectBus.Protocol/Services/ProtocolService.cs diff --git a/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs index 6dec9db..9d64747 100644 --- a/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application.Contracts/ScheduledMeterReading/IScheduledMeterReadingService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using JiShe.CollectBus.Ammeters; using JiShe.CollectBus.GatherItem; @@ -72,6 +73,13 @@ namespace JiShe.CollectBus.ScheduledMeterReading /// Task AmmeterScheduledAutoValveControl(); + /// + /// 电表自动校时 + /// + /// 采集频率 + /// + Task AmmeterScheduledAutomaticVerificationTime(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps); + #endregion diff --git a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj index b97fd0f..6f71f34 100644 --- a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj +++ b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj @@ -22,7 +22,6 @@ - diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index 750b938..7173813 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -138,6 +138,27 @@ namespace JiShe.CollectBus.ScheduledMeterReading timeDensity = 15; } + + //电表定时广播校时,一天一次。 + string currentTimeStr = $"{currentTime:HH:mm:00}"; + //判断是否是自动校时时间 + if (!string.Equals(currentTimeStr, _applicationOptions.AutomaticVerificationTime, StringComparison.CurrentCultureIgnoreCase)) + { + _logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); + return; + } + else + { + _ = CreateMeterPublishTask( + timeDensity: timeDensity, + nextTaskTime: currentTime, + meterType: MeterTypeEnum.Ammeter, + taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => + { + await AmmeterScheduledAutomaticVerificationTime(timeDensity, data, groupIndex, timestamps); + }); + } + //检查任务时间节点,由于定时任务10秒钟运行一次,需要判定当前时间是否在任务时间节点内,不在则跳过 if (!IsTaskTime(tasksToBeIssueModel.NextTaskTime, timeDensity)) { @@ -198,11 +219,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading //根据当前的采集频率和类型,重新更新下一个任务点,把任务的创建源固定在当前逻辑,避免任务处理的逻辑异常导致任务创建失败。 tasksToBeIssueModel.LastTaskTime = currentTaskTime; tasksToBeIssueModel.NextTaskTime = currentTaskTime.CalculateNextCollectionTime(timeDensity); - await FreeRedisProvider.Instance.SetAsync(item, tasksToBeIssueModel); + await FreeRedisProvider.Instance.SetAsync(item, tasksToBeIssueModel); } //电表定时阀控任务处理。 - //电表定时广播校时,一天一次。 + _= AmmeterScheduledAutoValveControl(); + } #region 电表采集处理 @@ -695,6 +717,110 @@ namespace JiShe.CollectBus.ScheduledMeterReading throw new NotImplementedException($"{nameof(AmmeterScheduledAutoValveControl)}请根据不同系统类型进行实现"); } + /// + /// 电表自动校时 + /// + /// 采集频率 + /// 电表信息 + /// 集中器所在分组 + /// 采集频率对应的时间戳 + /// + public virtual async Task AmmeterScheduledAutomaticVerificationTime(int timeDensity, AmmeterInfo ammeterInfo, int groupIndex, DateTime timestamps) + { + var currentTime = DateTime.Now; + string currentTimeStr = $"{currentTime:HH:mm:00}"; + + try + { + //判断是否是自动校时时间 + if (!string.Equals(currentTimeStr , _applicationOptions.AutomaticVerificationTime,StringComparison.CurrentCultureIgnoreCase)) + { + _logger.LogInformation($"{nameof(AmmeterScheduledAutomaticVerificationTime)} 电表自动校时,非自动校时时间"); + return; + } + + List taskList = new List(); + var metadata = await _dbProvider.GetMetadata(); + + var temCode = "10_01"; + + //根据电表型号获取协议插件 + var protocolPlugin = await _protocolService.GetProtocolServiceAsync(ammeterInfo.BrandType); + if (protocolPlugin == null) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有找到对应的协议组件,-105"); + return; + } + + ProtocolBuildResponse builderResponse = await protocolPlugin.BuildAsync(new ProtocolBuildRequest() + { + FocusAddress = ammeterInfo.FocusAddress, + Pn = ammeterInfo.MeteringCode, + ItemCode = temCode, + SubProtocolRequest = new SubProtocolBuildRequest() + { + MeterAddress = ammeterInfo.AmmerterAddress, + Password = ammeterInfo.Password, + ItemCode = T645PacketItemCodeConst.C08, + } + }); + + string taskMark = CommonHelper.GetTaskMark(builderResponse.AFn, builderResponse.Fn, ammeterInfo.MeteringCode, builderResponse.MSA, builderResponse.Seq); + var meterReadingRecords = new MeterReadingTelemetryPacketInfo() + { + SystemName = SystemType, + ProjectId = $"{ammeterInfo.ProjectID}", + DeviceType = $"{MeterTypeEnum.Ammeter}", + DeviceId = $"{ammeterInfo.MeterId}", + Timestamps = currentTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), + DatabaseBusiID = ammeterInfo.DatabaseBusiID, + PendingCopyReadTime = currentTime, + CreationTime = currentTime, + MeterAddress = ammeterInfo.AmmerterAddress, + AFN = builderResponse.AFn, + Fn = builderResponse.Fn, + Seq = builderResponse.Seq, + MSA = builderResponse.MSA, + ItemCode = temCode, + TaskMark = taskMark, + IsSend = false, + ManualOrNot = false, + Pn = ammeterInfo.MeteringCode, + IssuedMessageId = GuidGenerator.Create().ToString(), + IssuedMessageHexString = Convert.ToHexString(builderResponse.Data), + IsReceived = false, + ScoreValue = $"{ammeterInfo.FocusAddress}.{taskMark}".Md5Fun(), + }; + taskList.Add(meterReadingRecords); + + if (taskList == null || taskList.Count <= 0) + { + _logger.LogError($"{nameof(AmmeterScheduledAutoValveControl)} 定时阀控运行时间{currentTime}没有自动阀控任务生成,-106"); + return; + } + + //任务记录入库 + await _dbProvider.BatchInsertAsync(metadata, taskList); + + //任务信息推送Kafka + _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( + items: taskList, + deviceIdSelector: data => data.DeviceId, + processor: (data, groupIndex) => + { + _ = KafkaProducerIssuedMessageAction(ProtocolConst.AmmeterSubscriberWorkerOtherIssuedEventName, data, groupIndex); + } + ); + + //todo 阀控记录入库,推送到新的服务 + } + catch (Exception) + { + + throw; + } + } + #endregion diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs index fbe667a..d451b2a 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/EnergySystemScheduledMeterReadingService.cs @@ -311,7 +311,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading } //任务记录入库 - _ = _dbProvider.BatchInsertAsync(metadata, taskList); + await _dbProvider.BatchInsertAsync(metadata, taskList); //任务信息推送Kafka _ = DeviceGroupBalanceControl.ProcessWithThrottleAsync( diff --git a/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs b/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs index 5f8e441..6af0fd0 100644 --- a/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/ProtocolConst.cs @@ -47,7 +47,7 @@ namespace JiShe.CollectBus.Common.Consts public const string AmmeterSubscriberWorkerFifteenMinuteIssuedEventName = "issued.auto.fifteen.ammeter.event"; /// - /// 其他采集数据下行消息主题,日冻结,月冻结、集中器版本号控等 + /// 其他采集数据下行消息主题,日冻结,月冻结、集中器版本号、SIM卡号、定时校时等 /// public const string AmmeterSubscriberWorkerOtherIssuedEventName = "issued.auto.other.ammeter.event"; diff --git a/shared/JiShe.CollectBus.Common/Consts/T645PacketItemCodeConst.cs b/shared/JiShe.CollectBus.Common/Consts/T645PacketItemCodeConst.cs index 449ef9a..3b94e07 100644 --- a/shared/JiShe.CollectBus.Common/Consts/T645PacketItemCodeConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/T645PacketItemCodeConst.cs @@ -11,6 +11,7 @@ namespace JiShe.CollectBus.Common.Consts /// public class T645PacketItemCodeConst { + #region 下行报文编码 #region 跳合闸、报警、保电 /// /// 跳闸 @@ -55,5 +56,6 @@ namespace JiShe.CollectBus.Common.Consts /// public const string C08 = "08"; #endregion + #endregion } }