Commit 0f58218badea86a5209ae7f1ccd60b7cb4b26eee

Authored by panlinlin
2 parents c1b3f2be e864beca

Merge remote-tracking branch 'origin/master' into wvp-28181-2.0

# Conflicts:
#	README.md
#	src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
#	src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
#	src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
#	src/main/resources/wvp.sqlite
#	web_src/.postcssrc.js
#	web_src/src/components/UiHeader.vue
#	web_src/src/main.js
#	web_src/src/router/index.js
Showing 62 changed files with 3127 additions and 449 deletions

Too many changes to show.

To preserve performance only 62 of 68 files are displayed.

README.md
... ... @@ -13,6 +13,12 @@ WEB VIDEO PLATFORM銝銝芸鈭B28181-2016像嚗
13 13 # gitee郊隞
14 14 https://gitee.com/18010473990/wvp-GB28181.git
15 15  
  16 +#
  17 +![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_1.png)
  18 +![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_2.png)
  19 +![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_20201012_151459.png)
  20 +![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_20201012_152643.png)
  21 +![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_20201012_151606.png)
16 22  
17 23 # 1.0
18 24 1. 閫;
... ... @@ -36,8 +42,32 @@ https://gitee.com/18010473990/wvp-GB28181.git
36 42 19. h265, g.711撘(閬loseWaitRTPInfo霈曆蛹false)
37 43 20. 霅虫縑憭垢霅虫縑
38 44  
39   -# 2.0
40   -- [ ] 漣
  45 +#
  46 +1. eb, 銝閬蝵脣垢, wvp蔭辣蝵, vp銝韏琿蝵;
  47 +2. 像, 笆憭批像憭折挽憭餈;
  48 +3. 蝝,;
  49 +4. 蔭ZLM慦, 蔭憸憸;
  50 +5. udp憭垢璅∪, dp璅∪扯;
  51 +6. 憸挽蝵;
  52 +7. 敶霂;
  53 +8. dp/tcp芋撘;
  54 +9. 颲RTSPTMPTTP-FLVebsocket-FLVLS憭悅瘚
  55 +10.
  56 +11. 蝵蝵, vp銝lm蝵
  57 +12. h265, g.711撘
  58 +13. 摰嚗瘚嚗誨絲. ( [IKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD)嚗
  59 +14. 霅虫縑憭垢霅虫縑
  60 +15. 恥瘜
  61 + - [X] 蝘餃雿蔭霈a
  62 + - [X] 蝘餃雿蔭憭
  63 + - [ ] 霅虫辣霈a
  64 + - [X] 霅虫辣憭
  65 + - [ ] 霈曉敶恥
  66 + - [X] 霈曉敶憭
  67 +16. 蝘餃雿蔭霂W蝷綽蔭辣霈曄蔭蝘餃雿蔭摮
  68 +
  69 +# 2.0
  70 +- [ ] 漣
41 71 - [X] WEB瘛餃漣撟喳
42 72 - [X] 瘜典
43 73 - [X] 敹歲靽暑
... ... @@ -45,13 +75,18 @@ https://gitee.com/18010473990/wvp-GB28181.git
45 75 - [X]
46 76 - [ ]
47 77 - [ ] 鈭
48   -- [ ] 瘛餃TSP閫
49   -- [ ] 瘛餃NVIF瘚挽憭
50   -- [ ] 瘛餃TMP閫
51   -- [ ] 瘛餃頂蝏蔭
52   -- [ ] 瘛餃蝞∠
53   -
54   -
  78 +- [ ] 瘛餃TSP閫
  79 +- [ ] 瘛餃NVIF瘚挽憭
  80 +- [ ] 瘛餃TMP閫
  81 +- [ ] 瘛餃頂蝏蔭
  82 +- [ ] 瘛餃蝞∠
  83 +
  84 +# 敺嚗
  85 +銝漣蝥扯
  86 +瘚”
  87 +”
  88 +web蝟餌挽蝵
  89 +雿輻mysql雿蛹摨
55 90  
56 91 # 憿寧蝵
57 92 :[WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki)
... ...
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
... ... @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp;
3 3 import java.util.logging.LogManager;
4 4  
5 5 import org.springframework.boot.SpringApplication;
6   -import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
7 6 import org.springframework.boot.autoconfigure.SpringBootApplication;
8 7  
9 8 @SpringBootApplication
... ...
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
1 1 package com.genersoft.iot.vmp.common;
2 2  
3 3 /**
4   - * @Description:TODO(这里用一句话描述这个类的作用)
  4 + * @Description: 定义常量
5 5 * @author: swwheihei
6 6 * @date: 2019年5月30日 下午3:04:04
7 7 *
... ...
src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf;
  2 +
  3 +import org.springframework.beans.factory.annotation.Value;
  4 +import org.springframework.context.annotation.Configuration;
  5 +
  6 +@Configuration("userSetup")
  7 +public class UserSetup {
  8 + @Value("${userSettings.savePositionHistory}")
  9 + boolean savePositionHistory;
  10 +
  11 + public boolean getSavePositionHistory() {
  12 + return savePositionHistory;
  13 + }
  14 +
  15 + public void setSavePositionHistory(boolean savePositionHistory) {
  16 + this.savePositionHistory = savePositionHistory;
  17 + }
  18 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java
... ... @@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Value;
4 4 import org.springframework.context.annotation.Configuration;
5 5  
6 6 /**
7   - * @Description:TODO(这里用一句话描述这个类的作用)
  7 + * @Description: 获取数据库配置
8 8 * @author: swwheihei
9 9 * @date: 2020年5月6日 下午2:46:00
10 10 */
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
... ... @@ -149,8 +149,6 @@ public class SipLayer implements SipListener {
149 149 }
150 150 }
151 151 }
152   - // } else if (status == Response.TRYING) {
153   - // trying不会回复
154 152 } else if ((status >= 100) && (status < 200)) {
155 153 // 增加其它无需回复的响应,如101、180等
156 154 } else {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
... ... @@ -91,8 +91,10 @@ public class DigestServerAuthenticationHelper {
91 91 long time = date.getTime();
92 92 Random rand = new Random();
93 93 long pad = rand.nextLong();
94   - String nonceString = (new Long(time)).toString()
95   - + (new Long(pad)).toString();
  94 + // String nonceString = (new Long(time)).toString()
  95 + // + (new Long(pad)).toString();
  96 + String nonceString = Long.valueOf(time).toString()
  97 + + Long.valueOf(pad).toString();
96 98 byte mdbytes[] = messageDigest.digest(nonceString.getBytes());
97 99 // Convert the mdbytes array into a hex string.
98 100 return toHexString(mdbytes);
... ... @@ -191,7 +193,7 @@ public class DigestServerAuthenticationHelper {
191 193  
192 194 // 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。
193 195 // 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护
194   - String cNonce = authHeader.getCNonce();
  196 + //String cNonce = authHeader.getCNonce();
195 197  
196 198 // nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
197 199 int nc = authHeader.getNonceCount();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/BaiduPoint.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +public class BaiduPoint {
  4 +
  5 + String bdLng;
  6 +
  7 + String bdLat;
  8 +
  9 + public String getBdLng() {
  10 + return bdLng;
  11 + }
  12 +
  13 + public void setBdLng(String bdLng) {
  14 + this.bdLng = bdLng;
  15 + }
  16 +
  17 + public String getBdLat() {
  18 + return bdLat;
  19 + }
  20 +
  21 + public void setBdLat(String bdLat) {
  22 + this.bdLat = bdLat;
  23 + }
  24 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/MobilePosition.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * @Description: 移动位置bean
  5 + * @author: lawrencehj
  6 + * @date: 2021年1月23日
  7 + */
  8 +
  9 +public class MobilePosition {
  10 + /**
  11 + * 设备Id
  12 + */
  13 + private String deviceId;
  14 +
  15 + /**
  16 + * 设备名称
  17 + */
  18 + private String deviceName;
  19 +
  20 + /**
  21 + * 通知时间
  22 + */
  23 + private String time;
  24 +
  25 + /**
  26 + * 经度
  27 + */
  28 + private double longitude;
  29 +
  30 + /**
  31 + * 纬度
  32 + */
  33 + private double latitude;
  34 +
  35 + /**
  36 + * 海拔高度
  37 + */
  38 + private double altitude;
  39 +
  40 + /**
  41 + * 速度
  42 + */
  43 + private double speed;
  44 +
  45 + /**
  46 + * 方向
  47 + */
  48 + private double direction;
  49 +
  50 + /**
  51 + * 位置信息上报来源(Mobile Position、GPS Alarm)
  52 + */
  53 + private String reportSource;
  54 +
  55 + /**
  56 + * 国内地理坐标系(GCJ-02 / BD-09)
  57 + */
  58 + private String GeodeticSystem;
  59 +
  60 + /**
  61 + * 国内坐标系:经度坐标
  62 + */
  63 + private String cnLng;
  64 +
  65 + /**
  66 + * 国内坐标系:纬度坐标
  67 + */
  68 + private String cnLat;
  69 +
  70 +
  71 + public String getDeviceId() {
  72 + return deviceId;
  73 + }
  74 +
  75 + public void setDeviceId(String deviceId) {
  76 + this.deviceId = deviceId;
  77 + }
  78 +
  79 + public String getDeviceName() {
  80 + return deviceName;
  81 + }
  82 +
  83 + public void setDeviceName(String deviceName) {
  84 + this.deviceName = deviceName;
  85 + }
  86 +
  87 + public String getTime() {
  88 + return time;
  89 + }
  90 +
  91 + public void setTime(String time) {
  92 + this.time = time;
  93 + }
  94 +
  95 + public double getLongitude() {
  96 + return longitude;
  97 + }
  98 +
  99 + public void setLongitude(double longitude) {
  100 + this.longitude = longitude;
  101 + }
  102 +
  103 + public double getLatitude() {
  104 + return latitude;
  105 + }
  106 +
  107 + public void setLatitude(double latitude) {
  108 + this.latitude = latitude;
  109 + }
  110 +
  111 + public double getAltitude() {
  112 + return altitude;
  113 + }
  114 +
  115 + public void setAltitude(double altitude) {
  116 + this.altitude = altitude;
  117 + }
  118 +
  119 + public double getSpeed() {
  120 + return speed;
  121 + }
  122 +
  123 + public void setSpeed(double speed) {
  124 + this.speed = speed;
  125 + }
  126 +
  127 + public double getDirection() {
  128 + return direction;
  129 + }
  130 +
  131 + public void setDirection(double direction) {
  132 + this.direction = direction;
  133 + }
  134 +
  135 + public String getReportSource() {
  136 + return reportSource;
  137 + }
  138 +
  139 + public void setReportSource(String reportSource) {
  140 + this.reportSource = reportSource;
  141 + }
  142 +
  143 + public String getGeodeticSystem() {
  144 + return GeodeticSystem;
  145 + }
  146 +
  147 + public void setGeodeticSystem(String geodeticSystem) {
  148 + GeodeticSystem = geodeticSystem;
  149 + }
  150 +
  151 + public String getCnLng() {
  152 + return cnLng;
  153 + }
  154 +
  155 + public void setCnLng(String cnLng) {
  156 + this.cnLng = cnLng;
  157 + }
  158 +
  159 + public String getCnLat() {
  160 + return cnLat;
  161 + }
  162 +
  163 + public void setCnLat(String cnLat) {
  164 + this.cnLat = cnLat;
  165 + }
  166 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3 3  
4   -import gov.nist.javax.sip.header.SIPDate;
  4 +//import gov.nist.javax.sip.header.SIPDate;
5 5  
6 6 import java.util.List;
7 7  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
  3 +import gov.nist.core.InternalErrorHandler;
3 4 import gov.nist.javax.sip.header.SIPDate;
4 5  
  6 +import java.util.*;
  7 +
5 8 /**
6 9 * 重写jain sip的SIPDate解决与国标时间格式不一致的问题
7 10 */
8 11 public class WvpSipDate extends SIPDate {
9 12  
  13 + /**
  14 + *
  15 + */
  16 + private static final long serialVersionUID = 1L;
  17 +
  18 + private Calendar javaCal;
  19 +
10 20 public WvpSipDate(long timeMillis) {
11   - super(timeMillis);
  21 + this.javaCal = new GregorianCalendar(TimeZone.getDefault(), Locale.getDefault());
  22 + Date date = new Date(timeMillis);
  23 + this.javaCal.setTime(date);
  24 + this.wkday = this.javaCal.get(7);
  25 + switch(this.wkday) {
  26 + case 1:
  27 + this.sipWkDay = "Sun";
  28 + break;
  29 + case 2:
  30 + this.sipWkDay = "Mon";
  31 + break;
  32 + case 3:
  33 + this.sipWkDay = "Tue";
  34 + break;
  35 + case 4:
  36 + this.sipWkDay = "Wed";
  37 + break;
  38 + case 5:
  39 + this.sipWkDay = "Thu";
  40 + break;
  41 + case 6:
  42 + this.sipWkDay = "Fri";
  43 + break;
  44 + case 7:
  45 + this.sipWkDay = "Sat";
  46 + break;
  47 + default:
  48 + InternalErrorHandler.handleException("No date map for wkday " + this.wkday);
  49 + }
  50 +
  51 + this.day = this.javaCal.get(5);
  52 + this.month = this.javaCal.get(2);
  53 + switch(this.month) {
  54 + case 0:
  55 + this.sipMonth = "Jan";
  56 + break;
  57 + case 1:
  58 + this.sipMonth = "Feb";
  59 + break;
  60 + case 2:
  61 + this.sipMonth = "Mar";
  62 + break;
  63 + case 3:
  64 + this.sipMonth = "Apr";
  65 + break;
  66 + case 4:
  67 + this.sipMonth = "May";
  68 + break;
  69 + case 5:
  70 + this.sipMonth = "Jun";
  71 + break;
  72 + case 6:
  73 + this.sipMonth = "Jul";
  74 + break;
  75 + case 7:
  76 + this.sipMonth = "Aug";
  77 + break;
  78 + case 8:
  79 + this.sipMonth = "Sep";
  80 + break;
  81 + case 9:
  82 + this.sipMonth = "Oct";
  83 + break;
  84 + case 10:
  85 + this.sipMonth = "Nov";
  86 + break;
  87 + case 11:
  88 + this.sipMonth = "Dec";
  89 + break;
  90 + default:
  91 + InternalErrorHandler.handleException("No date map for month " + this.month);
  92 + }
  93 +
  94 + this.year = this.javaCal.get(1);
  95 + this.hour = this.javaCal.get(11);
  96 + this.minute = this.javaCal.get(12);
  97 + this.second = this.javaCal.get(13);
12 98 }
13 99  
14 100 @Override
... ... @@ -48,7 +134,7 @@ public class WvpSipDate extends SIPDate {
48 134 var6 = "" + this.second;
49 135 }
50 136  
51   - int var8 = this.getJavaCal().get(14);
  137 + int var8 = this.javaCal.get(14);
52 138 String var7;
53 139 if (var8 < 10) {
54 140 var7 = "00" + var8;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
... ... @@ -65,4 +65,5 @@ public class EventPublisher {
65 65 alarmEvent.setAlarmInfo(deviceAlarm);
66 66 applicationEventPublisher.publishEvent(alarmEvent);
67 67 }
  68 +
68 69 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
1 1 package com.genersoft.iot.vmp.gb28181.event;
2 2  
3   -import com.alibaba.fastjson.JSONObject;
4   -import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
5   -import org.slf4j.Logger;
6   -import org.slf4j.LoggerFactory;
7 3 import org.springframework.stereotype.Component;
8 4  
9 5 import javax.sip.ResponseEvent;
10   -import javax.sip.message.Request;
11   -import java.util.EventObject;
12 6 import java.util.Map;
13 7 import java.util.concurrent.ConcurrentHashMap;
14 8  
15 9 @Component
16 10 public class SipSubscribe {
17 11  
18   - private final static Logger logger = LoggerFactory.getLogger(SipSubscribe.class);
19   -
20 12 private Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>();
21 13  
22 14 private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java
... ... @@ -10,6 +10,11 @@ import org.springframework.context.ApplicationEvent;
10 10 */
11 11  
12 12 public class AlarmEvent extends ApplicationEvent {
  13 + /**
  14 + *
  15 + */
  16 + private static final long serialVersionUID = 1L;
  17 +
13 18 public AlarmEvent(Object source) {
14 19 super(source);
15 20 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java
... ... @@ -3,18 +3,17 @@ package com.genersoft.iot.vmp.gb28181.event.offline;
3 3 import org.springframework.context.ApplicationEvent;
4 4  
5 5 /**
6   - * @Description:TODO(这里用一句话描述这个类的作用)
  6 + * @Description: 离线事件类
7 7 * @author: swwheihei
8 8 * @date: 2020年5月6日 上午11:33:13
9 9 */
10 10 public class OfflineEvent extends ApplicationEvent {
11 11  
12   - /**
13   - * @Title: OutlineEvent
14   - * @Description: TODO(这里用一句话描述这个方法的作用)
15   - * @param: @param source
16   - * @throws
17   - */
  12 + /**
  13 + *
  14 + */
  15 + private static final long serialVersionUID = 1L;
  16 +
18 17 public OfflineEvent(Object source) {
19 18 super(source);
20 19 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java
... ... @@ -3,18 +3,17 @@ package com.genersoft.iot.vmp.gb28181.event.online;
3 3 import org.springframework.context.ApplicationEvent;
4 4  
5 5 /**
6   - * @Description:TODO(这里用一句话描述这个类的作用)
  6 + * @Description: 在线事件类
7 7 * @author: swwheihei
8 8 * @date: 2020年5月6日 上午11:32:56
9 9 */
10 10 public class OnlineEvent extends ApplicationEvent {
11 11  
12   - /**
13   - * @Title: OnlineEvent
14   - * @Description: TODO(这里用一句话描述这个方法的作用)
15   - * @param: @param source
16   - * @throws
17   - */
  12 + /**
  13 + *
  14 + */
  15 + private static final long serialVersionUID = 1L;
  16 +
18 17 public OnlineEvent(Object source) {
19 18 super(source);
20 19 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
... ... @@ -19,6 +19,8 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
19 19 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
20 20 import org.slf4j.Logger;
21 21 import org.slf4j.LoggerFactory;
  22 +// import org.slf4j.Logger;
  23 +// import org.slf4j.LoggerFactory;
22 24 import org.springframework.beans.factory.annotation.Autowired;
23 25 import org.springframework.beans.factory.annotation.Qualifier;
24 26 import org.springframework.context.annotation.Lazy;
... ... @@ -36,6 +38,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor;
36 38 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor;
37 39 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor;
38 40 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
  41 +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor;
39 42 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor;
40 43 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor;
41 44 import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor;
... ... @@ -49,7 +52,7 @@ import com.genersoft.iot.vmp.utils.SpringBeanFactory;
49 52 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
50 53  
51 54 /**
52   - * @Description:TODO(这里用一句话描述这个类的作用)
  55 + * @Description: SIP信令处理分配
53 56 * @author: swwheihei
54 57 * @date: 2020年5月3日 下午4:24:37
55 58 */
... ... @@ -78,7 +81,7 @@ public class SIPProcessorFactory {
78 81  
79 82 @Autowired
80 83 private SIPCommanderFroPlatform cmderFroPlatform;
81   -
  84 +
82 85 @Autowired
83 86 private RedisUtil redis;
84 87  
... ... @@ -122,6 +125,7 @@ public class SIPProcessorFactory {
122 125 Request request = evt.getRequest();
123 126 String method = request.getMethod();
124 127 // logger.info("接收到消息:"+request.getMethod());
  128 +// sipSubscribe.getSubscribe(evt.getServerTransaction().getBranchId()).response(evt);
125 129 if (Request.INVITE.equals(method)) {
126 130 InviteRequestProcessor processor = new InviteRequestProcessor();
127 131 processor.setRequestEvent(evt);
... ... @@ -161,7 +165,6 @@ public class SIPProcessorFactory {
161 165 processor.setRequestEvent(evt);
162 166 return processor;
163 167 } else if (Request.MESSAGE.equals(method)) {
164   -
165 168 MessageRequestProcessor processor = new MessageRequestProcessor();
166 169 processor.setRequestEvent(evt);
167 170 processor.setTcpSipProvider(getTcpSipProvider());
... ... @@ -175,8 +178,23 @@ public class SIPProcessorFactory {
175 178 processor.setStorager(storager);
176 179 processor.setRedisCatchStorage(redisCatchStorage);
177 180 return processor;
  181 + } else if (Request.NOTIFY.equalsIgnoreCase(method)) {
  182 + NotifyRequestProcessor processor = new NotifyRequestProcessor();
  183 + processor.setRequestEvent(evt);
  184 + processor.setTcpSipProvider(getTcpSipProvider());
  185 + processor.setUdpSipProvider(getUdpSipProvider());
  186 + processor.setPublisher(publisher);
  187 + processor.setRedis(redis);
  188 + processor.setDeferredResultHolder(deferredResultHolder);
  189 + processor.setOffLineDetector(offLineDetector);
  190 + processor.setCmder(cmder);
  191 + processor.setStorager(storager);
  192 + processor.setRedisCatchStorage(redisCatchStorage);
  193 + return processor;
178 194 } else {
179   - return new OtherRequestProcessor();
  195 + OtherRequestProcessor processor = new OtherRequestProcessor();
  196 + processor.setRequestEvent(evt);
  197 + return processor;
180 198 }
181 199 }
182 200  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.transmit.callback;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Comparator;
  5 +import java.util.List;
  6 +import java.util.concurrent.TimeUnit;
  7 +
  8 +import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
  9 +import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
  10 +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
  11 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
  12 +
  13 +import org.slf4j.Logger;
  14 +
  15 +@SuppressWarnings("unchecked")
  16 +public class CheckForAllRecordsThread extends Thread {
  17 +
  18 + private String key;
  19 +
  20 + private RecordInfo recordInfo;
  21 +
  22 + private RedisUtil redis;
  23 +
  24 + private Logger logger;
  25 +
  26 + private DeferredResultHolder deferredResultHolder;
  27 +
  28 + public CheckForAllRecordsThread(String key, RecordInfo recordInfo) {
  29 + this.key = key;
  30 + this.recordInfo = recordInfo;
  31 + }
  32 +
  33 + public void run() {
  34 +
  35 + String cacheKey = this.key;
  36 +
  37 + for (long stop = System.nanoTime() + TimeUnit.SECONDS.toNanos(10); stop > System.nanoTime();) {
  38 + List<Object> cacheKeys = redis.scan(cacheKey + "_*");
  39 + List<RecordItem> totalRecordList = new ArrayList<RecordItem>();
  40 + for (int i = 0; i < cacheKeys.size(); i++) {
  41 + totalRecordList.addAll((List<RecordItem>) redis.get(cacheKeys.get(i).toString()));
  42 + }
  43 + if (totalRecordList.size() < this.recordInfo.getSumNum()) {
  44 + logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + this.recordInfo.getSumNum() + "项");
  45 + } else {
  46 + logger.info("录像数据已全部获取,共" + this.recordInfo.getSumNum() + "项");
  47 + this.recordInfo.setRecordList(totalRecordList);
  48 + for (int i = 0; i < cacheKeys.size(); i++) {
  49 + redis.del(cacheKeys.get(i).toString());
  50 + }
  51 + break;
  52 + }
  53 + }
  54 + // 自然顺序排序, 元素进行升序排列
  55 + this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
  56 + RequestMessage msg = new RequestMessage();
  57 + String deviceId = recordInfo.getDeviceId();
  58 + msg.setDeviceId(deviceId);
  59 + msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
  60 + msg.setData(recordInfo);
  61 + deferredResultHolder.invokeResult(msg);
  62 + logger.info("处理完成,返回结果");
  63 + MessageRequestProcessor.threadNameList.remove(cacheKey);
  64 + }
  65 +
  66 + public void setRedis(RedisUtil redis) {
  67 + this.redis = redis;
  68 + }
  69 +
  70 + public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) {
  71 + this.deferredResultHolder = deferredResultHolder;
  72 + }
  73 +
  74 + public void setLogger(Logger logger) {
  75 + this.logger = logger;
  76 + }
  77 +
  78 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.callback;
2 2  
3   -import java.util.HashMap;
4 3 import java.util.Map;
5 4 import java.util.concurrent.ConcurrentHashMap;
6 5  
... ... @@ -10,15 +9,24 @@ import org.springframework.stereotype.Component;
10 9 import org.springframework.web.context.request.async.DeferredResult;
11 10  
12 11 /**
13   - * @Description:TODO(这里用一句话描述这个类的作用)
  12 + * @Description: 异步请求处理
14 13 * @author: swwheihei
15 14 * @date: 2020年5月8日 下午7:59:05
16 15 */
  16 +@SuppressWarnings(value = {"rawtypes", "unchecked"})
17 17 @Component
18 18 public class DeferredResultHolder {
19 19  
  20 + public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS";
  21 +
20 22 public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
21 23  
  24 + public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL";
  25 +
  26 + public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG";
  27 +
  28 + public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD";
  29 +
22 30 public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
23 31  
24 32 public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
... ... @@ -27,6 +35,12 @@ public class DeferredResultHolder {
27 35  
28 36 public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
29 37  
  38 + public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
  39 +
  40 + public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
  41 +
  42 + public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
  43 +
30 44 private Map<String, DeferredResult> map = new ConcurrentHashMap<String, DeferredResult>();
31 45  
32 46 public void put(String key, DeferredResult result) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.callback;
2 2  
3 3 /**
4   - * @Description:TODO(这里用一句话描述这个类的作用)
  4 + * @Description: 请求信息定义
5 5 * @author: swwheihei
6 6 * @date: 2020年5月8日 下午1:09:18
7 7 */
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3   -import com.genersoft.iot.vmp.common.StreamInfo;
4 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 5 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
... ... @@ -115,24 +114,35 @@ public interface ISIPCommander {
115 114 /**
116 115 * 音视频录像控制
117 116 *
118   - * @param device 视频设备
119   - * @param channelId 预览通道
  117 + * @param device 视频设备
  118 + * @param channelId 预览通道
  119 + * @param recordCmdStr 录像命令:Record / StopRecord
120 120 */
121   - boolean recordCmd(Device device,String channelId);
  121 + boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent);
122 122  
123 123 /**
  124 + * 远程启动控制命令
  125 + *
  126 + * @param device 视频设备
  127 + */
  128 + boolean teleBootCmd(Device device);
  129 +
  130 + /**
124 131 * 报警布防/撤防命令
125 132 *
126   - * @param device 视频设备
  133 + * @param device 视频设备
  134 + * @param setGuard true: SetGuard, false: ResetGuard
127 135 */
128   - boolean guardCmd(Device device);
  136 + boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent);
129 137  
130 138 /**
131 139 * 报警复位命令
132 140 *
133   - * @param device 视频设备
  141 + * @param device 视频设备
  142 + * @param alarmMethod 报警方式(可选)
  143 + * @param alarmType 报警类型(可选)
134 144 */
135   - boolean alarmCmd(Device device);
  145 + boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent);
136 146  
137 147 /**
138 148 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
... ... @@ -140,14 +150,17 @@ public interface ISIPCommander {
140 150 * @param device 视频设备
141 151 * @param channelId 预览通道
142 152 */
143   - boolean iFameCmd(Device device,String channelId);
  153 + boolean iFrameCmd(Device device, String channelId);
144 154  
145 155 /**
146 156 * 看守位控制命令
147 157 *
148   - * @param device 视频设备
  158 + * @param device 视频设备
  159 + * @param enabled 看守位使能:1 = 开启,0 = 关闭
  160 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
  161 + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
149 162 */
150   - boolean homePositionCmd(Device device);
  163 + boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent);
151 164  
152 165 /**
153 166 * 设备配置命令
... ... @@ -156,13 +169,24 @@ public interface ISIPCommander {
156 169 */
157 170 boolean deviceConfigCmd(Device device);
158 171  
  172 + /**
  173 + * 设备配置命令:basicParam
  174 + *
  175 + * @param device 视频设备
  176 + * @param channelId 通道编码(可选)
  177 + * @param name 设备/通道名称(可选)
  178 + * @param expiration 注册过期时间(可选)
  179 + * @param heartBeatInterval 心跳间隔时间(可选)
  180 + * @param heartBeatCount 心跳超时次数(可选)
  181 + */
  182 + boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent);
159 183  
160 184 /**
161 185 * 查询设备状态
162 186 *
163 187 * @param device 视频设备
164 188 */
165   - boolean deviceStatusQuery(Device device);
  189 + boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent);
166 190  
167 191 /**
168 192 * 查询设备信息
... ... @@ -191,30 +215,65 @@ public interface ISIPCommander {
191 215 /**
192 216 * 查询报警信息
193 217 *
194   - * @param device 视频设备
  218 + * @param device 视频设备
  219 + * @param startPriority 报警起始级别(可选)
  220 + * @param endPriority 报警终止级别(可选)
  221 + * @param alarmMethod 报警方式条件(可选)
  222 + * @param alarmType 报警类型
  223 + * @param startTime 报警发生起始时间(可选)
  224 + * @param endTime 报警发生终止时间(可选)
  225 + * @return true = 命令发送成功
195 226 */
196   - boolean alarmInfoQuery(Device device);
  227 + boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
  228 + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent);
197 229  
198 230 /**
199 231 * 查询设备配置
200 232 *
201   - * @param device 视频设备
  233 + * @param device 视频设备
  234 + * @param channelId 通道编码(可选)
  235 + * @param configType 配置类型:
202 236 */
203   - boolean configQuery(Device device);
  237 + boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent);
204 238  
205 239 /**
206 240 * 查询设备预置位置
207 241 *
208 242 * @param device 视频设备
209 243 */
210   - boolean presetQuery(Device device);
  244 + boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent);
211 245  
212 246 /**
213 247 * 查询移动设备位置数据
214 248 *
215 249 * @param device 视频设备
216 250 */
217   - boolean mobilePostitionQuery(Device device);
  251 + boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent);
  252 +
  253 + /**
  254 + * 订阅、取消订阅移动位置
  255 + *
  256 + * @param device 视频设备
  257 + * @param expires 订阅超时时间(值=0时为取消订阅)
  258 + * @param interval 上报时间间隔
  259 + * @return true = 命令发送成功
  260 + */
  261 + boolean mobilePositionSubscribe(Device device, int expires, int interval);
  262 +
  263 + /**
  264 + * 订阅、取消订阅报警信息
  265 + * @param device 视频设备
  266 + * @param expires 订阅过期时间(0 = 取消订阅)
  267 + * @param startPriority 报警起始级别(可选)
  268 + * @param endPriority 报警终止级别(可选)
  269 + * @param alarmMethods 报警方式条件(可选)
  270 + * @param alarmType 报警类型
  271 + * @param startTime 报警发生起始时间(可选)
  272 + * @param endTime 报警发生终止时间(可选)
  273 + * @return true = 命令发送成功
  274 + */
  275 + boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
  276 +
218 277  
219 278 /**
220 279 * 释放rtpserver
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -168,4 +168,51 @@ public class SIPRequestHeaderProvider {
168 168 request.setContent(content, contentTypeHeader);
169 169 return request;
170 170 }
  171 +
  172 + public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event) throws ParseException, InvalidArgumentException, PeerUnavailableException {
  173 + Request request = null;
  174 + // sipuri
  175 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
  176 + // via
  177 + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
  178 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
  179 + device.getTransport(), viaTag);
  180 + viaHeader.setRPort();
  181 + viaHeaders.add(viaHeader);
  182 + // from
  183 + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),
  184 + sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
  185 + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  186 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
  187 + // to
  188 + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain());
  189 + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  190 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
  191 + // callid
  192 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  193 + : udpSipProvider.getNewCallId();
  194 + // Forwards
  195 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  196 + // ceq
  197 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.SUBSCRIBE);
  198 +
  199 + request = sipFactory.createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
  200 + toHeader, viaHeaders, maxForwards);
  201 +
  202 +
  203 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
  204 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  205 +
  206 + // Expires
  207 + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(expires);
  208 + request.addHeader(expireHeader);
  209 +
  210 + // Event
  211 + EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
  212 + request.addHeader(eventHeader);
  213 +
  214 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
  215 + request.setContent(content, contentTypeHeader);
  216 + return request;
  217 + }
171 218 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2  
3 3 import java.text.ParseException;
4   -import java.util.UUID;
5 4 import java.util.regex.Matcher;
6 5 import java.util.regex.Pattern;
7 6  
8 7 import javax.sip.*;
9 8 import javax.sip.address.SipURI;
10 9 import javax.sip.header.CallIdHeader;
11   -import javax.sip.header.Header;
12 10 import javax.sip.header.ViaHeader;
13 11 import javax.sip.message.Request;
14 12  
15 13 import com.alibaba.fastjson.JSONObject;
16 14 import com.genersoft.iot.vmp.common.StreamInfo;
17 15 import com.genersoft.iot.vmp.conf.MediaServerConfig;
18   -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
19 16 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
20 17 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
21 18 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
... ... @@ -34,6 +31,8 @@ import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
34 31 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
35 32 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
36 33 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
  34 +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
  35 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
37 36  
38 37 /**
39 38 * @Description:设备能力接口,用于定义设备的控制、查询能力
... ... @@ -235,7 +234,8 @@ public class SIPCommander implements ISIPCommander {
235 234 ptzXml.append("</Info>\r\n");
236 235 ptzXml.append("</Control>\r\n");
237 236  
238   - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", null);
  237 + String tm = Long.toString(System.currentTimeMillis());
  238 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null);
239 239  
240 240 transmitRequest(device, request);
241 241 return true;
... ... @@ -271,7 +271,8 @@ public class SIPCommander implements ISIPCommander {
271 271 ptzXml.append("</Info>\r\n");
272 272 ptzXml.append("</Control>\r\n");
273 273  
274   - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", null);
  274 + String tm = Long.toString(System.currentTimeMillis());
  275 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null);
275 276 transmitRequest(device, request);
276 277 return true;
277 278 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -383,7 +384,8 @@ public class SIPCommander implements ISIPCommander {
383 384  
384 385 content.append("y="+ssrc+"\r\n");//ssrc
385 386  
386   - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "live", null, ssrc);
  387 + String tm = Long.toString(System.currentTimeMillis());
  388 + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc);
387 389  
388 390 ClientTransaction transaction = transmitRequest(device, request, errorEvent);
389 391 streamSession.put(streamId, transaction);
... ... @@ -482,7 +484,8 @@ public class SIPCommander implements ISIPCommander {
482 484  
483 485 content.append("y="+ssrc+"\r\n");//ssrc
484 486  
485   - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "playback", null);
  487 + String tm = Long.toString(System.currentTimeMillis());
  488 + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null);
486 489  
487 490 ClientTransaction transaction = transmitRequest(device, request, errorEvent);
488 491 streamSession.put(streamId, transaction);
... ... @@ -573,24 +576,89 @@ public class SIPCommander implements ISIPCommander {
573 576 /**
574 577 * 音视频录像控制
575 578 *
576   - * @param device 视频设备
577   - * @param channelId 预览通道
  579 + * @param device 视频设备
  580 + * @param channelId 预览通道
  581 + * @param recordCmdStr 录像命令:Record / StopRecord
578 582 */
579 583 @Override
580   - public boolean recordCmd(Device device, String channelId) {
581   - // TODO Auto-generated method stub
582   - return false;
  584 + public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) {
  585 + try {
  586 + StringBuffer cmdXml = new StringBuffer(200);
  587 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  588 + cmdXml.append("<Control>\r\n");
  589 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  590 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  591 + if (XmlUtil.isEmpty(channelId)) {
  592 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  593 + } else {
  594 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  595 + }
  596 + cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
  597 + cmdXml.append("</Control>\r\n");
  598 +
  599 + String tm = Long.toString(System.currentTimeMillis());
  600 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromRecord" + tm, null);
  601 + transmitRequest(device, request, errorEvent);
  602 + return true;
  603 + } catch (SipException | ParseException | InvalidArgumentException e) {
  604 + e.printStackTrace();
  605 + return false;
  606 + }
583 607 }
584 608  
585 609 /**
  610 + * 远程启动控制命令
  611 + *
  612 + * @param device 视频设备
  613 + */
  614 + @Override
  615 + public boolean teleBootCmd(Device device) {
  616 + try {
  617 + StringBuffer cmdXml = new StringBuffer(200);
  618 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  619 + cmdXml.append("<Control>\r\n");
  620 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  621 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  622 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  623 + cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");
  624 + cmdXml.append("</Control>\r\n");
  625 +
  626 + String tm = Long.toString(System.currentTimeMillis());
  627 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null);
  628 + transmitRequest(device, request);
  629 + return true;
  630 + } catch (SipException | ParseException | InvalidArgumentException e) {
  631 + e.printStackTrace();
  632 + return false;
  633 + }
  634 + }
  635 +
  636 + /**
586 637 * 报警布防/撤防命令
587 638 *
588   - * @param device 视频设备
589   - */
  639 + * @param device 视频设备
  640 + * @param guardCmdStr "SetGuard"/"ResetGuard"
  641 + */
590 642 @Override
591   - public boolean guardCmd(Device device) {
592   - // TODO Auto-generated method stub
593   - return false;
  643 + public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) {
  644 + try {
  645 + StringBuffer cmdXml = new StringBuffer(200);
  646 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  647 + cmdXml.append("<Control>\r\n");
  648 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  649 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  650 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  651 + cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
  652 + cmdXml.append("</Control>\r\n");
  653 +
  654 + String tm = Long.toString(System.currentTimeMillis());
  655 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null);
  656 + transmitRequest(device, request, errorEvent);
  657 + return true;
  658 + } catch (SipException | ParseException | InvalidArgumentException e) {
  659 + e.printStackTrace();
  660 + return false;
  661 + }
594 662 }
595 663  
596 664 /**
... ... @@ -599,9 +667,37 @@ public class SIPCommander implements ISIPCommander {
599 667 * @param device 视频设备
600 668 */
601 669 @Override
602   - public boolean alarmCmd(Device device) {
603   - // TODO Auto-generated method stub
604   - return false;
  670 + public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) {
  671 + try {
  672 + StringBuffer cmdXml = new StringBuffer(200);
  673 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  674 + cmdXml.append("<Control>\r\n");
  675 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  676 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  677 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  678 + cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
  679 + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) {
  680 + cmdXml.append("<Info>\r\n");
  681 + }
  682 + if (!XmlUtil.isEmpty(alarmMethod)) {
  683 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  684 + }
  685 + if (!XmlUtil.isEmpty(alarmType)) {
  686 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  687 + }
  688 + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) {
  689 + cmdXml.append("</Info>\r\n");
  690 + }
  691 + cmdXml.append("</Control>\r\n");
  692 +
  693 + String tm = Long.toString(System.currentTimeMillis());
  694 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null);
  695 + transmitRequest(device, request, errorEvent);
  696 + return true;
  697 + } catch (SipException | ParseException | InvalidArgumentException e) {
  698 + e.printStackTrace();
  699 + return false;
  700 + }
605 701 }
606 702  
607 703 /**
... ... @@ -611,20 +707,79 @@ public class SIPCommander implements ISIPCommander {
611 707 * @param channelId 预览通道
612 708 */
613 709 @Override
614   - public boolean iFameCmd(Device device, String channelId) {
615   - // TODO Auto-generated method stub
616   - return false;
  710 + public boolean iFrameCmd(Device device, String channelId) {
  711 + try {
  712 + StringBuffer cmdXml = new StringBuffer(200);
  713 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  714 + cmdXml.append("<Control>\r\n");
  715 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  716 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  717 + if (XmlUtil.isEmpty(channelId)) {
  718 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  719 + } else {
  720 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  721 + }
  722 + cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");
  723 + cmdXml.append("</Control>\r\n");
  724 +
  725 + String tm = Long.toString(System.currentTimeMillis());
  726 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null);
  727 + transmitRequest(device, request);
  728 + return true;
  729 + } catch (SipException | ParseException | InvalidArgumentException e) {
  730 + e.printStackTrace();
  731 + return false;
  732 + }
617 733 }
618 734  
619 735 /**
620 736 * 看守位控制命令
621 737 *
622   - * @param device 视频设备
  738 + * @param device 视频设备
  739 + * @param enabled 看守位使能:1 = 开启,0 = 关闭
  740 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
  741 + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
623 742 */
624 743 @Override
625   - public boolean homePositionCmd(Device device) {
626   - // TODO Auto-generated method stub
627   - return false;
  744 + public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) {
  745 + try {
  746 + StringBuffer cmdXml = new StringBuffer(200);
  747 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  748 + cmdXml.append("<Control>\r\n");
  749 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  750 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  751 + if (XmlUtil.isEmpty(channelId)) {
  752 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  753 + } else {
  754 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  755 + }
  756 + cmdXml.append("<HomePosition>\r\n");
  757 + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
  758 + cmdXml.append("<Enabled>1</Enabled>\r\n");
  759 + if (NumericUtil.isInteger(resetTime)) {
  760 + cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
  761 + } else {
  762 + cmdXml.append("<ResetTime>0</ResetTime>\r\n");
  763 + }
  764 + if (NumericUtil.isInteger(presetIndex)) {
  765 + cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
  766 + } else {
  767 + cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
  768 + }
  769 + } else {
  770 + cmdXml.append("<Enabled>0</Enabled>\r\n");
  771 + }
  772 + cmdXml.append("</HomePosition>\r\n");
  773 + cmdXml.append("</Control>\r\n");
  774 +
  775 + String tm = Long.toString(System.currentTimeMillis());
  776 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null);
  777 + transmitRequest(device, request, errorEvent);
  778 + return true;
  779 + } catch (SipException | ParseException | InvalidArgumentException e) {
  780 + e.printStackTrace();
  781 + return false;
  782 + }
628 783 }
629 784  
630 785 /**
... ... @@ -639,14 +794,87 @@ public class SIPCommander implements ISIPCommander {
639 794 }
640 795  
641 796 /**
  797 + * 设备配置命令:basicParam
  798 + *
  799 + * @param device 视频设备
  800 + * @param channelId 通道编码(可选)
  801 + * @param name 设备/通道名称(可选)
  802 + * @param expiration 注册过期时间(可选)
  803 + * @param heartBeatInterval 心跳间隔时间(可选)
  804 + * @param heartBeatCount 心跳超时次数(可选)
  805 + */
  806 + @Override
  807 + public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration,
  808 + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) {
  809 + try {
  810 + StringBuffer cmdXml = new StringBuffer(200);
  811 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  812 + cmdXml.append("<Control>\r\n");
  813 + cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
  814 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  815 + if (XmlUtil.isEmpty(channelId)) {
  816 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  817 + } else {
  818 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  819 + }
  820 + cmdXml.append("<BasicParam>\r\n");
  821 + if (!XmlUtil.isEmpty(name)) {
  822 + cmdXml.append("<Name>" + name + "</Name>\r\n");
  823 + }
  824 + if (NumericUtil.isInteger(expiration)) {
  825 + if (Integer.valueOf(expiration) > 0) {
  826 + cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");
  827 + }
  828 + }
  829 + if (NumericUtil.isInteger(heartBeatInterval)) {
  830 + if (Integer.valueOf(heartBeatInterval) > 0) {
  831 + cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
  832 + }
  833 + }
  834 + if (NumericUtil.isInteger(heartBeatCount)) {
  835 + if (Integer.valueOf(heartBeatCount) > 0) {
  836 + cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
  837 + }
  838 + }
  839 + cmdXml.append("</BasicParam>\r\n");
  840 + cmdXml.append("</Control>\r\n");
  841 +
  842 + String tm = Long.toString(System.currentTimeMillis());
  843 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null);
  844 + transmitRequest(device, request, errorEvent);
  845 + return true;
  846 + } catch (SipException | ParseException | InvalidArgumentException e) {
  847 + e.printStackTrace();
  848 + return false;
  849 + }
  850 + }
  851 +
  852 + /**
642 853 * 查询设备状态
643 854 *
644 855 * @param device 视频设备
645 856 */
646 857 @Override
647   - public boolean deviceStatusQuery(Device device) {
648   - // TODO Auto-generated method stub
649   - return false;
  858 + public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) {
  859 + try {
  860 + StringBuffer catalogXml = new StringBuffer(200);
  861 + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  862 + catalogXml.append("<Query>\r\n");
  863 + catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
  864 + catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  865 + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  866 + catalogXml.append("</Query>\r\n");
  867 +
  868 + String tm = Long.toString(System.currentTimeMillis());
  869 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, "FromStatus" + tm, null);
  870 +
  871 + transmitRequest(device, request, errorEvent);
  872 + return true;
  873 +
  874 + } catch (SipException | ParseException | InvalidArgumentException e) {
  875 + e.printStackTrace();
  876 + return false;
  877 + }
650 878 }
651 879  
652 880 /**
... ... @@ -665,7 +893,8 @@ public class SIPCommander implements ISIPCommander {
665 893 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
666 894 catalogXml.append("</Query>\r\n");
667 895  
668   - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", null);
  896 + String tm = Long.toString(System.currentTimeMillis());
  897 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDev" + tm, null);
669 898  
670 899 transmitRequest(device, request);
671 900  
... ... @@ -694,7 +923,8 @@ public class SIPCommander implements ISIPCommander {
694 923 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
695 924 catalogXml.append("</Query>\r\n");
696 925  
697   - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", null);
  926 + String tm = Long.toString(System.currentTimeMillis());
  927 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCat" + tm, null);
698 928  
699 929 transmitRequest(device, request, errorEvent);
700 930 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -728,7 +958,8 @@ public class SIPCommander implements ISIPCommander {
728 958 recordInfoXml.append("<Type>all</Type>\r\n");
729 959 recordInfoXml.append("</Query>\r\n");
730 960  
731   - Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", null);
  961 + String tm = Long.toString(System.currentTimeMillis());
  962 + Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "fromRec" + tm, null);
732 963  
733 964 transmitRequest(device, request);
734 965 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -741,23 +972,86 @@ public class SIPCommander implements ISIPCommander {
741 972 /**
742 973 * 查询报警信息
743 974 *
744   - * @param device 视频设备
745   - */
  975 + * @param device 视频设备
  976 + * @param startPriority 报警起始级别(可选)
  977 + * @param endPriority 报警终止级别(可选)
  978 + * @param alarmMethods 报警方式条件(可选)
  979 + * @param alarmType 报警类型
  980 + * @param startTime 报警发生起始时间(可选)
  981 + * @param endTime 报警发生终止时间(可选)
  982 + * @return true = 命令发送成功
  983 + */
