From f7714971dd6e03720d05a256c5498969ce7abe96 Mon Sep 17 00:00:00 2001
From: fajiao <1519100073@qq.com>
Date: Fri, 7 Apr 2023 14:07:28 +0800
Subject: [PATCH] update frame
---
EC.Util/EC.Util.csproj | 1 -
EC.Util/Port/SerialPortParam.cs | 2 +-
EC.Util/Zmq/ZmqUtil.cs | 2 +-
JiLinApp.Biz/JiLinApp.Biz.csproj | 13 +
JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs | 33 +
.../Transmit/Entity/AlarmMessageHelper.cs | 40 +
.../Transmit/Service/AlarmMqttService.cs | 5 +
.../Transmit/Service/AlarmZmqService.cs | 5 +
.../Service/Interfaces/IAlarmService.cs | 5 +
JiLinApp.Docking/Alarm/AlarmCode.cs | 9 +
JiLinApp.Docking/Alarm/AlarmCodeHelper.cs | 41 +
.../FenceAlarm/Entity/DeviceStateMessage.cs | 25 +
.../FenceAlarm/Entity/SectorState.cs | 67 +
.../FenceAlarm/Entity/UdpAlarmHostDevice.cs | 170 ++
.../FenceAlarm/Entity/UdpAlarmHostMessage.cs | 30 +
.../FenceAlarm/Entity/UdpManagerConfig.cs | 12 +
.../FenceAlarm/Service/AlarmEncode.cs | 141 ++
JiLinApp.Docking/FenceAlarm/Service/Udp.cs | 85 +
.../FenceAlarm/Service/UdpManager.cs | 838 +++++++
JiLinApp.Docking/JiLinApp.Docking.csproj | 19 +
JiLinApp.Docking/Ptz/DCamera.cs | 130 +
JiLinApp.Docking/Ptz/PelcoD.cs | 242 ++
JiLinApp.Docking/Ptz/PelcoP.cs | 339 +++
JiLinApp.Docking/Ptz/PtzCmd.cs | 219 ++
.../VibrateAlarm/Entity/ClientMessage.cs | 73 +
.../VibrateAlarm/Entity/DataMessage.cs | 89 +
.../VibrateAlarm/Entity/DataRequest.cs | 14 +
.../VibrateAlarm/Entity/SectionState.cs | 57 +
.../Entity/TcpAlarmHostMessage.cs | 20 +
.../VibrateAlarm/Entity/TcpAlarmHostTable.cs | 16 +
.../VibrateAlarm/Entity/TcpManagerConfig.cs | 10 +
.../VibrateAlarm/Entity/TcpSectionTable.cs | 17 +
.../VibrateAlarm/Service/AsyncTcpServer.cs | 522 ++++
JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs | 49 +
.../Service/TcpClientConnectedEventArgs.cs | 26 +
.../Service/TcpClientDisconnectedEventArgs.cs | 26 +
.../VibrateAlarm/Service/TcpClientState.cs | 47 +
.../Service/TcpDatagramReceivedEventArgs.cs | 29 +
.../VibrateAlarm/Service/TcpManager.cs | 685 +++++
JiLinApp.Docking/config/alarmcode.json | 2198 +++++++++++++++++
JiLinApp.sln | 14 +-
41 files changed, 6361 insertions(+), 4 deletions(-)
create mode 100644 JiLinApp.Biz/JiLinApp.Biz.csproj
create mode 100644 JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs
create mode 100644 JiLinApp.Biz/Transmit/Entity/AlarmMessageHelper.cs
create mode 100644 JiLinApp.Biz/Transmit/Service/AlarmMqttService.cs
create mode 100644 JiLinApp.Biz/Transmit/Service/AlarmZmqService.cs
create mode 100644 JiLinApp.Biz/Transmit/Service/Interfaces/IAlarmService.cs
create mode 100644 JiLinApp.Docking/Alarm/AlarmCode.cs
create mode 100644 JiLinApp.Docking/Alarm/AlarmCodeHelper.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Entity/DeviceStateMessage.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Entity/UdpManagerConfig.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Service/Udp.cs
create mode 100644 JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs
create mode 100644 JiLinApp.Docking/JiLinApp.Docking.csproj
create mode 100644 JiLinApp.Docking/Ptz/DCamera.cs
create mode 100644 JiLinApp.Docking/Ptz/PelcoD.cs
create mode 100644 JiLinApp.Docking/Ptz/PelcoP.cs
create mode 100644 JiLinApp.Docking/Ptz/PtzCmd.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/DataMessage.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/DataRequest.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/SectionState.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/TcpManagerConfig.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Entity/TcpSectionTable.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/TcpClientConnectedEventArgs.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/TcpClientDisconnectedEventArgs.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs
create mode 100644 JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs
create mode 100644 JiLinApp.Docking/config/alarmcode.json
diff --git a/EC.Util/EC.Util.csproj b/EC.Util/EC.Util.csproj
index 50886e3..3ab8825 100644
--- a/EC.Util/EC.Util.csproj
+++ b/EC.Util/EC.Util.csproj
@@ -37,7 +37,6 @@
-
diff --git a/EC.Util/Port/SerialPortParam.cs b/EC.Util/Port/SerialPortParam.cs
index 8f129f9..0dd221b 100644
--- a/EC.Util/Port/SerialPortParam.cs
+++ b/EC.Util/Port/SerialPortParam.cs
@@ -5,7 +5,7 @@
///
public class SerialPortParam
{
- #region fields
+ #region Fields
///
/// 串口名称
diff --git a/EC.Util/Zmq/ZmqUtil.cs b/EC.Util/Zmq/ZmqUtil.cs
index 2335201..cbdc72a 100644
--- a/EC.Util/Zmq/ZmqUtil.cs
+++ b/EC.Util/Zmq/ZmqUtil.cs
@@ -2,7 +2,7 @@
internal class ZmqUtil
{
- //#region fields
+ //#region Fields
//private SubscriberSocket SubSocket { get; set; }
//private PublisherSocket PubSocket { get; set; }
diff --git a/JiLinApp.Biz/JiLinApp.Biz.csproj b/JiLinApp.Biz/JiLinApp.Biz.csproj
new file mode 100644
index 0000000..982d279
--- /dev/null
+++ b/JiLinApp.Biz/JiLinApp.Biz.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs b/JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs
new file mode 100644
index 0000000..86802f6
--- /dev/null
+++ b/JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs
@@ -0,0 +1,33 @@
+namespace JiLinApp.Biz.Transmit;
+
+public class AlarmMessage
+{
+ /** (必填)传感器设备编码*/
+ public string labelCode;
+ /** (必填)报警类型((1-视频报警,2-雷达报警;3-微振动警报,4-电子围网警报,9-其他报警))*/
+ public int warnType;
+ /** (必填)报警级别(1-5)*/
+ public int warnLevel;
+ /** (必填)报警内容*/
+ public string warnContent;
+ /** 处置方式*/
+ public int dealWay;
+ /** (必填)处置状态(1-未处理,2-已处理)*/
+ public int dealStatus;
+ /** (必填)发生地点*/
+ public string cameraLoc;
+ /** (必填)发生时间*/
+ public DateTime createTime;
+ /** 负责人*/
+ public string director;
+ /** (必填)类型(1-预警,2-报警,3-故障,)*/
+ public int kind;
+ /** 现场照片*/
+ public string imgUrl;
+
+ public override string ToString()
+ {
+ return string.Format("{{ labelCode:{0}, warnType:{1}, warnLevel:{2}, warnContent:{3}, createTime:{4} }}",
+ labelCode, warnType, warnLevel, warnContent, createTime);
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Biz/Transmit/Entity/AlarmMessageHelper.cs b/JiLinApp.Biz/Transmit/Entity/AlarmMessageHelper.cs
new file mode 100644
index 0000000..c05b7b2
--- /dev/null
+++ b/JiLinApp.Biz/Transmit/Entity/AlarmMessageHelper.cs
@@ -0,0 +1,40 @@
+using JiLinApp.Docking.Alarm;
+using JiLinApp.Docking.FenceAlarm;
+using JiLinApp.Docking.VibrateAlarm;
+
+namespace JiLinApp.Biz.Transmit;
+
+public static class AlarmMessageHelper
+{
+ public static AlarmMessage ToAlarmMessage(this TcpAlarmHostMessage msg)
+ {
+ AlarmCode code = AlarmCodeHelper.Get(msg.AlarmId);
+ AlarmMessage obj = new()
+ {
+ labelCode = Convert.ToString(msg.DeviceID),
+ warnType = 3,
+ warnLevel = code.Level,
+ warnContent = code.Content,
+ dealStatus = 1,
+ createTime = Convert.ToDateTime(msg.AlarmTime),
+ kind = 2,
+ };
+ return obj;
+ }
+
+ public static AlarmMessage ToAlarmMessage(this UdpAlarmHostMessage msg)
+ {
+ AlarmCode code = AlarmCodeHelper.Get(msg.CID);
+ AlarmMessage obj = new()
+ {
+ labelCode = Convert.ToString(msg.DeviceID),
+ warnType = 4,
+ warnLevel = code.Level,
+ warnContent = code.Content,
+ dealStatus = 1,
+ createTime = Convert.ToDateTime(msg.AlarmTime),
+ kind = 2,
+ };
+ return obj;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Biz/Transmit/Service/AlarmMqttService.cs b/JiLinApp.Biz/Transmit/Service/AlarmMqttService.cs
new file mode 100644
index 0000000..4be7bc0
--- /dev/null
+++ b/JiLinApp.Biz/Transmit/Service/AlarmMqttService.cs
@@ -0,0 +1,5 @@
+using JiLinApp.Biz.Transmit;
+
+public class AlarmMqttService : IAlarmService
+{
+}
\ No newline at end of file
diff --git a/JiLinApp.Biz/Transmit/Service/AlarmZmqService.cs b/JiLinApp.Biz/Transmit/Service/AlarmZmqService.cs
new file mode 100644
index 0000000..cc04baa
--- /dev/null
+++ b/JiLinApp.Biz/Transmit/Service/AlarmZmqService.cs
@@ -0,0 +1,5 @@
+using JiLinApp.Biz.Transmit;
+
+public class AlarmZmqService : IAlarmService
+{
+}
\ No newline at end of file
diff --git a/JiLinApp.Biz/Transmit/Service/Interfaces/IAlarmService.cs b/JiLinApp.Biz/Transmit/Service/Interfaces/IAlarmService.cs
new file mode 100644
index 0000000..582e7d8
--- /dev/null
+++ b/JiLinApp.Biz/Transmit/Service/Interfaces/IAlarmService.cs
@@ -0,0 +1,5 @@
+namespace JiLinApp.Biz.Transmit;
+
+public interface IAlarmService
+{
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/Alarm/AlarmCode.cs b/JiLinApp.Docking/Alarm/AlarmCode.cs
new file mode 100644
index 0000000..5f2c4b0
--- /dev/null
+++ b/JiLinApp.Docking/Alarm/AlarmCode.cs
@@ -0,0 +1,9 @@
+namespace JiLinApp.Docking.Alarm;
+
+public class AlarmCode
+{
+ public string Id { get; set; }
+ public int Level { get; set; }
+ public string Type { get; set; }
+ public string Content { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs b/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs
new file mode 100644
index 0000000..37086db
--- /dev/null
+++ b/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs
@@ -0,0 +1,41 @@
+using Newtonsoft.Json;
+
+namespace JiLinApp.Docking.Alarm;
+
+public class AlarmCodeHelper
+{
+ #region Fields
+
+ private static readonly Dictionary AlarmCodeDict;
+ private static readonly List LevelList;
+ private static readonly List TypeList;
+
+ #endregion fields
+
+ static AlarmCodeHelper()
+ {
+ using StreamReader r = new(Path.Combine("config", "alarmcode.json"));
+ string jsonStr = r.ReadToEnd();
+ List list = JsonConvert.DeserializeObject>(jsonStr) ?? new();
+ AlarmCodeDict = list.ToDictionary(item => item.Id, item => item);
+ LevelList = list.GroupBy(item => item.Level)
+ .Select(it => it.First().Level).ToList();
+ TypeList = list.GroupBy(item => item.Type)
+ .Select(it => it.First().Type).ToList();
+ }
+
+ public static void Init()
+ { }
+
+ public static AlarmCode Get(string id)
+ {
+ return AlarmCodeDict[id];
+ }
+
+ public static bool TryGet(string id, out AlarmCode alarmCode)
+ {
+ bool flag = AlarmCodeDict.TryGetValue(id, out AlarmCode? temp);
+ alarmCode = temp ?? new();
+ return flag;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Entity/DeviceStateMessage.cs b/JiLinApp.Docking/FenceAlarm/Entity/DeviceStateMessage.cs
new file mode 100644
index 0000000..e522438
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Entity/DeviceStateMessage.cs
@@ -0,0 +1,25 @@
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class DeviceStateMessage
+{
+ public int deviceID { get; set; }//设备唯一ID
+ public string StatusTime { get; set; }//时间
+ public int channel { get; set; }//防区
+ public int StatusType { get; set; }//状态
+
+ public DeviceStateMessage(int id, DateTime time, int Channel, int statusType)
+ {
+ deviceID = id;
+ StatusTime = time.ToString("yyyy-MM-dd HH:mm:ss");
+ channel = Channel;
+ StatusType = statusType;
+ }
+
+ public DeviceStateMessage()
+ {
+ deviceID = -1;
+ StatusTime = "";
+ channel = -1;
+ StatusType = -1;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs b/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs
new file mode 100644
index 0000000..de7d8e5
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs
@@ -0,0 +1,67 @@
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class SectorState
+{
+ public int id { get; set; }//防区号
+ /*0:防区未使用
+ 1:防区撤防
+ 2:防区布防
+ 3:防区旁路
+ 4:防区报警
+ 5:无线防区欠压
+ 6:防区掉线(与主线总线脱离)
+ */
+ public int state { get; set; }//防区状态
+
+ public string stateStr
+ {
+ get
+ {
+ switch (state)
+ {
+ 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:网络或总线多子防区模块
+ */
+ public int type { get; set; }//防区类型,特殊参数需单独查询
+
+ public string typeStr
+ {
+ get
+ {
+ switch (type)
+ {
+ case 0: return "普通防区";
+ case 1: return "张力防区";
+ case 2: return "脉冲围栏";
+ case 3: return "振动光纤";
+ case 4: return "泄漏电缆";
+ case 5: return "网络或总线多子防区模块";
+ default: return "未知类型:" + type;
+ }
+ }
+ }
+
+ public SectorState(int id, byte data)
+ {
+ this.id = id;
+ state = data & 0x0F;
+ type = data >> 4;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs
new file mode 100644
index 0000000..fc2ec7f
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs
@@ -0,0 +1,170 @@
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class UdpAlarmHostDevice
+{
+ public int deviceID { get; set; }//设备唯一ID
+
+ public string IP { get; set; }//设备IP
+
+ 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
new file mode 100644
index 0000000..a987c96
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs
@@ -0,0 +1,30 @@
+using Newtonsoft.Json.Linq;
+
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class UdpAlarmHostMessage
+{
+ public int Id { get; set; }
+ public string AlarmTime { get; set; }//报警时间
+ public string CID { get; set; }//CID代码
+
+ /*设备信息*/
+ public int DeviceID { get; set; }//设备唯一ID
+ public int ChannelNum { get; set; }//防区号
+ public int SubChannelNum { get; set; }//子防区号
+ public string Ip { get; set; }//设备IP
+ public int GroupID { get; set; }//分组号,报警主机可划入不同组
+ public int UserID { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分
+ public int LinkOut { get; set; }//联动输出
+ public string ExtendArgs { get; set; }//扩展参数
+
+ /*CID信息*/
+ public string AlarmLevel { get; set; }//报警级别
+ public string AlarmContent { get; set; }//报警内容
+ public string AlarmRemarks { get; set; }//报警备注
+ public string AlarmType { get; set; }//报警类型
+
+ /*联动信息*/
+ public bool IsLinked { get; set; }//是否有联动信息
+ public JArray Linklist { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Entity/UdpManagerConfig.cs b/JiLinApp.Docking/FenceAlarm/Entity/UdpManagerConfig.cs
new file mode 100644
index 0000000..0ab414c
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Entity/UdpManagerConfig.cs
@@ -0,0 +1,12 @@
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class UdpManagerConfig
+{
+ public string ServerIp { get; set; }
+
+ public int ServerPort { get; set; }
+
+ public int DevicePort { get; set; }
+
+ public int DeviceHeartKeep { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs b/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs
new file mode 100644
index 0000000..59e9e49
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs
@@ -0,0 +1,141 @@
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class AlarmEncode
+{
+ private static 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)
+ {
+ if (!checkMessage(msg)) return null;
+ return getMessage(msg[0], btea_encrypt(getContent(msg, msg[0] - 1)));
+ }
+
+ public static byte[] decodeMessage(byte[] msg)
+ {
+ if (!checkMessage(msg)) return null;
+ return getMessage(msg[0], btea_decrpyt(getContent(msg, msg[0] - 1)));
+ }
+
+ public static byte[] CRC16(byte[] data)
+ {
+ 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 };
+ }
+
+ 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)
+ {
+ byte[] msg = null;
+ if (data == null)
+ {
+ msg = new byte[8];
+ }
+ else
+ {
+ msg = new byte[data.Length + 8];
+ }
+ msg[0] = (byte)msg.Length;
+ msg[1] = version;
+ msg[2] = head[0];
+ msg[3] = head[1];
+ msg[4] = command;
+ if (data != null)
+ {
+ for (int i = 0; i < data.Length; i++)
+ {
+ msg[i + 5] = data[i];
+ }
+ }
+ byte[] subMsg = null;
+ if (data == null)
+ {
+ subMsg = new byte[4];
+ }
+ else
+ {
+ subMsg = new byte[4 + data.Length];
+ }
+ 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;
+ 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)
+ {
+ byte[] out_msg = new byte[msg.Length + 1];
+ out_msg[0] = msgLen;
+ for (int i = 0; i < msg.Length; i++)
+ {
+ out_msg[i + 1] = msg[i];
+ }
+ return out_msg;
+ }
+
+ private static byte[] btea_encrypt(byte[] bytes)
+ {
+ byte[] output = new byte[bytes.Length];
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ byte abyte = (byte)(bytes[i] ^ TEA_key[i % 16]);
+ output[i] = (byte)(((byte)(abyte >> 3)) | ((byte)(abyte << 5)));
+ }
+ return output;
+ }
+
+ private static byte[] btea_decrpyt(byte[] bytes)
+ {
+ byte[] output = new byte[bytes.Length];
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ byte abyte = (byte)(((byte)(bytes[i] << 3)) | ((byte)(bytes[i] >> 5)));
+ output[i] = (byte)(abyte ^ TEA_key[i % 16]);
+ }
+ return output;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Service/Udp.cs b/JiLinApp.Docking/FenceAlarm/Service/Udp.cs
new file mode 100644
index 0000000..d7a5f23
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Service/Udp.cs
@@ -0,0 +1,85 @@
+using System.ComponentModel;
+using System.Net;
+using System.Net.Sockets;
+
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class Udp
+{
+ private BackgroundWorker back = null;
+
+ ///
+ /// 用于UDP发送的网络服务类
+ ///
+ private UdpClient udpcSend = null;
+
+ ///
+ /// 用于UDP接收的网络服务类
+ ///
+ private UdpClient udpcRecv;
+
+ public delegate void UDPReceive(string IP, byte[] str);//
+
+ public event UDPReceive myUDPReceive;//
+
+ public Udp(string ip, int port)
+ {
+ IPEndPoint localIpep = new IPEndPoint(
+ IPAddress.Parse(ip), port); // 本机IP和监听端口号
+
+ udpcRecv = new UdpClient(localIpep);
+ udpcSend = new UdpClient();
+ back = new BackgroundWorker();
+ back.WorkerSupportsCancellation = true;
+ back.DoWork += back_DoWork;
+ back.RunWorkerAsync();
+ }
+
+ ~Udp()
+ {
+ Stop();
+ }
+
+ public void Stop()
+ {
+ if (back != null)
+ {
+ back.CancelAsync();
+ back = null;
+ }
+ if (udpcRecv != null)
+ {
+ udpcRecv.Close();
+ udpcRecv = null;
+ }
+ if (udpcSend != null)
+ {
+ udpcSend.Close();
+ udpcSend = null;
+ }
+ }
+
+ public bool SendMessage(byte[] sendbytes, string IP, int port)
+ {
+ IPEndPoint remoteIpep = new IPEndPoint(
+ IPAddress.Parse(IP), port); // 发送到的IP地址和端口号
+ int result = udpcSend.Send(sendbytes, sendbytes.Length, remoteIpep);
+ return result >= sendbytes.Length;
+ }
+
+ private void back_DoWork(object sender, DoWorkEventArgs e)
+ {
+ IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);
+ while (!back.CancellationPending)
+ {
+ try
+ {
+ byte[] bytRecv = udpcRecv.Receive(ref remoteIpep);
+ myUDPReceive(remoteIpep.Address.ToString(), bytRecv);
+ }
+ catch
+ {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs b/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs
new file mode 100644
index 0000000..fdc1cde
--- /dev/null
+++ b/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs
@@ -0,0 +1,838 @@
+using System.Data;
+using System.Timers;
+using Timer = System.Timers.Timer;
+
+namespace JiLinApp.Docking.FenceAlarm;
+
+public class UdpManager
+{
+ #region Fields
+
+ private Udp myUdp = null;
+ private int udp_sendPort = -1;
+ private int udp_ReceivePort = -1;
+ private int keep_alive = -1;
+ private Timer PtzCheckTimer = new();
+
+ private List deviceList = new();
+
+ #endregion fields
+
+ public UdpManager()
+ {
+ PtzCheckTimer.Interval = 1000;
+ PtzCheckTimer.Elapsed += PTZCheckTimer_Elapsed;
+ }
+
+ //计时判断设备是否在线,若超过规定时间没有新消息发来,则设备离线
+ 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, "设备离线");
+ }
+ }
+ }
+ }
+
+ public List getDeviceAll()
+ {
+ return deviceList;
+ }
+
+ public UdpAlarmHostDevice getDevice(int deviceID)
+ {
+ foreach (UdpAlarmHostDevice p1 in deviceList)
+ {
+ if (p1.deviceID == deviceID) return p1;
+ }
+ return null;
+ }
+
+ public List getDeviceChannelAll(int deviceID)
+ {
+ foreach (UdpAlarmHostDevice p1 in deviceList)
+ {
+ if (p1.deviceID == deviceID) return p1.sectorList;
+ }
+ return null;
+ }
+
+ 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;
+ }
+
+ #region BaseMethod
+
+ public bool StartServer(UdpManagerConfig config)
+ {
+ string s_IP = config.ServerIp;
+ int s_Port = config.ServerPort;
+ int d_Port = config.DevicePort;
+ int d_Keep = config.DeviceHeartKeep;
+
+ return AlarmHostLogin(s_IP, s_Port, d_Port, d_Keep);
+ }
+
+ public bool StopServer()
+ {
+ return AlarmHostLoginOut();
+ }
+
+ private bool AlarmHostLogin(string IP, int Port, int device_port, int keep_alive)
+ {
+ if (myUdp != null) AlarmHostLoginOut();
+
+ this.udp_ReceivePort = Port;
+ this.udp_sendPort = device_port;
+ this.keep_alive = keep_alive;
+ try
+ {
+ //启动UDP协议
+ myUdp = new Udp(IP, udp_ReceivePort);
+ myUdp.myUDPReceive += myUDPReceive;
+ }
+ catch (Exception ex)
+ {
+ myUdp = null;
+ return false;
+ }
+ if (keep_alive > 0)
+ {
+ PtzCheckTimer.Enabled = true;
+ }
+ return true;
+ }
+
+ private bool AlarmHostLoginOut()
+ {
+ PtzCheckTimer.Enabled = false;
+ if (myUdp != null)
+ {
+ myUdp.myUDPReceive -= myUDPReceive;
+ myUdp.Stop();
+ myUdp = null;
+ }
+ 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 event UDPAlarmEvent OnUdpAlarmEvent;
+
+ public delegate void UDPAlarmCancelEvent(int deviceId, int channel);
+
+ public event UDPAlarmCancelEvent OnUdpAlarmCancel;
+
+ private void myUDPReceive(string Ip, byte[] str)
+ {
+ //解码
+ byte[] msg = AlarmEncode.decodeMessage(str);
+ //解析
+ switch (msg[4])
+ {
+ case 0x01: //心跳数据
+ analysisHeartMessage(Ip, msg);
+ break;
+
+ case 0x02://报警信息
+ AnalysisAlarmMessage(Ip, msg);
+ break;
+
+ case 0x03://防区信息
+ analysisAllSectorMessage(Ip, msg);
+ break;
+
+ case 0x04://张力防区信息
+ analysisSectorMessage(Ip, msg);
+ break;
+
+ case 0x05://报警主机最大防区信息
+ analysisMaxSectorMessage(Ip, msg);
+ break;
+
+ case 0x08://返回报警主机设置参数回服务器,无需解析
+ break;
+
+ default:
+ break;
+ }
+ Console.WriteLine("消息类型:" + msg[4]);
+ sendOK(Ip);
+ }
+
+ private void sendOK(string IP)
+ {
+ if (myUdp == null) return;
+ //byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x7F, 0x2E, 0x0D };
+ byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x06, 0x6B, 0x0D };
+ myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), IP, udp_sendPort);
+ }
+
+ private void analysisHeartMessage(string IP, byte[] msg)
+ {
+ int deviceID = ByteToInt(msg, 5);
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (device == null)
+ {
+ device = new UdpAlarmHostDevice();
+ device.deviceID = deviceID;
+ device.userID = ByteToInt(msg, 13);
+ device.IP = IP;
+ device.deviceOnlineState = 1;
+ device.keep_live = keep_alive;
+ deviceList.Add(device);
+ }
+ device.deviceID = deviceID;
+ device.IP = IP;
+ device.groupID = ByteToInt(msg, 9);
+ device.userID = ByteToInt(msg, 13);
+ if (device.deviceState != msg[17])
+ {
+ 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;
+ }
+ }
+ }
+ device.deviceState = msg[17];
+ device.deviceWorkState = 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);
+ //设备状态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);
+ //设备状态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.keep_live = keep_alive;
+ if (device.deviceOnlineState == 0)
+ {
+ if (OnUdpAlarmDeviceState != null)
+ {
+ OnUdpAlarmDeviceState(device.deviceID, "设备上线");
+ }
+ }
+ device.deviceOnlineState = 1;
+ }
+
+ private int getBit(byte bytes, int index)
+ {
+ switch (index)
+ {
+ 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;
+ }
+ }
+
+ 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
+ };
+ 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]);
+
+ UdpAlarmHostMessage alarm = new()
+ {
+ DeviceID = deviceID,
+ Ip = ip,
+ 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,
+ 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();
+ }
+
+ private void analysisAllSectorMessage(string IP, byte[] msg)
+ {
+ int deviceID = ByteToInt(msg, 5);
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (device == null)
+ {
+ device = new UdpAlarmHostDevice();
+ device.deviceID = deviceID;
+ device.IP = IP;
+ device.deviceOnlineState = 1;
+ device.keep_live = keep_alive;
+ deviceList.Add(device);
+ }
+ device.IP = IP;
+ device.groupID = ByteToInt(msg, 9);
+ device.userID = ByteToInt(msg, 13);
+
+ if (device.sectorList == null)
+ {
+ device.sectorList = new List();
+ }
+ int count = msg[19];
+ for (int i = 0; i < count; i++)
+ {
+ int index = i + msg[20];//防区序号
+ 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)
+ {
+ //设备离线
+ if (list[i].state != state.state)
+ {
+ reportSectorState(deviceId, state.id, state.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)
+ {
+ 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;
+ }
+ }
+ }
+
+ private void analysisSectorMessage(string IP, byte[] msg)
+ {
+ //东北没有张力防区,暂不解析
+ }
+
+ private void analysisMaxSectorMessage(string IP, byte[] msg)
+ {
+ int deviceID = ByteToInt(msg, 5);
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (device == null)
+ {
+ device = new UdpAlarmHostDevice();
+ device.deviceID = deviceID;
+ device.IP = IP;
+ device.deviceOnlineState = 1;
+ device.keep_live = keep_alive;
+ deviceList.Add(device);
+ }
+ device.IP = IP;
+ device.groupID = ByteToInt(msg, 9);
+ device.userID = ByteToInt(msg, 13);
+ device.maxSectorNum = msg[17] * 256 + msg[18];
+ }
+
+ private bool checkDevice(UdpAlarmHostDevice device, ref string error)
+ {
+ if (device == null)
+ {
+ error = "没有此报警主机的记录";
+ return false;
+ }
+ if (device.deviceOnlineState == 0)
+ {
+ error = "此报警主机离线";
+ return false;
+ }
+ if (myUdp == null)
+ {
+ error = "UDP故障";
+ return false;
+ }
+ return true;
+ }
+
+ //外出布防或者布防
+ public bool setDeviceDefence(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x60 });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //立即布防
+ public bool setDeviceDefenceImmediately(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x62 });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //在家布防留守布防
+ public bool setDeviceDefenceHome(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x63 });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //即时留守布防
+ public bool setDeviceDefenceHomeImmediately(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x64 });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //撤防
+ public bool withdrawDeviceDefence(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x61 });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //清除报警记忆(复位)
+ public bool clearDeviceDefence(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x65 });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //校对系统时间
+ public bool setDeviceTime(int deviceID, DateTime time, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] content = getBCDTime(time);
+ byte[] bytes = AlarmEncode.getSendMessage(0x8D, content);
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //设备重启
+ public bool rebootDevice(int deviceID, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0xA0, null);
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //单防区布防
+ public bool setDeviceChannelDefence(int deviceID, int channel, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0xC0, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //单防区撤防
+ public bool withdrawDeviceChannelDefence(int deviceID, int channel, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0xC1, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //单防区旁路
+ public bool setDeviceChannelByway(int deviceID, int channel, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0xC2, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ //单防区旁路恢复
+ public bool withdrawDeviceChannelByway(int deviceID, int channel, ref string error)
+ {
+ UdpAlarmHostDevice device = getDevice(deviceID);
+ if (checkDevice(device, ref error))
+ {
+ byte[] bytes = AlarmEncode.getSendMessage(0xC3, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
+ return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/JiLinApp.Docking.csproj b/JiLinApp.Docking/JiLinApp.Docking.csproj
new file mode 100644
index 0000000..2b31c0d
--- /dev/null
+++ b/JiLinApp.Docking/JiLinApp.Docking.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/JiLinApp.Docking/Ptz/DCamera.cs b/JiLinApp.Docking/Ptz/DCamera.cs
new file mode 100644
index 0000000..5a2f8e7
--- /dev/null
+++ b/JiLinApp.Docking/Ptz/DCamera.cs
@@ -0,0 +1,130 @@
+using System;
+
+namespace JiLinApp.Docking.Ptz;
+
+public class DCamera
+{
+ #region Fields
+
+ #region Data3
+
+ public static double SpeedMin = 1;
+ public static double SpeedMax = 60;
+
+ #endregion Data3
+
+ #endregion fields
+
+ #region BaseMethod
+
+ private static byte[] CommandPara(byte com1, byte com2, int data1, int data2)
+ {
+ byte[] b = new byte[11];
+ b[0] = 0xA1;
+ int temp1 = data1;
+ int temp2 = data2;
+ b[1] = 0x00;
+ b[2] = 0x0B;
+ b[3] = com1;
+ b[4] = com2;
+ b[5] = (byte)(data1 >> 8 & 0xFF);
+ b[6] = (byte)(temp1 & 0xFF);
+ b[7] = (byte)(data2 >> 8 & 0xFF);
+ b[8] = (byte)(temp2 & 0xFF);
+ b[9] = (byte)(b[0] ^ b[1] ^ b[2] ^ b[3] ^ b[4] ^ b[5] ^ b[6] ^ b[7] ^ b[8]);
+ b[10] = 0xAF;
+ return b;
+ }
+
+ private static byte[] SendJoystick(double headSpeed, double pitchSpeed)
+ {
+ return CommandPara(0x4D, 0x58, (int)(headSpeed * 100), (int)(pitchSpeed * 100));
+ }
+
+ #endregion BaseMethod
+
+ #region PtzMethod
+
+ public static byte[] Left(double headSpeed)
+ {
+ double absHs = Math.Abs(headSpeed);
+ if (absHs < SpeedMin) headSpeed = -SpeedMin;
+ if (absHs > SpeedMax) headSpeed = -SpeedMax;
+ return SendJoystick(headSpeed, 0);
+ }
+
+ public static byte[] Right(double headSpeed)
+ {
+ double absHs = Math.Abs(headSpeed);
+ if (absHs < SpeedMin) headSpeed = SpeedMin;
+ if (absHs > SpeedMax) headSpeed = SpeedMax;
+ return SendJoystick(headSpeed, 0);
+ }
+
+ public static byte[] Up(double pitchSpeed)
+ {
+ double absPs = Math.Abs(pitchSpeed);
+ if (absPs < SpeedMin) pitchSpeed = SpeedMin;
+ if (absPs > SpeedMax) pitchSpeed = SpeedMax;
+ return SendJoystick(0, pitchSpeed);
+ }
+
+ public static byte[] Down(double pitchSpeed)
+ {
+ double absPs = Math.Abs(pitchSpeed);
+ if (absPs < SpeedMin) pitchSpeed = -SpeedMin;
+ if (absPs > SpeedMax) pitchSpeed = -SpeedMax;
+ return SendJoystick(0, pitchSpeed);
+ }
+
+ public static byte[] LeftUp(double headSpeed, double pitchSpeed)
+ {
+ double absHs = Math.Abs(headSpeed);
+ if (absHs < SpeedMin) headSpeed = -SpeedMin;
+ if (absHs > SpeedMax) headSpeed = -SpeedMax;
+ double absPs = Math.Abs(pitchSpeed);
+ if (absPs < SpeedMin) pitchSpeed = SpeedMin;
+ if (absPs > SpeedMax) pitchSpeed = SpeedMax;
+ return SendJoystick(headSpeed, pitchSpeed);
+ }
+
+ public static byte[] LeftDown(double headSpeed, double pitchSpeed)
+ {
+ double absHs = Math.Abs(headSpeed);
+ if (absHs < SpeedMin) headSpeed = -SpeedMin;
+ if (absHs > SpeedMax) headSpeed = -SpeedMax;
+ double absPs = Math.Abs(pitchSpeed);
+ if (absPs < SpeedMin) pitchSpeed = -SpeedMin;
+ if (absPs > SpeedMax) pitchSpeed = -SpeedMax;
+ return SendJoystick(headSpeed, pitchSpeed);
+ }
+
+ public static byte[] RightUp(double headSpeed, double pitchSpeed)
+ {
+ double absHs = Math.Abs(headSpeed);
+ if (absHs < SpeedMin) headSpeed = SpeedMin;
+ if (absHs > SpeedMax) headSpeed = SpeedMax;
+ double absPs = Math.Abs(pitchSpeed);
+ if (absPs < SpeedMin) pitchSpeed = SpeedMin;
+ if (absPs > SpeedMax) pitchSpeed = SpeedMax;
+ return SendJoystick(headSpeed, pitchSpeed);
+ }
+
+ public static byte[] RightDown(double headSpeed, double pitchSpeed)
+ {
+ double absHs = Math.Abs(headSpeed);
+ if (absHs < SpeedMin) headSpeed = SpeedMin;
+ if (absHs > SpeedMax) headSpeed = SpeedMax;
+ double absPs = Math.Abs(pitchSpeed);
+ if (absPs < SpeedMin) pitchSpeed = -SpeedMin;
+ if (absPs > SpeedMax) pitchSpeed = -SpeedMax;
+ return SendJoystick(headSpeed, pitchSpeed);
+ }
+
+ public static byte[] Stop()
+ {
+ return SendJoystick(0, 0);
+ }
+
+ #endregion PtzMethod
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/Ptz/PelcoD.cs b/JiLinApp.Docking/Ptz/PelcoD.cs
new file mode 100644
index 0000000..549358b
--- /dev/null
+++ b/JiLinApp.Docking/Ptz/PelcoD.cs
@@ -0,0 +1,242 @@
+using System;
+
+namespace JiLinApp.Docking.Ptz;
+
+public class PelcoD
+{
+ private string watchdir = ""; //监控方向
+ private static readonly byte STX = 0xFF; //同步字节
+
+ #region 监控方向和定时监控实体
+
+ public string WatchDir
+ {
+ get { return watchdir; }
+ set { watchdir = value; }
+ }
+
+ #endregion 监控方向和定时监控实体
+
+ #region 基本指令定义
+
+ #region 指令码1
+
+ private const byte FocusNear = 0x01; //增加聚焦
+ private const byte IrisOpen = 0x02; //减小光圈
+ private const byte IrisClose = 0x04; //增加光圈
+ private const byte CameraOnOff = 0x08; //摄像机打开和关闭
+ private const byte AutoManualScan = 0x10; //自动和手动扫描
+ private const byte Sense = 0x80; //Sence码
+
+ #endregion 指令码1
+
+ #region 指令码2
+
+ private const byte PanRight = 0x02; //右
+ private const byte PanLeft = 0x04; //左
+
+ private const byte TiltUp = 0x08; //上
+ private const byte TiltDown = 0x10; //下
+ private const byte ZoomTele = 0x20; //增加对焦
+ private const byte ZoomWide = 0x40; //减小对焦
+ private const byte FocusFar = 0x80; //减小聚焦
+
+ #endregion 指令码2
+
+ #region 镜头左右平移的速度
+
+ public static byte PanSpeedMin = 0x00; //停止
+ public static byte PanSpeedMax = 0x3F; //最高速
+
+ #endregion 镜头左右平移的速度
+
+ #region 镜头上下移动的速度
+
+ public static byte TiltSpeedMin = 0x00; //停止
+ public static byte TiltSpeedMax = 0x3F; //最高速
+
+ #endregion 镜头上下移动的速度
+
+ #endregion 基本指令定义
+
+ private const byte PanRightUp = 0xa; //右上
+ private const byte PanLeftUp = 0x0c; //左上
+
+ private const byte PanRightDown = 0x12; //右下
+ private const byte PanLeftDown = 0x14; //左下
+
+ #region 云台控制枚举
+
+ public enum Switch
+ {
+ On = 0x01,
+ Off = 0x02
+ } //雨刷控制
+
+ public enum Focus
+ {
+ Near = FocusNear,
+ Far = FocusFar
+ } //聚焦控制
+
+ public enum Zoom
+ {
+ Wide = ZoomWide,
+ Tele = ZoomTele
+ } //对焦控制
+
+ public enum Tilt
+ {
+ Up = TiltUp,
+ Down = TiltDown
+ } //上下控制
+
+ public enum Pan
+ {
+ Left = PanLeft,
+ Right = PanRight,
+ LeftUp = PanLeftUp,
+ LeftDown = PanLeftDown,
+ RightUp = PanRightUp,
+ RightDown = PanRightDown
+ } //左右控制
+
+ public enum Scan
+ {
+ Auto,
+ Manual
+ } //自动和手动控制
+
+ public enum Iris
+ {
+ Open = IrisOpen,
+ Close = IrisClose
+ } //光圈控制
+
+ public enum PresetAction
+ {
+ Set = 0x03,
+ Clear = 0x05,
+ Goto = 0x07
+ }
+
+ #endregion 云台控制枚举
+
+ #region 云台控制方法
+
+ //雨刷控制
+ public static byte[] CameraSwitch(uint deviceAddress, Switch action)
+ {
+ byte m_action = CameraOnOff;
+ if (action == Switch.On)
+ m_action = CameraOnOff + Sense;
+ return Message.GetMessage(deviceAddress, m_action, 0x00, 0x00, 0x00);
+ }
+
+ //光圈控制
+ public static byte[] CameraIrisSwitch(uint deviceAddress, Iris action)
+ {
+ return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
+ }
+
+ //聚焦控制
+ public static byte[] CameraFocus(uint deviceAddress, Focus action)
+ {
+ if (action == Focus.Near)
+ return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
+ else
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, 0x00);
+ }
+
+ //对焦控制
+ public static byte[] CameraZoom(uint deviceAddress, Zoom action)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, 0x00);
+ }
+
+ ///
+ /// 上下控制
+ ///
+ ///
+ ///
+ ///
+ ///
+
+ public static byte[] CameraTilt(uint deviceAddress, Tilt action, uint speed)
+ {
+ if (speed < TiltSpeedMin)
+ speed = TiltSpeedMin;
+ if (speed > TiltSpeedMax)
+ speed = TiltSpeedMax;
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, (byte)speed);
+ }
+
+ ///
+ /// 左右控制
+ ///
+ ///
+ ///
+ ///
+ ///
+
+ public static byte[] CameraPan(uint deviceAddress, Pan action, uint speed)
+ {
+ if (speed < PanSpeedMin)
+ speed = PanSpeedMin;
+ if (speed > PanSpeedMax)
+ speed = PanSpeedMax;
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, (byte)speed, 0x00);
+ }
+
+ //停止云台的移动
+ public static byte[] CameraStop(uint deviceAddress)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x00, 0x00, 0x00);
+ }
+
+ //自动和手动控制
+ public static byte[] CameraScan(uint deviceAddress, Scan scan)
+ {
+ byte m_byte = AutoManualScan;
+ if (scan == Scan.Auto)
+ m_byte = AutoManualScan + Sense;
+ return Message.GetMessage(deviceAddress, m_byte, 0x00, 0x00, 0x00);
+ }
+
+ public static byte[] Preset(uint deviceAddress, PresetAction action, byte presetId)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, presetId);
+ }
+
+ #endregion 云台控制方法
+
+ public struct Message
+ {
+ public static byte Address;
+ public static byte CheckSum;
+
+ public static byte Command1,
+ Command2,
+ Data1,
+ Data2;
+
+ public static byte[] GetMessage(
+ uint address,
+ byte command1,
+ byte command2,
+ byte data1,
+ byte data2
+ )
+ {
+ if (address < 1 & address > 256)
+ throw new Exception("Pelco D协议只支持256设备");
+ Address = byte.Parse(address.ToString());
+ Command1 = command1;
+ Command2 = command2;
+ Data1 = data1;
+ Data2 = data2;
+ CheckSum = (byte)(Address + Command1 + Command2 + Data1 + Data2);
+ return new byte[] { STX, Address, Command1, Command2, Data1, Data2, CheckSum };
+ }
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/Ptz/PelcoP.cs b/JiLinApp.Docking/Ptz/PelcoP.cs
new file mode 100644
index 0000000..df7e521
--- /dev/null
+++ b/JiLinApp.Docking/Ptz/PelcoP.cs
@@ -0,0 +1,339 @@
+using System;
+
+namespace JiLinApp.Docking.Ptz;
+
+///
+/// dot.NET Implementation of Pelco P Protocol
+///
+public class PelcoP
+{
+ private const byte STX = 0xA0;
+ private const byte ETX = 0xAF;
+
+ #region Pan and Tilt Commands
+
+ #region Data1
+
+ private const byte FocusFar = 0x01;
+ private const byte FocusNear = 0x02;
+ private const byte IrisOpen = 0x04;
+ private const byte IrisClose = 0x08;
+ private const byte CameraOnOff = 0x10;
+ private const byte AutoscanOn = 0x20;
+ private const byte CameraOn = 0x40;
+
+ #endregion Data1
+
+ #region Data2
+
+ private const byte PanRight = 0x02;
+ private const byte PanLeft = 0x04;
+ private const byte TiltUp = 0x08;
+ private const byte TiltDown = 0x10;
+ private const byte ZoomTele = 0x20;
+ private const byte ZoomWide = 0x40;
+
+ #endregion Data2
+
+ #region Data3
+
+ public static byte PanSpeedMin = 0x00;
+ public static byte PanSpeedMax = 0x3F;
+
+ #endregion Data3
+
+ #region Data4
+
+ public static byte TiltSpeedMin = 0x00;
+ public static byte TiltSpeedMax = 0x3F;
+
+ #endregion Data4
+
+ #endregion Pan and Tilt Commands
+
+ #region Enums
+
+ public enum PatternAction
+ {
+ Start,
+ Stop,
+ Run
+ }
+
+ public enum Action
+ {
+ Start,
+ Stop
+ }
+
+ public enum LensSpeed
+ {
+ Low = 0x00,
+ Medium = 0x01,
+ High = 0x02,
+ Turbo = 0x03
+ }
+
+ public enum Pan
+ {
+ Left = PanLeft,
+ Right = PanRight
+ }
+
+ public enum Tilt
+ {
+ Up = TiltUp,
+ Down = TiltDown
+ }
+
+ public enum Iris
+ {
+ Open = IrisOpen,
+ Close = IrisClose
+ }
+
+ public enum Zoom
+ {
+ Wide = ZoomWide,
+ Tele = ZoomTele
+ }
+
+ public enum Switch
+ {
+ On,
+ Off
+ }
+
+ public enum Focus
+ {
+ Near = FocusNear,
+ Far = FocusFar
+ }
+
+ public enum PresetAction
+ {
+ Set = 0x03,
+ Clear = 0x05,
+ Goto = 0x07
+ }
+
+ #endregion Enums
+
+ #region Extended Command Set
+
+ public static byte[] Preset(uint deviceAddress, PresetAction action, byte presetId)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, presetId);
+ }
+
+ public static byte[] Flip(uint deviceAddress)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x07, 0x00, 0x21);
+ }
+
+ public static byte[] ZeroPanPosition(uint deviceAddress)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x07, 0x00, 0x22);
+ }
+
+ public static byte[] AutoScan(uint deviceAddress, Action action)
+ {
+ byte m_action;
+ if (action == Action.Start)
+ m_action = 0x09;
+ else
+ m_action = 0x0B;
+ return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, 0x00);
+ }
+
+ public static byte[] RemoteReset(uint deviceAddress)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x0F, 0x00, 0x00);
+ }
+
+ public static byte[] Zone(uint deviceAddress, byte zone, Action action)
+ {
+ if (zone < 0x01 & zone > 0x08)
+ throw new Exception("Zone value should be between 0x01 and 0x08 include");
+ byte m_action;
+ if (action == Action.Start)
+ m_action = 0x11;
+ else
+ m_action = 0x13;
+
+ return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, zone);
+ }
+
+ public static byte[] WriteToScreen(uint deviceAddress, string text)
+ {
+ if (text.Length > 40)
+ text = text.Remove(40, text.Length - 40);
+ System.Text.Encoding encoding = System.Text.Encoding.ASCII;
+ byte[] m_bytes = new byte[encoding.GetByteCount(text) * 8];
+ int i = 0;
+ byte m_scrPosition;
+ byte m_ASCIIchr;
+
+ foreach (char ch in text)
+ {
+ m_scrPosition = Convert.ToByte(i / 8);
+ m_ASCIIchr = Convert.ToByte(ch);
+ Array.Copy(
+ Message.GetMessage(deviceAddress, 0x00, 0x15, m_scrPosition, m_ASCIIchr),
+ 0,
+ m_bytes,
+ i,
+ 8
+ );
+ i += 8;
+ }
+
+ return m_bytes;
+ }
+
+ public static byte[] ClearScreen(uint deviceAddress)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x17, 0x00, 0x00);
+ }
+
+ public static byte[] AlarmAcknowledge(uint deviceAddress, uint alarmID)
+ {
+ if (alarmID < 1 & alarmID > 8)
+ throw new Exception("Only 8 alarms allowed for Pelco P implementation");
+ return Message.GetMessage(deviceAddress, 0x00, 0x19, 0x00, Convert.ToByte(alarmID));
+ }
+
+ public static byte[] ZoneScan(uint deviceAddress, Action action)
+ {
+ byte m_action;
+ if (action == Action.Start)
+ m_action = 0x1B;
+ else
+ m_action = 0x1D;
+ return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, 0x00);
+ }
+
+ public static byte[] Pattern(uint deviceAddress, PatternAction action)
+ {
+ byte m_action = action switch
+ {
+ PatternAction.Start => 0x1F,
+ PatternAction.Stop => 0x21,
+ PatternAction.Run => 0x23,
+ _ => 0x23,
+ };
+ return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, 0x00);
+ }
+
+ public static byte[] SetZoomLensSpeed(uint deviceAddress, LensSpeed speed)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x25, 0x00, (byte)speed);
+ }
+
+ public static byte[] SetFocusLensSpeed(uint deviceAddress, LensSpeed speed)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x27, 0x00, (byte)speed);
+ }
+
+ #endregion Extended Command Set
+
+ #region Base Command Set
+
+ public static byte[] CameraSwitch(uint deviceAddress, Switch action)
+ {
+ byte m_action = CameraOnOff;
+ if (action == Switch.On)
+ m_action += CameraOnOff; //Maybe wrong !!!
+ return Message.GetMessage(deviceAddress, m_action, 0x00, 0x00, 0x00);
+ }
+
+ public static byte[] CameraIrisSwitch(uint deviceAddress, Iris action)
+ {
+ return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
+ }
+
+ public static byte[] CameraFocus(uint deviceAddress, Focus action)
+ {
+ return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
+ }
+
+ public static byte[] CameraZoom(uint deviceAddress, Zoom action)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, 0x00);
+ }
+
+ public static byte[] CameraTilt(uint deviceAddress, Tilt action, uint speed)
+ {
+ if (speed < TiltSpeedMin)
+ speed = TiltSpeedMin;
+ if (speed > TiltSpeedMax)
+ speed = TiltSpeedMax;
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, (byte)speed);
+ }
+
+ public static byte[] CameraPan(uint deviceAddress, Pan action, uint speed)
+ {
+ if (speed < PanSpeedMin)
+ speed = PanSpeedMin;
+ if (speed > PanSpeedMax)
+ speed = PanSpeedMax;
+ return Message.GetMessage(deviceAddress, 0x00, (byte)action, (byte)speed, 0x00);
+ }
+
+ public static byte[] CameraPanTilt(
+ uint deviceAddress,
+ Pan panAction,
+ uint panSpeed,
+ Tilt tiltAction,
+ uint tiltSpeed
+ )
+ {
+ byte[] m_tiltMessage = CameraTilt(deviceAddress, tiltAction, tiltSpeed);
+ byte[] m_panMessage = CameraPan(deviceAddress, panAction, panSpeed);
+ byte[] m_bytes = Message.GetMessage(
+ deviceAddress,
+ 0x00,
+ (byte)(m_tiltMessage[3] + m_panMessage[3]),
+ m_panMessage[4],
+ m_tiltMessage[5]
+ );
+ return m_bytes;
+ }
+
+ public static byte[] CameraStop(uint deviceAddress)
+ {
+ return Message.GetMessage(deviceAddress, 0x00, 0x00, 0x00, 0x00);
+ }
+
+ #endregion Base Command Set
+
+ public struct Message
+ {
+ public static byte Address;
+ public static byte CheckSum;
+
+ public static byte Data1,
+ Data2,
+ Data3,
+ Data4;
+
+ public static byte[] GetMessage(
+ uint address,
+ byte data1,
+ byte data2,
+ byte data3,
+ byte data4
+ )
+ {
+ if (address < 0 & address > 32)
+ throw new Exception("Protocol Pelco P support 32 devices only");
+ Address = byte.Parse((address - 1).ToString());
+ Data1 = data1;
+ Data2 = data2;
+ Data3 = data3;
+ Data4 = data4;
+ CheckSum = (byte)(STX ^ Address ^ Data1 ^ Data2 ^ Data3 ^ Data4 ^ ETX);
+ return new byte[] { STX, Address, Data1, Data2, Data3, Data4, ETX, CheckSum };
+ }
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/Ptz/PtzCmd.cs b/JiLinApp.Docking/Ptz/PtzCmd.cs
new file mode 100644
index 0000000..5962239
--- /dev/null
+++ b/JiLinApp.Docking/Ptz/PtzCmd.cs
@@ -0,0 +1,219 @@
+using EC.Util.CameraSDK;
+using System;
+
+namespace JiLinApp.Docking.Ptz;
+
+public class PtzCmd
+{
+ public static PtzControlType GetControlType(string ctrlStr)
+ {
+ return ctrlStr switch
+ {
+ "PelcoD" => PtzControlType.PelcoD,
+ "PelcoP" => PtzControlType.PelcoP,
+ "HikSdk" => PtzControlType.HikSdk,
+ _ => PtzControlType.None
+ };
+ }
+
+ public static PtzCmdType GetCmdType(string cmdStr)
+ {
+ return cmdStr switch
+ {
+ "Top" => PtzCmdType.Top,
+ "Down" => PtzCmdType.Down,
+ "Left" => PtzCmdType.Left,
+ "Right" => PtzCmdType.Right,
+ "TopLeft" => PtzCmdType.LeftTop,
+ "TopRight" => PtzCmdType.RightTop,
+ "DownLeft" => PtzCmdType.LeftDown,
+ "DownRight" => PtzCmdType.RightDown,
+ "Stop" => PtzCmdType.Stop,
+ "AutoStart" => PtzCmdType.AutoStart,
+ "AutoStop" => PtzCmdType.AutoStop,
+ "PresetSet" => PtzCmdType.PresetSet,
+ "PresetClear" => PtzCmdType.PresetClear,
+ "PresetGoto" => PtzCmdType.PresetGoto,
+ _ => PtzCmdType.None
+ };
+ }
+
+ ///
+ /// GetPelcoDCmd
+ /// GetPelcoPCmd
+ /// DCamearCmd
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static byte[] GetCmd(PtzControlType ctrlType, PtzCmdType cmdType, object[] args = null)
+ {
+ byte[] cmd = ctrlType switch
+ {
+ PtzControlType.PelcoD => GetPelcoDCmd(cmdType, args),
+ PtzControlType.PelcoP => GetPelcoPCmd(cmdType, args),
+ PtzControlType.DCamera => GetDCameraCmd(cmdType, args),
+ _ => Array.Empty(),
+ };
+ return cmd;
+ }
+
+ public static byte[] GetPelcoDCmd(PtzCmdType cmdType, object[] args)
+ {
+ uint addr = (byte)args[0];
+ uint panSpeed = 0x2f;
+ uint tiltSpeed = (uint)(PelcoD.TiltSpeedMax + PelcoD.TiltSpeedMin) / 2;
+ byte[] cmd = cmdType switch
+ {
+ PtzCmdType.Left => PelcoD.CameraPan(addr, PelcoD.Pan.Left, panSpeed),
+ PtzCmdType.Right => PelcoD.CameraPan(addr, PelcoD.Pan.Right, panSpeed),
+ PtzCmdType.Top => PelcoD.CameraTilt(addr, PelcoD.Tilt.Up, tiltSpeed),
+ PtzCmdType.Down => PelcoD.CameraTilt(addr, PelcoD.Tilt.Down, tiltSpeed),
+ PtzCmdType.LeftTop => PelcoD.CameraPan(addr, PelcoD.Pan.LeftUp, panSpeed),
+ PtzCmdType.LeftDown => PelcoD.CameraPan(addr, PelcoD.Pan.LeftDown, panSpeed),
+ PtzCmdType.RightTop => PelcoD.CameraPan(addr, PelcoD.Pan.RightUp, panSpeed),
+ PtzCmdType.RightDown => PelcoD.CameraPan(addr, PelcoD.Pan.RightDown, panSpeed),
+ PtzCmdType.Stop => PelcoD.CameraStop(addr),
+ PtzCmdType.AutoStart => PelcoD.CameraScan(addr, PelcoD.Scan.Auto),
+ PtzCmdType.AutoStop => PelcoD.CameraScan(addr, PelcoD.Scan.Manual),
+ PtzCmdType.PresetGoto => PelcoD.Preset(addr, PelcoD.PresetAction.Goto, (byte)args[1]),
+ _ => Array.Empty(),
+ };
+ return cmd;
+ }
+
+ public static byte[] GetPelcoPCmd(PtzCmdType cmdType, object[] args)
+ {
+ uint addr = (byte)args[0];
+ uint panSpeed = (uint)(PelcoP.PanSpeedMax + PelcoP.PanSpeedMin) / 2;
+ uint tiltSpeed = (uint)(PelcoP.TiltSpeedMax + PelcoP.TiltSpeedMin) / 2;
+ byte[] cmd = cmdType switch
+ {
+ PtzCmdType.Left => PelcoP.CameraPan(addr, PelcoP.Pan.Left, panSpeed),
+ PtzCmdType.Right => PelcoP.CameraPan(addr, PelcoP.Pan.Right, panSpeed),
+ PtzCmdType.Top => PelcoP.CameraTilt(addr, PelcoP.Tilt.Up, tiltSpeed),
+ PtzCmdType.Down => PelcoP.CameraTilt(addr, PelcoP.Tilt.Down, tiltSpeed),
+ PtzCmdType.LeftTop => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Left, panSpeed, PelcoP.Tilt.Up, tiltSpeed),
+ PtzCmdType.LeftDown => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Left, panSpeed, PelcoP.Tilt.Down, tiltSpeed),
+ PtzCmdType.RightTop => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Right, panSpeed, PelcoP.Tilt.Up, tiltSpeed),
+ PtzCmdType.RightDown => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Right, panSpeed, PelcoP.Tilt.Down, tiltSpeed),
+ PtzCmdType.Stop => PelcoP.CameraStop(addr),
+ PtzCmdType.AutoStart => PelcoP.AutoScan(addr, PelcoP.Action.Start),
+ PtzCmdType.AutoStop => PelcoP.AutoScan(addr, PelcoP.Action.Stop),
+ PtzCmdType.PresetGoto => PelcoP.Preset(addr, PelcoP.PresetAction.Goto, (byte)args[1]),
+ _ => Array.Empty(),
+ };
+ return cmd;
+ }
+
+ public static byte[] GetDCameraCmd(PtzCmdType cmdType, object[] args)
+ {
+ double speed = (DCamera.SpeedMax + DCamera.SpeedMin) / 2;
+ byte[] cmd = cmdType switch
+ {
+ PtzCmdType.Left => DCamera.Left(speed),
+ PtzCmdType.Right => DCamera.Right(speed),
+ PtzCmdType.Top => DCamera.Up(speed),
+ PtzCmdType.Down => DCamera.Down(speed),
+ PtzCmdType.LeftTop => DCamera.LeftUp(speed, speed),
+ PtzCmdType.LeftDown => DCamera.LeftDown(speed, speed),
+ PtzCmdType.RightTop => DCamera.RightUp(speed, speed),
+ PtzCmdType.RightDown => DCamera.RightDown(speed, speed),
+ PtzCmdType.Stop => DCamera.Stop(),
+ //PtzCmdType.PresetGoto => DCamera.Up(speed),
+ _ => Array.Empty(),
+ };
+ return cmd;
+ }
+
+ public static void HikPtzMove(ref HiKSDK sdk, PtzCmdType cmdType, uint[] args)
+ {
+ if (sdk == null || args == null) return;
+ uint[] arr = new uint[args.Length + 1];
+ args.CopyTo(arr, 1);
+ switch (cmdType)
+ {
+ case PtzCmdType.Left:
+ arr[0] = HiKOriSDK.PAN_LEFT;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.Right:
+ arr[0] = HiKOriSDK.PAN_RIGHT;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.Top:
+ arr[0] = HiKOriSDK.TILT_UP;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.Down:
+ arr[0] = HiKOriSDK.TILT_DOWN;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.LeftTop:
+ arr[0] = HiKOriSDK.UP_LEFT;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.LeftDown:
+ arr[0] = HiKOriSDK.DOWN_LEFT;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.RightTop:
+ arr[0] = HiKOriSDK.UP_RIGHT;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.RightDown:
+ arr[0] = HiKOriSDK.DOWN_RIGHT;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.AutoStart:
+ arr[0] = HiKOriSDK.PAN_AUTO;
+ sdk.PtzMove(arr);
+ break;
+
+ case PtzCmdType.PresetGoto:
+ arr[0] = HiKOriSDK.GOTO_PRESET;
+ sdk.PtzPreset(arr);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+public enum PtzControlType
+{
+ PelcoD,
+ PelcoP,
+ DCamera,
+ HikSdk,
+ None,
+}
+
+public enum PtzCmdType
+{
+ Top,
+ Down,
+ Left,
+ Right,
+ LeftTop,
+ LeftDown,
+ RightTop,
+ RightDown,
+ Stop,
+ AutoStart,
+ AutoStop,
+ PresetSet,
+ PresetClear,
+ PresetGoto,
+ None
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs
new file mode 100644
index 0000000..5b2ecec
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs
@@ -0,0 +1,73 @@
+using System.Collections;
+using System.Net.Sockets;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class ClientMessage
+{
+ public TcpClient client { get; set; }
+
+ public TcpAlarmHostTable host { get; set; }
+
+ public string IP
+ {
+ get
+ {
+ if (host != null) return host.ip;
+ if (client != null) return client.Client.RemoteEndPoint.ToString().Split(':')[0];
+ return "";
+ }
+ }
+
+ public string Port
+ {
+ get
+ {
+ if (host != null) return host.port;
+ if (client != null) return client.Client.RemoteEndPoint.ToString().Split(':')[1];
+ return "-1";
+ }
+ }
+
+ public List list { get; set; }
+
+ public Hashtable sectioTable { get; set; }
+
+ public ClientMessage()
+ {
+ list = new List();
+ host = null;
+ sectioTable = new Hashtable();
+ }
+
+ public List getMessageList()
+ {
+ List msglist = new List();
+ while (list.Count >= 19)
+ {
+ if (list[0] == 0xAA && list[1] == 0xAA)
+ {
+ int num = list[17];
+ if (list.Count < 19 + num)
+ {
+ break;
+ }
+ else
+ {
+ byte[] bytes = new byte[num + 19];
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ bytes[i] = list[i];
+ }
+ msglist.Add(bytes);
+ list.RemoveRange(0, num + 19);
+ }
+ }
+ else
+ {
+ list.RemoveAt(0);
+ }
+ }
+ return msglist;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/DataMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/DataMessage.cs
new file mode 100644
index 0000000..7b6aa84
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/DataMessage.cs
@@ -0,0 +1,89 @@
+using System.Text;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class DataMessage
+{
+ private byte headA = 0xAA;
+ private byte headB = 0xAA; //(1)帧头
+ public int deviceID { get; set; } //(2)设备ID
+
+ public string sendIP { get; set; } //(3)原地址
+ public int sendPort { get; set; }//(3)原地址
+ public string receiveIP { get; set; }//(4)目标地址
+ public int receivePort { get; set; }//(4)目标地址
+ public byte frameNum { get; set; }//(5)帧编号
+ public byte functionNum { get; set; }//(6)功能码
+ public byte dataLen { get; set; }//(7)传输数据长度
+ public byte[] data { get; set; }//(8)传输数据
+ public byte CRC { get; set; }//(9)CRC8
+
+ public void decode(byte[] bytes)
+ {
+ deviceID = bytes[2];
+ sendIP = bytes[3].ToString() + "." + bytes[4].ToString() + "." + bytes[5].ToString() + "." + bytes[6].ToString();
+ sendPort = bytes[8] * 256 + bytes[7];
+ receiveIP = bytes[9].ToString() + "." + bytes[10].ToString() + "." + bytes[11].ToString() + "." + bytes[12].ToString();
+ receivePort = bytes[13] * 256 + bytes[14];
+ frameNum = bytes[15];
+ functionNum = bytes[16];
+ dataLen = bytes[17];
+ data = new byte[dataLen];
+ for (int i = 0; i < dataLen; i++)
+ {
+ data[i] = bytes[18 + i];
+ }
+ CRC = bytes[18 + dataLen];
+ }
+
+ public byte[] encode()
+ {
+ byte[] bytes = new byte[19 + dataLen];
+ bytes[0] = bytes[1] = 0xAA;
+ bytes[2] = (byte)deviceID;
+
+ string[] strs = sendIP.Split('.');
+ bytes[3] = byte.Parse(strs[0]);
+ bytes[4] = byte.Parse(strs[1]);
+ bytes[5] = byte.Parse(strs[2]);
+ bytes[6] = byte.Parse(strs[3]);
+ bytes[7] = (byte)(sendPort % 256);
+ bytes[8] = (byte)(sendPort / 256);
+
+ string[] strs2 = receiveIP.Split('.');
+ bytes[9] = byte.Parse(strs2[0]);
+ bytes[10] = byte.Parse(strs2[1]);
+ bytes[11] = byte.Parse(strs2[2]);
+ bytes[12] = byte.Parse(strs2[3]);
+ bytes[13] = (byte)(receivePort % 256);
+ bytes[14] = (byte)(receivePort / 256);
+ bytes[15] = frameNum;
+ bytes[16] = functionNum;
+ bytes[17] = dataLen;
+ for (int i = 0; i < dataLen; i++)
+ {
+ bytes[18 + i] = data[i];
+ }
+ bytes[bytes.Length - 1] = CRC8.CRC(bytes, 0, bytes.Length - 1);
+ Console.WriteLine("发送指令:" + ToHexString(bytes));
+ return bytes;
+ }
+
+ private string ToHexString(byte[] bytes)
+ {
+ string hexString = string.Empty;
+
+ if (bytes != null)
+ {
+ StringBuilder strB = new StringBuilder();
+
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ strB.Append(bytes[i].ToString("X2") + " ");
+ }
+
+ hexString = strB.ToString();
+ }
+ return hexString;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/DataRequest.cs b/JiLinApp.Docking/VibrateAlarm/Entity/DataRequest.cs
new file mode 100644
index 0000000..d3e39e3
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/DataRequest.cs
@@ -0,0 +1,14 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class DataRequest
+{
+ public DataMessage request { get; set; }
+
+ public DataMessage responce { get; set; }
+
+ public DataRequest()
+ {
+ responce = null;
+ request = null;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/SectionState.cs b/JiLinApp.Docking/VibrateAlarm/Entity/SectionState.cs
new file mode 100644
index 0000000..0b6339e
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/SectionState.cs
@@ -0,0 +1,57 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class SectionState
+{
+ public int deviceID { get; set; }
+
+ public string channel { get; set; }
+ public int online { get; set; }
+
+ public string onLine_str
+ {
+ get
+ {
+ if (online == 0)
+ {
+ return "在线";
+ }
+ else
+ {
+ return "离线";
+ }
+ }
+ }
+
+ public int alarm { get; set; }
+
+ public string alarm_str
+ {
+ get
+ {
+ if (alarm == 0)
+ {
+ return "消警";
+ }
+ else
+ {
+ return "报警";
+ }
+ }
+ }
+
+ public SectionState(int id, int chan, int state)
+ {
+ deviceID = id;
+ channel = chan.ToString();
+ online = state % 2;
+ alarm = state / 2 % 2;
+ }
+
+ public SectionState(int id, int chan, int on, int a)
+ {
+ deviceID = id;
+ channel = chan.ToString();
+ online = on;
+ alarm = a;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs
new file mode 100644
index 0000000..4a92739
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json.Linq;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class TcpAlarmHostMessage
+{
+ public int Id { get; set; }
+ public string AlarmId { get; set; }//CID代码
+ public string AlarmTime { get; set; }//报警时间
+
+ /*设备信息*/
+ public int DeviceID { get; set; }//设备唯一ID
+ public string ChannelNum { get; set; }//防区号
+ public string Mode { get; set; }
+ public string Sensitivity { get; set; }
+
+ /*联动信息*/
+ public bool IsLinked { get; set; }//是否有联动信息
+ public JArray Linklist { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs
new file mode 100644
index 0000000..2a40f91
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs
@@ -0,0 +1,16 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class TcpAlarmHostTable
+{
+ public int id { get; set; }
+
+ public string name { get; set; }
+
+ public string lat { get; set; }
+
+ public string lng { get; set; }
+
+ public string ip { get; set; }
+
+ public string port { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/TcpManagerConfig.cs b/JiLinApp.Docking/VibrateAlarm/Entity/TcpManagerConfig.cs
new file mode 100644
index 0000000..6d3ce78
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/TcpManagerConfig.cs
@@ -0,0 +1,10 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class TcpManagerConfig
+{
+ public string ServerIp { get; set; }
+
+ public int ServerPort { get; set; }
+
+ public int DeviceHeartKeep { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/TcpSectionTable.cs b/JiLinApp.Docking/VibrateAlarm/Entity/TcpSectionTable.cs
new file mode 100644
index 0000000..42b4ff2
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Entity/TcpSectionTable.cs
@@ -0,0 +1,17 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class TcpSectionTable
+{
+ public int id { get; set; }
+ public int deviceID { get; set; }
+
+ public string name { get; set; }
+ public string lat { get; set; }
+
+ public string lng { get; set; }
+
+ public string channel { get; set; }
+
+ public string mode { get; set; }
+ public string sensitivity { get; set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs
new file mode 100644
index 0000000..7eb9fba
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs
@@ -0,0 +1,522 @@
+using System.Collections.Concurrent;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class AsyncTcpServer : IDisposable
+{
+ #region Fields
+
+ private TcpListener _listener;
+ private ConcurrentDictionary _clients;
+ private bool _disposed = false;
+
+ #endregion Fields
+
+ #region Ctors
+
+ private byte[] inOptionValues;
+
+ ///
+ /// 异步TCP服务器
+ ///
+ /// 监听的端口
+ public AsyncTcpServer(int listenPort)
+ : this(IPAddress.Any, listenPort)
+ {
+ uint dummy = 0;
+ inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
+ BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
+ BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
+ BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
+ }
+
+ ///
+ /// 异步TCP服务器
+ ///
+ /// 监听的终结点
+ public AsyncTcpServer(IPEndPoint localEP)
+ : this(localEP.Address, localEP.Port)
+ {
+ uint dummy = 0;
+ inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
+ BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
+ BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
+ BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
+ }
+
+ ///
+ /// 异步TCP服务器
+ ///
+ /// 监听的IP地址
+ /// 监听的端口
+ public AsyncTcpServer(IPAddress localIPAddress, int listenPort)
+ {
+ uint dummy = 0;
+ inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
+ BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
+ BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
+ BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
+ Address = localIPAddress;
+ Port = listenPort;
+ Encoding = Encoding.Default;
+
+ _clients = new ConcurrentDictionary();
+
+ _listener = new TcpListener(Address, Port);
+ _listener.AllowNatTraversal(true);
+ }
+
+ #endregion Ctors
+
+ #region Properties
+
+ ///
+ /// 服务器是否正在运行
+ ///
+ public bool IsRunning { get; private set; }
+
+ ///
+ /// 监听的IP地址
+ ///
+ public IPAddress Address { get; private set; }
+
+ ///
+ /// 监听的端口
+ ///
+ public int Port { get; private set; }
+
+ ///
+ /// 通信使用的编码
+ ///
+ public Encoding Encoding { get; set; }
+
+ #endregion Properties
+
+ #region Server
+
+ ///
+ /// 启动服务器
+ ///
+ /// 异步TCP服务器
+ public AsyncTcpServer Start()
+ {
+ return Start(30);
+ }
+
+ ///
+ /// 启动服务器
+ ///
+ /// 服务器所允许的挂起连接序列的最大长度
+ /// 异步TCP服务器
+ public AsyncTcpServer Start(int backlog)
+ {
+ if (IsRunning) return this;
+
+ IsRunning = true;
+ _listener.Start(backlog);
+ ContinueAcceptTcpClient(_listener);
+
+ return this;
+ }
+
+ ///
+ /// 停止服务器
+ ///
+ /// 异步TCP服务器
+ public AsyncTcpServer Stop()
+ {
+ if (!IsRunning) return this;
+
+ try
+ {
+ _listener.Stop();
+
+ foreach (var client in _clients.Values)
+ {
+ client.TcpClient.Client.Disconnect(false);
+ }
+ _clients.Clear();
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine("socket错误:" + ex.Message);
+ }
+ IsRunning = false;
+
+ return this;
+ }
+
+ private void ContinueAcceptTcpClient(TcpListener tcpListener)
+ {
+ try
+ {
+ tcpListener.BeginAcceptTcpClient(new AsyncCallback(HandleTcpClientAccepted), tcpListener);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine("socket错误:" + ex.Message);
+ }
+ }
+
+ #endregion Server
+
+ #region Receive
+
+ private void HandleTcpClientAccepted(IAsyncResult ar)
+ {
+ if (!IsRunning) return;
+
+ TcpListener tcpListener;
+ TcpClient tcpClient;
+ try
+ {
+ tcpListener = (TcpListener)ar.AsyncState;
+ tcpClient = tcpListener.EndAcceptTcpClient(ar);
+ tcpClient.Client.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ return;
+ }
+ if (!tcpClient.Connected) return;
+
+ byte[] buffer = new byte[tcpClient.ReceiveBufferSize];
+ TcpClientState internalClient = new TcpClientState(tcpClient, buffer);
+
+ // add client connection to cache
+ string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString();
+ _clients.AddOrUpdate(tcpClientKey, internalClient, (n, o) => { return internalClient; });
+ RaiseClientConnected(tcpClient);
+
+ // begin to read data
+ NetworkStream networkStream = internalClient.NetworkStream;
+ ContinueReadBuffer(internalClient, networkStream);
+
+ // keep listening to accept next connection
+ ContinueAcceptTcpClient(tcpListener);
+ }
+
+ private void HandleDatagramReceived(IAsyncResult ar)
+ {
+ if (!IsRunning) return;
+
+ try
+ {
+ TcpClientState internalClient = (TcpClientState)ar.AsyncState;
+ if (!internalClient.TcpClient.Connected) return;
+
+ NetworkStream networkStream = internalClient.NetworkStream;
+
+ int numberOfReadBytes = 0;
+ try
+ {
+ // if the remote host has shutdown its connection,
+ // read will immediately return with zero bytes.
+ numberOfReadBytes = networkStream.EndRead(ar);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("错误:" + ex.Message);
+ numberOfReadBytes = 0;
+ }
+
+ if (numberOfReadBytes == 0)
+ {
+ // connection has been closed
+ TcpClientState internalClientToBeThrowAway;
+ string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString();
+ _clients.TryRemove(tcpClientKey, out internalClientToBeThrowAway);
+ RaiseClientDisconnected(internalClient.TcpClient);
+ return;
+ }
+
+ // received byte and trigger event notification
+ byte[] receivedBytes = new byte[numberOfReadBytes];
+ Buffer.BlockCopy(internalClient.Buffer, 0, receivedBytes, 0, numberOfReadBytes);
+ RaiseDatagramReceived(internalClient, receivedBytes);
+
+ // continue listening for tcp datagram packets
+ ContinueReadBuffer(internalClient, networkStream);
+ }
+ catch (InvalidOperationException ex)
+ {
+ Console.WriteLine("错误:" + ex.Message);
+ }
+ }
+
+ private void ContinueReadBuffer(TcpClientState internalClient, NetworkStream networkStream)
+ {
+ try
+ {
+ networkStream.BeginRead(internalClient.Buffer, 0, internalClient.Buffer.Length, HandleDatagramReceived, internalClient);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ }
+ }
+
+ #endregion Receive
+
+ #region Events
+
+ ///
+ /// 接收到数据报文事件
+ ///
+ public event EventHandler> DatagramReceived;
+
+ private void RaiseDatagramReceived(TcpClientState sender, byte[] datagram)
+ {
+ if (DatagramReceived != null)
+ {
+ DatagramReceived(this, new TcpDatagramReceivedEventArgs(sender, datagram));
+ }
+ }
+
+ ///
+ /// 与客户端的连接已建立事件
+ ///
+ public event EventHandler ClientConnected;
+
+ ///
+ /// 与客户端的连接已断开事件
+ ///
+ public event EventHandler ClientDisconnected;
+
+ private void RaiseClientConnected(TcpClient tcpClient)
+ {
+ if (ClientConnected != null)
+ {
+ ClientConnected(this, new TcpClientConnectedEventArgs(tcpClient));
+ }
+ }
+
+ private void RaiseClientDisconnected(TcpClient tcpClient)
+ {
+ if (ClientDisconnected != null)
+ {
+ ClientDisconnected(this, new TcpClientDisconnectedEventArgs(tcpClient));
+ }
+ }
+
+ #endregion Events
+
+ #region Send
+
+ private void GuardRunning()
+ {
+ if (!IsRunning)
+ throw new InvalidProgramException("This TCP server has not been started yet.");
+ }
+
+ ///
+ /// 发送报文至指定的客户端
+ ///
+ /// 客户端
+ /// 报文
+ public void Send(TcpClient tcpClient, byte[] datagram)
+ {
+ GuardRunning();
+
+ if (tcpClient == null)
+ throw new ArgumentNullException("tcpClient");
+
+ if (datagram == null)
+ throw new ArgumentNullException("datagram");
+
+ try
+ {
+ NetworkStream stream = tcpClient.GetStream();
+ if (stream.CanWrite)
+ {
+ stream.BeginWrite(datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient);
+ }
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ }
+ }
+
+ ///
+ /// 发送报文至指定的客户端
+ ///
+ /// 客户端
+ /// 报文
+ public void Send(TcpClient tcpClient, string datagram)
+ {
+ Send(tcpClient, Encoding.GetBytes(datagram));
+ }
+
+ ///
+ /// 发送报文至所有客户端
+ ///
+ /// 报文
+ public void SendToAll(byte[] datagram)
+ {
+ GuardRunning();
+
+ foreach (var client in _clients.Values)
+ {
+ Send(client.TcpClient, datagram);
+ }
+ }
+
+ public ICollection GetAllClient()
+ {
+ return _clients.Values;
+ }
+
+ ///
+ /// 发送报文至所有客户端
+ ///
+ /// 报文
+ public void SendToAll(string datagram)
+ {
+ GuardRunning();
+
+ SendToAll(Encoding.GetBytes(datagram));
+ }
+
+ private void HandleDatagramWritten(IAsyncResult ar)
+ {
+ try
+ {
+ ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ }
+ catch (InvalidOperationException ex)
+ {
+ Console.WriteLine("错误:" + ex.Message);
+ }
+ catch (IOException ex)
+ {
+ Console.WriteLine("错误:" + ex.Message);
+ }
+ }
+
+ ///
+ /// 发送报文至指定的客户端
+ ///
+ /// 客户端
+ /// 报文
+ public void SyncSend(TcpClient tcpClient, byte[] datagram)
+ {
+ GuardRunning();
+
+ if (tcpClient == null)
+ throw new ArgumentNullException("tcpClient");
+
+ if (datagram == null)
+ throw new ArgumentNullException("datagram");
+
+ try
+ {
+ NetworkStream stream = tcpClient.GetStream();
+ if (stream.CanWrite)
+ {
+ stream.Write(datagram, 0, datagram.Length);
+ }
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Console.WriteLine("对象注销错误:" + ex.Message);
+ }
+ }
+
+ ///
+ /// 发送报文至指定的客户端
+ ///
+ /// 客户端
+ /// 报文
+ public void SyncSend(TcpClient tcpClient, string datagram)
+ {
+ SyncSend(tcpClient, Encoding.GetBytes(datagram));
+ }
+
+ ///
+ /// 发送报文至所有客户端
+ ///
+ /// 报文
+ public void SyncSendToAll(byte[] datagram)
+ {
+ GuardRunning();
+
+ foreach (var client in _clients.Values)
+ {
+ SyncSend(client.TcpClient, datagram);
+ }
+ }
+
+ ///
+ /// 发送报文至所有客户端
+ ///
+ /// 报文
+ public void SyncSendToAll(string datagram)
+ {
+ GuardRunning();
+
+ SyncSendToAll(Encoding.GetBytes(datagram));
+ }
+
+ #endregion Send
+
+ #region IDisposable Members
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (disposing)
+ {
+ try
+ {
+ Stop();
+
+ if (_listener != null)
+ {
+ _listener = null;
+ }
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine("socket错误:" + ex.Message);
+ }
+ }
+
+ _disposed = true;
+ }
+ }
+
+ #endregion IDisposable Members
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs b/JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs
new file mode 100644
index 0000000..55fb289
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs
@@ -0,0 +1,49 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class CRC8
+{
+ ///
+ /// CRC8位校验表
+ ///
+ private static byte[] CRC8Table = new byte[] {
+ 0,94,188,226,97,63,221,131,194,156,126,32,163,253,31,65,
+ 157,195,33,127,252,162,64,30, 95,1,227,189,62,96,130,220,
+ 35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
+ 190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
+ 70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
+ 219,133,103,57,186,228,6,88,25,71,165,251,120,38,196,154,
+ 101,59,217,135,4,90,184,230,167,249,27,69,198,152,122,36,
+ 248,166,68,26,153,199,37,123,58,100,134,216,91,5,231,185,
+ 140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
+ 17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
+ 175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
+ 50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
+ 202,148,118,40,171,245,23,73,8,86,180,234,105,55,213,139,
+ 87,9,235,181,54,104,138,212,149,203, 41,119,244,170,72,22,
+ 233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
+ 116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53 };
+
+ public static byte CRC(byte[] buffer)
+ {
+ return CRC(buffer, 0, buffer.Length);
+ }
+
+ public static byte CRC(byte[] buffer, int off, int len)
+ {
+ byte crc = 0;
+ if (buffer == null)
+ {
+ throw new ArgumentNullException("buffer");
+ }
+ if (off < 0 || len < 0 || off + len > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ for (int i = off; i < len; i++)
+ {
+ crc = CRC8Table[crc ^ buffer[i]];
+ }
+ return crc;
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpClientConnectedEventArgs.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientConnectedEventArgs.cs
new file mode 100644
index 0000000..5445a6e
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientConnectedEventArgs.cs
@@ -0,0 +1,26 @@
+using System.Net.Sockets;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+///
+/// 与客户端的连接已建立事件参数
+///
+public class TcpClientConnectedEventArgs : EventArgs
+{
+ ///
+ /// 与客户端的连接已建立事件参数
+ ///
+ /// 客户端
+ public TcpClientConnectedEventArgs(TcpClient tcpClient)
+ {
+ if (tcpClient == null)
+ throw new ArgumentNullException("tcpClient");
+
+ TcpClient = tcpClient;
+ }
+
+ ///
+ /// 客户端
+ ///
+ public TcpClient TcpClient { get; private set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpClientDisconnectedEventArgs.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientDisconnectedEventArgs.cs
new file mode 100644
index 0000000..25f96e4
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientDisconnectedEventArgs.cs
@@ -0,0 +1,26 @@
+using System.Net.Sockets;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+///
+/// 与客户端的连接已断开事件参数
+///
+public class TcpClientDisconnectedEventArgs : EventArgs
+{
+ ///
+ /// 与客户端的连接已断开事件参数
+ ///
+ /// 客户端
+ public TcpClientDisconnectedEventArgs(TcpClient tcpClient)
+ {
+ if (tcpClient == null)
+ throw new ArgumentNullException("tcpClient");
+
+ TcpClient = tcpClient;
+ }
+
+ ///
+ /// 客户端
+ ///
+ public TcpClient TcpClient { get; private set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs
new file mode 100644
index 0000000..b9b5fe7
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs
@@ -0,0 +1,47 @@
+using System.Net.Sockets;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class TcpClientState
+{
+ ///
+ /// Constructor for a new Client
+ ///
+ /// The TCP client
+ /// The byte array buffer
+ public TcpClientState(TcpClient tcpClient, byte[] buffer)
+ {
+ if (tcpClient == null) throw new ArgumentNullException("tcpClient");
+ if (buffer == null) throw new ArgumentNullException("buffer");
+
+ TcpClient = tcpClient;
+ Buffer = buffer;
+ temp = string.Empty;
+ }
+
+ ///
+ /// Gets the TCP Client
+ ///
+ public TcpClient TcpClient { get; private set; }
+
+ ///
+ /// Gets the Buffer.
+ ///
+ public byte[] Buffer { get; private set; }
+
+ ///
+ /// TCP接收到但未处理的数据
+ ///
+ public string temp { get; set; }
+
+ ///
+ /// Gets the network stream
+ ///
+ public NetworkStream NetworkStream
+ {
+ get
+ {
+ return TcpClient.GetStream();
+ }
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs
new file mode 100644
index 0000000..c2ef7bd
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs
@@ -0,0 +1,29 @@
+namespace JiLinApp.Docking.VibrateAlarm;
+
+///
+/// 接收到数据报文事件参数
+///
+/// 报文类型
+public class TcpDatagramReceivedEventArgs : EventArgs
+{
+ ///
+ /// 接收到数据报文事件参数
+ ///
+ /// 客户端
+ /// 报文
+ public TcpDatagramReceivedEventArgs(TcpClientState tcpClient, T datagram)
+ {
+ TcpClient = tcpClient;
+ Datagram = datagram;
+ }
+
+ ///
+ /// 客户端
+ ///
+ public TcpClientState TcpClient { get; private set; }
+
+ ///
+ /// 报文
+ ///
+ public T Datagram { get; private set; }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs
new file mode 100644
index 0000000..3a82d9e
--- /dev/null
+++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs
@@ -0,0 +1,685 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using Timer = System.Timers.Timer;
+
+namespace JiLinApp.Docking.VibrateAlarm;
+
+public class TcpManager
+{
+ #region Fields
+
+ private JsonSerializerSettings jSetting { get; } = new();
+
+ private AsyncTcpServer server { get; set; } = null;
+
+ private Timer stateSpanTimer { get; } = new();
+
+ private Timer heartTimer { get; } = new();
+
+ private List list { get; } = new();
+
+ #endregion fields
+
+ public TcpManager()
+ {
+ jSetting.NullValueHandling = NullValueHandling.Ignore;
+ jSetting.DefaultValueHandling = DefaultValueHandling.Ignore;
+ }
+
+ #region BaseMethod
+
+ public void StartServer(TcpManagerConfig config)
+ {
+ if (IsRunning()) return;
+ IPAddress address = IPAddress.Any;
+ _ = IPAddress.TryParse(config.ServerIp, out address);
+
+ server = new AsyncTcpServer(address, config.ServerPort);
+ server.ClientConnected += server_ClientConnected;
+ server.ClientDisconnected += server_ClientDisconnected;
+ server.DatagramReceived += server_DatagramReceived;
+ server.Start();
+
+ heartTimer.Close();
+ heartTimer.Interval = 1000 * config.DeviceHeartKeep;
+ heartTimer.Elapsed += HeartTimer_Elapsed;
+ heartTimer.Enabled = true;
+ heartTimer.Start();
+ }
+
+ public void StopServer()
+ {
+ heartTimer.Enabled = false;
+ if (IsRunning())
+ {
+ server.Stop();
+ server = null;
+ }
+ }
+
+ public bool IsRunning()
+ {
+ return server != null && server.IsRunning;
+ }
+
+ public bool StartScan(ref string error)
+ {
+ if (server == null)
+ {
+ error = "服务未创建";
+ return false;
+ }
+ if (!server.IsRunning)
+ {
+ error = "服务未运行";
+ return false;
+ }
+ stateSpanTimer.Enabled = true;
+ return true;
+ }
+
+ public void StopScan()
+ {
+ stateSpanTimer.Enabled = false;
+ }
+
+ #endregion BaseMethod
+
+ private void StateSpanTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ string error = "";
+ for (int i = 0; i < list.Count; i++)
+ {
+ sendState(list[i], ref error);
+ }
+ }
+
+ private void HeartTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ string error = "";
+ for (int i = 0; i < list.Count; i++)
+ {
+ sendHeart(list[i], ref error);
+ }
+ }
+
+ private ClientMessage GetClientMessage(TcpClient client)
+ {
+ string clientIP = client.Client.RemoteEndPoint.ToString().Split(':')[0];
+ for (int i = 0; i < list.Count; i++)
+ {
+ if (list[i].IP == clientIP)
+ {
+ return list[i];
+ }
+ }
+ return null;
+ }
+
+ private ClientMessage GetClientMessageIP(string clientIP)
+ {
+ for (int i = 0; i < list.Count; i++)
+ {
+ if (list[i].IP == clientIP)
+ {
+ return list[i];
+ }
+ }
+ return null;
+ }
+
+ private ClientMessage GetClientMessageDeviceID(int deviceId)
+ {
+ for (int i = 0; i < list.Count; i++)
+ {
+ if (list[i].host != null && list[i].host.id == deviceId)
+ {
+ return list[i];
+ }
+ }
+ return null;
+ }
+
+ public delegate void TCPSectionAlarmOnEvent(TcpAlarmHostMessage msg);
+
+ public event TCPSectionAlarmOnEvent OnTcpSectionAlarmOn;
+
+ public delegate void TCPSectionStateChangeEvent(SectionState state);
+
+ public event TCPSectionStateChangeEvent OnTcpSectionStateChange;
+
+ public delegate void TCPDeviceMessageEvent(TcpAlarmHostTable host, string msg);
+
+ public event TCPDeviceMessageEvent OnTcpDeviceMessage;
+
+ public delegate void TCPSectionMessageEvent(TcpAlarmHostTable host, TcpSectionTable section, string msg);
+
+ public event TCPSectionMessageEvent OnTcpSectionMessage;
+
+ private void server_DatagramReceived(object sender, TcpDatagramReceivedEventArgs e)
+ {
+ string clientIP = e.TcpClient.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
+ ClientMessage client = GetClientMessage(e.TcpClient.TcpClient);
+ if (client != null)
+ {
+ AnalysisClientMessage(client, e.Datagram);
+ }
+ }
+
+ public void TestAlarm(string devideId, string channel)
+ {
+ ClientMessage message = new ClientMessage();
+ message.client = new TcpClient("127.0.0.1", 5080);
+
+ list.Add(message);
+ byte[] bytes1 = BitConverter.GetBytes(int.Parse(devideId));
+ byte[] bytes2 = BitConverter.GetBytes(int.Parse(channel));
+ byte[] bytes = new byte[24]{
+ 0xAA,0xAA,bytes1[0],bytes1[1],
+ 127,0,0,1,
+ 0x00,0x00,127,0,
+ 0,1,0x00,0x00,
+ 1,0x14,0x04,bytes2[0],
+ bytes2[1],0x02,0x00,0x00
+ };
+ AnalysisClientMessage(message, bytes);
+ }
+
+ private string ToHexString(byte[] bytes)
+ {
+ string hexString = string.Empty;
+
+ if (bytes != null)
+ {
+ StringBuilder strB = new StringBuilder();
+
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ strB.Append(bytes[i].ToString("X2") + " ");
+ }
+
+ hexString = strB.ToString();
+ }
+ return hexString;
+ }
+
+ private void AnalysisClientMessage(ClientMessage client, byte[] bytes)
+ {
+ client.list.AddRange(bytes);
+
+ List msglist = client.getMessageList();
+ if (msglist != null && msglist.Count > 0)
+ {
+ for (int i = 0; i < msglist.Count; i++)
+ {
+ Console.WriteLine(client.IP + " 收到数据:" + ToHexString(msglist[i]));
+ DataMessage mm = new DataMessage();
+ mm.decode(msglist[i]);
+ switch (mm.functionNum)
+ {
+ case 0x00:
+ Console.WriteLine(client.IP + " 登录");
+ if (client.host == null || client.host.id != mm.deviceID)
+ {
+ //string error = "";
+ //JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "id=" + mm.deviceID, ref error);
+ JArray arr = new();
+ if (arr != null && arr.Count > 0)
+ {
+ client.host = JsonConvert.DeserializeObject(arr[0].ToString(), jSetting);
+ client.host.ip = mm.sendIP;
+ client.host.port = mm.sendPort.ToString();
+ }
+ }
+ if (OnTcpDeviceMessage != null)
+ {
+ if (client.host != null)
+ {
+ OnTcpDeviceMessage(client.host, "报警主机登录");
+ }
+ else
+ {
+ OnTcpDeviceMessage(new TcpAlarmHostTable() { id = mm.deviceID, ip = mm.sendIP, port = mm.sendPort.ToString(), name = "未知设备" }, "报警主机登录");
+ }
+ }
+ break;
+
+ case 0x01:
+ Console.WriteLine(client.IP + " 心跳");
+ break;
+
+ case 0x12:
+ Console.WriteLine(client.IP + "传感器地址设置响应");
+ SetDataRequest(mm, 0x02);
+ break;
+
+ case 0x13:
+ Console.WriteLine(client.IP + "传感器模式设置响应");
+ SetDataRequest(mm, 0x03);
+ break;
+
+ case 0x14:
+ Console.WriteLine(client.IP + "传感器状态响应");
+ int channel = 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;
+ TcpAlarmHostTable host = new() { id = mm.deviceID, ip = mm.sendIP, port = mm.sendPort.ToString(), name = "未知设备" };
+ ProcessOnlineEvent(client, host, mm, channel, online);
+ ProcessAlarmEvent(client, host, mm, channel, alarm);
+ UpdateOnLineAlarm(client, host, channel, online, alarm);
+ SetDataRequest(mm, 0x04);
+ break;
+
+ case 0x15:
+ Console.WriteLine(client.IP + "传感器复位响应");
+ SetDataRequest(mm, 0x05);
+ break;
+ }
+ }
+ }
+ }
+
+ private void ProcessOnlineEvent(ClientMessage client, TcpAlarmHostTable host, DataMessage mm, int channel, int online)
+ {
+ if (client.sectioTable.ContainsKey(channel))
+ {
+ SectionState oldState = client.sectioTable[channel] as SectionState;
+ if (oldState.online == online) return;
+ }
+ TcpAlarmHostTable host1 = client.host == null ? host : client.host;
+ string error = "";
+ TcpSectionTable section = new TcpSectionTable() { deviceID = host.id, name = "未知传感器", channel = channel.ToString() };
+ //JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID=" + mm.deviceID + "/channel='" + channel + "'", ref error);
+ JArray arr = new();
+ if (arr != null && arr.Count > 0) section = JsonConvert.DeserializeObject(arr[0].ToString(), jSetting);
+ if (OnTcpSectionMessage != null)
+ {
+ OnTcpSectionMessage(host1, section, online == 0 ? "传感器上线" : "传感器离线");
+ }
+ }
+
+ private void ProcessAlarmEvent(ClientMessage client, TcpAlarmHostTable host, DataMessage mm, int channel, int alarm)
+ {
+ if (client.sectioTable.ContainsKey(channel))
+ {
+ SectionState oldState = client.sectioTable[channel] as SectionState;
+ if (oldState.alarm == alarm) return;
+ }
+ TcpAlarmHostTable host1 = client.host == null ? host : client.host;
+ if (alarm == 1)
+ {
+ ProcessAlarm(host1.id, channel, alarm);
+ }
+ }
+
+ private void UpdateOnLineAlarm(ClientMessage client, TcpAlarmHostTable host, int channel, int online, int alarm)
+ {
+ if (client.sectioTable.ContainsKey(channel))
+ {
+ SectionState oldState = client.sectioTable[channel] as SectionState;
+ oldState.online = online;
+ oldState.alarm = alarm;
+ if (OnTcpSectionStateChange != null)
+ {
+ OnTcpSectionStateChange(oldState);
+ }
+ }
+ else
+ {
+ TcpAlarmHostTable host1 = client.host == null ? host : client.host;
+ SectionState state = new SectionState(host1.id, channel, online, alarm);
+ client.sectioTable[channel] = state;
+ if (OnTcpSectionStateChange != null)
+ {
+ OnTcpSectionStateChange(state);
+ }
+ }
+ }
+
+ private void ProcessAlarm(int deviceId, int channel, int alarmId)
+ {
+ TcpAlarmHostMessage alarm = new()
+ {
+ AlarmId = Convert.ToString(alarmId),
+ AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+ DeviceID = deviceId,
+ ChannelNum = channel.ToString()
+ };
+ ProcessAlarmDB(alarm);
+ }
+
+ //处理报警事件
+ private void ProcessAlarmDB(TcpAlarmHostMessage msg)
+ {
+ if (OnTcpSectionAlarmOn != null) OnTcpSectionAlarmOn(msg);
+ }
+
+ public void SetDataRequest(DataMessage msg, byte functionNum)
+ {
+ lock (this)
+ {
+ for (int i = 0; i < reqlist.Count; i++)
+ {
+ if (reqlist[i].request.functionNum == functionNum && reqlist[i].request.frameNum == msg.frameNum)
+ {
+ reqlist[i].responce = msg;
+ }
+ }
+ }
+ }
+
+ public bool SendMessage(string IP, byte[] bytes, ref string error)
+ {
+ if (server == null)
+ {
+ error = "服务未创建";
+ return false;
+ }
+ if (!server.IsRunning)
+ {
+ error = "服务未运行";
+ return false;
+ }
+ ClientMessage client = GetClientMessageIP(IP);
+ if (client != null)
+ {
+ server.Send(client.client, bytes);
+ return true;
+ }
+ else
+ {
+ error = "主机未连接";
+ return false;
+ }
+ }
+
+ private List reqlist = new List();
+ private byte frameNumber = 0;
+
+ public bool sendRequest(ref DataRequest request, ref string error)
+ {
+ if (request.request == null)
+ {
+ error = "请求信息未填写";
+ return false;
+ }
+ //int waitTime = int.Parse(DBCenter.center.GetConfig("WW_TCP_DeviceTimeOut")) * 10;
+ int waitTime = 100;
+ request.request.frameNum = frameNumber;
+ frameNumber++;
+ bool send = SendMessage(request.request.receiveIP, request.request.encode(), ref error);
+ if (!send) return false;
+ reqlist.Add(request);
+ for (int i = 0; i < waitTime; i++)
+ {
+ if (request.responce != null)
+ {
+ reqlist.Remove(request);
+ return true;
+ }
+ System.Threading.Thread.Sleep(100);
+ }
+ return false;
+ }
+
+ public bool sendNoRequest(DataMessage msg, ref string error)
+ {
+ msg.frameNum = frameNumber;
+ frameNumber++;
+ return SendMessage(msg.receiveIP, msg.encode(), ref error);
+ }
+
+ public bool sendHeart(ClientMessage client, ref string error)
+ {
+ if (client.host == null)
+ {
+ error = "报警主机信息缺失";
+ return false;
+ }
+ DataMessage msg = getSendMessageHead(client.host.id, client, 0x01, 1);
+ msg.data = new byte[] { 0xFF };
+
+ return sendNoRequest(msg, ref error);
+ }
+
+ public bool SetSectionAddress(int deviceId, string channel_str, int address, ref string error)
+ {
+ ClientMessage client = GetClientMessageDeviceID(deviceId);
+ if (client == null)
+ {
+ error = "此主机号不在线";
+ return false;
+ }
+ DataMessage msg = getSendMessageHead(deviceId, client, 0x02, 4);
+ int channel = int.Parse(channel_str);
+ msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (byte)(address % 256), (byte)(address / 256) };
+ DataRequest request = new DataRequest();
+ request.request = msg;
+ bool result = sendRequest(ref request, ref error);
+ if (result)
+ {
+ JObject conlist = new JObject();
+ conlist.Add("deviceID", deviceId);
+ conlist.Add("channel", channel_str);
+ JObject valuelist = new JObject();
+ valuelist.Add("channel", address.ToString());
+ //DBCenter.center.UpdateResult("table_TCPSection", valuelist, conlist, ref error);
+ }
+ return result;
+ }
+
+ public bool SetSectionMode(int deviceId, string channel_str, byte mode, byte sensitivity, ref string error)
+ {
+ ClientMessage client = GetClientMessageDeviceID(deviceId);
+ if (client == null)
+ {
+ error = "此主机号不在线";
+ return false;
+ }
+ DataMessage msg = getSendMessageHead(deviceId, client, 0x03, 3);
+ int channel = int.Parse(channel_str);
+ msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (byte)(mode + sensitivity * 8) };
+ DataRequest request = new DataRequest();
+ request.request = msg;
+ bool result = sendRequest(ref request, ref error);
+ if (result)
+ {
+ JObject conlist = new JObject();
+ conlist.Add("deviceID", deviceId);
+ conlist.Add("channel", channel_str);
+ JObject valuelist = new JObject();
+ valuelist.Add("mode", mode.ToString());
+ valuelist.Add("sensitivity", sensitivity.ToString());
+ //DBCenter.center.UpdateResult("table_TCPSection", valuelist, conlist, ref error);
+ }
+ return result;
+ }
+
+ public bool SetSectionReset(int deviceId, string channel_str, ref string error)
+ {
+ ClientMessage client = GetClientMessageDeviceID(deviceId);
+ if (client == null)
+ {
+ error = "此主机号不在线";
+ return false;
+ }
+ DataMessage msg = getSendMessageHead(deviceId, client, 0x05, 2);
+ int channel = int.Parse(channel_str);
+ msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
+ DataRequest request = new DataRequest();
+ request.request = msg;
+ return sendRequest(ref request, ref error);
+ }
+
+ public SectionState SetSectionCheck(int deviceId, string channel_str, ref string error)
+ {
+ ClientMessage client = GetClientMessageDeviceID(deviceId);
+ if (client == null)
+ {
+ error = "此主机号不在线";
+ return null;
+ }
+ DataMessage msg = getSendMessageHead(deviceId, client, 0x04, 2);
+ int channel = int.Parse(channel_str);
+ msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
+ DataRequest request = new DataRequest();
+ request.request = msg;
+ bool result = sendRequest(ref request, ref error);
+ if (result)
+ {
+ int channel2 = request.responce.data[0] + request.responce.data[1] * 256;
+ int state2 = request.responce.data[2] + request.responce.data[3] * 256;
+ return new SectionState(deviceId, channel2, state2);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public List SetDeviceCheck(int deviceId, ref string error)
+ {
+ List list = new List();
+ //JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID=" + deviceId, ref error);
+ JArray arr = new();
+ if (arr != null && arr.Count > 0)
+ {
+ for (int i = 0; i < arr.Count; i++)
+ {
+ string channel = arr[i]["channel"].ToString();
+ SectionState state = SetSectionCheck(deviceId, channel, ref error);
+ if (state == null)
+ {
+ state = new SectionState(deviceId, int.Parse(channel), -1, -1);
+ }
+ list.Add(state);
+ }
+ }
+ else
+ {
+ error = "数据库中没有防区信息";
+ }
+ return list;
+ }
+
+ public List SetAllCheck(ref string error)
+ {
+ List list = new List();
+ //JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "", ref error);
+ JArray arr = new();
+ if (arr != null && arr.Count > 0)
+ {
+ for (int i = 0; i < arr.Count; i++)
+ {
+ int deviceId = int.Parse(arr[i]["id"].ToString());
+ list.AddRange(SetDeviceCheck(deviceId, ref error));
+ }
+ }
+ return list;
+ }
+
+ private DataMessage getSendMessageHead(int deviceId, ClientMessage client, byte fun_num, byte datalen)
+ {
+ //DataMessage msg = new DataMessage();
+ //msg.deviceID = deviceId;
+ //msg.sendIP = DBCenter.center.GetConfig("WW_TCP_ServeIP");
+ //msg.sendPort = int.Parse(DBCenter.center.GetConfig("WW_TCP_ServePort"));
+ //msg.receiveIP = client.IP;
+ //msg.receivePort = int.Parse(client.Port);
+ //msg.functionNum = fun_num;
+ //msg.dataLen = datalen;
+ //return msg;
+ return null;
+ }
+
+ public void sendState(ClientMessage client, ref string error)
+ {
+ //if (client.host == null)
+ //{
+ // error = "报警主机信息缺失";
+ // return;
+ //}
+ //JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID='" + client.host.id + "'", ref error);
+ //if (arr != null && arr.Count > 0)
+ //{
+ // for (int i = 0; i < arr.Count; i++)
+ // {
+ // DataMessage msg = getSendMessageHead(client.host.id, client, 0x04, 2);
+ // int channel = int.Parse(arr[i]["channel"].ToString());
+ // msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
+ // sendNoRequest(msg, ref error);
+ // }
+ //}
+ }
+
+ private void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
+ {
+ string clientIP = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
+ Console.WriteLine(clientIP + "下线");
+ ClientMessage client = GetClientMessage(e.TcpClient);
+ if (client != null)
+ {
+ list.Remove(client);
+ if (OnTcpDeviceMessage != null)
+ {
+ if (client.host != null)
+ {
+ OnTcpDeviceMessage(client.host, "报警主机掉线");
+ }
+ else
+ {
+ OnTcpDeviceMessage(new TcpAlarmHostTable() { id = -1, ip = clientIP, port = client.Port, name = "未知设备" }, "报警主机掉线");
+ }
+ }
+ }
+ }
+
+ private void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
+ {
+ string error = "";
+ string clientIP = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
+ string port = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[1];
+ Console.WriteLine(clientIP + "上线");
+ ClientMessage client = GetClientMessage(e.TcpClient);
+ if (client == null)
+ {
+ ClientMessage msg = new ClientMessage();
+ msg.client = e.TcpClient;
+ //JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "IP='" + clientIP + "'", ref error);
+ JArray arr = new();
+ if (arr != null && arr.Count > 0)
+ {
+ msg.host = JsonConvert.DeserializeObject(arr[0].ToString(), jSetting);
+ }
+ list.Add(msg);
+ if (OnTcpDeviceMessage != null)
+ {
+ if (msg.host != null)
+ {
+ OnTcpDeviceMessage(msg.host, "报警主机上线");
+ }
+ else
+ {
+ OnTcpDeviceMessage(new TcpAlarmHostTable() { id = -1, ip = clientIP, port = client.Port, name = "未知设备" }, "报警主机上线");
+ }
+ }
+ }
+ }
+
+ public List getOnlineState(int deviceId)
+ {
+ ClientMessage msg = GetClientMessageDeviceID(deviceId);
+ if (msg != null)
+ {
+ return msg.sectioTable.Values as List;
+ }
+ else
+ {
+ return new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/JiLinApp.Docking/config/alarmcode.json b/JiLinApp.Docking/config/alarmcode.json
new file mode 100644
index 0000000..9e6b6a2
--- /dev/null
+++ b/JiLinApp.Docking/config/alarmcode.json
@@ -0,0 +1,2198 @@
+[
+ {
+ "Id": "1000",
+ "Level": "0",
+ "Type": "错误",
+ "Content": "接收到未定义的代码"
+ },
+ {
+ "Id": "1100",
+ "Level": "1",
+ "Type": "紧急",
+ "Content": "个人救护报警"
+ },
+ {
+ "Id": "1101",
+ "Level": "1",
+ "Type": "紧急",
+ "Content": "个人救护报警,紧急按钮"
+ },
+ {
+ "Id": "1102",
+ "Level": "1",
+ "Type": "紧急",
+ "Content": "报到失败"
+ },
+ {
+ "Id": "1103",
+ "Level": "1",
+ "Type": "紧急",
+ "Content": "紧急报警"
+ },
+ {
+ "Id": "1104",
+ "Level": "1",
+ "Type": "紧急",
+ "Content": "紧急报警"
+ },
+ {
+ "Id": "1110",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "火警报警"
+ },
+ {
+ "Id": "1111",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "烟感探头"
+ },
+ {
+ "Id": "1112",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "燃烧"
+ },
+ {
+ "Id": "1113",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "消防水流"
+ },
+ {
+ "Id": "1114",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "热感探头"
+ },
+ {
+ "Id": "1115",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "火警手动报警"
+ },
+ {
+ "Id": "1117",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "火焰探头"
+ },
+ {
+ "Id": "1118",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "接近警报"
+ },
+ {
+ "Id": "1119",
+ "Level": "1",
+ "Type": "火警",
+ "Content": "煤气泄漏"
+ },
+ {
+ "Id": "1120",
+ "Level": "1",
+ "Type": "劫盗",
+ "Content": "劫盗"
+ },
+ {
+ "Id": "1121",
+ "Level": "1",
+ "Type": "劫盗",
+ "Content": "挟持"
+ },
+ {
+ "Id": "1122",
+ "Level": "1",
+ "Type": "劫盗",
+ "Content": "无声劫盗"
+ },
+ {
+ "Id": "1123",
+ "Level": "1",
+ "Type": "劫盗",
+ "Content": "有声劫盗"
+ },
+ {
+ "Id": "1124",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "异地劫持"
+ },
+ {
+ "Id": "1130",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "窃盗"
+ },
+ {
+ "Id": "1131",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "周界窃盗"
+ },
+ {
+ "Id": "1132",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "内部窃盗"
+ },
+ {
+ "Id": "1133",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "24小时窃盗"
+ },
+ {
+ "Id": "1134",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "出/入窃盗"
+ },
+ {
+ "Id": "1135",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "日/夜防区"
+ },
+ {
+ "Id": "1136",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "室外窃盗"
+ },
+ {
+ "Id": "1137",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "拆动报警"
+ },
+ {
+ "Id": "1138",
+ "Level": "1",
+ "Type": "窃盗",
+ "Content": "接近报警"
+ },
+ {
+ "Id": "1140",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "一般报警"
+ },
+ {
+ "Id": "1141",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "总线开路"
+ },
+ {
+ "Id": "1142",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "总线短路"
+ },
+ {
+ "Id": "1143",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "扩充器故障"
+ },
+ {
+ "Id": "1144",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "探头被拆动"
+ },
+ {
+ "Id": "1145",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "扩充器被拆"
+ },
+ {
+ "Id": "1150",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "24小时非盗窃报警"
+ },
+ {
+ "Id": "1156",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "日间防区"
+ },
+ {
+ "Id": "1158",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "温度过高"
+ },
+ {
+ "Id": "1159",
+ "Level": "1",
+ "Type": "警报",
+ "Content": "温度过低"
+ },
+ {
+ "Id": "1161",
+ "Level": "1",
+ "Type": "周界窃盗",
+ "Content": "攀爬报警"
+ },
+ {
+ "Id": "1170",
+ "Level": "1",
+ "Type": "故障",
+ "Content": "用户离线"
+ },
+ {
+ "Id": "1180",
+ "Level": "1",
+ "Type": "故障",
+ "Content": "GPRS设备断线"
+ },
+ {
+ "Id": "1181",
+ "Level": "1",
+ "Type": "周界窃盗",
+ "Content": "张力围栏报警"
+ },
+ {
+ "Id": "1190",
+ "Level": "1",
+ "Type": "周界窃盗",
+ "Content": "脉冲围栏断路报警"
+ },
+ {
+ "Id": "1191",
+ "Level": "1",
+ "Type": "周界窃盗",
+ "Content": "脉冲围栏短路报警"
+ },
+ {
+ "Id": "1192",
+ "Level": "1",
+ "Type": "周界窃盗",
+ "Content": "振动光纤断光"
+ },
+ {
+ "Id": "1193",
+ "Level": "1",
+ "Type": "周界窃盗",
+ "Content": "振动光纤触网"
+ },
+ {
+ "Id": "1200",
+ "Level": "2",
+ "Type": "监控",
+ "Content": "火警监视"
+ },
+ {
+ "Id": "1201",
+ "Level": "2",
+ "Type": "监控",
+ "Content": "水压过低"
+ },
+ {
+ "Id": "1202",
+ "Level": "2",
+ "Type": "监控",
+ "Content": "二氧化碳过低"
+ },
+ {
+ "Id": "1203",
+ "Level": "2",
+ "Type": "监控",
+ "Content": "阀门感应"
+ },
+ {
+ "Id": "1300",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "系统故障"
+ },
+ {
+ "Id": "1301",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "无交流"
+ },
+ {
+ "Id": "1302",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "电池低压"
+ },
+ {
+ "Id": "1303",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "RAM校验和故障"
+ },
+ {
+ "Id": "1304",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "ROM校验和故障"
+ },
+ {
+ "Id": "1305",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "系统重新设定"
+ },
+ {
+ "Id": "1306",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "编程改动"
+ },
+ {
+ "Id": "1307",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "自检故障"
+ },
+ {
+ "Id": "1308",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "主机停机使用"
+ },
+ {
+ "Id": "1309",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "电池测试故障"
+ },
+ {
+ "Id": "130A",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "系统复位"
+ },
+ {
+ "Id": "1310",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "接地故障"
+ },
+ {
+ "Id": "1320",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "警号/继电器"
+ },
+ {
+ "Id": "1321",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "警铃#1"
+ },
+ {
+ "Id": "1322",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "警铃#2"
+ },
+ {
+ "Id": "1323",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "警报继电器"
+ },
+ {
+ "Id": "1324",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "故障继电器"
+ },
+ {
+ "Id": "1325",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "逆转继电器"
+ },
+ {
+ "Id": "132A",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "警铃保险管烧坏"
+ },
+ {
+ "Id": "1330",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "系统周边"
+ },
+ {
+ "Id": "1331",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "总线开路"
+ },
+ {
+ "Id": "1332",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "总线短路"
+ },
+ {
+ "Id": "1333",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "防区掉线"
+ },
+ {
+ "Id": "1334",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "单元控制器掉线楼道机"
+ },
+ {
+ "Id": "1335",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "打印机无纸"
+ },
+ {
+ "Id": "1339",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "振动光纤断光"
+ },
+ {
+ "Id": "1340",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "网络设备离线"
+ },
+ {
+ "Id": "1336",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "打印机故障"
+ },
+ {
+ "Id": "1350",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "通讯故障"
+ },
+ {
+ "Id": "1351",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "电话线1故障"
+ },
+ {
+ "Id": "1352",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "电话线2故障"
+ },
+ {
+ "Id": "1353",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "长距离无线发射器故障"
+ },
+ {
+ "Id": "1354",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "通讯失败"
+ },
+ {
+ "Id": "1355",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "失去长距无线监控"
+ },
+ {
+ "Id": "1356",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "失去长距无线中央监控"
+ },
+ {
+ "Id": "1357",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "无线干扰"
+ },
+ {
+ "Id": "1360",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "防区故障"
+ },
+ {
+ "Id": "1361",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "防拆故障"
+ },
+ {
+ "Id": "1362",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "充电故障"
+ },
+ {
+ "Id": "1363",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "模块未准备就绪"
+ },
+ {
+ "Id": "1370",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "保护回路"
+ },
+ {
+ "Id": "1371",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "保护回路开路"
+ },
+ {
+ "Id": "1372",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "保护回路短路"
+ },
+ {
+ "Id": "1373",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "火警回路故障"
+ },
+ {
+ "Id": "137A",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "回路故障"
+ },
+ {
+ "Id": "1380",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "感应器故障"
+ },
+ {
+ "Id": "1381",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "无线监控故障"
+ },
+ {
+ "Id": "1382",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "总线监控故障"
+ },
+ {
+ "Id": "1383",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "感应器被拆"
+ },
+ {
+ "Id": "1384",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "无线感应器电池过低"
+ },
+ {
+ "Id": "1393",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "电话故障"
+ },
+ {
+ "Id": "1394",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "卡故障"
+ },
+ {
+ "Id": "13A0",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "请求服务"
+ },
+ {
+ "Id": "13A1",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "时间重设"
+ },
+ {
+ "Id": "13A2",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "5(12)伏电源故障"
+ },
+ {
+ "Id": "13A3",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "电话线故障"
+ },
+ {
+ "Id": "13A4",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "卡故障"
+ },
+ {
+ "Id": "13A5",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "失去电池"
+ },
+ {
+ "Id": "13A6",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "进入编程模式"
+ },
+ {
+ "Id": "13A7",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "未知故障"
+ },
+ {
+ "Id": "13A8",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "无效报告"
+ },
+ {
+ "Id": "13B0",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "用户密码更改"
+ },
+ {
+ "Id": "13B1",
+ "Level": "3",
+ "Type": "故障",
+ "Content": "错误信息"
+ },
+ {
+ "Id": "1400",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "撤防"
+ },
+ {
+ "Id": "1401",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "用户撤防"
+ },
+ {
+ "Id": "1402",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "集体撤防"
+ },
+ {
+ "Id": "1403",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "自动撤防"
+ },
+ {
+ "Id": "1404",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "过迟撤防"
+ },
+ {
+ "Id": "1405",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "不适用"
+ },
+ {
+ "Id": "1406",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "取消"
+ },
+ {
+ "Id": "1407",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "遥控撤防"
+ },
+ {
+ "Id": "1408",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "快速撤防"
+ },
+ {
+ "Id": "1409",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "开关撤防"
+ },
+ {
+ "Id": "140A",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "部分撤防"
+ },
+ {
+ "Id": "140B",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "周边撤防"
+ },
+ {
+ "Id": "1411",
+ "Level": "4",
+ "Type": "遥控",
+ "Content": "要求回电"
+ },
+ {
+ "Id": "1412",
+ "Level": "4",
+ "Type": "遥控",
+ "Content": "遥控编程成功"
+ },
+ {
+ "Id": "1413",
+ "Level": "4",
+ "Type": "遥控",
+ "Content": "遥控不成功"
+ },
+ {
+ "Id": "1414",
+ "Level": "4",
+ "Type": "遥控",
+ "Content": "关闭系统"
+ },
+ {
+ "Id": "1415",
+ "Level": "4",
+ "Type": "遥控",
+ "Content": "关闭通讯"
+ },
+ {
+ "Id": "1416",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "撤防操作"
+ },
+ {
+ "Id": "1417",
+ "Level": "4",
+ "Type": "撤防",
+ "Content": "防区撤防"
+ },
+ {
+ "Id": "1421",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "拒绝出入-用户"
+ },
+ {
+ "Id": "1422",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "成功出入-用户"
+ },
+ {
+ "Id": "1441",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "在家布防"
+ },
+ {
+ "Id": "1450",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "非正常时段撤防"
+ },
+ {
+ "Id": "1451",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "过早撤防"
+ },
+ {
+ "Id": "1452",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "过迟撤防"
+ },
+ {
+ "Id": "1453",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "撤防失败"
+ },
+ {
+ "Id": "1454",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "布防失败"
+ },
+ {
+ "Id": "1455",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "自动布防失败"
+ },
+ {
+ "Id": "1456",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "部分布防"
+ },
+ {
+ "Id": "1457",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "外出错误"
+ },
+ {
+ "Id": "1458",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "操作员在现场"
+ },
+ {
+ "Id": "1459",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "最近布防"
+ },
+ {
+ "Id": "1480",
+ "Level": "4",
+ "Type": "出入",
+ "Content": "关警号"
+ },
+ {
+ "Id": "1520",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "停用警号/继电器"
+ },
+ {
+ "Id": "1521",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "警铃1停用"
+ },
+ {
+ "Id": "1522",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "警铃2停用"
+ },
+ {
+ "Id": "1523",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "停用警报继电器"
+ },
+ {
+ "Id": "1524",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "停用故障继电器"
+ },
+ {
+ "Id": "1525",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "逆反继电器"
+ },
+ {
+ "Id": "1530",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "停用系统周边"
+ },
+ {
+ "Id": "1540",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "停用系统周边"
+ },
+ {
+ "Id": "1551",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "通讯器停用"
+ },
+ {
+ "Id": "1552",
+ "Level": "5",
+ "Type": "停用",
+ "Content": "无线发射器停用"
+ },
+ {
+ "Id": "1570",
+ "Level": "5",
+ "Type": "旁路",
+ "Content": "防区旁路"
+ },
+ {
+ "Id": "1571",
+ "Level": "5",
+ "Type": "旁路",
+ "Content": "火警旁路"
+ },
+ {
+ "Id": "1572",
+ "Level": "5",
+ "Type": "旁路",
+ "Content": "24小时防区旁路"
+ },
+ {
+ "Id": "1573",
+ "Level": "5",
+ "Type": "旁路",
+ "Content": "窃盗旁路"
+ },
+ {
+ "Id": "1574",
+ "Level": "5",
+ "Type": "旁路",
+ "Content": "集体旁路"
+ },
+ {
+ "Id": "1580",
+ "Level": "5",
+ "Type": "旁路",
+ "Content": "旁路操作"
+ },
+ {
+ "Id": "1601",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "手动测试"
+ },
+ {
+ "Id": "1602",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "定期测试"
+ },
+ {
+ "Id": "1603",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "定期无线发射器测试"
+ },
+ {
+ "Id": "1604",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "火警测试"
+ },
+ {
+ "Id": "1605",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "状态报告"
+ },
+ {
+ "Id": "1606",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "监听"
+ },
+ {
+ "Id": "1607",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "不行测试模式"
+ },
+ {
+ "Id": "1609",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "图像传输"
+ },
+ {
+ "Id": "1630",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "改动时间表"
+ },
+ {
+ "Id": "1631",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "改动例外时间表"
+ },
+ {
+ "Id": "1632",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "改动出入时间表"
+ },
+ {
+ "Id": "1695",
+ "Level": "6",
+ "Type": "用户",
+ "Content": "提早布防"
+ },
+ {
+ "Id": "1696",
+ "Level": "6",
+ "Type": "用户",
+ "Content": "未及时布防"
+ },
+ {
+ "Id": "1697",
+ "Level": "6",
+ "Type": "用户",
+ "Content": "提早撤防"
+ },
+ {
+ "Id": "1698",
+ "Level": "6",
+ "Type": "用户",
+ "Content": "未及时撤防"
+ },
+ {
+ "Id": "1699",
+ "Level": "6",
+ "Type": "用户",
+ "Content": "超时测试间隔信号"
+ },
+ {
+ "Id": "16A0",
+ "Level": "6",
+ "Type": "用户",
+ "Content": "用户缴费时间到"
+ },
+ {
+ "Id": "16B0",
+ "Level": "6",
+ "Type": "测试",
+ "Content": "手动测试操作"
+ },
+ {
+ "Id": "16CC",
+ "Level": "6",
+ "Type": "错误",
+ "Content": "测试"
+ },
+ {
+ "Id": "3100",
+ "Level": "1",
+ "Type": "紧急恢复",
+ "Content": "个人救护报警恢复"
+ },
+ {
+ "Id": "3101",
+ "Level": "1",
+ "Type": "紧急恢复",
+ "Content": "个人救护报警,紧急按钮恢复"
+ },
+ {
+ "Id": "3102",
+ "Level": "1",
+ "Type": "紧急恢复",
+ "Content": "报到失败恢复"
+ },
+ {
+ "Id": "3103",
+ "Level": "1",
+ "Type": "紧急恢复",
+ "Content": "紧急报警恢复"
+ },
+ {
+ "Id": "3104",
+ "Level": "1",
+ "Type": "紧急恢复",
+ "Content": "紧急报警恢复"
+ },
+ {
+ "Id": "3110",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "火警报警恢复"
+ },
+ {
+ "Id": "3111",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "烟感探头恢复"
+ },
+ {
+ "Id": "3112",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "燃烧熄灭"
+ },
+ {
+ "Id": "3113",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "消防水流恢复"
+ },
+ {
+ "Id": "3114",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "热感探头恢复"
+ },
+ {
+ "Id": "3115",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "火警手动报警恢复"
+ },
+ {
+ "Id": "3116",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "空调槽烟感恢复"
+ },
+ {
+ "Id": "3117",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "火焰探头恢复"
+ },
+ {
+ "Id": "3118",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "接近警报恢复"
+ },
+ {
+ "Id": "3119",
+ "Level": "1",
+ "Type": "火警恢复",
+ "Content": "煤气泄漏恢复"
+ },
+ {
+ "Id": "3120",
+ "Level": "1",
+ "Type": "劫盗恢复",
+ "Content": "劫盗恢复"
+ },
+ {
+ "Id": "3121",
+ "Level": "1",
+ "Type": "劫盗恢复",
+ "Content": "挟持恢复"
+ },
+ {
+ "Id": "3122",
+ "Level": "1",
+ "Type": "劫盗恢复",
+ "Content": "无声劫盗恢复"
+ },
+ {
+ "Id": "3123",
+ "Level": "1",
+ "Type": "劫盗恢复",
+ "Content": "有声劫盗恢复"
+ },
+ {
+ "Id": "3124",
+ "Level": "1",
+ "Type": "劫盗恢复",
+ "Content": "异地劫持恢复"
+ },
+ {
+ "Id": "3130",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "窃盗恢复"
+ },
+ {
+ "Id": "3131",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "周界窃盗恢复"
+ },
+ {
+ "Id": "3132",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "内部窃盗恢复"
+ },
+ {
+ "Id": "3133",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "24小时窃盗恢复"
+ },
+ {
+ "Id": "3134",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "出/入窃盗恢复"
+ },
+ {
+ "Id": "3135",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "日/夜防区恢复"
+ },
+ {
+ "Id": "3136",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "室外窃盗恢复"
+ },
+ {
+ "Id": "3137",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "拆动报警恢复"
+ },
+ {
+ "Id": "3138",
+ "Level": "1",
+ "Type": "窃盗恢复",
+ "Content": "接近报警恢复"
+ },
+ {
+ "Id": "3140",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "一般报警恢复"
+ },
+ {
+ "Id": "3141",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "总线开路恢复"
+ },
+ {
+ "Id": "3142",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "总线短路恢复"
+ },
+ {
+ "Id": "3143",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "扩充器恢复"
+ },
+ {
+ "Id": "3144",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "探头被拆动恢复"
+ },
+ {
+ "Id": "3145",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "扩充器被拆恢复"
+ },
+ {
+ "Id": "3150",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "24小时非窃盗报警恢复"
+ },
+ {
+ "Id": "3151",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "气体恢复"
+ },
+ {
+ "Id": "3152",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "冷藏器恢复"
+ },
+ {
+ "Id": "3153",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "加热系统恢复"
+ },
+ {
+ "Id": "3154",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "漏水恢复"
+ },
+ {
+ "Id": "3155",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "箔片破损恢复"
+ },
+ {
+ "Id": "3156",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "日间防区恢复"
+ },
+ {
+ "Id": "3157",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "气体水平过低恢复"
+ },
+ {
+ "Id": "3158",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "温度过高恢复"
+ },
+ {
+ "Id": "3159",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "温度过低恢复"
+ },
+ {
+ "Id": "3161",
+ "Level": "1",
+ "Type": "警报恢复",
+ "Content": "空气流动恢复"
+ },
+ {
+ "Id": "3170",
+ "Level": "1",
+ "Type": "故障恢复",
+ "Content": "用户离线恢复"
+ },
+ {
+ "Id": "3180",
+ "Level": "1",
+ "Type": "故障",
+ "Content": "GPRS设备恢复连接"
+ },
+ {
+ "Id": "3200",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "火警监控恢复"
+ },
+ {
+ "Id": "3201",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "水压过低恢复"
+ },
+ {
+ "Id": "3202",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "二氧化碳过低恢复"
+ },
+ {
+ "Id": "3203",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "阀门感应恢复"
+ },
+ {
+ "Id": "3204",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "水压过低恢复"
+ },
+ {
+ "Id": "3205",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "水泵关闭"
+ },
+ {
+ "Id": "3206",
+ "Level": "2",
+ "Type": "监控恢复",
+ "Content": "水泵故障恢复"
+ },
+ {
+ "Id": "3300",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "系统故障恢复"
+ },
+ {
+ "Id": "3301",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "交流恢复"
+ },
+ {
+ "Id": "3302",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "电池低压恢复"
+ },
+ {
+ "Id": "3303",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "RAM校验和故障恢复"
+ },
+ {
+ "Id": "3304",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "ROM检验和故障恢复"
+ },
+ {
+ "Id": "3305",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "系统重新设定恢复"
+ },
+ {
+ "Id": "3306",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "编程改动恢复"
+ },
+ {
+ "Id": "3307",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "自检故障恢复"
+ },
+ {
+ "Id": "3308",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "主机停机使用恢复"
+ },
+ {
+ "Id": "3309",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "电池测试故障恢复"
+ },
+ {
+ "Id": "330A",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "系统复位恢复"
+ },
+ {
+ "Id": "3310",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "接地故障恢复"
+ },
+ {
+ "Id": "3320",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "警号/继电器恢复"
+ },
+ {
+ "Id": "3321",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "警铃#1恢复"
+ },
+ {
+ "Id": "3322",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "警铃#2恢复"
+ },
+ {
+ "Id": "3323",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "警报继电器恢复"
+ },
+ {
+ "Id": "3324",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "故障继电器恢复"
+ },
+ {
+ "Id": "3325",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "逆转继电器恢复"
+ },
+ {
+ "Id": "332A",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "警铃保险管烧坏恢复"
+ },
+ {
+ "Id": "3330",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "系统周边恢复"
+ },
+ {
+ "Id": "3331",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "总线开路恢复"
+ },
+ {
+ "Id": "3332",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "总线短路恢复"
+ },
+ {
+ "Id": "3333",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "扩充器故障"
+ },
+ {
+ "Id": "3334",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "重复器故障恢复"
+ },
+ {
+ "Id": "3335",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "打印机无纸恢复"
+ },
+ {
+ "Id": "3336",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "打印机故障恢复"
+ },
+ {
+ "Id": "3339",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "振动光纤断光恢复"
+ },
+ {
+ "Id": "3340",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "网络设备在线"
+ },
+ {
+ "Id": "3350",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "通讯故障恢复"
+ },
+ {
+ "Id": "3351",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "电话线1故障恢复"
+ },
+ {
+ "Id": "3352",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "电话线2故障恢复"
+ },
+ {
+ "Id": "3353",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "长距离无线发射器故障恢复"
+ },
+ {
+ "Id": "3354",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "通讯失败恢复"
+ },
+ {
+ "Id": "3355",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "失去长距无线监控恢复"
+ },
+ {
+ "Id": "3356",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "失去长距无线中央监控恢复"
+ },
+ {
+ "Id": "3357",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "无线感干扰恢复"
+ },
+ {
+ "Id": "3360",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "防区故障恢复"
+ },
+ {
+ "Id": "3361",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "防拆故障恢复"
+ },
+ {
+ "Id": "3362",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "充电故障恢复"
+ },
+ {
+ "Id": "3363",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "模块已准备就绪"
+ },
+ {
+ "Id": "3370",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "保护回路恢复"
+ },
+ {
+ "Id": "3371",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "保护回路开路恢复"
+ },
+ {
+ "Id": "3372",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "保护回路短路恢复"
+ },
+ {
+ "Id": "3373",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "火警回路故障恢复"
+ },
+ {
+ "Id": "337A",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "回路故障恢复"
+ },
+ {
+ "Id": "3380",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "感应器故障恢复"
+ },
+ {
+ "Id": "3381",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "无线监控故障恢复"
+ },
+ {
+ "Id": "3382",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "总线监控故障恢复"
+ },
+ {
+ "Id": "3383",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "感应器被拆恢复"
+ },
+ {
+ "Id": "3384",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "无线感应器电池过低恢复"
+ },
+ {
+ "Id": "3393",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "电话故障恢复"
+ },
+ {
+ "Id": "3394",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "卡故障恢复"
+ },
+ {
+ "Id": "33A0",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "请求服务恢复"
+ },
+ {
+ "Id": "33A1",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "设置时间恢复"
+ },
+ {
+ "Id": "33A2",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "5(12)伏电源故障恢复"
+ },
+ {
+ "Id": "33A3",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "电话线故障恢复"
+ },
+ {
+ "Id": "33A4",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "卡故障恢复"
+ },
+ {
+ "Id": "33A5",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "失去电池恢复"
+ },
+ {
+ "Id": "33A6",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "进入编程模式恢复"
+ },
+ {
+ "Id": "33A7",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "未知故障恢复"
+ },
+ {
+ "Id": "33A8",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "无效报告恢复"
+ },
+ {
+ "Id": "33B0",
+ "Level": "3",
+ "Type": "密码恢复",
+ "Content": "用户密码更改恢复"
+ },
+ {
+ "Id": "33B1",
+ "Level": "3",
+ "Type": "故障恢复",
+ "Content": "错误恢复"
+ },
+ {
+ "Id": "3400",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "布防"
+ },
+ {
+ "Id": "3401",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "用户布防"
+ },
+ {
+ "Id": "3402",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "集体布防"
+ },
+ {
+ "Id": "3403",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "自动布防"
+ },
+ {
+ "Id": "3404",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "过迟布防"
+ },
+ {
+ "Id": "3405",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "不适用恢复"
+ },
+ {
+ "Id": "3406",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "取消恢复"
+ },
+ {
+ "Id": "3407",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "遥控布防"
+ },
+ {
+ "Id": "3408",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "快速布防"
+ },
+ {
+ "Id": "3409",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "开关布防"
+ },
+ {
+ "Id": "340A",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "部分布防"
+ },
+ {
+ "Id": "340B",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "周边布防"
+ },
+ {
+ "Id": "3411",
+ "Level": "4",
+ "Type": "遥控恢复",
+ "Content": "要求回电恢复"
+ },
+ {
+ "Id": "3412",
+ "Level": "4",
+ "Type": "遥控恢复",
+ "Content": "遥控编程成功恢复"
+ },
+ {
+ "Id": "3413",
+ "Level": "4",
+ "Type": "遥控恢复",
+ "Content": "遥控不成功恢复"
+ },
+ {
+ "Id": "3414",
+ "Level": "4",
+ "Type": "遥控恢复",
+ "Content": "关闭系统恢复"
+ },
+ {
+ "Id": "3415",
+ "Level": "4",
+ "Type": "遥控恢复",
+ "Content": "关闭通讯恢复"
+ },
+ {
+ "Id": "3416",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "布防操作"
+ },
+ {
+ "Id": "3417",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "防区布防"
+ },
+ {
+ "Id": "3421",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "拒绝出入-用户恢复"
+ },
+ {
+ "Id": "3422",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "成功出入-用户恢复"
+ },
+ {
+ "Id": "3441",
+ "Level": "4",
+ "Type": "布防",
+ "Content": "留守布防"
+ },
+ {
+ "Id": "3450",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "非正常时段布防"
+ },
+ {
+ "Id": "3451",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "过早布防"
+ },
+ {
+ "Id": "3452",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "过迟布防"
+ },
+ {
+ "Id": "3453",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "撤防失败恢复"
+ },
+ {
+ "Id": "3454",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "布防失败恢复"
+ },
+ {
+ "Id": "3455",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "自动布防失败恢复"
+ },
+ {
+ "Id": "3456",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "部分布防恢复"
+ },
+ {
+ "Id": "3457",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "外出错误恢复"
+ },
+ {
+ "Id": "3458",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "操作员在现场恢复"
+ },
+ {
+ "Id": "3459",
+ "Level": "4",
+ "Type": "出入恢复",
+ "Content": "最近布防恢复"
+ },
+ {
+ "Id": "3480",
+ "Level": "4",
+ "Type": "用户恢复",
+ "Content": "开警号"
+ },
+ {
+ "Id": "3520",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "停用警号/继电器恢复"
+ },
+ {
+ "Id": "3521",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "警铃1停用恢复"
+ },
+ {
+ "Id": "3522",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "警铃2停用恢复"
+ },
+ {
+ "Id": "3523",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "停用警报继电器恢复"
+ },
+ {
+ "Id": "3524",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "停用故障继电器恢复"
+ },
+ {
+ "Id": "3525",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "逆反继电器恢复"
+ },
+ {
+ "Id": "3530",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "停用系统周边恢复"
+ },
+ {
+ "Id": "3540",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "停用系统周边恢复"
+ },
+ {
+ "Id": "3551",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "通讯器停用恢复"
+ },
+ {
+ "Id": "3552",
+ "Level": "5",
+ "Type": "停用恢复",
+ "Content": "无线发射器停用恢复"
+ },
+ {
+ "Id": "3570",
+ "Level": "5",
+ "Type": "旁路恢复",
+ "Content": "防区旁路恢复"
+ },
+ {
+ "Id": "3571",
+ "Level": "5",
+ "Type": "旁路恢复",
+ "Content": "火警旁路恢复"
+ },
+ {
+ "Id": "3572",
+ "Level": "5",
+ "Type": "旁路恢复",
+ "Content": "24小时防区旁路恢复"
+ },
+ {
+ "Id": "3573",
+ "Level": "5",
+ "Type": "旁路恢复",
+ "Content": "窃盗旁路恢复"
+ },
+ {
+ "Id": "3574",
+ "Level": "5",
+ "Type": "旁路恢复",
+ "Content": "集体旁路恢复"
+ },
+ {
+ "Id": "3580",
+ "Level": "5",
+ "Type": "旁路恢复",
+ "Content": "旁路操作恢复"
+ },
+ {
+ "Id": "3601",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "手动测试恢复"
+ },
+ {
+ "Id": "3602",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "定期测试恢复"
+ },
+ {
+ "Id": "3603",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "定期无线发射器测试恢复"
+ },
+ {
+ "Id": "3604",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "火警测试恢复"
+ },
+ {
+ "Id": "3605",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "状态报告恢复"
+ },
+ {
+ "Id": "3606",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "监听恢复"
+ },
+ {
+ "Id": "3607",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "步行测试模式恢复"
+ },
+ {
+ "Id": "3609",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "图像传输恢复"
+ },
+ {
+ "Id": "3630",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "改动时间表恢复"
+ },
+ {
+ "Id": "3631",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "改动例外时间表恢复"
+ },
+ {
+ "Id": "3632",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "改动出入时间表恢复"
+ },
+ {
+ "Id": "3695",
+ "Level": "6",
+ "Type": "用户恢复",
+ "Content": "提早布防恢复"
+ },
+ {
+ "Id": "3696",
+ "Level": "6",
+ "Type": "用户恢复",
+ "Content": "未及时布防恢复"
+ },
+ {
+ "Id": "3697",
+ "Level": "6",
+ "Type": "用户恢复",
+ "Content": "提早撤防恢复"
+ },
+ {
+ "Id": "3698",
+ "Level": "6",
+ "Type": "用户恢复",
+ "Content": "未及时撤防恢复"
+ },
+ {
+ "Id": "3699",
+ "Level": "6",
+ "Type": "用户恢复",
+ "Content": "超过测试间隔信号恢复"
+ },
+ {
+ "Id": "36B0",
+ "Level": "6",
+ "Type": "测试恢复",
+ "Content": "手动测试操作恢复"
+ }
+]
\ No newline at end of file
diff --git a/JiLinApp.sln b/JiLinApp.sln
index 82cd743..3105430 100644
--- a/JiLinApp.sln
+++ b/JiLinApp.sln
@@ -5,7 +5,11 @@ VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiLinApp", "JiLinApp\JiLinApp.csproj", "{273E34C9-ED30-460E-BA9A-66A8F27CC5FE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EC.Util", "EC.Util\EC.Util.csproj", "{A41E47C9-1930-4FF0-955E-B91EC859D262}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EC.Util", "EC.Util\EC.Util.csproj", "{A41E47C9-1930-4FF0-955E-B91EC859D262}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiLinApp.Docking", "JiLinApp.Docking\JiLinApp.Docking.csproj", "{B664DFEE-E137-44AC-A766-95D384E3F70B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiLinApp.Biz", "JiLinApp.Biz\JiLinApp.Biz.csproj", "{7CE63A50-C92C-4554-8E0C-F7BED355C1FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +25,14 @@ Global
{A41E47C9-1930-4FF0-955E-B91EC859D262}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A41E47C9-1930-4FF0-955E-B91EC859D262}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A41E47C9-1930-4FF0-955E-B91EC859D262}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B664DFEE-E137-44AC-A766-95D384E3F70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B664DFEE-E137-44AC-A766-95D384E3F70B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B664DFEE-E137-44AC-A766-95D384E3F70B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B664DFEE-E137-44AC-A766-95D384E3F70B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE