Commit a60e1102c41b5fa89c5e2cbbef81f668b0495240

Authored by Lawrence
1 parent 035691ed

完善前端控制信令,实现GB28181 A.3前端设备控制协议

libs/jain-sip-ri-1.3.0-91.jar deleted 100644 → 0
No preview for this file type
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -65,6 +65,18 @@ public interface ISIPCommander {
65 65 public boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
66 66  
67 67 /**
  68 + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
  69 + *
  70 + * @param device 控制设备
  71 + * @param channelId 预览通道
  72 + * @param cmdCode 指令码
  73 + * @param parameter1 数据1
  74 + * @param parameter2 数据2
  75 + * @param combineCode2 组合码2
  76 + */
  77 + public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2);
  78 +
  79 + /**
68 80 * 请求预览视频流
69 81 *
70 82 * @param device 视频设备
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -163,6 +163,32 @@ public class SIPCommander implements ISIPCommander {
163 163 return builder.toString();
164 164 }
165 165  
  166 + /**
  167 + * 云台指令码计算
  168 + *
  169 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  170 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  171 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  172 + * @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
  173 + * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
  174 + */
  175 + public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) {
  176 + StringBuilder builder = new StringBuilder("A50F01");
  177 + String strTmp;
  178 + strTmp = String.format("%02X", cmdCode);
  179 + builder.append(strTmp, 0, 2);
  180 + strTmp = String.format("%02X", parameter1);
  181 + builder.append(strTmp, 0, 2);
  182 + strTmp = String.format("%02X", parameter2);
  183 + builder.append(strTmp, 0, 2);
  184 + strTmp = String.format("%X", combineCode2);
  185 + builder.append(strTmp, 0, 1).append("0");
  186 + //计算校验码
  187 + int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
  188 + strTmp = String.format("%02X", checkCode);
  189 + builder.append(strTmp, 0, 2);
  190 + return builder.toString();
  191 + }
166 192  
167 193 /**
168 194 * 云台控制,支持方向与缩放控制
... ... @@ -202,6 +228,41 @@ public class SIPCommander implements ISIPCommander {
202 228 }
203 229  
204 230 /**
  231 + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
  232 + *
  233 + * @param device 控制设备
  234 + * @param channelId 预览通道
  235 + * @param cmdCode 指令码
  236 + * @param parameter1 数据1
  237 + * @param parameter2 数据2
  238 + * @param combineCode2 组合码2
  239 + */
  240 + @Override
  241 + public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) {
  242 + try {
  243 + String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
  244 + System.out.println("控制字符串:" + cmdStr);
  245 + StringBuffer ptzXml = new StringBuffer(200);
  246 + ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
  247 + ptzXml.append("<Control>\r\n");
  248 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  249 + ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  250 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  251 + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
  252 + ptzXml.append("<Info>\r\n");
  253 + ptzXml.append("</Info>\r\n");
  254 + ptzXml.append("</Control>\r\n");
  255 +
  256 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
  257 +
  258 + transmitRequest(device, request);
  259 + return true;
  260 + } catch (SipException | ParseException | InvalidArgumentException e) {
  261 + e.printStackTrace();
  262 + }
  263 + return false;
  264 + }
  265 + /**
205 266 * 请求预览视频流
206 267 *
207 268 * @param device 视频设备
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
... ... @@ -138,7 +138,7 @@ public class DeviceController {
138 138 DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId);
139 139 if (deviceChannel == null) {
140 140 PageResult<DeviceChannel> deviceChannelPageResult = new PageResult<>();
141   - new ResponseEntity<>(deviceChannelPageResult,HttpStatus.OK);
  141 + return new ResponseEntity<>(deviceChannelPageResult,HttpStatus.OK);
142 142 }
143 143  
144 144 PageResult pageResult = storager.querySubChannels(deviceId, channelId, query, channelType, online, page, count);
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
... ... @@ -40,14 +40,35 @@ public class PtzController {
40 40 * @return
41 41 */
42 42 @PostMapping("/ptz/{deviceId}/{channelId}")
43   - public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed){
  43 + public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed){
44 44  
45 45 if (logger.isDebugEnabled()) {
46   - 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));
  46 + logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,cmdCode:%d ,horizonSpeed:%d ,verticalSpeed:%d ,zoomSpeed:%d",deviceId, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed));
