Commit d3fa1dd2262fc311661aa675e4a30b2423c7b130
Committed by
GitHub
Merge pull request #47 from lawrencehj/master
增加订阅与通知方法,增加移动位置支持等
Showing
36 changed files
with
3260 additions
and
249 deletions
README.md
| ... | ... | @@ -42,6 +42,14 @@ https://gitee.com/18010473990/wvp-GB28181.git |
| 42 | 42 | 12. 支持播放h265, g.711格式的流 |
| 43 | 43 | 13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](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)) |
| 44 | 44 | 14. 报警信息处理,支持向前端推送报警信息 |
| 45 | +15. 支持订阅与通知方法 | |
| 46 | + - [X] 移动位置订阅 | |
| 47 | + - [X] 移动位置通知处理 | |
| 48 | + - [ ] 报警事件订阅 | |
| 49 | + - [X] 报警事件通知处理 | |
| 50 | + - [ ] 设备目录订阅 | |
| 51 | + - [X] 设备目录通知处理 | |
| 52 | +16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 | |
| 45 | 53 | |
| 46 | 54 | # 待实现: |
| 47 | 55 | 上级级联 | ... | ... |
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/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/transmit/SIPProcessorFactory.java
| ... | ... | @@ -26,6 +26,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor; |
| 26 | 26 | import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor; |
| 27 | 27 | import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor; |
| 28 | 28 | import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor; |
| 29 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor; | |
| 29 | 30 | import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor; |
| 30 | 31 | import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor; |
| 31 | 32 | import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor; |
| ... | ... | @@ -132,7 +133,6 @@ public class SIPProcessorFactory { |
| 132 | 133 | processor.setRequestEvent(evt); |
| 133 | 134 | return processor; |
| 134 | 135 | } else if (Request.MESSAGE.equals(method)) { |
| 135 | - | |
| 136 | 136 | MessageRequestProcessor processor = new MessageRequestProcessor(); |
| 137 | 137 | processor.setRequestEvent(evt); |
| 138 | 138 | processor.setTcpSipProvider(getTcpSipProvider()); |
| ... | ... | @@ -145,13 +145,27 @@ public class SIPProcessorFactory { |
| 145 | 145 | processor.setStorager(storager); |
| 146 | 146 | processor.setRedisCatchStorage(redisCatchStorage); |
| 147 | 147 | return processor; |
| 148 | + } else if (Request.NOTIFY.equalsIgnoreCase(method)) { | |
| 149 | + NotifyRequestProcessor processor = new NotifyRequestProcessor(); | |
| 150 | + processor.setRequestEvent(evt); | |
| 151 | + processor.setTcpSipProvider(getTcpSipProvider()); | |
| 152 | + processor.setUdpSipProvider(getUdpSipProvider()); | |
| 153 | + processor.setPublisher(publisher); | |
| 154 | + processor.setRedis(redis); | |
| 155 | + processor.setDeferredResultHolder(deferredResultHolder); | |
| 156 | + processor.setOffLineDetector(offLineDetector); | |
| 157 | + processor.setCmder(cmder); | |
| 158 | + processor.setStorager(storager); | |
| 159 | + processor.setRedisCatchStorage(redisCatchStorage); | |
| 160 | + return processor; | |
| 148 | 161 | } else { |
| 149 | - return new OtherRequestProcessor(); | |
| 162 | + OtherRequestProcessor processor = new OtherRequestProcessor(); | |
| 163 | + processor.setRequestEvent(evt); | |
| 164 | + return processor; | |
| 150 | 165 | } |
| 151 | 166 | } |
| 152 | 167 | |
| 153 | 168 | public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) { |
| 154 | - | |
| 155 | 169 | Response response = evt.getResponse(); |
| 156 | 170 | CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
| 157 | 171 | String method = cseqHeader.getMethod(); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
| ... | ... | @@ -17,8 +17,16 @@ import org.springframework.web.context.request.async.DeferredResult; |
| 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/cmd/ISIPCommander.java
| ... | ... | @@ -115,24 +115,35 @@ public interface ISIPCommander { |
| 115 | 115 | /** |
| 116 | 116 | * 音视频录像控制 |
| 117 | 117 | * |
| 118 | - * @param device 视频设备 | |
| 119 | - * @param channelId 预览通道 | |
| 118 | + * @param device 视频设备 | |
| 119 | + * @param channelId 预览通道 | |
| 120 | + * @param recordCmdStr 录像命令:Record / StopRecord | |
| 120 | 121 | */ |
| 121 | - boolean recordCmd(Device device,String channelId); | |
| 122 | + boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent); | |
| 122 | 123 | |
| 123 | 124 | /** |
| 125 | + * 远程启动控制命令 | |
| 126 | + * | |
| 127 | + * @param device 视频设备 | |
| 128 | + */ | |
| 129 | + boolean teleBootCmd(Device device); | |
| 130 | + | |
| 131 | + /** | |
| 124 | 132 | * 报警布防/撤防命令 |
| 125 | 133 | * |
| 126 | - * @param device 视频设备 | |
| 134 | + * @param device 视频设备 | |
| 135 | + * @param setGuard true: SetGuard, false: ResetGuard | |
| 127 | 136 | */ |
| 128 | - boolean guardCmd(Device device); | |
| 137 | + boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent); | |
| 129 | 138 | |
| 130 | 139 | /** |
| 131 | 140 | * 报警复位命令 |
| 132 | 141 | * |
| 133 | - * @param device 视频设备 | |
| 142 | + * @param device 视频设备 | |
| 143 | + * @param alarmMethod 报警方式(可选) | |
| 144 | + * @param alarmType 报警类型(可选) | |
| 134 | 145 | */ |
| 135 | - boolean alarmCmd(Device device); | |
| 146 | + boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent); | |
| 136 | 147 | |
| 137 | 148 | /** |
| 138 | 149 | * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 |
| ... | ... | @@ -140,14 +151,17 @@ public interface ISIPCommander { |
| 140 | 151 | * @param device 视频设备 |
| 141 | 152 | * @param channelId 预览通道 |
| 142 | 153 | */ |
| 143 | - boolean iFameCmd(Device device,String channelId); | |
| 154 | + boolean iFrameCmd(Device device, String channelId); | |
| 144 | 155 | |
| 145 | 156 | /** |
| 146 | 157 | * 看守位控制命令 |
| 147 | 158 | * |
| 148 | - * @param device 视频设备 | |
| 159 | + * @param device 视频设备 | |
| 160 | + * @param enabled 看守位使能:1 = 开启,0 = 关闭 | |
| 161 | + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) | |
| 162 | + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 | |
| 149 | 163 | */ |
| 150 | - boolean homePositionCmd(Device device); | |
| 164 | + boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent); | |
| 151 | 165 | |
| 152 | 166 | /** |
| 153 | 167 | * 设备配置命令 |
| ... | ... | @@ -156,13 +170,24 @@ public interface ISIPCommander { |
| 156 | 170 | */ |
| 157 | 171 | boolean deviceConfigCmd(Device device); |
| 158 | 172 | |
| 173 | + /** | |
| 174 | + * 设备配置命令:basicParam | |
| 175 | + * | |
| 176 | + * @param device 视频设备 | |
| 177 | + * @param channelId 通道编码(可选) | |
| 178 | + * @param name 设备/通道名称(可选) | |
| 179 | + * @param expiration 注册过期时间(可选) | |
| 180 | + * @param heartBeatInterval 心跳间隔时间(可选) | |
| 181 | + * @param heartBeatCount 心跳超时次数(可选) | |
| 182 | + */ | |
| 183 | + boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent); | |
| 159 | 184 | |
| 160 | 185 | /** |
| 161 | 186 | * 查询设备状态 |
| 162 | 187 | * |
| 163 | 188 | * @param device 视频设备 |
| 164 | 189 | */ |
| 165 | - boolean deviceStatusQuery(Device device); | |
| 190 | + boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent); | |
| 166 | 191 | |
| 167 | 192 | /** |
| 168 | 193 | * 查询设备信息 |
| ... | ... | @@ -191,30 +216,65 @@ public interface ISIPCommander { |
| 191 | 216 | /** |
| 192 | 217 | * 查询报警信息 |
| 193 | 218 | * |
| 194 | - * @param device 视频设备 | |
| 219 | + * @param device 视频设备 | |
| 220 | + * @param startPriority 报警起始级别(可选) | |
| 221 | + * @param endPriority 报警终止级别(可选) | |
| 222 | + * @param alarmMethod 报警方式条件(可选) | |
| 223 | + * @param alarmType 报警类型 | |
| 224 | + * @param startTime 报警发生起始时间(可选) | |
| 225 | + * @param endTime 报警发生终止时间(可选) | |
| 226 | + * @return true = 命令发送成功 | |
| 195 | 227 | */ |
| 196 | - boolean alarmInfoQuery(Device device); | |
| 228 | + boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, | |
| 229 | + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent); | |
| 197 | 230 | |
| 198 | 231 | /** |
| 199 | 232 | * 查询设备配置 |
| 200 | 233 | * |
| 201 | - * @param device 视频设备 | |
| 234 | + * @param device 视频设备 | |
| 235 | + * @param channelId 通道编码(可选) | |
| 236 | + * @param configType 配置类型: | |
| 202 | 237 | */ |
| 203 | - boolean configQuery(Device device); | |
| 238 | + boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent); | |
| 204 | 239 | |
| 205 | 240 | /** |
| 206 | 241 | * 查询设备预置位置 |
| 207 | 242 | * |
| 208 | 243 | * @param device 视频设备 |
| 209 | 244 | */ |
| 210 | - boolean presetQuery(Device device); | |
| 245 | + boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent); | |
| 211 | 246 | |
| 212 | 247 | /** |
| 213 | 248 | * 查询移动设备位置数据 |
| 214 | 249 | * |
| 215 | 250 | * @param device 视频设备 |
| 216 | 251 | */ |
| 217 | - boolean mobilePostitionQuery(Device device); | |
| 252 | + boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent); | |
| 253 | + | |
| 254 | + /** | |
| 255 | + * 订阅、取消订阅移动位置 | |
| 256 | + * | |
| 257 | + * @param device 视频设备 | |
| 258 | + * @param expires 订阅超时时间(值=0时为取消订阅) | |
| 259 | + * @param interval 上报时间间隔 | |
| 260 | + * @return true = 命令发送成功 | |
| 261 | + */ | |
| 262 | + boolean mobilePositionSubscribe(Device device, int expires, int interval); | |
| 263 | + | |
| 264 | + /** | |
| 265 | + * 订阅、取消订阅报警信息 | |
| 266 | + * @param device 视频设备 | |
| 267 | + * @param expires 订阅过期时间(0 = 取消订阅) | |
| 268 | + * @param startPriority 报警起始级别(可选) | |
| 269 | + * @param endPriority 报警终止级别(可选) | |
| 270 | + * @param alarmMethods 报警方式条件(可选) | |
| 271 | + * @param alarmType 报警类型 | |
| 272 | + * @param startTime 报警发生起始时间(可选) | |
| 273 | + * @param endTime 报警发生终止时间(可选) | |
| 274 | + * @return true = 命令发送成功 | |
| 275 | + */ | |
| 276 | + boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); | |
| 277 | + | |
| 218 | 278 | |
| 219 | 279 | /** |
| 220 | 280 | * 释放rtpserver | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| ... | ... | @@ -164,4 +164,51 @@ public class SIPRequestHeaderProvider { |
| 164 | 164 | request.setContent(content, contentTypeHeader); |
| 165 | 165 | return request; |
| 166 | 166 | } |
| 167 | + | |
| 168 | + public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event) throws ParseException, InvalidArgumentException, PeerUnavailableException { | |
| 169 | + Request request = null; | |
| 170 | + // sipuri | |
| 171 | + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); | |
| 172 | + // via | |
| 173 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 174 | + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), | |
| 175 | + device.getTransport(), viaTag); | |
| 176 | + viaHeader.setRPort(); | |
| 177 | + viaHeaders.add(viaHeader); | |
| 178 | + // from | |
| 179 | + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), | |
| 180 | + sipConfig.getSipIp() + ":" + sipConfig.getSipPort()); | |
| 181 | + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); | |
| 182 | + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); | |
| 183 | + // to | |
| 184 | + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain()); | |
| 185 | + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); | |
| 186 | + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); | |
| 187 | + // callid | |
| 188 | + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | |
| 189 | + : udpSipProvider.getNewCallId(); | |
| 190 | + // Forwards | |
| 191 | + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); | |
| 192 | + // ceq | |
| 193 | + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.SUBSCRIBE); | |
| 194 | + | |
| 195 | + request = sipFactory.createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader, | |
| 196 | + toHeader, viaHeaders, maxForwards); | |
| 197 | + | |
| 198 | + | |
| 199 | + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort())); | |
| 200 | + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); | |
| 201 | + | |
| 202 | + // Expires | |
| 203 | + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(expires); | |
| 204 | + request.addHeader(expireHeader); | |
| 205 | + | |
| 206 | + // Event | |
| 207 | + EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); | |
| 208 | + request.addHeader(eventHeader); | |
| 209 | + | |
| 210 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | |
| 211 | + request.setContent(content, contentTypeHeader); | |
| 212 | + return request; | |
| 213 | + } | |
| 167 | 214 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| ... | ... | @@ -34,6 +34,8 @@ import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 34 | 34 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 35 | 35 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; |
| 36 | 36 | import com.genersoft.iot.vmp.gb28181.utils.DateUtil; |
| 37 | +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; | |
| 38 | +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | |
| 37 | 39 | |
| 38 | 40 | /** |
| 39 | 41 | * @Description:设备能力接口,用于定义设备的控制、查询能力 |
| ... | ... | @@ -235,7 +237,8 @@ public class SIPCommander implements ISIPCommander { |
| 235 | 237 | ptzXml.append("</Info>\r\n"); |
| 236 | 238 | ptzXml.append("</Control>\r\n"); |
| 237 | 239 | |
| 238 | - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", null); | |
| 240 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 241 | + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null); | |
| 239 | 242 | |
| 240 | 243 | transmitRequest(device, request); |
| 241 | 244 | return true; |
| ... | ... | @@ -271,7 +274,8 @@ public class SIPCommander implements ISIPCommander { |
| 271 | 274 | ptzXml.append("</Info>\r\n"); |
| 272 | 275 | ptzXml.append("</Control>\r\n"); |
| 273 | 276 | |
| 274 | - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", null); | |
| 277 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 278 | + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtz" + tm, null); | |
| 275 | 279 | transmitRequest(device, request); |
| 276 | 280 | return true; |
| 277 | 281 | } catch (SipException | ParseException | InvalidArgumentException e) { |
| ... | ... | @@ -383,7 +387,8 @@ public class SIPCommander implements ISIPCommander { |
| 383 | 387 | |
| 384 | 388 | content.append("y="+ssrc+"\r\n");//ssrc |
| 385 | 389 | |
| 386 | - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "live", null, ssrc); | |
| 390 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 391 | + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc); | |
| 387 | 392 | |
| 388 | 393 | ClientTransaction transaction = transmitRequest(device, request, errorEvent); |
| 389 | 394 | streamSession.put(streamId, transaction); |
| ... | ... | @@ -482,7 +487,8 @@ public class SIPCommander implements ISIPCommander { |
| 482 | 487 | |
| 483 | 488 | content.append("y="+ssrc+"\r\n");//ssrc |
| 484 | 489 | |
| 485 | - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "playback", null); | |
| 490 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 491 | + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null); | |
| 486 | 492 | |
| 487 | 493 | ClientTransaction transaction = transmitRequest(device, request, errorEvent); |
| 488 | 494 | streamSession.put(streamId, transaction); |
| ... | ... | @@ -573,24 +579,89 @@ public class SIPCommander implements ISIPCommander { |
| 573 | 579 | /** |
| 574 | 580 | * 音视频录像控制 |
| 575 | 581 | * |
| 576 | - * @param device 视频设备 | |
| 577 | - * @param channelId 预览通道 | |
| 582 | + * @param device 视频设备 | |
| 583 | + * @param channelId 预览通道 | |
| 584 | + * @param recordCmdStr 录像命令:Record / StopRecord | |
| 578 | 585 | */ |
| 579 | 586 | @Override |
| 580 | - public boolean recordCmd(Device device, String channelId) { | |
| 581 | - // TODO Auto-generated method stub | |
| 582 | - return false; | |
| 587 | + public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) { | |
| 588 | + try { | |
| 589 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 590 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 591 | + cmdXml.append("<Control>\r\n"); | |
| 592 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 593 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 594 | + if (XmlUtil.isEmpty(channelId)) { | |
| 595 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 596 | + } else { | |
| 597 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 598 | + } | |
| 599 | + cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n"); | |
| 600 | + cmdXml.append("</Control>\r\n"); | |
| 601 | + | |
| 602 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 603 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromRecord" + tm, null); | |
| 604 | + transmitRequest(device, request, errorEvent); | |
| 605 | + return true; | |
| 606 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 607 | + e.printStackTrace(); | |
| 608 | + return false; | |
| 609 | + } | |
| 583 | 610 | } |
| 584 | 611 | |
| 585 | 612 | /** |
| 613 | + * 远程启动控制命令 | |
| 614 | + * | |
| 615 | + * @param device 视频设备 | |
| 616 | + */ | |
| 617 | + @Override | |
| 618 | + public boolean teleBootCmd(Device device) { | |
| 619 | + try { | |
| 620 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 621 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 622 | + cmdXml.append("<Control>\r\n"); | |
| 623 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 624 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 625 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 626 | + cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n"); | |
| 627 | + cmdXml.append("</Control>\r\n"); | |
| 628 | + | |
| 629 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 630 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null); | |
| 631 | + transmitRequest(device, request); | |
| 632 | + return true; | |
| 633 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 634 | + e.printStackTrace(); | |
| 635 | + return false; | |
| 636 | + } | |
| 637 | + } | |
| 638 | + | |
| 639 | + /** | |
| 586 | 640 | * 报警布防/撤防命令 |
| 587 | 641 | * |
| 588 | - * @param device 视频设备 | |
| 589 | - */ | |
| 642 | + * @param device 视频设备 | |
| 643 | + * @param guardCmdStr "SetGuard"/"ResetGuard" | |
| 644 | + */ | |
| 590 | 645 | @Override |
| 591 | - public boolean guardCmd(Device device) { | |
| 592 | - // TODO Auto-generated method stub | |
| 593 | - return false; | |
| 646 | + public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) { | |
| 647 | + try { | |
| 648 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 649 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 650 | + cmdXml.append("<Control>\r\n"); | |
| 651 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 652 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 653 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 654 | + cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); | |
| 655 | + cmdXml.append("</Control>\r\n"); | |
| 656 | + | |
| 657 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 658 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null); | |
| 659 | + transmitRequest(device, request, errorEvent); | |
| 660 | + return true; | |
| 661 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 662 | + e.printStackTrace(); | |
| 663 | + return false; | |
| 664 | + } | |
| 594 | 665 | } |
| 595 | 666 | |
| 596 | 667 | /** |
| ... | ... | @@ -599,9 +670,37 @@ public class SIPCommander implements ISIPCommander { |
| 599 | 670 | * @param device 视频设备 |
| 600 | 671 | */ |
| 601 | 672 | @Override |
| 602 | - public boolean alarmCmd(Device device) { | |
| 603 | - // TODO Auto-generated method stub | |
| 604 | - return false; | |
| 673 | + public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) { | |
| 674 | + try { | |
| 675 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 676 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 677 | + cmdXml.append("<Control>\r\n"); | |
| 678 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 679 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 680 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 681 | + cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n"); | |
| 682 | + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { | |
| 683 | + cmdXml.append("<Info>\r\n"); | |
| 684 | + } | |
| 685 | + if (!XmlUtil.isEmpty(alarmMethod)) { | |
| 686 | + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 687 | + } | |
| 688 | + if (!XmlUtil.isEmpty(alarmType)) { | |
| 689 | + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 690 | + } | |
| 691 | + if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { | |
| 692 | + cmdXml.append("</Info>\r\n"); | |
| 693 | + } | |
| 694 | + cmdXml.append("</Control>\r\n"); | |
| 695 | + | |
| 696 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 697 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null); | |
| 698 | + transmitRequest(device, request, errorEvent); | |
| 699 | + return true; | |
| 700 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 701 | + e.printStackTrace(); | |
| 702 | + return false; | |
| 703 | + } | |
| 605 | 704 | } |
| 606 | 705 | |
| 607 | 706 | /** |
| ... | ... | @@ -611,20 +710,79 @@ public class SIPCommander implements ISIPCommander { |
| 611 | 710 | * @param channelId 预览通道 |
| 612 | 711 | */ |
| 613 | 712 | @Override |
| 614 | - public boolean iFameCmd(Device device, String channelId) { | |
| 615 | - // TODO Auto-generated method stub | |
| 616 | - return false; | |
| 713 | + public boolean iFrameCmd(Device device, String channelId) { | |
| 714 | + try { | |
| 715 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 716 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 717 | + cmdXml.append("<Control>\r\n"); | |
| 718 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 719 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 720 | + if (XmlUtil.isEmpty(channelId)) { | |
| 721 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 722 | + } else { | |
| 723 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 724 | + } | |
| 725 | + cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n"); | |
| 726 | + cmdXml.append("</Control>\r\n"); | |
| 727 | + | |
| 728 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 729 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromBoot" + tm, null); | |
| 730 | + transmitRequest(device, request); | |
| 731 | + return true; | |
| 732 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 733 | + e.printStackTrace(); | |
| 734 | + return false; | |
| 735 | + } | |
| 617 | 736 | } |
| 618 | 737 | |
| 619 | 738 | /** |
| 620 | 739 | * 看守位控制命令 |
| 621 | 740 | * |
| 622 | - * @param device 视频设备 | |
| 741 | + * @param device 视频设备 | |
| 742 | + * @param enabled 看守位使能:1 = 开启,0 = 关闭 | |
| 743 | + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) | |
| 744 | + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 | |
| 623 | 745 | */ |
| 624 | 746 | @Override |
| 625 | - public boolean homePositionCmd(Device device) { | |
| 626 | - // TODO Auto-generated method stub | |
| 627 | - return false; | |
| 747 | + public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) { | |
| 748 | + try { | |
| 749 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 750 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 751 | + cmdXml.append("<Control>\r\n"); | |
| 752 | + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | |
| 753 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 754 | + if (XmlUtil.isEmpty(channelId)) { | |
| 755 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 756 | + } else { | |
| 757 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 758 | + } | |
| 759 | + cmdXml.append("<HomePosition>\r\n"); | |
| 760 | + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { | |
| 761 | + cmdXml.append("<Enabled>1</Enabled>\r\n"); | |
| 762 | + if (NumericUtil.isInteger(resetTime)) { | |
| 763 | + cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n"); | |
| 764 | + } else { | |
| 765 | + cmdXml.append("<ResetTime>0</ResetTime>\r\n"); | |
| 766 | + } | |
| 767 | + if (NumericUtil.isInteger(presetIndex)) { | |
| 768 | + cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n"); | |
| 769 | + } else { | |
| 770 | + cmdXml.append("<PresetIndex>0</PresetIndex>\r\n"); | |
| 771 | + } | |
| 772 | + } else { | |
| 773 | + cmdXml.append("<Enabled>0</Enabled>\r\n"); | |
| 774 | + } | |
| 775 | + cmdXml.append("</HomePosition>\r\n"); | |
| 776 | + cmdXml.append("</Control>\r\n"); | |
| 777 | + | |
| 778 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 779 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromGuard" + tm, null); | |
| 780 | + transmitRequest(device, request, errorEvent); | |
| 781 | + return true; | |
| 782 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 783 | + e.printStackTrace(); | |
| 784 | + return false; | |
| 785 | + } | |
| 628 | 786 | } |
| 629 | 787 | |
| 630 | 788 | /** |
| ... | ... | @@ -639,14 +797,87 @@ public class SIPCommander implements ISIPCommander { |
| 639 | 797 | } |
| 640 | 798 | |
| 641 | 799 | /** |
| 800 | + * 设备配置命令:basicParam | |
| 801 | + * | |
| 802 | + * @param device 视频设备 | |
| 803 | + * @param channelId 通道编码(可选) | |
| 804 | + * @param name 设备/通道名称(可选) | |
| 805 | + * @param expiration 注册过期时间(可选) | |
| 806 | + * @param heartBeatInterval 心跳间隔时间(可选) | |
| 807 | + * @param heartBeatCount 心跳超时次数(可选) | |
| 808 | + */ | |
| 809 | + @Override | |
| 810 | + public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, | |
| 811 | + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) { | |
| 812 | + try { | |
| 813 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 814 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 815 | + cmdXml.append("<Control>\r\n"); | |
| 816 | + cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n"); | |
| 817 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 818 | + if (XmlUtil.isEmpty(channelId)) { | |
| 819 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 820 | + } else { | |
| 821 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 822 | + } | |
| 823 | + cmdXml.append("<BasicParam>\r\n"); | |
| 824 | + if (!XmlUtil.isEmpty(name)) { | |
| 825 | + cmdXml.append("<Name>" + name + "</Name>\r\n"); | |
| 826 | + } | |
| 827 | + if (NumericUtil.isInteger(expiration)) { | |
| 828 | + if (Integer.valueOf(expiration) > 0) { | |
| 829 | + cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n"); | |
| 830 | + } | |
| 831 | + } | |
| 832 | + if (NumericUtil.isInteger(heartBeatInterval)) { | |
| 833 | + if (Integer.valueOf(heartBeatInterval) > 0) { | |
| 834 | + cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n"); | |
| 835 | + } | |
| 836 | + } | |
| 837 | + if (NumericUtil.isInteger(heartBeatCount)) { | |
| 838 | + if (Integer.valueOf(heartBeatCount) > 0) { | |
| 839 | + cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n"); | |
| 840 | + } | |
| 841 | + } | |
| 842 | + cmdXml.append("</BasicParam>\r\n"); | |
| 843 | + cmdXml.append("</Control>\r\n"); | |
| 844 | + | |
| 845 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 846 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null); | |
| 847 | + transmitRequest(device, request, errorEvent); | |
| 848 | + return true; | |
| 849 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 850 | + e.printStackTrace(); | |
| 851 | + return false; | |
| 852 | + } | |
| 853 | + } | |
| 854 | + | |
| 855 | + /** | |
| 642 | 856 | * 查询设备状态 |
| 643 | 857 | * |
| 644 | 858 | * @param device 视频设备 |
| 645 | 859 | */ |
| 646 | 860 | @Override |
| 647 | - public boolean deviceStatusQuery(Device device) { | |
| 648 | - // TODO Auto-generated method stub | |
| 649 | - return false; | |
| 861 | + public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) { | |
| 862 | + try { | |
| 863 | + StringBuffer catalogXml = new StringBuffer(200); | |
| 864 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | |
| 865 | + catalogXml.append("<Query>\r\n"); | |
| 866 | + catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n"); | |
| 867 | + catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 868 | + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 869 | + catalogXml.append("</Query>\r\n"); | |
| 870 | + | |
| 871 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 872 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, "FromStatus" + tm, null); | |
| 873 | + | |
| 874 | + transmitRequest(device, request, errorEvent); | |
| 875 | + return true; | |
| 876 | + | |
| 877 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 878 | + e.printStackTrace(); | |
| 879 | + return false; | |
| 880 | + } | |
| 650 | 881 | } |
| 651 | 882 | |
| 652 | 883 | /** |
| ... | ... | @@ -665,7 +896,8 @@ public class SIPCommander implements ISIPCommander { |
| 665 | 896 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 666 | 897 | catalogXml.append("</Query>\r\n"); |
| 667 | 898 | |
| 668 | - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", null); | |
| 899 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 900 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDev" + tm, null); | |
| 669 | 901 | |
| 670 | 902 | transmitRequest(device, request); |
| 671 | 903 | |
| ... | ... | @@ -694,7 +926,8 @@ public class SIPCommander implements ISIPCommander { |
| 694 | 926 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 695 | 927 | catalogXml.append("</Query>\r\n"); |
| 696 | 928 | |
| 697 | - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", null); | |
| 929 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 930 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCat" + tm, null); | |
| 698 | 931 | |
| 699 | 932 | transmitRequest(device, request, errorEvent); |
| 700 | 933 | } catch (SipException | ParseException | InvalidArgumentException e) { |
| ... | ... | @@ -728,7 +961,8 @@ public class SIPCommander implements ISIPCommander { |
| 728 | 961 | recordInfoXml.append("<Type>all</Type>\r\n"); |
| 729 | 962 | recordInfoXml.append("</Query>\r\n"); |
| 730 | 963 | |
| 731 | - Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", null); | |
| 964 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 965 | + Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "fromRec" + tm, null); | |
| 732 | 966 | |
| 733 | 967 | transmitRequest(device, request); |
| 734 | 968 | } catch (SipException | ParseException | InvalidArgumentException e) { |
| ... | ... | @@ -741,23 +975,86 @@ public class SIPCommander implements ISIPCommander { |
| 741 | 975 | /** |
| 742 | 976 | * 查询报警信息 |
| 743 | 977 | * |
| 744 | - * @param device 视频设备 | |
| 745 | - */ | |
| 978 | + * @param device 视频设备 | |
| 979 | + * @param startPriority 报警起始级别(可选) | |
| 980 | + * @param endPriority 报警终止级别(可选) | |
| 981 | + * @param alarmMethods 报警方式条件(可选) | |
| 982 | + * @param alarmType 报警类型 | |
| 983 | + * @param startTime 报警发生起始时间(可选) | |
| 984 | + * @param endTime 报警发生终止时间(可选) | |
| 985 | + * @return true = 命令发送成功 | |
| 986 | + */ | |
| 746 | 987 | @Override |
| 747 | - public boolean alarmInfoQuery(Device device) { | |
| 748 | - // TODO Auto-generated method stub | |
| 749 | - return false; | |
| 988 | + public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType, | |
| 989 | + String startTime, String endTime, SipSubscribe.Event errorEvent) { | |
| 990 | + try { | |
| 991 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 992 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 993 | + cmdXml.append("<Query>\r\n"); | |
| 994 | + cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 995 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 996 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 997 | + if (!XmlUtil.isEmpty(startPriority)) { | |
| 998 | + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); | |
| 999 | + } | |
| 1000 | + if (!XmlUtil.isEmpty(endPriority)) { | |
| 1001 | + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); | |
| 1002 | + } | |
| 1003 | + if (!XmlUtil.isEmpty(alarmMethod)) { | |
| 1004 | + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 1005 | + } | |
| 1006 | + if (!XmlUtil.isEmpty(alarmType)) { | |
| 1007 | + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 1008 | + } | |
| 1009 | + if (!XmlUtil.isEmpty(startTime)) { | |
| 1010 | + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); | |
| 1011 | + } | |
| 1012 | + if (!XmlUtil.isEmpty(endTime)) { | |
| 1013 | + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); | |
| 1014 | + } | |
| 1015 | + cmdXml.append("</Query>\r\n"); | |
| 1016 | + | |
| 1017 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 1018 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromAlarm" + tm, null); | |
| 1019 | + transmitRequest(device, request, errorEvent); | |
| 1020 | + return true; | |
| 1021 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 1022 | + e.printStackTrace(); | |
| 1023 | + return false; | |
| 1024 | + } | |
| 750 | 1025 | } |
| 751 | 1026 | |
| 752 | 1027 | /** |
| 753 | 1028 | * 查询设备配置 |
| 754 | 1029 | * |
| 755 | - * @param device 视频设备 | |
| 756 | - */ | |
| 1030 | + * @param device 视频设备 | |
| 1031 | + * @param channelId 通道编码(可选) | |
| 1032 | + * @param configType 配置类型: | |
| 1033 | + */ | |
| 757 | 1034 | @Override |
| 758 | - public boolean configQuery(Device device) { | |
| 759 | - // TODO Auto-generated method stub | |
| 760 | - return false; | |
| 1035 | + public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) { | |
| 1036 | + try { | |
| 1037 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1038 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 1039 | + cmdXml.append("<Query>\r\n"); | |
| 1040 | + cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n"); | |
| 1041 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 1042 | + if (XmlUtil.isEmpty(channelId)) { | |
| 1043 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1044 | + } else { | |
| 1045 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1046 | + } | |
| 1047 | + cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n"); | |
| 1048 | + cmdXml.append("</Query>\r\n"); | |
| 1049 | + | |
| 1050 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 1051 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null); | |
| 1052 | + transmitRequest(device, request, errorEvent); | |
| 1053 | + return true; | |
| 1054 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 1055 | + e.printStackTrace(); | |
| 1056 | + return false; | |
| 1057 | + } | |
| 761 | 1058 | } |
| 762 | 1059 | |
| 763 | 1060 | /** |
| ... | ... | @@ -766,9 +1063,28 @@ public class SIPCommander implements ISIPCommander { |
| 766 | 1063 | * @param device 视频设备 |
| 767 | 1064 | */ |
| 768 | 1065 | @Override |
| 769 | - public boolean presetQuery(Device device) { | |
| 770 | - // TODO Auto-generated method stub | |
| 771 | - return false; | |
| 1066 | + public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) { | |
| 1067 | + try { | |
| 1068 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1069 | + cmdXml.append("<?xml version=\"1.0\" ?>\r\n"); | |
| 1070 | + cmdXml.append("<Query>\r\n"); | |
| 1071 | + cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n"); | |
| 1072 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 1073 | + if (XmlUtil.isEmpty(channelId)) { | |
| 1074 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1075 | + } else { | |
| 1076 | + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | |
| 1077 | + } | |
| 1078 | + cmdXml.append("</Query>\r\n"); | |
| 1079 | + | |
| 1080 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 1081 | + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, "FromConfig" + tm, null); | |
| 1082 | + transmitRequest(device, request, errorEvent); | |
| 1083 | + return true; | |
| 1084 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 1085 | + e.printStackTrace(); | |
| 1086 | + return false; | |
| 1087 | + } | |
| 772 | 1088 | } |
| 773 | 1089 | |
| 774 | 1090 | /** |
| ... | ... | @@ -777,11 +1093,116 @@ public class SIPCommander implements ISIPCommander { |
| 777 | 1093 | * @param device 视频设备 |
| 778 | 1094 | */ |
| 779 | 1095 | @Override |
| 780 | - public boolean mobilePostitionQuery(Device device) { | |
| 781 | - // TODO Auto-generated method stub | |
| 782 | - return false; | |
| 1096 | + public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) { | |
| 1097 | + try { | |
| 1098 | + StringBuffer mobilePostitionXml = new StringBuffer(200); | |
| 1099 | + mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | |
| 1100 | + mobilePostitionXml.append("<Query>\r\n"); | |
| 1101 | + mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n"); | |
| 1102 | + mobilePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 1103 | + mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1104 | + mobilePostitionXml.append("<Interval>60</Interval>\r\n"); | |
| 1105 | + mobilePostitionXml.append("</Query>\r\n"); | |
| 1106 | + | |
| 1107 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 1108 | + Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null); | |
| 1109 | + | |
| 1110 | + transmitRequest(device, request, errorEvent); | |
| 1111 | + | |
| 1112 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 1113 | + e.printStackTrace(); | |
| 1114 | + return false; | |
| 1115 | + } | |
| 1116 | + return true; | |
| 783 | 1117 | } |
| 784 | 1118 | |
| 1119 | + /** | |
| 1120 | + * 订阅、取消订阅移动位置 | |
| 1121 | + * | |
| 1122 | + * @param device 视频设备 | |
| 1123 | + * @param expires 订阅超时时间 | |
| 1124 | + * @param interval 上报时间间隔 | |
| 1125 | + * @return true = 命令发送成功 | |
| 1126 | + */ | |
| 1127 | + public boolean mobilePositionSubscribe(Device device, int expires, int interval) { | |
| 1128 | + try { | |
| 1129 | + StringBuffer subscribePostitionXml = new StringBuffer(200); | |
| 1130 | + subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | |
| 1131 | + subscribePostitionXml.append("<Query>\r\n"); | |
| 1132 | + subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n"); | |
| 1133 | + subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 1134 | + subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1135 | + if (expires > 0) { | |
| 1136 | + subscribePostitionXml.append("<Interval>" + String.valueOf(interval) + "</Interval>\r\n"); | |
| 1137 | + } | |
| 1138 | + subscribePostitionXml.append("</Query>\r\n"); | |
| 1139 | + | |
| 1140 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 1141 | + Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); //Position;id=" + tm.substring(tm.length() - 4)); | |
| 1142 | + transmitRequest(device, request); | |
| 1143 | + | |
| 1144 | + return true; | |
| 1145 | + | |
| 1146 | + } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { | |
| 1147 | + e.printStackTrace(); | |
| 1148 | + return false; | |
| 1149 | + } | |
| 1150 | + } | |
| 1151 | + | |
| 1152 | + /** | |
| 1153 | + * 订阅、取消订阅报警信息 | |
| 1154 | + * | |
| 1155 | + * @param device 视频设备 | |
| 1156 | + * @param expires 订阅过期时间(0 = 取消订阅) | |
| 1157 | + * @param startPriority 报警起始级别(可选) | |
| 1158 | + * @param endPriority 报警终止级别(可选) | |
| 1159 | + * @param alarmMethod 报警方式条件(可选) | |
| 1160 | + * @param alarmType 报警类型 | |
| 1161 | + * @param startTime 报警发生起始时间(可选) | |
| 1162 | + * @param endTime 报警发生终止时间(可选) | |
| 1163 | + * @return true = 命令发送成功 | |
| 1164 | + */ | |
| 1165 | + public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) { | |
| 1166 | + try { | |
| 1167 | + StringBuffer cmdXml = new StringBuffer(200); | |
| 1168 | + cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | |
| 1169 | + cmdXml.append("<Query>\r\n"); | |
| 1170 | + cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); | |
| 1171 | + cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 1172 | + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | |
| 1173 | + if (!XmlUtil.isEmpty(startPriority)) { | |
| 1174 | + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); | |
| 1175 | + } | |
| 1176 | + if (!XmlUtil.isEmpty(endPriority)) { | |
| 1177 | + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); | |
| 1178 | + } | |
| 1179 | + if (!XmlUtil.isEmpty(alarmMethod)) { | |
| 1180 | + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); | |
| 1181 | + } | |
| 1182 | + if (!XmlUtil.isEmpty(alarmType)) { | |
| 1183 | + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); | |
| 1184 | + } | |
| 1185 | + if (!XmlUtil.isEmpty(startTime)) { | |
| 1186 | + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); | |
| 1187 | + } | |
| 1188 | + if (!XmlUtil.isEmpty(endTime)) { | |
| 1189 | + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); | |
| 1190 | + } | |
| 1191 | + cmdXml.append("</Query>\r\n"); | |
| 1192 | + | |
| 1193 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 1194 | + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "viaTagPos" + tm, "fromTagPos" + tm, null, expires, "presence" ); | |
| 1195 | + transmitRequest(device, request); | |
| 1196 | + | |
| 1197 | + return true; | |
| 1198 | + | |
| 1199 | + } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { | |
| 1200 | + e.printStackTrace(); | |
| 1201 | + return false; | |
| 1202 | + } | |
| 1203 | + } | |
| 1204 | + | |
| 1205 | + | |
| 785 | 1206 | private ClientTransaction transmitRequest(Device device, Request request) throws SipException { |
| 786 | 1207 | return transmitRequest(device, request, null, null); |
| 787 | 1208 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
| ... | ... | @@ -10,19 +10,15 @@ import javax.sip.SipException; |
| 10 | 10 | import javax.sip.message.Request; |
| 11 | 11 | import javax.sip.message.Response; |
| 12 | 12 | |
| 13 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 14 | -import org.dom4j.Document; | |
| 15 | -import org.dom4j.DocumentException; | |
| 16 | -import org.dom4j.Element; | |
| 17 | -import org.dom4j.io.SAXReader; | |
| 18 | -import org.slf4j.Logger; | |
| 19 | -import org.slf4j.LoggerFactory; | |
| 20 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 21 | - | |
| 13 | +import com.alibaba.fastjson.JSONObject; | |
| 14 | +import com.genersoft.iot.vmp.common.StreamInfo; | |
| 22 | 15 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 16 | +import com.genersoft.iot.vmp.conf.UserSetup; | |
| 17 | +import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint; | |
| 23 | 18 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 24 | 19 | import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; |
| 25 | 20 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 21 | +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; | |
| 26 | 22 | import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; |
| 27 | 23 | import com.genersoft.iot.vmp.gb28181.bean.RecordItem; |
| 28 | 24 | import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
| ... | ... | @@ -32,18 +28,31 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 32 | 28 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 33 | 29 | import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
| 34 | 30 | import com.genersoft.iot.vmp.gb28181.utils.DateUtil; |
| 31 | +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; | |
| 35 | 32 | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
| 33 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 36 | 34 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 35 | +import com.genersoft.iot.vmp.utils.GpsUtil; | |
| 36 | +import com.genersoft.iot.vmp.utils.SpringBeanFactory; | |
| 37 | 37 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| 38 | + | |
| 39 | +import org.dom4j.Document; | |
| 40 | +import org.dom4j.DocumentException; | |
| 41 | +import org.dom4j.Element; | |
| 42 | +import org.dom4j.io.SAXReader; | |
| 43 | +import org.slf4j.Logger; | |
| 44 | +import org.slf4j.LoggerFactory; | |
| 38 | 45 | import org.springframework.util.StringUtils; |
| 39 | -import com.genersoft.iot.vmp.common.StreamInfo; | |
| 40 | 46 | /** |
| 41 | 47 | * @Description:MESSAGE请求处理器 |
| 42 | 48 | * @author: swwheihei |
| 43 | 49 | * @date: 2020年5月3日 下午5:32:41 |
| 44 | 50 | */ |
| 51 | + | |
| 45 | 52 | public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 46 | 53 | |
| 54 | + private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup"); | |
| 55 | + | |
| 47 | 56 | private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); |
| 48 | 57 | |
| 49 | 58 | private SIPCommander cmder; |
| ... | ... | @@ -70,9 +79,12 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 70 | 79 | private static final String MESSAGE_RECORD_INFO = "RecordInfo"; |
| 71 | 80 | private static final String MESSAGE_MEDIA_STATUS = "MediaStatus"; |
| 72 | 81 | // private static final String MESSAGE_BROADCAST = "Broadcast"; |
| 73 | - // private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus"; | |
| 74 | - // private static final String MESSAGE_MOBILE_POSITION = "MobilePosition"; | |
| 82 | + private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus"; | |
| 83 | + private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl"; | |
| 84 | + private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig"; | |
| 85 | + private static final String MESSAGE_MOBILE_POSITION = "MobilePosition"; | |
| 75 | 86 | // private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval"; |
| 87 | + private static final String MESSAGE_PRESET_QUERY = "PresetQuery"; | |
| 76 | 88 | |
| 77 | 89 | /** |
| 78 | 90 | * 处理MESSAGE请求 |
| ... | ... | @@ -91,12 +103,22 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 91 | 103 | processMessageKeepAlive(evt); |
| 92 | 104 | } else if (MESSAGE_CONFIG_DOWNLOAD.equals(cmd)) { |
| 93 | 105 | logger.info("接收到ConfigDownload消息"); |
| 106 | + processMessageConfigDownload(evt); | |
| 94 | 107 | } else if (MESSAGE_CATALOG.equals(cmd)) { |
| 95 | 108 | logger.info("接收到Catalog消息"); |
| 96 | 109 | processMessageCatalogList(evt); |
| 97 | 110 | } else if (MESSAGE_DEVICE_INFO.equals(cmd)) { |
| 98 | 111 | logger.info("接收到DeviceInfo消息"); |
| 99 | 112 | processMessageDeviceInfo(evt); |
| 113 | + } else if (MESSAGE_DEVICE_STATUS.equals(cmd)) { | |
| 114 | + logger.info("接收到DeviceStatus消息"); | |
| 115 | + processMessageDeviceStatus(evt); | |
| 116 | + } else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) { | |
| 117 | + logger.info("接收到DeviceControl消息"); | |
| 118 | + processMessageDeviceControl(evt); | |
| 119 | + } else if (MESSAGE_DEVICE_CONFIG.equals(cmd)) { | |
| 120 | + logger.info("接收到DeviceConfig消息"); | |
| 121 | + processMessageDeviceConfig(evt); | |
| 100 | 122 | } else if (MESSAGE_ALARM.equals(cmd)) { |
| 101 | 123 | logger.info("接收到Alarm消息"); |
| 102 | 124 | processMessageAlarm(evt); |
| ... | ... | @@ -106,16 +128,239 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 106 | 128 | }else if (MESSAGE_MEDIA_STATUS.equals(cmd)) { |
| 107 | 129 | logger.info("接收到MediaStatus消息"); |
| 108 | 130 | processMessageMediaStatus(evt); |
| 131 | + } else if (MESSAGE_MOBILE_POSITION.equals(cmd)) { | |
| 132 | + logger.info("接收到MobilePosition消息"); | |
| 133 | + processMessageMobilePosition(evt); | |
| 134 | + } else if (MESSAGE_PRESET_QUERY.equals(cmd)) { | |
| 135 | + logger.info("接收到PresetQuery消息"); | |
| 136 | + processMessagePresetQuery(evt); | |
| 109 | 137 | } else { |
| 110 | 138 | logger.info("接收到消息:" + cmd); |
| 139 | + responseAck(evt); | |
| 140 | + } | |
| 141 | + } catch (DocumentException | SipException |InvalidArgumentException | ParseException e) { | |
| 142 | + e.printStackTrace(); | |
| 143 | + } | |
| 144 | + } | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * 处理MobilePosition移动位置消息 | |
| 148 | + * | |
| 149 | + * @param evt | |
| 150 | + */ | |
| 151 | + private void processMessageMobilePosition(RequestEvent evt) { | |
| 152 | + try { | |
| 153 | + Element rootElement = getRootElement(evt); | |
| 154 | + MobilePosition mobilePosition = new MobilePosition(); | |
| 155 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 156 | + String deviceId = deviceIdElement.getTextTrim().toString(); | |
| 157 | + Device device = storager.queryVideoDevice(deviceId); | |
| 158 | + if (device != null) { | |
| 159 | + if (!StringUtils.isEmpty(device.getName())) { | |
| 160 | + mobilePosition.setDeviceName(device.getName()); | |
| 161 | + } | |
| 162 | + } | |
| 163 | + mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID")); | |
| 164 | + mobilePosition.setTime(XmlUtil.getText(rootElement, "Time")); | |
| 165 | + mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); | |
| 166 | + mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); | |
| 167 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) { | |
| 168 | + mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed"))); | |
| 169 | + } else { | |
| 170 | + mobilePosition.setSpeed(0.0); | |
| 171 | + } | |
| 172 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) { | |
| 173 | + mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction"))); | |
| 174 | + } else { | |
| 175 | + mobilePosition.setDirection(0.0); | |
| 176 | + } | |
| 177 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) { | |
| 178 | + mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude"))); | |
| 179 | + } else { | |
| 180 | + mobilePosition.setAltitude(0.0); | |
| 181 | + } | |
| 182 | + mobilePosition.setReportSource("Mobile Position"); | |
| 183 | + BaiduPoint bp = new BaiduPoint(); | |
| 184 | + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); | |
| 185 | + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); | |
| 186 | + mobilePosition.setGeodeticSystem("BD-09"); | |
| 187 | + mobilePosition.setCnLng(bp.getBdLng()); | |
| 188 | + mobilePosition.setCnLat(bp.getBdLat()); | |
| 189 | + if (!userSetup.getSavePositionHistory()) { | |
| 190 | + storager.clearMobilePositionsByDeviceId(deviceId); | |
| 191 | + } | |
| 192 | + storager.insertMobilePosition(mobilePosition); | |
| 193 | + //回复 200 OK | |
| 194 | + responseAck(evt); | |
| 195 | + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | |
| 196 | + e.printStackTrace(); | |
| 197 | + } | |
| 198 | + } | |
| 199 | + | |
| 200 | + /** | |
| 201 | + * 处理DeviceStatus设备状态Message | |
| 202 | + * | |
| 203 | + * @param evt | |
| 204 | + */ | |
| 205 | + private void processMessageDeviceStatus(RequestEvent evt) { | |
| 206 | + try { | |
| 207 | + Element rootElement = getRootElement(evt); | |
| 208 | + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); | |
| 209 | + // 检查设备是否存在, 不存在则不回复 | |
| 210 | + if (storager.exists(deviceId)) { | |
| 211 | + // 回复200 OK | |
| 212 | + responseAck(evt); | |
| 213 | + JSONObject json = new JSONObject(); | |
| 214 | + XmlUtil.node2Json(rootElement, json); | |
| 215 | + if (logger.isDebugEnabled()) { | |
| 216 | + logger.debug(json.toJSONString()); | |
| 217 | + } | |
| 218 | + RequestMessage msg = new RequestMessage(); | |
| 219 | + msg.setDeviceId(deviceId); | |
| 220 | + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS); | |
| 221 | + msg.setData(json); | |
| 222 | + deferredResultHolder.invokeResult(msg); | |
| 223 | + | |
| 224 | + if (offLineDetector.isOnline(deviceId)) { | |
| 225 | + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | |
| 226 | + } else { | |
| 227 | + } | |
| 228 | + } | |
| 229 | + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | |
| 230 | + e.printStackTrace(); | |
| 231 | + } | |
| 232 | + } | |
| 233 | + | |
| 234 | + /** | |
| 235 | + * 处理DeviceControl设备状态Message | |
| 236 | + * | |
| 237 | + * @param evt | |
| 238 | + */ | |
| 239 | + private void processMessageDeviceControl(RequestEvent evt) { | |
| 240 | + try { | |
| 241 | + Element rootElement = getRootElement(evt); | |
| 242 | + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); | |
| 243 | + String result = XmlUtil.getText(rootElement, "Result"); | |
| 244 | + // 回复200 OK | |
| 245 | + responseAck(evt); | |
| 246 | + if (!XmlUtil.isEmpty(result)) { | |
| 247 | + // 此处是对本平台发出DeviceControl指令的应答 | |
| 248 | + JSONObject json = new JSONObject(); | |
| 249 | + XmlUtil.node2Json(rootElement, json); | |
| 250 | + if (logger.isDebugEnabled()) { | |
| 251 | + logger.debug(json.toJSONString()); | |
| 252 | + } | |
| 253 | + RequestMessage msg = new RequestMessage(); | |
| 254 | + msg.setDeviceId(deviceId); | |
| 255 | + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL); | |
| 256 | + msg.setData(json); | |
| 257 | + deferredResultHolder.invokeResult(msg); | |
| 258 | + } else { | |
| 259 | + // 此处是上级发出的DeviceControl指令 | |
| 260 | + } | |
| 261 | + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | |
| 262 | + e.printStackTrace(); | |
| 263 | + } | |
| 264 | + } | |
| 265 | + | |
| 266 | + /** | |
| 267 | + * 处理DeviceConfig设备状态Message | |
| 268 | + * | |
| 269 | + * @param evt | |
| 270 | + */ | |
| 271 | + private void processMessageDeviceConfig(RequestEvent evt) { | |
| 272 | + try { | |
| 273 | + Element rootElement = getRootElement(evt); | |
| 274 | + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); | |
| 275 | + String result = XmlUtil.getText(rootElement, "Result"); | |
| 276 | + // 回复200 OK | |
| 277 | + responseAck(evt); | |
| 278 | + //if (!XmlUtil.isEmpty(result)) { | |
| 279 | + // 此处是对本平台发出DeviceControl指令的应答 | |
| 280 | + JSONObject json = new JSONObject(); | |
| 281 | + XmlUtil.node2Json(rootElement, json); | |
| 282 | + if (logger.isDebugEnabled()) { | |
| 283 | + logger.debug(json.toJSONString()); | |
| 284 | + } | |
| 285 | + RequestMessage msg = new RequestMessage(); | |
| 286 | + msg.setDeviceId(deviceId); | |
| 287 | + msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG); | |
| 288 | + msg.setData(json); | |
| 289 | + deferredResultHolder.invokeResult(msg); | |
| 290 | + // } else { | |
| 291 | + // // 此处是上级发出的DeviceConfig指令 | |
| 292 | + //} | |
| 293 | + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | |
| 294 | + e.printStackTrace(); | |
| 295 | + } | |
| 296 | + } | |
| 297 | + | |
| 298 | + /** | |
| 299 | + * 处理ConfigDownload设备状态Message | |
| 300 | + * | |
| 301 | + * @param evt | |
| 302 | + */ | |
| 303 | + private void processMessageConfigDownload(RequestEvent evt) { | |
| 304 | + try { | |
| 305 | + Element rootElement = getRootElement(evt); | |
| 306 | + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); | |
| 307 | + String result = XmlUtil.getText(rootElement, "Result"); | |
| 308 | + // 回复200 OK | |
| 309 | + responseAck(evt); | |
| 310 | + //if (!XmlUtil.isEmpty(result)) { | |
| 311 | + // 此处是对本平台发出DeviceControl指令的应答 | |
| 312 | + JSONObject json = new JSONObject(); | |
| 313 | + XmlUtil.node2Json(rootElement, json); | |
| 314 | + if (logger.isDebugEnabled()) { | |
| 315 | + logger.debug(json.toJSONString()); | |
| 316 | + } | |
| 317 | + RequestMessage msg = new RequestMessage(); | |
| 318 | + msg.setDeviceId(deviceId); | |
| 319 | + msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD); | |
| 320 | + msg.setData(json); | |
| 321 | + deferredResultHolder.invokeResult(msg); | |
| 322 | + // } else { | |
| 323 | + // // 此处是上级发出的DeviceConfig指令 | |
| 324 | + //} | |
| 325 | + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | |
| 326 | + e.printStackTrace(); | |
| 327 | + } | |
| 328 | + } | |
| 329 | + | |
| 330 | + /** | |
| 331 | + * 处理PresetQuery预置位列表Message | |
| 332 | + * | |
| 333 | + * @param evt | |
| 334 | + */ | |
| 335 | + private void processMessagePresetQuery(RequestEvent evt) { | |
| 336 | + try { | |
| 337 | + Element rootElement = getRootElement(evt); | |
| 338 | + String deviceId = XmlUtil.getText(rootElement, "DeviceID"); | |
| 339 | + String result = XmlUtil.getText(rootElement, "Result"); | |
| 340 | + // 回复200 OK | |
| 341 | + responseAck(evt); | |
| 342 | + if (rootElement.getName().equals("Response")) {// !XmlUtil.isEmpty(result)) { | |
| 343 | + // 此处是对本平台发出DeviceControl指令的应答 | |
| 344 | + JSONObject json = new JSONObject(); | |
| 345 | + XmlUtil.node2Json(rootElement, json); | |
| 346 | + if (logger.isDebugEnabled()) { | |
| 347 | + logger.debug(json.toJSONString()); | |
| 348 | + } | |
| 349 | + RequestMessage msg = new RequestMessage(); | |
| 350 | + msg.setDeviceId(deviceId); | |
| 351 | + msg.setType(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY); | |
| 352 | + msg.setData(json); | |
| 353 | + deferredResultHolder.invokeResult(msg); | |
| 354 | + } else { | |
| 355 | + // 此处是上级发出的DeviceControl指令 | |
| 111 | 356 | } |
| 112 | - } catch (DocumentException e) { | |
| 357 | + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | |
| 113 | 358 | e.printStackTrace(); |
| 114 | 359 | } |
| 115 | 360 | } |
| 116 | 361 | |
| 117 | 362 | /** |
| 118 | - * 收到deviceInfo设备信息请求 处理 | |
| 363 | + * 处理DeviceInfo设备信息Message | |
| 119 | 364 | * |
| 120 | 365 | * @param evt |
| 121 | 366 | */ |
| ... | ... | @@ -123,7 +368,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 123 | 368 | try { |
| 124 | 369 | Element rootElement = getRootElement(evt); |
| 125 | 370 | Element deviceIdElement = rootElement.element("DeviceID"); |
| 126 | - String deviceId = deviceIdElement.getText().toString(); | |
| 371 | + String deviceId = deviceIdElement.getTextTrim().toString(); | |
| 127 | 372 | |
| 128 | 373 | Device device = storager.queryVideoDevice(deviceId); |
| 129 | 374 | if (device == null) { |
| ... | ... | @@ -180,11 +425,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 180 | 425 | if (channelDeviceElement == null) { |
| 181 | 426 | continue; |
| 182 | 427 | } |
| 183 | - String channelDeviceId = channelDeviceElement.getText(); | |
| 428 | + String channelDeviceId = channelDeviceElement.getTextTrim(); | |
| 184 | 429 | Element channdelNameElement = itemDevice.element("Name"); |
| 185 | 430 | String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; |
| 186 | 431 | Element statusElement = itemDevice.element("Status"); |
| 187 | - String status = statusElement != null ? statusElement.getText().toString() : "ON"; | |
| 432 | + String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON"; | |
| 188 | 433 | DeviceChannel deviceChannel = new DeviceChannel(); |
| 189 | 434 | deviceChannel.setName(channelName); |
| 190 | 435 | deviceChannel.setChannelId(channelDeviceId); |
| ... | ... | @@ -238,15 +483,15 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 238 | 483 | deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); |
| 239 | 484 | } |
| 240 | 485 | deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password")); |
| 241 | - if (XmlUtil.getText(itemDevice, "Longitude") == null || XmlUtil.getText(itemDevice, "Longitude") == "") { | |
| 242 | - deviceChannel.setLongitude(0.00); | |
| 243 | - } else { | |
| 486 | + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) { | |
| 244 | 487 | deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude"))); |
| 245 | - } | |
| 246 | - if (XmlUtil.getText(itemDevice, "Latitude") == null || XmlUtil.getText(itemDevice, "Latitude") =="") { | |
| 247 | - deviceChannel.setLatitude(0.00); | |
| 248 | 488 | } else { |
| 489 | + deviceChannel.setLongitude(0.00); | |
| 490 | + } | |
| 491 | + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) { | |
| 249 | 492 | deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude"))); |
| 493 | + } else { | |
| 494 | + deviceChannel.setLatitude(0.00); | |
| 250 | 495 | } |
| 251 | 496 | if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") { |
| 252 | 497 | deviceChannel.setPTZType(0); |
| ... | ... | @@ -274,8 +519,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 274 | 519 | } |
| 275 | 520 | |
| 276 | 521 | /*** |
| 277 | - * 收到alarm设备报警信息 处理 | |
| 278 | - * | |
| 522 | + * alarm设备报警信息处理 | |
| 279 | 523 | * @param evt |
| 280 | 524 | */ |
| 281 | 525 | private void processMessageAlarm(RequestEvent evt) { |
| ... | ... | @@ -283,48 +527,72 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 283 | 527 | Element rootElement = getRootElement(evt); |
| 284 | 528 | Element deviceIdElement = rootElement.element("DeviceID"); |
| 285 | 529 | String deviceId = deviceIdElement.getText().toString(); |
| 530 | + // 回复200 OK | |
| 531 | + responseAck(evt); | |
| 286 | 532 | |
| 287 | 533 | Device device = storager.queryVideoDevice(deviceId); |
| 288 | 534 | if (device == null) { |
| 289 | - // TODO 也可能是通道 | |
| 290 | - // storager.queryChannel(deviceId) | |
| 291 | 535 | return; |
| 292 | 536 | } |
| 293 | 537 | |
| 294 | - DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 295 | - deviceAlarm.setDeviceId(deviceId); | |
| 296 | - deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); | |
| 297 | - deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); | |
| 298 | - deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); | |
| 299 | - if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { | |
| 300 | - deviceAlarm.setAlarmDescription(""); | |
| 301 | - } else { | |
| 302 | - deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription")); | |
| 303 | - } | |
| 304 | - if (XmlUtil.getText(rootElement, "Longitude") == null || XmlUtil.getText(rootElement, "Longitude") == "") { | |
| 305 | - deviceAlarm.setLongitude(0.00); | |
| 306 | - } else { | |
| 307 | - deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); | |
| 308 | - } | |
| 309 | - if (XmlUtil.getText(rootElement, "Latitude") == null || XmlUtil.getText(rootElement, "Latitude") =="") { | |
| 310 | - deviceAlarm.setLatitude(0.00); | |
| 311 | - } else { | |
| 312 | - deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); | |
| 313 | - } | |
| 314 | - | |
| 315 | - // device.setName(XmlUtil.getText(rootElement, "DeviceName")); | |
| 316 | - // device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer")); | |
| 317 | - // device.setModel(XmlUtil.getText(rootElement, "Model")); | |
| 318 | - // device.setFirmware(XmlUtil.getText(rootElement, "Firmware")); | |
| 319 | - // if (StringUtils.isEmpty(device.getStreamMode())) { | |
| 320 | - // device.setStreamMode("UDP"); | |
| 321 | - // } | |
| 322 | - // storager.updateDevice(device); | |
| 323 | - //cmder.catalogQuery(device, null); | |
| 324 | - // 回复200 OK | |
| 325 | - responseAck(evt); | |
| 326 | - if (offLineDetector.isOnline(deviceId)) { | |
| 327 | - publisher.deviceAlarmEventPublish(deviceAlarm); | |
| 538 | + if (rootElement.getName().equals("Notify")) { // 处理报警通知 | |
| 539 | + DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 540 | + deviceAlarm.setDeviceId(deviceId); | |
| 541 | + deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); | |
| 542 | + deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); | |
| 543 | + deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); | |
| 544 | + if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { | |
| 545 | + deviceAlarm.setAlarmDescription(""); | |
| 546 | + } else { | |
| 547 | + deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription")); | |
| 548 | + } | |
| 549 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) { | |
| 550 | + deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); | |
| 551 | + } else { | |
| 552 | + deviceAlarm.setLongitude(0.00); | |
| 553 | + } | |
| 554 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) { | |
| 555 | + deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); | |
| 556 | + } else { | |
| 557 | + deviceAlarm.setLatitude(0.00); | |
| 558 | + } | |
| 559 | + | |
| 560 | + if (!XmlUtil.isEmpty(deviceAlarm.getAlarmMethod())) { | |
| 561 | + if ( deviceAlarm.getAlarmMethod().equals("4")) { | |
| 562 | + MobilePosition mobilePosition = new MobilePosition(); | |
| 563 | + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); | |
| 564 | + mobilePosition.setTime(deviceAlarm.getAlarmTime()); | |
| 565 | + mobilePosition.setLongitude(deviceAlarm.getLongitude()); | |
| 566 | + mobilePosition.setLatitude(deviceAlarm.getLatitude()); | |
| 567 | + mobilePosition.setReportSource("GPS Alarm"); | |
| 568 | + BaiduPoint bp = new BaiduPoint(); | |
| 569 | + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); | |
| 570 | + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); | |
| 571 | + mobilePosition.setGeodeticSystem("BD-09"); | |
| 572 | + mobilePosition.setCnLng(bp.getBdLng()); | |
| 573 | + mobilePosition.setCnLat(bp.getBdLat()); | |
| 574 | + if (!userSetup.getSavePositionHistory()) { | |
| 575 | + storager.clearMobilePositionsByDeviceId(deviceId); | |
| 576 | + } | |
| 577 | + storager.insertMobilePosition(mobilePosition); | |
| 578 | + } | |
| 579 | + } | |
| 580 | + // TODO: 需要实现存储报警信息、报警分类 | |
| 581 | + | |
| 582 | + if (offLineDetector.isOnline(deviceId)) { | |
| 583 | + publisher.deviceAlarmEventPublish(deviceAlarm); | |
| 584 | + } | |
| 585 | + } else if (rootElement.getName().equals("Response")) { // 处理报警查询响应 | |
| 586 | + JSONObject json = new JSONObject(); | |
| 587 | + XmlUtil.node2Json(rootElement, json); | |
| 588 | + if (logger.isDebugEnabled()) { | |
| 589 | + logger.debug(json.toJSONString()); | |
| 590 | + } | |
| 591 | + RequestMessage msg = new RequestMessage(); | |
| 592 | + msg.setDeviceId(deviceId); | |
| 593 | + msg.setType(DeferredResultHolder.CALLBACK_CMD_ALARM); | |
| 594 | + msg.setData(json); | |
| 595 | + deferredResultHolder.invokeResult(msg); | |
| 328 | 596 | } |
| 329 | 597 | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { |
| 330 | 598 | // } catch (DocumentException e) { |
| ... | ... | @@ -350,14 +618,13 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 350 | 618 | } else { |
| 351 | 619 | } |
| 352 | 620 | } |
| 353 | - | |
| 354 | 621 | } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { |
| 355 | 622 | e.printStackTrace(); |
| 356 | 623 | } |
| 357 | 624 | } |
| 358 | 625 | |
| 359 | 626 | /*** |
| 360 | - * 收到catalog设备目录列表请求 处理 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致 | |
| 627 | + * 处理RecordInfo设备录像列表Message请求 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致 | |
| 361 | 628 | * |
| 362 | 629 | * @param evt |
| 363 | 630 | */ |
| ... | ... | @@ -444,12 +711,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 444 | 711 | // 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作 |
| 445 | 712 | // 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据 |
| 446 | 713 | |
| 447 | - // 对记录进行排序 | |
| 448 | 714 | RequestMessage msg = new RequestMessage(); |
| 449 | 715 | msg.setDeviceId(deviceId); |
| 450 | 716 | msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); |
| 451 | - // // 自然顺序排序, 元素进行升序排列 | |
| 452 | - // recordInfo.getRecordList().sort(Comparator.naturalOrder()); | |
| 453 | 717 | msg.setData(recordInfo); |
| 454 | 718 | deferredResultHolder.invokeResult(msg); |
| 455 | 719 | logger.info("处理完成,返回结果"); |
| ... | ... | @@ -458,7 +722,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { |
| 458 | 722 | } |
| 459 | 723 | } |
| 460 | 724 | |
| 461 | - | |
| 725 | + /** | |
| 726 | + * 收到MediaStatus消息处理 | |
| 727 | + * | |
| 728 | + * @param evt | |
| 729 | + */ | |
| 462 | 730 | private void processMessageMediaStatus(RequestEvent evt){ |
| 463 | 731 | try { |
| 464 | 732 | // 回复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 SIPCommander cmder; | |
| 54 | + | |
| 55 | + private IVideoManagerStorager storager; | |
| 56 | + | |
| 57 | + private IRedisCatchStorage redisCatchStorage; | |
| 58 | + | |
| 59 | + private EventPublisher publisher; | |
| 60 | + | |
| 61 | + private RedisUtil redis; | |
| 62 | + | |
| 63 | + private DeferredResultHolder deferredResultHolder; | |
| 64 | + | |
| 65 | + private DeviceOffLineDetector offLineDetector; | |
| 66 | + | |
| 67 | + private static final String NOTIFY_CATALOG = "Catalog"; | |
| 68 | + private static final String NOTIFY_ALARM = "Alarm"; | |
| 69 | + private static final String NOTIFY_MOBILE_POSITION = "MobilePosition"; | |
| 70 | + | |
| 71 | + @Override | |
| 72 | + public void process(RequestEvent evt) { | |
| 73 | + try { | |
| 74 | + Element rootElement = getRootElement(evt); | |
| 75 | + String cmd = XmlUtil.getText(rootElement, "CmdType"); | |
| 76 | + | |
| 77 | + if (NOTIFY_CATALOG.equals(cmd)) { | |
| 78 | + logger.info("接收到Catalog通知"); | |
| 79 | + processNotifyCatalogList(evt); | |
| 80 | + } else if (NOTIFY_ALARM.equals(cmd)) { | |
| 81 | + logger.info("接收到Alarm通知"); | |
| 82 | + processNotifyAlarm(evt); | |
| 83 | + } else if (NOTIFY_MOBILE_POSITION.equals(cmd)) { | |
| 84 | + logger.info("接收到MobilePosition通知"); | |
| 85 | + processNotifyMobilePosition(evt); | |
| 86 | + } else { | |
| 87 | + logger.info("接收到消息:" + cmd); | |
| 88 | + response200Ok(evt); | |
| 89 | + } | |
| 90 | + } catch (DocumentException | SipException |InvalidArgumentException | ParseException e) { | |
| 91 | + e.printStackTrace(); | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * 处理MobilePosition移动位置Notify | |
| 97 | + * @param evt | |
| 98 | + */ | |
| 99 | + private void processNotifyMobilePosition(RequestEvent evt) { | |
| 100 | + try { | |
| 101 | + //回复 200 OK | |
| 102 | + Element rootElement = getRootElement(evt); | |
| 103 | + MobilePosition mobilePosition = new MobilePosition(); | |
| 104 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 105 | + String deviceId = deviceIdElement.getTextTrim().toString(); | |
| 106 | + Device device = storager.queryVideoDevice(deviceId); | |
| 107 | + if (device != null) { | |
| 108 | + if (!StringUtils.isEmpty(device.getName())) { | |
| 109 | + mobilePosition.setDeviceName(device.getName()); | |
| 110 | + } | |
| 111 | + } | |
| 112 | + mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID")); | |
| 113 | + mobilePosition.setTime(XmlUtil.getText(rootElement, "Time")); | |
| 114 | + mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); | |
| 115 | + mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); | |
| 116 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) { | |
| 117 | + mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed"))); | |
| 118 | + } else { | |
| 119 | + mobilePosition.setSpeed(0.0); | |
| 120 | + } | |
| 121 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) { | |
| 122 | + mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction"))); | |
| 123 | + } else { | |
| 124 | + mobilePosition.setDirection(0.0); | |
| 125 | + } | |
| 126 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) { | |
| 127 | + mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude"))); | |
| 128 | + } else { | |
| 129 | + mobilePosition.setAltitude(0.0); | |
| 130 | + } | |
| 131 | + mobilePosition.setReportSource("Mobile Position"); | |
| 132 | + BaiduPoint bp = new BaiduPoint(); | |
| 133 | + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); | |
| 134 | + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); | |
| 135 | + mobilePosition.setGeodeticSystem("BD-09"); | |
| 136 | + mobilePosition.setCnLng(bp.getBdLng()); | |
| 137 | + mobilePosition.setCnLat(bp.getBdLat()); | |
| 138 | + if (!userSetup.getSavePositionHistory()) { | |
| 139 | + storager.clearMobilePositionsByDeviceId(deviceId); | |
| 140 | + } | |
| 141 | + storager.insertMobilePosition(mobilePosition); | |
| 142 | + response200Ok(evt); | |
| 143 | + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | |
| 144 | + e.printStackTrace(); | |
| 145 | + } | |
| 146 | + } | |
| 147 | + | |
| 148 | + /*** | |
| 149 | + * 处理alarm设备报警Notify | |
| 150 | + * @param evt | |
| 151 | + */ | |
| 152 | + private void processNotifyAlarm(RequestEvent evt) { | |
| 153 | + try { | |
| 154 | + Element rootElement = getRootElement(evt); | |
| 155 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 156 | + String deviceId = deviceIdElement.getText().toString(); | |
| 157 | + | |
| 158 | + Device device = storager.queryVideoDevice(deviceId); | |
| 159 | + if (device == null) { | |
| 160 | + return; | |
| 161 | + } | |
| 162 | + DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 163 | + deviceAlarm.setDeviceId(deviceId); | |
| 164 | + deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); | |
| 165 | + deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); | |
| 166 | + deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); | |
| 167 | + if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { | |
| 168 | + deviceAlarm.setAlarmDescription(""); | |
| 169 | + } else { | |
| 170 | + deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription")); | |
| 171 | + } | |
| 172 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) { | |
| 173 | + deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); | |
| 174 | + } else { | |
| 175 | + deviceAlarm.setLongitude(0.00); | |
| 176 | + } | |
| 177 | + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) { | |
| 178 | + deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); | |
| 179 | + } else { | |
| 180 | + deviceAlarm.setLatitude(0.00); | |
| 181 | + } | |
| 182 | + | |
| 183 | + if ( deviceAlarm.getAlarmMethod().equals("4")) { | |
| 184 | + MobilePosition mobilePosition = new MobilePosition(); | |
| 185 | + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); | |
| 186 | + mobilePosition.setTime(deviceAlarm.getAlarmTime()); | |
| 187 | + mobilePosition.setLongitude(deviceAlarm.getLongitude()); | |
| 188 | + mobilePosition.setLatitude(deviceAlarm.getLatitude()); | |
| 189 | + mobilePosition.setReportSource("GPS Alarm"); | |
| 190 | + BaiduPoint bp = new BaiduPoint(); | |
| 191 | + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); | |
| 192 | + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); | |
| 193 | + mobilePosition.setGeodeticSystem("BD-09"); | |
| 194 | + mobilePosition.setCnLng(bp.getBdLng()); | |
| 195 | + mobilePosition.setCnLat(bp.getBdLat()); | |
| 196 | + if (!userSetup.getSavePositionHistory()) { | |
| 197 | + storager.clearMobilePositionsByDeviceId(deviceId); | |
| 198 | + } | |
| 199 | + storager.insertMobilePosition(mobilePosition); | |
| 200 | + } | |
| 201 | + // TODO: 需要实现存储报警信息、报警分类 | |
| 202 | + | |
| 203 | + // 回复200 OK | |
| 204 | + response200Ok(evt); | |
| 205 | + if (offLineDetector.isOnline(deviceId)) { | |
| 206 | + publisher.deviceAlarmEventPublish(deviceAlarm); | |
| 207 | + } | |
| 208 | + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | |
| 209 | + e.printStackTrace(); | |
| 210 | + } | |
| 211 | + } | |
| 212 | + | |
| 213 | + /*** | |
| 214 | + * 处理catalog设备目录列表Notify | |
| 215 | + * | |
| 216 | + * @param evt | |
| 217 | + */ | |
| 218 | + private void processNotifyCatalogList(RequestEvent evt) { | |
| 219 | + try { | |
| 220 | + Element rootElement = getRootElement(evt); | |
| 221 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 222 | + String deviceId = deviceIdElement.getText(); | |
| 223 | + Element deviceListElement = rootElement.element("DeviceList"); | |
| 224 | + if (deviceListElement == null) { | |
| 225 | + return; | |
| 226 | + } | |
| 227 | + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); | |
| 228 | + if (deviceListIterator != null) { | |
| 229 | + Device device = storager.queryVideoDevice(deviceId); | |
| 230 | + if (device == null) { | |
| 231 | + return; | |
| 232 | + } | |
| 233 | + // 遍历DeviceList | |
| 234 | + while (deviceListIterator.hasNext()) { | |
| 235 | + Element itemDevice = deviceListIterator.next(); | |
| 236 | + Element channelDeviceElement = itemDevice.element("DeviceID"); | |
| 237 | + if (channelDeviceElement == null) { | |
| 238 | + continue; | |
| 239 | + } | |
| 240 | + String channelDeviceId = channelDeviceElement.getTextTrim(); | |
| 241 | + Element channdelNameElement = itemDevice.element("Name"); | |
| 242 | + String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; | |
| 243 | + Element statusElement = itemDevice.element("Status"); | |
| 244 | + String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON"; | |
| 245 | + DeviceChannel deviceChannel = new DeviceChannel(); | |
| 246 | + deviceChannel.setName(channelName); | |
| 247 | + deviceChannel.setChannelId(channelDeviceId); | |
| 248 | + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 | |
| 249 | + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { | |
| 250 | + deviceChannel.setStatus(1); | |
| 251 | + } | |
| 252 | + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { | |
| 253 | + deviceChannel.setStatus(0); | |
| 254 | + } | |
| 255 | + | |
| 256 | + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer")); | |
| 257 | + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model")); | |
| 258 | + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner")); | |
| 259 | + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode")); | |
| 260 | + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block")); | |
| 261 | + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address")); | |
| 262 | + if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") { | |
| 263 | + deviceChannel.setParental(0); | |
| 264 | + } else { | |
| 265 | + deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental"))); | |
| 266 | + } | |
| 267 | + deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID")); | |
| 268 | + if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay")== "") { | |
| 269 | + deviceChannel.setSafetyWay(0); | |
| 270 | + } else { | |
| 271 | + deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay"))); | |
| 272 | + } | |
| 273 | + if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") =="") { | |
| 274 | + deviceChannel.setRegisterWay(1); | |
| 275 | + } else { | |
| 276 | + deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay"))); | |
| 277 | + } | |
| 278 | + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum")); | |
| 279 | + if (XmlUtil.getText(itemDevice, "Certifiable") == null || 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 || XmlUtil.getText(itemDevice, "ErrCode") == "") { | |
| 285 | + deviceChannel.setErrCode(0); | |
| 286 | + } else { | |
| 287 | + deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode"))); | |
| 288 | + } | |
| 289 | + deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime")); | |
| 290 | + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy")); | |
| 291 | + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress")); | |
| 292 | + if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") =="") { | |
| 293 | + deviceChannel.setPort(0); | |
| 294 | + } else { | |
| 295 | + deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); | |
| 296 | + } | |
| 297 | + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password")); | |
| 298 | + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) { | |
| 299 | + deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude"))); | |
| 300 | + } else { | |
| 301 | + deviceChannel.setLongitude(0.00); | |
| 302 | + } | |
| 303 | + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) { | |
| 304 | + deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude"))); | |
| 305 | + } else { | |
| 306 | + deviceChannel.setLatitude(0.00); | |
| 307 | + } | |
| 308 | + if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") { | |
| 309 | + deviceChannel.setPTZType(0); | |
| 310 | + } else { | |
| 311 | + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); | |
| 312 | + } | |
| 313 | + deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC | |
| 314 | + storager.updateChannel(device.getDeviceId(), deviceChannel); | |
| 315 | + } | |
| 316 | + | |
| 317 | + // RequestMessage msg = new RequestMessage(); | |
| 318 | + // msg.setDeviceId(deviceId); | |
| 319 | + // msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG); | |
| 320 | + // msg.setData(device); | |
| 321 | + // deferredResultHolder.invokeResult(msg); | |
| 322 | + // 回复200 OK | |
| 323 | + response200Ok(evt); | |
| 324 | + if (offLineDetector.isOnline(deviceId)) { | |
| 325 | + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | |
| 326 | + } | |
| 327 | + } | |
| 328 | + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | |
| 329 | + e.printStackTrace(); | |
| 330 | + } | |
| 331 | + } | |
| 332 | + | |
| 333 | + | |
| 334 | + /*** | |
| 335 | + * 回复200 OK | |
| 336 | + * @param evt | |
| 337 | + * @throws SipException | |
| 338 | + * @throws InvalidArgumentException | |
| 339 | + * @throws ParseException | |
| 340 | + */ | |
| 341 | + private void response200Ok(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { | |
| 342 | + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); | |
| 343 | + getServerTransaction(evt).sendResponse(response); | |
| 344 | + } | |
| 345 | + | |
| 346 | + private Element getRootElement(RequestEvent evt) throws DocumentException { | |
| 347 | + Request request = evt.getRequest(); | |
| 348 | + SAXReader reader = new SAXReader(); | |
| 349 | + reader.setEncoding("gbk"); | |
| 350 | + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | |
| 351 | + return xml.getRootElement(); | |
| 352 | + } | |
| 353 | + | |
| 354 | + public void setCmder(SIPCommander cmder) { | |
| 355 | + this.cmder = cmder; | |
| 356 | + } | |
| 357 | + | |
| 358 | + public void setStorager(IVideoManagerStorager storager) { | |
| 359 | + this.storager = storager; | |
| 360 | + } | |
| 361 | + | |
| 362 | + public void setPublisher(EventPublisher publisher) { | |
| 363 | + this.publisher = publisher; | |
| 364 | + } | |
| 365 | + | |
| 366 | + public void setRedis(RedisUtil redis) { | |
| 367 | + this.redis = redis; | |
| 368 | + } | |
| 369 | + | |
| 370 | + public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) { | |
| 371 | + this.deferredResultHolder = deferredResultHolder; | |
| 372 | + } | |
| 373 | + | |
| 374 | + public void setOffLineDetector(DeviceOffLineDetector offLineDetector) { | |
| 375 | + this.offLineDetector = offLineDetector; | |
| 376 | + } | |
| 377 | + | |
| 378 | + public IRedisCatchStorage getRedisCatchStorage() { | |
| 379 | + return redisCatchStorage; | |
| 380 | + } | |
| 381 | + | |
| 382 | + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { | |
| 383 | + this.redisCatchStorage = redisCatchStorage; | |
| 384 | + } | |
| 385 | +} | ... | ... |
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/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 an Integer!"); | |
| 19 | + return true; | |
| 20 | + } catch (Exception e) { | |
| 21 | + System.out.println(str + " Is not an Integer!"); | |
| 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 Number!"); | |
| 35 | + return true; | |
| 36 | + } catch (Exception e) { | |
| 37 | + System.out.println(str + " Is not Number!"); | |
| 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/storager/IVideoManagerStorager.java
| ... | ... | @@ -4,6 +4,7 @@ import java.util.List; |
| 4 | 4 | |
| 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.bean.MobilePosition; | |
| 7 | 8 | import com.github.pagehelper.PageInfo; |
| 8 | 9 | |
| 9 | 10 | /** |
| ... | ... | @@ -151,4 +152,30 @@ public interface IVideoManagerStorager { |
| 151 | 152 | */ |
| 152 | 153 | void cleanChannelsForDevice(String deviceId); |
| 153 | 154 | |
| 155 | + /** | |
| 156 | + * 添加Mobile Position设备移动位置 | |
| 157 | + * @param MobilePosition | |
| 158 | + * @return | |
| 159 | + */ | |
| 160 | + public boolean insertMobilePosition(MobilePosition mobilePosition); | |
| 161 | + | |
| 162 | + /** | |
| 163 | + * 查询移动位置轨迹 | |
| 164 | + * @param deviceId | |
| 165 | + * @param startTime | |
| 166 | + * @param endTime | |
| 167 | + */ | |
| 168 | + public List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime); | |
| 169 | + | |
| 170 | + /** | |
| 171 | + * 查询最新移动位置 | |
| 172 | + * @param deviceId | |
| 173 | + */ | |
| 174 | + public MobilePosition queryLatestPosition(String deviceId); | |
| 175 | + | |
| 176 | + /** | |
| 177 | + * 删除指定设备的所有移动位置 | |
| 178 | + * @param deviceId | |
| 179 | + */ | |
| 180 | + public int clearMobilePositionsByDeviceId(String deviceId); | |
| 154 | 181 | } | ... | ... |
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/VideoManagerStoragerImpl.java
| ... | ... | @@ -3,8 +3,10 @@ package com.genersoft.iot.vmp.storager.impl; |
| 3 | 3 | import java.util.*; |
| 4 | 4 | |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; | |
| 6 | 7 | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| 7 | 8 | import com.genersoft.iot.vmp.storager.dao.DeviceMapper; |
| 9 | +import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; | |
| 8 | 10 | import com.github.pagehelper.PageHelper; |
| 9 | 11 | import com.github.pagehelper.PageInfo; |
| 10 | 12 | import io.swagger.models.auth.In; |
| ... | ... | @@ -27,7 +29,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { |
| 27 | 29 | private DeviceMapper deviceMapper; |
| 28 | 30 | |
| 29 | 31 | @Autowired |
| 30 | - private DeviceChannelMapper deviceChannelMapper; | |
| 32 | + private DeviceChannelMapper deviceChannelMapper; | |
| 33 | + | |
| 34 | + @Autowired | |
| 35 | + private DeviceMobilePositionMapper deviceMobilePositionMapper; | |
| 31 | 36 | |
| 32 | 37 | |
| 33 | 38 | /** |
| ... | ... | @@ -200,11 +205,49 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { |
| 200 | 205 | return deviceMapper.update(device) > 0; |
| 201 | 206 | } |
| 202 | 207 | |
| 203 | - | |
| 208 | + /** | |
| 209 | + * 清空通道 | |
| 210 | + * @param deviceId | |
| 211 | + */ | |
| 204 | 212 | @Override |
| 205 | 213 | public void cleanChannelsForDevice(String deviceId) { |
| 206 | 214 | int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId); |
| 207 | 215 | } |
| 208 | 216 | |
| 217 | + /** | |
| 218 | + * 添加Mobile Position设备移动位置 | |
| 219 | + * @param MobilePosition | |
| 220 | + */ | |
| 221 | + @Override | |
| 222 | + public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { | |
| 223 | + return deviceMobilePositionMapper.insertNewPosition(mobilePosition) > 0; | |
| 224 | + } | |
| 209 | 225 | |
| 226 | + /** | |
| 227 | + * 查询移动位置轨迹 | |
| 228 | + * @param deviceId | |
| 229 | + * @param startTime | |
| 230 | + * @param endTime | |
| 231 | + */ | |
| 232 | + @Override | |
| 233 | + public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime) { | |
| 234 | + return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime); | |
| 235 | + } | |
| 236 | + | |
| 237 | + /** | |
| 238 | + * 查询最新移动位置 | |
| 239 | + * @param deviceId | |
| 240 | + */ | |
| 241 | + @Override | |
| 242 | + public MobilePosition queryLatestPosition(String deviceId) { | |
| 243 | + return deviceMobilePositionMapper.queryLatestPositionByDevice(deviceId); | |
| 244 | + } | |
| 245 | + | |
| 246 | + /** | |
| 247 | + * 删除指定设备的所有移动位置 | |
| 248 | + * @param deviceId | |
| 249 | + */ | |
| 250 | + public int clearMobilePositionsByDeviceId(String deviceId) { | |
| 251 | + return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); | |
| 252 | + } | |
| 210 | 253 | } | ... | ... |
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/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.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 DeviceConfig { | |
| 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 | + * @param enabled 看守位使能1:开启,0:关闭 | |
| 49 | + * @param resetTime 自动归位时间间隔(可选) | |
| 50 | + * @param presetIndex 调用预置位编号(可选) | |
| 51 | + * @param channelId 通道编码(可选) | |
| 52 | + */ | |
| 53 | + @GetMapping("/config/{deviceId}/basicParam") | |
| 54 | + public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId, | |
| 55 | + @RequestParam(required = false) String channelId, | |
| 56 | + @RequestParam(required = false) String name, | |
| 57 | + @RequestParam(required = false) String expiration, | |
| 58 | + @RequestParam(required = false) String heartBeatInterval, | |
| 59 | + @RequestParam(required = false) String heartBeatCount) { | |
| 60 | + if (logger.isDebugEnabled()) { | |
| 61 | + logger.debug("报警复位API调用"); | |
| 62 | + } | |
| 63 | + Device device = storager.queryVideoDevice(deviceId); | |
| 64 | + cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> { | |
| 65 | + Response response = event.getResponse(); | |
| 66 | + RequestMessage msg = new RequestMessage(); | |
| 67 | + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); | |
| 68 | + msg.setData(String.format("设备配置操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); | |
| 69 | + resultHolder.invokeResult(msg); | |
| 70 | + }); | |
| 71 | + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L); | |
| 72 | + result.onTimeout(() -> { | |
| 73 | + logger.warn(String.format("设备配置操作超时, 设备未返回应答指令")); | |
| 74 | + // 释放rtpserver | |
| 75 | + RequestMessage msg = new RequestMessage(); | |
| 76 | + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); | |
| 77 | + JSONObject json = new JSONObject(); | |
| 78 | + json.put("DeviceID", deviceId); | |
| 79 | + json.put("Status", "Timeout"); | |
| 80 | + json.put("Description", "设备配置操作超时, 设备未返回应答指令"); | |
| 81 | + msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令"); | |
| 82 | + resultHolder.invokeResult(msg); | |
| 83 | + }); | |
| 84 | + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); | |
| 85 | + return result; | |
| 86 | + } | |
| 87 | + | |
| 88 | + /** | |
| 89 | + * 设备配置查询请求API接口 | |
| 90 | + * | |
| 91 | + * @param deviceId | |
| 92 | + */ | |
| 93 | + @GetMapping("/config/{deviceId}/query/{configType}") | |
| 94 | + public DeferredResult<ResponseEntity<String>> configDownloadApi(@PathVariable String deviceId, | |
| 95 | + @PathVariable String configType, | |
| 96 | + @RequestParam(required = false) String channelId) { | |
| 97 | + if (logger.isDebugEnabled()) { | |
| 98 | + logger.debug("设备状态查询API调用"); | |
| 99 | + } | |
| 100 | + Device device = storager.queryVideoDevice(deviceId); | |
| 101 | + cmder.deviceConfigQuery(device, channelId, configType, event -> { | |
| 102 | + Response response = event.getResponse(); | |
| 103 | + RequestMessage msg = new RequestMessage(); | |
| 104 | + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); | |
| 105 | + msg.setData(String.format("获取设备配置失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); | |
| 106 | + resultHolder.invokeResult(msg); | |
| 107 | + }); | |
| 108 | + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L); | |
| 109 | + result.onTimeout(()->{ | |
| 110 | + logger.warn(String.format("获取设备配置超时")); | |
| 111 | + // 释放rtpserver | |
| 112 | + RequestMessage msg = new RequestMessage(); | |
| 113 | + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); | |
| 114 | + msg.setData("Timeout. Device did not response to this command."); | |
| 115 | + resultHolder.invokeResult(msg); | |
| 116 | + }); | |
| 117 | + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); | |
| 118 | + return result; | |
| 119 | + } | |
| 120 | + | |
| 121 | +} | ... | ... |
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
| ... | ... | @@ -17,6 +17,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 17 | 17 | import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
| 18 | 18 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 19 | 19 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 20 | +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | |
| 20 | 21 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 21 | 22 | |
| 22 | 23 | import javax.sip.message.Response; |
| ... | ... | @@ -24,9 +25,9 @@ import javax.sip.message.Response; |
| 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/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/resources/application-dev.yml
| ... | ... | @@ -35,18 +35,18 @@ server: |
| 35 | 35 | # 作为28181服务器的配置 |
| 36 | 36 | sip: |
| 37 | 37 | # [必须修改] 本机的IP, 必须是网卡上的IP |
| 38 | - ip: 192.168.1.44 | |
| 38 | + ip: 192.168.0.100 | |
| 39 | 39 | # [可选] 28181服务监听的端口 |
| 40 | 40 | port: 5060 |
| 41 | 41 | # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) |
| 42 | 42 | # 后两位为行业编码,定义参照附录D.3 |
| 43 | 43 | # 3701020049标识山东济南历下区 信息行业接入 |
| 44 | 44 | # [可选] |
| 45 | - domain: 3402000000 | |
| 45 | + domain: 4401020049 | |
| 46 | 46 | # [可选] |
| 47 | - id: 34020000002000000001 | |
| 47 | + id: 44010200492000000001 | |
| 48 | 48 | # [可选] 默认设备认证密码,后续扩展使用设备单独密码 |
| 49 | - password: 12345678 | |
| 49 | + password: admin123 | |
| 50 | 50 | |
| 51 | 51 | # 登陆的用户名密码 |
| 52 | 52 | auth: |
| ... | ... | @@ -58,7 +58,7 @@ auth: |
| 58 | 58 | #zlm服务器配置 |
| 59 | 59 | media: |
| 60 | 60 | # [必须修改] zlm服务器的内网IP |
| 61 | - ip: 192.168.1.44 | |
| 61 | + ip: 192.168.0.100 | |
| 62 | 62 | # [可选] zlm服务器的公网IP, 内网部署置空即可 |
| 63 | 63 | wanIp: |
| 64 | 64 | # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip |
| ... | ... | @@ -70,9 +70,9 @@ media: |
| 70 | 70 | # [可选] zlm服务器的hook.admin_params=secret |
| 71 | 71 | secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc |
| 72 | 72 | # [可选] zlm服务器的general.streamNoneReaderDelayMS |
| 73 | - streamNoneReaderDelayMS: 600000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流 | |
| 73 | + streamNoneReaderDelayMS: 18000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流 | |
| 74 | 74 | # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true |
| 75 | - autoApplyPlay: true | |
| 75 | + autoApplyPlay: false | |
| 76 | 76 | # [可选] 部分设备需要扩展SDP,需要打开此设置 |
| 77 | 77 | seniorSdp: false |
| 78 | 78 | # 启用udp多端口模式, 详细解释参考: https://github.com/xia-chu/ZLMediaKit/wiki/GB28181%E6%8E%A8%E6%B5%81 下的高阶使用 |
| ... | ... | @@ -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 | ... | ... |
src/main/resources/wvp.sqlite
No preview for this file type
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
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 | |
| 9 | 10 | const originalPush = VueRouter.prototype.push |
| ... | ... | @@ -35,5 +36,10 @@ export default new VueRouter({ |
| 35 | 36 | name: 'channelList', |
| 36 | 37 | component: channelList, |
| 37 | 38 | }, |
| 39 | + { | |
| 40 | + path: '/devicePosition/:deviceId/:parentChannelId/:count/:page', | |
| 41 | + name: 'devicePosition', | |
| 42 | + component: devicePosition, | |
| 43 | + }, | |
| 38 | 44 | ] |
| 39 | 45 | }) | ... | ... |