Commit 2a273acd09cc5e9656a5cf2673c98d7b5e8453df

Authored by lawrencehj
1 parent 3609d361

增加上级平台云台控制功能

README.md
... ... @@ -60,21 +60,24 @@ https://gitee.com/18010473990/wvp-GB28181.git
60 60 15. 支持订阅与通知方法
61 61 - [X] 移动位置订阅
62 62 - [X] 移动位置通知处理
63   - - [ ] 报警事件订阅
  63 + - [X] 报警事件订阅
64 64 - [X] 报警事件通知处理
65 65 - [ ] 设备目录订阅
66 66 - [X] 设备目录通知处理
67 67 16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储
68 68  
69 69 # 2.0 支持特性
70   -- [ ] 国标通道向上级联
  70 +- [X] 国标通道向上级联
71 71 - [X] WEB添加上级平台
72 72 - [X] 注册
73 73 - [X] 心跳保活
74 74 - [X] 通道选择
75 75 - [X] 通道推送
76   - - [ ] 点播
77   - - [ ] 云台控制
  76 + - [X] 点播
  77 + - [X] 云台控制
  78 + - [X] 平台状态查询
  79 + - [X] 平台信息查询
  80 + - [X] 平台远程启动
78 81 - [ ] 添加RTSP视频
79 82 - [ ] 添加ONVIF探测局域网内的设备
80 83 - [ ] 添加RTMP视频
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -78,6 +78,14 @@ public interface ISIPCommander {
78 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 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 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 316 * @param device 视频设备
287 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 4 import java.text.ParseException;
5 5 import java.util.*;
6 6  
  7 +import javax.sip.address.SipURI;
  8 +
7 9 import javax.sip.header.FromHeader;
8 10 import javax.sip.header.HeaderAddress;
  11 +import javax.sip.header.ToHeader;
9 12 import javax.sip.InvalidArgumentException;
10 13 import javax.sip.ListeningPoint;
11 14 import javax.sip.ObjectInUseException;
... ... @@ -290,38 +293,50 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
290 293 deferredResultHolder.invokeResult(msg);
291 294 } else {
292 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 342 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
... ...