47 47 }
48 48 Device device = storager.queryVideoDevice(deviceId);
49 49  
50   - cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
  50 + cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
  51 + return new ResponseEntity<String>("success",HttpStatus.OK);
  52 + }
  53 + // public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed){
  54 +
  55 + // if (logger.isDebugEnabled()) {
  56 + // 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));
  57 + // }
  58 + // Device device = storager.queryVideoDevice(deviceId);
  59 +
  60 + // cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
  61 + // return new ResponseEntity<String>("success",HttpStatus.OK);
  62 + // }
  63 + @PostMapping("/frontEndCommand/{deviceId}/{channelId}")
  64 + public ResponseEntity<String> frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
  65 +
  66 + if (logger.isDebugEnabled()) {
  67 + logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,cmdCode:%d parameter1:%d parameter2:%d",deviceId, channelId, cmdCode, parameter1, parameter2));
  68 + }
  69 + Device device = storager.queryVideoDevice(deviceId);
  70 +
  71 + cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
51 72 return new ResponseEntity<String>("success",HttpStatus.OK);
52 73 }
53 74 }
... ...
web_src/src/components/gb28181/devicePlayer.vue
... ... @@ -40,7 +40,7 @@
40 40  
41 41 <!-- <el-date-picker v-model="videoHistory.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="结束时间"-->
42 42 <!-- @change="recordList()"></el-date-picker>-->
43   - <el-table :data="videoHistory.searchHistoryResult" height="150" v-load="recordsLoading">
  43 + <el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading">
44 44 <el-table-column label="名称" prop="name"></el-table-column>
45 45 <el-table-column label="文件" prop="filePath"></el-table-column>
46 46 <el-table-column label="开始时间" prop="startTime" :formatter="timeFormatter"></el-table-column>
... ... @@ -55,32 +55,61 @@
55 55 </el-tab-pane>
56 56 <!--遥控界面-->
57 57 <el-tab-pane label="云台控制" name="control">
58   - <div style="display: flex; justify-content: center;">
  58 + <div style="display: flex; justify-content: left;">
59 59 <div class="control-wrapper">
60   - <div class="control-btn control-top" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)">
  60 + <div class="control-btn control-top" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
61 61 <i class="el-icon-caret-top"></i>
62 62 <div class="control-inner-btn control-inner"></div>
63 63 </div>
64   - <div class="control-btn control-left" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
  64 + <div class="control-btn control-left" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
65 65 <i class="el-icon-caret-left"></i>
66 66 <div class="control-inner-btn control-inner"></div>
67 67 </div>
68   - <div class="control-btn control-bottom" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
  68 + <div class="control-btn control-bottom" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)">
69 69 <i class="el-icon-caret-bottom"></i>
70 70 <div class="control-inner-btn control-inner"></div>
71 71 </div>
72   - <div class="control-btn control-right" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
  72 + <div class="control-btn control-right" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
73 73 <i class="el-icon-caret-right"></i>
74 74 <div class="control-inner-btn control-inner"></div>
75 75 </div>
76 76 <div class="control-round">
77 77 <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
78 78 </div>
79   - <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-in" style="font-size: 1.875rem;"></i></div>
80   - <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera(0, 0, 1)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div>
  79 + <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera(0, 0, 1)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-in" style="font-size: 1.875rem;"></i></div>
  80 + <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div>
  81 + </div>
  82 + <div class="control-panel">
  83 + <el-button-group>
  84 + <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium" type="info">预置位编号</el-tag>
  85 + <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number>
  86 + <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button>
  87 + <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button>
  88 + <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button>
  89 + <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium" type="info">巡航速度</el-tag>
  90 + <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
  91 + <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button>
  92 + <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium" type="info">停留时间</el-tag>
  93 + <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
  94 + <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button>
  95 + <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium" type="info">巡航组编号</el-tag>
  96 + <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number>
  97 + <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button>
  98 + <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button>
  99 + <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button>
  100 + <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button>
  101 + <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium" type="info">扫描速度</el-tag>
  102 + <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
  103 + <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button>
  104 + <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium" type="info">扫描组编号</el-tag>
  105 + <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number>
  106 + <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button>
  107 + <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button>
  108 + <el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描</el-button>
  109 + <el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger" icon="el-icon-switch-button" @click="ptzCamera(0, 0, 0)">停止</el-button>
  110 + </el-button-group>