746 984 @Override
747   - public boolean alarmInfoQuery(Device device) {
748   - // TODO Auto-generated method stub
749   - return false;
  985 + public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,
  986 + String startTime, String endTime, SipSubscribe.Event errorEvent) {
  987 + try {
  988 + StringBuffer cmdXml = new StringBuffer(200);
  989 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  990 + cmdXml.append("<Query>\r\n");
  991 + cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
  992 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  993 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  994 + if (!XmlUtil.isEmpty(startPriority)) {
  995 + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
  996 + }
  997 + if (!XmlUtil.isEmpty(endPriority)) {
  998 + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
  999 + }
  1000 + if (!XmlUtil.isEmpty(alarmMethod)) {
  1001 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  1002 + }
  1003 + if (!XmlUtil.isEmpty(alarmType)) {
  1004 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  1005 + }
  1006 + if (!XmlUtil.isEmpty(startTime)) {
  1007 + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
  1008 + }
  1009 + if (!XmlUtil.isEmpty(endTime)) {
  1010 + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
  1011 + }
  1012 + cmdXml.append("</Query>\r\n");
  1013 +
  1014 + String tm = Long.toString(System.currentTimeMillis());
  1015 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null);
  1016 + transmitRequest(device, request, errorEvent);
  1017 + return true;
  1018 + } catch (SipException | ParseException | InvalidArgumentException e) {
  1019 + e.printStackTrace();
  1020 + return false;
  1021 + }
750 1022 }
751 1023  
752 1024 /**
753 1025 * 查询设备配置
754 1026 *
755   - * @param device 视频设备
756   - */
  1027 + * @param device 视频设备
  1028 + * @param channelId 通道编码(可选)
  1029 + * @param configType 配置类型:
  1030 + */
757 1031 @Override
758   - public boolean configQuery(Device device) {
759   - // TODO Auto-generated method stub
760   - return false;
  1032 + public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) {
  1033 + try {
  1034 + StringBuffer cmdXml = new StringBuffer(200);
  1035 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1036 + cmdXml.append("<Query>\r\n");
  1037 + cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
  1038 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1039 + if (XmlUtil.isEmpty(channelId)) {
  1040 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1041 + } else {
  1042 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1043 + }
  1044 + cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
  1045 + cmdXml.append("</Query>\r\n");
  1046 +
  1047 + String tm = Long.toString(System.currentTimeMillis());
  1048 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null);
  1049 + transmitRequest(device, request, errorEvent);
  1050 + return true;
  1051 + } catch (SipException | ParseException | InvalidArgumentException e) {
  1052 + e.printStackTrace();
  1053 + return false;
  1054 + }
761 1055 }
762 1056  
763 1057 /**
... ... @@ -766,9 +1060,28 @@ public class SIPCommander implements ISIPCommander {
766 1060 * @param device 视频设备
767 1061 */
768 1062 @Override
769   - public boolean presetQuery(Device device) {
770   - // TODO Auto-generated method stub
771   - return false;
  1063 + public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) {
  1064 + try {
  1065 + StringBuffer cmdXml = new StringBuffer(200);
  1066 + cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1067 + cmdXml.append("<Query>\r\n");
  1068 + cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
  1069 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1070 + if (XmlUtil.isEmpty(channelId)) {
  1071 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1072 + } else {
  1073 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1074 + }
  1075 + cmdXml.append("</Query>\r\n");
  1076 +
  1077 + String tm = Long.toString(System.currentTimeMillis());
  1078 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null);
  1079 + transmitRequest(device, request, errorEvent);
  1080 + return true;
  1081 + } catch (SipException | ParseException | InvalidArgumentException e) {
  1082 + e.printStackTrace();
  1083 + return false;
  1084 + }
772 1085 }
773 1086  
774 1087 /**
... ... @@ -777,11 +1090,116 @@ public class SIPCommander implements ISIPCommander {
777 1090 * @param device 视频设备
778 1091 */
779 1092 @Override
780   - public boolean mobilePostitionQuery(Device device) {
781   - // TODO Auto-generated method stub
782   - return false;
  1093 + public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) {
  1094 + try {
  1095 + StringBuffer mobilePostitionXml = new StringBuffer(200);
  1096 + mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1097 + mobilePostitionXml.append("<Query>\r\n");
  1098 + mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  1099 + mobilePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1100 + mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1101 + mobilePostitionXml.append("<Interval>60</Interval>\r\n");
  1102 + mobilePostitionXml.append("</Query>\r\n");
  1103 +
  1104 + String tm = Long.toString(System.currentTimeMillis());
  1105 + Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null);
  1106 +
  1107 + transmitRequest(device, request, errorEvent);
  1108 +
  1109 + } catch (SipException | ParseException | InvalidArgumentException e) {
  1110 + e.printStackTrace();
  1111 + return false;
  1112 + }
  1113 + return true;
783 1114 }
784 1115  
  1116 + /**
  1117 + * 订阅、取消订阅移动位置
  1118 + *
  1119 + * @param device 视频设备
  1120 + * @param expires 订阅超时时间
  1121 + * @param interval 上报时间间隔
  1122 + * @return true = 命令发送成功
  1123 + */
  1124 + public boolean mobilePositionSubscribe(Device device, int expires, int interval) {
  1125 + try {
  1126 + StringBuffer subscribePostitionXml = new StringBuffer(200);
  1127 + subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1128 + subscribePostitionXml.append("<Query>\r\n");
  1129 + subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  1130 + subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1131 + subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1132 + if (expires > 0) {
  1133 + subscribePostitionXml.append("<Interval>" + String.valueOf(interval) + "</Interval>\r\n");
  1134 + }
  1135 + subscribePostitionXml.append("</Query>\r\n");
  1136 +
  1137 + String tm = Long.toString(System.currentTimeMillis());
  1138 + Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); //Position;id=" + tm.substring(tm.length() - 4));
  1139 + transmitRequest(device, request);
  1140 +
  1141 + return true;
  1142 +
  1143 + } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
  1144 + e.printStackTrace();
  1145 + return false;
  1146 + }
  1147 + }
  1148 +
  1149 + /**
  1150 + * 订阅、取消订阅报警信息
  1151 + *
  1152 + * @param device 视频设备
  1153 + * @param expires 订阅过期时间(0 = 取消订阅)
  1154 + * @param startPriority 报警起始级别(可选)
  1155 + * @param endPriority 报警终止级别(可选)
  1156 + * @param alarmMethod 报警方式条件(可选)
  1157 + * @param alarmType 报警类型
  1158 + * @param startTime 报警发生起始时间(可选)
  1159 + * @param endTime 报警发生终止时间(可选)
  1160 + * @return true = 命令发送成功
  1161 + */
  1162 + public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
  1163 + try {
  1164 + StringBuffer cmdXml = new StringBuffer(200);
  1165 + cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1166 + cmdXml.append("<Query>\r\n");
  1167 + cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
  1168 + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1169 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1170 + if (!XmlUtil.isEmpty(startPriority)) {
  1171 + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
  1172 + }
  1173 + if (!XmlUtil.isEmpty(endPriority)) {
  1174 + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
  1175 + }
  1176 + if (!XmlUtil.isEmpty(alarmMethod)) {
  1177 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  1178 + }
  1179 + if (!XmlUtil.isEmpty(alarmType)) {
  1180 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  1181 + }
  1182 + if (!XmlUtil.isEmpty(startTime)) {
  1183 + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
  1184 + }
  1185 + if (!XmlUtil.isEmpty(endTime)) {
  1186 + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
  1187 + }
  1188 + cmdXml.append("</Query>\r\n");
  1189 +
  1190 + String tm = Long.toString(System.currentTimeMillis());
  1191 + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" );
  1192 + transmitRequest(device, request);
  1193 +
  1194 + return true;
  1195 +
  1196 + } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
  1197 + e.printStackTrace();
  1198 + return false;
  1199 + }
  1200 + }
  1201 +
  1202 +
785 1203 private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
786 1204 return transmitRequest(device, request, null, null);
787 1205 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
... ... @@ -26,6 +26,10 @@ import org.slf4j.LoggerFactory;
26 26 import org.springframework.beans.factory.annotation.Autowired;
27 27  
28 28 import com.genersoft.iot.vmp.common.VideoManagerConstants;
  29 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  30 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  31 +import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
  32 +import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
29 33 import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
30 34 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
31 35 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
... ... @@ -73,9 +77,12 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
73 77 private static final String MESSAGE_RECORD_INFO = "RecordInfo";
74 78 private static final String MESSAGE_MEDIA_STATUS = "MediaStatus";
75 79 // private static final String MESSAGE_BROADCAST = "Broadcast";
76   - // private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
77   - // private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
  80 + private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
  81 + private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl";
  82 + private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig";
  83 + private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
78 84 // private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";
  85 + private static final String MESSAGE_PRESET_QUERY = "PresetQuery";
79 86  
80 87 /**
81 88 * 处理MESSAGE请求
... ... @@ -94,12 +101,22 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
94 101 processMessageKeepAlive(evt);
95 102 } else if (MESSAGE_CONFIG_DOWNLOAD.equals(cmd)) {
96 103 logger.info("接收到ConfigDownload消息");
  104 + processMessageConfigDownload(evt);
97 105 } else if (MESSAGE_CATALOG.equals(cmd)) {
98 106 logger.info("接收到Catalog消息");
99 107 processMessageCatalogList(evt);
100 108 } else if (MESSAGE_DEVICE_INFO.equals(cmd)) {
101 109 logger.info("接收到DeviceInfo消息");
102 110 processMessageDeviceInfo(evt);
  111 + } else if (MESSAGE_DEVICE_STATUS.equals(cmd)) {
  112 + logger.info("接收到DeviceStatus消息");
  113 + processMessageDeviceStatus(evt);
  114 + } else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) {
  115 + logger.info("接收到DeviceControl消息");
  116 + processMessageDeviceControl(evt);
  117 + } else if (MESSAGE_DEVICE_CONFIG.equals(cmd)) {
  118 + logger.info("接收到DeviceConfig消息");
  119 + processMessageDeviceConfig(evt);
103 120 } else if (MESSAGE_ALARM.equals(cmd)) {
104 121 logger.info("接收到Alarm消息");
105 122 processMessageAlarm(evt);
... ... @@ -109,16 +126,236 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
109 126 }else if (MESSAGE_MEDIA_STATUS.equals(cmd)) {
110 127 logger.info("接收到MediaStatus消息");
111 128 processMessageMediaStatus(evt);
  129 + } else if (MESSAGE_MOBILE_POSITION.equals(cmd)) {
  130 + logger.info("接收到MobilePosition消息");
  131 + processMessageMobilePosition(evt);
  132 + } else if (MESSAGE_PRESET_QUERY.equals(cmd)) {
  133 + logger.info("接收到PresetQuery消息");
  134 + processMessagePresetQuery(evt);
112 135 } else {
113 136 logger.info("接收到消息:" + cmd);
  137 + responseAck(evt);
  138 + }
  139 + } catch (DocumentException | SipException |InvalidArgumentException | ParseException e) {
  140 + e.printStackTrace();
  141 + }
  142 + }
  143 +
  144 + /**
  145 + * 处理MobilePosition移动位置消息
  146 + *
  147 + * @param evt
  148 + */
  149 + private void processMessageMobilePosition(RequestEvent evt) {
  150 + try {
  151 + Element rootElement = getRootElement(evt);
  152 + MobilePosition mobilePosition = new MobilePosition();
  153 + Element deviceIdElement = rootElement.element("DeviceID");
  154 + String deviceId = deviceIdElement.getTextTrim().toString();
  155 + Device device = storager.queryVideoDevice(deviceId);
  156 + if (device != null) {
  157 + if (!StringUtils.isEmpty(device.getName())) {
  158 + mobilePosition.setDeviceName(device.getName());
  159 + }
  160 + }
  161 + mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID"));
  162 + mobilePosition.setTime(XmlUtil.getText(rootElement, "Time"));
  163 + mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
  164 + mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
  165 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
  166 + mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed")));
  167 + } else {
  168 + mobilePosition.setSpeed(0.0);
  169 + }
  170 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) {
  171 + mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction")));
  172 + } else {
  173 + mobilePosition.setDirection(0.0);
  174 + }
  175 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) {
  176 + mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude")));
  177 + } else {
  178 + mobilePosition.setAltitude(0.0);
  179 + }
  180 + mobilePosition.setReportSource("Mobile Position");
  181 + BaiduPoint bp = new BaiduPoint();
  182 + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
  183 + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
  184 + mobilePosition.setGeodeticSystem("BD-09");
  185 + mobilePosition.setCnLng(bp.getBdLng());
  186 + mobilePosition.setCnLat(bp.getBdLat());
  187 + if (!userSetup.getSavePositionHistory()) {
  188 + storager.clearMobilePositionsByDeviceId(deviceId);
  189 + }
  190 + storager.insertMobilePosition(mobilePosition);
  191 + //回复 200 OK
  192 + responseAck(evt);
  193 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  194 + e.printStackTrace();
  195 + }
  196 + }
  197 +
  198 + /**
  199 + * 处理DeviceStatus设备状态Message
  200 + *
  201 + * @param evt
  202 + */
  203 + private void processMessageDeviceStatus(RequestEvent evt) {
  204 + try {
  205 + Element rootElement = getRootElement(evt);
  206 + String deviceId = XmlUtil.getText(rootElement, "DeviceID");
  207 + // 检查设备是否存在, 不存在则不回复
  208 + if (storager.exists(deviceId)) {
  209 + // 回复200 OK
  210 + responseAck(evt);
  211 + JSONObject json = new JSONObject();
  212 + XmlUtil.node2Json(rootElement, json);
  213 + if (logger.isDebugEnabled()) {
  214 + logger.debug(json.toJSONString());
  215 + }
  216 + RequestMessage msg = new RequestMessage();
  217 + msg.setDeviceId(deviceId);
  218 + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
  219 + msg.setData(json);
  220 + deferredResultHolder.invokeResult(msg);
  221 +
  222 + if (offLineDetector.isOnline(deviceId)) {
  223 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  224 + } else {
  225 + }
  226 + }
  227 + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
  228 + e.printStackTrace();
  229 + }
  230 + }
  231 +
  232 + /**
  233 + * 处理DeviceControl设备状态Message
  234 + *
  235 + * @param evt
  236 + */
  237 + private void processMessageDeviceControl(RequestEvent evt) {
  238 + try {
  239 + Element rootElement = getRootElement(evt);
  240 + String deviceId = XmlUtil.getText(rootElement, "DeviceID");
  241 + //String result = XmlUtil.getText(rootElement, "Result");
  242 + // 回复200 OK
  243 + responseAck(evt);
  244 + if (rootElement.getName().equals("Response")) {//} !XmlUtil.isEmpty(result)) {
  245 + // 此处是对本平台发出DeviceControl指令的应答
  246 + JSONObject json = new JSONObject();
  247 + XmlUtil.node2Json(rootElement, json);
  248 + if (logger.isDebugEnabled()) {
  249 + logger.debug(json.toJSONString());
  250 + }
  251 + RequestMessage msg = new RequestMessage();
  252 + msg.setDeviceId(deviceId);
  253 + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL);
  254 + msg.setData(json);
  255 + deferredResultHolder.invokeResult(msg);
  256 + } else {
  257 + // 此处是上级发出的DeviceControl指令
  258 + }
  259 + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
  260 + e.printStackTrace();
  261 + }
  262 + }
  263 +
  264 + /**
  265 + * 处理DeviceConfig设备状态Message
  266 + *
  267 + * @param evt
  268 + */
  269 + private void processMessageDeviceConfig(RequestEvent evt) {
  270 + try {
  271 + Element rootElement = getRootElement(evt);
  272 + String deviceId = XmlUtil.getText(rootElement, "DeviceID");
  273 + // 回复200 OK
  274 + responseAck(evt);
  275 + if (rootElement.getName().equals("Response")) {
  276 + // 此处是对本平台发出DeviceControl指令的应答
  277 + JSONObject json = new JSONObject();
  278 + XmlUtil.node2Json(rootElement, json);
  279 + if (logger.isDebugEnabled()) {
  280 + logger.debug(json.toJSONString());
  281 + }
  282 + RequestMessage msg = new RequestMessage();
  283 + msg.setDeviceId(deviceId);
  284 + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG);
  285 + msg.setData(json);
  286 + deferredResultHolder.invokeResult(msg);
  287 + } else {
  288 + // 此处是上级发出的DeviceConfig指令
  289 + }
  290 + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
  291 + e.printStackTrace();
  292 + }
  293 + }
  294 +
  295 + /**
  296 + * 处理ConfigDownload设备状态Message
  297 + *
  298 + * @param evt
  299 + */
  300 + private void processMessageConfigDownload(RequestEvent evt) {
  301 + try {
  302 + Element rootElement = getRootElement(evt);
  303 + String deviceId = XmlUtil.getText(rootElement, "DeviceID");
  304 + // 回复200 OK
  305 + responseAck(evt);
  306 + if (rootElement.getName().equals("Response")) {
  307 + // 此处是对本平台发出DeviceControl指令的应答
  308 + JSONObject json = new JSONObject();
  309 + XmlUtil.node2Json(rootElement, json);
  310 + if (logger.isDebugEnabled()) {
  311 + logger.debug(json.toJSONString());
  312 + }
  313 + RequestMessage msg = new RequestMessage();
  314 + msg.setDeviceId(deviceId);
  315 + msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD);
  316 + msg.setData(json);
  317 + deferredResultHolder.invokeResult(msg);
  318 + } else {
  319 + // 此处是上级发出的DeviceConfig指令
  320 + }
  321 + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
  322 + e.printStackTrace();
  323 + }
  324 + }
  325 +
  326 + /**
  327 + * 处理PresetQuery预置位列表Message
  328 + *
  329 + * @param evt
  330 + */
  331 + private void processMessagePresetQuery(RequestEvent evt) {
  332 + try {
  333 + Element rootElement = getRootElement(evt);
  334 + String deviceId = XmlUtil.getText(rootElement, "DeviceID");
  335 + // 回复200 OK
  336 + responseAck(evt);
  337 + if (rootElement.getName().equals("Response")) {// !XmlUtil.isEmpty(result)) {
  338 + // 此处是对本平台发出DeviceControl指令的应答
  339 + JSONObject json = new JSONObject();
  340 + XmlUtil.node2Json(rootElement, json);
  341 + if (logger.isDebugEnabled()) {
  342 + logger.debug(json.toJSONString());
  343 + }
  344 + RequestMessage msg = new RequestMessage();
  345 + msg.setDeviceId(deviceId);
  346 + msg.setType(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY);
  347 + msg.setData(json);
  348 + deferredResultHolder.invokeResult(msg);
  349 + } else {
  350 + // 此处是上级发出的DeviceControl指令
114 351 }
115   - } catch (DocumentException e) {
  352 + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
116 353 e.printStackTrace();
117 354 }
118 355 }
119 356  
120 357 /**
121   - * 收到deviceInfo设备信息请求 处理
  358 + * 处理DeviceInfo设备信息Message
122 359 *
123 360 * @param evt
124 361 */
... ... @@ -126,7 +363,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
126 363 try {
127 364 Element rootElement = getRootElement(evt);
128 365 Element deviceIdElement = rootElement.element("DeviceID");
129   - String deviceId = deviceIdElement.getText().toString();
  366 + String deviceId = deviceIdElement.getTextTrim().toString();
130 367  
131 368 Device device = storager.queryVideoDevice(deviceId);
132 369 if (device == null) {
... ... @@ -228,80 +465,78 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
228 465 deviceChannel.setStatus(0);
229 466 }
230 467  
231   - deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
232   - deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
233   - deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
234   - deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
235   - deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
236   - deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
237   - if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") {
238   - deviceChannel.setParental(0);
239   - } else {
240   - deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
241   - }
242   - deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
243   - if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay")== "") {
244   - deviceChannel.setSafetyWay(0);
245   - } else {
246   - deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
247   - }
248   - if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") =="") {
249   - deviceChannel.setRegisterWay(1);
250   - } else {
251   - deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
252   - }
253   - deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
254   - if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") {
255   - deviceChannel.setCertifiable(0);
256   - } else {
257   - deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
258   - }
259   - if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") {
260   - deviceChannel.setErrCode(0);
261   - } else {
262   - deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
263   - }
264   - deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
265   - deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
266   - deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
267   - if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") =="") {
268   - deviceChannel.setPort(0);
269   - } else {
270   - deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
271   - }
272   - deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
273   - if (XmlUtil.getText(itemDevice, "Longitude") == null || XmlUtil.getText(itemDevice, "Longitude") == "") {
274   - deviceChannel.setLongitude(0.00);
275   - } else {
276   - deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
277   - }
278   - if (XmlUtil.getText(itemDevice, "Latitude") == null || XmlUtil.getText(itemDevice, "Latitude") =="") {
279   - deviceChannel.setLatitude(0.00);
280   - } else {
281   - deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
282   - }
283   - if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") {
284   - deviceChannel.setPTZType(0);
285   - } else {
286   - deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
287   - }
288   - deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
289   - storager.updateChannel(device.getDeviceId(), deviceChannel);
  468 + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
  469 + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
  470 + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
  471 + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
  472 + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
  473 + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
  474 + if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") {
  475 + deviceChannel.setParental(0);
  476 + } else {
  477 + deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
  478 + }
  479 + deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
  480 + if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay")== "") {
  481 + deviceChannel.setSafetyWay(0);
  482 + } else {
  483 + deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
290 484 }
291   -
292   - RequestMessage msg = new RequestMessage();
293   - msg.setDeviceId(deviceId);
294   - msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
295   - msg.setData(device);
296   - deferredResultHolder.invokeResult(msg);
297   - // 回复200 OK
298   - responseAck(evt);
299   - if (offLineDetector.isOnline(deviceId)) {
300   - publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  485 + if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") =="") {
  486 + deviceChannel.setRegisterWay(1);
  487 + } else {
  488 + deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
  489 + }
  490 + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
  491 + if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") {
  492 + deviceChannel.setCertifiable(0);
  493 + } else {
  494 + deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
  495 + }
  496 + if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") {
  497 + deviceChannel.setErrCode(0);
  498 + } else {
  499 + deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
  500 + }
  501 + deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
  502 + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
  503 + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
  504 + if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") =="") {
  505 + deviceChannel.setPort(0);
  506 + } else {
  507 + deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
  508 + }
  509 + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
  510 + if (XmlUtil.getText(itemDevice, "Longitude") == null || XmlUtil.getText(itemDevice, "Longitude") == "") {
  511 + deviceChannel.setLongitude(0.00);
  512 + } else {
  513 + deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
301 514 }
  515 + if (XmlUtil.getText(itemDevice, "Latitude") == null || XmlUtil.getText(itemDevice, "Latitude") =="") {
  516 + deviceChannel.setLatitude(0.00);
  517 + } else {
  518 + deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
  519 + }
  520 + if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") {
  521 + deviceChannel.setPTZType(0);
  522 + } else {
  523 + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
  524 + }
  525 + deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
  526 + storager.updateChannel(device.getDeviceId(), deviceChannel);
