From acd061b9ee66c84550f9338ba26c41274ba92f42 Mon Sep 17 00:00:00 2001
From: cli <377476583@qq.com>
Date: Tue, 29 Oct 2024 16:28:14 +0800
Subject: [PATCH] xiugai daima
---
JiShe.CollectBus.Common/DataConvert.cs | 176 ----
.../Enums/376Enums.cs | 6 +-
.../Enums/CommandChunkEnum.cs | 15 +
.../Extensions/HexStringExtensions.cs | 78 ++
.../Extensions/IntExtensions.cs | 30 +
.../Extensions/StringExtensions.cs | 173 +++-
.../Models/CommandReuslt.cs | 8 +-
.../DependencyInjectionExtensions.cs | 6 +-
.../JiShe.CollectBus.Console.csproj | 6 +
JiShe.CollectBus.Console/Program.cs | 26 +-
JiShe.CollectBus.Console/appsettings.json | 27 +
JiShe.CollectBus.Core/Plugins/ClosePlugin.cs | 5 +-
.../Plugins/TcpServiceReceivedPlugin.cs | 58 +-
JiShe.CollectBus.Core/Services/BusService.cs | 15 +-
.../Abstracts/BaseProtocolPlugin.cs | 334 +++++++-
.../Interfaces/IProtocolPlugin.cs | 9 +-
.../Models/MessageReceivedEvent.cs | 23 +
.../Models/ReqParameter.cs | 2 +
.../TestProtocolPlugin.cs | 7 +-
.../StandardProtocolPlugin.cs | 787 +-----------------
.../Consumers/MessageIssuedConsumer.cs | 6 +-
.../MessageReceivedHeartbeatConsumer.cs | 35 +
.../Consumers/MessageReceivedLoginConsumer.cs | 35 +
.../JiSheCollectBusRabbitMqModule.cs | 19 +-
JiShe.CollectBus.RabbitMQ/Senders/INSender.cs | 4 +
JiShe.CollectBus.RabbitMQ/Senders/NSender.cs | 20 +
26 files changed, 910 insertions(+), 1000 deletions(-)
delete mode 100644 JiShe.CollectBus.Common/DataConvert.cs
rename JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs => JiShe.CollectBus.Common/Enums/376Enums.cs (96%)
create mode 100644 JiShe.CollectBus.Common/Enums/CommandChunkEnum.cs
create mode 100644 JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs
create mode 100644 JiShe.CollectBus.Common/Extensions/IntExtensions.cs
rename {JiShe.CollectBus.Protocol.Contracts => JiShe.CollectBus.Common}/Models/CommandReuslt.cs (85%)
create mode 100644 JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedHeartbeatConsumer.cs
create mode 100644 JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedLoginConsumer.cs
diff --git a/JiShe.CollectBus.Common/DataConvert.cs b/JiShe.CollectBus.Common/DataConvert.cs
deleted file mode 100644
index 71d2fcf..0000000
--- a/JiShe.CollectBus.Common/DataConvert.cs
+++ /dev/null
@@ -1,176 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.RegularExpressions;
-
-namespace JiShe.CollectBus.Common
-{
- public class DataConvert
- {
- ///
- /// 十进制转二进制
- ///
- /// 十进制数
- ///
- public static string DecToBin(int decimalNumber)
- {
- var binaryString = Convert.ToString(decimalNumber, 2);
- return binaryString;
- }
-
- ///
- /// 二进制转十六进制
- ///
- ///
- ///
- public static string BinToHex(string binaryString)
- {
- var decimalNumber = Convert.ToInt32(binaryString, 2);// 将二进制字符串转换为整数
- var hexString = Convert.ToString(decimalNumber, 16); //decimalNumber.ToString("X"); // 将整数转换为十六进制字符串
- return hexString;
- }
-
- ///
- /// 十进制转十六进制
- ///
- ///
- ///
- public static string DecToHex(int decimalNumber)
- {
- var hexString = decimalNumber.ToString("X");
- return hexString;
- }
-
- ///
- /// 二进制转十进制
- ///
- ///
- ///
- public static int BinToDec(string binaryString)
- {
- var decimalNumber = Convert.ToInt32(binaryString, 2);
- return decimalNumber;
- }
-
- ///
- /// 十六进制转十进制
- ///
- ///
- ///
- public static int HexToDec(string hexString)
- {
- var decimalNumber = Convert.ToInt32(hexString, 16);
- return decimalNumber;
- }
-
- ///
- /// 十六进制转二进制
- ///
- ///
- ///
- public static string HexToBin(string hexString)
- {
- var binaryValue = Convert.ToString(Convert.ToInt32(hexString, 16), 2);
- return binaryValue;
- }
-
-
- ///
- /// 字符串倒序
- ///
- ///
- ///
- public static string StringReversed(string str)
- {
- var reversed = new string(str.Reverse().ToArray());
- return reversed;
- }
-
- ///
- /// 字符串分割成2个字符一组
- ///
- ///
- ///
- public static List StringToPairs(string str)
- {
- var pairs = str.Select((ch, index) => new { ch, index })
- .GroupBy(x => x.index / 2)
- .Select(g => string.Concat(g.Select(x => x.ch)))
- .ToList();
- return pairs;
- }
-
- ///
- /// 格式化字符串
- ///
- ///
- ///
- public static string StrAddSpan(string str)
- {
- if (str == "")
- {
- return "";
- }
- return Regex.Replace(str.Replace(" ", ""), @"(?<=[0-9A-Za-z]{2})[0-9A-Za-z]{2}", " $0").Trim();
- }
-
- ///
- /// 格式化字符串且反转
- ///
- ///
- ///
- public static string StrReverseOrder(string ste)
- {
- if (ste == "")
- {
- return "";
- }
- string[] strArr = ste.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries);
-
- return string.Join(" ", strArr.Reverse());
- }
-
- ///
- /// 数据值加33
- ///
- ///
- ///
- public static string StrAddHex33(string str)
- {
- if (str == "")
- {
- return "";
- }
- string[] strArr = str.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries);
- for (int i = 0; i < strArr.Length; i++)
- {
- strArr[i] = (Convert.ToInt32(strArr[i], 16) + Convert.ToInt32("33", 16)).ToString("X2");
- if (strArr[i].Length > 2)
- {
- strArr[i] = strArr[i].Substring(strArr[i].Length - 2);
- }
- }
- return string.Join(" ", strArr);
- }
-
- private static string AddHex33(string strGet)
- {
- string result;
- if (string.IsNullOrEmpty(strGet))
- {
- result = "";
- }
- else
- {
- string[] source = StrAddSpan(strGet).Split(new char[]
- {
- ' '
- }, StringSplitOptions.RemoveEmptyEntries);
- result = string.Join("", from s in source
- select (Convert.ToInt32(s, 16) + Convert.ToInt32("33", 16)).ToString("X2"));
- }
- return result;
- }
-
- }
-}
diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs b/JiShe.CollectBus.Common/Enums/376Enums.cs
similarity index 96%
rename from JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs
rename to JiShe.CollectBus.Common/Enums/376Enums.cs
index 878d45c..0f10f0d 100644
--- a/JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs
+++ b/JiShe.CollectBus.Common/Enums/376Enums.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace JiShe.CollectBus.Protocol.Contracts.Models
+namespace JiShe.CollectBus.Common.Enums
{
///
/// 规约标识 高位在前 D1+D0
diff --git a/JiShe.CollectBus.Common/Enums/CommandChunkEnum.cs b/JiShe.CollectBus.Common/Enums/CommandChunkEnum.cs
new file mode 100644
index 0000000..55e02fa
--- /dev/null
+++ b/JiShe.CollectBus.Common/Enums/CommandChunkEnum.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JiShe.CollectBus.Common.Enums
+{
+ public enum CommandChunkEnum
+ {
+ C = 6,
+ A = 7,
+ AFN = 12,
+ SEQ = 13,
+ FN = 17,
+ }
+}
diff --git a/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs b/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs
new file mode 100644
index 0000000..f223188
--- /dev/null
+++ b/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs
@@ -0,0 +1,78 @@
+using JiShe.CollectBus.Common.Enums;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using JiShe.CollectBus.Common.Models;
+using System.Runtime.CompilerServices;
+
+namespace JiShe.CollectBus.Common.Extensions
+{
+ public static class HexStringExtensions
+ {
+ //起始字符
+ private const string startStr = "68";
+ //结束字符
+ private const string endStr = "16";
+ //头部字节长度
+ private const int hearderLen = 6;
+ //消息认证码字段长度
+ private const int pWLen = 16;
+
+ private const int tPLen = 6;
+
+ private const int FixedLength = 18;
+
+
+ public static object GetAnalyzeValue(this List hexStringList, CommandChunkEnum chunk)
+ {
+ if (hexStringList.Count < hearderLen || hexStringList[0] != startStr || hexStringList[5] != startStr || hexStringList.Count < FixedLength)
+ {
+ return null;
+ }
+
+ switch (chunk)
+ {
+ case CommandChunkEnum.AFN:
+ var aFn = hexStringList[(int)CommandChunkEnum.AFN].HexToDec();//1字节
+ return aFn;
+ case CommandChunkEnum.FN:
+ //(DT2*8)+DT1=fn
+ var dt1Bin = hexStringList[(int)CommandChunkEnum.FN - 1].HexToBin();
+ var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0;
+ var dt2 = hexStringList[(int)CommandChunkEnum.FN].HexToDec();
+ var fn = dt2 * 8 + dt1;
+ return fn;
+ case CommandChunkEnum.A:
+ var aHexList = hexStringList.Skip((int)CommandChunkEnum.A).Take(5).ToList();
+ 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')}";
+ var a3Bin = aHexList[4].HexToBin().PadLeft(8, '0');
+ var msa = a3Bin.Substring(0, 7).BinToDec();
+ return new Tuple(a, msa);
+ case CommandChunkEnum.SEQ:
+ var seq = hexStringList[(int)CommandChunkEnum.SEQ].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);
+ return new Seq
+ {
+ CON = con,
+ FIRFIN = firfin,
+ PRSEQ = prseqBin.BinToDec(),
+ TpV = tpV
+ };
+ default:
+ throw new ArgumentOutOfRangeException(nameof(chunk), chunk, null);
+ }
+ }
+
+
+ }
+}
diff --git a/JiShe.CollectBus.Common/Extensions/IntExtensions.cs b/JiShe.CollectBus.Common/Extensions/IntExtensions.cs
new file mode 100644
index 0000000..e92a5d9
--- /dev/null
+++ b/JiShe.CollectBus.Common/Extensions/IntExtensions.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace JiShe.CollectBus.Common.Extensions
+{
+ public static class IntExtensions
+ {
+ ///
+ /// 十进制转二进制
+ ///
+ /// 十进制数
+ ///
+ public static string DecToBin(this int decimalNumber)
+ {
+ var binaryString = Convert.ToString(decimalNumber, 2);
+ return binaryString;
+ }
+
+
+ ///
+ /// 十进制转十六进制
+ ///
+ ///
+ ///
+ public static string DecToHex(this int decimalNumber)
+ {
+ var hexString = decimalNumber.ToString("X");
+ return hexString;
+ }
+ }
+}
diff --git a/JiShe.CollectBus.Common/Extensions/StringExtensions.cs b/JiShe.CollectBus.Common/Extensions/StringExtensions.cs
index 21e9e19..3653956 100644
--- a/JiShe.CollectBus.Common/Extensions/StringExtensions.cs
+++ b/JiShe.CollectBus.Common/Extensions/StringExtensions.cs
@@ -47,38 +47,6 @@ namespace JiShe.CollectBus.Common.Extensions
return string.Copy(str);
}
- /// Gets the phone number.
- /// The string.
- /// The pattern.
- ///
- ///
- ///
- [Description("获取单个手机号")]
- public static string GetPhoneNumber(this string str, string pattern = RegexConst.PhoneNumber)
- {
- var reg = new Regex(pattern);
- var match = reg.Match(str);
- if (match.Success)
- {
- return match.Value;
- }
- return null;
- }
-
- /// Gets the phone numbers.
- /// The string.
- /// The pattern.
- ///
- ///
- ///
- [Description("获取全部手机号")]
- public static List GetPhoneNumbers(this string str, string pattern = RegexConst.PhoneNumber)
- {
- var reg = new Regex(pattern);
- var matches = reg.Matches(str);
- return (from Match item in matches select item.Value).ToList();
- }
-
/// Regex Match the specified pattern.
/// The string.
/// The pattern.
@@ -1106,6 +1074,147 @@ namespace JiShe.CollectBus.Common.Extensions
return string.Join(",", list) == intStr;
}
+ ///
+ /// 字符串倒序
+ ///
+ ///
+ ///
+ public static string StringReversed(this string str)
+ {
+ var reversed = new string(str.Reverse().ToArray());
+ return reversed;
+ }
+
+ ///
+ /// 字符串分割成2个字符一组
+ ///
+ ///
+ ///
+ public static List StringToPairs(this string str)
+ {
+ var pairs = str.Select((ch, index) => new { ch, index })
+ .GroupBy(x => x.index / 2)
+ .Select(g => string.Concat(g.Select(x => x.ch)))
+ .ToList();
+ return pairs;
+ }
+
+ ///
+ /// 格式化字符串
+ ///
+ ///
+ ///
+ public static string StrAddSpan(this string str)
+ {
+ if (str == "")
+ {
+ return "";
+ }
+ return Regex.Replace(str.Replace(" ", ""), @"(?<=[0-9A-Za-z]{2})[0-9A-Za-z]{2}", " $0").Trim();
+ }
+
+ ///
+ /// 格式化字符串且反转
+ ///
+ ///
+ ///
+ public static string StrReverseOrder(this string ste)
+ {
+ if (ste == "")
+ {
+ return "";
+ }
+ string[] strArr = ste.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries);
+
+ return string.Join(" ", strArr.Reverse());
+ }
+
+ ///
+ /// 二进制转十六进制
+ ///
+ ///
+ ///
+ public static string BinToHex(this string binaryString)
+ {
+ var decimalNumber = Convert.ToInt32(binaryString, 2);// 将二进制字符串转换为整数
+ var hexString = Convert.ToString(decimalNumber, 16); //decimalNumber.ToString("X"); // 将整数转换为十六进制字符串
+ return hexString;
+ }
+
+
+ ///
+ /// 二进制转十进制
+ ///
+ ///
+ ///
+ public static int BinToDec(this string binaryString)
+ {
+ var decimalNumber = Convert.ToInt32(binaryString, 2);
+ return decimalNumber;
+ }
+
+ ///
+ /// 十六进制转十进制
+ ///
+ ///
+ ///
+ public static int HexToDec(this string hexString)
+ {
+ var decimalNumber = Convert.ToInt32(hexString, 16);
+ return decimalNumber;
+ }
+
+ ///
+ /// 十六进制转二进制
+ ///
+ ///
+ ///
+ public static string HexToBin(this string hexString)
+ {
+ var binaryValue = Convert.ToString(Convert.ToInt32(hexString, 16), 2);
+ return binaryValue;
+ }
+
+ ///
+ /// 数据值加33
+ ///
+ public static string StrAddHex33(this string str)
+ {
+ if (str == "")
+ {
+ return "";
+ }
+ var strArr = str.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries);
+ for (int i = 0; i < strArr.Length; i++)
+ {
+ strArr[i] = (Convert.ToInt32(strArr[i], 16) + Convert.ToInt32("33", 16)).ToString("X2");
+ if (strArr[i].Length > 2)
+ {
+ strArr[i] = strArr[i].Substring(strArr[i].Length - 2);
+ }
+ }
+ return string.Join(" ", strArr);
+ }
+
+ private static string AddHex33(this string strGet)
+ {
+ string result;
+ if (string.IsNullOrEmpty(strGet))
+ {
+ result = "";
+ }
+ else
+ {
+ string[] source = StrAddSpan(strGet).Split(new char[]
+ {
+ ' '
+ }, StringSplitOptions.RemoveEmptyEntries);
+ result = string.Join("", from s in source
+ select (Convert.ToInt32(s, 16) + Convert.ToInt32("33", 16)).ToString("X2"));
+ }
+ return result;
+ }
+
private static void CreateAlphaNumMask(StringBuilder buffer, string source, char mask, int length)
{
for (int i = 0; i < length; i++)
diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/CommandReuslt.cs b/JiShe.CollectBus.Common/Models/CommandReuslt.cs
similarity index 85%
rename from JiShe.CollectBus.Protocol.Contracts/Models/CommandReuslt.cs
rename to JiShe.CollectBus.Common/Models/CommandReuslt.cs
index 89db4d4..0d75c42 100644
--- a/JiShe.CollectBus.Protocol.Contracts/Models/CommandReuslt.cs
+++ b/JiShe.CollectBus.Common/Models/CommandReuslt.cs
@@ -1,9 +1,7 @@
-using JiShe.CollectBus.Common;
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+using JiShe.CollectBus.Common.Enums;
-namespace JiShe.CollectBus.Protocol.Contracts.Models
+namespace JiShe.CollectBus.Common.Models
{
//TODO
public class CommandReulstMsg
diff --git a/JiShe.CollectBus.Console/Extensions/DependencyInjections/DependencyInjectionExtensions.cs b/JiShe.CollectBus.Console/Extensions/DependencyInjections/DependencyInjectionExtensions.cs
index 96b7cfd..a2f7992 100644
--- a/JiShe.CollectBus.Console/Extensions/DependencyInjections/DependencyInjectionExtensions.cs
+++ b/JiShe.CollectBus.Console/Extensions/DependencyInjections/DependencyInjectionExtensions.cs
@@ -5,6 +5,7 @@ using JiShe.CollectBus.Common.Interfaces;
using TouchSocket.Core;
using Microsoft.Extensions.Hosting;
using System;
+using Serilog;
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
@@ -22,7 +23,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
if (typeof(IJiSheModule).IsAssignableFrom(type) && type is { IsClass: true, IsAbstract: false })
{
-
+ Log.Logger.Information($"正在加载模块{type.Name}...");
var instance = Activator.CreateInstance(type);
_ = (type.GetMethod("ConfigureServices")?.Invoke(instance, [services, hostContext]));
}
@@ -90,6 +91,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
var attr = type.GetCustomAttribute();
if (attr == null) continue;
+ Log.Logger.Information($"正在加载插件{attr.Name}...");
var serviceDescriptor = new ServiceDescriptor(interfaceType, attr.Name, type, ServiceLifetime.Singleton);
services.Add(serviceDescriptor);
}
@@ -102,6 +104,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
var attr = type.GetCustomAttribute();
if (attr == null) continue;
+ Log.Logger.Information($"正在加载插件{attr.Name}...");
var serviceDescriptor = new ServiceDescriptor(interfaceType, attr.Name, type, ServiceLifetime.Transient);
services.Add(serviceDescriptor);
}
@@ -114,6 +117,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
var attr = type.GetCustomAttribute();
if (attr == null) continue;
+ Log.Logger.Information($"正在加载插件{attr.Name}...");
var serviceDescriptor = new ServiceDescriptor(interfaceType, attr.Name, type, ServiceLifetime.Scoped);
services.Add(serviceDescriptor);
}
diff --git a/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj b/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj
index 3fd1a06..1bdd619 100644
--- a/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj
+++ b/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj
@@ -30,6 +30,12 @@
+
+
+
+
+
+
diff --git a/JiShe.CollectBus.Console/Program.cs b/JiShe.CollectBus.Console/Program.cs
index fcaad3a..5c6c9d5 100644
--- a/JiShe.CollectBus.Console/Program.cs
+++ b/JiShe.CollectBus.Console/Program.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using Serilog;
namespace JiShe.CollectBus.Console
{
@@ -9,7 +10,23 @@ namespace JiShe.CollectBus.Console
static void Main(string[] args)
{
- CreateHostBuilder(args).Build().Run();
+ try
+ {
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .CreateLogger();
+
+
+ CreateHostBuilder(args).Build().Run();
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Application terminated unexpectedly");
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
@@ -29,9 +46,16 @@ namespace JiShe.CollectBus.Console
private static void ConfigureServices(IServiceCollection services, HostBuilderContext hostContext)
{
var configuration = hostContext.Configuration;
+
+ services.AddSerilog((context, lc) =>
+ {
+ lc.ReadFrom.Configuration(configuration)
+ .ReadFrom.Services(context);
+ });
services.ModuleRegister(hostContext);
services.ServiceRegister();
services.PluginServiceRegister();
+
services.AddTcp(configuration);
//services.AddUdp(configuration);
services.AddStackExchangeRedisCache(options =>
diff --git a/JiShe.CollectBus.Console/appsettings.json b/JiShe.CollectBus.Console/appsettings.json
index 4d74af7..72e8a02 100644
--- a/JiShe.CollectBus.Console/appsettings.json
+++ b/JiShe.CollectBus.Console/appsettings.json
@@ -1,4 +1,31 @@
{
+ "Serilog": {
+ "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
+ "MinimumLevel": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "System": "Warning"
+ },
+ "WriteTo": [
+ { "Name": "Console" },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "Logs/log-.txt",
+ "rollingInterval": "Day"
+ //"rollOnFileSizeLimit": true,
+ //"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
+ }
+ }
+ ],
+ "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
+
+ "Properties": {
+ "Application": "CollectBus",
+ "Environment": "Development"
+ }
+ },
+
"ConnectionStrings": {
"Default": "Data Source=192.168.111.248;Port=3306;Database=JiSheCollectBus;uid=root;pwd=123456abcD;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true",
"ClickHouse": "host=localhost;port=8123;user=default;password=;database=default"
diff --git a/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs b/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs
index df99a94..b0c0531 100644
--- a/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs
+++ b/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs
@@ -1,10 +1,11 @@
using JiShe.CollectBus.Core.Exceptions;
+using Microsoft.Extensions.Logging;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace JiShe.CollectBus.Core.Plugins
{
- public partial class TcpClosePlugin(ILog logger) : PluginBase
+ public partial class TcpClosePlugin(ILogger logger) : PluginBase
{
[GeneratorPlugin(typeof(ITcpReceivedPlugin))]
public async Task OnTcpReceived(ITcpSessionClient client, ReceivedDataEventArgs e)
@@ -15,7 +16,7 @@ namespace JiShe.CollectBus.Core.Plugins
}
catch (CloseException ex)
{
- logger.Info("拦截到CloseException");
+ logger.LogInformation("拦截到CloseException");
client.Close(ex.Message);
}
catch (Exception exx)
diff --git a/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs b/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs
index 1b463e4..9cb8fc3 100644
--- a/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs
+++ b/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs
@@ -1,17 +1,23 @@
-using JiShe.CollectBus.Protocol.Contracts.Models;
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Extensions;
+using JiShe.CollectBus.Protocol.Contracts.Models;
using TouchSocket.Core;
using TouchSocket.Sockets;
using JiShe.CollectBus.RabbitMQ.Senders;
+using Microsoft.Extensions.Logging;
namespace JiShe.CollectBus.Core.Plugins
{
public partial class TcpServiceReceivedPlugin : PluginBase
{
private readonly INSender _nSender;
+ private readonly ILogger _logger;
- public TcpServiceReceivedPlugin(INSender nSender)
+
+ public TcpServiceReceivedPlugin(INSender nSender, ILogger logger)
{
_nSender = nSender;
+ _logger = logger;
}
@@ -32,29 +38,55 @@ namespace JiShe.CollectBus.Core.Plugins
//client.Logger.Info($"[TCP] 已从{client.GetIPPort()}接收到信息:{messageHexString}");
//await protocolPlugin.ReceivedAsync(client,e);
- await _nSender.SendToReceivedAsync(new MessageReceivedEvent
+
+ var messageHexString = Convert.ToHexString(e.ByteBlock.Span);
+ var hexStringList = messageHexString.StringToPairs();
+ var aFn = (int?)hexStringList.GetAnalyzeValue(CommandChunkEnum.AFN);
+ var fn = (int?)hexStringList.GetAnalyzeValue(CommandChunkEnum.FN);
+
+ if (aFn.HasValue && fn.HasValue)
{
- ClientIP = client.IP,
- ClientId = client.Id,
- MessageHexString = Convert.ToHexString(e.ByteBlock.Span),
- Port = client.Port
- });
+ if ((AFN)aFn == AFN.链路接口检测)
+ {
+ switch (fn)
+ {
+ case 1://登录
+ await _nSender.SendToReceivedLoginAsync(new MessageReceivedLoginEvent(client.Id,client.IP, client.Port, messageHexString,""));
+ break;
+ case 2://退出登录
+ await _nSender.SendToReceivedLoginAsync(new MessageReceivedLoginEvent(client.Id, client.IP, client.Port, messageHexString, ""));
+ break;
+ case 3://心跳
+ await _nSender.SendToReceivedHeartbeatAsync(new MessageReceivedHeartbeatEvent(client.Id, client.IP, client.Port, messageHexString, ""));
+ break;
+ }
+ }
+ else
+ {
+ await _nSender.SendToReceivedAsync(new MessageReceivedEvent(client.Id, client.IP, client.Port, messageHexString, ""));
+ }
+ }
+ else
+ {
+ _logger.LogError($"指令初步解析失败,指令内容:{messageHexString}");
+ }
+
await e.InvokeNext();
}
[GeneratorPlugin(typeof(ITcpConnectingPlugin))]
- public async Task OnTcpConnecting(ITcpSessionClient client, ConnectingEventArgs e)
+ public async Task OnTcpConnecting(ITcpSessionClient client,ConnectingEventArgs e)
{
- client.Logger.Info($"[TCP] ID:{client.Id} IP:{client.GetIPPort()}正在连接中...");
+ _logger.LogInformation($"[TCP] ID:{client.Id} IP:{client.GetIPPort()}正在连接中...");
await e.InvokeNext();
}
[GeneratorPlugin(typeof(ITcpConnectedPlugin))]
- public async Task OnTcpConnected(ITcpSessionClient client, ConnectedEventArgs e)
+ public async Task OnTcpConnected(ITcpSessionClient client,ConnectedEventArgs e)
{
- client.Logger.Info($"[TCP] ID:{client.Id} IP:{client.GetIPPort()}已连接");
+ _logger.LogInformation($"[TCP] ID:{client.Id} IP:{client.GetIPPort()}已连接");
await e.InvokeNext();
}
@@ -62,7 +94,7 @@ namespace JiShe.CollectBus.Core.Plugins
[GeneratorPlugin(typeof(ITcpClosedPlugin))]
public async Task OnTcpClosed(ITcpSessionClient client, ClosedEventArgs e)
{
- client.Logger.Info($"[TCP] ID:{client.Id} IP:{client.GetIPPort()}已关闭连接");
+ _logger.LogInformation($"[TCP] ID:{client.Id} IP:{client.GetIPPort()}已关闭连接");
await e.InvokeNext();
}
diff --git a/JiShe.CollectBus.Core/Services/BusService.cs b/JiShe.CollectBus.Core/Services/BusService.cs
index 9f1253e..f8419a2 100644
--- a/JiShe.CollectBus.Core/Services/BusService.cs
+++ b/JiShe.CollectBus.Core/Services/BusService.cs
@@ -1,4 +1,5 @@
-using System;
+using Microsoft.Extensions.Logging;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,7 +9,7 @@ using TouchSocket.Sockets;
namespace JiShe.CollectBus.Core.Services
{
- public partial class BusService : PluginBase
+ public partial class BusService(ILogger logger) : PluginBase
{
[GeneratorPlugin(typeof(IServerStartedPlugin))]
public Task OnServerStarted(IServiceBase sender, ServiceStateEventArgs e)
@@ -19,26 +20,26 @@ namespace JiShe.CollectBus.Core.Services
{
foreach (var item in service.Monitors)
{
- ConsoleLogger.Default.Info($"TCP {item.Option.IpHost}");
+ logger.LogInformation($"TCP {item.Option.IpHost}");
}
break;
}
case UdpSession session:
- ConsoleLogger.Default.Info($"UDP {session.Monitor.IPHost}");
+ logger.LogInformation($"UDP {session.Monitor.IPHost}");
break;
}
- ConsoleLogger.Default.Info(e.ServerState == ServerState.Running
+ logger.LogInformation(e.ServerState == ServerState.Running
? $"服务器成功启动"
: $"服务器启动失败,状态:{e.ServerState},异常:{e.Exception}");
return e.InvokeNext();
}
[GeneratorPlugin(typeof(IServerStopedPlugin))]
- public Task OnServerStoped(IServiceBase sender, ServiceStateEventArgs e)
+ public Task OnServerStoped(IServiceBase sender,ServiceStateEventArgs e)
{
- Console.WriteLine("服务已停止");
+ logger.LogInformation("服务已停止");
return e.InvokeNext();
}
}
diff --git a/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs b/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs
index 8a700d9..8427949 100644
--- a/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs
+++ b/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs
@@ -1,13 +1,343 @@
-using System.Threading.Tasks;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using JiShe.CollectBus.Common;
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Extensions;
+using JiShe.CollectBus.Common.Models;
using JiShe.CollectBus.Protocol.Contracts.Interfaces;
using JiShe.CollectBus.Protocol.Contracts.Models;
+using Microsoft.Extensions.Logging;
namespace JiShe.CollectBus.Protocol.Contracts.Abstracts
{
public abstract class BaseProtocolPlugin : IProtocolPlugin
{
+ public readonly ILogger _logger;
+ //起始字符
+ public const string stx = "68";
+ //结束字符
+ public const string end = "16";
+ //头部字节长度
+ public const int hearderLen = 6;
+ //消息认证码字段长度
+ public const int pWLen = 16;
+
+ public const int tPLen = 6;
+
+
+ protected BaseProtocolPlugin(ILogger logger)
+ {
+ _logger = logger;
+ }
+
public abstract Task GetAsync();
- public abstract Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent);
+ public abstract Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent, Action? sendAction = null);
+
+ ///
+ /// 登录帧解析
+ ///
+ /// 报文
+ /// 发送委托
+ ///
+ public virtual Task LoginAsync(MessageReceivedLoginEvent messageReceivedEvent, Action? sendAction = null)
+ {
+ var hexStringList = messageReceivedEvent.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 = GetCommandBytes(reqParam);
+ if (sendAction != null)
+ {
+ sendAction(bytes);
+ }
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// 心跳帧解析
+ ///
+ /// 报文
+ /// 发送委托
+ ///
+ public virtual Task HeartbeatAsync(MessageReceivedHeartbeatEvent messageReceivedEvent, Action? sendAction = null)
+ {
+ var hexStringList = messageReceivedEvent.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 = GetCommandBytes(reqParam);
+ if (sendAction != null)
+ {
+ sendAction(bytes);
+ }
+ }
+ return Task.CompletedTask;
+ }
+
+
+ #region 通用解析
+
+ public byte[] GetCommandBytes(ReqParameter reqParameter, List? dataUnit = null)
+ {
+ var cmdStrList = new List();
+ var userDatas = GetUserData(reqParameter, dataUnit);
+ var hearders = GetHeaders(userDatas.Count);
+ var cs = GetCS(userDatas);
+ cmdStrList.AddRange(hearders);
+ cmdStrList.AddRange(userDatas);
+ cmdStrList.Add(cs);
+ cmdStrList.Add(end);
+ _logger.LogInformation($"回复:{string.Join(" ", cmdStrList)}");
+ var bytes = cmdStrList.Select(x => Convert.ToByte(x, 16)).ToArray();
+ return bytes;
+ }
+
+ ///
+ /// 帧校验和
+ ///
+ /// 用户数据区
+ ///
+ public string GetCS(List userData)
+ {
+ byte sum = 0;
+ foreach (var d in userData)
+ {
+ var b = Convert.ToByte(d, 16);
+ sum += b;
+ }
+ return sum.ToString("X2");
+ }
+
+ ///
+ /// 用户数据区
+ ///
+ ///
+ ///
+ public List GetUserData(ReqParameter reqParameter, List? dataUnit)
+ {
+ var c = GetC(reqParameter.FunCode, reqParameter.PRM);
+ var a = GetAList(reqParameter.A, reqParameter.MSA);
+
+ var linkUserData = GetLinkUserData(reqParameter.AFN, reqParameter.Seq,
+ ((ReqParameter2)reqParameter).Pn, ((ReqParameter2)reqParameter).Fn, dataUnit);
+
+ var list = new List() { c };
+ list.AddRange(a);
+ list.AddRange(linkUserData);
+ return list;
+ }
+
+ ///
+ /// 固定长度的报文头 起始字符+长度+长度+起始字符
+ ///
+ ///
+ ///
+ public List GetHeaders(int length)
+ {
+ var headers = new List();
+ headers.Add(stx);
+ var l = GetLength(length);
+ headers.AddRange(l);
+ headers.AddRange(l);
+ headers.Add(stx);
+ return headers;
+ }
+
+ ///
+ /// 长度 2字节 [用户数据区长度]
+ ///
+ ///
+ public List GetLength(int length1)
+ {
+ var binaryLen = length1.DecToBin();
+ var protocolIdentification = Enum.Format(typeof(ProtocolIdentification),
+ ProtocolIdentification.本规约使用, "d").PadLeft(2, '0');
+ var lenStr = $"{binaryLen}{protocolIdentification}";
+ var hexLen = lenStr.BinToHex();
+ hexLen = hexLen.PadLeft(4, '0');
+ var list = hexLen.StringToPairs();
+ list.Reverse();
+ return list;
+ }
+
+ ///
+ /// 控制域
+ ///
+ /// 功能码
+ ///
+ ///
+ ///
+ public string GetC(int funCode, PRM pRM, int fcb = 0, FCV fcv = FCV.FCB位无效)
+ {
+ var cMasterStationFunCodeHex = funCode.DecToBin();
+ cMasterStationFunCodeHex = cMasterStationFunCodeHex.ToString().PadLeft(4, '0');
+ var strC = $"{(int)DIR.主站下行报文}{(int)pRM}{fcb}{(int)fcv}{cMasterStationFunCodeHex}";
+ var hexC = strC.BinToHex().PadLeft(2, '0');
+ return hexC;
+ }
+
+
+ ///
+ /// 地址域 3220 09872
+ ///
+ /// 行政区划码 BCD码 3220=2032
+ /// 逻辑地址 BIN 09872=2690=>9026
+ /// 主站地址 BIN 0~127
+ ///
+ public List GetAList(string a, int mSA)
+ {
+ var list = new List();
+
+ var a1 = a.Substring(0, 4);
+ var a1Pairs = a1.StringToPairs();
+ a1Pairs.Reverse();
+ list.AddRange(a1Pairs);
+
+ var a2 = Convert.ToInt32(a.Substring(4));
+ var decA2 = a2.DecToHex();
+ var a2Pairs = decA2.PadLeft(4, '0').StringToPairs();
+ a2Pairs.Reverse();
+ list.AddRange(a2Pairs);
+
+ //TODO:主站地址和组地址标志
+ var a3Bin = $"{mSA.DecToBin().PadLeft(7, '0')}0";
+ list.Add(a3Bin.BinToHex().PadLeft(2, '0'));
+
+ return list;
+ }
+
+ public List GetLinkUserData(AFN aFN, Seq seq, int pn, int fn, List? dataUnit)
+ {
+ var aFNValue = ((int)aFN).DecToHex().PadLeft(2, '0');
+ var sEQ = GetSEQ(seq.TpV, seq.FIRFIN, seq.CON, seq.PRSEQ);
+ var dA = GetDA(pn);
+ var dT = GetDT(fn);
+ var list = new List() { aFNValue, sEQ };
+ list.AddRange(dA);
+ list.AddRange(dT);
+
+ if (dataUnit != null)
+ {
+ list.AddRange(dataUnit);
+ }
+ //list.AddRange(GetDataUnit(aFN,seq));
+
+ if (seq.TpV == TpV.附加信息域中带时间标签)
+ list.AddRange(GetTp("00"));
+
+ return list;
+ }
+
+ ///
+ /// 帧序列域
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string GetSEQ(TpV tpV, FIRFIN fIRFIN, CON cON, int pRSEQ)
+ {
+ var tpVValue = Enum.Format(typeof(TpV),
+ tpV, "d");
+ var fIRFINValue = Enum.Format(typeof(FIRFIN),
+ fIRFIN, "d");
+ var cONValue = (int)cON;
+ var sEQBin = $"{tpVValue}{fIRFINValue}{cONValue}{pRSEQ.DecToBin().PadLeft(4, '0')}";
+ var hexSEQ = sEQBin.BinToHex().PadLeft(2, '0');
+ return hexSEQ;
+ }
+
+ ///
+ /// 信息点标识
+ ///
+ /// 计量点
+ ///
+ public List GetDA(int pn)
+ {
+ if (pn == 0)
+ return new List() { "00", "00" };
+ var dA2 = (pn - 1) / 8 + 1;//信息点组从1开始 第几组
+ var dA1 = pn - (dA2 - 1) * 8;//pn % 8
+ var dA1Hex = "1".PadRight(dA1, '0').BinToHex();//对位信息 第几位 二进制有效位
+ var dA2Hex = dA2.DecToHex();
+ return new List() { dA1Hex.PadLeft(2, '0'), dA2Hex.PadLeft(2, '0') };
+
+ }
+
+ ///
+ /// 数据单元标识
+ ///
+ ///
+ ///
+ public List GetDT(int fn)
+ {
+ var dT2 = (fn - 1) / 8;//从零开始 第几组
+ var dT1 = fn - dT2 * 8;
+ var dT1Hex = "1".PadRight(dT1, '0').BinToHex();//对位信息 第几位 二进制有效位
+ var dT2Hex = dT2.DecToHex();
+ return new List() { dT1Hex.PadLeft(2, '0'), dT2Hex.PadLeft(2, '0') };
+ }
+
+ ///
+ /// 时间标签
+ ///
+ /// 启动帧帧序号计数器PFC 1字节
+ /// 允许发送传输延时时间 min 1字节
+ ///
+ public List GetTp(string pFC = "00", int delayTime = 0)
+ {
+
+ var now = DateTime.Now; // 获取当前时间
+ var seconds = now.Second.ToString().PadLeft(2, '0'); // 获取当前秒数
+ var minutes = now.Minute.ToString().PadLeft(2, '0'); // 获取当前分钟数
+ var hours = now.Hour.ToString().PadLeft(2, '0'); // 获取当前小时数
+ var day = now.Day.ToString().PadLeft(2, '0'); // 获取当前日期的日数
+ return new List() { pFC, seconds, minutes, hours, day, delayTime.ToString().PadLeft(2, '0') };
+ }
+
+ #endregion
+
}
}
diff --git a/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs b/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs
index 6eadf7e..66105cc 100644
--- a/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs
+++ b/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs
@@ -1,4 +1,5 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
using JiShe.CollectBus.Protocol.Contracts.Models;
using TouchSocket.Sockets;
@@ -8,6 +9,10 @@ namespace JiShe.CollectBus.Protocol.Contracts.Interfaces
{
Task GetAsync();
- Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent);
+ Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent, Action? sendAction = null);
+
+ Task LoginAsync(MessageReceivedLoginEvent messageReceivedEvent, Action? sendAction = null);
+
+ Task HeartbeatAsync(MessageReceivedHeartbeatEvent messageReceivedEvent, Action? sendAction = null);
}
}
diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/MessageReceivedEvent.cs b/JiShe.CollectBus.Protocol.Contracts/Models/MessageReceivedEvent.cs
index 87e093d..5a6aa3c 100644
--- a/JiShe.CollectBus.Protocol.Contracts/Models/MessageReceivedEvent.cs
+++ b/JiShe.CollectBus.Protocol.Contracts/Models/MessageReceivedEvent.cs
@@ -2,6 +2,15 @@
{
public class MessageReceivedEvent
{
+ public MessageReceivedEvent(string clientId, string clientIp,int port, string messageHexString, string deviceNo)
+ {
+ ClientId = clientId;
+ ClientIP = clientIp;
+ Port = port;
+ MessageHexString = messageHexString;
+ DeviceNo = deviceNo;
+ }
+
///
/// 客服端标识
///
@@ -27,4 +36,18 @@
///
public string DeviceNo { get; set; }
}
+
+ public class MessageReceivedLoginEvent: MessageReceivedEvent
+ {
+ public MessageReceivedLoginEvent(string clientId, string clientIp, int port, string messageHexString, string deviceNo) : base(clientId, clientIp, port, messageHexString, deviceNo)
+ {
+ }
+ }
+
+ public class MessageReceivedHeartbeatEvent : MessageReceivedEvent
+ {
+ public MessageReceivedHeartbeatEvent(string clientId, string clientIp, int port, string messageHexString, string deviceNo) : base(clientId, clientIp, port, messageHexString, deviceNo)
+ {
+ }
+ }
}
diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs b/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs
index 00503fb..dfee33e 100644
--- a/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs
+++ b/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using JiShe.CollectBus.Common;
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Models;
namespace JiShe.CollectBus.Protocol.Contracts.Models
{
diff --git a/JiShe.CollectBus.Protocol.Test/TestProtocolPlugin.cs b/JiShe.CollectBus.Protocol.Test/TestProtocolPlugin.cs
index 13d6c87..b1f43b8 100644
--- a/JiShe.CollectBus.Protocol.Test/TestProtocolPlugin.cs
+++ b/JiShe.CollectBus.Protocol.Test/TestProtocolPlugin.cs
@@ -3,6 +3,7 @@ using JiShe.CollectBus.Protocol.Contracts.Abstracts;
using JiShe.CollectBus.Protocol.Contracts.Attributes;
using JiShe.CollectBus.Protocol.Contracts.Models;
using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.Logging;
using TouchSocket.Sockets;
namespace JiShe.CollectBus.Protocol.Test
@@ -10,12 +11,16 @@ namespace JiShe.CollectBus.Protocol.Test
[ProtocolName("TestProtocol")]
public class TestProtocolPlugin : BaseProtocolPlugin, ISingletonDependency
{
+ public TestProtocolPlugin(ILogger logger) : base(logger)
+ {
+ }
+
public override Task GetAsync()
{
throw new NotImplementedException();
}
- public override Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent)
+ public override Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent, Action? sendAction = null)
{
throw new NotImplementedException();
}
diff --git a/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs b/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs
index ad49e01..a47505a 100644
--- a/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs
+++ b/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs
@@ -1,53 +1,29 @@
using JiShe.CollectBus.Common;
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Extensions.DependencyInjections;
+using JiShe.CollectBus.Common.Models;
using JiShe.CollectBus.Protocol.Contracts.Abstracts;
using JiShe.CollectBus.Protocol.Contracts.Attributes;
using JiShe.CollectBus.Protocol.Contracts.Models;
using JiShe.CollectBus.RabbitMQ.Senders;
using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.Logging;
using TouchSocket.Sockets;
namespace JiShe.CollectBus.Protocol
{
[ProtocolName("StandardProtocol")]
- public class StandardProtocolPlugin(INSender nSender) : BaseProtocolPlugin, ISingletonDependency
+ public class StandardProtocolPlugin(INSender nSender, ILogger logger) : BaseProtocolPlugin(logger), ISingletonDependency
{
- //起始字符
- private const string stx = "68";
- //结束字符
- private const string end = "16";
- //头部字节长度
- private const int hearderLen = 6;
- //消息认证码字段长度
- private const int pWLen = 16;
-
- private const int tPLen = 6;
-
- static object locker = new object();
- static List MSA = new List();
- static Dictionary> usingMSA = new Dictionary>();
-
- private string clientId = "";
-
- static StandardProtocolPlugin()
- {
- for (int i = 1; i <= 127; i++)
- {
- MSA.Add(i);
- }
- }
-
-
public override async Task GetAsync()
{
var info = new ProtocolInfo("Standard", "376.1", "TCP", "376.1协议", "DTS1980");
return await Task.FromResult(info);
}
- public override async Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent)
+ public override async Task AnalyzeAsync(MessageReceivedEvent messageReceivedEvent, Action? sendAction = null)
{
- clientId = messageReceivedEvent.ClientId;
-
var cmdResult = AnalysisCmd(messageReceivedEvent.MessageHexString);
if (cmdResult == null)
{
@@ -57,29 +33,32 @@ namespace JiShe.CollectBus.Protocol
await Task.CompletedTask;
}
- ///
- /// Gets the msa.
- ///
- /// The mark.
- ///
- public static int GetMSA(string mark)
+ public override async Task LoginAsync(MessageReceivedLoginEvent messageReceivedEvent, Action? sendAction = null)
{
- lock (locker)
+ async void SendAction(byte[] bytes)
{
- if (!usingMSA.Keys.Contains(mark))
- usingMSA.Add(mark, new List());
-
- int msa = MSA.Except(usingMSA[mark]).FirstOrDefault();
- //if (msa == 1) msa = 2;//msa=1为自定义指令保留
- usingMSA[mark].Add(msa);
-
- if (msa == 127)
- usingMSA[mark].RemoveAll(m => true);
-
- return msa;
+ await nSender.SendToIssuedAsync(new MessageIssuedEvent { ClientId = messageReceivedEvent.ClientId, DeviceNo = messageReceivedEvent.DeviceNo, Message = bytes });
}
+
+ await base.LoginAsync(messageReceivedEvent, SendAction);
}
+
+ public override async Task HeartbeatAsync(MessageReceivedHeartbeatEvent messageReceivedEvent, Action? sendAction = null)
+ {
+ async void SendAction(byte[] bytes)
+ {
+ await nSender.SendToIssuedAsync(new MessageIssuedEvent { ClientId = messageReceivedEvent.ClientId, DeviceNo = messageReceivedEvent.DeviceNo, Message = bytes });
+ }
+ await base.HeartbeatAsync(messageReceivedEvent, SendAction);
+ }
+
+
+
+
+
+
+
#region 上行命令
//68
@@ -112,7 +91,7 @@ namespace JiShe.CollectBus.Protocol
public CommandReulst? AnalysisCmd(string cmd)
{
CommandReulst? commandReulst = null;
- var hexStringList = DataConvert.StringToPairs(cmd);
+ var hexStringList = cmd.StringToPairs();
if (hexStringList.Count < hearderLen)
{
@@ -125,8 +104,8 @@ namespace JiShe.CollectBus.Protocol
}
var lenHexStr = $"{hexStringList[2]}{hexStringList[1]}";
- var lenBin = DataConvert.HexToBin(lenHexStr);
- var len = DataConvert.BinToDec(lenBin.Remove(lenBin.Length - 2));
+ var lenBin = lenHexStr.HexToBin();
+ var len = lenBin.Remove(lenBin.Length - 2).BinToDec();
//验证长度
if (hexStringList.Count - 2 != hearderLen + len)
return commandReulst;
@@ -137,14 +116,14 @@ namespace JiShe.CollectBus.Protocol
var aHexList = hexStringList.Skip(userDataIndex).Take(5).ToList();//地址域 5字节
var a = AnalysisA(aHexList);
- var a3Bin = DataConvert.HexToBin(aHexList[4]).PadLeft(8, '0');
- var mSA = DataConvert.BinToDec(a3Bin.Substring(0, 7));
+ var a3Bin = aHexList[4].HexToBin().PadLeft(8, '0');
+ var mSA = a3Bin.Substring(0, 7).BinToDec();
userDataIndex += 5;
- var aFN = (AFN)DataConvert.HexToDec(hexStringList[userDataIndex]);//1字节
+ var aFN = (AFN)hexStringList[userDataIndex].HexToDec();//1字节
userDataIndex += 1;
- var seq = DataConvert.HexToBin(hexStringList[userDataIndex]).PadLeft(8, '0');
+ 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));
@@ -152,20 +131,19 @@ namespace JiShe.CollectBus.Protocol
userDataIndex += 1;
// (DA2 - 1) * 8 + DA1 = pn
- var da1Bin = DataConvert.HexToBin(hexStringList[userDataIndex]);
+ var da1Bin = hexStringList[userDataIndex].HexToBin();
var da1 = da1Bin == "0" ? 0 : da1Bin.Length;
userDataIndex += 1;
- var da2 = DataConvert.HexToDec(hexStringList[userDataIndex]);
- userDataIndex += 1;
+ var da2 = hexStringList[userDataIndex].HexToDec();
var pn = da2 == 0 ? 0 : (da2 - 1) * 8 + da1;
-
+ userDataIndex += 1;
//(DT2*8)+DT1=fn
- var dt1Bin = DataConvert.HexToBin(hexStringList[userDataIndex]);
+ var dt1Bin = hexStringList[userDataIndex].HexToBin();
var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0;
userDataIndex += 1;
- var dt2 = DataConvert.HexToDec(hexStringList[userDataIndex]);
- userDataIndex += 1;
+ var dt2 = hexStringList[userDataIndex].HexToDec();
var fn = dt2 * 8 + dt1;
+ userDataIndex += 1;
//数据单元
var datas = hexStringList.Skip(userDataIndex).Take(len + hearderLen - userDataIndex).ToList();
@@ -182,7 +160,7 @@ namespace JiShe.CollectBus.Protocol
TpV = tpV,
FIRFIN = fIRFIN,
CON = cON,
- PRSEQ = DataConvert.BinToDec(prseqBin),
+ PRSEQ = prseqBin.BinToDec(),
},
CmdLength = len,
Pn = pn,
@@ -202,7 +180,7 @@ namespace JiShe.CollectBus.Protocol
{
var a1 = aHexList[1] + aHexList[0];
var a2 = aHexList[3] + aHexList[2];
- var a2Dec = DataConvert.HexToDec(a2);
+ var a2Dec = a2.HexToDec();
var a3 = aHexList[4];
var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}";
return a;
@@ -285,12 +263,6 @@ namespace JiShe.CollectBus.Protocol
Fn = 1
};
commandReulst.ReplyBytes = GetCommandBytes(reqParam);
- nSender.SendToIssuedAsync(new MessageIssuedEvent
- {
- ClientId = clientId,
- DeviceNo = "",
- Message = commandReulst.ReplyBytes
- });
}
else if (commandReulst.Fn == 2)//退出登录
{
@@ -332,681 +304,6 @@ namespace JiShe.CollectBus.Protocol
commandReulst.ReplyBytes = GetCommandBytes(reqParam);
}
}
-
- ///
- /// 解析时间标签
- ///
- ///
- private void AnalysisTp(List hexDatas)
- {
- var pFC = DataConvert.HexToDec(hexDatas[0]);//启动帧帧序号计数器
- var seconds = Convert.ToInt32(hexDatas[1]); // 获取当前秒数
- var minutes = Convert.ToInt32(hexDatas[2]); // 获取当前分钟数
- var hours = Convert.ToInt32(hexDatas[3]); // 获取当前小时数
- var day = Convert.ToInt32(hexDatas[4]); // 获取当前日期的日数
- var delayTime = DataConvert.HexToDec(hexDatas[5]);//延迟时间 min
- }
-
- ///
- /// 解析电表档案
- ///
- ///
- ///
- public List AnalysisAFN04F10DataUnit(List hexDatas)
- {
- var meterList = new List();
- var count = DataConvert.HexToDec($"{hexDatas[1]}{hexDatas[0]}");
- //if (2 + count * 27 != hexDatas.Count - pWLen - tPLen - 2)
- // return;
- var index = 2;//数量
- for (int i = 1; i <= count; i++)
- {
- var meterNumber = DataConvert.HexToDec($"{hexDatas[index + 1]}{hexDatas[index]}");
- index += 2;
-
- var pn = DataConvert.HexToDec($"{hexDatas[index + 1]}{hexDatas[index]}");
- index += 2;
-
- var baudRateAndPortBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0');
- var baudRate = DataConvert.BinToDec(baudRateAndPortBin.Substring(0, 3));
- var port = DataConvert.BinToDec(baudRateAndPortBin.Substring(3, 5));
- index += 1;
-
- var protocolType = (CommunicationProtocolType)DataConvert.HexToDec(hexDatas[index]);
- index += 1;
-
- var addressHexList = hexDatas.Skip(index).Take(6).ToList();
- addressHexList.Reverse();
- var address = string.Join("", addressHexList);
- index += 6;
-
- var pwdHexList = hexDatas.Skip(index).Take(6).ToList();
- pwdHexList.Reverse();
- var password = string.Join("", pwdHexList.Take(3).ToList());
- index += 6;
-
- var rateNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0');
- var rateNumber = DataConvert.BinToDec(rateNumberBin.Substring(4));
- index += 1;
-
- var intBitAndDecBitNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0');
- var intBitNumber = DataConvert.BinToDec(intBitAndDecBitNumberBin.Substring(4, 2)) + 4;
- var decBitNumber = DataConvert.BinToDec(intBitAndDecBitNumberBin.Substring(6, 2)) + 1;
- index += 1;
-
- // hexDatas.GetRange()
- var collectorAddressHexList = hexDatas.Skip(index).Take(6).ToList();
- collectorAddressHexList.Reverse();
- var collectorAddress = string.Join("", collectorAddressHexList);
- index += 6;
-
- var userClassNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0');
- var userClass = DataConvert.BinToDec(userClassNumberBin.Substring(0, 4));
- var userSubClass = DataConvert.BinToDec(userClassNumberBin.Substring(4, 4));
- index += 1;
-
- meterList.Add(new MeterParameter()
- {
- Pn = pn,
- BaudRate = baudRate,
- Port = port,
- ProtocolType = protocolType,
- Address = address,
- Password = password,
- RateNumber = rateNumber,
- IntegerBitNumber = intBitNumber,
- DecimalBitNumber = decBitNumber,
- CollectorAddress = collectorAddress,
- UserCategoryNumber = userClass,
- UserSubclassNumber = userSubClass,
- });
- }
- return meterList;
- }
-
- ///
- /// 解析实时数据F129
- ///
- ///
- private void AnalysisAFN0CF129DataUnit(List hexDatas)
- {
- var minutes = Convert.ToInt32(hexDatas[0]); // 获取当前分钟数
- var hours = Convert.ToInt32(hexDatas[1]); // 获取当前小时数
- var day = Convert.ToInt32(hexDatas[2]); // 获取当前日期的日数
- var month = Convert.ToInt32(hexDatas[3]); // 获取当前月份
- var year = Convert.ToInt32(hexDatas[4]); // 获取当前日期的年份
-
- var rateNumber = Convert.ToInt32(hexDatas[5]);
- var kwhTotal = hexDatas.Skip(5).Take(5).ToList();
- var kwhList = new List();
- var index = 11;
- for (int i = 0; i < rateNumber; i++)
- {
- var kwhHexList = hexDatas.Skip(11).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(val);
- index += 5;
- }
- }
-
#endregion
-
- #region 下行命令
-
- ///
- /// 设置电表档案
- ///
- /// 集中器地址
- ///
- public void GetSetAmmeterParameter(string a, List meterParameters)
- {
- var dataUnit = GetAFN04F10DataUnit(meterParameters);
- var bytes = GetCommandBytes(new ReqParameter2()
- {
- AFN = AFN.设置参数,
- FunCode = (int)CMasterStationFunCode.请求1级数据,
- A = a,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.需要对该帧进行确认,
- PRSEQ = 10,
- },
- MSA = GetMSA(a),
- Pn = 0,
- Fn = 10
- }, dataUnit);
- }
-
- ///
- /// 查询电表档案
- ///
- ///
- /// 对象序号
- public void GetAmmeterParameter(string a, List meterNumberList)
- {
- var dataUnit = new List();
- var countHex = DataConvert.DecToHex(meterNumberList.Count()).PadLeft(4, '0');
- var countHexPairs = DataConvert.StringToPairs(countHex);
- countHexPairs.Reverse();
- dataUnit.AddRange(countHexPairs);
-
- foreach (var number in meterNumberList)
- {
- var numberHex = DataConvert.DecToHex(number).PadLeft(4, '0');
- var numberHexPairs = DataConvert.StringToPairs(numberHex);
- numberHexPairs.Reverse();
- dataUnit.AddRange(numberHexPairs);
- }
- var bytes = GetCommandBytes(new ReqParameter2()
- {
- AFN = AFN.查询参数,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = a,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 0,
- },
- MSA = GetMSA(a),
- Pn = 0,
- Fn = 10
- }, dataUnit);
- }
-
- ///
- /// 电表抄读
- ///
- ///
- ///
- public void GetAmmterReading(string a, int pn)
- {
- var bytes = GetCommandBytes(new ReqParameter2()
- {
- AFN = AFN.请求实时数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = a,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(a),
- Pn = pn,
- Fn = 129
- });
- }
-
- ///
- /// 组装电表阀控
- ///
- /// 电表地址
- /// 特殊控制码
- /// 密码
- /// 是否为开阀
- ///
- public List AmmeterValveControl(string address, string specialnocode, string password, bool state, string modelCode = "")
- {
- address = address.Trim().TrimStart('0');
- if (address.Length < 12) address = address.PadLeft(12, '0');
- string Code = string.Empty;
-
- if (state)
- {
- if (string.IsNullOrEmpty(specialnocode))
- Code = "1B";
- else
- Code = specialnocode == "1B" || specialnocode == "1C" ? specialnocode : "1C";
- }
- else
- Code = "1A";//跳闸
-
- if (specialnocode == "1W")
- {
- if (state)
- Code = "1A";
- else
- Code = "1C";
- }
-
- var pwdLevel = "02";
- if (modelCode == "HL_DTSU2625" || modelCode == "DDZY9866")
- pwdLevel = "04";
- else if (modelCode == "DDS2705")
- pwdLevel = "03";
-
- if (!string.IsNullOrWhiteSpace(password) && password.Contains("|"))
- {
- var sp = password.Split('|');
- pwdLevel = sp[1];
- password = sp[0];
- }
-
- string strDate = DataConvert.StrAddSpan(DateTime.Now.AddYears(3).ToString("000012ddMMyy"));
- if (specialnocode == "1D" || modelCode == "SZBD_DDZY1225")
- strDate = "FF FF FF FF FF FF";
- string strP = DataConvert.StrReverseOrder(DataConvert.StrAddSpan(password));
- string strSJY = " " + pwdLevel + " " + strP + " 01 00 00 00 " + Code + " 00 " + strDate;
- string strLen = (strSJY.Replace(" ", "").Length / 2).ToString("X2");
- string strReturn = "68 " + DataConvert.StrReverseOrder(DataConvert.StrAddSpan(address)) + " 68 1C " + strLen + " " + DataConvert.StrAddHex33(strSJY) + " ";
- string strSum = strReturn.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
- strReturn += strSum.Substring(strSum.Length - 2) + " 16";
-
- return strReturn.Split(' ').ToList();
- }
-
- ///
- /// 帧命令组装
- ///
- /// 请求参数
- /// 数据单元
- ///
- public byte[] GetCommandBytes(ReqParameter reqParameter, List? dataUnit = null)
- {
- var cmdStrList = new List();
- var userDatas = GetUserData(reqParameter, dataUnit);
- var hearders = GetHeaders(userDatas.Count);
- var cs = GetCS(userDatas);
- cmdStrList.AddRange(hearders);
- cmdStrList.AddRange(userDatas);
- cmdStrList.Add(cs);
- cmdStrList.Add(end);
- Console.WriteLine($"回复:{string.Join(" ", cmdStrList)}");
- var bytes = cmdStrList.Select(x => Convert.ToByte(x, 16)).ToArray();
- return bytes;
- }
-
-
- ///
- /// 固定长度的报文头 起始字符+长度+长度+起始字符
- ///
- ///
- ///
- private List GetHeaders(int length)
- {
- var headers = new List();
- headers.Add(stx);
- var l = GetLength(length);
- headers.AddRange(l);
- headers.AddRange(l);
- headers.Add(stx);
- return headers;
- }
-
- ///
- /// 用户数据区
- ///
- ///
- ///
- public List GetUserData(ReqParameter reqParameter, List? dataUnit)
- {
- var c = GetC(reqParameter.FunCode, reqParameter.PRM);
- var a = GetAList(reqParameter.A, reqParameter.MSA);
-
- var linkUserData = GetLinkUserData(reqParameter.AFN, reqParameter.Seq,
- ((ReqParameter2)reqParameter).Pn, ((ReqParameter2)reqParameter).Fn, dataUnit);
-
- var list = new List() { c };
- list.AddRange(a);
- list.AddRange(linkUserData);
- return list;
- }
-
-
- ///
- /// 长度 2字节 [用户数据区长度]
- ///
- ///
- private List GetLength(int length1)
- {
- var binaryLen = DataConvert.DecToBin(length1);
- var protocolIdentification = Enum.Format(typeof(ProtocolIdentification),
- ProtocolIdentification.本规约使用, "d").PadLeft(2, '0');
- var lenStr = $"{binaryLen}{protocolIdentification}";
- var hexLen = DataConvert.BinToHex(lenStr);
- hexLen = hexLen.PadLeft(4, '0');
- var list = DataConvert.StringToPairs(hexLen);
- list.Reverse();
- return list;
- }
-
- ///
- /// 控制域
- ///
- /// 功能码
- ///
- ///
- ///
- private string GetC(int funCode, PRM pRM, int fcb = 0, FCV fcv = FCV.FCB位无效)
- {
- var cMasterStationFunCodeHex = DataConvert.DecToBin(funCode);
- cMasterStationFunCodeHex = cMasterStationFunCodeHex.ToString().PadLeft(4, '0');
- var strC = $"{(int)DIR.主站下行报文}{(int)pRM}{fcb}{(int)fcv}{cMasterStationFunCodeHex}";
- var hexC = DataConvert.BinToHex(strC).PadLeft(2, '0');
- return hexC;
- }
-
- ///
- /// 地址域 3220 09872
- ///
- /// 行政区划码 BCD码 3220=2032
- /// 逻辑地址 BIN 09872=2690=>9026
- /// 主站地址 BIN 0~127
- ///
- private List GetAList(string a, int mSA)
- {
- var list = new List();
-
- var a1 = a.Substring(0, 4);
- var a1Pairs = DataConvert.StringToPairs(a1);
- a1Pairs.Reverse();
- list.AddRange(a1Pairs);
-
- var a2 = Convert.ToInt32(a.Substring(4));
- var decA2 = DataConvert.DecToHex(a2);
- var a2Pairs = DataConvert.StringToPairs(decA2.PadLeft(4, '0'));
- a2Pairs.Reverse();
- list.AddRange(a2Pairs);
-
- //TODO:主站地址和组地址标志
- var a3Bin = $"{DataConvert.DecToBin(mSA).PadLeft(7, '0')}0";
- list.Add(DataConvert.BinToHex(a3Bin).PadLeft(2, '0'));
-
- return list;
- }
-
- #region 链路用户数据
-
- private List GetLinkUserData(AFN aFN, Seq seq, int pn, int fn, List? dataUnit)
- {
- var aFNValue = DataConvert.DecToHex((int)aFN).PadLeft(2, '0');
- var sEQ = GetSEQ(seq.TpV, seq.FIRFIN, seq.CON, seq.PRSEQ);
- var dA = GetDA(pn);
- var dT = GetDT(fn);
- var list = new List() { aFNValue, sEQ };
- list.AddRange(dA);
- list.AddRange(dT);
-
- if (dataUnit != null)
- {
- list.AddRange(dataUnit);
- }
- //list.AddRange(GetDataUnit(aFN,seq));
-
- if (seq.TpV == TpV.附加信息域中带时间标签)
- list.AddRange(GetTp("00"));
-
- return list;
- }
-
-
- ///
- /// 帧序列域
- ///
- ///
- ///
- ///
- ///
- private string GetSEQ(TpV tpV, FIRFIN fIRFIN, CON cON, int pRSEQ)
- {
- var tpVValue = Enum.Format(typeof(TpV),
- tpV, "d");
- var fIRFINValue = Enum.Format(typeof(FIRFIN),
- fIRFIN, "d");
- var cONValue = (int)cON;
- var sEQBin = $"{tpVValue}{fIRFINValue}{cONValue}{DataConvert.DecToBin(pRSEQ).PadLeft(4, '0')}";
- var hexSEQ = DataConvert.BinToHex(sEQBin).PadLeft(2, '0');
- return hexSEQ;
- }
-
- ///
- /// 信息点标识
- ///
- /// 计量点
- ///
- private List GetDA(int pn)
- {
- if (pn == 0)
- return new List() { "00", "00" };
- var dA2 = (pn - 1) / 8 + 1;//信息点组从1开始 第几组
- var dA1 = pn - (dA2 - 1) * 8;//pn % 8
- var dA1Hex = DataConvert.BinToHex("1".PadRight(dA1, '0'));//对位信息 第几位 二进制有效位
- var dA2Hex = DataConvert.DecToHex(dA2);
- return new List() { dA1Hex.PadLeft(2, '0'), dA2Hex.PadLeft(2, '0') };
-
- }
-
- ///
- /// 数据单元标识
- ///
- ///
- ///
- private List GetDT(int fn)
- {
- var dT2 = (fn - 1) / 8;//从零开始 第几组
- var dT1 = fn - dT2 * 8;
- var dT1Hex = DataConvert.BinToHex("1".PadRight(dT1, '0'));//对位信息 第几位 二进制有效位
- var dT2Hex = DataConvert.DecToHex(dT2);
- return new List() { dT1Hex.PadLeft(2, '0'), dT2Hex.PadLeft(2, '0') };
- }
-
- private List GetDataUnit(AFN aFN, Seq seq)
- {
- var datas = new List();
- switch (aFN)
- {
- case AFN.确认或否认:
- break;
- case AFN.复位:
- break;
- case AFN.链路接口检测:
- break;
- case AFN.中继站命令:
- break;
- case AFN.设置参数:
- break;
- case AFN.控制命令:
- break;
- case AFN.身份认证及密钥协商:
- break;
- case AFN.备用:
- break;
- case AFN.请求被级联终端主动上报:
- break;
- case AFN.请求终端配置:
- break;
- case AFN.查询参数:
- break;
- case AFN.请求任务数据:
- break;
- case AFN.请求实时数据:
- break;
- case AFN.请求历史数据:
- break;
- case AFN.请求事件数据:
- break;
- case AFN.文件传输:
- break;
- case AFN.数据转发:
- break;
- default:
- break;
- }
- if (seq.TpV == TpV.附加信息域中带时间标签)
- datas.AddRange(GetTp("00"));
- return datas;
- }
-
- private void GetAFN00DataUnit(Seq seq)
- {
- //EC+Tp
-
- }
-
- ///
- /// 终端电能表配置参数
- ///
- ///
- ///
- public List GetAFN04F10DataUnit(List meterParameters)
- {
- var hexDatas = new List();
-
- var countHex = DataConvert.DecToHex(meterParameters.Count()).PadLeft(4, '0');
- hexDatas.Add(countHex);
-
- //TODO 优化代码:目标数据入参,返回类型为出参
- for (int i = 0; i <= meterParameters.Count - 1; i++)
- {
- var meter = meterParameters[i];
-
- var indexHex = DataConvert.DecToHex(i + 1).PadLeft(4, '0');
- hexDatas.Add(indexHex);
-
- var pnHex = DataConvert.DecToHex(meter.Pn).PadLeft(4, '0');
- hexDatas.Add(pnHex);
-
- var baudRateBin = DataConvert.DecToBin(meter.BaudRate).PadLeft(3, '0');
- var portBin = DataConvert.DecToBin(meter.Port).PadLeft(5, '0');
- var baudRateAndPortHex = DataConvert.BinToHex($"{baudRateBin}{portBin}").PadLeft(2, '0');
- hexDatas.Add(baudRateAndPortHex);
-
- var protocolTypeHex = DataConvert.DecToHex((int)meter.ProtocolType).PadLeft(2, '0');
- hexDatas.Add(protocolTypeHex);
-
- hexDatas.Add(meter.Address);
-
- hexDatas.Add(meter.Password.PadLeft(12, '0'));
-
- var rateNumberBin = $"0000{DataConvert.DecToBin(meter.RateNumber).PadLeft(4, '0')}";
- var rateNumberHex = DataConvert.BinToHex(rateNumberBin).PadLeft(2, '0');
- hexDatas.Add(rateNumberHex);
-
- var intBitNumberBin = DataConvert.DecToBin(meter.IntegerBitNumber - 4).PadLeft(2, '0');
- var decBitNumberBin = DataConvert.DecToBin(meter.DecimalBitNumber - 1).PadLeft(2, '0');
- var intAndDecBitNumberBin = $"0000{intBitNumberBin}{decBitNumberBin}";
- var intAndDecBitNumberHex = DataConvert.BinToHex(intAndDecBitNumberBin).PadLeft(2, '0');
- hexDatas.Add(intAndDecBitNumberHex);
-
- hexDatas.Add(meter.CollectorAddress.PadLeft(12, '0'));
-
- var userCategoryNumberBin = DataConvert.DecToBin(meter.UserCategoryNumber).PadLeft(4, '0');
- var userSubclassNumberBin = DataConvert.DecToBin(meter.UserSubclassNumber).PadLeft(4, '0');
- var userNumberHex = DataConvert.BinToHex($"{userCategoryNumberBin}{userSubclassNumberBin}").PadLeft(2, '0');
- hexDatas.Add(userNumberHex);
- }
-
- //高位在前,低位在后
- var datas = new List();
- foreach (var hexData in hexDatas)
- {
- if (hexData.Length == 2)
- datas.Add(hexData);
- else
- {
- var lst = DataConvert.StringToPairs(hexData);
- lst.Reverse();
- datas.AddRange(lst);
- }
- }
- datas.AddRange(GetPW());
- return datas;
- }
-
- ///
- /// 透明转发
- ///
- /// 终端通信端口 1~31
- /// 0~7 对应300,600,1200,2400,4800,7200,9600,19200
- ///
- ///
- ///
- ///
- public List GetAFN1001DataUnit(int port, BaudRate baudRate, StopBit stopBit, Parity parity, DataBit dataBit,
- int waitContentTimeout, int waitByteTimeout, List datas)
- {
- var dataUnit = new List();
-
- var portHex = DataConvert.DecToHex(port).PadLeft(2, '0');
- dataUnit.Add(portHex);
-
- var baudRateBin = DataConvert.DecToBin((int)baudRate).PadLeft(3, '0');
- var stopBitBin = DataConvert.DecToBin((int)stopBit);
- var parityBin = parity != Parity.None ? $"1{DataConvert.DecToBin((int)parity)}" : $"0{DataConvert.DecToBin((int)parity)}";
- var dataBitBin = DataConvert.DecToBin((int)dataBit).PadLeft(2, '0');
- var controlHex = DataConvert.BinToHex($"{baudRateBin}{stopBitBin}{parityBin}{dataBitBin}").PadLeft(2, '0'); ;
- dataUnit.Add(controlHex);
-
- var waitContentTimeoutBin = $"1{DataConvert.DecToBin(waitContentTimeout).PadLeft(7, '0')}";
- var waitContentTimeoutHex = DataConvert.BinToHex(waitContentTimeoutBin).PadLeft(2, '0');
- var waitByteTimeoutHex = DataConvert.DecToHex(waitByteTimeout).PadLeft(2, '0');
-
- dataUnit.Add(waitContentTimeoutHex);
- dataUnit.Add(waitByteTimeoutHex);
-
- var countHex = DataConvert.DecToHex(datas.Count).PadLeft(4, '0');
- var countHexPairs = DataConvert.StringToPairs(countHex);
- countHexPairs.Reverse();
- dataUnit.AddRange(countHexPairs);
-
- dataUnit.AddRange(datas);
-
- return dataUnit;
- }
-
- //TODO AUX=消息认证码字段(PW,16个字节)+时间标签
- private List GetPW()
- {
- var str = "00";
- var pWList = Enumerable.Repeat(str, pWLen).ToList();
- return pWList;
- }
-
- ///
- /// 时间标签
- ///
- /// 启动帧帧序号计数器PFC 1字节
- /// 允许发送传输延时时间 min 1字节
- ///
- private List GetTp(string pFC = "00", int delayTime = 0)
- {
-
- var now = DateTime.Now; // 获取当前时间
- var seconds = now.Second.ToString().PadLeft(2, '0'); // 获取当前秒数
- var minutes = now.Minute.ToString().PadLeft(2, '0'); // 获取当前分钟数
- var hours = now.Hour.ToString().PadLeft(2, '0'); // 获取当前小时数
- var day = now.Day.ToString().PadLeft(2, '0'); // 获取当前日期的日数
- return new List() { pFC, seconds, minutes, hours, day, delayTime.ToString().PadLeft(2, '0') };
- }
-
- #endregion
-
- ///
- /// 帧校验和
- ///
- /// 用户数据区
- ///
- private string GetCS(List userData)
- {
- byte sum = 0;
- foreach (var d in userData)
- {
- var b = Convert.ToByte(d, 16);
- sum += b;
- }
- return sum.ToString("X2");
- }
-
- #endregion
-
-
}
}
diff --git a/JiShe.CollectBus.RabbitMQ/Consumers/MessageIssuedConsumer.cs b/JiShe.CollectBus.RabbitMQ/Consumers/MessageIssuedConsumer.cs
index f78e267..744b4a7 100644
--- a/JiShe.CollectBus.RabbitMQ/Consumers/MessageIssuedConsumer.cs
+++ b/JiShe.CollectBus.RabbitMQ/Consumers/MessageIssuedConsumer.cs
@@ -1,7 +1,5 @@
-using JiShe.CollectBus.Protocol.Contracts.Interfaces;
-using JiShe.CollectBus.Protocol.Contracts.Models;
+using JiShe.CollectBus.Protocol.Contracts.Models;
using MassTransit;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TouchSocket.Sockets;
@@ -15,7 +13,7 @@ namespace JiShe.CollectBus.RabbitMQ.Consumers
public MessageIssuedConsumer(ILogger logger, ITcpService tcpService)
{
_logger = logger;
- _tcpService = tcpService;
+ _tcpService = tcpService;
}
public async Task Consume(ConsumeContext context)
diff --git a/JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedHeartbeatConsumer.cs b/JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedHeartbeatConsumer.cs
new file mode 100644
index 0000000..ceda2ae
--- /dev/null
+++ b/JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedHeartbeatConsumer.cs
@@ -0,0 +1,35 @@
+using JiShe.CollectBus.Protocol.Contracts.Interfaces;
+using JiShe.CollectBus.Protocol.Contracts.Models;
+using MassTransit;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace JiShe.CollectBus.RabbitMQ.Consumers
+{
+ public class MessageReceivedHeartbeatConsumer : IConsumer
+ {
+ private readonly ILogger _logger;
+ private readonly IServiceProvider _serviceProvider;
+
+ public MessageReceivedHeartbeatConsumer(ILogger logger, IServiceProvider serviceProvider)
+ {
+ _logger = logger;
+ _serviceProvider = serviceProvider;
+ }
+
+ public async Task Consume(ConsumeContext context)
+ {
+ _logger.LogInformation("心跳消费队列开始处理");
+ var protocolPlugin = _serviceProvider.GetKeyedService("StandardProtocol");
+ if (protocolPlugin == null)
+ {
+ _logger.LogError("【心跳消费队列开始处理】协议不存在!");
+ }
+ else
+ {
+ await protocolPlugin.HeartbeatAsync(context.Message);
+ _logger.LogInformation("心跳消费队列完成处理");
+ }
+ }
+ }
+}
diff --git a/JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedLoginConsumer.cs b/JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedLoginConsumer.cs
new file mode 100644
index 0000000..0132baa
--- /dev/null
+++ b/JiShe.CollectBus.RabbitMQ/Consumers/MessageReceivedLoginConsumer.cs
@@ -0,0 +1,35 @@
+using JiShe.CollectBus.Protocol.Contracts.Interfaces;
+using JiShe.CollectBus.Protocol.Contracts.Models;
+using MassTransit;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace JiShe.CollectBus.RabbitMQ.Consumers
+{
+ public class MessageReceivedLoginConsumer : IConsumer
+ {
+ private readonly ILogger _logger;
+ private readonly IServiceProvider _serviceProvider;
+
+ public MessageReceivedLoginConsumer(ILogger logger, IServiceProvider serviceProvider)
+ {
+ _logger = logger;
+ _serviceProvider = serviceProvider;
+ }
+
+ public async Task Consume(ConsumeContext context)
+ {
+ _logger.LogInformation("登录消费队列开始处理");
+ var protocolPlugin = _serviceProvider.GetKeyedService("StandardProtocol");
+ if (protocolPlugin == null)
+ {
+ _logger.LogError("【登录消费队列开始处理】协议不存在!");
+ }
+ else
+ {
+ await protocolPlugin.LoginAsync(context.Message);
+ _logger.LogInformation("登录消费队列完成处理");
+ }
+ }
+ }
+}
diff --git a/JiShe.CollectBus.RabbitMQ/JiSheCollectBusRabbitMqModule.cs b/JiShe.CollectBus.RabbitMQ/JiSheCollectBusRabbitMqModule.cs
index eaeed17..7b9db9f 100644
--- a/JiShe.CollectBus.RabbitMQ/JiSheCollectBusRabbitMqModule.cs
+++ b/JiShe.CollectBus.RabbitMQ/JiSheCollectBusRabbitMqModule.cs
@@ -1,10 +1,8 @@
-using System;
-using JiShe.CollectBus.Common.Interfaces;
+using JiShe.CollectBus.Common.Interfaces;
using JiShe.CollectBus.RabbitMQ.Consumers;
using MassTransit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using RabbitMQ.Client;
namespace JiShe.CollectBus.RabbitMQ
{
@@ -17,6 +15,8 @@ namespace JiShe.CollectBus.RabbitMQ
{
x.AddConsumer();
x.AddConsumer();
+ x.AddConsumer();
+ x.AddConsumer();
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host(configuration["MQ:Host"], ushort.Parse(configuration["MQ:Port"] ?? string.Empty), configuration["MQ:VirtualHost"], h =>
@@ -31,7 +31,18 @@ namespace JiShe.CollectBus.RabbitMQ
configurator.ConfigureConsumeTopology = false;
configurator.Consumer(context);
});
-
+ // 登录
+ cfg.ReceiveEndpoint($"{configuration["MQ:Queue:Received"]}_Login" ?? string.Empty, configurator =>
+ {
+ configurator.ConfigureConsumeTopology = false;
+ configurator.Consumer(context);
+ });
+ // 心跳
+ cfg.ReceiveEndpoint($"{configuration["MQ:Queue:Received"]}_Heartbeat" ?? string.Empty, configurator =>
+ {
+ configurator.ConfigureConsumeTopology = false;
+ configurator.Consumer(context);
+ });
// 消息下发队列
cfg.ReceiveEndpoint(configuration["MQ:Queue:Issued"] ?? string.Empty, configurator =>
{
diff --git a/JiShe.CollectBus.RabbitMQ/Senders/INSender.cs b/JiShe.CollectBus.RabbitMQ/Senders/INSender.cs
index 0f5c8fc..52e5a87 100644
--- a/JiShe.CollectBus.RabbitMQ/Senders/INSender.cs
+++ b/JiShe.CollectBus.RabbitMQ/Senders/INSender.cs
@@ -12,6 +12,10 @@ namespace JiShe.CollectBus.RabbitMQ.Senders
Task SendToIssuedAsync(object message, CancellationToken cancellationToken = default);
Task SendToReceivedAsync(T message, CancellationToken cancellationToken = default) where T : class;
Task SendToReceivedAsync(object message, CancellationToken cancellationToken = default);
+ Task SendToReceivedLoginAsync(T message, CancellationToken cancellationToken = default) where T : class;
+ Task SendToReceivedLoginAsync(object message, CancellationToken cancellationToken = default);
+ Task SendToReceivedHeartbeatAsync(T message, CancellationToken cancellationToken = default) where T : class;
+ Task SendToReceivedHeartbeatAsync(object message, CancellationToken cancellationToken = default);
Task SendAsync(string queueKey, object message, CancellationToken cancellationToken = default);
}
diff --git a/JiShe.CollectBus.RabbitMQ/Senders/NSender.cs b/JiShe.CollectBus.RabbitMQ/Senders/NSender.cs
index 3a57911..b435e4c 100644
--- a/JiShe.CollectBus.RabbitMQ/Senders/NSender.cs
+++ b/JiShe.CollectBus.RabbitMQ/Senders/NSender.cs
@@ -43,6 +43,26 @@ namespace JiShe.CollectBus.RabbitMQ.Senders
await SendAsync(_receivedKey, message, cancellationToken);
}
+ public async Task SendToReceivedLoginAsync(T message, CancellationToken cancellationToken = default) where T : class
+ {
+ await SendAsync($"{_receivedKey}_Login", message, cancellationToken);
+ }
+
+ public async Task SendToReceivedLoginAsync(object message, CancellationToken cancellationToken = default)
+ {
+ await SendAsync($"{_receivedKey}_Login", message, cancellationToken);
+ }
+
+ public async Task SendToReceivedHeartbeatAsync(T message, CancellationToken cancellationToken = default) where T : class
+ {
+ await SendAsync($"{_receivedKey}_Heartbeat", message, cancellationToken);
+ }
+
+ public async Task SendToReceivedHeartbeatAsync(object message, CancellationToken cancellationToken = default)
+ {
+ await SendAsync($"{_receivedKey}_Heartbeat", message, cancellationToken);
+ }
+
public async Task SendAsync(string queueKey, object message, CancellationToken cancellationToken = default)
{