优化播放页面的预置位控制

pull/1694/head
648540858 2024-11-08 17:40:05 +08:00
parent e27d93e22d
commit 5c2b4f386b
11 changed files with 177 additions and 47 deletions

View File

@ -0,0 +1,12 @@
package com.genersoft.iot.vmp.gb28181.bean;
import lombok.Data;
@Data
public class Preset {
private String presetId;
private String presetName;
}

View File

@ -1,28 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* @author chenjialing
*/
public class PresetQuerySipReq {
private String presetId;
private String presetName;
public String getPresetId() {
return presetId;
}
public void setPresetId(String presetId) {
this.presetId = presetId;
}
public String getPresetName() {
return presetName;
}
public void setPresetName(String presetName) {
this.presetName = presetName;
}
}

View File

@ -119,7 +119,7 @@ public class PtzController {
@Parameter(name = "parameter1", description = "数据一", required = true) @Parameter(name = "parameter1", description = "数据一", required = true)
@Parameter(name = "parameter2", description = "数据二", required = true) @Parameter(name = "parameter2", description = "数据二", required = true)
@Parameter(name = "combindCode2", description = "组合码二", required = true) @Parameter(name = "combindCode2", description = "组合码二", required = true)
@PostMapping("/front_end_command/{deviceId}/{channelId}") @PostMapping("/fi/{deviceId}/{channelId}")
public void frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){ public void frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -136,11 +136,11 @@ public class PtzController {
} }
@Operation(summary = "预置位查询", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "查询预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@GetMapping("/preset/query/{deviceId}/{channelId}") @GetMapping("/preset/query/{deviceId}/{channelId}")
public DeferredResult<String> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) { public DeferredResult<String> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("设备预置位查询API调用"); log.debug("设备预置位查询API调用");
} }
@ -175,4 +175,40 @@ public class PtzController {
} }
return result; return result;
} }
@Operation(summary = "新增预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "presetId", description = "预置位编号", required = true)
@GetMapping("/preset/add/{deviceId}/{channelId}")
public void addPreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
if (presetId == null || presetId < 1 || presetId > 255) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
}
frontEndCommand(deviceId, channelId, 0x81, 1, presetId, 0);
}
@Operation(summary = "调用预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "presetId", description = "预置位编号", required = true)
@GetMapping("/preset/call/{deviceId}/{channelId}")
public void callPreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
if (presetId == null || presetId < 1 || presetId > 255) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
}
frontEndCommand(deviceId, channelId, 0x82, 1, presetId, 0);
}
@Operation(summary = "删除预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "presetId", description = "预置位编号", required = true)
@GetMapping("/preset/delete/{deviceId}/{channelId}")
public void deletePreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
if (presetId == null || presetId < 1 || presetId > 255) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
}
frontEndCommand(deviceId, channelId, 0x83, 1, presetId, 0);
}
} }

View File

@ -0,0 +1,21 @@
package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Preset;
import java.util.List;
public interface IPTZService {
List<Preset> queryPresetList(String deviceId, String channelDeviceId);
void addPreset(Preset preset);
void deletePreset(Integer qq);
void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed);
void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2);
}

View File

