Commit 2a273acd09cc5e9656a5cf2673c98d7b5e8453df
1 parent
3609d361
增加上级平台云台控制功能
Showing
4 changed files
with
90 additions
and
34 deletions
README.md
| @@ -60,21 +60,24 @@ https://gitee.com/18010473990/wvp-GB28181.git | @@ -60,21 +60,24 @@ https://gitee.com/18010473990/wvp-GB28181.git | ||
| 60 | 15. 支持订阅与通知方法 | 60 | 15. 支持订阅与通知方法 |
| 61 | - [X] 移动位置订阅 | 61 | - [X] 移动位置订阅 |
| 62 | - [X] 移动位置通知处理 | 62 | - [X] 移动位置通知处理 |
| 63 | - - [ ] 报警事件订阅 | 63 | + - [X] 报警事件订阅 |
| 64 | - [X] 报警事件通知处理 | 64 | - [X] 报警事件通知处理 |
| 65 | - [ ] 设备目录订阅 | 65 | - [ ] 设备目录订阅 |
| 66 | - [X] 设备目录通知处理 | 66 | - [X] 设备目录通知处理 |
| 67 | 16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 | 67 | 16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 |
| 68 | 68 | ||
| 69 | # 2.0 支持特性 | 69 | # 2.0 支持特性 |
| 70 | -- [ ] 国标通道向上级联 | 70 | +- [X] 国标通道向上级联 |
| 71 | - [X] WEB添加上级平台 | 71 | - [X] WEB添加上级平台 |
| 72 | - [X] 注册 | 72 | - [X] 注册 |
| 73 | - [X] 心跳保活 | 73 | - [X] 心跳保活 |
| 74 | - [X] 通道选择 | 74 | - [X] 通道选择 |
| 75 | - [X] 通道推送 | 75 | - [X] 通道推送 |
| 76 | - - [ ] 点播 | ||
| 77 | - - [ ] 云台控制 | 76 | + - [X] 点播 |
| 77 | + - [X] 云台控制 | ||
| 78 | + - [X] 平台状态查询 | ||
| 79 | + - [X] 平台信息查询 | ||
| 80 | + - [X] 平台远程启动 | ||
| 78 | - [ ] 添加RTSP视频 | 81 | - [ ] 添加RTSP视频 |
| 79 | - [ ] 添加ONVIF探测局域网内的设备 | 82 | - [ ] 添加ONVIF探测局域网内的设备 |
| 80 | - [ ] 添加RTMP视频 | 83 | - [ ] 添加RTMP视频 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| @@ -78,6 +78,14 @@ public interface ISIPCommander { | @@ -78,6 +78,14 @@ public interface ISIPCommander { | ||
| 78 | boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2); | 78 | boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2); |
| 79 | 79 | ||
| 80 | /** | 80 | /** |
| 81 | + * 前端控制指令(用于转发上级指令) | ||
| 82 | + * @param device 控制设备 | ||
| 83 | + * @param channelId 预览通道 | ||
| 84 | + * @param cmdString 前端控制指令串 | ||
| 85 | + */ | ||
| 86 | + boolean fronEndCmd(Device device, String channelId, String cmdString); | ||
| 87 | + | ||
| 88 | + /** | ||
| 81 | * 请求预览视频流 | 89 | * 请求预览视频流 |
| 82 | * | 90 | * |
| 83 | * @param device 视频设备 | 91 | * @param device 视频设备 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -282,6 +282,36 @@ public class SIPCommander implements ISIPCommander { | @@ -282,6 +282,36 @@ public class SIPCommander implements ISIPCommander { | ||
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | /** | 284 | /** |
| 285 | + * 前端控制指令(用于转发上级指令) | ||
| 286 | + * @param device 控制设备 | ||
| 287 | + * @param channelId 预览通道 | ||
| 288 | + * @param cmdString 前端控制指令串 | ||
| 289 | + */ | ||
| 290 | + @Override | ||
| 291 | + public boolean fronEndCmd(Device device, String channelId, String cmdString) { | ||
| 292 | + try { | ||
| 293 | + StringBuffer ptzXml = new StringBuffer(200); | ||
| 294 | + ptzXml.append("<?xml version=\"1.0\" ?>\r\n"); | ||
| 295 | + ptzXml.append("<Control>\r\n"); | ||
| 296 | + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n"); | ||
| 297 | + ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | ||
| 298 | + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); | ||
| 299 | + ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n"); | ||
| 300 | + ptzXml.append("<Info>\r\n"); | ||
| 301 | + ptzXml.append("</Info>\r\n"); | ||
| 302 | + ptzXml.append("</Control>\r\n"); | ||
| 303 | + | ||
| 304 | + String tm = Long.toString(System.currentTimeMillis()); | ||
| 305 | + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null); | ||
| 306 | + transmitRequest(device, request); | ||
| 307 | + return true; | ||
| 308 | + } catch (SipException | ParseException | InvalidArgumentException e) { | ||
| 309 | + e.printStackTrace(); | ||
| 310 | + } | ||
| 311 | + return false; | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + /** | ||
| 285 | * 请求预览视频流 | 315 | * 请求预览视频流 |
| 286 | * @param device 视频设备 | 316 | * @param device 视频设备 |
| 287 | * @param channelId 预览通道 | 317 | * @param channelId 预览通道 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
| @@ -4,8 +4,11 @@ import java.io.ByteArrayInputStream; | @@ -4,8 +4,11 @@ import java.io.ByteArrayInputStream; | ||
| 4 | import java.text.ParseException; | 4 | import java.text.ParseException; |
| 5 | import java.util.*; | 5 | import java.util.*; |
| 6 | 6 | ||
| 7 | +import javax.sip.address.SipURI; | ||
| 8 | + | ||
| 7 | import javax.sip.header.FromHeader; | 9 | import javax.sip.header.FromHeader; |
| 8 | import javax.sip.header.HeaderAddress; | 10 | import javax.sip.header.HeaderAddress; |
| 11 | +import javax.sip.header.ToHeader; | ||
| 9 | import javax.sip.InvalidArgumentException; | 12 | import javax.sip.InvalidArgumentException; |
| 10 | import javax.sip.ListeningPoint; | 13 | import javax.sip.ListeningPoint; |
| 11 | import javax.sip.ObjectInUseException; | 14 | import javax.sip.ObjectInUseException; |
| @@ -290,38 +293,50 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -290,38 +293,50 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 290 | deferredResultHolder.invokeResult(msg); | 293 | deferredResultHolder.invokeResult(msg); |
| 291 | } else { | 294 | } else { |
| 292 | // 此处是上级发出的DeviceControl指令 | 295 | // 此处是上级发出的DeviceControl指令 |
| 293 | - if (XmlUtil.getText(rootElement, "TeleBoot").equals("Boot") ) { // 远程启动功能:需要在重新启动程序后先对SipStack解绑 | ||
| 294 | - String platformId = ((SipUri) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); | ||
| 295 | - logger.info("执行远程启动命令"); | ||
| 296 | - ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); | ||
| 297 | - cmderFroPlatform.unregister(parentPlatform, null, null); | ||
| 298 | - | ||
| 299 | - Thread restartThread = new Thread(new Runnable() { | ||
| 300 | - @Override | ||
| 301 | - public void run() { | ||
| 302 | - try { | ||
| 303 | - Thread.sleep(3000); | ||
| 304 | - SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); | ||
| 305 | - SipStackImpl stack = (SipStackImpl)up.getSipStack(); | ||
| 306 | - stack.stop(); | ||
| 307 | - Iterator listener = stack.getListeningPoints(); | ||
| 308 | - while (listener.hasNext()) { | ||
| 309 | - stack.deleteListeningPoint((ListeningPoint) listener.next()); | ||
| 310 | - } | ||
| 311 | - Iterator providers = stack.getSipProviders(); | ||
| 312 | - while (providers.hasNext()) { | ||
| 313 | - stack.deleteSipProvider((SipProvider) providers.next()); | 296 | + String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); |
| 297 | + String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); | ||
| 298 | + // 远程启动功能 | ||
| 299 | + if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) { | ||
| 300 | + if (deviceId.equals(targetGBId)) { | ||
| 301 | + // 远程启动功能:需要在重新启动程序后先对SipStack解绑 | ||
| 302 | + logger.info("执行远程启动本平台命令"); | ||
| 303 | + ParentPlatform parentPlatform = storager.queryParentPlatById(platformId); | ||
| 304 | + cmderFroPlatform.unregister(parentPlatform, null, null); | ||
| 305 | + | ||
| 306 | + Thread restartThread = new Thread(new Runnable() { | ||
| 307 | + @Override | ||
| 308 | + public void run() { | ||
| 309 | + try { | ||
| 310 | + Thread.sleep(3000); | ||
| 311 | + SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); | ||
| 312 | + SipStackImpl stack = (SipStackImpl)up.getSipStack(); | ||
| 313 | + stack.stop(); | ||
| 314 | + Iterator listener = stack.getListeningPoints(); | ||
| 315 | + while (listener.hasNext()) { | ||
| 316 | + stack.deleteListeningPoint((ListeningPoint) listener.next()); | ||
| 317 | + } | ||
| 318 | + Iterator providers = stack.getSipProviders(); | ||
| 319 | + while (providers.hasNext()) { | ||
| 320 | + stack.deleteSipProvider((SipProvider) providers.next()); | ||
| 321 | + } | ||
| 322 | + VManageBootstrap.restart(); | ||
| 323 | + } catch (InterruptedException ignored) { | ||
| 324 | + } catch (ObjectInUseException e) { | ||
| 325 | + e.printStackTrace(); | ||
| 314 | } | 326 | } |
| 315 | - VManageBootstrap.restart(); | ||
| 316 | - } catch (InterruptedException ignored) { | ||
| 317 | - } catch (ObjectInUseException e) { | ||
| 318 | - e.printStackTrace(); | ||
| 319 | } | 327 | } |
| 320 | - } | ||
| 321 | - }); | ||
| 322 | - | ||
| 323 | - restartThread.setDaemon(false); | ||
| 324 | - restartThread.start(); | 328 | + }); |
| 329 | + | ||
| 330 | + restartThread.setDaemon(false); | ||
| 331 | + restartThread.start(); | ||
| 332 | + } else { | ||
| 333 | + // 远程启动指定设备 | ||
| 334 | + } | ||
| 335 | + } | ||
| 336 | + if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) { | ||
| 337 | + String cmdString = XmlUtil.getText(rootElement,"PTZCmd"); | ||
| 338 | + Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId); | ||
| 339 | + cmder.fronEndCmd(device, deviceId, cmdString); | ||
| 325 | } | 340 | } |
| 326 | } | 341 | } |
| 327 | } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | 342 | } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { |