Commit 5dc08a45f8398fffee141b0389bd79decccaf277

Authored by 648540858
1 parent 7f965a69

增加redis通知方式向设备/平台发送报警消息功能

@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 11
12 <groupId>com.genersoft</groupId> 12 <groupId>com.genersoft</groupId>
13 <artifactId>wvp-pro</artifactId> 13 <artifactId>wvp-pro</artifactId>
14 - <version>2.1.1</version> 14 + <version>2.2.1</version>
15 <name>web video platform</name> 15 <name>web video platform</name>
16 <description>国标28181视频平台</description> 16 <description>国标28181视频平台</description>
17 17
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.common.VideoManagerConstants; 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
  4 +import com.genersoft.iot.vmp.service.impl.RedisAlarmMsgListener;
4 import com.genersoft.iot.vmp.service.impl.RedisGPSMsgListener; 5 import com.genersoft.iot.vmp.service.impl.RedisGPSMsgListener;
5 import org.apache.commons.lang3.StringUtils; 6 import org.apache.commons.lang3.StringUtils;
6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Autowired;
@@ -48,6 +49,9 @@ public class RedisConfig extends CachingConfigurerSupport { @@ -48,6 +49,9 @@ public class RedisConfig extends CachingConfigurerSupport {
48 @Autowired 49 @Autowired
49 private RedisGPSMsgListener redisGPSMsgListener; 50 private RedisGPSMsgListener redisGPSMsgListener;
50 51
  52 + @Autowired
  53 + private RedisAlarmMsgListener redisAlarmMsgListener;
  54 +
51 @Bean 55 @Bean
52 public JedisPool jedisPool() { 56 public JedisPool jedisPool() {
53 if (StringUtils.isBlank(password)) { 57 if (StringUtils.isBlank(password)) {
@@ -93,6 +97,7 @@ public class RedisConfig extends CachingConfigurerSupport { @@ -93,6 +97,7 @@ public class RedisConfig extends CachingConfigurerSupport {
93 RedisMessageListenerContainer container = new RedisMessageListenerContainer(); 97 RedisMessageListenerContainer container = new RedisMessageListenerContainer();
94 container.setConnectionFactory(connectionFactory); 98 container.setConnectionFactory(connectionFactory);
95 container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS)); 99 container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS));
  100 + container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
96 return container; 101 return container;
97 } 102 }
98 103
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
@@ -29,7 +29,7 @@ public class SipConfig { @@ -29,7 +29,7 @@ public class SipConfig {
29 29
30 Integer registerTimeInterval = 120; 30 Integer registerTimeInterval = 120;
31 31
32 - private boolean alarm = false; 32 + private boolean alarm;
33 33
34 public void setIp(String ip) { 34 public void setIp(String ip) {
35 this.ip = ip; 35 this.ip = ip;
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AlarmChannelMessage.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * 通过redis分发报警消息
  5 + */
  6 +public class AlarmChannelMessage {
  7 + /**
  8 + * 国标编号
  9 + */
  10 + private String gbId;
  11 +
  12 + /**
  13 + * 报警编号
  14 + */
  15 + private int alarmSn;
  16 +
  17 +
  18 + /**
  19 + * 报警描述
  20 + */
  21 + private String alarmDescription;
  22 +
  23 + public String getGbId() {
  24 + return gbId;
  25 + }
  26 +
  27 + public void setGbId(String gbId) {
  28 + this.gbId = gbId;
  29 + }
  30 +
  31 + public int getAlarmSn() {
  32 + return alarmSn;
  33 + }
  34 +
  35 + public void setAlarmSn(int alarmSn) {
  36 + this.alarmSn = alarmSn;
  37 + }
  38 +
  39 + public String getAlarmDescription() {
  40 + return alarmDescription;
  41 + }
  42 +
  43 + public void setAlarmDescription(String alarmDescription) {
  44 + this.alarmDescription = alarmDescription;
  45 + }
  46 +}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java
@@ -50,7 +50,30 @@ public class DeviceAlarm { @@ -50,7 +50,30 @@ public class DeviceAlarm {
50 private double latitude; 50 private double latitude;
51 51
52 /** 52 /**
53 - * 报警类型 53 + * 报警类型,
  54 + * 报警方式为2时,不携带 AlarmType为默认的报警设备报警,
  55 + * 携带 AlarmType取值及对应报警类型如下:
  56 + * 1-视频丢失报警;
  57 + * 2-设备防拆报警;
  58 + * 3-存储设备磁盘满报警;
  59 + * 4-设备高温报警;
  60 + * 5-设备低温报警。
  61 + * 报警方式为5时,取值如下:
  62 + * 1-人工视频报警;
  63 + * 2-运动目标检测报警;
  64 + * 3-遗留物检测报警;
  65 + * 4-物体移除检测报警;
  66 + * 5-绊线检测报警;
  67 + * 6-入侵检测报警;
  68 + * 7-逆行检测报警;
  69 + * 8-徘徊检测报警;
  70 + * 9-流量统计报警;
  71 + * 10-密度检测报警;
  72 + * 11-视频异常检测报警;
  73 + * 12-快速移动报警。
  74 + * 报警方式为6时,取值下:
  75 + * 1-存储设备磁盘故障报警;
  76 + * 2-存储设备风扇故障报警。
54 */ 77 */
55 private String alarmType; 78 private String alarmType;
56 79
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
@@ -25,6 +25,9 @@ public class SubscribeInfo { @@ -25,6 +25,9 @@ public class SubscribeInfo {
25 this.callId = callIdHeader.getCallId(); 25 this.callId = callIdHeader.getCallId();
26 } 26 }
27 27
  28 + public SubscribeInfo() {
  29 + }
  30 +
28 private String id; 31 private String id;
29 private int expires; 32 private int expires;
30 private String callId; 33 private String callId;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
1 package com.genersoft.iot.vmp.gb28181.transmit.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
5 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback; 4 +import com.genersoft.iot.vmp.gb28181.bean.*;
6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -336,4 +335,13 @@ public interface ISIPCommander { @@ -336,4 +335,13 @@ public interface ISIPCommander {
336 * @param cmdString 前端控制指令串 335 * @param cmdString 前端控制指令串
337 */ 336 */
338 boolean dragZoomCmd(Device device, String channelId, String cmdString); 337 boolean dragZoomCmd(Device device, String channelId, String cmdString);
  338 +
  339 +
  340 + /**
  341 + * 向设备发送报警NOTIFY消息, 用于互联结构下,此时将设备当成一个平级平台看待
  342 + * @param device 设备
  343 + * @param deviceAlarm 报警信息信息
  344 + * @return
  345 + */
  346 + boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm);
339 } 347 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
1 package com.genersoft.iot.vmp.gb28181.transmit.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2
3 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
4 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;  
5 -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;  
6 -import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; 3 +import com.genersoft.iot.vmp.gb28181.bean.*;
7 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
8 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
9 6
@@ -76,6 +73,14 @@ public interface ISIPCommanderForPlatform { @@ -76,6 +73,14 @@ public interface ISIPCommanderForPlatform {
76 boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo); 73 boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo);
77 74
78 /** 75 /**
  76 + * 向上级回复报警消息
  77 + * @param parentPlatform 平台信息
  78 + * @param deviceAlarm 报警信息信息
  79 + * @return
  80 + */
  81 + boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm);
  82 +
  83 + /**
79 * 回复catalog事件-增加/更新 84 * 回复catalog事件-增加/更新
80 * @param parentPlatform 85 * @param parentPlatform
81 * @param deviceChannels 86 * @param deviceChannels
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -5,10 +5,7 @@ import com.genersoft.iot.vmp.common.StreamInfo; @@ -5,10 +5,7 @@ import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.conf.DynamicTask; 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 import com.genersoft.iot.vmp.conf.SipConfig; 6 import com.genersoft.iot.vmp.conf.SipConfig;
7 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
8 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
9 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;  
10 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;  
11 -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; 8 +import com.genersoft.iot.vmp.gb28181.bean.*;
12 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
13 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
@@ -23,6 +20,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -23,6 +20,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
23 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 20 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
24 import gov.nist.javax.sip.SipProviderImpl; 21 import gov.nist.javax.sip.SipProviderImpl;
25 import gov.nist.javax.sip.SipStackImpl; 22 import gov.nist.javax.sip.SipStackImpl;
  23 +import gov.nist.javax.sip.message.MessageFactoryImpl;
26 import gov.nist.javax.sip.message.SIPRequest; 24 import gov.nist.javax.sip.message.SIPRequest;
27 import gov.nist.javax.sip.stack.SIPDialog; 25 import gov.nist.javax.sip.stack.SIPDialog;
28 import org.slf4j.Logger; 26 import org.slf4j.Logger;
@@ -35,10 +33,7 @@ import org.springframework.util.StringUtils; @@ -35,10 +33,7 @@ import org.springframework.util.StringUtils;
35 33
36 import javax.sip.*; 34 import javax.sip.*;
37 import javax.sip.address.SipURI; 35 import javax.sip.address.SipURI;
38 -import javax.sip.header.CallIdHeader;  
39 -import javax.sip.header.ContentTypeHeader;  
40 -import javax.sip.header.ExpiresHeader;  
41 -import javax.sip.header.ViaHeader; 36 +import javax.sip.header.*;
42 import javax.sip.message.Request; 37 import javax.sip.message.Request;
43 import java.lang.reflect.Field; 38 import java.lang.reflect.Field;
44 import java.text.ParseException; 39 import java.text.ParseException;
@@ -1777,4 +1772,101 @@ public class SIPCommander implements ISIPCommander { @@ -1777,4 +1772,101 @@ public class SIPCommander implements ISIPCommander {
1777 e.printStackTrace(); 1772 e.printStackTrace();
1778 } 1773 }
1779 } 1774 }
  1775 +
  1776 + @Override
  1777 + public boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) {
  1778 + if (device == null) {
  1779 + return false;
  1780 + }
  1781 + logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
  1782 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  1783 + try {
  1784 + String characterSet = device.getCharset();
  1785 + StringBuffer deviceStatusXml = new StringBuffer(600);
  1786 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  1787 + deviceStatusXml.append("<Notify>\r\n");
  1788 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  1789 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1790 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  1791 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  1792 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  1793 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  1794 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  1795 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  1796 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  1797 + deviceStatusXml.append("<info>\r\n");
  1798 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  1799 + deviceStatusXml.append("</info>\r\n");
  1800 + deviceStatusXml.append("</Notify>\r\n");
  1801 +
  1802 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1803 + : udpSipProvider.getNewCallId();
  1804 + String tm = Long.toString(System.currentTimeMillis());
  1805 + Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader);
  1806 + transmitRequest(device, request);
  1807 +
  1808 +
  1809 + } catch (SipException | ParseException e) {
  1810 + e.printStackTrace();
  1811 + return false;
  1812 + } catch (InvalidArgumentException e) {
  1813 + throw new RuntimeException(e);
  1814 + }
  1815 + return true;
  1816 + }
  1817 +
  1818 + private void sendNotify(Device device, String catalogXmlContent,
  1819 + SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
  1820 + throws NoSuchFieldException, IllegalAccessException, SipException, ParseException {
  1821 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  1822 + String characterSet = device.getCharset();
  1823 + // 设置编码, 防止中文乱码
  1824 + messageFactory.setDefaultContentEncodingCharset(characterSet);
  1825 + Dialog dialog = subscribeInfo.getDialog();
  1826 + if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) return;
  1827 + SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
  1828 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  1829 + notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
  1830 +
  1831 + SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
  1832 + .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
  1833 + notifyRequest.addHeader(subscriptionState);
  1834 +
  1835 + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  1836 + if (subscribeInfo.getEventId() != null) {
  1837 + event.setEventId(subscribeInfo.getEventId());
  1838 + }
  1839 + notifyRequest.addHeader(event);
  1840 +
  1841 + SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
  1842 + if (subscribeInfo.getTransaction() != null) {
  1843 + SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
  1844 + sipURI.setHost(request.getRemoteAddress().getHostAddress());
  1845 + sipURI.setPort(request.getRemotePort());
  1846 + }else {
  1847 + sipURI.setHost(device.getIp());
  1848 + sipURI.setPort(device.getPort());
  1849 + }
  1850 +
  1851 + ClientTransaction transaction = null;
  1852 + if ("TCP".equals(device.getTransport())) {
  1853 + transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
  1854 + } else if ("UDP".equals(device.getTransport())) {
  1855 + transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
  1856 + }
  1857 + // 添加错误订阅
  1858 + if (errorEvent != null) {
  1859 + sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
  1860 + }
  1861 + // 添加订阅
  1862 + if (okEvent != null) {
  1863 + sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
  1864 + }
  1865 + if (transaction == null) {
  1866 + logger.error("平台{}的Transport错误:{}",device.getDeviceId(), device.getTransport());
  1867 + return;
  1868 + }
  1869 + dialog.sendRequest(transaction);
  1870 +
  1871 + }
1780 } 1872 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -436,6 +436,48 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -436,6 +436,48 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
436 } 436 }
437 437
438 @Override 438 @Override
  439 + public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) {
  440 + if (parentPlatform == null) {
  441 + return false;
  442 + }
  443 + logger.info("[发送 报警订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
  444 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  445 + try {
  446 + String characterSet = parentPlatform.getCharacterSet();
  447 + StringBuffer deviceStatusXml = new StringBuffer(600);
  448 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  449 + deviceStatusXml.append("<Notify>\r\n");
  450 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  451 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  452 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  453 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  454 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  455 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  456 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  457 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  458 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  459 + deviceStatusXml.append("<info>\r\n");
  460 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  461 + deviceStatusXml.append("</info>\r\n");
  462 + deviceStatusXml.append("</Notify>\r\n");
  463 +
  464 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  465 + : udpSipProvider.getNewCallId();
  466 +
  467 + String tm = Long.toString(System.currentTimeMillis());
  468 + Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), "FromPtz" + tm, callIdHeader);
  469 + transmitRequest(parentPlatform, request);
  470 +
  471 + } catch (SipException | ParseException e) {
  472 + e.printStackTrace();
  473 + return false;
  474 + } catch (InvalidArgumentException e) {
  475 + throw new RuntimeException(e);
  476 + }
  477 + return true;
  478 + }
  479 +
  480 + @Override
439 public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) { 481 public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
440 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { 482 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
441 return false; 483 return false;
@@ -495,11 +537,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -495,11 +537,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
495 event.setEventId(subscribeInfo.getEventId()); 537 event.setEventId(subscribeInfo.getEventId());
496 } 538 }
497 notifyRequest.addHeader(event); 539 notifyRequest.addHeader(event);
498 -  
499 SipURI sipURI = (SipURI) notifyRequest.getRequestURI(); 540 SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
500 - SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();  
501 - sipURI.setHost(request.getRemoteAddress().getHostAddress());  
502 - sipURI.setPort(request.getRemotePort()); 541 + if (subscribeInfo.getTransaction() != null) {
  542 + SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
  543 + sipURI.setHost(request.getRemoteAddress().getHostAddress());
  544 + sipURI.setPort(request.getRemotePort());
  545 + }else {
  546 + sipURI.setHost(parentPlatform.getServerIP());
  547 + sipURI.setPort(parentPlatform.getServerPort());
  548 + }
  549 +
503 ClientTransaction transaction = null; 550 ClientTransaction transaction = null;
504 if ("TCP".equals(parentPlatform.getTransport())) { 551 if ("TCP".equals(parentPlatform.getTransport())) {
505 transaction = tcpSipProvider.getNewClientTransaction(notifyRequest); 552 transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
2 2
  3 +import com.alibaba.fastjson.JSON;
3 import com.genersoft.iot.vmp.conf.SipConfig; 4 import com.genersoft.iot.vmp.conf.SipConfig;
4 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.gb28181.bean.*; 6 import com.genersoft.iot.vmp.gb28181.bean.*;
@@ -11,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify. @@ -11,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.
11 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; 12 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
12 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 13 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
13 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 14 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
  15 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
15 import com.genersoft.iot.vmp.utils.GpsUtil; 17 import com.genersoft.iot.vmp.utils.GpsUtil;
16 import org.dom4j.Element; 18 import org.dom4j.Element;
@@ -21,7 +23,12 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +23,12 @@ import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
22 import org.springframework.util.StringUtils; 24 import org.springframework.util.StringUtils;
23 25
  26 +import javax.sip.InvalidArgumentException;
24 import javax.sip.RequestEvent; 27 import javax.sip.RequestEvent;
  28 +import javax.sip.SipException;
  29 +import javax.sip.message.Response;
  30 +
  31 +import java.text.ParseException;
25 32
26 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*; 33 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
27 34
@@ -47,6 +54,9 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -47,6 +54,9 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
47 private IVideoManagerStorage storager; 54 private IVideoManagerStorage storager;
48 55
49 @Autowired 56 @Autowired
  57 + private IRedisCatchStorage redisCatchStorage;
  58 +
  59 + @Autowired
50 private IDeviceAlarmService deviceAlarmService; 60 private IDeviceAlarmService deviceAlarmService;
51 61
52 @Autowired 62 @Autowired
@@ -59,11 +69,22 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -59,11 +69,22 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
59 69
60 @Override 70 @Override
61 public void handForDevice(RequestEvent evt, Device device, Element rootElement) { 71 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
62 - if (!sipConfig.isAlarm()) {  
63 - return; 72 + logger.info("收到来自设备[{}]的报警通知", device.getDeviceId());
  73 + // 回复200 OK
  74 + try {
  75 + responseAck(evt, Response.OK);
  76 + } catch (SipException e) {
  77 + throw new RuntimeException(e);
  78 + } catch (InvalidArgumentException e) {
  79 + throw new RuntimeException(e);
  80 + } catch (ParseException e) {
  81 + throw new RuntimeException(e);
64 } 82 }
  83 +
65 Element deviceIdElement = rootElement.element("DeviceID"); 84 Element deviceIdElement = rootElement.element("DeviceID");
66 String channelId = deviceIdElement.getText().toString(); 85 String channelId = deviceIdElement.getText().toString();
  86 +
  87 +
67 DeviceAlarm deviceAlarm = new DeviceAlarm(); 88 DeviceAlarm deviceAlarm = new DeviceAlarm();
68 deviceAlarm.setDeviceId(device.getDeviceId()); 89 deviceAlarm.setDeviceId(device.getDeviceId());
69 deviceAlarm.setChannelId(channelId); 90 deviceAlarm.setChannelId(channelId);
@@ -111,9 +132,24 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -111,9 +132,24 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
111 deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType")); 132 deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));
112 } 133 }
113 } 134 }
  135 +
  136 + if (channelId.equals(sipConfig.getId())) {
  137 + // 发送给平台的报警信息。 发送redis通知
  138 + AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
  139 + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
  140 + alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
  141 + alarmChannelMessage.setGbId(channelId);
  142 + redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
  143 +
  144 + return;
  145 + }
  146 +
114 logger.debug("存储报警信息、报警分类"); 147 logger.debug("存储报警信息、报警分类");
115 // 存储报警信息、报警分类 148 // 存储报警信息、报警分类
116 - deviceAlarmService.add(deviceAlarm); 149 + if (sipConfig.isAlarm()) {
  150 + deviceAlarmService.add(deviceAlarm);
  151 + }
  152 +
117 153
118 if (offLineDetector.isOnline(device.getDeviceId())) { 154 if (offLineDetector.isOnline(device.getDeviceId())) {
119 publisher.deviceAlarmEventPublish(deviceAlarm); 155 publisher.deviceAlarmEventPublish(deviceAlarm);
@@ -121,7 +157,59 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -121,7 +157,59 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
121 } 157 }
122 158
123 @Override 159 @Override
124 - public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { 160 + public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
  161 + logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId());
  162 + // 回复200 OK
  163 + try {
  164 + responseAck(evt, Response.OK);
  165 + } catch (SipException e) {
  166 + throw new RuntimeException(e);
  167 + } catch (InvalidArgumentException e) {
  168 + throw new RuntimeException(e);
  169 + } catch (ParseException e) {
  170 + throw new RuntimeException(e);
  171 + }
  172 + Element deviceIdElement = rootElement.element("DeviceID");
  173 + String channelId = deviceIdElement.getText().toString();
  174 +
  175 +
  176 + DeviceAlarm deviceAlarm = new DeviceAlarm();
  177 + deviceAlarm.setDeviceId(parentPlatform.getServerGBId());
  178 + deviceAlarm.setChannelId(channelId);
  179 + deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority"));
  180 + deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod"));
  181 + deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime"));
  182 + if (getText(rootElement, "AlarmDescription") == null) {
  183 + deviceAlarm.setAlarmDescription("");
  184 + } else {
  185 + deviceAlarm.setAlarmDescription(getText(rootElement, "AlarmDescription"));
  186 + }
  187 + if (NumericUtil.isDouble(getText(rootElement, "Longitude"))) {
  188 + deviceAlarm.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
  189 + } else {
  190 + deviceAlarm.setLongitude(0.00);
  191 + }
  192 + if (NumericUtil.isDouble(getText(rootElement, "Latitude"))) {
  193 + deviceAlarm.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
  194 + } else {
  195 + deviceAlarm.setLatitude(0.00);
  196 + }
  197 +
  198 + if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
  199 +
  200 + if (deviceAlarm.getAlarmMethod().equals("5")) {
  201 + deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));
  202 + }
  203 + }
125 204
  205 + if (channelId.equals(parentPlatform.getDeviceGBId())) {
  206 + // 发送给平台的报警信息。 发送redis通知
  207 + AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
  208 + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
  209 + alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
  210 + alarmChannelMessage.setGbId(channelId);
  211 + redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
  212 + return;
  213 + }
126 } 214 }
127 } 215 }
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
@@ -25,6 +25,7 @@ public class SipUtils { @@ -25,6 +25,7 @@ public class SipUtils {
25 * */ 25 * */
26 public static String getChannelIdFromHeader(Request request) { 26 public static String getChannelIdFromHeader(Request request) {
27 Header subject = request.getHeader("subject"); 27 Header subject = request.getHeader("subject");
  28 + if (subject == null) return null;
28 return ((Subject) subject).getSubject().split(":")[0]; 29 return ((Subject) subject).getSubject().split(":")[0];
29 } 30 }
30 31
src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.impl;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.genersoft.iot.vmp.gb28181.bean.*;
  5 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  7 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  8 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  9 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  10 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.data.redis.connection.Message;
  15 +import org.springframework.data.redis.connection.MessageListener;
  16 +import org.springframework.http.HttpStatus;
  17 +import org.springframework.http.ResponseEntity;
  18 +import org.springframework.stereotype.Component;
  19 +
  20 +import java.text.SimpleDateFormat;
  21 +
  22 +@Component
  23 +public class RedisAlarmMsgListener implements MessageListener {
  24 +
  25 + private final static Logger logger = LoggerFactory.getLogger(RedisAlarmMsgListener.class);
  26 +
  27 + @Autowired
  28 + private ISIPCommander commander;
  29 +
  30 + @Autowired
  31 + private ISIPCommanderForPlatform commanderForPlatform;
  32 +
  33 + @Autowired
  34 + private IVideoManagerStorage storage;
  35 +
  36 + private final SimpleDateFormat formatForGB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
  37 +
  38 + @Override
  39 + public void onMessage(Message message, byte[] bytes) {
  40 + logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody()));
  41 + AlarmChannelMessage alarmChannelMessage = JSON.parseObject(message.getBody(), AlarmChannelMessage.class);
  42 + if (alarmChannelMessage == null) {
  43 + logger.warn("[REDIS的ALARM通知]消息解析失败");
  44 + return;
  45 + }
  46 + String gbId = alarmChannelMessage.getGbId();
  47 + Device device = storage.queryVideoDevice(gbId);
  48 + ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
  49 +
  50 + DeviceAlarm deviceAlarm = new DeviceAlarm();
  51 + deviceAlarm.setChannelId(gbId);
  52 + deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
  53 + deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
  54 + deviceAlarm.setAlarmPriority("1");
  55 + deviceAlarm.setAlarmTime(formatForGB.format(System.currentTimeMillis()));
  56 + deviceAlarm.setAlarmType("1");
  57 + deviceAlarm.setLongitude(0);
  58 + deviceAlarm.setLatitude(0);
  59 +
  60 +
  61 + if (device != null && platform == null) {
  62 + commander.sendAlarmMessage(device, deviceAlarm);
  63 + }else if (device == null && platform != null){
  64 + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  65 + }else {
  66 + logger.warn("无法确定" + gbId + "是平台还是设备");
  67 + }
  68 + }
  69 +}
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -140,6 +140,12 @@ public interface IRedisCatchStorage { @@ -140,6 +140,12 @@ public interface IRedisCatchStorage {
140 void sendStreamChangeMsg(String type, JSONObject jsonObject); 140 void sendStreamChangeMsg(String type, JSONObject jsonObject);
141 141
142 /** 142 /**
  143 + * 发送报警消息
  144 + * @param msg 消息内容
  145 + */
  146 + void sendAlarmMsg(AlarmChannelMessage msg);
  147 +
  148 + /**
143 * 添加流信息到redis 149 * 添加流信息到redis
144 * @param mediaServerItem 150 * @param mediaServerItem
145 * @param app 151 * @param app
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -639,4 +639,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -639,4 +639,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
639 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); 639 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
640 } 640 }
641 641
  642 + @Override
  643 + public void sendAlarmMsg(AlarmChannelMessage msg) {
  644 + String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM;
  645 + logger.info("[redis 报警通知] {}: {}", key, JSON.toJSON(msg));
  646 + redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
  647 + }
642 } 648 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.alarm; 1 package com.genersoft.iot.vmp.vmanager.gb28181.alarm;
2 2
  3 +import com.genersoft.iot.vmp.gb28181.bean.Device;
3 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; 4 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  5 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  6 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
  7 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
4 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 9 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
5 import com.genersoft.iot.vmp.service.IGbStreamService; 10 import com.genersoft.iot.vmp.service.IGbStreamService;
  11 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
6 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 12 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
7 import com.github.pagehelper.PageInfo; 13 import com.github.pagehelper.PageInfo;
8 import io.swagger.annotations.Api; 14 import io.swagger.annotations.Api;
@@ -31,7 +37,17 @@ public class AlarmController { @@ -31,7 +37,17 @@ public class AlarmController {
31 @Autowired 37 @Autowired
32 private IDeviceAlarmService deviceAlarmService; 38 private IDeviceAlarmService deviceAlarmService;
33 39
  40 + @Autowired
  41 + private ISIPCommander commander;
  42 +
  43 + @Autowired
  44 + private ISIPCommanderForPlatform commanderForPlatform;
  45 +
  46 + @Autowired
  47 + private IVideoManagerStorage storage;
  48 +
34 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 49 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  50 + private SimpleDateFormat formatForGB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
35 51
36 /** 52 /**
37 * 分页查询报警 53 * 分页查询报警
@@ -133,5 +149,51 @@ public class AlarmController { @@ -133,5 +149,51 @@ public class AlarmController {
133 return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK); 149 return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
134 } 150 }
135 151
  152 + /**
  153 + * 测试向上级/设备发送模拟报警通知
  154 + *
  155 + * @param deviceId 报警id
  156 + * @return
  157 + */
  158 + @ApiOperation("测试向上级/设备发送模拟报警通知")
  159 + @GetMapping("/test/notify/alarm")
  160 + @ApiImplicitParams({
  161 + @ApiImplicitParam(name="deviceId", value = "deviceId", required = true ,dataTypeClass = Integer.class)
  162 + })
  163 + public ResponseEntity<WVPResult<String>> delete(
  164 + @RequestParam(required = false) String deviceId
  165 + ) {
  166 + if (StringUtils.isEmpty(deviceId)) {
  167 + return new ResponseEntity<>(HttpStatus.NOT_FOUND);
  168 + }
  169 + Device device = storage.queryVideoDevice(deviceId);
  170 + ParentPlatform platform = storage.queryParentPlatByServerGBId(deviceId);
  171 + DeviceAlarm deviceAlarm = new DeviceAlarm();
  172 + deviceAlarm.setChannelId(deviceId);
  173 + deviceAlarm.setAlarmDescription("test");
  174 + deviceAlarm.setAlarmMethod("1");
  175 + deviceAlarm.setAlarmPriority("1");
  176 + deviceAlarm.setAlarmTime(formatForGB.format(System.currentTimeMillis()));
  177 + deviceAlarm.setAlarmType("1");
  178 + deviceAlarm.setLongitude(115.33333);
  179 + deviceAlarm.setLatitude(39.33333);
  180 +
  181 + if (device != null && platform == null) {
  182 + commander.sendAlarmMessage(device, deviceAlarm);
  183 + }else if (device == null && platform != null){
  184 + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  185 + }else {
  186 + WVPResult wvpResult = new WVPResult();
  187 + wvpResult.setCode(0);
  188 + wvpResult.setMsg("无法确定" + deviceId + "是平台还是设备");
  189 + return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
  190 + }
  191 +
  192 + WVPResult wvpResult = new WVPResult();
  193 + wvpResult.setCode(0);
  194 + wvpResult.setMsg("success");
  195 + return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
  196 + }
  197 +
136 198
137 } 199 }