302 527 }
303   - }
304 528  
  529 + RequestMessage msg = new RequestMessage();
  530 + msg.setDeviceId(deviceId);
  531 + msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
  532 + msg.setData(device);
  533 + deferredResultHolder.invokeResult(msg);
  534 + // 回复200 OK
  535 + responseAck(evt);
  536 + if (offLineDetector.isOnline(deviceId)) {
  537 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  538 + }
  539 + }
305 540 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
306 541 e.printStackTrace();
307 542 }
... ... @@ -324,41 +559,19 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
324 559 // storager.queryChannel(deviceId)
325 560 return;
326 561 }
327   -
328   - DeviceAlarm deviceAlarm = new DeviceAlarm();
329   - deviceAlarm.setDeviceId(deviceId);
330   - deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
331   - deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
332   - deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime"));
333   - if (XmlUtil.getText(rootElement, "AlarmDescription") == null) {
334   - deviceAlarm.setAlarmDescription("");
335   - } else {
336   - deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription"));
337   - }
338   - if (XmlUtil.getText(rootElement, "Longitude") == null || XmlUtil.getText(rootElement, "Longitude") == "") {
339   - deviceAlarm.setLongitude(0.00);
340   - } else {
341   - deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
342   - }
343   - if (XmlUtil.getText(rootElement, "Latitude") == null || XmlUtil.getText(rootElement, "Latitude") =="") {
344   - deviceAlarm.setLatitude(0.00);
345   - } else {
346   - deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
  562 + device.setName(XmlUtil.getText(rootElement, "DeviceName"));
  563 + device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
  564 + device.setModel(XmlUtil.getText(rootElement, "Model"));
  565 + device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
  566 + if (StringUtils.isEmpty(device.getStreamMode())) {
  567 + device.setStreamMode("UDP");
347 568 }
348   -
349   - // device.setName(XmlUtil.getText(rootElement, "DeviceName"));
350   - // device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
351   - // device.setModel(XmlUtil.getText(rootElement, "Model"));
352   - // device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
353   - // if (StringUtils.isEmpty(device.getStreamMode())) {
354   - // device.setStreamMode("UDP");
355   - // }
356   - // storager.updateDevice(device);
  569 + storager.updateDevice(device);
357 570 //cmder.catalogQuery(device, null);
358 571 // 回复200 OK
359 572 responseAck(evt);
360 573 if (offLineDetector.isOnline(deviceId)) {
361   - publisher.deviceAlarmEventPublish(deviceAlarm);
  574 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
362 575 }
363 576 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
364 577 // } catch (DocumentException e) {
... ... @@ -384,14 +597,13 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
384 597 } else {
385 598 }
386 599 }
387   -
388 600 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
389 601 e.printStackTrace();
390 602 }
391 603 }
392 604  
393 605 /***
394   - * 收到catalog设备目录列表请求 处理 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致
  606 + * 处理RecordInfo设备录像列表Message请求 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致
395 607 *
396 608 * @param evt
397 609 */
... ... @@ -415,8 +627,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
415 627 Element recordListElement = rootElement.element("RecordList");
416 628 if (recordListElement == null || recordInfo.getSumNum() == 0) {
417 629 logger.info("无录像数据");
418   - // responseAck(evt);
419   - // return;
  630 + RequestMessage msg = new RequestMessage();
  631 + msg.setDeviceId(deviceId);
  632 + msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
  633 + msg.setData(recordInfo);
  634 + deferredResultHolder.invokeResult(msg);
420 635 } else {
421 636 Iterator<Element> recordListIterator = recordListElement.elementIterator();
422 637 List<RecordItem> recordList = new ArrayList<RecordItem>();
... ... @@ -446,53 +661,73 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
446 661 record.setRecorderId(XmlUtil.getText(itemRecord, "RecorderID"));
447 662 recordList.add(record);
448 663 }
449   - // recordList.sort(Comparator.naturalOrder());
450 664 recordInfo.setRecordList(recordList);
451 665 }
452 666  
453   - // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回
454   - if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) {
455   - // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分
456   - String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn;
457   -
458   - redis.set(cacheKey + "_" + uuid, recordList, 90);
459   - List<Object> cacheKeys = redis.scan(cacheKey + "_*");
460   - List<RecordItem> totalRecordList = new ArrayList<RecordItem>();
461   - for (int i = 0; i < cacheKeys.size(); i++) {
462   - totalRecordList.addAll((List<RecordItem>) redis.get(cacheKeys.get(i).toString()));
  667 + // 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题
  668 + String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn;
  669 + redis.set(cacheKey + "_" + uuid, recordList, 90);
  670 + if (!threadNameList.contains(cacheKey)) {
  671 + threadNameList.add(cacheKey);
  672 + CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo);
  673 + chk.setName(cacheKey);
  674 + chk.setDeferredResultHolder(deferredResultHolder);
  675 + chk.setRedis(redis);
  676 + chk.setLogger(logger);
  677 + chk.start();
  678 + if (logger.isDebugEnabled()) {
  679 + logger.debug("Start Thread " + cacheKey + ".");
463 680 }
464   - if (totalRecordList.size() < recordInfo.getSumNum()) {
465   - logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项");
466   - return;
467   - }
468   - logger.info("录像数据已全部获取,共" + recordInfo.getSumNum() + "项");
469   - recordInfo.setRecordList(totalRecordList);
470   - for (int i = 0; i < cacheKeys.size(); i++) {
471   - redis.del(cacheKeys.get(i).toString());
  681 + } else {
  682 + if (logger.isDebugEnabled()) {
  683 + logger.debug("Thread " + cacheKey + " already started.");
472 684 }
473 685 }
474   - // 自然顺序排序, 元素进行升序排列
475   - recordInfo.getRecordList().sort(Comparator.naturalOrder());
  686 +
  687 + // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回
  688 + // if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) {
  689 + // // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分
  690 + // String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn;
  691 +
  692 + // redis.set(cacheKey + "_" + uuid, recordList, 90);
  693 + // List<Object> cacheKeys = redis.scan(cacheKey + "_*");
  694 + // List<RecordItem> totalRecordList = new ArrayList<RecordItem>();
  695 + // for (int i = 0; i < cacheKeys.size(); i++) {
  696 + // totalRecordList.addAll((List<RecordItem>) redis.get(cacheKeys.get(i).toString()));
  697 + // }
  698 + // if (totalRecordList.size() < recordInfo.getSumNum()) {
  699 + // logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项");
  700 + // return;
  701 + // }
  702 + // logger.info("录像数据已全部获取,共" + recordInfo.getSumNum() + "项");
  703 + // recordInfo.setRecordList(totalRecordList);
  704 + // for (int i = 0; i < cacheKeys.size(); i++) {
  705 + // redis.del(cacheKeys.get(i).toString());
  706 + // }
  707 + // }
  708 + // // 自然顺序排序, 元素进行升序排列
  709 + // recordInfo.getRecordList().sort(Comparator.naturalOrder());
476 710 }
477 711 // 走到这里,有以下可能:1、没有录像信息,第一次收到recordinfo的消息即返回响应数据,无redis操作
478 712 // 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作
479 713 // 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据
480 714  
481   - // 对记录进行排序
482   - RequestMessage msg = new RequestMessage();
483   - msg.setDeviceId(deviceId);
484   - msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
485   - // // 自然顺序排序, 元素进行升序排列
486   - // recordInfo.getRecordList().sort(Comparator.naturalOrder());
487   - msg.setData(recordInfo);
488   - deferredResultHolder.invokeResult(msg);
489   - logger.info("处理完成,返回结果");
  715 + // RequestMessage msg = new RequestMessage();
  716 + // msg.setDeviceId(deviceId);
  717 + // msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
  718 + // msg.setData(recordInfo);
  719 + // deferredResultHolder.invokeResult(msg);
  720 + // logger.info("处理完成,返回结果");
490 721 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
491 722 e.printStackTrace();
492 723 }
493 724 }
494 725  
495   -
  726 + /**
  727 + * 收到MediaStatus消息处理
  728 + *
  729 + * @param evt
  730 + */
496 731 private void processMessageMediaStatus(RequestEvent evt){
497 732 try {
498 733 // 回复200 OK
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/NotifyRequestProcessor.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
  2 +
  3 +import java.io.ByteArrayInputStream;
  4 +import java.text.ParseException;
  5 +import java.util.Iterator;
  6 +
  7 +import javax.sip.InvalidArgumentException;
  8 +import javax.sip.RequestEvent;
  9 +import javax.sip.SipException;
  10 +import javax.sip.message.Request;
  11 +import javax.sip.message.Response;
  12 +
  13 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
  14 +import com.genersoft.iot.vmp.conf.UserSetup;
  15 +import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
  16 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  17 +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  18 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  19 +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
  20 +import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
  21 +import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  22 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  23 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  24 +import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
  25 +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
  26 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  27 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  28 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  29 +import com.genersoft.iot.vmp.utils.GpsUtil;
  30 +import com.genersoft.iot.vmp.utils.SpringBeanFactory;
  31 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
  32 +
  33 +import org.dom4j.Document;
  34 +import org.dom4j.DocumentException;
  35 +import org.dom4j.Element;
  36 +import org.dom4j.io.SAXReader;
  37 +import org.slf4j.Logger;
  38 +import org.slf4j.LoggerFactory;
  39 +import org.springframework.util.StringUtils;
  40 +
  41 +/**
  42 + * @Description: Notify请求处理器
  43 + * @author: lawrencehj
  44 + * @date: 2021年1月27日
  45 + */
  46 +
  47 +public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
  48 +
  49 + private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
  50 +
  51 + private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
  52 +
  53 + private IVideoManagerStorager storager;
  54 +
  55 + private IRedisCatchStorage redisCatchStorage;
  56 +
  57 + private EventPublisher publisher;
  58 +
  59 + private DeviceOffLineDetector offLineDetector;
  60 +
  61 + private static final String NOTIFY_CATALOG = "Catalog";
  62 + private static final String NOTIFY_ALARM = "Alarm";
  63 + private static final String NOTIFY_MOBILE_POSITION = "MobilePosition";
  64 +
  65 + @Override
  66 + public void process(RequestEvent evt) {
  67 + try {
  68 + Element rootElement = getRootElement(evt);
  69 + String cmd = XmlUtil.getText(rootElement, "CmdType");
  70 +
  71 + if (NOTIFY_CATALOG.equals(cmd)) {
  72 + logger.info("接收到Catalog通知");
  73 + processNotifyCatalogList(evt);
  74 + } else if (NOTIFY_ALARM.equals(cmd)) {
  75 + logger.info("接收到Alarm通知");
  76 + processNotifyAlarm(evt);
  77 + } else if (NOTIFY_MOBILE_POSITION.equals(cmd)) {
  78 + logger.info("接收到MobilePosition通知");
  79 + processNotifyMobilePosition(evt);
  80 + } else {
  81 + logger.info("接收到消息:" + cmd);
  82 + response200Ok(evt);
  83 + }
  84 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  85 + e.printStackTrace();
  86 + }
  87 + }
  88 +
  89 + /**
  90 + * 处理MobilePosition移动位置Notify
  91 + *
  92 + * @param evt
  93 + */
  94 + private void processNotifyMobilePosition(RequestEvent evt) {
  95 + try {
  96 + // 回复 200 OK
  97 + Element rootElement = getRootElement(evt);
  98 + MobilePosition mobilePosition = new MobilePosition();
  99 + Element deviceIdElement = rootElement.element("DeviceID");
  100 + String deviceId = deviceIdElement.getTextTrim().toString();
  101 + Device device = storager.queryVideoDevice(deviceId);
  102 + if (device != null) {
  103 + if (!StringUtils.isEmpty(device.getName())) {
  104 + mobilePosition.setDeviceName(device.getName());
  105 + }
  106 + }
  107 + mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID"));
  108 + mobilePosition.setTime(XmlUtil.getText(rootElement, "Time"));
  109 + mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
  110 + mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
  111 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
  112 + mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed")));
  113 + } else {
  114 + mobilePosition.setSpeed(0.0);
  115 + }
  116 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) {
  117 + mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction")));
  118 + } else {
  119 + mobilePosition.setDirection(0.0);
  120 + }
  121 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) {
  122 + mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude")));
  123 + } else {
  124 + mobilePosition.setAltitude(0.0);
  125 + }
  126 + mobilePosition.setReportSource("Mobile Position");
  127 + BaiduPoint bp = new BaiduPoint();
  128 + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
  129 + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
  130 + mobilePosition.setGeodeticSystem("BD-09");
  131 + mobilePosition.setCnLng(bp.getBdLng());
  132 + mobilePosition.setCnLat(bp.getBdLat());
  133 + if (!userSetup.getSavePositionHistory()) {
  134 + storager.clearMobilePositionsByDeviceId(deviceId);
  135 + }
  136 + storager.insertMobilePosition(mobilePosition);
  137 + response200Ok(evt);
  138 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  139 + e.printStackTrace();
  140 + }
  141 + }
  142 +
  143 + /***
  144 + * 处理alarm设备报警Notify
  145 + *
  146 + * @param evt
  147 + */
  148 + private void processNotifyAlarm(RequestEvent evt) {
  149 + try {
  150 + Element rootElement = getRootElement(evt);
  151 + Element deviceIdElement = rootElement.element("DeviceID");
  152 + String deviceId = deviceIdElement.getText().toString();
  153 +
  154 + Device device = storager.queryVideoDevice(deviceId);
  155 + if (device == null) {
  156 + return;
  157 + }
  158 + DeviceAlarm deviceAlarm = new DeviceAlarm();
  159 + deviceAlarm.setDeviceId(deviceId);
  160 + deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
  161 + deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
  162 + deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime"));
  163 + if (XmlUtil.getText(rootElement, "AlarmDescription") == null) {
  164 + deviceAlarm.setAlarmDescription("");
  165 + } else {
  166 + deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription"));
  167 + }
  168 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) {
  169 + deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
  170 + } else {
  171 + deviceAlarm.setLongitude(0.00);
  172 + }
  173 + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) {
  174 + deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
  175 + } else {
  176 + deviceAlarm.setLatitude(0.00);
  177 + }
  178 +
  179 + if (deviceAlarm.getAlarmMethod().equals("4")) {
  180 + MobilePosition mobilePosition = new MobilePosition();
  181 + mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
  182 + mobilePosition.setTime(deviceAlarm.getAlarmTime());
  183 + mobilePosition.setLongitude(deviceAlarm.getLongitude());
  184 + mobilePosition.setLatitude(deviceAlarm.getLatitude());
  185 + mobilePosition.setReportSource("GPS Alarm");
  186 + BaiduPoint bp = new BaiduPoint();
  187 + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
  188 + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
  189 + mobilePosition.setGeodeticSystem("BD-09");
  190 + mobilePosition.setCnLng(bp.getBdLng());
  191 + mobilePosition.setCnLat(bp.getBdLat());
  192 + if (!userSetup.getSavePositionHistory()) {
  193 + storager.clearMobilePositionsByDeviceId(deviceId);
  194 + }
  195 + storager.insertMobilePosition(mobilePosition);
  196 + }
  197 + // TODO: 需要实现存储报警信息、报警分类
  198 +
  199 + // 回复200 OK
  200 + response200Ok(evt);
  201 + if (offLineDetector.isOnline(deviceId)) {
  202 + publisher.deviceAlarmEventPublish(deviceAlarm);
  203 + }
  204 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  205 + e.printStackTrace();
  206 + }
  207 + }
  208 +
  209 + /***
  210 + * 处理catalog设备目录列表Notify
  211 + *
  212 + * @param evt
  213 + */
  214 + private void processNotifyCatalogList(RequestEvent evt) {
  215 + try {
  216 + Element rootElement = getRootElement(evt);
  217 + Element deviceIdElement = rootElement.element("DeviceID");
  218 + String deviceId = deviceIdElement.getText();
  219 + Element deviceListElement = rootElement.element("DeviceList");
  220 + if (deviceListElement == null) {
  221 + return;
  222 + }
  223 + Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
  224 + if (deviceListIterator != null) {
  225 + Device device = storager.queryVideoDevice(deviceId);
  226 + if (device == null) {
  227 + return;
  228 + }
  229 + // 遍历DeviceList
  230 + while (deviceListIterator.hasNext()) {
  231 + Element itemDevice = deviceListIterator.next();
  232 + Element channelDeviceElement = itemDevice.element("DeviceID");
  233 + if (channelDeviceElement == null) {
  234 + continue;
  235 + }
  236 + String channelDeviceId = channelDeviceElement.getTextTrim();
  237 + Element channdelNameElement = itemDevice.element("Name");
  238 + String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
  239 + Element statusElement = itemDevice.element("Status");
  240 + String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
  241 + DeviceChannel deviceChannel = new DeviceChannel();
  242 + deviceChannel.setName(channelName);
  243 + deviceChannel.setChannelId(channelDeviceId);
  244 + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
  245 + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
  246 + deviceChannel.setStatus(1);
  247 + }
  248 + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
  249 + deviceChannel.setStatus(0);
  250 + }
  251 +
  252 + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
  253 + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
  254 + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
  255 + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
  256 + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
  257 + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
  258 + if (XmlUtil.getText(itemDevice, "Parental") == null
  259 + || XmlUtil.getText(itemDevice, "Parental") == "") {
  260 + deviceChannel.setParental(0);
  261 + } else {
  262 + deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
  263 + }
  264 + deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
  265 + if (XmlUtil.getText(itemDevice, "SafetyWay") == null
  266 + || XmlUtil.getText(itemDevice, "SafetyWay") == "") {
  267 + deviceChannel.setSafetyWay(0);
  268 + } else {
  269 + deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
  270 + }
  271 + if (XmlUtil.getText(itemDevice, "RegisterWay") == null
  272 + || XmlUtil.getText(itemDevice, "RegisterWay") == "") {
  273 + deviceChannel.setRegisterWay(1);
  274 + } else {
  275 + deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
  276 + }
  277 + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
  278 + if (XmlUtil.getText(itemDevice, "Certifiable") == null
  279 + || XmlUtil.getText(itemDevice, "Certifiable") == "") {
  280 + deviceChannel.setCertifiable(0);
  281 + } else {
  282 + deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
  283 + }
  284 + if (XmlUtil.getText(itemDevice, "ErrCode") == null
  285 + || XmlUtil.getText(itemDevice, "ErrCode") == "") {
  286 + deviceChannel.setErrCode(0);
  287 + } else {
  288 + deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
  289 + }
  290 + deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
  291 + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
  292 + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
  293 + if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") {
  294 + deviceChannel.setPort(0);
  295 + } else {
  296 + deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
  297 + }
  298 + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
  299 + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {
  300 + deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
  301 + } else {
  302 + deviceChannel.setLongitude(0.00);
  303 + }
  304 + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
  305 + deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
  306 + } else {
  307 + deviceChannel.setLatitude(0.00);
  308 + }
  309 + if (XmlUtil.getText(itemDevice, "PTZType") == null
  310 + || XmlUtil.getText(itemDevice, "PTZType") == "") {
  311 + deviceChannel.setPTZType(0);
  312 + } else {
  313 + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
  314 + }
  315 + deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
  316 + storager.updateChannel(device.getDeviceId(), deviceChannel);
  317 + }
  318 +
  319 + // RequestMessage msg = new RequestMessage();
  320 + // msg.setDeviceId(deviceId);
  321 + // msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
  322 + // msg.setData(device);
  323 + // deferredResultHolder.invokeResult(msg);
  324 + // 回复200 OK
  325 + response200Ok(evt);
  326 + if (offLineDetector.isOnline(deviceId)) {
  327 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  328 + }
  329 + }
  330 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  331 + e.printStackTrace();
  332 + }
  333 + }
  334 +
  335 + /***
  336 + * 回复200 OK
  337 + *
  338 + * @param evt
  339 + * @throws SipException
  340 + * @throws InvalidArgumentException
  341 + * @throws ParseException
  342 + */
  343 + private void response200Ok(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  344 + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
  345 + getServerTransaction(evt).sendResponse(response);
  346 + }
  347 +
  348 + private Element getRootElement(RequestEvent evt) throws DocumentException {
  349 + Request request = evt.getRequest();
  350 + SAXReader reader = new SAXReader();
  351 + reader.setEncoding("gbk");
  352 + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
  353 + return xml.getRootElement();
  354 + }
  355 +
  356 + public void setCmder(SIPCommander cmder) {
  357 + }
  358 +
  359 + public void setStorager(IVideoManagerStorager storager) {
  360 + this.storager = storager;
  361 + }
  362 +
  363 + public void setPublisher(EventPublisher publisher) {
  364 + this.publisher = publisher;
  365 + }
  366 +
  367 + public void setRedis(RedisUtil redis) {
  368 + }
  369 +
  370 + public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) {
  371 + }
  372 +
  373 + public void setOffLineDetector(DeviceOffLineDetector offLineDetector) {
  374 + this.offLineDetector = offLineDetector;
  375 + }
  376 +
  377 + public IRedisCatchStorage getRedisCatchStorage() {
  378 + return redisCatchStorage;
  379 + }
  380 +
  381 + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
  382 + this.redisCatchStorage = redisCatchStorage;
  383 + }
  384 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java
