Commit 0f58218badea86a5209ae7f1ccd60b7cb4b26eee
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
68 changed files
with
3578 additions
and
494 deletions
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 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 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
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
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
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
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
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
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>=#{startTime}</if>" + | |
| 21 | + "<if test=\"endTime != null\"> AND time<=#{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
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
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 | +}; | ... | ... |
web_src/src/components/Login.vue
| ... | ... | @@ -29,14 +29,13 @@ export default { |
| 29 | 29 | } |
| 30 | 30 | }, |
| 31 | 31 | created(){ |
| 32 | - var that = this; | |
| 33 | - document.onkeydown = function(e) { | |
| 34 | - var key = window.event.keyCode; | |
| 35 | - if (key == 13) { | |
| 36 | - that.login(); | |
| 32 | + var that = this; | |
| 33 | + document.onkeydown = function(e) { | |
| 34 | + var key = window.event.keyCode; | |
| 35 | + if (key == 13) { | |
| 36 | + that.login(); | |
| 37 | + } | |
| 37 | 38 | } |
| 38 | - } | |
| 39 | - | |
| 40 | 39 | }, |
| 41 | 40 | methods:{ |
| 42 | 41 | |
| ... | ... | @@ -70,6 +69,7 @@ export default { |
| 70 | 69 | if (res.data == "success") { |
| 71 | 70 | that.$cookies.set("session", {"username": that.username}) ; |
| 72 | 71 | //登录成功后 |
| 72 | + that.cancelEnterkeyDefaultAction(); | |
| 73 | 73 | that.$router.push('/'); |
| 74 | 74 | }else{ |
| 75 | 75 | that.isLoging = false; |
| ... | ... | @@ -84,18 +84,23 @@ export default { |
| 84 | 84 | that.$message.error(error.response.statusText); |
| 85 | 85 | that.isLoging = false; |
| 86 | 86 | }); |
| 87 | - | |
| 88 | - | |
| 89 | - | |
| 90 | 87 | }, |
| 91 | - setCookie: function (cname, cvalue, exdays) { | |
| 92 | - var d = new Date(); | |
| 93 | - d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); | |
| 94 | - var expires = "expires=" + d.toUTCString(); | |
| 95 | - console.info(cname + "=" + cvalue + "; " + expires); | |
| 96 | - document.cookie = cname + "=" + cvalue + "; " + expires; | |
| 97 | - console.info(document.cookie); | |
| 98 | - }, | |
| 88 | + setCookie: function (cname, cvalue, exdays) { | |
| 89 | + var d = new Date(); | |
| 90 | + d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); | |
| 91 | + var expires = "expires=" + d.toUTCString(); | |
| 92 | + console.info(cname + "=" + cvalue + "; " + expires); | |
| 93 | + document.cookie = cname + "=" + cvalue + "; " + expires; | |
| 94 | + console.info(document.cookie); | |
| 95 | + }, | |
| 96 | + cancelEnterkeyDefaultAction: function() { | |
| 97 | + document.onkeydown = function(e) { | |
| 98 | + var key = window.event.keyCode; | |
| 99 | + if (key == 13) { | |
| 100 | + return false; | |
| 101 | + } | |
| 102 | + } | |
| 103 | + } | |
| 99 | 104 | } |
| 100 | 105 | } |
| 101 | 106 | </script> | ... | ... |
web_src/src/components/UiHeader.vue
| ... | ... | @@ -34,7 +34,7 @@ export default { |
| 34 | 34 | let that = this; |
| 35 | 35 | if (this.alarmNotify) { |
| 36 | 36 | console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId); |
| 37 | - this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId); | |
| 37 | + this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId); | |
| 38 | 38 | this.sseSource.addEventListener('message', function(evt) { |
| 39 | 39 | that.$notify({ |
| 40 | 40 | title: '收到报警信息', |
| ... | ... | @@ -59,7 +59,7 @@ export default { |
| 59 | 59 | this.sseSource.removeEventListener('message', null); |
| 60 | 60 | this.sseSource.removeEventListener('error', null); |
| 61 | 61 | this.sseSource.close(); |
| 62 | - } | |
| 62 | + } | |
| 63 | 63 | } |
| 64 | 64 | }, |
| 65 | 65 | mounted() { | ... | ... |
web_src/src/components/devicePosition.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div id="devicePosition" style="height: 100%"> | |
| 3 | + <el-container style="height: 100%"> | |
| 4 | + <el-header> | |
| 5 | + <uiHeader></uiHeader> | |
| 6 | + </el-header> | |
| 7 | + <el-main> | |
| 8 | + <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> | |
| 9 | + <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span> | |
| 10 | + </div> | |
| 11 | + <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;"> | |
| 12 | + <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button> | |
| 13 | + <!-- <span class="demonstration">从</span> --> | |
| 14 | + <el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> | |
| 15 | + <el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> | |
| 16 | + <el-button-group> | |
| 17 | + <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button> | |
| 18 | + <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button> | |
| 19 | + </el-button-group> | |
| 20 | + <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag> | |
| 21 | + <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number> | |
| 22 | + <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag> | |
| 23 | + <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number> | |
| 24 | + <el-button-group> | |
| 25 | + <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button> | |
| 26 | + <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button> | |
| 27 | + </el-button-group> | |
| 28 | + <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox> | |
| 29 | + </div> | |
| 30 | + <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);"> | |
| 31 | + <div class="baidumap" id="allmap"></div> | |
| 32 | + </div> | |
| 33 | + </el-main> | |
| 34 | + </el-container> | |
| 35 | + </div> | |
| 36 | +</template> | |
| 37 | + | |
| 38 | +<script> | |
| 39 | +import uiHeader from "./UiHeader.vue"; | |
| 40 | +import moment from "moment"; | |
| 41 | +import geoTools from "./GeoConvertTools.js"; | |
| 42 | +export default { | |
| 43 | + name: "devicePosition", | |
| 44 | + components: { | |
| 45 | + uiHeader, | |
| 46 | + }, | |
| 47 | + data() { | |
| 48 | + return { | |
| 49 | + pickerOptions: { | |
| 50 | + shortcuts: [{ | |
| 51 | + text: '今天', | |
| 52 | + onClick(picker) { | |
| 53 | + picker.$emit('pick', new Date()); | |
| 54 | + } | |
| 55 | + }, { | |
| 56 | + text: '昨天', | |
| 57 | + onClick(picker) { | |
| 58 | + const date = new Date(); | |
| 59 | + date.setTime(date.getTime() - 3600 * 1000 * 24); | |
| 60 | + picker.$emit('pick', date); | |
| 61 | + } | |
| 62 | + }, { | |
| 63 | + text: '一周前', | |
| 64 | + onClick(picker) { | |
| 65 | + const date = new Date(); | |
| 66 | + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); | |
| 67 | + picker.$emit('pick', date); | |
| 68 | + } | |
| 69 | + }] | |
| 70 | + }, | |
| 71 | + deviceId: this.$route.params.deviceId, | |
| 72 | + showHistoryPosition: false, //显示历史轨迹 | |
| 73 | + startTime: null, | |
| 74 | + endTime: null, | |
| 75 | + searchFrom: null, | |
| 76 | + searchTo: null, | |
| 77 | + expired: 600, | |
| 78 | + interval: 5, | |
| 79 | + mobilePositionList: [], | |
| 80 | + mapPointList: [], | |
| 81 | + parentChannelId: this.$route.params.parentChannelId, | |
| 82 | + updateLooper: 0, //数据刷新轮训标志 | |
| 83 | + total: 0, | |
| 84 | + beforeUrl: "/videoList", | |
| 85 | + isLoging: false, | |
| 86 | + autoList: false, | |
| 87 | + }; | |
| 88 | + }, | |
| 89 | + mounted() { | |
| 90 | + this.initData(); | |
| 91 | + this.initBaiduMap(); | |
| 92 | + if (this.autoList) { | |
| 93 | + this.updateLooper = setInterval(this.initData, 5000); | |
| 94 | + } | |
| 95 | + }, | |
| 96 | + destroyed() { | |
| 97 | + // this.$destroy("videojs"); | |
| 98 | + clearTimeout(this.updateLooper); | |
| 99 | + }, | |
| 100 | + methods: { | |
| 101 | + initData: function () { | |
| 102 | + // if (this.parentChannelId == "" || this.parentChannelId == 0) { | |
| 103 | + // this.getDeviceChannelList(); | |
| 104 | + // } else { | |
| 105 | + // this.showSubchannels(); | |
| 106 | + // } | |
| 107 | + }, | |
| 108 | + initParam: function () { | |
| 109 | + // this.deviceId = this.$route.params.deviceId; | |
| 110 | + // this.parentChannelId = this.$route.params.parentChannelId; | |
| 111 | + // this.currentPage = parseInt(this.$route.params.page); | |
| 112 | + // this.count = parseInt(this.$route.params.count); | |
| 113 | + // if (this.parentChannelId == "" || this.parentChannelId == 0) { | |
| 114 | + // this.beforeUrl = "/videoList"; | |
| 115 | + // } | |
| 116 | + }, | |
| 117 | + initBaiduMap() { | |
| 118 | + this.map = new BMap.Map("allmap"); // 创建地图实例 | |
| 119 | + let points = []; | |
| 120 | + let point = new BMap.Point(116.231398, 39.567445); // 创建点坐标 | |
| 121 | + this.map.centerAndZoom(point, 5); // 初始化地图,设置中心点坐标和地图级别 | |
| 122 | + this.map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放 | |
| 123 | + this.map.addControl(new BMap.NavigationControl()); | |
| 124 | + this.map.addControl(new BMap.ScaleControl()); | |
| 125 | + this.map.addControl(new BMap.OverviewMapControl()); | |
| 126 | + this.map.addControl(new BMap.MapTypeControl()); | |
| 127 | + //map.setMapStyle({ style: 'midnight' }) //地图风格 | |
| 128 | + }, | |
| 129 | + currentChange: function (val) { | |
| 130 | + // var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`; | |
| 131 | + // console.log(url); | |
| 132 | + // this.$router.push(url).then(() => { | |
| 133 | + // this.initParam(); | |
| 134 | + // this.initData(); | |
| 135 | + // }); | |
| 136 | + }, | |
| 137 | + handleSizeChange: function (val) { | |
| 138 | + // var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`; | |
| 139 | + // this.$router.push(url).then(() => { | |
| 140 | + // this.initParam(); | |
| 141 | + // this.initData(); | |
| 142 | + // }); | |
| 143 | + }, | |
| 144 | + showDevice: function () { | |
| 145 | + this.$router.push(this.beforeUrl).then(() => { | |
| 146 | + this.initParam(); | |
| 147 | + this.initData(); | |
| 148 | + }); | |
| 149 | + }, | |
| 150 | + autoListChange: function () { | |
| 151 | + if (this.autoList) { | |
| 152 | + this.updateLooper = setInterval(this.initData, 1500); | |
| 153 | + } else { | |
| 154 | + window.clearInterval(this.updateLooper); | |
| 155 | + } | |
| 156 | + }, | |
| 157 | + showHistoryPath: function () { | |
| 158 | + this.map.clearOverlays(); | |
| 159 | + this.mapPointList = []; | |
| 160 | + this.mobilePositionList = []; | |
| 161 | + if (!!this.searchFrom) { | |
| 162 | + this.startTime = this.toGBString(this.searchFrom); | |
| 163 | + console.log(this.startTime); | |
| 164 | + } else{ | |
| 165 | + this.startTime = null; | |
| 166 | + } | |
| 167 | + if (!!this.searchTo) { | |
| 168 | + this.endTime = this.toGBString(this.searchTo); | |
| 169 | + console.log(this.endTime); | |
| 170 | + } else { | |
| 171 | + this.endTime = null; | |
| 172 | + } | |
| 173 | + let self = this; | |
| 174 | + this.$axios.get(`/api/positions/${this.deviceId}/history`, { | |
| 175 | + params: { | |
| 176 | + start: self.startTime, | |
| 177 | + end: self.endTime, | |
| 178 | + }, | |
| 179 | + }) | |
| 180 | + .then(function (res) { | |
| 181 | + self.total = res.data.length; | |
| 182 | + self.mobilePositionList = res.data; | |
| 183 | + console.log(self.mobilePositionList); | |
| 184 | + if (self.total == 0) { | |
| 185 | + self.$message({ | |
| 186 | + showClose: true, | |
| 187 | + message: '未找到符合条件的移动位置信息', | |
| 188 | + type: 'error' | |
| 189 | + }); | |
| 190 | + } else { | |
| 191 | + self.$nextTick(() => { | |
| 192 | + self.showMarkPoints(self); | |
| 193 | + }); | |
| 194 | + } | |
| 195 | + }) | |
| 196 | + .catch(function (error) { | |
| 197 | + console.log(error); | |
| 198 | + }); | |
| 199 | + }, | |
| 200 | + showLatestPosition: function() { | |
| 201 | + this.map.clearOverlays(); | |
| 202 | + this.mapPointList = []; | |
| 203 | + this.mobilePositionList = []; | |
| 204 | + let self = this; | |
| 205 | + this.$axios.get(`/api/positions/${this.deviceId}/latest`) | |
| 206 | + .then(function (res) { | |
| 207 | + console.log(res.data); | |
| 208 | + self.total = res.data.length; | |
| 209 | + self.mobilePositionList.push(res.data); | |
| 210 | + console.log(self.mobilePositionList); | |
| 211 | + if (self.total == 0) { | |
| 212 | + self.$message({ | |
| 213 | + showClose: true, | |
| 214 | + message: '未找到符合条件的移动位置信息', | |
| 215 | + type: 'error' | |
| 216 | + }); | |
| 217 | + } else { | |
| 218 | + self.$nextTick(() => { | |
| 219 | + self.showMarkPoints(self); | |
| 220 | + }); | |
| 221 | + } | |
| 222 | + }) | |
| 223 | + .catch(function (error) { | |
| 224 | + console.log(error); | |
| 225 | + }); | |
| 226 | + }, | |
| 227 | + subscribeMobilePosition: function() { | |
| 228 | + let self = this; | |
| 229 | + this.$axios.get(`/api/positions/${this.deviceId}/subscribe`, { | |
| 230 | + params: { | |
| 231 | + expires: self.expired, | |
| 232 | + interval: self.interval, | |
| 233 | + }, | |
| 234 | + }) | |
| 235 | + .then(function (res) { | |
| 236 | + console.log(res.data); | |
| 237 | + }) | |
| 238 | + .catch(function (error) { | |
| 239 | + console.log(error); | |
| 240 | + }); | |
| 241 | + }, | |
| 242 | + unSubscribeMobilePosition: function() { | |
| 243 | + let self = this; | |
| 244 | + this.$axios.get(`/api/positions/${this.deviceId}/subscribe`, { | |
| 245 | + params: { | |
| 246 | + expires: 0, | |
| 247 | + interval: self.interval, | |
| 248 | + }, | |
| 249 | + }) | |
| 250 | + .then(function (res) { | |
| 251 | + console.log(res.data); | |
| 252 | + }) | |
| 253 | + .catch(function (error) { | |
| 254 | + console.log(error); | |
| 255 | + }); | |
| 256 | + }, | |
| 257 | + toGBString: function (dateTime) { | |
| 258 | + return ( | |
| 259 | + dateTime.getFullYear() + | |
| 260 | + "-" + this.twoDigits(dateTime.getMonth() + 1) + | |
| 261 | + "-" + this.twoDigits(dateTime.getDate()) + | |
| 262 | + "T" + this.twoDigits(dateTime.getHours()) + | |
| 263 | + ":" + this.twoDigits(dateTime.getMinutes()) + | |
| 264 | + ":" + this.twoDigits(dateTime.getSeconds()) | |
| 265 | + ); | |
| 266 | + }, | |
| 267 | + twoDigits: function (num) { | |
| 268 | + if (num < 10) { | |
| 269 | + return "0" + num; | |
| 270 | + } else { | |
| 271 | + return "" + num; | |
| 272 | + } | |
| 273 | + }, | |
| 274 | + showMarkPoints: function(self) { | |
| 275 | + let that = self; | |
| 276 | + let npointJ = null; | |
| 277 | + let npointW = null; | |
| 278 | + let point = null; | |
| 279 | + for (let i = 0; i < self.mobilePositionList.length; i++) { | |
| 280 | + if (self.mobilePositionList[i].geodeticSystem == "BD-09") { | |
| 281 | + npointJ = self.mobilePositionList[i].cnLng; | |
| 282 | + npointW = self.mobilePositionList[i].cnLat; | |
| 283 | + point = new BMap.Point(npointJ, npointW); | |
| 284 | + } else { | |
| 285 | + npointJ = self.mobilePositionList[i].longitude; | |
| 286 | + npointW = self.mobilePositionList[i].latitude; | |
| 287 | + let bd2 = geoTools.GPSToBaidu(npointJ, npointW); | |
| 288 | + point = new BMap.Point(bd2.lat, bd2.lng); | |
| 289 | + } | |
| 290 | + self.mapPointList.push(point); | |
| 291 | + let marker = new BMap.Marker(point); // 创建标注 | |
| 292 | + self.map.addOverlay(marker); // 将标注添加到地图中 | |
| 293 | + //提示信息 可以解析 HTML标签以及CSS | |
| 294 | + let infoWindow = new BMap.InfoWindow(`<p style='text-align:left;font-weight:800'>设备: ${self.mobilePositionList[i].deviceId}</p> | |
| 295 | + <p style='text-align:left;font-weight:0'>时间: ${self.mobilePositionList[i].time}</p>`); | |
| 296 | + // 鼠标移上标注点要发生的事 | |
| 297 | + marker.addEventListener("mouseover", function () { | |
| 298 | + this.openInfoWindow(infoWindow); | |
| 299 | + }); | |
| 300 | + // 鼠标移开标注点要发生的事 | |
| 301 | + marker.addEventListener("mouseout", function () { | |
| 302 | + this.closeInfoWindow(infoWindow); | |
| 303 | + }); | |
| 304 | + // 鼠标点击标注点要发生的事情 | |
| 305 | + marker.addEventListener("click", function () { | |
| 306 | + alert("点击"); | |
| 307 | + }); | |
| 308 | + } | |
| 309 | + let view = that.map.getViewport(eval(self.mapPointList)); | |
| 310 | + that.map.centerAndZoom(view.center, view.zoom); | |
| 311 | + }, | |
| 312 | + }, | |
| 313 | +}; | |
| 314 | +</script> | |
| 315 | + | |
| 316 | +<style> | |
| 317 | +.videoList { | |
| 318 | + display: flex; | |
| 319 | + flex-wrap: wrap; | |
| 320 | + align-content: flex-start; | |
| 321 | +} | |
| 322 | + | |
| 323 | +.video-item { | |
| 324 | + position: relative; | |
| 325 | + width: 15rem; | |
| 326 | + height: 10rem; | |
| 327 | + margin-right: 1rem; | |
| 328 | + background-color: #000000; | |
| 329 | +} | |
| 330 | + | |
| 331 | +.video-item-img { | |
| 332 | + position: absolute; | |
| 333 | + top: 0; | |
| 334 | + bottom: 0; | |
| 335 | + left: 0; | |
| 336 | + right: 0; | |
| 337 | + margin: auto; | |
| 338 | + width: 100%; | |
| 339 | + height: 100%; | |
| 340 | +} | |
| 341 | + | |
| 342 | +.video-item-img:after { | |
| 343 | + content: ""; | |
| 344 | + display: inline-block; | |
| 345 | + position: absolute; | |
| 346 | + z-index: 2; | |
| 347 | + top: 0; | |
| 348 | + bottom: 0; | |
| 349 | + left: 0; | |
| 350 | + right: 0; | |
| 351 | + margin: auto; | |
| 352 | + width: 3rem; | |
| 353 | + height: 3rem; | |
| 354 | + background-image: url("../assets/loading.png"); | |
| 355 | + background-size: cover; | |
| 356 | + background-color: #000000; | |
| 357 | +} | |
| 358 | + | |
| 359 | +.video-item-title { | |
| 360 | + position: absolute; | |
| 361 | + bottom: 0; | |
| 362 | + color: #000000; | |
| 363 | + background-color: #ffffff; | |
| 364 | + line-height: 1.5rem; | |
| 365 | + padding: 0.3rem; | |
| 366 | + width: 14.4rem; | |
| 367 | +} | |
| 368 | + | |
| 369 | +.baidumap { | |
| 370 | + width: 100%; | |
| 371 | + height: 100%; | |
| 372 | + border: none; | |
| 373 | + position: absolute; | |
| 374 | + left: 0; | |
| 375 | + top: 0; | |
| 376 | + right: 0; | |
| 377 | + bottom: 0; | |
| 378 | + margin: auto; | |
| 379 | +} | |
| 380 | + | |
| 381 | +/* 去除百度地图版权那行字 和 百度logo */ | |
| 382 | +.baidumap > .BMap_cpyCtrl { | |
| 383 | + display: none !important; | |
| 384 | +} | |
| 385 | +.baidumap > .anchorBL { | |
| 386 | + display: none !important; | |
| 387 | +} | |
| 388 | +</style> | ... | ... |
web_src/src/components/videoList.vue
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button> |
| 12 | 12 | </div> |
| 13 | 13 | </div> |
| 14 | - <devicePlayer ref="devicePlayer"></devicePlayer> | |
| 14 | + <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> | |
| 15 | 15 | <!--设备列表--> |
| 16 | 16 | <el-table :data="deviceList" border style="width: 100%" :height="winHeight"> |
| 17 | 17 | <el-table-column prop="name" label="名称" width="180" align="center"> |
| ... | ... | @@ -40,7 +40,7 @@ |
| 40 | 40 | </el-table-column> |
| 41 | 41 | <el-table-column prop="channelCount" label="通道数" align="center"> |
| 42 | 42 | </el-table-column> |
| 43 | - <el-table-column label="状态" width="180" align="center"> | |
| 43 | + <el-table-column label="状态" width="80" align="center"> | |
| 44 | 44 | <template slot-scope="scope"> |
| 45 | 45 | <div slot="reference" class="name-wrapper"> |
| 46 | 46 | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> |
| ... | ... | @@ -49,11 +49,15 @@ |
| 49 | 49 | </template> |
| 50 | 50 | </el-table-column> |
| 51 | 51 | |
| 52 | - <el-table-column label="操作" width="240" align="center" fixed="right"> | |
| 52 | + <el-table-column label="操作" width="360" align="center" fixed="right"> | |
| 53 | 53 | <template slot-scope="scope"> |
| 54 | - <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button> | |
| 55 | - <el-button size="mini" icon="el-icon-s-open" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">查看通道</el-button> | |
| 56 | - </template> | |
| 54 | + <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> | |
| 55 | + <el-button-group> | |
| 56 | + <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button> | |
| 57 | + <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button> | |
| 58 | + <el-button size="mini" icon="el-icon-s-tools" v-bind:disabled="scope.row.online==0" type="primary">控制</el-button> | |
| 59 | + </el-button-group> | |
| 60 | + </template> | |
| 57 | 61 | </el-table-column> |
| 58 | 62 | </el-table> |
| 59 | 63 | <el-pagination |
| ... | ... | @@ -73,7 +77,7 @@ |
| 73 | 77 | </template> |
| 74 | 78 | |
| 75 | 79 | <script> |
| 76 | - import uiHeader from './UiHeader.vue' | |
| 80 | + import uiHeader from './UiHeader.vue' | |
| 77 | 81 | export default { |
| 78 | 82 | name: 'app', |
| 79 | 83 | components: { |
| ... | ... | @@ -155,7 +159,10 @@ |
| 155 | 159 | console.log(JSON.stringify(row)) |
| 156 | 160 | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); |
| 157 | 161 | }, |
| 158 | - | |
| 162 | + showDevicePosition: function(row) { | |
| 163 | + console.log(JSON.stringify(row)) | |
| 164 | + this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); | |
| 165 | + }, | |
| 159 | 166 | |
| 160 | 167 | //gb28181平台对接 |
| 161 | 168 | //刷新设备信息 |
| ... | ... | @@ -191,18 +198,18 @@ |
| 191 | 198 | }, |
| 192 | 199 | //通知设备上传媒体流 |
| 193 | 200 | sendDevicePush: function(itemData) { |
| 194 | - let deviceId = this.currentDevice.deviceId; | |
| 195 | - let channelId = itemData.channelId; | |
| 196 | - console.log("通知设备推流1:" + deviceId + " : " + channelId); | |
| 197 | - let that = this; | |
| 198 | - this.$axios({ | |
| 199 | - method: 'get', | |
| 200 | - url: '/api/play/' + deviceId + '/' + channelId | |
| 201 | - }).then(function(res) { | |
| 202 | - let ssrc = res.data.ssrc; | |
| 203 | - that.$refs.devicePlayer.play(ssrc,deviceId,channelId); | |
| 204 | - }).catch(function(e) { | |
| 205 | - }); | |
| 201 | + // let deviceId = this.currentDevice.deviceId; | |
| 202 | + // let channelId = itemData.channelId; | |
| 203 | + // console.log("通知设备推流1:" + deviceId + " : " + channelId); | |
| 204 | + // let that = this; | |
| 205 | + // this.$axios({ | |
| 206 | + // method: 'get', | |
| 207 | + // url: '/api/play/' + deviceId + '/' + channelId | |
| 208 | + // }).then(function(res) { | |
| 209 | + // let ssrc = res.data.ssrc; | |
| 210 | + // that.$refs.devicePlayer.play(ssrc,deviceId,channelId); | |
| 211 | + // }).catch(function(e) { | |
| 212 | + // }); | |
| 206 | 213 | }, |
| 207 | 214 | transportChange: function (row) { |
| 208 | 215 | console.log(row); | ... | ... |
web_src/src/main.js
| ... | ... | @@ -12,21 +12,21 @@ import VueClipboard from 'vue-clipboard2'; |
| 12 | 12 | import { Notification } from 'element-ui'; |
| 13 | 13 | import Fingerprint2 from 'fingerprintjs2'; |
| 14 | 14 | |
| 15 | -// 生成唯一ID | |
| 15 | +// 鐢熸垚鍞竴ID | |
| 16 | 16 | Fingerprint2.get(function(components) { |
| 17 | 17 | const values = components.map(function(component,index) { |
| 18 | - if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样 | |
| 18 | + if (index === 0) { //鎶婂井淇℃祻瑙堝櫒閲孶A鐨剋ifi鎴G绛夌綉缁滄浛鎹㈡垚绌,涓嶇劧鍒囨崲缃戠粶浼欼D涓嶄竴鏍 | |
| 19 | 19 | return component.value.replace(/\bNetType\/\w+\b/, ''); |
| 20 | 20 | } |
| 21 | 21 | return component.value; |
| 22 | 22 | }) |
| 23 | - //console.log(values) //使用的浏览器信息npm | |
| 24 | - // 生成最终id | |
| 23 | + //console.log(values) //浣跨敤鐨勬祻瑙堝櫒淇℃伅npm | |
| 24 | + // 鐢熸垚鏈缁坕d | |
| 25 | 25 | let port = window.location.port; |
| 26 | 26 | console.log(port); |
| 27 | 27 | const fingerPrint = Fingerprint2.x64hash128(values.join(port), 31) |
| 28 | 28 | Vue.prototype.$browserId = fingerPrint; |
| 29 | - console.log("唯一标识码:" + fingerPrint); | |
| 29 | + console.log("鍞竴鏍囪瘑鐮侊細" + fingerPrint); | |
| 30 | 30 | }); |
| 31 | 31 | |
| 32 | 32 | Vue.use(VueClipboard); | ... | ... |
web_src/src/router/index.js
| ... | ... | @@ -4,6 +4,7 @@ import VueRouter from 'vue-router' |
| 4 | 4 | import control from '../components/control.vue' |
| 5 | 5 | import videoList from '../components/videoList.vue' |
| 6 | 6 | import channelList from '../components/channelList.vue' |
| 7 | +import devicePosition from '../components/devicePosition.vue' | |
| 7 | 8 | import login from '../components/Login.vue' |
| 8 | 9 | import parentPlatformList from '../components/ParentPlatformList.vue' |
| 9 | 10 | |
| ... | ... | @@ -41,5 +42,10 @@ export default new VueRouter({ |
| 41 | 42 | name: 'parentPlatformList', |
| 42 | 43 | component: parentPlatformList, |
| 43 | 44 | }, |
| 45 | + { | |
| 46 | + path: '/devicePosition/:deviceId/:parentChannelId/:count/:page', | |
| 47 | + name: 'devicePosition', | |
| 48 | + component: devicePosition, | |
| 49 | + }, | |
| 44 | 50 | ] |
| 45 | 51 | }) | ... | ... |