@ -19,7 +19,6 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.service.IMediaServerService;
@ -34,7 +33,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
@ -51,9 +49,6 @@ import java.util.concurrent.TimeUnit;
@DS("master") @DS("master")
public class DeviceServiceImpl implements IDeviceService { public class DeviceServiceImpl implements IDeviceService {
@Autowired
private SIPCommander cmder;
@Autowired @Autowired
private DynamicTask dynamicTask; private DynamicTask dynamicTask;

View File

@ -0,0 +1,62 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Preset;
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.Collections;
import java.util.List;
@Slf4j
@Service
public class PTZServiceImpl implements IPTZService {
@Autowired
private SIPCommander cmder;
@Override
public void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed) {
try {
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 云台控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2) {
try {
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 前端控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@Override
public List<Preset> queryPresetList(String deviceId, String channelDeviceId) {
return Collections.emptyList();
}
@Override
public void addPreset(Preset preset) {
}
@Override
public void deletePreset(Integer qq) {
}
}

View File

@ -488,8 +488,7 @@ public class PlayServiceImpl implements IPlayService {
log.info("[语音对讲]开始 获取发流端口失败 deviceId: {}, channelId: {},", device.getDeviceId(), channel.getDeviceId()); log.info("[语音对讲]开始 获取发流端口失败 deviceId: {}, channelId: {},", device.getDeviceId(), channel.getDeviceId());
return; return;
} }
sendRtpInfo.setOnlyAudio(true); sendRtpInfo.setOnlyAudio(true);
sendRtpInfo.setPt(8); sendRtpInfo.setPt(8);
sendRtpInfo.setStatus(1); sendRtpInfo.setStatus(1);

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform; import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq; import com.genersoft.iot.vmp.gb28181.bean.Preset;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@ -79,11 +79,11 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
return; return;
} }
int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num")); int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>(); List<Preset> presetQuerySipReqList = new ArrayList<>();
if (sumNum > 0) { if (sumNum > 0) {
for (Iterator<Element> presetIterator = presetListNumElement.elementIterator(); presetIterator.hasNext(); ) { for (Iterator<Element> presetIterator = presetListNumElement.elementIterator(); presetIterator.hasNext(); ) {
Element itemListElement = presetIterator.next(); Element itemListElement = presetIterator.next();
PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq(); Preset presetQuerySipReq = new Preset();
for (Iterator<Element> itemListIterator = itemListElement.elementIterator(); itemListIterator.hasNext(); ) { for (Iterator<Element> itemListIterator = itemListElement.elementIterator(); itemListIterator.hasNext(); ) {
// 遍历item // 遍历item
Element itemOne = itemListIterator.next(); Element itemOne = itemListIterator.next();

View File

@ -299,7 +299,7 @@ public class ZLMHttpHookListener {
@ResponseBody @ResponseBody
@PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8") @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) { public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) {
log.info("[ZLM HOOK] 录像完成事件{}->{}", param.getMediaServerId(), param.getFile_path()); log.info("[ZLM HOOK] 录像完成时长: {}, {}->{}",param.getTime_len(), param.getMediaServerId(), param.getFile_path());
try { try {
MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());

View File

@ -4,7 +4,7 @@ import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq; import com.genersoft.iot.vmp.gb28181.bean.Preset;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService; import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@ -215,13 +215,13 @@ public class ApiDeviceController {
} }
deferredResultEx.setFilter(filterResult->{ deferredResultEx.setFilter(filterResult->{
List<PresetQuerySipReq> presetQuerySipReqList = (List<PresetQuerySipReq>)filterResult; List<Preset> presetQuerySipReqList = (List<Preset>)filterResult;
HashMap<String, Object> resultMap = new HashMap<>(); HashMap<String, Object> resultMap = new HashMap<>();
resultMap.put("DeviceID", code); resultMap.put("DeviceID", code);
resultMap.put("Result", "OK"); resultMap.put("Result", "OK");
resultMap.put("SumNum", presetQuerySipReqList.size()); resultMap.put("SumNum", presetQuerySipReqList.size());
ArrayList<Map<String, Object>> presetItemList = new ArrayList<>(presetQuerySipReqList.size()); ArrayList<Map<String, Object>> presetItemList = new ArrayList<>(presetQuerySipReqList.size());
for (PresetQuerySipReq presetQuerySipReq : presetQuerySipReqList) { for (Preset presetQuerySipReq : presetQuerySipReqList) {
Map<String, Object> item = new HashMap<>(); Map<String, Object> item = new HashMap<>();
item.put("PresetID", presetQuerySipReq.getPresetId()); item.put("PresetID", presetQuerySipReq.getPresetId());
item.put("PresetName", presetQuerySipReq.getPresetName()); item.put("PresetName", presetQuerySipReq.getPresetName());

View File

@ -26,6 +26,7 @@
</div> </div>
<div id="shared" style="text-align: right; margin-top: 1rem;"> <div id="shared" style="text-align: right; margin-top: 1rem;">
<el-tabs v-model="tabActiveName" @tab-click="tabHandleClick"> <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick">
<el-tab-pane label="实时视频" name="media"> <el-tab-pane label="实时视频" name="media">
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
@ -154,7 +155,7 @@
<!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
<!--遥控界面--> <!--遥控界面-->
<el-tab-pane label="云台控制" name="control" v-if="showPtz"> <el-tab-pane label="云台控制" name="control" v-if="showPtz">
<div style="display: flex; justify-content: left;"> <div style="display: grid; grid-template-columns: 200px auto; height: 180px; overflow: auto">
<div class="control-wrapper"> <div class="control-wrapper">
<div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')"> <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
<i class="el-icon-caret-top"></i> <i class="el-icon-caret-top"></i>
@ -180,11 +181,39 @@
style="font-size: 1.875rem;"></i></div> style="font-size: 1.875rem;"></i></div>
<div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;"
@mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i
class="el-icon-zoom-out control-zoom-btn"></i></div> class="el-icon-zoom-out control-zoom-btn"></i></div>
<div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;"> <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">
<el-slider v-model="controSpeed" :max="255"></el-slider> <el-slider v-model="controSpeed" :max="255"></el-slider>
</div> </div>
</div> </div>
<div style="text-align: left" >
<el-select
v-model="ptzMethod"
style="width: 100%"
placeholder="请选择云台功能"
>
<el-option label="预置点" value="preset"></el-option>
<el-option label="巡航组" value="cruising"></el-option>
<el-option label="线性扫描" value="scan"></el-option>
<el-option label="巡迹" value="cruise"></el-option>
</el-select>
<ptzPreset :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'preset'" style="margin-top: 1rem"></ptzPreset>
<div v-if="ptzMethod === 'cruising'">
111
</div>
<div v-if="ptzMethod === 'scan'">
111
</div>
<div v-if="ptzMethod === 'cruise'">
111
</div>
</div>
</div>
<div style="display: flex; justify-content: left;">
<div class="control-panel"> <div class="control-panel">
<el-button-group> <el-button-group>
@ -327,11 +356,13 @@ import rtcPlayer from '../dialog/rtcPlayer.vue'
import LivePlayer from '@liveqing/liveplayer' import LivePlayer from '@liveqing/liveplayer'
import crypto from 'crypto' import crypto from 'crypto'
import jessibucaPlayer from '../common/jessibuca.vue' import jessibucaPlayer from '../common/jessibuca.vue'
import PtzPreset from "../common/ptzPreset.vue";
export default { export default {
name: 'devicePlayer', name: 'devicePlayer',
props: {}, props: {},
components: { components: {
PtzPreset,
LivePlayer, jessibucaPlayer, rtcPlayer, LivePlayer, jessibucaPlayer, rtcPlayer,
}, },
computed: { computed: {
@ -363,6 +394,8 @@ export default {
}, },
showVideoDialog: false, showVideoDialog: false,
streamId: '', streamId: '',
ptzMethod: 'preset',
ptzPresetId: '',
app: '', app: '',
mediaServerId: '', mediaServerId: '',
convertKey: '', convertKey: '',