... ... @@ -21,7 +21,7 @@ public class OtherRequestProcessor extends SIPRequestAbstractProcessor {
21 21 */
22 22 @Override
23 23 public void process(RequestEvent evt) {
24   - System.out.println("no support the method! Method:" + evt.getRequest().getMethod());
  24 + System.out.println("Unsupported the method: " + evt.getRequest().getMethod());
25 25 }
26 26  
27 27 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
... ... @@ -145,7 +145,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
145 145 // 下发catelog查询目录
146 146 if (registerFlag == 1 && device != null) {
147 147 logger.info("注册成功! deviceId:" + device.getDeviceId());
148   - boolean exists = storager.exists(device.getDeviceId());
  148 + // boolean exists = storager.exists(device.getDeviceId());
149 149 device.setRegisterTimeMillis(System.currentTimeMillis());
150 150 storager.updateDevice(device);
151 151 publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
... ... @@ -12,14 +12,12 @@ import javax.sip.header.ViaHeader;
12 12 import javax.sip.message.Request;
13 13 import javax.sip.message.Response;
14 14  
15   -import gov.nist.javax.sip.header.CSeq;
16   -import org.slf4j.Logger;
17   -import org.slf4j.LoggerFactory;
  15 +// import org.slf4j.Logger;
  16 +// import org.slf4j.LoggerFactory;
18 17 import org.springframework.stereotype.Component;
19 18  
20 19 import com.genersoft.iot.vmp.conf.SipConfig;
21 20 import com.genersoft.iot.vmp.gb28181.SipLayer;
22   -import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
23 21 import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
24 22  
25 23  
... ... @@ -31,7 +29,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
31 29 @Component
32 30 public class InviteResponseProcessor implements ISIPResponseProcessor {
33 31  
34   - private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
  32 + // private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
35 33  
36 34 /**
37 35 * 处理invite响应
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/NumericUtil.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.utils;
  2 +
  3 +/**
  4 + * 数值格式判断和处理
  5 + * @author lawrencehj
  6 + * @date 2021年1月27日
  7 + */
  8 +public class NumericUtil {
  9 +
  10 + /**
  11 + * 判断是否Double格式
  12 + * @param str
  13 + * @return true/false
  14 + */
  15 + public static boolean isDouble(String str) {
  16 + try {
  17 + Double num2 = Double.valueOf(str);
  18 + System.out.println(num2 + " is a valid numeric string!");
  19 + return true;
  20 + } catch (Exception e) {
  21 + System.out.println(str + " is an invalid numeric string!");
  22 + return false;
  23 + }
  24 + }
  25 +
  26 + /**
  27 + * 判断是否Double格式
  28 + * @param str
  29 + * @return true/false
  30 + */
  31 + public static boolean isInteger(String str) {
  32 + try {
  33 + int num2 = Integer.valueOf(str);
  34 + System.out.println(num2 + " is an integer!");
  35 + return true;
  36 + } catch (Exception e) {
  37 + System.out.println(str + " is not an integer!");
  38 + return false;
  39 + }
  40 + }
  41 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
... ... @@ -7,6 +7,9 @@ import java.util.Iterator;
7 7 import java.util.List;
8 8 import java.util.Map;
9 9  
  10 +import com.alibaba.fastjson.JSONArray;
  11 +import com.alibaba.fastjson.JSONObject;
  12 +
10 13 import org.dom4j.Attribute;
11 14 import org.dom4j.Document;
12 15 import org.dom4j.DocumentException;
... ... @@ -20,8 +23,7 @@ import org.slf4j.LoggerFactory;
20 23 *
21 24 *
22 25 */
23   -public class XmlUtil
24   -{
  26 +public class XmlUtil {
25 27 /**
26 28 * 日志服务
27 29 */
... ... @@ -30,22 +32,18 @@ public class XmlUtil
30 32 /**
31 33 * 解析XML为Document对象
32 34 *
33   - * @param xml
34   - * 被解析的XMl
  35 + * @param xml 被解析的XMl
  36 + *
35 37 * @return Document
36 38 */
37   - public static Element parseXml(String xml)
38   - {
  39 + public static Element parseXml(String xml) {
39 40 Document document = null;
40 41 //
41 42 StringReader sr = new StringReader(xml);
42 43 SAXReader saxReader = new SAXReader();
43   - try
44   - {
  44 + try {
45 45 document = saxReader.read(sr);
46   - }
47   - catch (DocumentException e)
48   - {
  46 + } catch (DocumentException e) {
49 47 LOG.error("解析失败", e);
50 48 }
51 49 return null == document ? null : document.getRootElement();
... ... @@ -54,16 +52,12 @@ public class XmlUtil
54 52 /**
55 53 * 获取element对象的text的值
56 54 *
57   - * @param em
58   - * 节点的对象
59   - * @param tag
60   - * 节点的tag
  55 + * @param em 节点的对象
  56 + * @param tag 节点的tag
61 57 * @return 节点
62 58 */
63   - public static String getText(Element em, String tag)
64   - {
65   - if (null == em)
66   - {
  59 + public static String getText(Element em, String tag) {
  60 + if (null == em) {
67 61 return null;
68 62 }
69 63 Element e = em.element(tag);
... ... @@ -74,16 +68,12 @@ public class XmlUtil
74 68 /**
75 69 * 递归解析xml节点,适用于 多节点数据
76 70 *
77   - * @param node
78   - * node
79   - * @param nodeName
80   - * nodeName
  71 + * @param node node
  72 + * @param nodeName nodeName
81 73 * @return List<Map<String, Object>>
82 74 */
83   - public static List<Map<String, Object>> listNodes(Element node, String nodeName)
84   - {
85   - if (null == node)
86   - {
  75 + public static List<Map<String, Object>> listNodes(Element node, String nodeName) {
  76 + if (null == node) {
87 77 return null;
88 78 }
89 79 // 初始化返回
... ... @@ -93,12 +83,9 @@ public class XmlUtil
93 83  
94 84 Map<String, Object> map = null;
95 85 // 遍历属性节点
96   - for (Attribute attribute : list)
97   - {
98   - if (nodeName.equals(node.getName()))
99   - {
100   - if (null == map)
101   - {
  86 + for (Attribute attribute : list) {
  87 + if (nodeName.equals(node.getName())) {
  88 + if (null == map) {
102 89 map = new HashMap<String, Object>();
103 90 listMap.add(map);
104 91 }
... ... @@ -110,12 +97,74 @@ public class XmlUtil
110 97 // 遍历当前节点下的所有节点 ,nodeName 要解析的节点名称
111 98 // 使用递归
112 99 Iterator<Element> iterator = node.elementIterator();
113   - while (iterator.hasNext())
114   - {
  100 + while (iterator.hasNext()) {
115 101 Element e = iterator.next();
116 102 listMap.addAll(listNodes(e, nodeName));
117 103 }
118 104 return listMap;
119 105 }
120 106  
  107 + /**
  108 + * xml转json
  109 + *
  110 + * @param element
  111 + * @param json
  112 + */
  113 + public static void node2Json(Element element, JSONObject json) {
  114 + // 如果是属性
  115 + for (Object o : element.attributes()) {
  116 + Attribute attr = (Attribute) o;
  117 + if (!isEmpty(attr.getValue())) {
  118 + json.put("@" + attr.getName(), attr.getValue());
  119 + }
  120 + }
  121 + List<Element> chdEl = element.elements();
  122 + if (chdEl.isEmpty() && !isEmpty(element.getText())) {// 如果没有子元素,只有一个值
  123 + json.put(element.getName(), element.getText());
  124 + }
  125 +
  126 + for (Element e : chdEl) { // 有子元素
  127 + if (!e.elements().isEmpty()) { // 子元素也有子元素
  128 + JSONObject chdjson = new JSONObject();
  129 + node2Json(e, chdjson);
  130 + Object o = json.get(e.getName());
  131 + if (o != null) {
  132 + JSONArray jsona = null;
  133 + if (o instanceof JSONObject) { // 如果此元素已存在,则转为jsonArray
  134 + JSONObject jsono = (JSONObject) o;
  135 + json.remove(e.getName());
  136 + jsona = new JSONArray();
  137 + jsona.add(jsono);
  138 + jsona.add(chdjson);
  139 + }
  140 + if (o instanceof JSONArray) {
  141 + jsona = (JSONArray) o;
  142 + jsona.add(chdjson);
  143 + }
  144 + json.put(e.getName(), jsona);
  145 + } else {
  146 + if (!chdjson.isEmpty()) {
  147 + json.put(e.getName(), chdjson);
  148 + }
  149 + }
  150 + } else { // 子元素没有子元素
  151 + for (Object o : element.attributes()) {
  152 + Attribute attr = (Attribute) o;
  153 + if (!isEmpty(attr.getValue())) {
  154 + json.put("@" + attr.getName(), attr.getValue());
  155 + }
  156 + }
  157 + if (!e.getText().isEmpty()) {
  158 + json.put(e.getName(), e.getText());
  159 + }
  160 + }
  161 + }
  162 + }
  163 +
  164 + public static boolean isEmpty(String str) {
  165 + if (str == null || str.trim().isEmpty() || "null".equals(str)) {
  166 + return true;
  167 + }
  168 + return false;
  169 + }
121 170 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java
1 1 package com.genersoft.iot.vmp.media.zlm;
2 2  
3   -import com.alibaba.fastjson.JSONObject;
4 3 import com.genersoft.iot.vmp.conf.MediaServerConfig;
5 4 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
6   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
7   -import org.slf4j.Logger;
8   -import org.slf4j.LoggerFactory;
  5 +// import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  6 +// import org.slf4j.Logger;
  7 +// import org.slf4j.LoggerFactory;
9 8 import org.springframework.beans.factory.annotation.Autowired;
10 9 import org.springframework.beans.factory.annotation.Value;
11   -import org.springframework.http.HttpHeaders;
12   -import org.springframework.http.HttpRequest;
13   -import org.springframework.http.HttpStatus;
14   -import org.springframework.http.ResponseEntity;
15 10 import org.springframework.web.bind.annotation.*;
16 11 import org.springframework.web.client.HttpClientErrorException;
17 12 import org.springframework.web.client.RestTemplate;
18 13  
19 14 import javax.servlet.http.HttpServletRequest;
20 15 import javax.servlet.http.HttpServletResponse;
21   -import java.util.Enumeration;
22 16  
23 17 @RestController
24 18 @RequestMapping("/zlm")
25 19 public class ZLMHTTPProxyController {
26 20  
27 21  
28   - private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
  22 + // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
29 23  
30   - @Autowired
31   - private IVideoManagerStorager storager;
  24 + // @Autowired
  25 + // private IVideoManagerStorager storager;
32 26  
33 27 @Autowired
34 28 private IRedisCatchStorage redisCatchStorage;
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -82,10 +82,10 @@ public class ZLMHttpHookListener {
82 82 @ResponseBody
83 83 @PostMapping(value = "/on_flow_report", produces = "application/json;charset=UTF-8")
84 84 public ResponseEntity<String> onFlowReport(@RequestBody JSONObject json){
85   -
86   - logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString());
87   - // TODO Auto-generated method stub
88   -
  85 +
  86 + if (logger.isDebugEnabled()) {
  87 + logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString());
  88 + }
89 89 JSONObject ret = new JSONObject();
90 90 ret.put("code", 0);
91 91 ret.put("msg", "success");
... ... @@ -103,8 +103,6 @@ public class ZLMHttpHookListener {
103 103 if (logger.isDebugEnabled()) {
104 104 logger.debug("ZLM HOOK on_http_access API 调用,参数:" + json.toString());
105 105 }
106   - // TODO Auto-generated method stub
107   -
108 106 JSONObject ret = new JSONObject();
109 107 ret.put("code", 0);
110 108 ret.put("err", "");
... ... @@ -124,8 +122,6 @@ public class ZLMHttpHookListener {
124 122 if (logger.isDebugEnabled()) {
125 123 logger.debug("ZLM HOOK on_play API调用,参数:" + json.toString());
126 124 }
127   - // TODO Auto-generated method stub
128   -
129 125 JSONObject ret = new JSONObject();
130 126 ret.put("code", 0);
131 127 ret.put("msg", "success");
... ... @@ -143,15 +139,10 @@ public class ZLMHttpHookListener {
143 139 if (logger.isDebugEnabled()) {
144 140 logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString());
145 141 }
146   - String app = json.getString("app");
147   - String streamId = json.getString("id");
148 142  
149 143 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
150 144 if (subscribe != null) subscribe.response(json);
151 145  
152   -
153   - // TODO Auto-generated method stub
154   -
155 146 JSONObject ret = new JSONObject();
156 147 ret.put("code", 0);
157 148 ret.put("msg", "success");
... ... @@ -172,8 +163,6 @@ public class ZLMHttpHookListener {
172 163 if (logger.isDebugEnabled()) {
173 164 logger.debug("ZLM HOOK on_record_mp4 API调用,参数:" + json.toString());
174 165 }
175   - // TODO Auto-generated method stub
176   -
177 166 JSONObject ret = new JSONObject();
178 167 ret.put("code", 0);
179 168 ret.put("msg", "success");
... ... @@ -191,8 +180,6 @@ public class ZLMHttpHookListener {
191 180 if (logger.isDebugEnabled()) {
192 181 logger.debug("ZLM HOOK on_rtsp_realm API调用,参数:" + json.toString());
193 182 }
194   - // TODO Auto-generated method stub
195   -
196 183 JSONObject ret = new JSONObject();
197 184 ret.put("code", 0);
198 185 ret.put("realm", "");
... ... @@ -211,8 +198,6 @@ public class ZLMHttpHookListener {
211 198 if (logger.isDebugEnabled()) {
212 199 logger.debug("ZLM HOOK on_rtsp_auth API调用,参数:" + json.toString());
213 200 }
214   - // TODO Auto-generated method stub
215   -
216 201 JSONObject ret = new JSONObject();
217 202 ret.put("code", 0);
218 203 ret.put("encrypted", false);
... ... @@ -269,8 +254,6 @@ public class ZLMHttpHookListener {
269 254 redisCatchStorage.stopPlayback(streamInfo);
270 255 }
271 256 }
272   -
273   -
274 257 JSONObject ret = new JSONObject();
275 258 ret.put("code", 0);
276 259 ret.put("msg", "success");
... ... @@ -318,8 +301,6 @@ public class ZLMHttpHookListener {
318 301 if (logger.isDebugEnabled()) {
319 302 logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
320 303 }
321   - // TODO Auto-generated method stub
322   -
323 304 if (autoApplyPlay) {
324 305 String app = json.getString("app");
325 306 String streamId = json.getString("stream");
... ... @@ -369,8 +350,6 @@ public class ZLMHttpHookListener {
369 350 mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp);
370 351 mediaServerConfig.setLocalIP(mediaIp);
371 352 redisCatchStorage.updateMediaInfo(mediaServerConfig);
372   - // TODO Auto-generated method stub
373   -
374 353 JSONObject ret = new JSONObject();
375 354 ret.put("code", 0);
376 355 ret.put("msg", "success");
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
1 1 package com.genersoft.iot.vmp.media.zlm;
2 2  
3   -import com.alibaba.fastjson.JSON;
4 3 import com.alibaba.fastjson.JSONObject;
5   -import com.genersoft.iot.vmp.common.StreamInfo;
6   -import com.genersoft.iot.vmp.conf.MediaServerConfig;
7   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
8   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
9   -import org.slf4j.Logger;
10   -import org.slf4j.LoggerFactory;
11   -import org.springframework.beans.factory.annotation.Autowired;
12   -import org.springframework.beans.factory.annotation.Value;
13   -import org.springframework.http.HttpStatus;
14   -import org.springframework.http.ResponseEntity;
15 4 import org.springframework.stereotype.Component;
16   -import org.springframework.util.ConcurrentReferenceHashMap;
17   -import org.springframework.web.bind.annotation.*;
18 5  
19   -import javax.servlet.http.HttpServletRequest;
20   -import java.math.BigInteger;
21   -import java.text.DecimalFormat;
22 6 import java.util.HashMap;
23 7 import java.util.Map;
24 8 import java.util.concurrent.ConcurrentHashMap;
... ... @@ -31,8 +15,6 @@ import java.util.concurrent.ConcurrentHashMap;
31 15 @Component
32 16 public class ZLMHttpHookSubscribe {
33 17  
34   - private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookSubscribe.class);
35   -
36 18 public enum HookType{
37 19 on_flow_report,
38 20 on_http_access,
... ... @@ -72,8 +54,6 @@ public class ZLMHttpHookSubscribe {
72 54 for (JSONObject key : eventMap.keySet()) {
73 55 Boolean result = null;
74 56 for (String s : key.keySet()) {
75   - String string = hookResponse.getString(s);
76   - String string1 = key.getString(s);
77 57 if (result == null) {
78 58 result = key.getString(s).equals(hookResponse.getString(s));
79 59 }else {
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
... ... @@ -11,7 +11,6 @@ import org.springframework.stereotype.Component;
11 11 import java.io.IOException;
12 12 import java.net.ConnectException;
13 13 import java.util.HashMap;
14   -import java.util.HashSet;
15 14 import java.util.Map;
16 15  
17 16 @Component
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
... ... @@ -5,8 +5,7 @@ import com.alibaba.fastjson.JSONArray;
5 5 import com.alibaba.fastjson.JSONObject;
6 6 import com.genersoft.iot.vmp.conf.MediaServerConfig;
7 7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
8   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
9   -import okhttp3.*;
  8 +//import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
10 9 import org.slf4j.Logger;
11 10 import org.slf4j.LoggerFactory;
12 11 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -16,9 +15,6 @@ import org.springframework.core.annotation.Order;
16 15 import org.springframework.stereotype.Component;
17 16 import org.springframework.util.StringUtils;
18 17  
19   -import java.io.IOException;
20   -import java.io.UnsupportedEncodingException;
21   -import java.net.URLEncoder;
22 18 import java.util.HashMap;
23 19 import java.util.Map;
24 20  
... ... @@ -28,8 +24,8 @@ public class ZLMRunner implements CommandLineRunner {
28 24  
29 25 private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class);
30 26  
31   - @Autowired
32   - private IVideoManagerStorager storager;
  27 + // @Autowired
  28 + // private IVideoManagerStorager storager;
33 29  
34 30 @Autowired
35 31 private IRedisCatchStorage redisCatchStorage;
... ...
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
... ... @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
8 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
9 9 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
10 10 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
  11 +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
11 12 import com.github.pagehelper.PageInfo;
12 13 import gov.nist.javax.sip.stack.NioTcpMessageProcessor;
13 14  
... ... @@ -236,4 +237,32 @@ public interface IVideoManagerStorager {
236 237 DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
237 238  
238 239 Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
  240 +
  241 +
  242 + /**
  243 + * 添加Mobile Position设备移动位置
  244 + * @param MobilePosition
  245 + * @return
  246 + */
  247 + public boolean insertMobilePosition(MobilePosition mobilePosition);
  248 +
  249 + /**
  250 + * 查询移动位置轨迹
  251 + * @param deviceId
  252 + * @param startTime
  253 + * @param endTime
  254 + */
  255 + public List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime);
  256 +
  257 + /**
  258 + * 查询最新移动位置
  259 + * @param deviceId
  260 + */
  261 + public MobilePosition queryLatestPosition(String deviceId);
  262 +
  263 + /**
  264 + * 删除指定设备的所有移动位置
  265 + * @param deviceId
  266 + */
  267 + public int clearMobilePositionsByDeviceId(String deviceId);
239 268 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java 0 → 100644
  1 +package com.genersoft.iot.vmp.storager.dao;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
  6 +import org.apache.ibatis.annotations.*;
  7 +//import org.springframework.stereotype.Repository;
  8 +
  9 +@Mapper
  10 +//@Repository
  11 +public interface DeviceMobilePositionMapper {
  12 +
  13 + @Insert("INSERT INTO device_mobile_position (deviceId, deviceName, time, longitude, latitude, altitude, speed, direction, reportSource, geodeticSystem, cnLng, cnLat) " +
  14 + "VALUES ('${deviceId}', '${deviceName}', '${time}', ${longitude}, ${latitude}, ${altitude}, ${speed}, ${direction}, '${reportSource}', '${geodeticSystem}', '${cnLng}', '${cnLat}')")
  15 + int insertNewPosition(MobilePosition mobilePosition);
  16 +
  17 + @Select(value = {" <script>" +
  18 + "SELECT * FROM device_mobile_position" +
  19 + " WHERE deviceId = #{deviceId} " +
  20 + "<if test=\"startTime != null\"> AND time&gt;=#{startTime}</if>" +
  21 + "<if test=\"endTime != null\"> AND time&lt;=#{endTime}</if>" +
  22 + " ORDER BY time ASC" +
  23 + " </script>"})
  24 + List<MobilePosition> queryPositionByDeviceIdAndTime(String deviceId, String startTime, String endTime);
  25 +
  26 + @Select("SELECT * FROM device_mobile_position WHERE deviceId = #{deviceId}" +
  27 + " ORDER BY time DESC LIMIT 1")
  28 + MobilePosition queryLatestPositionByDevice(String deviceId);
  29 +
  30 + @Delete("DELETE FROM device_mobile_position WHERE deviceId = #{deviceId}")
  31 + int clearMobilePositionsByDeviceId(String deviceId);
  32 +
  33 +}
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -14,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired;
14 14 import org.springframework.stereotype.Component;
15 15  
16 16 import java.util.HashMap;
17   -import java.util.HashSet;
18 17 import java.util.List;
19 18 import java.util.Map;
20 19  
... ... @@ -147,9 +146,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
147 146  
148 147 @Override
149 148 public StreamInfo queryPlaybackByDevice(String deviceId, String code) {
150   - String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
151   - deviceId,
152   - code);
  149 + // String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  150 + // deviceId,
  151 + // code);
153 152 List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
154 153 deviceId,
155 154 code));
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
... ... @@ -6,11 +6,13 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
6 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
8 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  9 +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
9 10 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
10 11 import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
11 12 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
12 13 import com.genersoft.iot.vmp.storager.dao.PatformChannelMapper;
13 14 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
  15 +import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper;
14 16 import com.github.pagehelper.PageHelper;
15 17 import com.github.pagehelper.PageInfo;
16 18 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -32,7 +34,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
32 34 private DeviceMapper deviceMapper;
33 35  
34 36 @Autowired
35   - private DeviceChannelMapper deviceChannelMapper;
  37 + private DeviceChannelMapper deviceChannelMapper;
  38 +
  39 + @Autowired
  40 + private DeviceMobilePositionMapper deviceMobilePositionMapper;
36 41  
37 42 @Autowired
38 43 private ParentPlatformMapper platformMapper;
... ... @@ -194,11 +199,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
194 199 @Override
195 200 public synchronized boolean online(String deviceId) {
196 201 Device device = deviceMapper.getDeviceByDeviceId(deviceId);
197   - device.setOnline(1);
198   - System.out.println("更新设备在线");
199 202 if (device == null) {
200 203 return false;
201 204 }
  205 + device.setOnline(1);
  206 + System.out.println("更新设备在线");
202 207 return deviceMapper.update(device) > 0;
203 208 }
204 209  
... ... @@ -216,10 +221,33 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
216 221 return deviceMapper.update(device) > 0;
217 222 }
218 223  
219   -
  224 + /**
  225 + * 清空通道
  226 + * @param deviceId
  227 + */
220 228 @Override
221 229 public void cleanChannelsForDevice(String deviceId) {
222   - int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
  230 + deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
  231 + }
  232 +
  233 + /**
  234 + * 添加Mobile Position设备移动位置
  235 + * @param MobilePosition
  236 + */
  237 + @Override
  238 + public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) {
  239 + return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0;
  240 + }
  241 +
  242 + /**
  243 + * 查询移动位置轨迹
  244 + * @param deviceId
  245 + * @param startTime
  246 + * @param endTime
  247 + */
  248 + @Override
  249 + public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime) {
  250 + return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime);
223 251 }
224 252  
225 253 @Override
... ... @@ -283,7 +311,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
283 311  
284 312 @Override
285 313 public PageInfo<ChannelReduce> queryAllChannelList(int page, int count, String query, Boolean online,
286   - Boolean channelType, String platformId, Boolean inPlatform) {
  314 + Boolean channelType, String platformId, Boolean inPlatform) {
287 315 PageHelper.startPage(page, count);
288 316 List<ChannelReduce> all = deviceChannelMapper.queryChannelListInAll(query, online, channelType, platformId, inPlatform);
289 317 return new PageInfo<>(all);
... ... @@ -341,4 +369,22 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
341 369 Device device = patformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId);
342 370 return device;
343 371 }
  372 +
  373 + /**
  374 + * 查询最新移动位置
  375 + * @param deviceId
  376 + */
  377 + @Override
  378 + public MobilePosition queryLatestPosition(String deviceId) {
  379 + return deviceMobilePositionMapper.queryLatestPositionByDevice(deviceId);
  380 + }
  381 +
  382 + /**
  383 + * 删除指定设备的所有移动位置
  384 + * @param deviceId
  385 + */
  386 + public int clearMobilePositionsByDeviceId(String deviceId) {
  387 + return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
  388 + }
  389 +
344 390 }
... ...
src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils;
  2 +
  3 +import java.io.BufferedReader;
  4 +import java.io.InputStreamReader;
  5 +import java.io.OutputStream;
  6 +import java.net.Socket;
  7 +import java.util.Base64;
  8 +
  9 +import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
  10 +
  11 +public class GpsUtil {
  12 + public static BaiduPoint Wgs84ToBd09(String xx, String yy) {
  13 + try {
  14 + Socket s = new Socket("api.map.baidu.com", 80);
  15 + BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
  16 + OutputStream out = s.getOutputStream();
  17 + StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4");
  18 + sb.append("&x=" + xx + "&y=" + yy);
  19 + sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");
  20 + sb.append("User-Agent: Java/1.6.0_20\r\n");
  21 + sb.append("Host: api.map.baidu.com:80\r\n");
  22 + sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");
  23 + sb.append("Connection: Close\r\n");
  24 + sb.append("\r\n");
  25 + out.write(sb.toString().getBytes());
  26 + String json = "";
  27 + String tmp = "";
  28 + while ((tmp = br.readLine()) != null) {
  29 + // System.out.println(tmp);
  30 + json += tmp;
  31 + }
  32 +
  33 + s.close();
  34 + int start = json.indexOf("cbk_3976");
  35 + int end = json.lastIndexOf("}");
  36 + if (start != -1 && end != -1 && json.contains("\"x\":\"")) {
  37 + json = json.substring(start, end);
  38 + String[] point = json.split(",");
  39 + String x = point[1].split(":")[1].replace("\"", "");
  40 + String y = point[2].split(":")[1].replace("\"", "");
  41 + BaiduPoint bdPoint= new BaiduPoint();
  42 + bdPoint.setBdLng(new String(decode(x)));
  43 + bdPoint.setBdLat(new String(decode(y)));
  44 + return bdPoint;
  45 + //return (new String(decode(x)) + "," + new String(decode(y)));
  46 + } else {
  47 + System.out.println("gps坐标无效!!");
  48 + }
  49 + out.close();
  50 + br.close();
  51 + } catch (Exception e) {
  52 + e.printStackTrace();
  53 + }
  54 + return null;
  55 + }
  56 +
  57 + /**
  58 + * BASE64解码
  59 + * @param str
  60 + * @return string
  61 + */
  62 + public static byte[] decode(String str) {
  63 + byte[] bt = null;
  64 + final Base64.Decoder decoder = Base64.getDecoder();
  65 + bt = decoder.decode(str); // .decodeBuffer(str);
  66 + return bt;
  67 + }
  68 +}
... ...
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
... ... @@ -4,8 +4,6 @@ import java.util.*;
4 4 import java.util.concurrent.TimeUnit;
5 5  
6 6 import org.springframework.beans.factory.annotation.Autowired;
7   -import org.springframework.dao.DataAccessException;
8   -import org.springframework.data.redis.connection.RedisConnection;
9 7 import org.springframework.data.redis.core.*;
10 8 import org.springframework.stereotype.Component;
11 9 import org.springframework.util.CollectionUtils;
... ... @@ -16,6 +14,7 @@ import org.springframework.util.CollectionUtils;
16 14 * @date: 2020年5月6日 下午8:27:29
17 15 */
18 16 @Component
  17 +@SuppressWarnings(value = {"rawtypes", "unchecked"})
19 18 public class RedisUtil {
20 19  
21 20 @Autowired
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/MobilePosition/MobilePositionController.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.MobilePosition;
  2 +
  3 +import java.util.List;
  4 +
  5 +import javax.sip.message.Response;
  6 +
  7 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  8 +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
  9 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  10 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  11 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  12 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  13 +import com.github.pagehelper.util.StringUtil;
  14 +
  15 +import org.slf4j.Logger;
  16 +import org.slf4j.LoggerFactory;
  17 +import org.springframework.beans.factory.annotation.Autowired;
  18 +import org.springframework.http.HttpStatus;
  19 +import org.springframework.http.ResponseEntity;
  20 +import org.springframework.web.bind.annotation.CrossOrigin;
  21 +import org.springframework.web.bind.annotation.GetMapping;
  22 +import org.springframework.web.bind.annotation.PathVariable;
  23 +import org.springframework.web.bind.annotation.RequestMapping;
  24 +import org.springframework.web.bind.annotation.RequestParam;
  25 +import org.springframework.web.bind.annotation.RestController;
  26 +import org.springframework.web.context.request.async.DeferredResult;
  27 +
  28 +@CrossOrigin
  29 +@RestController
  30 +@RequestMapping("/api")
  31 +public class MobilePositionController {
  32 +
  33 + private final static Logger logger = LoggerFactory.getLogger(MobilePositionController.class);
  34 +
  35 + @Autowired
  36 + private IVideoManagerStorager storager;
  37 +
  38 + @Autowired
  39 + private SIPCommander cmder;
  40 +
  41 + @Autowired
  42 + private DeferredResultHolder resultHolder;
  43 +
  44 + @GetMapping("/positions/{deviceId}/history")
  45 + public ResponseEntity<List<MobilePosition>> positions(@PathVariable String deviceId,
  46 + @RequestParam(required = false) String start,
  47 + @RequestParam(required = false) String end) {
  48 + if (logger.isDebugEnabled()) {
  49 + logger.debug("查询设备" + deviceId + "的历史轨迹");
  50 + }
  51 +
  52 + if (StringUtil.isEmpty(start)) {
  53 + start = null;
  54 + }
  55 + if (StringUtil.isEmpty(end)) {
  56 + end = null;
  57 + }
  58 +
  59 + List<MobilePosition> result = storager.queryMobilePositions(deviceId, start, end);
  60 + return new ResponseEntity<>(result, HttpStatus.OK);
  61 + }
  62 +
  63 + @GetMapping("/positions/{deviceId}/latest")
  64 + public ResponseEntity<MobilePosition> latestPosition(@PathVariable String deviceId) {
  65 + if (logger.isDebugEnabled()) {
  66 + logger.debug("查询设备" + deviceId + "的最新位置");
  67 + }
  68 + MobilePosition result = storager.queryLatestPosition(deviceId);
  69 + return new ResponseEntity<>(result, HttpStatus.OK);
  70 + }
  71 +
  72 + @GetMapping("/positions/{deviceId}/realtime")
  73 + public DeferredResult<ResponseEntity<MobilePosition>> realTimePosition(@PathVariable String deviceId) {
  74 + Device device = storager.queryVideoDevice(deviceId);
  75 + cmder.mobilePostitionQuery(device, event -> {
  76 + Response response = event.getResponse();
  77 + RequestMessage msg = new RequestMessage();
  78 + msg.setId(DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId);
  79 + msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  80 + resultHolder.invokeResult(msg);
  81 + });
  82 + DeferredResult<ResponseEntity<MobilePosition>> result = new DeferredResult<ResponseEntity<MobilePosition>>(5*1000L);
  83 + result.onTimeout(()->{
  84 + logger.warn(String.format("获取移动位置信息超时"));
  85 + // 释放rtpserver
  86 + RequestMessage msg = new RequestMessage();
  87 + msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
  88 + msg.setData("Timeout");
  89 + resultHolder.invokeResult(msg);
  90 + });
  91 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
  92 + return result;
  93 + }
  94 +
  95 + @GetMapping("/positions/{deviceId}/subscribe")
  96 + public ResponseEntity<String> positionSubscribe(@PathVariable String deviceId,
  97 + @RequestParam String expires,
  98 + @RequestParam String interval) {
  99 + String msg = ((expires.equals("0")) ? "取消" : "") + "订阅设备" + deviceId + "的移动位置";
  100 + if (logger.isDebugEnabled()) {
  101 + logger.debug(msg);
  102 + }
  103 +
  104 + if (StringUtil.isEmpty(interval)) {
  105 + interval = "5";
  106 + }
  107 + Device device = storager.queryVideoDevice(deviceId);
  108 +
  109 + String result = msg;
  110 + if (cmder.mobilePositionSubscribe(device, Integer.parseInt(expires), Integer.parseInt(interval))) {
  111 + result += ",成功";
  112 + } else {
  113 + result += ",失败";
  114 + }
  115 +
  116 + return new ResponseEntity<>(result, HttpStatus.OK);
  117 + }
  118 +}
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/SseController/SseController.java
... ... @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.SseController;
3 3 import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
4 4 import org.springframework.beans.factory.annotation.Autowired;
5 5 import org.springframework.stereotype.Controller;
  6 +import org.springframework.web.bind.annotation.CrossOrigin;
6 7 import org.springframework.web.bind.annotation.RequestMapping;
7 8 import org.springframework.web.bind.annotation.RequestParam;
8 9 import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
... ... @@ -13,6 +14,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
13 14 * @data: 2021-01-20
14 15 */
15 16  
  17 +@CrossOrigin
16 18 @Controller
17 19 @RequestMapping("/api")
18 20 public class SseController {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceConfig.java 0 → 100644
  1 +/**
  2 + * 设备设置命令API接口
  3 + *
  4 + * @author lawrencehj
  5 + * @date 2021年2月2日
  6 + */
  7 +
  8 +package com.genersoft.iot.vmp.vmanager.device;
  9 +
  10 +import javax.sip.message.Response;
  11 +
  12 +import com.alibaba.fastjson.JSONObject;
  13 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  14 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  15 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  16 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  17 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  18 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  19 +
  20 +import org.slf4j.Logger;
  21 +import org.slf4j.LoggerFactory;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.http.ResponseEntity;
  24 +import org.springframework.web.bind.annotation.*;
  25 +import org.springframework.web.context.request.async.DeferredResult;
  26 +
  27 +@CrossOrigin
  28 +@RestController
  29 +@RequestMapping("/api")
  30 +public class DeviceConfig {
  31 +
  32 + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class);
  33 +
  34 + @Autowired
  35 + private IVideoManagerStorager storager;
  36 +
  37 + @Autowired
  38 + private SIPCommander cmder;
  39 +
  40 + @Autowired
  41 + private DeferredResultHolder resultHolder;
  42 +
  43 + /**
  44 + * 看守位控制命令API接口
  45 + *
  46 + * @param deviceId
  47 + * @param enabled 看守位使能1:开启,0:关闭
  48 + * @param resetTime 自动归位时间间隔(可选)
  49 + * @param presetIndex 调用预置位编号(可选)
  50 + * @param channelId 通道编码(可选)
  51 + */
  52 + @GetMapping("/config/{deviceId}/basicParam")
  53 + public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
  54 + @RequestParam(required = false) String channelId,
  55 + @RequestParam(required = false) String name,
  56 + @RequestParam(required = false) String expiration,
  57 + @RequestParam(required = false) String heartBeatInterval,
  58 + @RequestParam(required = false) String heartBeatCount) {
  59 + if (logger.isDebugEnabled()) {
  60 + logger.debug("报警复位API调用");
  61 + }
  62 + Device device = storager.queryVideoDevice(deviceId);
  63 + cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
  64 + Response response = event.getResponse();
  65 + RequestMessage msg = new RequestMessage();
  66 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  67 + msg.setData(String.format("设备配置操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  68 + resultHolder.invokeResult(msg);
  69 + });
  70 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  71 + result.onTimeout(() -> {
  72 + logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
  73 + // 释放rtpserver
  74 + RequestMessage msg = new RequestMessage();
  75 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  76 + JSONObject json = new JSONObject();
  77 + json.put("DeviceID", deviceId);
  78 + json.put("Status", "Timeout");
  79 + json.put("Description", "设备配置操作超时, 设备未返回应答指令");
  80 + msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
  81 + resultHolder.invokeResult(msg);
  82 + });
  83 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
  84 + return result;
  85 + }
  86 +
  87 + /**
  88 + * 设备配置查询请求API接口
  89 + *
  90 + * @param deviceId
  91 + */
  92 + @GetMapping("/config/{deviceId}/query/{configType}")
  93 + public DeferredResult<ResponseEntity<String>> configDownloadApi(@PathVariable String deviceId,
  94 + @PathVariable String configType,
  95 + @RequestParam(required = false) String channelId) {
  96 + if (logger.isDebugEnabled()) {
  97 + logger.debug("设备状态查询API调用");
  98 + }
  99 + Device device = storager.queryVideoDevice(deviceId);
  100 + cmder.deviceConfigQuery(device, channelId, configType, event -> {
  101 + Response response = event.getResponse();
  102 + RequestMessage msg = new RequestMessage();
  103 + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  104 + msg.setData(String.format("获取设备配置失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  105 + resultHolder.invokeResult(msg);
  106 + });
  107 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
  108 + result.onTimeout(()->{
  109 + logger.warn(String.format("获取设备配置超时"));
  110 + // 释放rtpserver
  111 + RequestMessage msg = new RequestMessage();
  112 + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  113 + msg.setData("Timeout. Device did not response to this command.");
  114 + resultHolder.invokeResult(msg);
  115 + });
  116 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
  117 + return result;
  118 + }
  119 +
  120 +}
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceControl.java 0 → 100644
  1 +/**
  2 + * 设备控制命令API接口
  3 + *
  4 + * @author lawrencehj
  5 + * @date 2021年2月1日
  6 + */
  7 +
  8 +package com.genersoft.iot.vmp.vmanager.device;
  9 +
  10 +import javax.sip.message.Response;
  11 +
  12 +import com.alibaba.fastjson.JSONObject;
  13 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  14 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  15 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  16 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  17 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  18 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  19 +
  20 +import org.slf4j.Logger;
  21 +import org.slf4j.LoggerFactory;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.http.HttpStatus;
  24 +import org.springframework.http.ResponseEntity;
  25 +import org.springframework.web.bind.annotation.*;
  26 +import org.springframework.web.context.request.async.DeferredResult;
  27 +
  28 +@CrossOrigin
  29 +@RestController
  30 +@RequestMapping("/api")
  31 +public class DeviceControl {
  32 +
  33 + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class);
  34 +
  35 + @Autowired
  36 + private IVideoManagerStorager storager;
  37 +
  38 + @Autowired
  39 + private SIPCommander cmder;
  40 +
  41 + @Autowired
  42 + private DeferredResultHolder resultHolder;
  43 +
  44 + /**
  45 + * 远程启动控制命令API接口
  46 + *
  47 + * @param deviceId
  48 + */
  49 + @GetMapping("/control/{deviceId}/teleboot")
  50 + @PostMapping("/control/{deviceId}/teleboot")
  51 + public ResponseEntity<String> teleBootApi(@PathVariable String deviceId) {
  52 + if (logger.isDebugEnabled()) {
  53 + logger.debug("设备远程启动API调用");
  54 + }
  55 + Device device = storager.queryVideoDevice(deviceId);
  56 + boolean sucsess = cmder.teleBootCmd(device);
  57 + if (sucsess) {
  58 + JSONObject json = new JSONObject();
  59 + json.put("DeviceID", deviceId);
  60 + json.put("Result", "OK");
  61 + return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
  62 + } else {
  63 + logger.warn("设备远程启动API调用失败!");
  64 + return new ResponseEntity<String>("设备远程启动API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
  65 + }
  66 + }
  67 +
  68 + /**
  69 + * 录像控制命令API接口
  70 + *
  71 + * @param deviceId
  72 + * @param recordCmdStr Record:手动录像,StopRecord:停止手动录像
  73 + * @param channelId 通道编码(可选)
  74 + */
  75 + @GetMapping("/control/{deviceId}/record/{recordCmdStr}")
  76 + public DeferredResult<ResponseEntity<String>> recordApi(@PathVariable String deviceId,
  77 + @PathVariable String recordCmdStr, @RequestParam(required = false) String channelId) {
  78 + if (logger.isDebugEnabled()) {
  79 + logger.debug("开始/停止录像API调用");
  80 + }
  81 + Device device = storager.queryVideoDevice(deviceId);
  82 + cmder.recordCmd(device, channelId, recordCmdStr, event -> {
  83 + Response response = event.getResponse();
  84 + RequestMessage msg = new RequestMessage();
  85 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  86 + msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  87 + resultHolder.invokeResult(msg);
  88 + });
  89 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  90 + result.onTimeout(() -> {
  91 + logger.warn(String.format("开始/停止录像操作超时, 设备未返回应答指令"));
  92 + // 释放rtpserver
  93 + RequestMessage msg = new RequestMessage();
  94 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  95 + msg.setData("Timeout. Device did not response to this command.");
  96 + resultHolder.invokeResult(msg);
  97 + });
  98 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
  99 + return result;
  100 + }
  101 +
  102 + /**
  103 + * 报警布防/撤防命令API接口
  104 + *
  105 + * @param deviceId
  106 + * @param guardCmdStr SetGuard:布防,ResetGuard:撤防
  107 + */
  108 + @GetMapping("/control/{deviceId}/guard/{guardCmdStr}")
  109 + public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) {
  110 + if (logger.isDebugEnabled()) {
  111 + logger.debug("布防/撤防API调用");
  112 + }
  113 + Device device = storager.queryVideoDevice(deviceId);
  114 + cmder.guardCmd(device, guardCmdStr, event -> {
  115 + Response response = event.getResponse();
  116 + RequestMessage msg = new RequestMessage();
  117 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
  118 + msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  119 + resultHolder.invokeResult(msg);
  120 + });
  121 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  122 + result.onTimeout(() -> {
  123 + logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
  124 + // 释放rtpserver
  125 + RequestMessage msg = new RequestMessage();
  126 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
  127 + msg.setData("Timeout. Device did not response to this command.");
  128 + resultHolder.invokeResult(msg);
  129 + });
  130 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
  131 + return result;
  132 + }
  133 +
  134 + /**
  135 + * 报警复位API接口
  136 + *
  137 + * @param deviceId
  138 + * @param alarmMethod 报警方式(可选)
  139 + * @param alarmType 报警类型(可选)
  140 + */
  141 + @GetMapping("/control/{deviceId}/resetAlarm")
  142 + public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId,
  143 + @RequestParam(required = false) String alarmMethod,
  144 + @RequestParam(required = false) String alarmType) {
  145 + if (logger.isDebugEnabled()) {
  146 + logger.debug("报警复位API调用");
  147 + }
  148 + Device device = storager.queryVideoDevice(deviceId);
  149 + cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
  150 + Response response = event.getResponse();
  151 + RequestMessage msg = new RequestMessage();
  152 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
  153 + msg.setData(String.format("报警复位操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  154 + resultHolder.invokeResult(msg);
  155 + });
  156 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  157 + result.onTimeout(() -> {
  158 + logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
  159 + // 释放rtpserver
  160 + RequestMessage msg = new RequestMessage();
  161 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
  162 + msg.setData("Timeout. Device did not response to this command.");
  163 + resultHolder.invokeResult(msg);
  164 + });
  165 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
  166 + return result;
  167 + }
  168 +
  169 + /**
  170 + * 强制关键帧API接口
  171 + *
  172 + * @param deviceId
  173 + * @param channelId
  174 + */
  175 + @GetMapping("/control/{deviceId}/iFrame")
  176 + @PostMapping("/control/{deviceId}/iFrame")
  177 + public ResponseEntity<String> iFrame(@PathVariable String deviceId,
  178 + @RequestParam(required = false) String channelId) {
  179 + if (logger.isDebugEnabled()) {
  180 + logger.debug("强制关键帧API调用");
  181 + }
  182 + Device device = storager.queryVideoDevice(deviceId);
  183 + boolean sucsess = cmder.iFrameCmd(device, channelId);
  184 + if (sucsess) {
  185 + JSONObject json = new JSONObject();
  186 + json.put("DeviceID", deviceId);
  187 + json.put("ChannelID", channelId);
  188 + json.put("Result", "OK");
  189 + return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
  190 + } else {
  191 + logger.warn("强制关键帧API调用失败!");
  192 + return new ResponseEntity<String>("强制关键帧API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
  193 + }
  194 + }
  195 +
  196 + /**
  197 + * 看守位控制命令API接口
  198 + *
  199 + * @param deviceId
  200 + * @param enabled 看守位使能1:开启,0:关闭
  201 + * @param resetTime 自动归位时间间隔(可选)
  202 + * @param presetIndex 调用预置位编号(可选)
  203 + * @param channelId 通道编码(可选)
  204 + */
  205 + @GetMapping("/control/{deviceId}/homePosition/{enabled}")
  206 + public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
  207 + @PathVariable String enabled,
  208 + @RequestParam(required = false) String resetTime,
  209 + @RequestParam(required = false) String presetIndex,
  210 + @RequestParam(required = false) String channelId) {
  211 + if (logger.isDebugEnabled()) {
  212 + logger.debug("报警复位API调用");
  213 + }
  214 + Device device = storager.queryVideoDevice(deviceId);
  215 + cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
  216 + Response response = event.getResponse();
  217 + RequestMessage msg = new RequestMessage();
  218 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  219 + msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  220 + resultHolder.invokeResult(msg);
  221 + });
  222 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  223 + result.onTimeout(() -> {
  224 + logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
  225 + // 释放rtpserver
  226 + RequestMessage msg = new RequestMessage();
  227 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  228 + JSONObject json = new JSONObject();
  229 + json.put("DeviceID", deviceId);
  230 + json.put("Status", "Timeout");
  231 + json.put("Description", "看守位控制操作超时, 设备未返回应答指令");
  232 + msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
  233 + resultHolder.invokeResult(msg);
  234 + });
  235 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
  236 + return result;
  237 + }
  238 +}
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java renamed to src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceQuery.java
... ... @@ -21,12 +21,13 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
21 21  
22 22 import javax.sip.message.Response;
23 23  
  24 +@SuppressWarnings("rawtypes")
24 25 @CrossOrigin
25 26 @RestController
26 27 @RequestMapping("/api")
27   -public class DeviceController {
  28 +public class DeviceQuery {
28 29  
29   - private final static Logger logger = LoggerFactory.getLogger(DeviceController.class);
  30 + private final static Logger logger = LoggerFactory.getLogger(DeviceQuery.class);
30 31  
31 32 @Autowired
32 33 private IVideoManagerStorager storager;
... ... @@ -77,11 +78,9 @@ public class DeviceController {
77 78 int page, int count,
78 79 @RequestParam(required = false) String query,
79 80 @RequestParam(required = false) Boolean online,
80   - @RequestParam(required = false) Boolean channelType
81   - ){
82   -
  81 + @RequestParam(required = false) Boolean channelType) {
83 82 if (logger.isDebugEnabled()) {
84   - logger.debug("查询所有视频设备API调用");
  83 + logger.debug("查询视频设备通道API调用");
85 84 }
86 85 if (StringUtils.isEmpty(query)) {
87 86 query = null;
... ... @@ -135,8 +134,8 @@ public class DeviceController {
135 134 json.put("deviceId", deviceId);
136 135 return new ResponseEntity<>(json.toString(),HttpStatus.OK);
137 136 } else {
138   - logger.warn("设备预览API调用失败!");
139   - return new ResponseEntity<String>("设备预览API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
  137 + logger.warn("设备信息删除API调用失败!");
  138 + return new ResponseEntity<String>("设备信息删除API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
140 139 }
141 140 }
142 141  
... ... @@ -157,7 +156,7 @@ public class DeviceController {
157 156 @RequestParam(required = false) Boolean channelType){
158 157  
159 158 if (logger.isDebugEnabled()) {
160   - logger.debug("查询所有视频设备API调用");
  159 + logger.debug("查询所有视频通道API调用");
161 160 }
162 161 DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId);
163 162 if (deviceChannel == null) {
... ... @@ -183,4 +182,74 @@ public class DeviceController {
183 182 storager.updateDevice(device);
184 183 return new ResponseEntity<>(null,HttpStatus.OK);
185 184 }
  185 +
  186 + /**
  187 + * 设备状态查询请求API接口
  188 + *
  189 + * @param deviceId
  190 + */
  191 + @GetMapping("/devices/{deviceId}/status")
  192 + public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) {
  193 + if (logger.isDebugEnabled()) {
  194 + logger.debug("设备状态查询API调用");
  195 + }
  196 + Device device = storager.queryVideoDevice(deviceId);
  197 + cmder.deviceStatusQuery(device, event -> {
  198 + Response response = event.getResponse();
  199 + RequestMessage msg = new RequestMessage();
  200 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
  201 + msg.setData(String.format("获取设备状态失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  202 + resultHolder.invokeResult(msg);
  203 + });
  204 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2*1000L);
  205 + result.onTimeout(()->{
  206 + logger.warn(String.format("获取设备状态超时"));
  207 + // 释放rtpserver
  208 + RequestMessage msg = new RequestMessage();
  209 + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
  210 + msg.setData("Timeout. Device did not response to this command.");
  211 + resultHolder.invokeResult(msg);
  212 + });
  213 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, result);
  214 + return result;
  215 + }
  216 +
  217 + /**
  218 + * 设备报警查询请求API接口
  219 + *
  220 + * @param deviceId
  221 + */
  222 + @GetMapping("/alarm/{deviceId}")
  223 + public DeferredResult<ResponseEntity<String>> alarmApi(@PathVariable String deviceId,
  224 + @RequestParam(required = false) String startPriority,
  225 + @RequestParam(required = false) String endPriority,
  226 + @RequestParam(required = false) String alarmMethod,
  227 + @RequestParam(required = false) String alarmType,
  228 + @RequestParam(required = false) String startTime,
  229 + @RequestParam(required = false) String endTime) {
  230 + if (logger.isDebugEnabled()) {
  231 + logger.debug("设备报警查询API调用");
  232 + }
  233 + Device device = storager.queryVideoDevice(deviceId);
  234 + cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
  235 + Response response = event.getResponse();
  236 + RequestMessage msg = new RequestMessage();
  237 + msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
  238 + msg.setData(String.format("设备报警查询失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  239 + resultHolder.invokeResult(msg);
  240 + });
  241 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
  242 + result.onTimeout(()->{
  243 + logger.warn(String.format("设备报警查询超时"));
  244 + // 释放rtpserver
  245 + RequestMessage msg = new RequestMessage();
  246 + msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
  247 + msg.setData("设备报警查询超时");
  248 + resultHolder.invokeResult(msg);
  249 + });
  250 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, result);
  251 + return result;
  252 + }
  253 +
  254 +
186 255 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
1 1 package com.genersoft.iot.vmp.vmanager.play;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4   -import com.alibaba.fastjson.JSONArray;
5 4 import com.genersoft.iot.vmp.common.StreamInfo;
6 5 import com.genersoft.iot.vmp.conf.MediaServerConfig;
7   -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
8 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 8 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
11   -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
12 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
13 10 import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
14 11 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
15 12 import org.slf4j.Logger;
16 13 import org.slf4j.LoggerFactory;
17 14 import org.springframework.beans.factory.annotation.Autowired;
18   -import org.springframework.beans.factory.annotation.Value;
19 15 import org.springframework.http.HttpStatus;
20 16 import org.springframework.http.ResponseEntity;
21 17 import org.springframework.web.bind.annotation.CrossOrigin;
... ... @@ -32,7 +28,6 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
32 28 import org.springframework.web.context.request.async.DeferredResult;
33 29  
34 30 import javax.sip.message.Response;
35   -import java.text.DecimalFormat;
36 31 import java.util.UUID;
37 32  
38 33 @CrossOrigin
... ... @@ -103,7 +98,7 @@ public class PlayController {
103 98 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
104 99 RequestMessage msg = new RequestMessage();
105 100 msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
106   - Response response = event.getResponse();
  101 + //Response response = event.getResponse();
107 102 msg.setData(String.format("success"));
108 103 resultHolder.invokeResult(msg);
109 104 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java
1 1 package com.genersoft.iot.vmp.vmanager.playback;
2 2  
3   -import com.alibaba.fastjson.JSON;
4   -import com.alibaba.fastjson.JSONArray;
5 3 import com.genersoft.iot.vmp.common.StreamInfo;
6 4 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
7 5 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
8   -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  6 +//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
9 7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
10 8 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
11 9 import org.slf4j.Logger;
12 10 import org.slf4j.LoggerFactory;
13 11 import org.springframework.beans.factory.annotation.Autowired;
14   -import org.springframework.beans.factory.annotation.Value;
15 12 import org.springframework.http.HttpStatus;
16 13 import org.springframework.http.ResponseEntity;
17   -import org.springframework.util.StringUtils;
18 14 import org.springframework.web.bind.annotation.CrossOrigin;
19 15 import org.springframework.web.bind.annotation.GetMapping;
20 16 import org.springframework.web.bind.annotation.PathVariable;
21   -import org.springframework.web.bind.annotation.PostMapping;
22 17 import org.springframework.web.bind.annotation.RequestMapping;
23 18 import org.springframework.web.bind.annotation.RestController;
24 19  
... ... @@ -47,8 +42,8 @@ public class PlaybackController {
47 42 @Autowired
48 43 private IRedisCatchStorage redisCatchStorage;
49 44  
50   - @Autowired
51   - private ZLMRESTfulUtils zlmresTfulUtils;
  45 + // @Autowired
  46 + // private ZLMRESTfulUtils zlmresTfulUtils;
52 47  
53 48 @Autowired
54 49 private IPlayService playService;
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
... ... @@ -5,14 +5,16 @@ import org.slf4j.LoggerFactory;
5 5 import org.springframework.beans.factory.annotation.Autowired;
6 6 import org.springframework.http.HttpStatus;
7 7 import org.springframework.http.ResponseEntity;
8   -import org.springframework.web.bind.annotation.CrossOrigin;
9   -import org.springframework.web.bind.annotation.PathVariable;
10   -import org.springframework.web.bind.annotation.PostMapping;
11   -import org.springframework.web.bind.annotation.RequestMapping;
12   -import org.springframework.web.bind.annotation.RestController;
  8 +import org.springframework.web.bind.annotation.*;
  9 +import org.springframework.web.context.request.async.DeferredResult;
  10 +
  11 +import javax.sip.message.Response;
13 12  
14 13 import com.genersoft.iot.vmp.gb28181.bean.Device;
  14 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  15 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
15 16 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  17 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
16 18 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
17 19  
18 20 @CrossOrigin
... ... @@ -28,6 +30,9 @@ public class PtzController {
28 30 @Autowired
29 31 private IVideoManagerStorager storager;
30 32  
  33 + @Autowired
  34 + private DeferredResultHolder resultHolder;
  35 +
31 36 /***
32 37 * 云台控制
33 38 * @param deviceId 设备id
... ... @@ -49,16 +54,18 @@ public class PtzController {
49 54 cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
50 55 return new ResponseEntity<String>("success",HttpStatus.OK);
51 56 }
52   - // public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed){
53   -
54   - // if (logger.isDebugEnabled()) {
55   - // logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,leftRight:%d ,upDown:%d ,inOut:%d ,moveSpeed:%d ,zoomSpeed:%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed));
56   - // }
57   - // Device device = storager.queryVideoDevice(deviceId);
58   -
59   - // cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
60   - // return new ResponseEntity<String>("success",HttpStatus.OK);
61   - // }
  57 +
  58 + /**
  59 + * 通用前端控制命令API接口
  60 + *
  61 + * @param deviceId
  62 + * @param channelId
  63 + * @param cmdCode
  64 + * @param parameter1
  65 + * @param parameter2
  66 + * @param combindCode2
  67 + * @return
  68 + */
62 69 @PostMapping("/frontEndCommand/{deviceId}/{channelId}")
63 70 public ResponseEntity<String> frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
64 71  
... ... @@ -70,4 +77,37 @@ public class PtzController {
70 77 cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
71 78 return new ResponseEntity<String>("success",HttpStatus.OK);
72 79 }
  80 +
  81 + /**
  82 + * 预置位查询命令API接口
  83 + *
  84 + * @param deviceId
  85 + * @param channelId
  86 + * @return
  87 + */
  88 + @GetMapping("/presetQuery/{deviceId}/{channelId}")
  89 + public DeferredResult<ResponseEntity<String>> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) {
  90 + if (logger.isDebugEnabled()) {
  91 + logger.debug("设备预置位查询API调用");
  92 + }
  93 + Device device = storager.queryVideoDevice(deviceId);
  94 + cmder.presetQuery(device, channelId, event -> {
  95 + Response response = event.getResponse();
  96 + RequestMessage msg = new RequestMessage();
  97 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  98 + msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  99 + resultHolder.invokeResult(msg);
  100 + });
  101 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
  102 + result.onTimeout(()->{
  103 + logger.warn(String.format("获取设备预置位超时"));
  104 + // 释放rtpserver
  105 + RequestMessage msg = new RequestMessage();
  106 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId));
  107 + msg.setData("获取设备预置位超时");
  108 + resultHolder.invokeResult(msg);
  109 + });
  110 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result);
  111 + return result;
  112 + }
73 113 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java
1 1 package com.genersoft.iot.vmp.vmanager.service;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
4   -import com.genersoft.iot.vmp.common.StreamInfo;
5 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 5 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
7 6 import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
8   -import org.springframework.http.ResponseEntity;
9   -import org.springframework.web.context.request.async.DeferredResult;
10 7  
11 8 /**
12 9 * 点播处理
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
1 1 package com.genersoft.iot.vmp.vmanager.user;
2 2  
3   -import com.genersoft.iot.vmp.vmanager.play.PlayController;
4   -import org.slf4j.Logger;
5   -import org.slf4j.LoggerFactory;
6 3 import org.springframework.beans.factory.annotation.Value;
7 4 import org.springframework.util.StringUtils;
8 5 import org.springframework.web.bind.annotation.CrossOrigin;
... ... @@ -14,9 +11,6 @@ import org.springframework.web.bind.annotation.RestController;
14 11 @RequestMapping("/api")
15 12 public class UserController {
16 13  
17   - private final static Logger logger = LoggerFactory.getLogger(UserController.class);
18   -
19   -
20 14 @Value("${auth.username}")
21 15 private String usernameConfig;
22 16  
... ...
src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java
... ... @@ -4,12 +4,9 @@ import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
6 6 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
7   -import com.genersoft.iot.vmp.vmanager.ptz.PtzController;
8 7 import org.slf4j.Logger;
9 8 import org.slf4j.LoggerFactory;
10 9 import org.springframework.beans.factory.annotation.Autowired;
11   -import org.springframework.http.HttpStatus;
12   -import org.springframework.http.ResponseEntity;
13 10 import org.springframework.web.bind.annotation.*;
14 11  
15 12 /**
... ...
src/main/java/com/genersoft/iot/vmp/web/ApiController.java
... ... @@ -5,11 +5,9 @@ import com.genersoft.iot.vmp.conf.SipConfig;
5 5 import org.slf4j.Logger;
6 6 import org.slf4j.LoggerFactory;
7 7 import org.springframework.beans.factory.annotation.Autowired;
8   -import org.springframework.beans.factory.annotation.Value;
9 8 import org.springframework.stereotype.Controller;
10 9 import org.springframework.web.bind.annotation.CrossOrigin;
11 10 import org.springframework.web.bind.annotation.RequestMapping;
12   -import org.springframework.web.bind.annotation.RequestParam;
13 11 import org.springframework.web.bind.annotation.ResponseBody;
14 12  
15 13 /**
... ...
src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java
... ... @@ -4,9 +4,9 @@ import com.alibaba.fastjson.JSONArray;
4 4 import com.alibaba.fastjson.JSONObject;
5 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
7   -import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
8   -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  7 +// import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
  8 +// import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  9 +// import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
10 10 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
11 11 import com.github.pagehelper.PageInfo;
12 12 import org.slf4j.Logger;
... ... @@ -19,6 +19,7 @@ import java.util.List;
19 19 /**
20 20 * 兼容LiveGBS的API:设备信息
21 21 */
  22 +@SuppressWarnings("unchecked")
22 23 @CrossOrigin
23 24 @RestController
24 25 @RequestMapping(value = "/api/v1/device")
... ... @@ -29,14 +30,14 @@ public class ApiDeviceController {
29 30 @Autowired
30 31 private IVideoManagerStorager storager;
31 32  
32   - @Autowired
33   - private SIPCommander cmder;
  33 + // @Autowired
  34 + // private SIPCommander cmder;
34 35  
35   - @Autowired
36   - private DeferredResultHolder resultHolder;
  36 + // @Autowired
  37 + // private DeferredResultHolder resultHolder;
37 38  
38   - @Autowired
39   - private DeviceOffLineDetector offLineDetector;
  39 + // @Autowired
  40 + // private DeviceOffLineDetector offLineDetector;
40 41  
41 42 /**
42 43 * 分页获取设备列表 TODO 现在直接返回,尚未实现分页
... ...
src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java
1 1 package com.genersoft.iot.vmp.web;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4   -import com.alibaba.fastjson.JSONArray;
5 4 import com.alibaba.fastjson.JSONObject;
6 5 import com.genersoft.iot.vmp.common.StreamInfo;
7 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
8 7 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
9 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
10   -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  9 +// import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
11 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
13 12 import com.genersoft.iot.vmp.vmanager.play.PlayController;
14 13 import org.slf4j.Logger;
15 14 import org.slf4j.LoggerFactory;
16 15 import org.springframework.beans.factory.annotation.Autowired;
17   -import org.springframework.beans.factory.annotation.Value;
18   -import org.springframework.http.HttpStatus;
19 16 import org.springframework.http.ResponseEntity;
20 17 import org.springframework.web.bind.annotation.*;
21 18 import org.springframework.web.context.request.async.DeferredResult;
... ... @@ -23,6 +20,7 @@ import org.springframework.web.context.request.async.DeferredResult;
23 20 /**
24 21 * 兼容LiveGBS的API:实时直播
25 22 */
  23 +@SuppressWarnings(value = {"rawtypes", "unchecked"})
26 24 @CrossOrigin
27 25 @RestController
28 26 @RequestMapping(value = "/api/v1/stream")
... ... @@ -40,8 +38,8 @@ public class ApiStreamController {
40 38 private IRedisCatchStorage redisCatchStorage;
41 39  
42 40  
43   - @Autowired
44   - private ZLMRESTfulUtils zlmresTfulUtils;
  41 + // @Autowired
  42 + // private ZLMRESTfulUtils zlmresTfulUtils;
45 43  
46 44  
47 45 @Autowired
... ...
src/main/java/com/genersoft/iot/vmp/web/AuthController.java
1 1 package com.genersoft.iot.vmp.web;
2 2  
3   -import com.genersoft.iot.vmp.gb28181.bean.Device;
4 3 import org.springframework.beans.factory.annotation.Value;
5   -import org.springframework.http.ResponseEntity;
6   -import org.springframework.stereotype.Controller;
7 4 import org.springframework.util.StringUtils;
8 5 import org.springframework.web.bind.annotation.*;
9 6  
... ...
src/main/resources/application-dev.yml
... ... @@ -92,4 +92,8 @@ logging:
92 92 level:
93 93 com:
94 94 genersoft:
95   - iot: debug
96 95 \ No newline at end of file
  96 + iot: debug
  97 +# [根据业务需求配置]
  98 +userSettings:
  99 + # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
  100 + savePositionHistory: false
97 101 \ No newline at end of file
... ...
web_src/.postcssrc.js
... ... @@ -7,7 +7,7 @@ module.exports = {
7 7 // to edit target browsers: use "browserslist" field in package.json
8 8 "autoprefixer": {},
9 9 'postcss-pxtorem': {
10   - rootValue: 16,
  10 + rootValue: 24,
11 11 propList: ['font-size'] // 只转化font-size
12 12 }
13 13 }
... ...
web_src/index.html
... ... @@ -7,6 +7,7 @@
7 7 </head>
8 8 <body>
9 9 <script type="text/javascript" src="./js/EasyWasmPlayer.js"></script>
  10 + <script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=rk73w8dv1rkE4UdZsataG68VarhYQzrx&s=1"></script>
10 11 <div id="app"></div>
11 12 <!-- built files will be auto injected -->
12 13 </body>
... ...
web_src/package-lock.json
... ... @@ -1269,6 +1269,34 @@
1269 1269 "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=",
1270 1270 "dev": true
1271 1271 },
  1272 + "bmaplib.curveline": {
  1273 + "version": "1.0.0",
  1274 + "resolved": "https://registry.npmjs.org/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
  1275 + "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q=="
  1276 + },
  1277 + "bmaplib.heatmap": {
  1278 + "version": "1.0.4",
  1279 + "resolved": "https://registry.npmjs.org/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
  1280 + "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q=="
  1281 + },
  1282 + "bmaplib.lushu": {
  1283 + "version": "1.0.7",
  1284 + "resolved": "https://registry.npmjs.org/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz",
  1285 + "integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w=="
  1286 + },
  1287 + "bmaplib.markerclusterer": {
  1288 + "version": "1.0.13",
  1289 + "resolved": "https://registry.npmjs.org/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
  1290 + "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
  1291 + "requires": {
  1292 + "bmaplib.texticonoverlay": "^1.0.2"
  1293 + }
  1294 + },
  1295 + "bmaplib.texticonoverlay": {
  1296 + "version": "1.0.2",
  1297 + "resolved": "https://registry.npmjs.org/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
  1298 + "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg=="
  1299 + },
1272 1300 "bn.js": {
1273 1301 "version": "5.1.3",
1274 1302 "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.3.tgz",
... ... @@ -5266,6 +5294,14 @@
5266 5294 "invert-kv": "^1.0.0"
5267 5295 }
5268 5296 },
  5297 + "linkify-it": {
  5298 + "version": "2.2.0",
  5299 + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
  5300 + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
  5301 + "requires": {
  5302 + "uc.micro": "^1.0.1"
  5303 + }
  5304 + },
5269 5305 "load-json-file": {
5270 5306 "version": "2.0.0",
5271 5307 "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz",
... ... @@ -5443,6 +5479,25 @@
5443 5479 "object-visit": "^1.0.0"
5444 5480 }
5445 5481 },
  5482 + "markdown-it": {
  5483 + "version": "8.4.2",
  5484 + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
  5485 + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
  5486 + "requires": {
  5487 + "argparse": "^1.0.7",
  5488 + "entities": "~1.1.1",
  5489 + "linkify-it": "^2.0.0",
  5490 + "mdurl": "^1.0.1",
  5491 + "uc.micro": "^1.0.5"
  5492 + },
  5493 + "dependencies": {
  5494 + "entities": {
  5495 + "version": "1.1.2",
  5496 + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
  5497 + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
  5498 + }
  5499 + }
  5500 + },
5446 5501 "math-expression-evaluator": {
5447 5502 "version": "1.2.22",
5448 5503 "resolved": "https://registry.npm.taobao.org/math-expression-evaluator/download/math-expression-evaluator-1.2.22.tgz",
... ... @@ -5466,6 +5521,11 @@
5466 5521 "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=",
5467 5522 "dev": true
5468 5523 },
  5524 + "mdurl": {
  5525 + "version": "1.0.1",
  5526 + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
  5527 + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
  5528 + },
5469 5529 "media-typer": {
5470 5530 "version": "0.3.0",
5471 5531 "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
... ... @@ -10074,8 +10134,7 @@
10074 10134 "sprintf-js": {
10075 10135 "version": "1.0.3",
10076 10136 "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz",
10077   - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
10078   - "dev": true
  10137 + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
10079 10138 },
10080 10139 "ssri": {
10081 10140 "version": "5.3.0",
... ... @@ -10489,6 +10548,11 @@
10489 10548 "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
10490 10549 "dev": true
10491 10550 },
  10551 + "uc.micro": {
  10552 + "version": "1.0.6",
  10553 + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
  10554 + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
  10555 + },
10492 10556 "uglify-js": {
10493 10557 "version": "3.4.10",
10494 10558 "resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1601823880483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz",
... ... @@ -10841,6 +10905,18 @@
10841 10905 "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1600441238751&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
10842 10906 "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
10843 10907 },
  10908 + "vue-baidu-map": {
  10909 + "version": "0.21.22",
  10910 + "resolved": "https://registry.npmjs.org/vue-baidu-map/-/vue-baidu-map-0.21.22.tgz",
  10911 + "integrity": "sha512-WQMPCih4UTh0AZCKKH/OVOYnyAWjfRNeK6BIeoLmscyY5aF8zzlJhz/NOHLb3mdztIpB0Z6aohn4Jd9mfCSjQw==",
  10912 + "requires": {
  10913 + "bmaplib.curveline": "^1.0.0",
  10914 + "bmaplib.heatmap": "^1.0.4",
  10915 + "bmaplib.lushu": "^1.0.7",
  10916 + "bmaplib.markerclusterer": "^1.0.13",
  10917 + "markdown-it": "^8.4.0"
  10918 + }
  10919 + },
10844 10920 "vue-clipboard2": {
10845 10921 "version": "0.3.1",
10846 10922 "resolved": "https://registry.npm.taobao.org/vue-clipboard2/download/vue-clipboard2-0.3.1.tgz",
... ...
web_src/package.json
... ... @@ -19,6 +19,7 @@
19 19 "moment": "^2.29.1",
20 20 "postcss-pxtorem": "^5.1.1",
21 21 "vue": "^2.6.11",
  22 + "vue-baidu-map": "^0.21.22",
22 23 "vue-clipboard2": "^0.3.1",
23 24 "vue-cookies": "^1.7.4",
24 25 "vue-router": "^3.1.6"
... ...
web_src/src/components/GeoConvertTools.js 0 → 100644
  1 +/**
  2 + * 经纬度转换
  3 + */
  4 +export default {
  5 + PI: 3.1415926535897932384626,
  6 + //PI: 3.14159265358979324,
  7 + x_pi: (3.1415926535897932384626 * 3000.0) / 180.0,
  8 + delta: function (lat, lng) {
  9 + // Krasovsky 1940
  10 + //
  11 + // a = 6378245.0, 1/f = 298.3
  12 + // b = a * (1 - f)
  13 + // ee = (a^2 - b^2) / a^2;
  14 + var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
  15 + var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
  16 + var dLat = this.transformLat(lng - 105.0, lat - 35.0);
  17 + var dLng = this.transformLng(lng - 105.0, lat - 35.0);
  18 + var radLat = (lat / 180.0) * this.PI;
  19 + var magic = Math.sin(radLat);
  20 + magic = 1 - ee * magic * magic;
  21 + var sqrtMagic = Math.sqrt(magic);
  22 + dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * this.PI);
  23 + dLng = (dLng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * this.PI);
  24 + return {
  25 + lat: dLat,
  26 + lng: dLng
  27 + };
  28 + },
  29 + /**
  30 + * WGS-84 to GCJ-02 GPS坐标转中国坐标
  31 + * @param {number} wgsLat GPS纬度
  32 + * @param {number} wgsLng GPS经度
  33 + * @return {object} 返回中国坐标经纬度对象
  34 + */
  35 + GPSToChina: function (wgsLat, wgsLng) {
  36 + if (this.outOfChina(wgsLat, wgsLng)) return {
  37 + lat: wgsLat,
  38 + lng: wgsLng
  39 + };
  40 + var d = this.delta(wgsLat, wgsLng);
  41 + return {
  42 + lat: Number(wgsLat) + Number(d.lat),
  43 + lng: Number(wgsLng) + Number(d.lng)
  44 + };
  45 + },
  46 + /**
  47 + * GCJ-02 to WGS-84 中国标准坐标转GPS坐标
  48 + * @param {number} gcjLat 中国标准坐标纬度
  49 + * @param {number} gcjLng 中国标准坐标经度
  50 + * @return {object} 返回GPS经纬度对象
  51 + */
  52 + chinaToGPS: function (gcjLat, gcjLng) {
  53 + if (this.outOfChina(gcjLat, gcjLng)) return {
  54 + lat: gcjLat,
  55 + lng: gcjLng
  56 + };
  57 + var d = this.delta(gcjLat, gcjLng);
  58 + return {
  59 + lat: Number(gcjLat) - Number(d.lat),
  60 + lng: Number(gcjLng) - Number(d.lng)
  61 + };
  62 + },
  63 + /**
  64 + * GCJ-02 to WGS-84 exactly 中国标准坐标转GPS坐标(精确)
  65 + * @param {number} gcjLat 中国标准坐标纬度
  66 + * @param {number} gcjLng 中国标准坐标经度
  67 + * @return {object} 返回GPS经纬度对象(精确)
  68 + */
  69 + chinaToGPSExact: function (gcjLat, gcjLng) {
  70 + var initDelta = 0.01;
  71 + var threshold = 0.000000001;
  72 + var dLat = initDelta,
  73 + dLng = initDelta;
  74 + var mLat = gcjLat - dLat,
  75 + mLng = gcjLng - dLng;
  76 + var pLat = gcjLat + dLat,
  77 + pLng = gcjLng + dLng;
  78 + var wgsLat,
  79 + wgsLng,
  80 + i = 0;
  81 + while (1) {
  82 + wgsLat = (mLat + pLat) / 2;
  83 + wgsLng = (mLng + pLng) / 2;
  84 + var tmp = this.gcj_encrypt(wgsLat, wgsLng);
  85 + dLat = tmp.lat - gcjLat;
  86 + dLng = tmp.lng - gcjLng;
  87 + if (Math.abs(dLat) < threshold && Math.abs(dLng) < threshold) break;
  88 +
  89 + if (dLat > 0) pLat = wgsLat;
  90 + else mLat = wgsLat;
  91 + if (dLng > 0) pLng = wgsLng;
  92 + else mLng = wgsLng;
  93 +
  94 + if (++i > 10000) break;
  95 + }
  96 + //console.log(i);
  97 + return {
  98 + lat: wgsLat,
  99 + lng: wgsLng
  100 + };
  101 + },
  102 + /**
  103 + * GCJ-02 to BD-09 中国标准坐标转百度坐标(精确)
  104 + * @param {number} gcjLat 中国标准坐标纬度
  105 + * @param {number} gcjLng 中国标准坐标经度
  106 + * @return {object} 返回百度经纬度对象
  107 + */
  108 + chinaToBaidu: function (gcjLat, gcjLng) {
  109 + var x = gcjLng,
  110 + y = gcjLat;
  111 + var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);
  112 + var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);
  113 + var bdLng = z * Math.cos(theta) + 0.0065;
  114 + var bdLat = z * Math.sin(theta) + 0.006;
  115 + return {
  116 + lat: bdLat,
  117 + lng: bdLng
  118 + };
  119 + },
  120 + /**
  121 + * BD-09 to GCJ-02 百度坐标转中国标准坐标
  122 + * @param {number} bdLat 百度坐标纬度
  123 + * @param {number} bdLng 百度坐标经度
  124 + * @return {object} 返回中国标准经纬度对象
  125 + */
  126 + baiduToChina: function (bdLat, bdLng) {
  127 + var x = bdLng - 0.0065,
  128 + y = bdLat - 0.006;
  129 + var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);
  130 + var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);
  131 + var gcjLng = z * Math.cos(theta);
  132 + var gcjLat = z * Math.sin(theta);
  133 + return {
  134 + lat: gcjLat,
  135 + lng: gcjLng
  136 + };
  137 + },
  138 + /**
  139 + * BD-09 to GCJ-02 百度坐标转gps坐标
  140 + * @param {number} bdLat 百度坐标纬度
  141 + * @param {number} bdLng 百度坐标经度
  142 + * @return {object} 返回gps经纬度对象
  143 + */
  144 + baiduToGPS: function (bdLat, bdLng) {
  145 + let china = this.baiduToChina(bdLat, bdLng);
  146 + return this.chinaToGPS(china.lat, china.lng);
  147 + },
  148 + /**
  149 + * WGS-84 to to BD-09 GPS坐标转Baidu坐标
  150 + * @param {number} gpsLat GPS纬度
  151 + * @param {number} gpsLng GPS经度
  152 + * @return {object} 返回百度经纬度对象
  153 + */
  154 + GPSToBaidu: function (gpsLat, gpsLng) {
  155 + var china = this.GPSToChina(gpsLat, gpsLng);
  156 + return this.chinaToBaidu(china.lat, china.lng);
  157 + },
  158 + /**
  159 + * WGS-84 to Web mercator GPS坐标转墨卡托坐标
  160 + * @param {number} wgsLat GPS纬度
  161 + * @param {number} wgsLng GPS经度
  162 + * @return {object} 返回墨卡托经纬度对象
  163 + */
  164 + GPSToMercator: function (wgsLat, wgsLng) {
  165 + var x = (wgsLng * 20037508.34) / 180;
  166 + var y = Math.log(Math.tan(((90 + wgsLat) * this.PI) / 360)) / (this.PI / 180);
  167 + y = (y * 20037508.34) / 180;
  168 + return {
  169 + lat: y,
  170 + lng: x
  171 + };
  172 + /*
  173 + if ((Math.abs(wgsLng) > 180 || Math.abs(wgsLat) > 90))
  174 + return null;
  175 + var x = 6378137.0 * wgsLng * 0.017453292519943295;
  176 + var a = wgsLat * 0.017453292519943295;
  177 + var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
  178 + return {'lat' : y, 'lng' : x};
  179 + //*/
  180 + },
  181 + /**
  182 + * Web mercator to WGS-84 墨卡托坐标转GPS坐标
  183 + * @param {number} mercatorLat 墨卡托纬度
  184 + * @param {number} mercatorLng 墨卡托经度
  185 + * @return {object} 返回GPS经纬度对象
  186 + */
  187 + mercatorToGPS: function (mercatorLat, mercatorLng) {
  188 + var x = (mercatorLng / 20037508.34) * 180;
  189 + var y = (mercatorLat / 20037508.34) * 180;
  190 + y = (180 / this.PI) * (2 * Math.atan(Math.exp((y * this.PI) / 180)) - this.PI / 2);
  191 + return {
  192 + lat: y,
  193 + lng: x
  194 + };
  195 + /*
  196 + if (Math.abs(mercatorLng) < 180 && Math.abs(mercatorLat) < 90)
  197 + return null;
  198 + if ((Math.abs(mercatorLng) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892))
  199 + return null;
  200 + var a = mercatorLng / 6378137.0 * 57.295779513082323;
  201 + var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0);
  202 + var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323;
  203 + return {'lat' : y, 'lng' : x};
  204 + //*/
  205 + },
  206 + /**
  207 + * 两点之间的距离
  208 + * @param {number} latA 起点纬度
  209 + * @param {number} lngA 起点经度
  210 + * @param {number} latB 终点纬度
  211 + * @param {number} lngB 终点经度
  212 + * @return {number} 返回距离(米)
  213 + */
  214 + distance: function (latA, lngA, latB, lngB) {
  215 + var earthR = 6371000;
  216 + var x = Math.cos((latA * this.PI) / 180) * Math.cos((latB * this.PI) / 180) * Math.cos(((lngA - lngB) * this.PI) / 180);
  217 + var y = Math.sin((latA * this.PI) / 180) * Math.sin((latB * this.PI) / 180);
  218 + var s = x + y;
  219 + if (s > 1) s = 1;
  220 + if (s < -1) s = -1;
  221 + var alpha = Math.acos(s);
  222 + var distance = alpha * earthR;
  223 + return distance;
  224 + },
  225 + /**
  226 + * 是否在中国之外
  227 + * @param {number} lat 纬度
  228 + * @param {number} lng 经度
  229 + * @return {boolean]} 返回结果真或假
  230 + */
  231 + outOfChina: function (lat, lng) {
  232 + if (lat < 72.004 || lat > 137.8347) return true;
  233 + if (lng < 0.8293 || lng > 55.8271) return true;
  234 + return false;
  235 + },
  236 + transformLat: function (x, y) {
  237 + var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
  238 + ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0;
  239 + ret += ((20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin((y / 3.0) * this.PI)) * 2.0) / 3.0;
  240 + ret += ((160.0 * Math.sin((y / 12.0) * this.PI) + 320 * Math.sin((y * this.PI) / 30.0)) * 2.0) / 3.0;
  241 + return ret;
  242 + },
  243 + transformLng: function (x, y) {
  244 + var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
  245 + ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0;
  246 + ret += ((20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin((x / 3.0) * this.PI)) * 2.0) / 3.0;
  247 + ret += ((150.0 * Math.sin((x / 12.0) * this.PI) + 300.0 * Math.sin((x / 30.0) * this.PI)) * 2.0) / 3.0;
  248 + return ret;
  249 + }
  250 +};
... ...