Commit 2a273acd09cc5e9656a5cf2673c98d7b5e8453df

Authored by lawrencehj
1 parent 3609d361

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

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) {