diff --git a/JiShe.CollectBus.Common/Class1.cs b/JiShe.CollectBus.Common/Class1.cs new file mode 100644 index 0000000..deff6f7 --- /dev/null +++ b/JiShe.CollectBus.Common/Class1.cs @@ -0,0 +1,9 @@ +using System; + +namespace JiShe.CollectBus.Common +{ + public class Class1 + { + + } +} diff --git a/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj b/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj new file mode 100644 index 0000000..b4b43f4 --- /dev/null +++ b/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj @@ -0,0 +1,8 @@ + + + + netstandard2.1 + enable + + + diff --git a/JiShe.CollectBus.Console/Extensions/ServiceCollections/ServiceCollectionExtensions.cs b/JiShe.CollectBus.Console/Extensions/ServiceCollections/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..4d4b82f --- /dev/null +++ b/JiShe.CollectBus.Console/Extensions/ServiceCollections/ServiceCollectionExtensions.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JiShe.CollectBus.Core.Plugins; +using JiShe.CollectBus.Core.Services; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionExtensions + { + /// + /// 添加TcpService服务。 + /// + public static IServiceCollection AddTcp(this IServiceCollection services) + { + services.AddTcpService(config => + { + config.SetListenIPHosts(10500) + .ConfigureContainer(a => //容器的配置顺序应该在最前面 + { + a.AddConsoleLogger(); //添加一个控制台日志注入(注意:在maui中控制台日志不可用) + }) + .ConfigurePlugins(a => + { + a.UseCheckClear() + .SetCheckClearType(CheckClearType.All) + .SetTick(TimeSpan.FromSeconds(60)) + .SetOnClose((c, t) => + { + c.TryShutdown(); + c.SafeClose("超时无数据"); + }); + a.Add(); + a.Add(); + a.Add(); + }); + }); + return services; + } + + + /// + /// 添加UdpService服务。 + /// + public static IServiceCollection AddUdp(this IServiceCollection services) + { + services.AddUdpSession(config => + { + config.SetBindIPHost(10500) + .ConfigureContainer(a => //容器的配置顺序应该在最前面 + { + a.AddConsoleLogger(); //添加一个控制台日志注入(注意:在maui中控制台日志不可用) + }) + .ConfigurePlugins(a => + { + a.Add(); + a.Add(); + }) + .UseBroadcast() + .SetUdpDataHandlingAdapter(() => new NormalUdpDataHandlingAdapter()); + }); + return services; + } + } +} diff --git a/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj b/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj new file mode 100644 index 0000000..d5101fa --- /dev/null +++ b/JiShe.CollectBus.Console/JiShe.CollectBus.Console.csproj @@ -0,0 +1,20 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + diff --git a/JiShe.CollectBus.Console/Program.cs b/JiShe.CollectBus.Console/Program.cs new file mode 100644 index 0000000..de1bb00 --- /dev/null +++ b/JiShe.CollectBus.Console/Program.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace JiShe.CollectBus.Console +{ + internal class Program + { + + static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration(ConfigureAppConfiguration) + .ConfigureServices((hostContext, services) => { ConfigureServices(services, hostContext); }); + + + private static void ConfigureAppConfiguration(HostBuilderContext hostContext, IConfigurationBuilder config) + { + var env = hostContext.HostingEnvironment; + config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); + config.AddEnvironmentVariables(); + } + + + private static void ConfigureServices(IServiceCollection services, HostBuilderContext hostContext) + { + var configuration = hostContext.Configuration; + + services.AddTcp(); + services.AddUdp(); + + services.AddStackExchangeRedisCache(options => + { + options.Configuration = configuration["RedisCache:ConnectionString"]; + options.InstanceName = configuration["RedisCache:InstanceName"]; + }); + } + } +} + diff --git a/JiShe.CollectBus.Console/appsettings.json b/JiShe.CollectBus.Console/appsettings.json new file mode 100644 index 0000000..d41b49f --- /dev/null +++ b/JiShe.CollectBus.Console/appsettings.json @@ -0,0 +1,6 @@ +{ + "RedisCache": { + "ConnectionString": "123456@qwer@localhost:6379", + "InstanceName": "CollectBus" + } +} \ No newline at end of file diff --git a/JiShe.CollectBus.Core/Exceptions/CloseException.cs b/JiShe.CollectBus.Core/Exceptions/CloseException.cs new file mode 100644 index 0000000..e1f6260 --- /dev/null +++ b/JiShe.CollectBus.Core/Exceptions/CloseException.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Core.Exceptions +{ + public class CloseException(string msg) : Exception(msg); +} diff --git a/JiShe.CollectBus.Core/JiShe.CollectBus.Core.csproj b/JiShe.CollectBus.Core/JiShe.CollectBus.Core.csproj new file mode 100644 index 0000000..b791d87 --- /dev/null +++ b/JiShe.CollectBus.Core/JiShe.CollectBus.Core.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + diff --git a/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs b/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs new file mode 100644 index 0000000..cc613e5 --- /dev/null +++ b/JiShe.CollectBus.Core/Plugins/ClosePlugin.cs @@ -0,0 +1,37 @@ +using JiShe.CollectBus.Core.Exceptions; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace JiShe.CollectBus.Core.Plugins +{ + public class TcpClosePlugin(ILog logger) : PluginBase, ITcpReceivedPlugin + { + public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e) + { + try + { + await e.InvokeNext(); + } + catch (CloseException ex) + { + logger.Info("拦截到CloseException"); + client.Close(ex.Message); + } + catch (Exception exx) + { + // ignored + } + finally + { + } + } + } + + public class UdpClosePlugin(ILog logger) : PluginBase, IUdpReceivedPlugin + { + public async Task OnUdpReceived(IUdpSessionBase client, UdpReceivedDataEventArgs e) + { + throw new NotImplementedException(); + } + } +} diff --git a/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs b/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs new file mode 100644 index 0000000..6083990 --- /dev/null +++ b/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs @@ -0,0 +1,72 @@ +using JiShe.CollectBus.Core.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace JiShe.CollectBus.Core.Plugins +{ + public class TcpServiceReceivedPlugin : PluginBase, ITcpReceivedPlugin, ITcpConnectingPlugin, ITcpConnectedPlugin, ITcpClosedPlugin + { + public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e) + { + //TODO:根据指令区别是376还是645协议 + + var protocolType = ""; + switch (protocolType) + { + case "376": + //todo:登录拿到设备信息,根据设备信息使用不同的协议解析服务 + + break; + case "645": + //todo: 直接拿设备信息,根据设备信息使用不同的协议解析服务 + break; + default: + break; + } + + + //从客户端收到信息 + var messageHexString = Convert.ToHexString(e.ByteBlock.Span); + client.Logger.Info($"[TCP] 已从{client.GetIPPort()}接收到信息:{messageHexString}"); + + + await e.InvokeNext(); + } + + public async Task OnTcpConnecting(ITcpSession client, ConnectingEventArgs e) + { + if (client is ITcpSessionClient sessionClient) + { + client.Logger.Info($"[TCP] ID:{sessionClient.Id} IP:{client.GetIPPort()}正在连接中..."); + } + + await e.InvokeNext(); + + } + + public async Task OnTcpConnected(ITcpSession client, ConnectedEventArgs e) + { + if (client is ITcpSessionClient sessionClient) + { + client.Logger.Info($"[TCP] ID:{sessionClient.Id} IP:{client.GetIPPort()}已连接"); + } + + await e.InvokeNext(); + } + + public async Task OnTcpClosed(ITcpSession client, ClosedEventArgs e) + { + if (client is ITcpSessionClient sessionClient) + { + client.Logger.Info($"[TCP] ID:{sessionClient.Id} IP:{client.GetIPPort()}已关闭连接"); + + } + await e.InvokeNext(); + } + } +} diff --git a/JiShe.CollectBus.Core/Plugins/UdpServiceReceivedPlugin.cs b/JiShe.CollectBus.Core/Plugins/UdpServiceReceivedPlugin.cs new file mode 100644 index 0000000..3f1ddfa --- /dev/null +++ b/JiShe.CollectBus.Core/Plugins/UdpServiceReceivedPlugin.cs @@ -0,0 +1,19 @@ +using System.Text; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace JiShe.CollectBus.Core.Plugins +{ + public class UdpServiceReceivedPlugin : PluginBase, IUdpReceivedPlugin + { + public async Task OnUdpReceived(IUdpSessionBase client, UdpReceivedDataEventArgs e) + { + + var udpSession = client as UdpSession; + udpSession?.Logger.Info($"[TCP] 收到:{e.ByteBlock.Span.ToString(Encoding.UTF8)}"); + await udpSession.SendAsync("[TCP] 收到"); + + await e.InvokeNext(); + } + } +} diff --git a/JiShe.CollectBus.Core/Services/BusService.cs b/JiShe.CollectBus.Core/Services/BusService.cs new file mode 100644 index 0000000..ef306f5 --- /dev/null +++ b/JiShe.CollectBus.Core/Services/BusService.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace JiShe.CollectBus.Core.Services +{ + public class BusService : PluginBase, IServerStartedPlugin, IServerStopedPlugin + { + public Task OnServerStarted(IServiceBase sender, ServiceStateEventArgs e) + { + switch (sender) + { + case ITcpService service: + { + foreach (var item in service.Monitors) + { + ConsoleLogger.Default.Info($"TCP {item.Option.IpHost}"); + } + + break; + } + case UdpSession session: + ConsoleLogger.Default.Info($"UDP {session.Monitor.IPHost}"); + break; + } + + ConsoleLogger.Default.Info(e.ServerState == ServerState.Running + ? $"服务器成功启动" + : $"服务器启动失败,状态:{e.ServerState},异常:{e.Exception}"); + return e.InvokeNext(); + } + + public Task OnServerStoped(IServiceBase sender, ServiceStateEventArgs e) + { + Console.WriteLine("服务已停止"); + return e.InvokeNext(); + } + } +} diff --git a/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs b/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs new file mode 100644 index 0000000..2ccdb53 --- /dev/null +++ b/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using JiShe.CollectBus.Protocol.Contracts.Interfaces; +using Microsoft.Extensions.Caching.Distributed; + +namespace JiShe.CollectBus.Protocol.Contracts.Abstracts +{ + public abstract class BaseProtocolPlugin:IProtocolPlugin + { + private readonly IDistributedCache _cache; + + protected BaseProtocolPlugin(IDistributedCache cache) + { + _cache = cache; + } + + public abstract Models.Protocol Get(); + + public abstract void Received(); + + public abstract void Send(); + + public void Load() + { + var result = _cache.GetString("myKey"); + if (result == null) + { + result = "Calculated Data"; + _cache.SetString("myKey", result, new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10) + }); + } + } + + } +} diff --git a/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs b/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs new file mode 100644 index 0000000..fe54005 --- /dev/null +++ b/JiShe.CollectBus.Protocol.Contracts/Interfaces/IProtocolPlugin.cs @@ -0,0 +1,15 @@ +using JiShe.CollectBus.Protocol.Contracts.Models; + +namespace JiShe.CollectBus.Protocol.Contracts.Interfaces +{ + public interface IProtocolPlugin + { + Models.Protocol Get(); + + void Load(); + + void Received(); + + void Send(); + } +} diff --git a/JiShe.CollectBus.Protocol.Contracts/JiShe.CollectBus.Protocol.Contracts.csproj b/JiShe.CollectBus.Protocol.Contracts/JiShe.CollectBus.Protocol.Contracts.csproj new file mode 100644 index 0000000..8be6c70 --- /dev/null +++ b/JiShe.CollectBus.Protocol.Contracts/JiShe.CollectBus.Protocol.Contracts.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.1 + enable + + + + + + + diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/IProtocol.cs b/JiShe.CollectBus.Protocol.Contracts/Models/IProtocol.cs new file mode 100644 index 0000000..ba7ac3e --- /dev/null +++ b/JiShe.CollectBus.Protocol.Contracts/Models/IProtocol.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JiShe.CollectBus.Protocol.Contracts.Models +{ + public interface IProtocol + { + /// + /// 协议名称 + /// + string Name { get; set; } + + /// + /// 基础协议 376.1/645 + /// + string BaseProtocol { get; set; } + + /// + /// 协议类型 TCP/UDP + /// + string Type { get; set; } + + /// + /// 协议备注 + /// + string Description { get; set; } + + /// + /// 型号正则匹配 + /// + string RegularExpression { get; set; } + } +} diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/Protocol.cs b/JiShe.CollectBus.Protocol.Contracts/Models/Protocol.cs new file mode 100644 index 0000000..0abc809 --- /dev/null +++ b/JiShe.CollectBus.Protocol.Contracts/Models/Protocol.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JiShe.CollectBus.Protocol.Contracts.Models +{ + public class Protocol:IProtocol + { + public Protocol(string name, string baseProtocol, string type, string description, string regularExpression) + { + Name = name; + Type = type; + Description = description; + RegularExpression = regularExpression; + BaseProtocol = baseProtocol; + } + + /// + /// 协议名称 + /// + public string Name { get; set; } + + /// + /// 基础协议 376.1/645 + /// + public string BaseProtocol { get; set; } + + /// + /// 协议类型 TCP/UDP + /// + public string Type { get; set; } + + /// + /// 协议备注 + /// + public string Description { get; set; } + + /// + /// 型号正则匹配 + /// + public string RegularExpression { get; set; } + } +} diff --git a/JiShe.CollectBus.Protocol/Abstracts/BaseProtocolPlugin.cs b/JiShe.CollectBus.Protocol/Abstracts/BaseProtocolPlugin.cs new file mode 100644 index 0000000..aec53c7 --- /dev/null +++ b/JiShe.CollectBus.Protocol/Abstracts/BaseProtocolPlugin.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using JiShe.CollectBus.Protocol.Contracts.Interfaces; + +namespace JiShe.CollectBus.Protocol.Contracts.Abstracts +{ + public abstract class BaseProtocolPlugin:IProtocolPlugin + { + public abstract Models.Protocol Get(); + + public abstract void Received(); + + public abstract void Send(); + + public void Load() + { + + } + + } +} diff --git a/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj b/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj new file mode 100644 index 0000000..8fdf043 --- /dev/null +++ b/JiShe.CollectBus.Protocol/JiShe.CollectBus.Protocol.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs b/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs new file mode 100644 index 0000000..bf25b61 --- /dev/null +++ b/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs @@ -0,0 +1,27 @@ +using JiShe.CollectBus.Protocol.Contracts.Interfaces; + +namespace JiShe.CollectBus.Protocol +{ + public class StandardProtocolPlugin:IProtocolPlugin + { + public Contracts.Models.Protocol Get() + { + return new Contracts.Models.Protocol("Standard", "376.1", "TCP","376.1协议","DTS1980"); + } + + public void Load() + { + throw new NotImplementedException(); + } + + public void Received() + { + throw new NotImplementedException(); + } + + public void Send() + { + throw new NotImplementedException(); + } + } +} diff --git a/JiShe.CollectBus.sln b/JiShe.CollectBus.sln new file mode 100644 index 0000000..2073a2d --- /dev/null +++ b/JiShe.CollectBus.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Core", "JiShe.CollectBus.Core\JiShe.CollectBus.Core.csproj", "{F1360C93-5B6B-4E65-9D81-1DA38740F32D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Console", "JiShe.CollectBus.Console\JiShe.CollectBus.Console.csproj", "{40C4F834-3080-451B-9510-6FE7BC4F801F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol", "JiShe.CollectBus.Protocol\JiShe.CollectBus.Protocol.csproj", "{B2C476F1-AE32-419D-BDA2-291FCE639CF6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.Contracts", "JiShe.CollectBus.Protocol.Contracts\JiShe.CollectBus.Protocol.Contracts.csproj", "{4468B52D-3AAE-4918-B4D6-E6E8F000825D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Common", "JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj", "{1D3A5A4E-B977-4E33-A1AF-62508110C3B7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F1360C93-5B6B-4E65-9D81-1DA38740F32D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1360C93-5B6B-4E65-9D81-1DA38740F32D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1360C93-5B6B-4E65-9D81-1DA38740F32D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1360C93-5B6B-4E65-9D81-1DA38740F32D}.Release|Any CPU.Build.0 = Release|Any CPU + {40C4F834-3080-451B-9510-6FE7BC4F801F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40C4F834-3080-451B-9510-6FE7BC4F801F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40C4F834-3080-451B-9510-6FE7BC4F801F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40C4F834-3080-451B-9510-6FE7BC4F801F}.Release|Any CPU.Build.0 = Release|Any CPU + {B2C476F1-AE32-419D-BDA2-291FCE639CF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2C476F1-AE32-419D-BDA2-291FCE639CF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2C476F1-AE32-419D-BDA2-291FCE639CF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2C476F1-AE32-419D-BDA2-291FCE639CF6}.Release|Any CPU.Build.0 = Release|Any CPU + {4468B52D-3AAE-4918-B4D6-E6E8F000825D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4468B52D-3AAE-4918-B4D6-E6E8F000825D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4468B52D-3AAE-4918-B4D6-E6E8F000825D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4468B52D-3AAE-4918-B4D6-E6E8F000825D}.Release|Any CPU.Build.0 = Release|Any CPU + {1D3A5A4E-B977-4E33-A1AF-62508110C3B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D3A5A4E-B977-4E33-A1AF-62508110C3B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D3A5A4E-B977-4E33-A1AF-62508110C3B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D3A5A4E-B977-4E33-A1AF-62508110C3B7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {33261859-9CD1-4A43-B181-AB75C247D1CD} + EndGlobalSection +EndGlobal