增加视频参数范围设置接口

This commit is contained in:
lin 2026-06-17 16:34:06 +08:00
parent 5a3b831717
commit 56b211cc6c
14 changed files with 135 additions and 121 deletions

View File

@ -9,6 +9,9 @@ import org.dom4j.Element;
@Schema(description = "视频参数范围") @Schema(description = "视频参数范围")
public class VideoParamOpt implements DeviceConfigAware { public class VideoParamOpt implements DeviceConfigAware {
@Schema(description = "设备ID")
private String deviceId;
@Schema(description = "下载倍速范围,各可选参数以 '/' 分隔") @Schema(description = "下载倍速范围,各可选参数以 '/' 分隔")
private String downloadSpeed; private String downloadSpeed;

View File

@ -48,6 +48,30 @@ public class DeviceConfig {
return deferredResult; return deferredResult;
} }
@GetMapping("/set/videoParamOpt")
@Operation(summary = "设置视频参数", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "videoParamOpt", description = "视频参数", required = true)
public DeferredResult<WVPResult<String>> setVideoParamOpt(VideoParamOpt videoParamOpt) {
if (log.isDebugEnabled()) {
log.debug("视频参数设置命令API调用");
}
Assert.notNull(videoParamOpt.getDeviceId(), "设备ID必须存在");
Device device = deviceService.getDeviceByDeviceId(videoParamOpt.getDeviceId());
Assert.notNull(device, "设备不存在");
DeferredResult<WVPResult<String>> deferredResult = new DeferredResult<>();
deviceService.deviceVideoParamConfig(device, videoParamOpt, (code, msg, data) -> {
deferredResult.setResult(new WVPResult<>(code, msg, data));
});
deferredResult.onTimeout(() -> {
log.warn("[设备配置] 超时, {}", device.getDeviceId());
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
});
return deferredResult;
}
@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 = "通道国标编号") @Parameter(name = "channelId", description = "通道国标编号")

View File

@ -171,6 +171,8 @@ public interface IDeviceService {
void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback); void deviceBasicConfig(Device device, BasicParam basicParam, ErrorCallback<String> callback);
void deviceVideoParamConfig(Device device, VideoParamOpt videoParamOpt, ErrorCallback<String> callback);
<T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback); <T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback);
void teleboot(Device device); void teleboot(Device device);

View File

