From 174efc6a820f3a48db5d0efcb6b3ec2537d6771f Mon Sep 17 00:00:00 2001 From: fajiao <1519100073@qq.com> Date: Mon, 24 Apr 2023 18:00:21 +0800 Subject: [PATCH] =?UTF-8?q?2023=E5=B9=B44=E6=9C=8824=E6=97=A518:00:12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/AlarmServiceFactory.cs | 2 +- JiLinApp.Biz/TransmitAlarm/Common/Config.cs | 9 +- .../TransmitAlarm/Entity/AlarmMessage.cs | 28 +- .../Entity/AlarmMessageHelper.cs | 32 +- .../TransmitAlarm/Service/AlarmMqttService.cs | 88 +- .../TransmitAlarm/Service/AlarmZmqService.cs | 5 + .../Service/Interfaces/IAlarmService.cs | 2 + .../FenceAlarm/Entity/SectorState.cs | 72 +- .../FenceAlarm/Entity/UdpAlarmHost.cs | 148 +++ .../FenceAlarm/Entity/UdpAlarmHostDevice.cs | 172 --- .../FenceAlarm/Entity/UdpAlarmHostMessage.cs | 10 +- .../FenceAlarm/Service/AlarmEncode.cs | 269 ++-- .../FenceAlarm/Service/UdpManager.cs | 1159 ++++++++--------- .../Service/{Udp.cs => UdpServer.cs} | 94 +- .../VibrateAlarm/Entity/ClientMessage.cs | 2 +- .../{TcpAlarmHostTable.cs => TcpAlarmHost.cs} | 2 +- .../Entity/TcpAlarmHostMessage.cs | 2 +- .../VibrateAlarm/Service/AsyncTcpServer.cs | 83 +- .../VibrateAlarm/Service/TcpManager.cs | 182 +-- JiLinApp/Core/Config.cs | 4 +- JiLinApp/Core/Global.cs | 4 +- JiLinApp/Pages/FenceServerManage/Main.xaml.cs | 8 +- .../Pages/FenceServerManage/MainViewModel.cs | 4 +- JiLinApp/Pages/PtzManage/Main.xaml.cs | 8 +- .../VibrateServerManage/MainViewModel.cs | 4 +- JiLinApp/config/config.json | 14 +- 26 files changed, 1204 insertions(+), 1203 deletions(-) create mode 100644 JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHost.cs delete mode 100644 JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs rename JiLinApp.Docking/FenceAlarm/Service/{Udp.cs => UdpServer.cs} (57%) rename JiLinApp.Docking/VibrateAlarm/Entity/{TcpAlarmHostTable.cs => TcpAlarmHost.cs} (89%) diff --git a/JiLinApp.Biz/TransmitAlarm/Common/AlarmServiceFactory.cs b/JiLinApp.Biz/TransmitAlarm/Common/AlarmServiceFactory.cs index e2a3e1f..37fdfb1 100644 --- a/JiLinApp.Biz/TransmitAlarm/Common/AlarmServiceFactory.cs +++ b/JiLinApp.Biz/TransmitAlarm/Common/AlarmServiceFactory.cs @@ -2,7 +2,7 @@ public class AlarmServiceFactory { - public static IAlarmService CreateService(TransmitAlarmConfig config) + public static IAlarmService CreateService(AlarmPlatformConfig config) { IAlarmService service = (config.Type) switch { diff --git a/JiLinApp.Biz/TransmitAlarm/Common/Config.cs b/JiLinApp.Biz/TransmitAlarm/Common/Config.cs index 1dc5ee0..b35b574 100644 --- a/JiLinApp.Biz/TransmitAlarm/Common/Config.cs +++ b/JiLinApp.Biz/TransmitAlarm/Common/Config.cs @@ -1,6 +1,6 @@ namespace JiLinApp.Biz.TransmitAlarm; -public class TransmitAlarmConfig +public class AlarmPlatformConfig { public bool RealPlay { get; set; } @@ -11,6 +11,8 @@ public class TransmitAlarmConfig public class MqttConfig { + public string Ip { get; set; } + public int Port { get; set; } public string UserName { get; set; } @@ -19,7 +21,10 @@ public class MqttConfig public string ClientId { get; set; } - public string TransmitTopic { get; set; } + public string PubAlarmTopic { get; set; } + + public string SubTopic { get; set; } + } public class ZmqConfig diff --git a/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessage.cs b/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessage.cs index 9dfdbdb..449aff4 100644 --- a/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessage.cs +++ b/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessage.cs @@ -3,32 +3,32 @@ public class AlarmMessage { /** (必填)传感器设备编码*/ - public string labelCode; + public string LabelCode { get; set; } + public int ChannelId { get; set; } /** (必填)报警类型((1-视频报警,2-雷达报警;3-微振动警报,4-电子围网警报,9-其他报警))*/ - public int warnType; + public int WarnType { get; set; } /** (必填)报警级别(1-5)*/ - public int warnLevel; + public int WarnLevel { get; set; } /** (必填)报警内容*/ - public string warnContent; - public int ChannelNum; + public string WarnContent { get; set; } /** 处置方式*/ - public int dealWay; + public int DealWay { get; set; } /** (必填)处置状态(1-未处理,2-已处理)*/ - public int dealStatus; + public int DealStatus { get; set; } /** (必填)发生地点*/ - public string cameraLoc; + public string CameraLoc { get; set; } /** (必填)发生时间*/ - public DateTime createTime; + public DateTime CreateTime { get; set; } /** 负责人*/ - public string director; + public string Director { get; set; } /** (必填)类型(1-预警,2-报警,3-故障,)*/ - public int kind; + public int Kind { get; set; } /** 现场照片*/ - public string imgUrl; + public string ImgUrl { get; set; } public override string ToString() { - return string.Format("{{ labelCode:{0}, warnType:{1}, warnLevel:{2}, warnContent:{3}, createTime:{4} }}", - labelCode, warnType, warnLevel, warnContent, createTime); + return string.Format("{{ labelCode:{0}, channelId:{1}, warnType:{2}, warnLevel:{3}, warnContent:{4}, createTime:{5} }}", + LabelCode, ChannelId, WarnType, WarnLevel, WarnContent, CreateTime); } } \ No newline at end of file diff --git a/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessageHelper.cs b/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessageHelper.cs index aed29c0..56c6199 100644 --- a/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessageHelper.cs +++ b/JiLinApp.Biz/TransmitAlarm/Entity/AlarmMessageHelper.cs @@ -11,14 +11,14 @@ public static class AlarmMessageHelper AlarmCode code = AlarmCodeHelper.Get(msg.CID); AlarmMessage obj = new() { - labelCode = Convert.ToString(msg.DeviceID), - warnType = 3, - warnLevel = code.Level, - warnContent = code.Content, - ChannelNum = Convert.ToInt32(msg.ChannelNum), - dealStatus = 1, - createTime = Convert.ToDateTime(msg.AlarmTime), - kind = 2, + LabelCode = Convert.ToString(msg.DeviceID), + ChannelId = Convert.ToInt32(msg.SensorAddr), + WarnType = 3, + WarnLevel = code.Level, + WarnContent = code.Content, + DealStatus = 1, + CreateTime = Convert.ToDateTime(msg.AlarmTime), + Kind = 2, }; return obj; } @@ -28,14 +28,14 @@ public static class AlarmMessageHelper AlarmCode code = AlarmCodeHelper.Get(msg.CID); AlarmMessage obj = new() { - labelCode = Convert.ToString(msg.DeviceID), - warnType = 4, - warnLevel = code.Level, - warnContent = code.Content, - ChannelNum = msg.ChannelNum, - dealStatus = 1, - createTime = Convert.ToDateTime(msg.AlarmTime), - kind = 2, + LabelCode = Convert.ToString(msg.DeviceId), + ChannelId = msg.SectorId, + WarnType = 4, + WarnLevel = code.Level, + WarnContent = code.Content, + DealStatus = 1, + CreateTime = Convert.ToDateTime(msg.AlarmTime), + Kind = 2, }; return obj; } diff --git a/JiLinApp.Biz/TransmitAlarm/Service/AlarmMqttService.cs b/JiLinApp.Biz/TransmitAlarm/Service/AlarmMqttService.cs index b18af28..501c0ba 100644 --- a/JiLinApp.Biz/TransmitAlarm/Service/AlarmMqttService.cs +++ b/JiLinApp.Biz/TransmitAlarm/Service/AlarmMqttService.cs @@ -1,8 +1,6 @@ using EC.Util.Common; using MQTTnet; using MQTTnet.Client; -using MQTTnet.Protocol; -using MQTTnet.Server; using System.Text; namespace JiLinApp.Biz.TransmitAlarm; @@ -13,28 +11,33 @@ public class AlarmMqttService : IAlarmService private MqttConfig Config { get; } - private MqttServer Server { get; } + //private MqttServer Server { get; } private IMqttClient Client { get; } + private MqttClientOptions ClientOptions { get; } + + private MqttClientSubscribeOptions SubscribeOptions { get; } + #endregion Fields public AlarmMqttService(MqttConfig config) { MqttFactory factory = new(); - MqttServerOptions options = new MqttServerOptionsBuilder() - .WithDefaultEndpoint() - .WithDefaultEndpointPort(config.Port) - .Build(); - MqttServer server = factory.CreateMqttServer(options); - server.ValidatingConnectionAsync += Server_ValidatingConnectionAsync; - server.ClientConnectedAsync += Server_ClientConnectedAsync; - server.ClientDisconnectedAsync += Server_ClientDisconnectedAsync; - server.ClientAcknowledgedPublishPacketAsync += Server_ClientAcknowledgedPublishPacketAsync; IMqttClient client = factory.CreateMqttClient(); + client.ApplicationMessageReceivedAsync += Client_ApplicationMessageReceivedAsync; + ClientOptions = factory.CreateClientOptionsBuilder() + .WithTcpServer(config.Ip, config.Port) + .WithClientId(config.ClientId) + .WithCredentials(config.UserName, config.Password) + .WithCleanSession(false) + .WithKeepAlivePeriod(TimeSpan.FromSeconds(60)) + .Build(); + SubscribeOptions = factory.CreateSubscribeOptionsBuilder() + .WithTopicFilter(f => f.WithTopic("mqttnet/samples/topic/1")) + .Build(); Config = config; - Server = server; Client = client; } @@ -47,43 +50,38 @@ public class AlarmMqttService : IAlarmService public void Start() { - Server.StartAsync().Wait(); - ClientConnServer(); + if (IsRuning()) return; + MqttClientConnectResult connResult = Client.ConnectAsync(ClientOptions, CancellationToken.None).Result; + MqttClientSubscribeResult subResult = Client.SubscribeAsync(SubscribeOptions, CancellationToken.None).Result; } public void Close() { + if (!IsRuning()) return; Client.DisconnectAsync().Wait(); - Server.StopAsync().Wait(); } - private void ClientConnServer() + public bool IsRuning() { - if (Client.IsConnected) return; - MqttClientOptions mqttClientOptions = new MqttClientOptionsBuilder() - .WithTcpServer("127.0.0.1", Config.Port) - .WithClientId(Config.ClientId) - .WithCredentials(Config.UserName, Config.Password) - .Build(); - Client.ConnectAsync(mqttClientOptions, CancellationToken.None); + return Client != null && Client.IsConnected; } public void SendAlarmMessage(AlarmMessage msg) { MqttApplicationMessage mqttMsg = new MqttApplicationMessageBuilder() - .WithTopic(Config.TransmitTopic) + .WithTopic(Config.PubAlarmTopic) .WithPayload(JsonUtil.ToJson(msg)) .Build(); - MqttClientPublishResult? result = null; - while (result == null || !result.IsSuccess) + MqttClientPublishResult? pubResult = null; + while (pubResult == null || !pubResult.IsSuccess) { try { - result = Client.PublishAsync(mqttMsg, CancellationToken.None).Result; + pubResult = Client.PublishAsync(mqttMsg, CancellationToken.None).Result; } catch (Exception) { - ClientConnServer(); + Start(); Thread.Sleep(100); } } @@ -91,34 +89,16 @@ public class AlarmMqttService : IAlarmService #endregion Base - #region Server Event - - private Task Server_ValidatingConnectionAsync(ValidatingConnectionEventArgs arg) - { - if (arg.ClientId.Length == 0) arg.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid; - else if (arg.UserName != Config.UserName) arg.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; - else if (arg.Password != Config.Password) arg.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; - return Task.CompletedTask; - } - - private Task Server_ClientConnectedAsync(ClientConnectedEventArgs arg) - { - return Task.CompletedTask; - } - - private Task Server_ClientDisconnectedAsync(ClientDisconnectedEventArgs arg) - { - return Task.CompletedTask; - } + #region Receive - private Task Server_ClientAcknowledgedPublishPacketAsync(ClientAcknowledgedPublishPacketEventArgs arg) + private Task Client_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg) { - string clientId = arg.ClientId; - ushort packetIdentifier = arg.PublishPacket.PacketIdentifier; - string topic = arg.PublishPacket.Topic; - string msg = Encoding.UTF8.GetString(arg.PublishPacket.Payload); + string topic = arg.ApplicationMessage.Topic; + string text = Encoding.UTF8.GetString(arg.ApplicationMessage.Payload); + string qos = arg.ApplicationMessage.QualityOfServiceLevel.ToString(); + string retained = arg.ApplicationMessage.Retain.ToString(); return Task.CompletedTask; } - #endregion Server Event + #endregion Receive } \ No newline at end of file diff --git a/JiLinApp.Biz/TransmitAlarm/Service/AlarmZmqService.cs b/JiLinApp.Biz/TransmitAlarm/Service/AlarmZmqService.cs index ad12ecf..db09aac 100644 --- a/JiLinApp.Biz/TransmitAlarm/Service/AlarmZmqService.cs +++ b/JiLinApp.Biz/TransmitAlarm/Service/AlarmZmqService.cs @@ -12,6 +12,11 @@ public class AlarmZmqService : IAlarmService throw new NotImplementedException(); } + public bool IsRuning() + { + throw new NotImplementedException(); + } + public void SendAlarmMessage(AlarmMessage msg) { throw new NotImplementedException(); diff --git a/JiLinApp.Biz/TransmitAlarm/Service/Interfaces/IAlarmService.cs b/JiLinApp.Biz/TransmitAlarm/Service/Interfaces/IAlarmService.cs index baff02d..3c65d34 100644 --- a/JiLinApp.Biz/TransmitAlarm/Service/Interfaces/IAlarmService.cs +++ b/JiLinApp.Biz/TransmitAlarm/Service/Interfaces/IAlarmService.cs @@ -6,5 +6,7 @@ public interface IAlarmService void Close(); + bool IsRuning(); + void SendAlarmMessage(AlarmMessage msg); } \ No newline at end of file diff --git a/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs b/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs index 233a767..80918cf 100644 --- a/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs +++ b/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs @@ -5,58 +5,60 @@ public class SectorState #region Fields public int Id { get; set; }//防区号 - /*0:防区未使用 - 1:防区撤防 - 2:防区布防 - 3:防区旁路 - 4:防区报警 - 5:无线防区欠压 - 6:防区掉线(与主线总线脱离) - */ + + /// + /// 0: 防区未使用 + /// 1: 防区撤防 + /// 2: 防区布防 + /// 3: 防区旁路 + /// 4: 防区报警 + /// 5: 无线防区欠压 + /// 6: 防区掉线(与主线总线脱离) + /// public int State { get; set; }//防区状态 public string StateStr { get { - switch (State) + return State switch { - case 0: return "防区未使用"; - case 1: return "防区撤防"; - case 2: return "防区布防"; - case 3: return "防区旁路"; - case 4: return "防区报警"; - case 5: return "无线防区欠压"; - case 6: return "防区掉线"; - default: return "未知状态:" + State; - } + 0 => "防区未使用", + 1 => "防区撤防", + 2 => "防区布防", + 3 => "防区旁路", + 4 => "防区报警", + 5 => "无线防区欠压", + 6 => "防区掉线", + _ => "未知状态:" + State, + }; } } - /* - 0:普通防区,无特殊参数 - 1:张力防区需要单独查询因为这个防区显示张力线值每条线状态 - 2:脉冲围栏 - 3:振动光纤 - 4:泄漏电缆 - 5:网络或总线多子防区模块 - */ + /// + /// 0: 普通防区,无特殊参数 + /// 1: 张力防区需要单独查询因为这个防区显示张力线值每条线状态 + /// 2: 脉冲围栏 + /// 3: 振动光纤 + /// 4: 泄漏电缆 + /// 5: 网络或总线多子防区模块 + /// public int Type { get; set; }//防区类型,特殊参数需单独查询 public string TypeStr { get { - switch (Type) + return Type switch { - case 0: return "普通防区"; - case 1: return "张力防区"; - case 2: return "脉冲围栏"; - case 3: return "振动光纤"; - case 4: return "泄漏电缆"; - case 5: return "网络或总线多子防区模块"; - default: return "未知类型:" + Type; - } + 0 => "普通防区", + 1 => "张力防区", + 2 => "脉冲围栏", + 3 => "振动光纤", + 4 => "泄漏电缆", + 5 => "网络或总线多子防区模块", + _ => "未知类型:" + Type, + }; } } diff --git a/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHost.cs b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHost.cs new file mode 100644 index 0000000..830c114 --- /dev/null +++ b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHost.cs @@ -0,0 +1,148 @@ +using System.Collections.Concurrent; + +namespace JiLinApp.Docking.FenceAlarm; + +public class UdpAlarmHost +{ + public int DeviceId { get; set; } + + public string Ip { get; set; } + + public int Port { get; set; } + + public int GroupId { get; set; }//分组号,报警主机可划入不同组 + + public int UserId { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分 + + /// + /// 0x00: 撤防状态 + /// 0x01: 外出布防(普通布防最常用) + /// 0x02: 即时布防(所有防区没有延时) + /// 0x04: 在家布防(留守布防有些防区可能是在旁路状态) + /// 0x08: 即时留守布防(有些防区可能旁路, 但是没有旁路防区没有延时) + /// 0x09: 部分防区布防部分防区撤防 + /// + public int DefenceState { get; set; }//主机布撤状态 + + public string DefenceStateStr + { + get + { + return DefenceState switch + { + 0x00 => "撤防状态", + 0x01 => "外出布防", + 0x02 => "即时布防", + 0x04 => "在家布防", + 0x08 => "即时留守布防", + 0x09 => "部分防区布防", + _ => "未知状态号:" + DefenceState, + }; + } + } + + /// + /// 0x00:此设备处于常规工作状态,正常报警 + /// 0x01:工作在设置模式,不会处理报警,用户这进行设置,设置完一般很快退出 + /// 0x02:用户正在查询当前报警信息 + /// 0x03:用户正在设置时钟 + /// 0x04:工作在用户密码修改模式下 + /// + public int WorkState { get; set; }//设备工作状态 + + public string WorkStateStr + { + get + { + return DefenceState switch + { + 0x00 => "常规工作状态", + 0x01 => "在设置模式", + 0x02 => "用户正在查询报警", + 0x03 => "用户正在设置时钟", + 0x04 => "用户密码修改模式", + _ => "未知状态号:" + WorkState, + }; + } + } + + public int CellState { get; set; }//电池状态 1=电池故障 0=电池正常 + public int ElectricityState { get; set; }//交流状态 1=交流掉电 0=交流正常 + public int FuseState { get; set; }//警保险丝状态 1=外接警号断了0=正常 + public int SectorState { get; set; }//有线防区触发了 1=其中有线防区触发了 0=所有有线防区准备好 + public int CellTestState { get; set; }//正在电池载能测试 1=主机正在进行电池载能测试 0=无(主机会降低电压到电池12V以下,来测试电池负载特性需要2分钟) + public int DeviceElectricityState { get; set; }//设备交流电状态1=交流掉电,目前电池供电0=正常 这是即时状态 + public int SoundState { get; set; }//设备声音输出状态(=0关闭声音) =1 输出声音) 用于布防和报警延时 + public int TestState { get; set; }//主机本地测试状态1=主机在本地测试(用于测试探测好坏是没有报警记录的)0=无 + + public int CriticalAlarmState { get; set; }//软防区紧急报警状态1=有紧急报警(用户通过手动按下主机自带装置报警) 0=无 + public int FireAlarmState { get; set; }//软防区火警报警状态1=有火警报警(用户通过手动按下主机自带装置报警) 0=无 + public int StealAlarmState { get; set; }//软防区盗警报警状态1=有盗警报警(用户通过手动按下主机自带装置报警) 0=无 + public int DeviceFireAlarmState { get; set; }//设备中有火警报警状态 1=其中有火警防区触发了 0=无 整体状态 + public int DeviceAlarmState { get; set; }//设备有报警发生 1=指设备有报警状态,任一一种0=无报警 + public int DeviceBywayState { get; set; }//设备有旁路防区1=指设备某些防区有旁路了(这时软件可以要求上传具体旁路的防区) 2=无防区旁路 + public int BusOfflineState { get; set; }//有总线防区掉线状态1=指某些总线防区掉线了0=无 + public int NetOfflineState { get; set; }//有网络防区掉线状态1=指某些网络防区掉线了0=无 + + /// + /// 00: 通用设备兼容没有设置或未知设备 + /// 01: EH508报警主机 + /// 02: EH508NP网络模块 + /// 03: NETLINKBOARD32路网络模块 + /// 04: EH508NETCILENT网络终端 + /// 05: EH8008路光纤主机 + /// 06: EH508NP_UDP私有服务器网络模块 + /// 07: EH508CILENT_UDP私有服务器接警终端 + /// 08: EH508SEVER_UDP私有服务器主机 + /// 09: EH508MAP_UDP私有服务器电子地图 + /// 0A: EH508_UDP私有服务器用EH508主机 + /// 0x32: H768_IP系列网络模块 + /// 0x33: D238C_IP网络模块 + /// 0x34: H778S+系列报警主机 + /// 0x35: H778S系列报警主机 + /// 0x36: N201N202网络模块 + /// + public int DevideType { get; set; }//设备类型:区分不同的设备类型 增强可控,防止混乱,具体的设备类型见附加说明表格 + + public int SignalIntensity { get; set; }//31:信号最强,如果设备类型不是这种不需要显示 指主要带有GPRS模块设备跟据设备类型来的 + + //-------------------------------防区信息-----------------------------// + + public int SectorTotal { get; set; }//分区总数量 + + public ConcurrentDictionary SectorDict { get; } + + public int OnlineState { get; set; }//设备在线状态 + + public int KeepLive { get; set; }//设备在线状态 + + public UdpAlarmHost() + { + DeviceId = 0; + GroupId = 0; + UserId = 0; + DefenceState = -1; + WorkState = 0; + CellState = 0; + ElectricityState = 0; + FuseState = 0; + SectorState = 0; + CellTestState = 0; + DeviceElectricityState = 0; + SoundState = 0; + TestState = 0; + CriticalAlarmState = 0; + FireAlarmState = 0; + StealAlarmState = 0; + DeviceFireAlarmState = 0; + DeviceAlarmState = 0; + DeviceBywayState = 0; + BusOfflineState = 0; + NetOfflineState = 0; + DevideType = 0; + SignalIntensity = 0; + SectorTotal = 0; + OnlineState = 0; + SectorDict = new(); + } +} \ No newline at end of file diff --git a/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs deleted file mode 100644 index 5dc29df..0000000 --- a/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs +++ /dev/null @@ -1,172 +0,0 @@ -namespace JiLinApp.Docking.FenceAlarm; - -public class UdpAlarmHostDevice -{ - public int deviceID { get; set; }//设备唯一ID - - public string Ip { get; set; }//设备Ip - - public int Port { get; set; } //设备端口 - - public int GroupID { get; set; }//分组号,报警主机可划入不同组 - - public int UserID { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分 - /*0x00: 撤防状态 - 0x04: 在家布防(留守布防有些防区可能是在旁路状态) - 0x02:即时布防(所有防区没有延时) - 0x08 :即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时) - 0x01:外出布防(普通布防最常用) - 0x09:部分防区布防部分防区撤防 - */ - public int deviceState { get; set; }//主机布撤状态, - - public string deviceStateStr - { - get - { - switch (deviceState) - { - case 0x00: - return "撤防状态"; - - case 0x01: - return "外出布防"; - - case 0x02: - return "即时布防"; - - case 0x04: - return "在家布防"; - - case 0x08: - return "即时留守布防"; - - case 0x09: - return "部分防区布防"; - - default: - return "未知状态号:" + deviceState; - } - } - } - - /*0x00:此设备处于常规工作状态,正常报警 - 0x01:工作在设置模式,不会处理报警,用户这进行设置,设置完一般很快退出 - 0x02:用户正在查询当前报警信息 - 0x03:用户正在设置时钟 - 0x04:工作在用户密码修改模式下 - */ - public int deviceWorkState { get; set; }//设备工作状态 - - public string deviceWorkStateStr - { - get - { - switch (deviceState) - { - case 0x00: - return "常规工作状态"; - - case 0x01: - return "在设置模式"; - - case 0x02: - return "用户正在查询报警"; - - case 0x03: - return "用户正在设置时钟"; - - case 0x04: - return "用户密码修改模式"; - - default: - return "未知状态号:" + deviceWorkState; - } - } - } - - public int cellState { get; set; }//电池状态 1=电池故障 0=电池正常 - public int electricityState { get; set; }//交流状态 1=交流掉电 0=交流正常 - public int fuseState { get; set; }//警保险丝状态 1=外接警号断了0=正常 - public int sectorState { get; set; }//有线防区触发了 1=其中有线防区触发了 0=所有有线防区准备好 - public int cellTestState { get; set; }//正在电池载能测试 1=主机正在进行电池载能测试 0=无(主机会降低电压到电池12V以下,来测试电池负载特性需要2分钟) - public int deviceElectricityState { get; set; }//设备交流电状态1=交流掉电,目前电池供电0=正常 这是即时状态 - public int soundState { get; set; }//设备声音输出状态(=0关闭声音) =1 输出声音) 用于布防和报警延时 - public int testState { get; set; }//主机本地测试状态1=主机在本地测试(用于测试探测好坏是没有报警记录的)0=无 - - public int criticalAlarmState { get; set; }//软防区紧急报警状态1=有紧急报警(用户通过手动按下主机自带装置报警) 0=无 - public int fireAlarmState { get; set; }//软防区火警报警状态1=有火警报警(用户通过手动按下主机自带装置报警) 0=无 - public int stealAlarmState { get; set; }//软防区盗警报警状态1=有盗警报警(用户通过手动按下主机自带装置报警) 0=无 - public int deviceFireAlarmState { get; set; }//设备中有火警报警状态 1=其中有火警防区触发了 0=无 整体状态 - public int deviceAlarmState { get; set; }//设备有报警发生 1=指设备有报警状态,任一一种0=无报警 - public int deviceBywayState { get; set; }//设备有旁路防区1=指设备某些防区有旁路了(这时软件可以要求上传具体旁路的防区) 2=无防区旁路 - public int busOfflineState { get; set; }//有总线防区掉线状态1=指某些总线防区掉线了0=无 - public int netOfflineState { get; set; }//有网络防区掉线状态1=指某些网络防区掉线了0=无 - - /*00:通用设备兼容没有设置或未知设备 - 01:EH508报警主机 - 02:EH508NP网络模块 - 03: NETLINKBOARD32路网络模块 - 04: EH508NETCILENT网络终端 - 05: EH800 8路光纤主机 - 06: EH508NP_UDP 私有服务器网络模块 - 07: EH508CILENT_UDP 私有服务器接警终端 - 08: EH508SEVER_UDP 私有服务器主机 - 09: EH508MAP_UDP 私有服务器电子地图 - 0A: EH508_UDP 私有服务器用EH508主机 - 0x32: H768_IP系列网络模块 - 0x33: D238C_IP网络模块 - 0x34: H778S+ 系列报警主机 - 0x35: H778S系列报警主机 - 0x36:N201 N202网络模块 - */ - public int devideType { get; set; }//设备类型:区分不同的设备类型 增强可控,防止混乱,具体的设备类型见附加说明表格 - - public int signalIntensity { get; set; }//31:信号最强,如果设备类型不是这种不需要显示 指主要带有GPRS模块设备跟据设备类型来的 - - public int channelNum { get; set; }//分区数量 - - public List channelState { get; set; }//分区布防撤防状态,0为撤防,1为布防 - public List channelAlarmState { get; set; }//分区报警状态,0为报警中,1为未报警 - - //-------------------------------防区信息-----------------------------// - public int maxSectorNum { get; set; }//最大防区号 - - public List sectorList { get; set; } - - public int deviceOnlineState { get; set; }//设备在线状态 - - public int keep_live { get; set; }//设备在线状态 - - public UdpAlarmHostDevice() - { - deviceID = 0; - GroupID = 0; - UserID = 0; - deviceState = -1; - deviceWorkState = 0; - cellState = 0; - electricityState = 0; - fuseState = 0; - sectorState = 0; - cellTestState = 0; - deviceElectricityState = 0; - soundState = 0; - testState = 0; - criticalAlarmState = 0; - fireAlarmState = 0; - stealAlarmState = 0; - deviceFireAlarmState = 0; - deviceAlarmState = 0; - deviceBywayState = 0; - busOfflineState = 0; - netOfflineState = 0; - devideType = 0; - signalIntensity = 0; - channelNum = 0; - channelState = null; - channelAlarmState = null; - sectorList = null; - deviceOnlineState = 0; - } -} \ No newline at end of file diff --git a/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs index a987c96..df57a8a 100644 --- a/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs +++ b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs @@ -9,12 +9,12 @@ public class UdpAlarmHostMessage public string CID { get; set; }//CID代码 /*设备信息*/ - public int DeviceID { get; set; }//设备唯一ID - public int ChannelNum { get; set; }//防区号 - public int SubChannelNum { get; set; }//子防区号 + public int DeviceId { get; set; }//设备唯一ID public string Ip { get; set; }//设备IP - public int GroupID { get; set; }//分组号,报警主机可划入不同组 - public int UserID { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分 + public int SectorId { get; set; }//防区号 + public int SubSectorId { get; set; }//子防区号 + public int GroupId { get; set; }//分组号,报警主机可划入不同组 + public int UserId { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分 public int LinkOut { get; set; }//联动输出 public string ExtendArgs { get; set; }//扩展参数 diff --git a/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs b/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs index 59e9e49..2012437 100644 --- a/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs +++ b/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs @@ -2,65 +2,66 @@ public class AlarmEncode { - private static byte[] TEA_key = new byte[16] { + #region Fields + + public static readonly byte Version = 0x12; + public static readonly byte[] Head = new byte[] { 0xF0, 0xFA }; + public static readonly byte End = 0x0D; + + public static readonly byte[] TEA_key = new byte[16] { 0x08,0x01,0x08,0x06,0x07,0x08,0x07,0x08, 0x08,0x90,0xC5,0x04,0x0D,0x0E,0x0F,0x10 }; - public static byte[] encodeMessage(byte[] msg) + #endregion Fields + + public static byte[] EncodeMessage(byte[] msg) { - if (!checkMessage(msg)) return null; - return getMessage(msg[0], btea_encrypt(getContent(msg, msg[0] - 1))); + if (!CheckMessage(msg)) return Array.Empty(); + return GetMessage(msg[0], BteaEncrypt(GetContent(msg, msg[0] - 1))); } - public static byte[] decodeMessage(byte[] msg) + public static byte[] DecodeMessage(byte[] msg) { - if (!checkMessage(msg)) return null; - return getMessage(msg[0], btea_decrpyt(getContent(msg, msg[0] - 1))); + if (!CheckMessage(msg)) return Array.Empty(); + return GetMessage(msg[0], BteaDecrpyt(GetContent(msg, msg[0] - 1))); } - public static byte[] CRC16(byte[] data) + private static bool CheckMessage(byte[] msg) { - int len = data.Length; - if (len > 0) - { - ushort crc = 0xFFFF; - - for (int i = 0; i < len; i++) - { - crc = (ushort)(crc ^ (data[i])); - for (int j = 0; j < 8; j++) - { - crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1); - } - } - byte hi = (byte)((crc & 0xFF00) >> 8); //高位置 - byte lo = (byte)(crc & 0x00FF); //低位置 - - return new byte[] { hi, lo }; - } - return new byte[] { 0, 0 }; + if (msg == null) return false; + if (msg[0] > msg.Length) return false; + return true; } - private static byte version = 0x12; - private static byte[] head = new byte[] { 0xF0, 0xFA }; - private static byte end = 0x0D; - - public static byte[] getSendMessage(byte command, byte[] data) + private static byte[] GetMessage(byte msgLen, byte[] msg) { - byte[] msg = null; - if (data == null) + byte[] outMsg = new byte[msg.Length + 1]; + outMsg[0] = msgLen; + for (int i = 0; i < msg.Length; i++) { - msg = new byte[8]; + outMsg[i + 1] = msg[i]; } - else + return outMsg; + } + + private static byte[] GetContent(byte[] msg, int len) + { + byte[] bytes = new byte[len]; + for (int i = 0; i < len; i++) { - msg = new byte[data.Length + 8]; + bytes[i] = msg[i + 1]; } + return bytes; + } + + public static byte[] GetSendMessage(byte command, byte[] data) + { + byte[] msg = data != null ? new byte[data.Length + 8] : new byte[8]; msg[0] = (byte)msg.Length; - msg[1] = version; - msg[2] = head[0]; - msg[3] = head[1]; + msg[1] = Version; + msg[2] = Head[0]; + msg[3] = Head[1]; msg[4] = command; if (data != null) { @@ -69,55 +70,40 @@ public class AlarmEncode msg[i + 5] = data[i]; } } - byte[] subMsg = null; - if (data == null) - { - subMsg = new byte[4]; - } - else - { - subMsg = new byte[4 + data.Length]; - } + byte[] subMsg = data != null ? new byte[data.Length + 4] : new byte[4]; for (int i = 0; i < subMsg.Length; i++) { subMsg[i] = msg[i + 1]; } byte[] crc = CRC16(subMsg); - msg[msg.Length - 3] = crc[1]; - msg[msg.Length - 2] = crc[0]; - msg[msg.Length - 1] = end; + msg[^3] = crc[1]; + msg[^2] = crc[0]; + msg[^1] = End; return msg; } - private static bool checkMessage(byte[] msg) - { - if (msg == null) return false; - if (msg[0] > msg.Length) return false; - return true; - } - - private static byte[] getContent(byte[] msg, int len) - { - byte[] bytes = new byte[len]; - for (int i = 0; i < len; i++) - { - bytes[i] = msg[i + 1]; - } - return bytes; - } - - private static byte[] getMessage(byte msgLen, byte[] msg) + public static byte[] CRC16(byte[] data) { - byte[] out_msg = new byte[msg.Length + 1]; - out_msg[0] = msgLen; - for (int i = 0; i < msg.Length; i++) + int len = data.Length; + if (len > 0) { - out_msg[i + 1] = msg[i]; + ushort crc = 0xFFFF; + for (int i = 0; i < len; i++) + { + crc = (ushort)(crc ^ (data[i])); + for (int j = 0; j < 8; j++) + { + crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1); + } + } + byte hi = (byte)((crc & 0xFF00) >> 8); //高位置 + byte lo = (byte)(crc & 0x00FF); //低位置 + return new byte[] { hi, lo }; } - return out_msg; + return new byte[] { 0, 0 }; } - private static byte[] btea_encrypt(byte[] bytes) + private static byte[] BteaEncrypt(byte[] bytes) { byte[] output = new byte[bytes.Length]; for (int i = 0; i < bytes.Length; i++) @@ -128,7 +114,7 @@ public class AlarmEncode return output; } - private static byte[] btea_decrpyt(byte[] bytes) + private static byte[] BteaDecrpyt(byte[] bytes) { byte[] output = new byte[bytes.Length]; for (int i = 0; i < bytes.Length; i++) @@ -138,4 +124,133 @@ public class AlarmEncode } return output; } +} + +public enum DeviceCmd : byte +{ + /// + /// 心跳 + /// + HeartBeatCmd = 0x01, + + /// + /// 报警 + /// + AlarmCmd = 0x02, + + /// + /// 所有防区状态 + /// + AllSectorStateCmd = 0x03, + + /// + /// 实时防区状态 + /// + RtSectorStateCmd = 0x04, + + /// + /// 最大防区号 + /// + MaxSectorTotalCmd = 0x05, + + /// + /// 报警主机设置参数返回服务器 + /// + BackSettingsCmd = 0x08, + + /// + /// 布防指令 + /// + DefenceCmd = 0x80, + + /// + /// 校对时间指令 + /// + CheckTimeCmd = 0x8D, + + /// + /// 正确应答指令 + /// + OkCmd = 0x8F, + + /// + /// 主机重启指令 + /// + RebootCmd = 0xA0, +} + +public enum DeviceSectorType : byte +{ + /// + /// 防区未使用 + /// + NotUsed = 0x00, + + /// + /// 防区撤防 + /// + Withdraw = 0x01, + + /// + /// 防区布防 + /// + Deploy = 0x02, + + /// + /// 防区旁路 + /// + Byway = 0x03, + + /// + /// 防区报警 + /// + Alarm = 0x04, + + /// + /// 无线防区欠压 + /// + Undervoltage = 0x05, + + /// + /// 防区掉线(与主线总线脱离) + /// + OffBus = 0x06, + + /// + /// 未准备就绪 + /// + Unprepared = 0x07, +} + +public enum DeviceDefenceState : byte +{ + /// + /// 撤防状态 + /// + Withdraw = 0x00, + + /// + /// 外出布防(普通布防最常用) + /// + GoOut = 0x01, + + /// + /// 即时布防(所有防区没有延时) + /// + Immediately = 0x02, + + /// + /// 在家布防(留守布防有些防区可能是在旁路状态) + /// + Home = 0x04, + + /// + /// 即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时) + /// + HomeImmediately = 0x08, + + /// + /// 部分防区布防部分防区撤防 + /// + Part = 0x09 } \ No newline at end of file diff --git a/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs b/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs index e5454f2..0d4de82 100644 --- a/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs +++ b/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Collections.Concurrent; +using System.Net; using System.Timers; using Timer = System.Timers.Timer; @@ -8,608 +9,280 @@ public class UdpManager { #region Fields - private Udp myUdp = null; - private int udp_ReceivePort { get; set; } = -1; - private int keep_alive { get; set; } = -1; - private Timer PtzCheckTimer = new(); - private List deviceList { get; set; } = new(); + private UdpServer Server { get; set; } - #endregion Fields + private UdpManagerConfig Config { get; set; } - public UdpManager() - { - PtzCheckTimer.Interval = 1000; - PtzCheckTimer.Elapsed += PTZCheckTimer_Elapsed; - } + private Timer PtzCheckTimer { get; } = new(); - //计时判断设备是否在线,若超过规定时间没有新消息发来,则设备离线 - private void PTZCheckTimer_Elapsed(object sender, ElapsedEventArgs e) - { - foreach (UdpAlarmHostDevice p1 in deviceList) - { - if (p1.keep_live >= 0) - { - p1.keep_live--; - } - if (p1.keep_live < 0) - { - p1.deviceOnlineState = 0; - if (OnUdpAlarmDeviceState != null) - { - OnUdpAlarmDeviceState(p1.deviceID, "设备离线"); - } - } - } - } + private ConcurrentDictionary DeviceDict { get; } = new(); - public List getDeviceAll() - { - return deviceList; - } + #region Event - public UdpAlarmHostDevice getDevice(int deviceID) - { - foreach (UdpAlarmHostDevice p1 in deviceList) - { - if (p1.deviceID == deviceID) return p1; - } - return null; - } + public delegate void UDPAlarmDeviceStateEvent(int deviceId, int state); - public List getDeviceChannelAll(int deviceID) - { - foreach (UdpAlarmHostDevice p1 in deviceList) - { - if (p1.deviceID == deviceID) return p1.sectorList; - } - return null; - } + public delegate void UDPAlarmSectorStateEvent(int deviceId, int sectorId, int state); - public SectorState getDeviceChannel(int deviceID, int channel) - { - UdpAlarmHostDevice state = getDevice(deviceID); - if (state == null || state.sectorList == null) return null; - foreach (SectorState p1 in state.sectorList) - { - if (p1.Id == channel) return p1; - } - return null; - } + public delegate void UDPAlarmEvent(UdpAlarmHostMessage msg); - #region BaseMethod + public event UDPAlarmDeviceStateEvent? OnUdpAlarmDeviceState; - public bool StartServer(UdpManagerConfig config) - { - string s_IP = config.ServerIp; - int s_Port = config.ServerPort; - int d_Keep = config.DeviceHeartKeep; + public event UDPAlarmSectorStateEvent? OnUdpAlarmSectorState; - return AlarmHostLogin(s_IP, s_Port, d_Keep); - } + public event UDPAlarmEvent? OnUdpAlarm; - public bool StopServer() + #endregion Event + + #endregion Fields + + public UdpManager() { - return AlarmHostLoginOut(); } - private bool AlarmHostLogin(string ip, int port, int keep_alive) - { - if (myUdp != null) AlarmHostLoginOut(); + #region Server - this.udp_ReceivePort = port; - this.keep_alive = keep_alive; + public void Start(UdpManagerConfig config) + { + if (IsRunning()) return; try { - //启动UDP协议 - myUdp = new Udp(udp_ReceivePort); - myUdp.DatagramReceived += myUDPReceive; + Server = new(config.ServerPort); + Server.DatagramReceived += Server_DatagramReceived; + Server.Start(); } - catch (Exception ex) + catch (Exception) { - myUdp = null; - return false; + return; } - if (keep_alive > 0) - { - PtzCheckTimer.Enabled = true; - } - return true; + PtzCheckTimer.Interval = 1000;//1s + PtzCheckTimer.Elapsed += PTZCheckTimer_Elapsed; + PtzCheckTimer.Enabled = true; + + Config = config; } - private bool AlarmHostLoginOut() + public void Stop() { - PtzCheckTimer.Enabled = false; - if (myUdp != null) + if (!IsRunning()) return; + try { - myUdp.DatagramReceived -= myUDPReceive; - myUdp.Stop(); - myUdp = null; + Server.Stop(); + } + finally + { + Server.DatagramReceived -= Server_DatagramReceived; + Server = null; + DeviceDict.Clear(); + PtzCheckTimer.Stop(); + PtzCheckTimer.Elapsed -= PTZCheckTimer_Elapsed; } - return true; } - #endregion BaseMethod - - public delegate void UDPAlarmDeviceStateEvent(int deviceId, string state); - - public event UDPAlarmDeviceStateEvent OnUdpAlarmDeviceState; - - public delegate void UDPAlarmSectionStateEvent(int deviceId, int channel, string state); - - public event UDPAlarmSectionStateEvent OnUdpAlarmSectionState; - - public delegate void UDPAlarmEvent(UdpAlarmHostMessage msg); + public bool IsRunning() + { + return Server != null && Server.IsRunning(); + } - public event UDPAlarmEvent OnUdpAlarmEvent; + #endregion Server - public delegate void UDPAlarmCancelEvent(int deviceId, int channel); + #region Events - public event UDPAlarmCancelEvent OnUdpAlarmCancel; + /// + /// 计时判断设备是否在线,若超过规定时间没有新消息发来,则设备离线 + /// + /// + /// + private void PTZCheckTimer_Elapsed(object? sender, ElapsedEventArgs e) + { + foreach (var item in DeviceDict.Values) + { + if (item.KeepLive >= 0) + { + item.KeepLive--; + } + else + { + item.OnlineState = 0; + OnUdpAlarmDeviceState?.Invoke(item.DeviceId, 0); + } + } + } - private void myUDPReceive(IPEndPoint ipep, byte[] str) + private void Server_DatagramReceived(object? sender, UdpDatagramReceivedEventArgs e) { + IPEndPoint ipep = e.Ipep; //解码 - byte[] msg = AlarmEncode.decodeMessage(str); - string ip = ipep.Address.ToString(); - Console.WriteLine("Receive protocol:" + msg[4]); + byte[] msg = AlarmEncode.DecodeMessage(e.Datagram); + if (msg[2] != AlarmEncode.Head[0] && msg[3] != AlarmEncode.Head[1]) return; + //Console.WriteLine("Receive protocol:" + msg[4]); //解析 switch (msg[4]) { - case 0x01: //心跳数据 + case (byte)DeviceCmd.HeartBeatCmd://心跳信息 AnalysisHeartMessage(ipep, msg); break; - case 0x02://报警信息 - AnalysisAlarmMessage(ip, msg); + case (byte)DeviceCmd.AlarmCmd://报警信息 + AnalysisAlarmMessage(ipep, msg); break; - case 0x03://防区信息 + case (byte)DeviceCmd.AllSectorStateCmd://防区信息 AnalysisAllSectorMessage(ipep, msg); break; - case 0x04://张力防区信息 + case (byte)DeviceCmd.RtSectorStateCmd://张力防区信息 AnalysisSectorMessage(ipep, msg); break; - case 0x05://报警主机最大防区信息 + case (byte)DeviceCmd.MaxSectorTotalCmd://最大防区信息 AnalysisMaxSectorMessage(ipep, msg); break; - case 0x08://返回报警主机设置参数回服务器,无需解析 + case (byte)DeviceCmd.BackSettingsCmd://返回报警主机设置参数回服务器,无需解析 break; default: break; } - SendOK(ipep); + SendOk(ipep); } - private void SendOK(IPEndPoint ipep) - { - if (myUdp == null) return; - byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x06, 0x6B, 0x0D }; - bool flag = myUdp.SendMessage(ipep.Address.ToString(), ipep.Port, AlarmEncode.encodeMessage(bytes)); - //bool flag = myUdp.SendMessage(ipep, AlarmEncode.encodeMessage(bytes)); - } + #endregion Events + + #region Analysis private void AnalysisHeartMessage(IPEndPoint ipep, byte[] msg) { string ip = ipep.Address.ToString(); - int deviceID = ByteToInt(msg, 5); - UdpAlarmHostDevice device = getDevice(deviceID); - if (device == null) + int deviceId = ByteToInt(msg, 5); + if (!TryGetDevice(deviceId, out UdpAlarmHost device)) { device = new() { - deviceID = deviceID, - deviceOnlineState = 1, - keep_live = keep_alive + DeviceId = deviceId, + Ip = ip, + Port = ipep.Port, + GroupId = ByteToInt(msg, 9), + UserId = ByteToInt(msg, 13), + OnlineState = 1, + KeepLive = Config.DeviceHeartKeep }; - deviceList.Add(device); + AddDevice(deviceId, device); } - device.Ip = ip; - device.Port = ipep.Port; - device.GroupID = ByteToInt(msg, 9); - device.UserID = ByteToInt(msg, 13); - - if (device.deviceState != msg[17]) + byte defenceState = msg[17]; + if (device.DefenceState != defenceState && OnUdpAlarmDeviceState != null) { - if (OnUdpAlarmDeviceState != null) - { - switch (msg[17]) - { - case 0x00://撤防状态 - OnUdpAlarmDeviceState(device.deviceID, "撤防状态"); - break; - - case 0x01://外出布防 - OnUdpAlarmDeviceState(device.deviceID, "外出布防(普通布防最常用)"); - break; - - case 0x02://即时布防(所有防区没有延时) - OnUdpAlarmDeviceState(device.deviceID, "即时布防(所有防区没有延时)"); - break; - - case 0x04://在家布防(留守布防有些防区可能是在旁路状态) - OnUdpAlarmDeviceState(device.deviceID, "在家布防(留守布防有些防区可能是在旁路状态)"); - break; - - case 0x08://即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时) - OnUdpAlarmDeviceState(device.deviceID, "即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时)"); - break; - - case 0x09://部分防区布防部分防区撤防 - OnUdpAlarmDeviceState(device.deviceID, "部分防区布防部分防区撤防"); - break; - } - } + OnUdpAlarmDeviceState?.Invoke(device.DeviceId, defenceState); } - device.deviceState = msg[17]; - device.deviceWorkState = msg[18]; + device.DefenceState = msg[17]; + device.WorkState = msg[18]; //设备状态1 - device.cellState = getBit(msg[19], 0); - device.electricityState = getBit(msg[19], 1); - device.fuseState = getBit(msg[19], 2); - device.sectorState = getBit(msg[19], 3); - device.cellTestState = getBit(msg[19], 4); - device.deviceElectricityState = getBit(msg[19], 5); - device.soundState = getBit(msg[19], 6); - device.testState = getBit(msg[19], 7); + device.CellState = GetBit(msg[19], 0); + device.ElectricityState = GetBit(msg[19], 1); + device.FuseState = GetBit(msg[19], 2); + device.SectorState = GetBit(msg[19], 3); + device.CellTestState = GetBit(msg[19], 4); + device.DeviceElectricityState = GetBit(msg[19], 5); + device.SoundState = GetBit(msg[19], 6); + device.TestState = GetBit(msg[19], 7); //设备状态2 - device.criticalAlarmState = getBit(msg[20], 0); - device.fireAlarmState = getBit(msg[20], 1); - device.stealAlarmState = getBit(msg[20], 2); - device.deviceFireAlarmState = getBit(msg[20], 3); - device.deviceAlarmState = getBit(msg[20], 4); - device.deviceBywayState = getBit(msg[20], 5); - device.busOfflineState = getBit(msg[20], 6); - device.netOfflineState = getBit(msg[20], 7); + device.CriticalAlarmState = GetBit(msg[20], 0); + device.FireAlarmState = GetBit(msg[20], 1); + device.StealAlarmState = GetBit(msg[20], 2); + device.DeviceFireAlarmState = GetBit(msg[20], 3); + device.DeviceAlarmState = GetBit(msg[20], 4); + device.DeviceBywayState = GetBit(msg[20], 5); + device.BusOfflineState = GetBit(msg[20], 6); + device.NetOfflineState = GetBit(msg[20], 7); //设备状态3,4暂不使用 - - device.devideType = msg[23]; - device.signalIntensity = msg[24]; - device.channelNum = msg[25]; - if (device.channelNum > 0) - { - device.channelState = new List(); - device.channelAlarmState = new List(); - for (int i = 0; i < device.channelNum; i++) - { - device.channelState.Add(getBit(msg[26], i)); - device.channelAlarmState.Add(getBit(msg[27], i)); - } - } + device.DevideType = msg[23]; + device.SignalIntensity = msg[24]; + device.SectorTotal = msg[25]; //在线状态 - device.keep_live = keep_alive; - if (device.deviceOnlineState == 0) + device.KeepLive = Config.DeviceHeartKeep; + if (device.OnlineState == 0) { - if (OnUdpAlarmDeviceState != null) - { - OnUdpAlarmDeviceState(device.deviceID, "设备上线"); - } + device.OnlineState = 1; + OnUdpAlarmDeviceState?.Invoke(device.DeviceId, device.OnlineState); } - device.deviceOnlineState = 1; } - private int getBit(byte bytes, int index) + private void AnalysisAlarmMessage(IPEndPoint ipep, byte[] msg) { - switch (index) + string ip = ipep.Address.ToString(); + int deviceId = ByteToInt(msg, 5); + if (!TryGetDevice(deviceId, out _)) { - case 0: - return bytes & 0x01; - - case 1: - return (bytes & 0x02) >> 1; - - case 2: - return (bytes & 0x04) >> 2; - - case 3: - return (bytes & 0x08) >> 3; - - case 4: - return (bytes & 0x10) >> 4; - - case 5: - return (bytes & 0x20) >> 5; - - case 6: - return (bytes & 0x40) >> 6; - - case 7: - return (bytes & 0x80) >> 7; - - default: - return 0; + UdpAlarmHost device = new() + { + DeviceId = deviceId, + Ip = ip, + Port = ipep.Port, + GroupId = ByteToInt(msg, 9), + UserId = ByteToInt(msg, 13), + OnlineState = 1, + KeepLive = Config.DeviceHeartKeep + }; + AddDevice(deviceId, device); } - } - - private int ByteToInt(byte[] msg, int start) - { - byte[] bytes = new byte[] { msg[start + 3], msg[start + 2], msg[start + 1], msg[start] }; - return BitConverter.ToInt32(bytes, 0); - } - - private byte[] IntToByte(int num) - { - byte[] bytes = BitConverter.GetBytes(num); - return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }; - } - - public void TestAlarm(string devideId, string channel) - { - byte[] bytes = BitConverter.GetBytes(int.Parse(devideId)); - byte[] bytes2 = BitConverter.GetBytes(int.Parse(channel)); - byte[] msg = new byte[36]{ - 0x24,0x12,0xF0,0xFA, - 0x02,bytes[3],bytes[2],bytes[1], - bytes[0],0x00,0x00,0x00, - 0x00,bytes[3],bytes[2],bytes[1], - bytes[0],0x22,0x12,0x23, - 0x10,0x10,0x10,0x01, - 0x01,0x03,0x01,0x00, - 0x02,bytes2[0],bytes2[1],0x00, - 0x00,0x04,0x03,0x01 - }; - //byte[] encodeMsg = AlarmEncode.encodeMessage(msg); - AnalysisAlarmMessage("127.0.0.1", msg); - } - - private void AnalysisAlarmMessage(string ip, byte[] msg) - { - string CID = getCID(msg[23]) + getCID(msg[24]) + getCID(msg[25]) + getCID(msg[26]); - int deviceID = ByteToInt(msg, 5); - int channelNum = msg[29] + msg[30] * 256; - string alarmTime = "20" + getBCD(msg[17]) + "-" + getBCD(msg[18]) + "-" + getBCD(msg[19]) - + " " + getBCD(msg[20]) + ":" + getBCD(msg[21]) + ":" + getBCD(msg[22]); - + string alarmTime = $"20{GetBCD(msg[17])}-{GetBCD(msg[18])}-{GetBCD(msg[19])} " + + $"{GetBCD(msg[20])}:{GetBCD(msg[21])}:{GetBCD(msg[22])}"; + string CID = GetCID(msg[23]) + GetCID(msg[24]) + GetCID(msg[25]) + GetCID(msg[26]); + int sectorId = msg[29] + msg[30] * 256; UdpAlarmHostMessage alarm = new() { - DeviceID = deviceID, + DeviceId = deviceId, Ip = ip, - GroupID = ByteToInt(msg, 9), - UserID = ByteToInt(msg, 13), + GroupId = ByteToInt(msg, 9), + UserId = ByteToInt(msg, 13), AlarmTime = alarmTime, //CID暂定 CID = CID, LinkOut = msg[27] + msg[28] * 256, - ChannelNum = channelNum, - SubChannelNum = msg[31] + msg[32] * 256, + SectorId = sectorId, + SubSectorId = msg[31] + msg[32] * 256, ExtendArgs = msg[33].ToString("X2") + " " + msg[34].ToString("X2") + " " + msg[35].ToString("X2"), }; - - ProcessAlarm(alarm); - } - - //处理报警事件 - private void ProcessAlarm(UdpAlarmHostMessage msg) - { - OnUdpAlarmEvent(msg); - - ////报警信息放入数据库 - //JObject obj = new() - //{ - // { "alarmTime", msg.AlarmTime }, - // { "CID", msg.CID }, - - // { "deviceID", msg.DeviceID }, - // { "channelNum", msg.ChannelNum }, - // { "subChannelNum", msg.SubChannelNum }, - - // { "IP", msg.Ip }, - // { "groupID", msg.GroupID }, - // { "userID", msg.UserID }, - // { "linkOut", msg.LinkOut }, - // { "extendArgs", msg.ExtendArgs }, - - // { "alarm_level", msg.AlarmLevel }, - // { "alarm_content", msg.AlarmContent }, - // { "alarm_remarks", msg.AlarmRemarks }, - // { "alarm_type", msg.AlarmType }, - - // { "IsLinked", msg.IsLinked }, - // { "linklist", msg.Linklist } - //}; - //string error = ""; - //DBCenter.center.InsertResult("table_UDPAlarmMessage", obj, ref error); - ////打开预览窗口 - //if (msg.IsLinked) - //{ - // if (OnUdpAlarmEvent != null) - // { - // OnUdpAlarmEvent(msg); - // } - // //联动预置位 - // for (int i = 0; i < msg.Linklist.Count; i++) - // { - // if (msg.Linklist[i]["needPreset"].ToString() == "true") - // { - // //int camID = int.Parse(msg.linklist[i]["camID"].ToString()); - // //string camType = msg.linklist[i]["camType"].ToString(); - // //CamType device_type = CamType.Table; - // //if (camType == "摄像机") device_type = CamType.Camera; - // //int presetId = int.Parse(msg.linklist[i]["presetID"].ToString()); - // //RequestToService.center.NET_SDK_PTZPreset_Other(camID, device_type, (int)WMPTZPresetCommand.WMPTZPreset_GOTO, presetId, ref error); - // } - // } - //} - } - - private string getCID(byte bytes) - { - switch (bytes) - { - case 0x00: - return "0"; - - case 0x01: - return "1"; - - case 0x02: - return "2"; - - case 0x03: - return "3"; - - case 0x04: - return "4"; - - case 0x05: - return "5"; - - case 0x06: - return "6"; - - case 0x07: - return "7"; - - case 0x08: - return "8"; - - case 0x09: - return "9"; - - case 0x0A: - return "A"; - - case 0x0B: - return "B"; - - case 0x0C: - return "C"; - - case 0x0D: - return "D"; - - case 0x0E: - return "E"; - - case 0x0F: - return "F"; - - default: - return "0"; - } - } - - private string getBCD(byte bytes) - { - int num = (bytes >> 4) * 10 + (bytes & 0x0F); - return num.ToString(); - } - - private byte getBCDByte(int num) - { - if (num >= 100) num = num % 100; - int hex = num / 10; - int lex = num % 10; - return (byte)(hex * 16 + lex); - } - - private byte[] getBCDTime(DateTime time) - { - return new byte[] { getBCDByte(time.Year),getBCDByte((int)time.DayOfWeek),getBCDByte(time.Month),getBCDByte(time.Day), - - getBCDByte(time.Hour),getBCDByte(time.Minute),getBCDByte(time.Second) }; - } - - private string getBCD2(byte bytes) - { - int num1 = bytes / 16; - int num2 = bytes % 16; - return (num1 * 10 + num2).ToString(); + ReportAlarm(alarm); } private void AnalysisAllSectorMessage(IPEndPoint ipep, byte[] msg) { string ip = ipep.Address.ToString(); - int deviceID = ByteToInt(msg, 5); - UdpAlarmHostDevice device = getDevice(deviceID); - if (device == null) + int deviceId = ByteToInt(msg, 5); + if (!TryGetDevice(deviceId, out UdpAlarmHost device)) { device = new() { - deviceID = deviceID, - deviceOnlineState = 1, - keep_live = keep_alive + DeviceId = deviceId, + Ip = ip, + Port = ipep.Port, + GroupId = ByteToInt(msg, 9), + UserId = ByteToInt(msg, 13), + OnlineState = 1, + KeepLive = Config.DeviceHeartKeep }; - deviceList.Add(device); - } - device.Ip = ip; - device.Port = ipep.Port; - device.GroupID = ByteToInt(msg, 9); - device.UserID = ByteToInt(msg, 13); - - if (device.sectorList == null) - { - device.sectorList = new List(); + AddDevice(deviceId, device); } - int count = msg[19]; - for (int i = 0; i < count; i++) + device.SectorTotal = msg[17] * 256 + msg[18]; + int sectorNum = msg[19], startIndex = msg[20]; + for (int i = 0; i < sectorNum; i++) { - int index = i + msg[20];//防区序号 + int index = i + startIndex;//防区序号 int pos = 21 + i;//防区信息所在byte数组未知 - SectorState state = new SectorState(index, msg[pos]); - updateSector(state, device.sectorList, device.deviceID); - } - } - - private void updateSector(SectorState state, List list, int deviceId) - { - for (int i = 0; i < list.Count; i++) - { - if (list[i].Id == state.Id) + SectorState sector = new(index, msg[pos]); + if (device.SectorDict.ContainsKey(sector.Id)) { - //设备离线 - if (list[i].State != state.State) + if (device.SectorDict[sector.Id].State != sector.State) { - reportSectorState(deviceId, state.Id, state.State); + device.SectorDict[sector.Id] = sector; + ReportSectorState(deviceId, sector.Id, sector.State); } - list[i] = state; //防区存在,更新 - return; } - } - list.Add(state);//防区不存在,添加 - reportSectorState(deviceId, state.Id, state.State); - } - - private void reportSectorState(int deviceId, int channel, int state) - { - if (OnUdpAlarmSectionState != null) - { - switch (state) + else { - case 0: - OnUdpAlarmSectionState(deviceId, channel, "防区未使用"); - break; - - case 1://撤防 - OnUdpAlarmSectionState(deviceId, channel, "防区撤防"); - break; - - case 2://布防 - OnUdpAlarmSectionState(deviceId, channel, "防区布防"); - break; - - case 3://旁路 - OnUdpAlarmSectionState(deviceId, channel, "防区旁路"); - break; - - case 4://报警 - OnUdpAlarmSectionState(deviceId, channel, "防区报警"); - break; - - case 5://无线防区欠压 - OnUdpAlarmSectionState(deviceId, channel, "无线防区欠压"); - break; - - case 6://防区掉线 - OnUdpAlarmSectionState(deviceId, channel, "防区掉线(与主线总线脱离)"); - break; - - case 7://未准备就绪 - OnUdpAlarmSectionState(deviceId, channel, "未准备就绪"); - break; + device.SectorDict[sector.Id] = sector; + ReportSectorState(deviceId, sector.Id, sector.State); } } } @@ -617,228 +290,428 @@ public class UdpManager private void AnalysisSectorMessage(IPEndPoint ipep, byte[] msg) { //东北没有张力防区,暂不解析 + string ip = ipep.Address.ToString(); + int deviceId = ByteToInt(msg, 5); + if (!TryGetDevice(deviceId, out UdpAlarmHost device)) + { + device = new() + { + DeviceId = deviceId, + Ip = ip, + Port = ipep.Port, + GroupId = ByteToInt(msg, 9), + UserId = ByteToInt(msg, 13), + OnlineState = 1, + KeepLive = Config.DeviceHeartKeep + }; + AddDevice(deviceId, device); + } } private void AnalysisMaxSectorMessage(IPEndPoint ipep, byte[] msg) { string ip = ipep.Address.ToString(); - int deviceID = ByteToInt(msg, 5); - UdpAlarmHostDevice device = getDevice(deviceID); - if (device == null) + int deviceId = ByteToInt(msg, 5); + if (!TryGetDevice(deviceId, out UdpAlarmHost device)) { device = new() { - deviceID = deviceID, - deviceOnlineState = 1, - keep_live = keep_alive + DeviceId = deviceId, + Ip = ip, + Port = ipep.Port, + GroupId = ByteToInt(msg, 9), + UserId = ByteToInt(msg, 13), + OnlineState = 1, + KeepLive = Config.DeviceHeartKeep }; - deviceList.Add(device); + AddDevice(deviceId, device); } - device.Ip = ip; - device.Port = ipep.Port; - device.GroupID = ByteToInt(msg, 9); - device.UserID = ByteToInt(msg, 13); - device.maxSectorNum = msg[17] * 256 + msg[18]; + device.SectorTotal = msg[17] * 256 + msg[18]; } - private bool checkDevice(UdpAlarmHostDevice device, ref string error) + private void ReportAlarm(UdpAlarmHostMessage msg) { - if (device == null) - { - error = "没有此报警主机的记录"; - return false; - } - if (device.deviceOnlineState == 0) - { - error = "此报警主机离线"; - return false; - } - if (myUdp == null) - { - error = "UDP故障"; - return false; - } - return true; + OnUdpAlarm?.Invoke(msg); } - //外出布防或者布防 - public bool setDeviceDefence(int deviceID, ref string error) + private void ReportSectorState(int deviceId, int sectorId, int state) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) - { - byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x60 }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else - { - return false; - } + OnUdpAlarmSectorState?.Invoke(deviceId, sectorId, state); } - //立即布防 - public bool setDeviceDefenceImmediately(int deviceID, ref string error) + #endregion Analysis + + #region Send + + /// + /// 应答 + /// + /// + /// + private bool SendOk(IPEndPoint ipep) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) - { - byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x62 }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else - { - return false; - } + if (!IsRunning()) return false; + byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x06, 0x6B, 0x0D }; + //byte[] bytes = AlarmEncode.GetSendMessage(0x8F, Array.Empty()); + return Server.SendMessage(ipep.Address.ToString(), ipep.Port, AlarmEncode.EncodeMessage(bytes)); } - //在家布防留守布防 - public bool setDeviceDefenceHome(int deviceID, ref string error) + /// + /// 外出布防或者布防 + /// + /// + /// + public bool SetDeviceDefence(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) - { - byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x63 }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0x80, new byte[] { 0x60 }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //即时留守布防 - public bool setDeviceDefenceHomeImmediately(int deviceID, ref string error) + /// + /// 撤防 + /// + /// + /// + public bool WithdrawDeviceDefence(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) - { - byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x64 }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0x80, new byte[] { 0x61 }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //撤防 - public bool withdrawDeviceDefence(int deviceID, ref string error) + /// + /// 立即布防 + /// + /// + /// + public bool SetDeviceDefenceImmediately(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x61 }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else - { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0x80, new byte[] { 0x62 }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //清除报警记忆(复位) - public bool clearDeviceDefence(int deviceID, ref string error) + /// + /// 在家布防留守布防 + /// + /// + /// + public bool SetDeviceDefenceHome(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) - { - byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x65 }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0x80, new byte[] { 0x63 }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //校对系统时间 - public bool setDeviceTime(int deviceID, DateTime time, ref string error) + /// + /// 即时留守布防 + /// + /// + /// + public bool SetDeviceDefenceHomeImmediately(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] content = getBCDTime(time); - byte[] bytes = AlarmEncode.getSendMessage(0x8D, content); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); - } - else - { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0x80, new byte[] { 0x64 }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //设备重启 - public bool rebootDevice(int deviceID, ref string error) + /// + /// 清除报警记忆(复位) + /// + /// + /// + public bool ClearDeviceDefence(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] bytes = AlarmEncode.getSendMessage(0xA0, null); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); + byte[] bytes = AlarmEncode.GetSendMessage(0x80, new byte[] { 0x65 }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } - else + return false; + } + + /// + /// 校对系统时间 + /// + /// + /// + /// + public bool SetDeviceTime(int deviceId) + { + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] content = GetBCDTime(DateTime.Now); + byte[] bytes = AlarmEncode.GetSendMessage(0x8D, content); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //单防区布防 - public bool setDeviceChannelDefence(int deviceID, int channel, ref string error) + /// + /// 设备重启 + /// + /// + /// + public bool RebootDevice(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] bytes = AlarmEncode.getSendMessage(0xC0, new byte[] { (byte)(channel / 256), (byte)(channel % 256) }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); + byte[] bytes = AlarmEncode.GetSendMessage(0xA0, Array.Empty()); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } - else + return false; + } + + /// + /// 单防区布防 + /// + /// + /// + /// + public bool SetSectorefence(int deviceId, int sectorId) + { + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0xC0, new byte[] { (byte)(sectorId / 256), (byte)(sectorId % 256) }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //单防区撤防 - public bool withdrawDeviceChannelDefence(int deviceID, int channel, ref string error) + /// + /// 单防区撤防 + /// + /// + /// + /// + public bool WithdrawSectorDefence(int deviceId, int sectorId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] bytes = AlarmEncode.getSendMessage(0xC1, new byte[] { (byte)(channel / 256), (byte)(channel % 256) }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); + byte[] bytes = AlarmEncode.GetSendMessage(0xC1, new byte[] { (byte)(sectorId / 256), (byte)(sectorId % 256) }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } - else + return false; + } + + /// + /// 单防区旁路 + /// + /// + /// + /// + public bool SetSectorByway(int deviceId, int sectorId) + { + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0xC2, new byte[] { (byte)(sectorId / 256), (byte)(sectorId % 256) }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //单防区旁路 - public bool setDeviceChannelByway(int deviceID, int channel, ref string error) + /// + /// 单防区旁路恢复 + /// + /// + /// + /// + public bool WithdrawSectorByway(int deviceId, int sectorId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] bytes = AlarmEncode.getSendMessage(0xC2, new byte[] { (byte)(channel / 256), (byte)(channel % 256) }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); + byte[] bytes = AlarmEncode.GetSendMessage(0xC3, new byte[] { (byte)(sectorId / 256), (byte)(sectorId % 256) }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } - else + return false; + } + + /// + /// 查询防区状态 + /// + /// + /// + /// + public bool SearchSectorState(int deviceId, int sectorId) + { + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - return false; + byte[] bytes = AlarmEncode.GetSendMessage(0x85, new byte[] { (byte)(sectorId / 256), (byte)(sectorId % 256) }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } + return false; } - //单防区旁路恢复 - public bool withdrawDeviceChannelByway(int deviceID, int channel, ref string error) + /// + /// 查询所有防区状态 + /// + /// + /// + public bool SearchAllSectorState(int deviceId) { - UdpAlarmHostDevice device = getDevice(deviceID); - if (checkDevice(device, ref error)) + UdpAlarmHost device = GetDevice(deviceId); + if (CheckDevice(device)) { - byte[] bytes = AlarmEncode.getSendMessage(0xC3, new byte[] { (byte)(channel / 256), (byte)(channel % 256) }); - return myUdp.SendMessage(device.Ip, device.Port, AlarmEncode.encodeMessage(bytes)); + int sectorId = 0x00; + byte[] bytes = AlarmEncode.GetSendMessage(0x85, new byte[] { (byte)(sectorId / 256), (byte)(sectorId % 256) }); + return Server.SendMessage(device.Ip, device.Port, AlarmEncode.EncodeMessage(bytes)); } - else + return false; + } + + #endregion Send + + #region DeviceDict + + private bool ContainsDevice(int deviceId) + { + return DeviceDict.ContainsKey(deviceId); + } + + private UdpAlarmHost GetDevice(int deviceId) + { + return DeviceDict[deviceId]; + } + + private bool TryGetDevice(int deviceId, out UdpAlarmHost device) + { + return DeviceDict.TryGetValue(deviceId, out device); + } + + private bool AddDevice(int deviceId, UdpAlarmHost device) + { + if (ContainsDevice(deviceId)) return false; + DeviceDict[deviceId] = device; + return true; + } + + private void SetDevice(int deviceId, UdpAlarmHost device) + { + DeviceDict[deviceId] = device; + } + + private bool RemoveDevice(int deviceId) + { + return DeviceDict.Remove(deviceId, out _); + } + + private List GetDeviceList() + { + return DeviceDict.Values.ToList(); + } + + private bool CheckDevice(UdpAlarmHost device) + { + if (!IsRunning()) return false; + if (device == null) return false; + if (device.OnlineState == 0) return false; + return true; + } + + #endregion DeviceDict + + #region Util + + private int GetBit(byte bytes, int index) + { + return index switch { - return false; - } + 0 => bytes & 0x01, + 1 => (bytes & 0x02) >> 1, + 2 => (bytes & 0x04) >> 2, + 3 => (bytes & 0x08) >> 3, + 4 => (bytes & 0x10) >> 4, + 5 => (bytes & 0x20) >> 5, + 6 => (bytes & 0x40) >> 6, + 7 => (bytes & 0x80) >> 7, + _ => 0, + }; + } + + private int ByteToInt(byte[] msg, int start) + { + byte[] bytes = new byte[] { msg[start + 3], msg[start + 2], msg[start + 1], msg[start] }; + return BitConverter.ToInt32(bytes, 0); } + + private byte[] IntToByte(int num) + { + byte[] bytes = BitConverter.GetBytes(num); + return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }; + } + + private string GetCID(byte bytes) + { + return bytes switch + { + 0x00 => "0", + 0x01 => "1", + 0x02 => "2", + 0x03 => "3", + 0x04 => "4", + 0x05 => "5", + 0x06 => "6", + 0x07 => "7", + 0x08 => "8", + 0x09 => "9", + 0x0A => "A", + 0x0B => "B", + 0x0C => "C", + 0x0D => "D", + 0x0E => "E", + 0x0F => "F", + _ => "0", + }; + } + + private string GetBCD(byte bytes) + { + int num = (bytes >> 4) * 10 + (bytes & 0x0F); + return num.ToString(); + } + + private byte GetBCDByte(int num) + { + if (num >= 100) num %= 100; + int hex = num / 10; + int lex = num % 10; + return (byte)(hex * 16 + lex); + } + + private byte[] GetBCDTime(DateTime time) + { + return new byte[] { GetBCDByte(time.Year),GetBCDByte((int)time.DayOfWeek),GetBCDByte(time.Month),GetBCDByte(time.Day), + GetBCDByte(time.Hour),GetBCDByte(time.Minute),GetBCDByte(time.Second) }; + } + + #endregion Util } \ No newline at end of file diff --git a/JiLinApp.Docking/FenceAlarm/Service/Udp.cs b/JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs similarity index 57% rename from JiLinApp.Docking/FenceAlarm/Service/Udp.cs rename to JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs index 9916825..5f64209 100644 --- a/JiLinApp.Docking/FenceAlarm/Service/Udp.cs +++ b/JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs @@ -4,12 +4,10 @@ using System.Net.Sockets; namespace JiLinApp.Docking.FenceAlarm; -public class Udp +public class UdpServer { #region Fields - private BackgroundWorker BackWorker { get; } - /// /// 用于UDP接收的网络服务类 /// @@ -20,27 +18,38 @@ public class Udp /// private UdpClient SendUdp { get; } + private BackgroundWorker Worker { get; } + + #region Properties + + public string RecvIp { get; private set; } + + public int RecvPort { get; private set; } + + #endregion Properties + #endregion Fields #region Ctors - public Udp(int port) : this("0.0.0.0", port) + public UdpServer(int port) : this("0.0.0.0", port) { } - public Udp(string ip, int port) + public UdpServer(string ip, int port) { + RecvIp = ip; + RecvPort = port; RecvUdp = new(new IPEndPoint(IPAddress.Parse(ip), port)); SendUdp = new(new IPEndPoint(IPAddress.Any, 0)); - BackWorker = new BackgroundWorker + Worker = new() { WorkerSupportsCancellation = true }; - BackWorker.DoWork += Back_DoWork; - BackWorker.RunWorkerAsync(); + Worker.DoWork += Back_DoWork; } - ~Udp() + ~UdpServer() { Stop(); } @@ -49,24 +58,55 @@ public class Udp #region Server + public void Start() + { + if (IsRunning()) return; + Worker.RunWorkerAsync(); + } + public void Stop() { - BackWorker?.CancelAsync(); - RecvUdp?.Close(); - SendUdp?.Close(); + if (!IsRunning()) return; + Worker.CancelAsync(); + RecvUdp.Close(); + SendUdp.Close(); } - #endregion Server + public bool IsRunning() + { + return Worker != null && Worker.IsBusy; + } - #region Receive + #endregion Server - public delegate void UDPReceive(IPEndPoint ipep, byte[] str); + #region Events - public event UDPReceive DatagramReceived; + public event EventHandler>? DatagramReceived; private void RaiseDatagramReceived(IPEndPoint ipep, byte[] datagram) { - DatagramReceived?.Invoke(ipep, datagram); + DatagramReceived?.Invoke(this, new UdpDatagramReceivedEventArgs(ipep, datagram)); + //DatagramReceived?.Invoke(ipep, datagram); + } + + #endregion Events + + #region Receive + + private void Back_DoWork(object? sender, DoWorkEventArgs e) + { + IPEndPoint remoteIpep = new(IPAddress.Any, 0); + while (Worker != null && !Worker.CancellationPending) + { + try + { + byte[] bytRecv = RecvUdp.Receive(ref remoteIpep); + RaiseDatagramReceived(remoteIpep, bytRecv); + } + catch + { + } + } } #endregion Receive @@ -75,10 +115,9 @@ public class Udp public bool SendMessage(string ip, int port, byte[] byteMsg) { - IPEndPoint ipep = new(IPAddress.Parse(ip), port); // 发送到的IP地址和端口号 + IPEndPoint ipep = new(IPAddress.Parse(ip), port); int result = SendUdp.Send(byteMsg, byteMsg.Length, ipep); bool flag = result >= byteMsg.Length; - Console.WriteLine("Send ok: {0}", flag); return flag; } @@ -89,21 +128,4 @@ public class Udp } #endregion Send - - private void Back_DoWork(object? sender, DoWorkEventArgs e) - { - IPEndPoint remoteIpep = new(IPAddress.Any, 0); - while (BackWorker != null && !BackWorker.CancellationPending) - { - try - { - byte[] bytRecv = RecvUdp.Receive(ref remoteIpep); - DatagramReceived(remoteIpep, bytRecv); - } - catch - { - throw; - } - } - } } \ No newline at end of file diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs index ea9ba40..152c1c1 100644 --- a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs +++ b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs @@ -9,7 +9,7 @@ public class ClientMessage public TcpClient Client { get; set; } - public TcpAlarmHostTable Host { get; set; } + public TcpAlarmHost Host { get; set; } public List DataList { get; } = new(); diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHost.cs similarity index 89% rename from JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs rename to JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHost.cs index 6e5ba70..a948ee0 100644 --- a/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs +++ b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHost.cs @@ -1,6 +1,6 @@ namespace JiLinApp.Docking.VibrateAlarm; -public class TcpAlarmHostTable +public class TcpAlarmHost { public int Id { get; set; } diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs index aa180c3..f704ddc 100644 --- a/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs +++ b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs @@ -10,7 +10,7 @@ public class TcpAlarmHostMessage /*设备信息*/ public int DeviceID { get; set; }//设备唯一ID - public string ChannelNum { get; set; }//防区号 + public string SensorAddr { get; set; }//防区号 public string Mode { get; set; } public string Sensitivity { get; set; } diff --git a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs index e12d00a..4c19364 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs @@ -103,15 +103,8 @@ public class AsyncTcpServer : IDisposable public void Start(int backlog) { if (IsRunning()) return; - try - { - Listener.Start(backlog); - AcceptTcpClient(Listener); - } - catch (Exception) - { - throw; - } + Listener.Start(backlog); + AcceptTcpClient(Listener); } /// @@ -125,10 +118,6 @@ public class AsyncTcpServer : IDisposable { Listener.Stop(); } - catch (Exception) - { - throw; - } finally { foreach (var client in Clients.Values) @@ -151,6 +140,40 @@ public class AsyncTcpServer : IDisposable #endregion Server + #region Events + + /// + /// 与客户端的连接已建立事件 + /// + public event EventHandler? ClientConnected; + + /// + /// 与客户端的连接已断开事件 + /// + public event EventHandler? ClientDisconnected; + + /// + /// 接收到数据报文事件 + /// + public event EventHandler>? DatagramReceived; + + private void RaiseClientConnected(TcpClient client) + { + ClientConnected?.Invoke(this, new TcpClientConnectedEventArgs(client)); + } + + private void RaiseClientDisconnected(TcpClient client) + { + ClientDisconnected?.Invoke(this, new TcpClientDisconnectedEventArgs(client)); + } + + private void RaiseDatagramReceived(TcpClientState sender, byte[] datagram) + { + DatagramReceived?.Invoke(this, new TcpDatagramReceivedEventArgs(sender, datagram)); + } + + #endregion Events + #region Receive private void AcceptTcpClient(TcpListener listener) @@ -252,40 +275,6 @@ public class AsyncTcpServer : IDisposable #endregion Receive - #region Register Events - - /// - /// 与客户端的连接已建立事件 - /// - public event EventHandler? ClientConnected; - - /// - /// 与客户端的连接已断开事件 - /// - public event EventHandler? ClientDisconnected; - - /// - /// 接收到数据报文事件 - /// - public event EventHandler>? DatagramReceived; - - private void RaiseClientConnected(TcpClient client) - { - ClientConnected?.Invoke(this, new TcpClientConnectedEventArgs(client)); - } - - private void RaiseClientDisconnected(TcpClient client) - { - ClientDisconnected?.Invoke(this, new TcpClientDisconnectedEventArgs(client)); - } - - private void RaiseDatagramReceived(TcpClientState sender, byte[] datagram) - { - DatagramReceived?.Invoke(this, new TcpDatagramReceivedEventArgs(sender, datagram)); - } - - #endregion Register Events - #region Send /// diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs index 0fa1eeb..5ae332e 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs @@ -12,27 +12,33 @@ public class TcpManager private AsyncTcpServer Server { get; set; } + private TcpManagerConfig Config { get; set; } + private ConcurrentDictionary ClientMessageDict { get; } = new(); private Timer HeartTimer { get; } = new(); private Timer StateSpanTimer { get; } = new(); - public delegate void TcpDeviceMessageEvent(TcpAlarmHostTable host, string msg); + #region Event + + public delegate void TcpDeviceMessageEvent(TcpAlarmHost host, string msg); - public delegate void TcpSensorMessageEvent(TcpAlarmHostTable host, TcpSensorTable section, string msg); + public delegate void TcpSensorMessageEvent(TcpAlarmHost host, TcpSensorTable section, string msg); public delegate void TcpSensorStateChangeEvent(SensorState state); public delegate void TcpSensorAlarmEvent(TcpAlarmHostMessage msg); - public event TcpDeviceMessageEvent OnTcpDeviceMessage; + public event TcpDeviceMessageEvent? OnTcpDeviceMessage; - public event TcpSensorMessageEvent OnTcpSensorMessage; + public event TcpSensorMessageEvent? OnTcpSensorMessage; - public event TcpSensorStateChangeEvent OnTcpSensorStateChange; + public event TcpSensorStateChangeEvent? OnTcpSensorStateChange; - public event TcpSensorAlarmEvent OnTcpSensorAlarm; + public event TcpSensorAlarmEvent? OnTcpSensorAlarm; + + #endregion Event #endregion Fields @@ -45,23 +51,43 @@ public class TcpManager public void Start(TcpManagerConfig config) { if (IsRunning()) return; - Server = new AsyncTcpServer(IPAddress.Any, config.ServerPort); - Server.ClientConnected += Server_ClientConnected; - Server.ClientDisconnected += Server_ClientDisconnected; - Server.DatagramReceived += Server_DatagramReceived; - Server.Start(); - + try + { + Server = new(IPAddress.Any, config.ServerPort); + Server.ClientConnected += Server_ClientConnected; + Server.ClientDisconnected += Server_ClientDisconnected; + Server.DatagramReceived += Server_DatagramReceived; + Server.Start(); + } + catch (Exception) + { + return; + } HeartTimer.Close(); HeartTimer.Interval = 1000 * config.DeviceHeartKeep; HeartTimer.Elapsed += HeartTimer_Elapsed; - HeartTimer.Enabled = true; HeartTimer.Start(); + + Config = config; } public void Stop() { - HeartTimer.Enabled = false; - if (IsRunning()) Server.Stop(); + if (!IsRunning()) return; + try + { + Server.Stop(); + } + finally + { + Server.ClientConnected -= Server_ClientConnected; + Server.ClientDisconnected -= Server_ClientDisconnected; + Server.DatagramReceived -= Server_DatagramReceived; + Server = null; + ClientMessageDict.Clear(); + HeartTimer.Stop(); + HeartTimer.Elapsed -= HeartTimer_Elapsed; + } } public bool IsRunning() @@ -71,7 +97,7 @@ public class TcpManager #endregion Server - #region Register Event + #region Events private void HeartTimer_Elapsed(object? sender, ElapsedEventArgs e) { @@ -107,7 +133,7 @@ public class TcpManager } if (OnTcpDeviceMessage != null) { - TcpAlarmHostTable host = clientMsg.Host ?? new() { Id = -1, Ip = clientIp, Port = clientPort, Name = "未知设备" }; + TcpAlarmHost host = clientMsg.Host ?? new() { Id = -1, Ip = clientIp, Port = clientPort, Name = "未知设备" }; OnTcpDeviceMessage(host, "报警主机上线"); } } @@ -124,7 +150,7 @@ public class TcpManager RemoveClientMessage(clientIp); if (OnTcpDeviceMessage != null) { - TcpAlarmHostTable host = clientMsg.Host ?? new() { Id = -1, Ip = clientIp, Port = clientPort, Name = "未知设备" }; + TcpAlarmHost host = clientMsg.Host ?? new() { Id = -1, Ip = clientIp, Port = clientPort, Name = "未知设备" }; OnTcpDeviceMessage(host, "报警主机下线"); } } @@ -142,57 +168,7 @@ public class TcpManager } } - #endregion Register Event - - #region ClientMessage - - private bool ContainsClientMessage(string clientIp) - { - return ClientMessageDict.ContainsKey(clientIp); - } - - private ClientMessage GetClientMessage(string clientIp) - { - return ClientMessageDict[clientIp]; - } - - private bool TryGetClientMessage(string clientIp, out ClientMessage clientMsg) - { - return ClientMessageDict.TryGetValue(clientIp, out clientMsg); - } - - private bool AddClientMessage(string clientIp, ClientMessage clientMsg) - { - if (ContainsClientMessage(clientIp)) return false; - ClientMessageDict[clientIp] = clientMsg; - return true; - } - - private void SetClientMessage(string clientIp, ClientMessage clientMsg) - { - ClientMessageDict[clientIp] = clientMsg; - } - - private bool RemoveClientMessage(string clientIp) - { - return ClientMessageDict.Remove(clientIp, out _); - } - - private bool UpdateClientMessage(string clientIp, TcpAlarmHostTable host) - { - if (!ClientMessageDict.ContainsKey(clientIp)) return false; - ClientMessageDict[clientIp].Host = host; - return true; - } - - private bool UpdateClientMessage(string clientIp, List sensorList) - { - if (!ClientMessageDict.ContainsKey(clientIp)) return false; - ClientMessageDict[clientIp].SensorList = sensorList; - return true; - } - - #endregion ClientMessage + #endregion Events #region Analysis @@ -208,7 +184,7 @@ public class TcpManager DataMessage mm = new(); mm.Decode(msglist[i]); Console.WriteLine("Receive from {0}:{1} => {2}, {3}", clientMsg.Ip, clientMsg.Port, DataMessage.ToHexString(msglist[i]), JsonUtil.ToJson(mm)); - TcpAlarmHostTable host; + TcpAlarmHost host; switch (mm.FunctionNum) { case 0x00: @@ -254,7 +230,7 @@ public class TcpManager case 0x14: Console.WriteLine("传感器状态响应:{0}", clientMsg.Ip); - int channel = mm.Data[0] + mm.Data[1] * 256; + int sensorAddr = mm.Data[0] + mm.Data[1] * 256; int state = mm.Data[2] + mm.Data[3] * 256; int online = state % 2; int alarm = state / 2 % 2; @@ -263,9 +239,9 @@ public class TcpManager clientMsg.Host = new() { Id = mm.DeviceId, Ip = mm.SendIp, Port = mm.SendPort.ToString(), Name = "未知设备" }; UpdateClientMessage(clientMsg.Ip, clientMsg.Host); } - ProcessOnlineEvent(clientMsg, mm, channel, online); - ProcessAlarmEvent(clientMsg, mm, channel, alarm); - UpdateOnLineAlarm(clientMsg, channel, online, alarm); + ProcessOnlineEvent(clientMsg, mm, sensorAddr, online); + ProcessAlarmEvent(clientMsg, mm, sensorAddr, alarm); + UpdateOnLineAlarm(clientMsg, sensorAddr, online, alarm); SetDataRequest(mm, 0x04); if (alarm == 1) { @@ -309,7 +285,7 @@ public class TcpManager SensorState oldState = client.SectionTable[channel] as SensorState; if (oldState.online == online) return; } - TcpAlarmHostTable host = client.Host; + TcpAlarmHost host = client.Host; TcpSensorTable section = new() { DeviceId = host.Id, Name = "未知传感器", Channel = channel.ToString() }; OnTcpSensorMessage?.Invoke(host, section, online == 0 ? "传感器上线" : "传感器离线"); } @@ -321,7 +297,7 @@ public class TcpManager SensorState oldState = client.SectionTable[channel] as SensorState; if (oldState.alarm == alarm) return; } - TcpAlarmHostTable host = client.Host; + TcpAlarmHost host = client.Host; if (alarm == 1) { ProcessAlarm(host.Id, channel); @@ -339,7 +315,7 @@ public class TcpManager } else { - TcpAlarmHostTable host = client.Host; + TcpAlarmHost host = client.Host; SensorState state = new(host.Id, channel, online, alarm); client.SectionTable[channel] = state; OnTcpSensorStateChange?.Invoke(state); @@ -353,7 +329,7 @@ public class TcpManager AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), CID = "1151", DeviceID = deviceId, - ChannelNum = channel.ToString() + SensorAddr = channel.ToString() }; OnTcpSensorAlarm?.Invoke(alarmMsg); } @@ -476,6 +452,56 @@ public class TcpManager #endregion Send + #region ClientMessage + + private bool ContainsClientMessage(string clientIp) + { + return ClientMessageDict.ContainsKey(clientIp); + } + + private ClientMessage GetClientMessage(string clientIp) + { + return ClientMessageDict[clientIp]; + } + + private bool TryGetClientMessage(string clientIp, out ClientMessage clientMsg) + { + return ClientMessageDict.TryGetValue(clientIp, out clientMsg); + } + + private bool AddClientMessage(string clientIp, ClientMessage clientMsg) + { + if (ContainsClientMessage(clientIp)) return false; + ClientMessageDict[clientIp] = clientMsg; + return true; + } + + private void SetClientMessage(string clientIp, ClientMessage clientMsg) + { + ClientMessageDict[clientIp] = clientMsg; + } + + private bool RemoveClientMessage(string clientIp) + { + return ClientMessageDict.Remove(clientIp, out _); + } + + private bool UpdateClientMessage(string clientIp, TcpAlarmHost host) + { + if (!ClientMessageDict.ContainsKey(clientIp)) return false; + ClientMessageDict[clientIp].Host = host; + return true; + } + + private bool UpdateClientMessage(string clientIp, List sensorList) + { + if (!ClientMessageDict.ContainsKey(clientIp)) return false; + ClientMessageDict[clientIp].SensorList = sensorList; + return true; + } + + #endregion ClientMessage + #region Set private List Reqlist { get; } = new(); diff --git a/JiLinApp/Core/Config.cs b/JiLinApp/Core/Config.cs index 9961713..5ae77f3 100644 --- a/JiLinApp/Core/Config.cs +++ b/JiLinApp/Core/Config.cs @@ -9,11 +9,11 @@ public class AppConfig { public BaseConfig Base { get; set; } - public List ptzCtrlTypes { get; set; } + public List PtzCtrlTypes { get; set; } public List CameraList { get; set; } - public TransmitAlarmConfig TransmitAlarm { get; set; } + public AlarmPlatformConfig AlarmPlatform { get; set; } } public class BaseConfig diff --git a/JiLinApp/Core/Global.cs b/JiLinApp/Core/Global.cs index 14b5d91..58e4a48 100644 --- a/JiLinApp/Core/Global.cs +++ b/JiLinApp/Core/Global.cs @@ -32,9 +32,9 @@ public static class Global // 控制台 if (AppConfig.Base.Console) SystemUtil.AllocConsole(); // ptzCtrlTypes - PtzControlTypeConfigHelper.Init(AppConfig.ptzCtrlTypes); + PtzControlTypeConfigHelper.Init(AppConfig.PtzCtrlTypes); - AlarmService = AlarmServiceFactory.CreateService(AppConfig.TransmitAlarm); + AlarmService = AlarmServiceFactory.CreateService(AppConfig.AlarmPlatform); AlarmService?.Start(); } catch (Exception) diff --git a/JiLinApp/Pages/FenceServerManage/Main.xaml.cs b/JiLinApp/Pages/FenceServerManage/Main.xaml.cs index dd7531a..52cfbc9 100644 --- a/JiLinApp/Pages/FenceServerManage/Main.xaml.cs +++ b/JiLinApp/Pages/FenceServerManage/Main.xaml.cs @@ -32,8 +32,8 @@ public partial class Main : UserControl vm.SetView(this); Manager.OnUdpAlarmDeviceState += vm.OnUdpAlarmDeviceState; - Manager.OnUdpAlarmSectionState += vm.OnUdpAlarmSectionState; - Manager.OnUdpAlarmEvent += vm.OnUdpAlarmEvent; + Manager.OnUdpAlarmSectorState += vm.OnUdpAlarmSectionState; + Manager.OnUdpAlarm += vm.OnUdpAlarmEvent; } } @@ -64,7 +64,7 @@ public partial class Main : UserControl ServerPort = int.Parse(ServerPort.Text), DeviceHeartKeep = int.Parse(DeviceHeartKeep.Text) }; - Manager.StartServer(config); + Manager.Start(config); } catch (Exception ex) { @@ -78,7 +78,7 @@ public partial class Main : UserControl { try { - Manager.StopServer(); + Manager.Stop(); } catch (Exception) { diff --git a/JiLinApp/Pages/FenceServerManage/MainViewModel.cs b/JiLinApp/Pages/FenceServerManage/MainViewModel.cs index 6837a79..f6c7d0d 100644 --- a/JiLinApp/Pages/FenceServerManage/MainViewModel.cs +++ b/JiLinApp/Pages/FenceServerManage/MainViewModel.cs @@ -25,11 +25,11 @@ public class MainViewModel : ViewModelBase #region ConnEvent - internal void OnUdpAlarmDeviceState(int deviceId, string state) + internal void OnUdpAlarmDeviceState(int deviceId, int state) { } - internal void OnUdpAlarmSectionState(int deviceId, int channel, string state) + internal void OnUdpAlarmSectionState(int deviceId, int sectorId, int state) { } diff --git a/JiLinApp/Pages/PtzManage/Main.xaml.cs b/JiLinApp/Pages/PtzManage/Main.xaml.cs index ecf4c72..d33568c 100644 --- a/JiLinApp/Pages/PtzManage/Main.xaml.cs +++ b/JiLinApp/Pages/PtzManage/Main.xaml.cs @@ -62,7 +62,7 @@ public partial class Main : UserControl TaskUtil.RunCatch(() => Dispatcher.Invoke(LoadCameraList)); // 初始化云台控制类型 - foreach (var cfg in Global.AppConfig.ptzCtrlTypes) + foreach (var cfg in Global.AppConfig.PtzCtrlTypes) { ControlTypeName.Items.Add(new ComboBoxItem { Content = cfg.Name }); } @@ -249,7 +249,7 @@ public partial class Main : UserControl private void TestBtn_Click(object sender, RoutedEventArgs e) { AlarmMessage alarm = new(); - alarm.ChannelNum = Convert.ToInt32(PresetId.Text); + alarm.ChannelId = Convert.ToInt32(PresetId.Text); if (PresetId.Text == "5") { PresetId.Text = "6"; @@ -323,14 +323,14 @@ public partial class Main : UserControl { Dispatcher.Invoke(() => { - if (Global.AppConfig.TransmitAlarm.RealPlay) + if (Global.AppConfig.AlarmPlatform.RealPlay) { PtzControlType ctrlType = PtzControlTypeConfigHelper.GetControlType(ControlTypeName.Text); if (ctrlType == PtzControlType.CameraSdk) ShowLiveVideo(); } if (alarm != null) { - if (alarm.ChannelNum <= 5) + if (alarm.ChannelId <= 5) { PresetId.Text = "5"; } diff --git a/JiLinApp/Pages/VibrateServerManage/MainViewModel.cs b/JiLinApp/Pages/VibrateServerManage/MainViewModel.cs index e88a056..1674861 100644 --- a/JiLinApp/Pages/VibrateServerManage/MainViewModel.cs +++ b/JiLinApp/Pages/VibrateServerManage/MainViewModel.cs @@ -25,11 +25,11 @@ public class MainViewModel : ViewModelBase #region ConnEvent - internal void OnTcpDeviceMessage(TcpAlarmHostTable host, string msg) + internal void OnTcpDeviceMessage(TcpAlarmHost host, string msg) { } - internal void OnTcpSectionMessage(TcpAlarmHostTable host, TcpSensorTable section, string msg) + internal void OnTcpSectionMessage(TcpAlarmHost host, TcpSensorTable section, string msg) { } diff --git a/JiLinApp/config/config.json b/JiLinApp/config/config.json index 9593a11..a85b980 100644 --- a/JiLinApp/config/config.json +++ b/JiLinApp/config/config.json @@ -17,7 +17,7 @@ }, { "type": "DCamera", - "Name": "协议D" + "Name": "协议D508" } ], @@ -44,15 +44,21 @@ "password": "hk123456" } ], - "transmitAlarm": { + "alarmPlatform": { "realPlay": true, "type": "mqtt", "mqtt": { + "ip": "192.168.1.200", "port": "1883", "username": "admin", "password": "public", - "clientId": "alarmClient", - "transmitTopic": "alarm/transmit" + "clientId": "alarm-platform1", + "pubAlarmTopic": "PPS/AlarmMessage/Fence", + "subDevicesTopic": "PPS/AlarmMessage/Fence", + "subSensorsTopic": "PPS/AlarmMessage/Fence", + "subDeviceStateTopic": "PPS/AlarmMessage/Fence", + "subSensorStateTopic": "PPS/AlarmMessage/Fence", + "subCmdTopic": "" } } } \ No newline at end of file