81 111 </div>
82 112 </div>
83   -
84 113 </el-tab-pane>
85 114 </el-tabs>
86 115 </div>
... ... @@ -152,7 +181,12 @@ export default {
152 181 timeVal: 0,
153 182 timeMin: 0,
154 183 timeMax: 1440,
155   -
  184 + presetPos: 1,
  185 + cruisingSpeed: 100,
  186 + cruisingTime: 5,
  187 + cruisingGroup: 0,
  188 + scanSpeed: 100,
  189 + scanGroup: 0,
156 190 };
157 191 },
158 192 methods: {
... ... @@ -291,14 +325,41 @@ export default {
291 325 let that = this;
292 326 this.$axios({
293 327 method: 'post',
294   - url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown +
295   - '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'
  328 + // url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown +
  329 + // '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'
  330 + url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + (zoom * 16 + upDown * 4 + leftRight) + '&horizonSpeed=30&verticalSpeed=30&zoomSpeed=' + (2 * 16)
296 331 }).then(function (res) {});
297 332 },
298 333 //////////////////////播放器事件处理//////////////////////////
299 334 videoError: function (e) {
300 335 console.log("播放器错误:" + JSON.stringify(e));
301 336 },
  337 + presetPosition: function (cmdCode, presetPos) {
  338 + console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16));
  339 + let that = this;
  340 + this.$axios({
  341 + method: 'post',
  342 + url: '/api/frontEndCommand/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=0&parameter2=' + presetPos + '&combindCode2=0'
  343 + }).then(function (res) {});
  344 + },
  345 + setSpeedOrTime: function (cmdCode, groupNum, parameter) {
  346 + let that = this;
  347 + let parameter2 = parameter % 256;
  348 + let combindCode2 = Math.floor(parameter / 256) * 16;
  349 + console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16));
  350 + this.$axios({
  351 + method: 'post',
  352 + url: '/api/frontEndCommand/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter2 + '&combindCode2=' + combindCode2
  353 + }).then(function (res) {});
  354 + },
  355 + setCommand: function (cmdCode, groupNum, parameter) {
  356 + let that = this;
  357 + console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0');
  358 + this.$axios({
  359 + method: 'post',
  360 + url: '/api/frontEndCommand/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0'
  361 + }).then(function (res) {});
  362 + },
302 363 formatTooltip: function (val) {
303 364 var h = parseInt(val / 60);
304 365 var hStr = h < 10 ? ("0" + h) : h;
... ... @@ -356,11 +417,20 @@ export default {
356 417 height: 6.25rem;
357 418 max-width: 6.25rem;
358 419 max-height: 6.25rem;
359   - margin: 0 auto;
360 420 border-radius: 100%;
  421 + margin-top: 2.5rem;
  422 + margin-left: 0.5rem;
361 423 float: left;
362 424 }
363 425  
  426 +.control-panel {
  427 + position: relative;
  428 + top: 0;
  429 + left: 5rem;
  430 + height: 11rem;
  431 + max-height: 11rem;
  432 +}
  433 +
364 434 .control-btn {
365 435 display: flex;
366 436 justify-content: center;
... ... @@ -393,8 +463,8 @@ export default {
393 463  
394 464 .control-round-inner {
395 465 position: absolute;
396   - left: 15%;
397   - top: 15%;
  466 + left: 13%;
  467 + top: 13%;
398 468 display: flex;
399 469 justify-content: center;
400 470 align-items: center;
... ...