@ -1160,6 +1160,25 @@ public class DeviceServiceImpl implements IDeviceService {
} }
} }
@Override
public void deviceVideoParamConfig(Device device, VideoParamOpt videoParamOpt, ErrorCallback<String> callback) {
if (!userSetting.getServerId().equals(device.getServerId())) {
WVPResult<String> result = redisRpcService.deviceVideoParamConfig(device.getServerId(), device, videoParamOpt);
if (result.getCode() == ErrorCode.SUCCESS.getCode()) {
callback.run(result.getCode(), result.getMsg(), result.getData());
}
return;
}
try {
sipCommander.deviceVideoParamConfigCmd(device, videoParamOpt, callback);
} catch (InvalidArgumentException | SipException | ParseException e) {
log.error("[命令发送失败] 设备配置: {}", e.getMessage());
callback.run(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage(), null);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
}
}
@Override @Override
public <T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback) { public <T extends DeviceConfigAware> void deviceConfigQuery(Device device, String channelId, Class<T> configClass, ErrorCallback<T> callback) {

View File

@ -195,6 +195,11 @@ public interface ISIPCommander {
*/ */
void deviceBasicConfigCmd(Device device, BasicParam basicParam, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException; void deviceBasicConfigCmd(Device device, BasicParam basicParam, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/**
* 设备配置命令VideoParamOpt
*/
void deviceVideoParamConfigCmd(Device device, VideoParamOpt videoParamOpt, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询设备状态 * 查询设备状态
* *

View File

@ -883,6 +883,38 @@ public class SIPCommander implements ISIPCommander {
}); });
} }
@Override
public void deviceVideoParamConfigCmd(Device device, VideoParamOpt videoParamOpt, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException {
int sn = (int) ((Math.random() * 9 + 1) * 100000);
String cmdType = "DeviceConfig";
StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
cmdXml.append("<Control>\r\n");
cmdXml.append("<CmdType>" + cmdType + "</CmdType>\r\n");
cmdXml.append("<SN>" + sn + "</SN>\r\n");
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
cmdXml.append("<VideoParamOpt>\r\n");
if (!ObjectUtils.isEmpty(videoParamOpt.getResolution())) {
cmdXml.append("<Resolution>" + videoParamOpt.getResolution() + "</Resolution>\r\n");
}
if (!ObjectUtils.isEmpty(videoParamOpt.getDownloadSpeed())) {
cmdXml.append("<DownloadSpeed>" + videoParamOpt.getDownloadSpeed() + "</DownloadSpeed>\r\n");
}
cmdXml.append("</VideoParamOpt>\r\n");
cmdXml.append("</Control>\r\n");
MessageEvent<String> messageEvent = MessageEvent.getInstance(cmdType, sn + "", device.getDeviceId(), 2000L, callback);
messageSubscribe.addSubscribe(messageEvent);
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
messageSubscribe.removeSubscribe(messageEvent.getKey());
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
});
}
/** /**
* 查询设备状态 * 查询设备状态
* *

View File

@ -55,6 +55,8 @@ public interface IRedisRpcService {
WVPResult<String> deviceBasicConfig(String serverId, Device device, BasicParam basicParam); WVPResult<String> deviceBasicConfig(String serverId, Device device, BasicParam basicParam);
WVPResult<String> deviceVideoParamConfig(String serverId, Device device, VideoParamOpt videoParamOpt);
WVPResult<Object> deviceConfigQuery(String serverId, Device device, String channelId, String configType); WVPResult<Object> deviceConfigQuery(String serverId, Device device, String channelId, String configType);
void teleboot(String serverId, Device device); void teleboot(String serverId, Device device);

View File

@ -116,6 +116,26 @@ public class RedisRpcDeviceController extends RpcController {
return null; return null;
} }
@RedisRpcMapping("deviceVideoParamConfig")
public RedisRpcResponse deviceVideoParamConfig(RedisRpcRequest request) {
VideoParamOpt videoParamOpt = JSONObject.parseObject(request.getParam().toString(), VideoParamOpt.class);
Device device = deviceService.getDeviceByDeviceId(videoParamOpt.getDeviceId());
RedisRpcResponse response = request.getResponse();
if (device == null || !userSetting.getServerId().equals(device.getServerId())) {
response.setStatusCode(ErrorCode.ERROR400.getCode());
response.setBody("param error");
return response;
}
deviceService.deviceVideoParamConfig(device, videoParamOpt, (code, msg, data) -> {
response.setStatusCode(code);
response.setBody(new WVPResult<>(code, msg, data));
sendResponse(response);
});
return null;
}
@RedisRpcMapping("deviceConfigQuery") @RedisRpcMapping("deviceConfigQuery")
public RedisRpcResponse deviceConfigQuery(RedisRpcRequest request) { public RedisRpcResponse deviceConfigQuery(RedisRpcRequest request) {

View File

@ -350,6 +350,14 @@ public class RedisRpcServiceImpl implements IRedisRpcService {
return JSON.parseObject(response.getBody().toString(), WVPResult.class); return JSON.parseObject(response.getBody().toString(), WVPResult.class);
} }
@Override
public WVPResult<String> deviceVideoParamConfig(String serverId, Device device, VideoParamOpt videoParamOpt) {
RedisRpcRequest request = buildRequest("device/deviceVideoParamConfig", JSONObject.toJSONString(videoParamOpt));
request.setToId(serverId);
RedisRpcResponse response = redisRpcConfig.request(request, 50, TimeUnit.MILLISECONDS);
return JSON.parseObject(response.getBody().toString(), WVPResult.class);
}
@Override @Override
public WVPResult<Object> deviceConfigQuery(String serverId, Device device, String channelId, String configType) { public WVPResult<Object> deviceConfigQuery(String serverId, Device device, String channelId, String configType) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();

View File

@ -129,6 +129,14 @@ export function setBasicParam(params) {
}) })
} }
export function setVideoParamOpt(params) {
return request({
method: 'get',
url: '/api/device/config/set/videoParamOpt',
params
})
}
export function queryChannelOne(params) { export function queryChannelOne(params) {
const { deviceId, channelDeviceId } = params const { deviceId, channelDeviceId } = params
return request({ return request({

View File

@ -16,6 +16,7 @@ import {
resetGuard, resetGuard,
setBasicParam, setBasicParam,
setGuard, setGuard,
setVideoParamOpt,
subscribeCatalog, subscribeForAlarm, subscribeCatalog, subscribeForAlarm,
subscribeMobilePosition, subscribeMobilePosition,
sync, sync,
@ -145,6 +146,16 @@ const actions = {
}) })
}) })
}, },
setVideoParamOpt({ commit }, params) {
return new Promise((resolve, reject) => {
setVideoParamOpt(params).then(response => {
const { data } = response
resolve(data)
}).catch(error => {
reject(error)
})
})
},
queryChannelOne({ commit }, params) { queryChannelOne({ commit }, params) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
queryChannelOne(params).then(response => { queryChannelOne(params).then(response => {

View File

@ -8,26 +8,10 @@
<i class="iconfont icon-wxbzhuye" style="margin-right: 10px" /> <i class="iconfont icon-wxbzhuye" style="margin-right: 10px" />
<span>基础属性</span> <span>基础属性</span>
</el-menu-item> </el-menu-item>
<el-menu-item index="image">
<i class="iconfont icon-shishiyulan" style="margin-right: 10px" />
<span>图像属性</span>
</el-menu-item>
<el-menu-item index="encode">
<i class="iconfont icon-shipin" style="margin-right: 10px" />
<span>编码设置</span>
</el-menu-item>
<el-menu-item index="alarm">
<i class="iconfont icon-baojing" style="margin-right: 10px" />
<span>报警配置</span>
</el-menu-item>
</el-menu> </el-menu>
</div> </div>
<div class="config-content"> <div class="config-content">
<basicPropertyConfig v-if="activeTab === 'base'" :device-id="deviceId" :channel-device-id="channelDeviceId" /> <basicPropertyConfig v-if="activeTab === 'base'" :device-id="deviceId" :channel-device-id="channelDeviceId" />
<imagePropertyConfig v-if="activeTab === 'image'" :device-id="deviceId" :channel-device-id="channelDeviceId" />
<div v-if="activeTab === 'osd'" class="placeholder-tab">OSD配置开发中</div>
<div v-if="activeTab === 'encode'" class="placeholder-tab">编码设置开发中</div>
<div v-if="activeTab === 'alarm'" class="placeholder-tab">报警配置开发中</div>
</div> </div>
</div> </div>
</div> </div>
@ -35,11 +19,10 @@
<script> <script>
import basicPropertyConfig from './basicPropertyConfig.vue' import basicPropertyConfig from './basicPropertyConfig.vue'
import imagePropertyConfig from './imagePropertyConfig.vue'
export default { export default {
name: 'CameraConfigPage', name: 'CameraConfigPage',
components: { basicPropertyConfig, imagePropertyConfig }, components: { basicPropertyConfig },
props: { props: {
deviceId: { type: String, default: null }, deviceId: { type: String, default: null },
channelDeviceId: { type: String, default: null } channelDeviceId: { type: String, default: null }

View File

@ -1,84 +0,0 @@
<template>
<div id="dhImagePropertyPage">
<div class="image-property-body">
<div class="player-section">
<playerPtzPanel :device-id="deviceId" :channel-device-id="channelDeviceId" />
</div>
<div class="config-section">
<el-tabs v-model="activeTab" tab-position="left" class="config-tabs">
<el-tab-pane label="OSD配置" name="osd">
<div class="placeholder-tab">OSD配置开发中</div>
</el-tab-pane>
<el-tab-pane label="视角" name="control">
<div class="placeholder-tab">视角开发中</div>
</el-tab-pane>
<el-tab-pane label="画面遮挡" name="pictureMask">
<div class="placeholder-tab">画面遮挡开发中</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</template>
<script>
import playerPtzPanel from '../common/playerPtzPanel.vue'
export default {
name: 'ImagePropertyPage',
components: { playerPtzPanel },
props: {
deviceId: { type: String, default: null },
channelDeviceId: { type: String, default: null }
},
data() {
return {
activeTab: 'osd'
}
}
}
</script>
<style scoped>
#dhImagePropertyPage {
height: 100%;
display: flex;
flex-direction: column;
}
.image-property-body {
display: flex;
gap: 16px;
min-height: 30vw;
flex: 1;
padding-top: 16px;
}
.player-section {
width: 520px;
flex: none;
display: flex;
flex-direction: column;
}
.config-section {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
.config-tabs {
flex: 1;
min-height: 0;
}
.placeholder-tab {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
color: #909399;
font-size: 16px;
}
</style>

View File

@ -168,9 +168,6 @@
<el-dropdown-item command="resetGuard" :disabled="!scope.row.onLine"> <el-dropdown-item command="resetGuard" :disabled="!scope.row.onLine">
撤防 撤防
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item command="syncBasicParam" :disabled="!scope.row.onLine">
基础配置同步
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
@ -391,8 +388,6 @@ export default {
this.resetGuard(itemData) this.resetGuard(itemData)
} else if (command === 'delete') { } else if (command === 'delete') {
this.deleteDevice(itemData) this.deleteDevice(itemData)
} else if (command === 'syncBasicParam') {
this.syncBasicParam(itemData)
} }
}, },
setGuard: function(itemData) { setGuard: function(itemData) {
@ -472,20 +467,6 @@ export default {
}) })
}) })
}, },
syncBasicParam: function(data) {
this.$store.dispatch('device/queryBasicParam')
.then((data) => {
this.$message.success({
showClose: true,
message: `配置已同步,当前心跳间隔: ${data.BasicParam.HeartBeatInterval} 心跳间隔:${res.data.data.BasicParam.HeartBeatCount}`
})
}).catch((error) => {
this.$message.error({
showClose: true,
message: error.message
})
})
},
getKeepaliveTimeStatistics: function(deviceId) { getKeepaliveTimeStatistics: function(deviceId) {
this.$refs.timeStatistics.openDialog('心跳时间统计', 'device/getKeepaliveTimeStatistics', deviceId, 60) this.$refs.timeStatistics.openDialog('心跳时间统计', 'device/getKeepaliveTimeStatistics', deviceId, 60)
}, },