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; } } }