) response.getData();
- return R.ok(result);
- }
- return R.error(response.getMsg(), null);
- } catch (Exception e) {
- log.error("WVP获取云端录像下载地址失败:{}", e.getMessage(), e);
- return R.error("获取下载地址失败:" + e.getMessage(), null);
- }
- }
-
- @Override
- @Cacheable(
- cacheNames = "getVideoPlatformInstance",
- key = "#p0",
- unless = "#result == null")
- public VideoPlatformInstance getVideoPlatformInstance(String instanceKey) {
- if (StrUtil.isBlank(instanceKey)) {
- log.warn("wvp query instanceKey is blank");
- return null;
- }
- VideoPlatformInstance instance = new VideoPlatformInstance();
- instance.setInstanceKey(instanceKey);
- instance = videoPlatformInstanceMapper.selectOne(instance);
- return instance;
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpAutoConfiguration.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpAutoConfiguration.java
deleted file mode 100644
index f1c6941..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpAutoConfiguration.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: 本文件由 gitee.com/NexIoT 开发并拥有版权,未经授权严禁擅自商用、复制或传播。
- * @Author: gitee.com/NexIoT
- * @Email: wo8335224@gmail.com
- * @Wechat: outlookFil
- *
- *
- */
-
-package cn.wvp.protocol.config;
-
-import cn.universal.core.protocol.ProtocolModuleRuntimeRegistry;
-import jakarta.annotation.PostConstruct;
-import jakarta.annotation.PreDestroy;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * WVP 协议模块自动配置类
- *
- * 当 wvp.protocol.enabled=true 时,自动扫描包并创建所有WVP相关的Bean
- *
- *
通过 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 实现 Spring Boot 自动配置
- *
- * @version 2.0
- * @Author gitee.com/NexIoT
- * @since 2025/1/8
- */
-@Configuration
-@ConditionalOnProperty(name = "wvp.protocol.enabled", havingValue = "true", matchIfMissing = false)
-@ComponentScan(basePackages = "cn.wvp.protocol")
-@EnableConfigurationProperties(WvpProperties.class)
-@Slf4j
-public class WvpAutoConfiguration {
-
- @Autowired(required = false)
- private WvpModuleInfo moduleInfo;
-
- public WvpAutoConfiguration() {
- log.info("[WVP协议] WVP协议模块自动配置已启用");
- }
-
- @PostConstruct
- public void registerProtocol() {
- if (moduleInfo != null) {
- ProtocolModuleRuntimeRegistry.registerProtocol(moduleInfo);
- log.info("[WVP自动配置] 协议模块已注册到运行时注册表");
- }
- }
-
- @PreDestroy
- public void unregisterProtocol() {
- if (moduleInfo != null) {
- ProtocolModuleRuntimeRegistry.unregisterProtocol(moduleInfo.getCode());
- log.info("[WVP自动配置] 协议模块已从运行时注册表注销");
- }
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpModuleInfo.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpModuleInfo.java
deleted file mode 100644
index 2e3df32..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpModuleInfo.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: 本文件由 gitee.com/NexIoT 开发并拥有版权,未经授权严禁擅自商用、复制或传播。
- * @Author: gitee.com/NexIoT
- * @Email: wo8335224@gmail.com
- * @Wechat: outlookFil
- *
- *
- */
-
-package cn.wvp.protocol.config;
-
-import cn.universal.core.protocol.ProtocolModuleInfo;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP协议模块信息
- *
- * @version 2.0
- * @Author gitee.com/NexIoT
- * @since 2025/1/8
- */
-@Component
-public class WvpModuleInfo implements ProtocolModuleInfo {
-
- @Override
- public String getCode() {
- return "wvp";
- }
-
- @Override
- public String getName() {
- return "WVP国标视频平台";
- }
-
- @Override
- public String getVersion() {
- return "2.0";
- }
-
- @Override
- public String getDescription() {
- return "WVP(Web Video Platform)国标视频平台协议适配器";
- }
-
- @Override
- public ProtocolCategory getCategory() {
- return ProtocolCategory.PLATFORM;
- }
-
- @Override
- public boolean isManualCreatable() {
- return false;
- }
-
- @Override
- public String getNotCreatableReason() {
- return "视频平台产品采用懒创建策略,请在视频中心中勾选设备时自动创建";
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpProperties.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpProperties.java
deleted file mode 100644
index 9828fab..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/config/WvpProperties.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: 本文件由 gitee.com/NexIoT 开发并拥有版权,未经授权严禁擅自商用、复制或传播。
- * @Author: gitee.com/NexIoT
- * @Email: wo8335224@gmail.com
- * @Wechat: outlookFil
- *
- *
- */
-
-package cn.wvp.protocol.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * WVP 协议配置属性
- *
- * @version 2.0
- * @Author gitee.com/NexIoT
- * @since 2025/1/8
- */
-@ConfigurationProperties(prefix = "wvp.protocol")
-@Data
-public class WvpProperties {
-
- /** 是否启用WVP协议模块 */
- private boolean enabled = true;
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/constant/WvpApiConstants.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/constant/WvpApiConstants.java
deleted file mode 100644
index 1e7b57b..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/constant/WvpApiConstants.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- */
-package cn.wvp.protocol.constant;
-
-/**
- * WVP平台API路径常量
- * 基于wvp-GB28181-pro标准接口
- */
-public interface WvpApiConstants {
-
- /** 设备查询接口 */
- String API_DEVICE_QUERY = "/api/device/query/devices";
-
- /** 通道查询接口 */
- String API_DEVICE_CHANNELS = "/api/device/query/devices/%s/channels";
-
- /** 云台控制接口 (方向+缩放) */
- String API_PTZ_CONTROL = "/api/front-end/ptz/%s/%s";
-
- /** 光圈控制接口 */
- String API_IRIS_CONTROL = "/api/front-end/fi/iris/%s/%s";
-
- /** 聚焦控制接口 */
- String API_FOCUS_CONTROL = "/api/front-end/fi/focus/%s/%s";
-
- /** 预置位查询接口 */
- String API_PRESET_QUERY = "/api/front-end/preset/query/%s/%s";
-
- /** 抓拍接口 */
- String API_SNAPSHOT = "/api/play/snap";
-
- // ==================== 国标录像相关接口 ====================
-
- /** 国标录像查询接口 */
- String API_GB_RECORD_QUERY = "/api/gb_record/query/%s/%s";
-
- /** 国标录像下载开始 */
- String API_GB_RECORD_DOWNLOAD_START = "/api/gb_record/download/start/%s/%s";
-
- /** 国标录像下载停止 */
- String API_GB_RECORD_DOWNLOAD_STOP = "/api/gb_record/download/stop/%s/%s/%s";
-
- /** 国标录像下载进度 */
- String API_GB_RECORD_DOWNLOAD_PROGRESS = "/api/gb_record/download/progress/%s/%s/%s";
-
- // ==================== 云端录像相关接口 ====================
-
- /** 云端录像日期列表 */
- String API_CLOUD_RECORD_DATE_LIST = "/api/cloud/record/date/list";
-
- /** 云端录像列表查询 */
- String API_CLOUD_RECORD_LIST = "/api/cloud/record/list";
-
- /** 加载云端录像文件 */
- String API_CLOUD_RECORD_LOAD = "/api/cloud/record/loadRecord";
-
- /** 云端录像定位 */
- String API_CLOUD_RECORD_SEEK = "/api/cloud/record/seek";
-
- /** 云端录像倍速 */
- String API_CLOUD_RECORD_SPEED = "/api/cloud/record/speed";
-
- /** 云端录像删除 */
- String API_CLOUD_RECORD_DELETE = "/api/cloud/record/delete";
-
- /** 云端录像收藏添加 */
- String API_CLOUD_RECORD_COLLECT_ADD = "/api/cloud/record/collect/add";
-
- /** 云端录像收藏删除 */
- String API_CLOUD_RECORD_COLLECT_DELETE = "/api/cloud/record/collect/delete";
-
- /** 直播开始接口 */
- String API_PLAY_START = "/api/play/start/%s/%s";
-
- /** 直播停止接口 */
- String API_PLAY_STOP = "/api/play/stop/%s/%s";
-
- /** 回放开始接口 */
- String API_PLAYBACK_START = "/api/playback/start/%s/%s";
-
- /** 回放停止接口 */
- String API_PLAYBACK_STOP = "/api/playback/stop/%s/%s";
-
- /** 云端录像下载地址获取 */
- String API_CLOUD_RECORD_PLAY_PATH = "/api/cloud/record/play/path";
-
- /** Token请求头名称 */
- String HEADER_ACCESS_TOKEN = "Access-Token";
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/converter/WvpDownRequestConverter.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/converter/WvpDownRequestConverter.java
deleted file mode 100644
index 7a8db2f..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/converter/WvpDownRequestConverter.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: 本文件由 gitee.com/NexIoT 开发并拥有版权,未经授权严禁擅自商用、复制或传播。
- * @Author: gitee.com/NexIoT
- * @Email: wo8335224@gmail.com
- * @Wechat: outlookFil
- *
- *
- */
-
-package cn.wvp.protocol.converter;
-
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONUtil;
-import cn.universal.common.constant.IoTConstant.DownCmd;
-import cn.universal.core.downlink.DownlinkContext;
-import cn.universal.core.downlink.converter.DownRequestConverter;
-import cn.universal.core.message.UnifiedDownlinkCommand;
-import cn.universal.dm.device.service.AbstratIoTService;
-import cn.universal.dm.video.VideoPlatformInstanceAdapter;
-import cn.universal.persistence.dto.IoTDeviceDTO;
-import cn.universal.persistence.entity.IoTProduct;
-import cn.universal.persistence.entity.VideoPlatformInstance;
-import cn.universal.persistence.query.IoTDeviceQuery;
-import cn.wvp.protocol.config.WvpModuleInfo;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import jakarta.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP协议转换器 将UnifiedDownlinkCommand转换为WvpDownRequest
- *
- * @version 1.0
- * @since 2025/11/09
- */
-@Slf4j
-@Component("wvpConverter")
-public class WvpDownRequestConverter extends AbstratIoTService
- implements DownRequestConverter {
-
- @Autowired
- @Qualifier("wvpPlatformAdapter")
- private VideoPlatformInstanceAdapter videoPlatformInstanceAdapter;
-
- @Resource private WvpModuleInfo wvpModuleInfo;
-
- @Override
- public WvpDownRequest convert(UnifiedDownlinkCommand command, DownlinkContext> context) {
- try {
- // 1. 加载产品信息
- IoTProduct ioTProduct = getProduct(command.getProductKey());
- if (ioTProduct == null) {
- throw new IllegalArgumentException("产品不存在: " + command.getProductKey());
- }
-
- // 2. 创建WVP下行请求
- WvpDownRequest request = new WvpDownRequest();
- BeanUtil.copyProperties(command, request, "extensions", "metadata");
-
- // 3. 设置产品信息
- request.setIoTProduct(ioTProduct);
-
- // 4. 加载设备信息(对于DEV_ADD命令,设备可能不存在)
- IoTDeviceDTO ioTDeviceDTO = null;
- if (command.getCmd() != DownCmd.DEV_ADD && command.getCmd() != DownCmd.DEV_ADDS) {
- ioTDeviceDTO =
- getIoTDeviceDTO(
- IoTDeviceQuery.builder()
- .productKey(command.getProductKey())
- .deviceId(command.getDeviceId())
- .iotId(command.getIotId())
- .build());
-
- if (ioTDeviceDTO == null) {
- throw new IllegalArgumentException(
- "设备不存在: productKey="
- + command.getProductKey()
- + ", deviceId="
- + command.getDeviceId());
- }
- }
- request.setIoTDeviceDTO(ioTDeviceDTO);
-
- VideoPlatformInstance videoPlatformInstance =
- videoPlatformInstanceAdapter.getVideoPlatformInstance(command.getProductKey());
- if (videoPlatformInstance == null) {
- throw new IllegalArgumentException("视频实例不存在: " + command.getProductKey());
- }
- buildEndpointAuth(request, videoPlatformInstance);
- // 5. 处理扩展字段
- if (command.getExtensions() != null && !command.getExtensions().isEmpty()) {
- Map wvpRequestData = request.getWvpRequestData();
- wvpRequestData.putAll(command.getExtensions());
- request.setWvpRequestData(wvpRequestData);
- }
-
- // 6. 设置消息ID
- if (StrUtil.isBlank(request.getMsgId())) {
- request.setMsgId(generateMsgId());
- }
- if (command.getFunction() != null && !command.getFunction().isEmpty()) {
- request.setFunction(command.getFunction());
- if (command.getFunction().containsKey("data")) {
- request.setData(JSONUtil.parseObj(command.getFunction().get("data")));
- }
- }
- log.debug(
- "[WVP转换器] 转换完成: productKey={}, deviceId={}, cmd={}",
- request.getProductKey(),
- request.getDeviceId(),
- request.getCmd() != null ? request.getCmd().getValue() : null);
-
- return request;
-
- } catch (IllegalArgumentException e) {
- log.error("[WVP转换器] 参数验证失败: {}", e.getMessage());
- throw e;
- } catch (Exception e) {
- log.error("[WVP转换器] 转换失败", e);
- throw new IllegalStateException("WVP请求转换失败: " + e.getMessage(), e);
- }
- }
-
- /** 生成消息ID */
- private String generateMsgId() {
- return String.valueOf(System.currentTimeMillis());
- }
-
- @Override
- public String supportedProtocol() {
- return wvpModuleInfo.getCode();
- }
-
- @Override
- public int getPriority() {
- return 10;
- }
-
- @Override
- public boolean supports(UnifiedDownlinkCommand command) {
- return command.getCmd() != null;
- }
-
- @Override
- public void preConvert(UnifiedDownlinkCommand command, DownlinkContext> context) {
- if (StrUtil.isBlank(command.getProductKey())) {
- throw new IllegalArgumentException("productKey不能为空");
- }
-
- log.debug(
- "[WVP转换器] 开始转换: productKey={}, deviceId={}, cmd={}",
- command.getProductKey(),
- command.getDeviceId(),
- command.getCmd());
- }
-
- @Override
- public void postConvert(
- UnifiedDownlinkCommand command, WvpDownRequest request, DownlinkContext> context) {
- context.setAttribute("convertTime", System.currentTimeMillis());
- context.setAttribute("protocolType", "WVP");
-
- if (request.getIoTDeviceDTO() != null) {
- context.setAttribute("deviceName", request.getIoTDeviceDTO().getDeviceName());
- context.setAttribute("deviceStatus", request.getIoTDeviceDTO().getState());
- }
-
- log.debug("[WVP转换器] 转换后处理完成: msgId={}", request.getMsgId());
- }
-
- private void buildEndpointAuth(WvpDownRequest request, VideoPlatformInstance instance) {
- Map wvpRequestData = request.getWvpRequestData();
- if (wvpRequestData == null) {
- wvpRequestData = new HashMap<>();
- }
- String auth = instance.getAuth();
- if (JSONUtil.isTypeJSON(auth)) {
- wvpRequestData.putAll(JSONUtil.toBean(auth, Map.class));
- }
- String endpoint = instance.getEndpoint();
- if (StrUtil.isNotBlank(endpoint)) {
- wvpRequestData.put("endpoint", endpoint);
- }
- request.setWvpRequestData(wvpRequestData);
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/entity/WvpDownRequest.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/entity/WvpDownRequest.java
deleted file mode 100644
index e221423..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/entity/WvpDownRequest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package cn.wvp.protocol.entity;
-
-import cn.universal.common.constant.IoTConstant.DownCmd;
-import java.util.Map;
-
-/**
- * WVP 下行请求封装
- */
-public class WvpDownRequest extends cn.universal.persistence.base.BaseDownRequest {
- private DownCmd cmd;
- private String productKey;
- private String deviceId;
- private Map wvpRequestData;
-
- public DownCmd getCmd() {
- return cmd;
- }
-
- public void setCmd(DownCmd cmd) {
- this.cmd = cmd;
- }
-
- public String getProductKey() {
- return productKey;
- }
-
- public void setProductKey(String productKey) {
- this.productKey = productKey;
- }
-
- public String getDeviceId() {
- return deviceId;
- }
-
- public void setDeviceId(String deviceId) {
- this.deviceId = deviceId;
- }
-
- public Map getWvpRequestData() {
- return wvpRequestData;
- }
-
- public void setWvpRequestData(Map wvpRequestData) {
- this.wvpRequestData = wvpRequestData;
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handle/WvpDownHandle.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handle/WvpDownHandle.java
deleted file mode 100644
index 8f3bc89..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handle/WvpDownHandle.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package cn.wvp.protocol.handle;
-
-import cn.universal.common.constant.IoTConstant.DownCmd;
-import cn.universal.common.domain.R;
-import cn.universal.persistence.base.IoTDownAdapter;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandlerManager;
-import jakarta.annotation.Resource;
-import java.util.Objects;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP 下行实际处理入口(统一命令分发模式)
- */
-@Component
-public class WvpDownHandle extends IoTDownAdapter {
-
- private static final Logger log = LoggerFactory.getLogger(WvpDownHandle.class);
-
- @Resource private WvpCommandHandlerManager commandHandlerManager;
-
- public R> down(WvpDownRequest downRequest) {
- if (downRequest == null || downRequest.getCmd() == null) {
- log.warn("WVP设备处理下行对象为空,不处理={}", downRequest);
- return R.error("WVP设备处理下行对象为空");
- }
-
- R> preResult =
- beforeDownAction(downRequest.getIoTProduct(), downRequest.getData(), downRequest);
- if (Objects.nonNull(preResult)) {
- return preResult;
- }
-
- return dispatchCommand(downRequest);
- }
-
- private R> dispatchCommand(WvpDownRequest downRequest) {
- DownCmd cmd = downRequest.getCmd();
- switch (cmd) {
- case DEV_ADD:
- case DEV_DEL:
- case DEV_UPDATE:
- return commandHandlerManager.handleCommand(downRequest);
- case DEV_FUNCTION:
- return commandHandlerManager.handleCommand(downRequest);
- default:
- log.info("WVP设备处理下行未匹配到方法: {}", cmd);
- return R.error("未支持的命令类型: " + cmd);
- }
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/WvpCommandHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/WvpCommandHandler.java
deleted file mode 100644
index cfc58c7..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/WvpCommandHandler.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package cn.wvp.protocol.handler;
-
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-
-public interface WvpCommandHandler {
- String getSupportedCommand();
- R> handle(WvpDownRequest request);
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/WvpCommandHandlerManager.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/WvpCommandHandlerManager.java
deleted file mode 100644
index 92fc243..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/WvpCommandHandlerManager.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package cn.wvp.protocol.handler;
-
-import cn.hutool.core.map.MapUtil;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import java.util.HashMap;
-import java.util.Map;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP命令处理器管理器
- */
-@Slf4j
-@Component
-public class WvpCommandHandlerManager implements ApplicationContextAware {
-
- private Map handlerMap = new HashMap<>();
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- Map current =
- applicationContext.getBeansOfType(WvpCommandHandler.class);
- if (current != null && MapUtil.isNotEmpty(current)) {
- current.forEach(
- (key, handler) -> {
- String command = handler.getSupportedCommand();
- if (command != null && !command.isEmpty()) {
- handlerMap.put(command.toLowerCase(), handler);
- log.info("注册WVP命令处理器: {} -> {}", command, handler.getClass().getSimpleName());
- }
- });
- }
- }
-
- /**
- * 处理命令
- *
- * @param request 下行请求
- * @return 处理结果
- */
- public R> handleCommand(WvpDownRequest request) {
- String commandKey = getCommandKey(request);
- if (commandKey == null) {
- log.warn("WVP设备处理功能下行无法确定命令类型,不处理={}", request);
- return R.error("无法确定命令类型");
- }
-
- WvpCommandHandler handler = handlerMap.get(commandKey);
- if (handler == null) {
- log.info("WVP设备处理功能下行未匹配到处理器: {}", commandKey);
- return R.error("未找到对应的处理器: " + commandKey);
- }
-
- try {
- return handler.handle(request);
- } catch (Exception e) {
- log.error("处理命令时发生异常: {}", commandKey, e);
- return R.error("处理命令时发生异常: " + e.getMessage());
- }
- }
-
- /**
- * 获取命令键值
- * 兼容两种命令格式:
- * 1. DEV_FUNCTION 类型:从 function.function 字段或 data.function 字段获取
- * 2. DEV_ADD/DEV_DEL/DEV_UPDATE 类型:从 cmd 字段获取
- *
- * @param request 下行请求
- * @return 命令键值
- */
- private String getCommandKey(WvpDownRequest request) {
- // 首先尝试从 function.function 字段获取(DEV_FUNCTION 类型,新方式)
- if (request.getFunction() != null) {
- String function = (String) request.getFunction().get("function");
- if (function != null && !function.isEmpty()) {
- return function.toLowerCase();
- }
- }
-
- // 其次尝试从 data.function 字段获取(DEV_FUNCTION 类型,兼容旧方式)
- if (request.getData() != null) {
- String function = request.getData().getStr("function");
- if (function != null && !function.isEmpty()) {
- return function.toLowerCase();
- }
- }
-
- // 如果 function 为空,则从 cmd 字段获取(DEV_ADD/DEV_DEL/DEV_UPDATE 类型)
- if (request.getCmd() != null) {
- return request.getCmd().name().toLowerCase();
- }
-
- return null;
- }
-
- /**
- * 获取所有支持的命令
- *
- * @return 支持的命令列表
- */
- public String[] getSupportedCommands() {
- return handlerMap.keySet().toArray(new String[0]);
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceAddHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceAddHandler.java
deleted file mode 100644
index e221f8d..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceAddHandler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONUtil;
-import cn.universal.common.constant.IoTConstant.DeviceStatus;
-import cn.universal.common.constant.IoTConstant.DownCmd;
-import cn.universal.common.domain.R;
-import cn.universal.persistence.base.IoTDeviceLifeCycle;
-import cn.universal.persistence.dto.IoTDeviceDTO;
-import cn.universal.persistence.entity.IoTDevice;
-import cn.universal.persistence.mapper.IoTDeviceMapper;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import jakarta.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WvpDeviceAddHandler implements WvpCommandHandler {
-
- @Resource(name = "ioTDeviceActionAfterService")
- private IoTDeviceLifeCycle ioTDeviceLifeCycle;
-
- @Resource private IoTDeviceMapper ioTDeviceMapper;
-
- public R> handle(WvpDownRequest downRequest) {
- // 幂等检查:productKey + deviceId
- Map query = new HashMap<>();
- query.put("iotId", downRequest.getProductKey() + downRequest.getDeviceId());
- IoTDeviceDTO exist = ioTDeviceMapper.selectIoTDeviceBO(query);
- if (exist != null) {
- return R.error("设备已存在");
- }
- // TODO: 接入WVP级联/GB注册绑定逻辑
- IoTDevice ioTDevice = IoTDevice.builder()
- .deviceId(downRequest.getDeviceId())
- .createTime(System.currentTimeMillis() / 1000)
- .deviceName(StrUtil.emptyToDefault(downRequest.getDetail(), downRequest.getDeviceId()))
- .state(DeviceStatus.offline.getCode())
- .iotId(downRequest.getProductKey() + downRequest.getDeviceId())
- .creatorId(downRequest.getAppUnionId())
- .productName(downRequest.getIoTProduct().getName())
- .application(downRequest.getApplicationId())
- .detail(downRequest.getDetail())
- .productKey(downRequest.getProductKey())
- .build();
- Map config = new HashMap<>();
- config.put("discardValue", 0);
- ioTDevice.setConfiguration(JSONUtil.toJsonStr(config));
- ioTDeviceMapper.insertUseGeneratedKeys(ioTDevice);
- ioTDeviceLifeCycle.create(downRequest.getProductKey(), downRequest.getDeviceId(), downRequest);
- Map result = new HashMap<>();
- result.put("iotId", ioTDevice.getIotId());
- if (StrUtil.isNotBlank(downRequest.getIoTProduct().getMetadata())) {
- result.put("metadata", JSONUtil.parseObj(downRequest.getIoTProduct().getMetadata()));
- }
- result.put("productKey", downRequest.getProductKey());
- result.put("deviceNode", downRequest.getIoTProduct().getDeviceNode());
- return R.ok(result);
- }
-
- public String getSupportedCommand() {
- return DownCmd.DEV_ADD.name().toLowerCase();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceDeleteHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceDeleteHandler.java
deleted file mode 100644
index c1e5ac3..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceDeleteHandler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.IoTConstant.DownCmd;
-import cn.universal.common.domain.R;
-import cn.universal.dm.device.service.impl.IoTDeviceService;
-import cn.universal.persistence.base.IoTDeviceLifeCycle;
-import cn.universal.persistence.dto.IoTDeviceDTO;
-import cn.universal.persistence.mapper.IoTDeviceMapper;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import jakarta.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WvpDeviceDeleteHandler implements WvpCommandHandler {
-
- @Resource(name = "ioTDeviceActionAfterService")
- private IoTDeviceLifeCycle ioTDeviceLifeCycle;
- @Resource private IoTDeviceMapper ioTDeviceMapper;
- @Resource private IoTDeviceService iotDeviceService;
-
- public R> handle(WvpDownRequest downRequest) {
- // 幂等检查
- Map param = new HashMap<>();
- param.put("iotId", downRequest.getProductKey() + downRequest.getDeviceId());
- IoTDeviceDTO dto = ioTDeviceMapper.selectIoTDeviceBO(param);
- if (dto == null) {
- return R.error("设备不存在");
- }
- // TODO: 接入WVP解绑逻辑,若未绑定则直接删除本地
- ioTDeviceLifeCycle.delete(dto, downRequest);
- iotDeviceService.delDevInstance(dto.getIotId());
- return R.ok();
- }
-
- public String getSupportedCommand() {
- return DownCmd.DEV_DEL.name().toLowerCase();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceUpdateHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceUpdateHandler.java
deleted file mode 100644
index 65fa1cf..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpDeviceUpdateHandler.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.universal.common.constant.IoTConstant.DownCmd;
-import cn.universal.common.domain.R;
-import cn.universal.persistence.entity.IoTDevice;
-import cn.universal.persistence.mapper.IoTDeviceMapper;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import jakarta.annotation.Resource;
-import java.util.Map;
-import org.springframework.stereotype.Component;
-import tk.mybatis.mapper.entity.Example;
-
-@Component
-public class WvpDeviceUpdateHandler implements WvpCommandHandler {
- @Resource private IoTDeviceMapper ioTDeviceMapper;
-
- public R> handle(WvpDownRequest request) {
- Map data = request.getWvpRequestData();
- if (data == null || MapUtil.isEmpty(data)) return R.error("缺少参数: data");
- String newName = (String) data.get("deviceName");
- if (newName == null || newName.isEmpty()) return R.error("缺少参数: deviceName");
- String iotId = request.getProductKey() + request.getDeviceId();
- String latitude = (String) data.get("latitude");
- String longitude = (String) data.get("longitude");
- // 根据iotId更新设备名称
- IoTDevice dev = new IoTDevice();
- dev.setDeviceName(newName);
- if (StrUtil.isNotBlank(latitude) && StrUtil.isNotBlank(longitude)) {
- dev.setCoordinate(longitude + "," + latitude);
- }
-
- // 使用Example构建更新条件,根据iotId更新
- Example example = new Example(IoTDevice.class);
- example.createCriteria().andEqualTo("iotId", iotId);
- int count = ioTDeviceMapper.updateByExampleSelective(dev, example);
- if (count > 0) {
- return R.ok("更新成功");
- }
- return R.ok("无变化");
- }
-
- public String getSupportedCommand() {
- return DownCmd.DEV_UPDATE.name().toLowerCase();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpLiveStreamHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpLiveStreamHandler.java
deleted file mode 100644
index 887818c..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpLiveStreamHandler.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WvpLiveStreamHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- String function = request.getData() == null ? null : request.getData().getStr("function");
- return wvpDeviceService.startPreview(request);
- }
- public String getSupportedCommand() { return CameraCommand.CAMERA_LIVE_STREAM.getFunctionName(); }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpLoadCloudRecordHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpLoadCloudRecordHandler.java
deleted file mode 100644
index 57d761a..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpLoadCloudRecordHandler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP加载云端录像处理器
- *
- * @version 1.0
- * @since 2025/11/09
- */
-@Component
-public class WvpLoadCloudRecordHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- return wvpDeviceService.loadCloudRecord(request);
- }
-
- public String getSupportedCommand() {
- return CameraCommand.LOAD_CLOUD_RECORD.getFunctionName();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpPlaybackHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpPlaybackHandler.java
deleted file mode 100644
index bc0cae9..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpPlaybackHandler.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WvpPlaybackHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- return wvpDeviceService.startPlayback(request);
- }
- public String getSupportedCommand() { return CameraCommand.CAMERA_PLAYBACK.getFunctionName(); }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpPtzControlHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpPtzControlHandler.java
deleted file mode 100644
index 4a6228c..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpPtzControlHandler.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WvpPtzControlHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- return wvpDeviceService.ptzControl(request);
- }
- public String getSupportedCommand() { return CameraCommand.CAMERA_TURN.getFunctionName(); }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpQueryCloudRecordsHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpQueryCloudRecordsHandler.java
deleted file mode 100644
index d5cfd01..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpQueryCloudRecordsHandler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP查询云端录像处理器
- *
- * @version 1.0
- * @since 2025/11/09
- */
-@Component
-public class WvpQueryCloudRecordsHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- return wvpDeviceService.queryCloudRecords(request);
- }
-
- public String getSupportedCommand() {
- return CameraCommand.QUERY_CLOUD_RECORDS.getFunctionName();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpQueryRecordsHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpQueryRecordsHandler.java
deleted file mode 100644
index b3172c8..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpQueryRecordsHandler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-/**
- * WVP查询录像处理器
- *
- * @version 1.0
- * @since 2025/11/09
- */
-@Component
-public class WvpQueryRecordsHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- return wvpDeviceService.queryGBRecords(request);
- }
-
- public String getSupportedCommand() {
- return CameraCommand.QUERY_RECORDS.getFunctionName();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpSnapshotHandler.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpSnapshotHandler.java
deleted file mode 100644
index b94022e..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/handler/impl/WvpSnapshotHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package cn.wvp.protocol.handler.impl;
-
-import cn.universal.common.constant.CameraCommand;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handler.WvpCommandHandler;
-import cn.wvp.protocol.service.WvpDeviceService;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WvpSnapshotHandler implements WvpCommandHandler {
- @Resource private WvpDeviceService wvpDeviceService;
-
- public R> handle(WvpDownRequest request) {
- return wvpDeviceService.snapshot(request);
- }
-
- public String getSupportedCommand() {
- return CameraCommand.CAMERA_SNAPSHOT.getFunctionName();
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/WvpDeviceService.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/WvpDeviceService.java
deleted file mode 100644
index 2cb76e3..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/WvpDeviceService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package cn.wvp.protocol.service;
-
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import java.util.Map;
-
-/** WVP 设备服务接口 */
-public interface WvpDeviceService {
- // 设备/组织/通道拉取(供缓存同步使用)
- R> listDevices(String instanceKey, Map filters);
-
- R> listOrgs(String instanceKey, Map filters);
-
- R> listChannels(String serial, Map filters);
-
- // 能力调用(供命令处理器使用)
- R> ptzControl(WvpDownRequest request);
-
- R> startPreview(WvpDownRequest request);
-
- R> stopPreview(WvpDownRequest request);
-
- R> startPlayback(WvpDownRequest request);
-
- R> stopPlayback(WvpDownRequest request);
-
- R> snapshot(WvpDownRequest request);
-
- R> queryPresets(WvpDownRequest request);
-
- // ==================== 国标录像相关 ====================
-
- /** 查询国标录像 */
- R> queryGBRecords(WvpDownRequest request);
-
- /** 开始下载国标录像 */
- R> startGBRecordDownload(WvpDownRequest request);
-
- /** 停止下载国标录像 */
- R> stopGBRecordDownload(WvpDownRequest request);
-
- /** 获取下载进度 */
- R> getGBRecordDownloadProgress(WvpDownRequest request);
-
- // ==================== 云端录像相关 ====================
-
- /** 查询云端录像日期列表 */
- R> queryCloudRecordDates(WvpDownRequest request);
-
- /** 查询云端录像列表 */
- R> queryCloudRecords(WvpDownRequest request);
-
- /** 加载云端录像文件 */
- R> loadCloudRecord(WvpDownRequest request);
-
- /** 云端录像定位 */
- R> seekCloudRecord(WvpDownRequest request);
-
- /** 设置云端录像倍速 */
- R> setCloudRecordSpeed(WvpDownRequest request);
-
- /** 获取云端录像下载地址 */
- R> getCloudRecordPlayPath(WvpDownRequest request);
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/WvpDownService.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/WvpDownService.java
deleted file mode 100644
index ffb1f17..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/WvpDownService.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: 本文件由 gitee.com/NexIoT 开发并拥有版权,未经授权严禁擅自商用、复制或传播。
- * @Author: gitee.com/NexIoT
- * @Email: wo8335224@gmail.com
- * @Wechat: outlookFil
- *
- *
- */
-
-package cn.wvp.protocol.service;
-
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.universal.common.domain.R;
-import cn.universal.core.service.IDown;
-import cn.universal.dm.device.service.AbstractDownService;
-import cn.universal.persistence.dto.IoTDeviceDTO;
-import cn.universal.persistence.entity.IoTProduct;
-import cn.universal.persistence.query.IoTDeviceQuery;
-import cn.wvp.protocol.config.WvpModuleInfo;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.handle.WvpDownHandle;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-/**
- * WVP下行服务
- *
- * @version 2.0
- * @since 2025/1/15
- */
-@Service("wvpDownService")
-@Slf4j
-public class WvpDownService extends AbstractDownService implements IDown {
-
- @Resource private WvpModuleInfo wvpModuleInfo;
-
- @Resource private WvpDownHandle wvpDownHandle;
-
- @Resource private cn.universal.core.downlink.DownlinkInterceptorChain downlinkInterceptorChain;
-
- @Override
- public cn.universal.core.downlink.DownlinkInterceptorChain getInterceptorChain() {
- return downlinkInterceptorChain;
- }
-
- @Override
- public String code() {
- return wvpModuleInfo.getCode();
- }
-
- @Override
- public String name() {
- return wvpModuleInfo.getName();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public R> doProcess(cn.universal.core.downlink.DownlinkContext> context) {
- try {
- WvpDownRequest downRequest;
- if (context.getDownRequest() != null) {
- downRequest = (WvpDownRequest) context.getDownRequest();
- } else if (context.getRawMessage() != null) {
- downRequest = convert(context.getRawMessage());
- } else if (context.getJsonMessage() != null) {
- downRequest = convert(context.getJsonMessage());
- } else {
- return R.error("消息为空");
- }
-
- if (downRequest == null) {
- return R.error("转换下行请求失败");
- }
-
- // 设置上下文信息
- ((cn.universal.core.downlink.DownlinkContext) context)
- .setDownRequest(downRequest);
- context.setProductKey(downRequest.getProductKey());
- context.setDeviceId(downRequest.getDeviceId());
- context.setIotId(downRequest.getIotId());
-
- log.info(
- "[WVP下行] deviceId={} productKey={}",
- downRequest.getDeviceId(),
- downRequest.getProductKey());
-
- // 执行处理
- return wvpDownHandle.down(downRequest);
-
- } catch (Exception e) {
- log.error("[WVP下行] 处理异常", e);
- return R.error("处理异常: " + e.getMessage());
- }
- }
-
- @Override
- protected WvpDownRequest convert(String request) {
- return doConvert(request);
- }
-
- private WvpDownRequest convert(JSONObject request) {
- return doConvert(request);
- }
-
- /**
- * 执行转换操作
- *
- * @param request 请求对象
- * @return 转换后的下行请求
- */
- private WvpDownRequest doConvert(Object request) {
- try {
- WvpDownRequest value = parseRequest(request);
- if (value == null) {
- return null;
- }
- // 获取设备信息
- IoTDeviceDTO deviceDTO = getDeviceInfo(value);
- value.setIoTDeviceDTO(deviceDTO);
- // 获取产品信息
- IoTProduct product = getProduct(value.getProductKey());
- if (product == null) {
- log.warn("产品不存在: productKey={}", value.getProductKey());
- return null;
- }
-
- // 设置相关信息
- value.setIoTProduct(product);
- value.setIoTDeviceDTO(deviceDTO);
- value.setWvpRequestData(value.getWvpRequestData());
-
- return value;
- } catch (Exception e) {
- log.error("转换下行请求失败", e);
- return null;
- }
- }
-
- /**
- * 解析请求对象
- *
- * @param request 请求对象
- * @return 解析后的下行请求
- */
- private WvpDownRequest parseRequest(Object request) {
- if (request instanceof JSONObject) {
- return JSONUtil.toBean((JSONObject) request, WvpDownRequest.class);
- } else if (request instanceof String) {
- return JSONUtil.toBean((String) request, WvpDownRequest.class);
- } else {
- return JSONUtil.toBean(JSONUtil.toJsonStr(request), WvpDownRequest.class);
- }
- }
-
- /**
- * 获取设备信息
- *
- * @param value 下行请求
- * @return 设备信息
- */
- private IoTDeviceDTO getDeviceInfo(WvpDownRequest value) {
- IoTDeviceQuery query =
- IoTDeviceQuery.builder()
- .productKey(value.getProductKey())
- .deviceId(value.getDeviceId())
- .iotId(value.getIotId())
- .build();
- return getIoTDeviceDTO(query);
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/impl/WvpDeviceServiceImpl.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/impl/WvpDeviceServiceImpl.java
deleted file mode 100644
index 766210f..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/service/impl/WvpDeviceServiceImpl.java
+++ /dev/null
@@ -1,873 +0,0 @@
-package cn.wvp.protocol.service.impl;
-
-import cn.hutool.json.JSONObject;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.constant.WvpApiConstants;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.service.WvpDeviceService;
-import cn.wvp.protocol.util.VideoPlatformHttpUtil;
-import java.util.*;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-/** WVP设备服务实现 - 使用wvp-GB28181-pro标准接口 基于com.genersoft.iot.vmp.gb28181.controller下的标准API */
-@Slf4j
-@Service
-public class WvpDeviceServiceImpl implements WvpDeviceService {
-
- /** 从filters中提取endpoint */
- private String getEndpoint(Map filters) {
- return String.valueOf(Optional.ofNullable(filters).map(m -> m.get("endpoint")).orElse(""));
- }
-
- /** 从WvpDownRequest中提取endpoint */
- private String getEndpoint(WvpDownRequest request) {
- return String.valueOf(
- Optional.ofNullable(request.getWvpRequestData()).map(m -> m.get("endpoint")).orElse(""));
- }
-
- @Override
- public R> listDevices(String instanceKey, Map filters) {
- String endpoint = getEndpoint(filters);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(endpoint, WvpApiConstants.API_DEVICE_QUERY, filters);
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("获取设备列表失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 直接返回data部分,避免双层包装
- Object data = resp.get("data");
- return R.ok(data != null ? data : resp);
- }
-
- @Override
- public R> listOrgs(String instanceKey, Map filters) {
- // WVP GB28181通常不提供组织树结构,返回空列表
- return R.ok(Collections.emptyList());
- }
-
- @Override
- public R> listChannels(String serial, Map filters) {
- String endpoint = getEndpoint(filters);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String path = String.format(WvpApiConstants.API_DEVICE_CHANNELS, serial);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("获取通道列表失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 直接返回data部分,避免双层包装
- Object data = resp.get("data");
- return R.ok(data != null ? data : resp);
- }
-
- @Override
- public R> ptzControl(WvpDownRequest request) {
- JSONObject data = request.getData();
- if (data == null) {
- return R.error("缺少参数: data");
- }
-
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String command = data.getStr("command"); // left/right/up/down/stop/zoomin/zoomout/focusIn/focusOut/irisIn/irisOut等
- String channelId = data.getStr("channelId");
- Integer speed = data.getInt("speed", 50); // 速度默认50
-
- if (command == null || command.isEmpty()) {
- return R.error("缺少参数: command");
- }
- if (channelId == null || channelId.isEmpty()) {
- return R.error("缺少参数: channelId");
- }
-
- // 根据命令类型选择不同的接口
- String path;
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- // 判断是否为聚焦命令
- if ("focusIn".equalsIgnoreCase(command) || "focusOut".equalsIgnoreCase(command)) {
- path = String.format(WvpApiConstants.API_FOCUS_CONTROL, request.getDeviceId(), channelId);
- // 转换命令: focusIn -> near, focusOut -> far
- String focusCmd = "focusIn".equalsIgnoreCase(command) ? "near" : "far";
- filters.put("command", focusCmd);
- filters.put("speed", speed);
- }
- // 判断是否为光圈命令
- else if ("irisIn".equalsIgnoreCase(command) || "irisOut".equalsIgnoreCase(command)) {
- path = String.format(WvpApiConstants.API_IRIS_CONTROL, request.getDeviceId(), channelId);
- // 转换命令: irisIn -> in, irisOut -> out
- String irisCmd = "irisIn".equalsIgnoreCase(command) ? "in" : "out";
- filters.put("command", irisCmd);
- filters.put("speed", speed);
- }
- // 云台方向和缩放命令
- else {
- path = String.format(WvpApiConstants.API_PTZ_CONTROL, request.getDeviceId(), channelId);
-
- // 计算horizonSpeed和verticalSpeed
- int horizonSpeed = 0;
- int verticalSpeed = 0;
- int zoomSpeed = 0;
-
- // 根据命令设置速度
- switch (command.toLowerCase()) {
- case "left":
- case "right":
- horizonSpeed = speed;
- break;
- case "up":
- case "down":
- verticalSpeed = speed;
- break;
- case "leftup":
- case "upleft":
- case "rightup":
- case "upright":
- case "leftdown":
- case "downleft":
- case "rightdown":
- case "downright":
- horizonSpeed = speed;
- verticalSpeed = speed;
- break;
- case "zoomin":
- case "zoomout":
- zoomSpeed = Math.min(speed / 16, 15); // zoomSpeed范围0-15
- break;
- case "stop":
- // stop命令速度都为0
- break;
- default:
- return R.error("不支持的命令: " + command);
- }
-
- filters.put("command", command.toLowerCase());
- filters.put("horizonSpeed", horizonSpeed);
- filters.put("verticalSpeed", verticalSpeed);
- filters.put("zoomSpeed", zoomSpeed);
- }
-
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("云台控制失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- Map result = new HashMap<>();
- result.put("executed", true);
- result.put("command", command);
- result.put("channelId", channelId);
- return R.ok(result);
- }
-
- @Override
- public R> startPreview(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String channelId = data == null ? null : data.getStr("channelId");
- if (channelId == null || channelId.isEmpty()) {
- return R.error("缺少参数: channelId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("channelId", channelId);
-
- String path = String.format(WvpApiConstants.API_PLAY_START, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("启动预览失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
- return R.ok(resp.getJSONObject("data"));
- }
-
- @Override
- public R> startPlayback(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺少参数: data");
- }
-
- String channelId = data.getStr("channelId");
- Object startTimeObj = data.get("startTime");
- Object endTimeObj = data.get("endTime");
-
- if (channelId == null || startTimeObj == null || endTimeObj == null) {
- return R.error("缺少参数: channelId/startTime/endTime");
- }
-
- // 将时间戳转换为时间字符串格式(wvp API 需要 yyyy-MM-dd HH:mm:ss 格式)
- String startTimeStr;
- String endTimeStr;
- try {
- long startTime;
- long endTime;
-
- // 处理时间参数:可能是 Long 类型的时间戳,也可能是 String 类型
- if (startTimeObj instanceof Long) {
- startTime = (Long) startTimeObj;
- } else if (startTimeObj instanceof String) {
- startTime = Long.parseLong((String) startTimeObj);
- } else {
- startTime = ((Number) startTimeObj).longValue();
- }
-
- if (endTimeObj instanceof Long) {
- endTime = (Long) endTimeObj;
- } else if (endTimeObj instanceof String) {
- endTime = Long.parseLong((String) endTimeObj);
- } else {
- endTime = ((Number) endTimeObj).longValue();
- }
-
- // 如果是10位秒级时间戳,转换为毫秒
- if (startTime > 0 && startTime < 10000000000L) {
- startTime = startTime * 1000;
- }
- if (endTime > 0 && endTime < 10000000000L) {
- endTime = endTime * 1000;
- }
-
- // 转换为时间字符串格式
- java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- startTimeStr = sdf.format(new java.util.Date(startTime));
- endTimeStr = sdf.format(new java.util.Date(endTime));
- } catch (Exception e) {
- return R.error("时间参数格式错误: " + e.getMessage());
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- // wvp API 需要时间字符串格式
- filters.put("startTime", startTimeStr);
- filters.put("endTime", endTimeStr);
-
- String path =
- String.format(WvpApiConstants.API_PLAYBACK_START, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("启动回放失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 从响应中获取 data 对象
- JSONObject dataObj = resp.getJSONObject("data");
- if (dataObj == null) {
- return R.error("启动回放失败: 响应数据为空");
- }
-
- // 提取所有流地址字段
- Map urls = new LinkedHashMap<>();
- String flv = dataObj.getStr("flv");
- String httpsFlv = dataObj.getStr("https_flv");
- String wsFlv = dataObj.getStr("ws_flv");
- String wssFlv = dataObj.getStr("wss_flv");
- String hls = dataObj.getStr("hls");
- String httpsHls = dataObj.getStr("https_hls");
- String wsHls = dataObj.getStr("ws_hls");
- String wssHls = dataObj.getStr("wss_hls");
- String rtmp = dataObj.getStr("rtmp");
- String rtmps = dataObj.getStr("rtmps");
- String rtsp = dataObj.getStr("rtsp");
- String rtsps = dataObj.getStr("rtsps");
-
- if (flv != null) urls.put("flv", flv);
- if (httpsFlv != null) urls.put("https_flv", httpsFlv);
- if (wsFlv != null) urls.put("ws_flv", wsFlv);
- if (wssFlv != null) urls.put("wss_flv", wssFlv);
- if (hls != null) urls.put("hls", hls);
- if (httpsHls != null) urls.put("https_hls", httpsHls);
- if (wsHls != null) urls.put("ws_hls", wsHls);
- if (wssHls != null) urls.put("wss_hls", wssHls);
- if (rtmp != null) urls.put("rtmp", rtmp);
- if (rtmps != null) urls.put("rtmps", rtmps);
- if (rtsp != null) urls.put("rtsp", rtsp);
- if (rtsps != null) urls.put("rtsps", rtsps);
-
- // 提取其他重要字段
- String app = dataObj.getStr("app");
- String stream = dataObj.getStr("stream");
- String mediaServerId = dataObj.getStr("mediaServerId");
- String key = dataObj.getStr("key");
- String respStartTimeStr = dataObj.getStr("startTime");
- String respEndTimeStr = dataObj.getStr("endTime");
-
- Map res = new HashMap<>();
- res.put("channelId", channelId);
-
- // 保存原始时间戳(毫秒)- 使用请求时的时间字符串
- try {
- java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- res.put("startTime", sdf.parse(startTimeStr).getTime());
- res.put("endTime", sdf.parse(endTimeStr).getTime());
- } catch (Exception e) {
- // 如果解析失败,使用当前时间
- res.put("startTime", System.currentTimeMillis());
- res.put("endTime", System.currentTimeMillis());
- }
-
- // 将所有流地址直接放在根级别,而不是嵌套在 urls 中(前端需要直接访问)
- res.putAll(urls);
-
- // 添加其他重要字段
- if (app != null) res.put("app", app);
- if (stream != null) res.put("stream", stream);
- if (mediaServerId != null) res.put("mediaServerId", mediaServerId);
- if (key != null) res.put("key", key);
- // 使用响应中的时间字符串(如果存在)
- if (respStartTimeStr != null) res.put("startTimeStr", respStartTimeStr);
- else if (startTimeStr != null) res.put("startTimeStr", startTimeStr);
- if (respEndTimeStr != null) res.put("endTimeStr", respEndTimeStr);
- else if (endTimeStr != null) res.put("endTimeStr", endTimeStr);
-
- return R.ok(res);
- }
-
- @Override
- public R> snapshot(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String channelId = data == null ? null : data.getStr("channelId");
- if (channelId == null) {
- return R.error("缺少参数: channelId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("channelId", channelId);
- filters.put("deviceId", request.getDeviceId());
- String path = String.format(WvpApiConstants.API_SNAPSHOT, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("抓拍失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- String snapshotUrl = resp.getStr("snap", resp.getStr("url", ""));
- Map res = new HashMap<>();
- res.put("channelId", channelId);
- res.put("snapshotUrl", snapshotUrl);
- return R.ok(res);
- }
-
- @Override
- public R> stopPreview(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String channelId = data == null ? null : data.getStr("channelId");
- if (channelId == null || channelId.isEmpty()) {
- return R.error("缺少参数: channelId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- String path = String.format(WvpApiConstants.API_PLAY_STOP, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("停止预览失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok();
- }
-
- @Override
- public R> queryPresets(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String channelId = data == null ? null : data.getStr("channelId");
- if (channelId == null || channelId.isEmpty()) {
- return R.error("缺少参数: channelId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- String path = String.format(WvpApiConstants.API_PRESET_QUERY, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("查询预置位失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok(resp);
- }
-
- // ==================== 以下为新增录像相关接口 ====================
-
- @Override
- public R> stopPlayback(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺少参数: endpoint");
- }
-
- String channelId = data == null ? null : data.getStr("channelId");
- if (channelId == null || channelId.isEmpty()) {
- return R.error("缺岑参数: channelId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- String path =
- String.format(WvpApiConstants.API_PLAYBACK_STOP, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("停止回放失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok();
- }
-
- @Override
- public R> queryGBRecords(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String channelId = data.getStr("channelId");
- String startTime = data.getStr("startTime");
- String endTime = data.getStr("endTime");
-
- if (channelId == null || startTime == null || endTime == null) {
- return R.error("缺岑参数: channelId/startTime/endTime");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("startTime", startTime);
- filters.put("endTime", endTime);
-
- String path =
- String.format(WvpApiConstants.API_GB_RECORD_QUERY, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("国标录像查询失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok(resp.getJSONObject("data"));
- }
-
- @Override
- public R> startGBRecordDownload(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String channelId = data.getStr("channelId");
- String startTime = data.getStr("startTime");
- String endTime = data.getStr("endTime");
- Integer downloadSpeed = data.getInt("downloadSpeed", 1);
-
- if (channelId == null || startTime == null || endTime == null) {
- return R.error("缺岑参数: channelId/startTime/endTime");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("startTime", startTime);
- filters.put("endTime", endTime);
- filters.put("downloadSpeed", downloadSpeed);
-
- String path =
- String.format(
- WvpApiConstants.API_GB_RECORD_DOWNLOAD_START, request.getDeviceId(), channelId);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("开始下载失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok(resp.getJSONObject("data"));
- }
-
- @Override
- public R> stopGBRecordDownload(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String channelId = data.getStr("channelId");
- String stream = data.getStr("stream");
-
- if (channelId == null || stream == null) {
- return R.error("缺岑参数: channelId/stream");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- String path =
- String.format(
- WvpApiConstants.API_GB_RECORD_DOWNLOAD_STOP, request.getDeviceId(), channelId, stream);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("停止下载失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok();
- }
-
- @Override
- public R> getGBRecordDownloadProgress(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String channelId = data.getStr("channelId");
- String stream = data.getStr("stream");
-
- if (channelId == null || stream == null) {
- return R.error("缺岑参数: channelId/stream");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- String path =
- String.format(
- WvpApiConstants.API_GB_RECORD_DOWNLOAD_PROGRESS,
- request.getDeviceId(),
- channelId,
- stream);
- JSONObject resp = VideoPlatformHttpUtil.httpGetJson(endpoint, path, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("获取下载进度失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 直接返回data部分,避免双层包装
- Object respData = resp.get("data");
- return R.ok(respData != null ? respData : resp);
- }
-
- @Override
- public R> queryCloudRecordDates(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String app = data.getStr("app");
- String stream = data.getStr("stream");
-
- if (app == null || stream == null) {
- return R.error("缺岑参数: app/stream");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("app", app);
- filters.put("stream", stream);
-
- // 可选参数
- if (data.containsKey("year")) filters.put("year", data.getInt("year"));
- if (data.containsKey("month")) filters.put("month", data.getInt("month"));
- if (data.containsKey("mediaServerId"))
- filters.put("mediaServerId", data.getStr("mediaServerId"));
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(
- endpoint, WvpApiConstants.API_CLOUD_RECORD_DATE_LIST, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("查询云端录像日期失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 直接返回data部分,避免双层包装
- Object respData = resp.get("data");
- return R.ok(respData != null ? respData : resp);
- }
-
- @Override
- public R> queryCloudRecords(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
-
- // 必填分页参数
- filters.put("page", data.getInt("page", 1));
- filters.put("count", data.getInt("count", 10));
-
- // 可选参数
- if (data.containsKey("app")) filters.put("app", data.getStr("app"));
- if (data.containsKey("stream")) filters.put("stream", data.getStr("stream"));
- if (data.containsKey("startTime")) filters.put("startTime", data.getStr("startTime"));
- if (data.containsKey("endTime")) filters.put("endTime", data.getStr("endTime"));
- if (data.containsKey("mediaServerId"))
- filters.put("mediaServerId", data.getStr("mediaServerId"));
- if (data.containsKey("callId")) filters.put("callId", data.getStr("callId"));
- if (data.containsKey("query")) filters.put("query", data.getStr("query"));
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(endpoint, WvpApiConstants.API_CLOUD_RECORD_LIST, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("查询云端录像列表失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 直接返回data部分,避免双层包装
- Object respData = resp.get("data");
- return R.ok(respData != null ? respData : resp);
- }
-
- @Override
- public R> loadCloudRecord(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String app = data.getStr("app");
- String stream = data.getStr("stream");
- Integer cloudRecordId = data.getInt("cloudRecordId");
-
- if (app == null || stream == null || cloudRecordId == null) {
- return R.error("缺岑参数: app/stream/cloudRecordId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("app", app);
- filters.put("stream", stream);
- filters.put("cloudRecordId", cloudRecordId);
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(endpoint, WvpApiConstants.API_CLOUD_RECORD_LOAD, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("加载云端录像失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok(resp.getJSONObject("data"));
- }
-
- @Override
- public R> seekCloudRecord(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String mediaServerId = data.getStr("mediaServerId");
- String app = data.getStr("app");
- String stream = data.getStr("stream");
- Double seek = data.getDouble("seek");
-
- if (mediaServerId == null || app == null || stream == null || seek == null) {
- return R.error("缺岑参数: mediaServerId/app/stream/seek");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("mediaServerId", mediaServerId);
- filters.put("app", app);
- filters.put("stream", stream);
- filters.put("seek", seek);
- if (data.containsKey("schema")) filters.put("schema", data.getStr("schema"));
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(endpoint, WvpApiConstants.API_CLOUD_RECORD_SEEK, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("云端录像定位失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok();
- }
-
- @Override
- public R> setCloudRecordSpeed(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null) {
- return R.error("缺岑参数: data");
- }
-
- String mediaServerId = data.getStr("mediaServerId");
- String app = data.getStr("app");
- String stream = data.getStr("stream");
- Integer speed = data.getInt("speed");
-
- if (mediaServerId == null || app == null || stream == null || speed == null) {
- return R.error("缺岑参数: mediaServerId/app/stream/speed");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("mediaServerId", mediaServerId);
- filters.put("app", app);
- filters.put("stream", stream);
- filters.put("speed", speed);
- if (data.containsKey("schema")) filters.put("schema", data.getStr("schema"));
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(
- endpoint, WvpApiConstants.API_CLOUD_RECORD_SPEED, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("设置云端录像倍速失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- return R.ok();
- }
-
- @Override
- public R> getCloudRecordPlayPath(WvpDownRequest request) {
- JSONObject data = request.getData();
- String endpoint = getEndpoint(request);
- if (endpoint.isEmpty()) {
- return R.error("缺岑参数: endpoint");
- }
-
- if (data == null || !data.containsKey("recordId")) {
- return R.error("缺岑参数: recordId");
- }
-
- Map filters = new HashMap<>();
- if (request.getWvpRequestData() != null) {
- filters.putAll(request.getWvpRequestData());
- }
- filters.put("recordId", data.getInt("recordId"));
-
- JSONObject resp =
- VideoPlatformHttpUtil.httpGetJson(
- endpoint, WvpApiConstants.API_CLOUD_RECORD_PLAY_PATH, filters);
-
- if (VideoPlatformHttpUtil.hasError(resp)) {
- return R.error("获取云端录像下载地址失败: " + VideoPlatformHttpUtil.getErrorMessage(resp));
- }
-
- // 解析WVP返回的data字段,避免双重包裹
- JSONObject result = resp.getJSONObject("data");
- if (result == null) {
- result = new JSONObject();
- }
-
- return R.ok(result);
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/util/VideoPlatformHttpUtil.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/util/VideoPlatformHttpUtil.java
deleted file mode 100644
index ea4f0ed..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/util/VideoPlatformHttpUtil.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- */
-package cn.wvp.protocol.util;
-
-import cn.hutool.http.HttpRequest;
-import cn.hutool.http.HttpResponse;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import java.util.Map;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 视频平台HTTP请求工具类
- */
-@Slf4j
-public class VideoPlatformHttpUtil {
-
- private static final int DEFAULT_TIMEOUT = 10000; // 10秒超时
-
- /**
- * 执行GET请求并返回JSON结果(自动从filters提取token)
- *
- * @param baseUrl 基础URL
- * @param path 接口路径
- * @param filters 过滤参数(包含token)
- * @return JSON响应对象
- */
- public static JSONObject httpGetJson(
- String baseUrl, String path, Map filters) {
- return httpGetJson(baseUrl, path, filters, DEFAULT_TIMEOUT);
- }
-
- /**
- * 执行GET请求并返回JSON结果(支持自定义超时)
- *
- * @param baseUrl 基础URL
- * @param path 接口路径
- * @param filters 过滤参数(包含token和其他查询参数)
- * @param timeout 超时时间(毫秒)
- * @return JSON响应对象
- */
- public static JSONObject httpGetJson(
- String baseUrl,
- String path,
- Map filters,
- int timeout) {
- String url = buildUrl(baseUrl, path);
- HttpRequest request = HttpRequest.get(url).timeout(timeout);
-
- // 提取并设置token
- String token = extractToken(filters);
- if (token != null && !token.isEmpty()) {
- request.header("Access-Token", token);
- }
-
- // 添加查询参数(排除token和endpoint/auth等元数据)
- Map params = buildQueryParams(filters);
- if (!params.isEmpty()) {
- request.form(params);
- }
-
- try {
- log.info("HTTP GET请求: URL={}, params={}", url, filters);
- HttpResponse response = request.execute();
- String body = response.body();
- log.info("x`HTTP GET响应: status={}, body={}", response.getStatus(), body);
-
- if (body == null || body.isEmpty()) {
- return buildErrorResponse("响应体为空");
- }
- return JSONUtil.parseObj(body);
- } catch (Exception e) {
- log.error("HTTP GET请求失败: URL={}, error={}", url, e.getMessage(), e);
- return buildErrorResponse(e.getMessage());
- }
- }
-
- /**
- * 执行POST请求并返回JSON结果(自动从filters提取token)
- *
- * @param baseUrl 基础URL
- * @param path 接口路径
- * @param body 请求体(JSON)
- * @param filters 过滤参数(包含token)
- * @return JSON响应对象
- */
- public static JSONObject httpPostJson(
- String baseUrl, String path, JSONObject body, Map filters) {
- return httpPostJson(baseUrl, path, body, filters, DEFAULT_TIMEOUT);
- }
-
- /**
- * 执行POST请求并返回JSON结果(支持自定义超时)
- *
- * @param baseUrl 基础URL
- * @param path 接口路径
- * @param body 请求体(JSON)
- * @param filters 过滤参数(包含token)
- * @param timeout 超时时间(毫秒)
- * @return JSON响应对象
- */
- public static JSONObject httpPostJson(
- String baseUrl, String path, JSONObject body, Map filters, int timeout) {
- String url = buildUrl(baseUrl, path);
- HttpRequest request = HttpRequest.post(url).timeout(timeout);
-
- // 提取并设置token
- String token = extractToken(filters);
- if (token != null && !token.isEmpty()) {
- request.header("Access-Token", token);
- }
-
- // 设置请求体
- if (body != null) {
- request.body(body.toString()).contentType("application/json");
- }
-
- try {
- log.debug("HTTP POST请求: URL={}, body={}", url, body);
- HttpResponse response = request.execute();
- String responseBody = response.body();
- log.debug("HTTP POST响应: status={}, body={}", response.getStatus(), responseBody);
-
- if (responseBody == null || responseBody.isEmpty()) {
- return buildErrorResponse("响应体为空");
- }
- return JSONUtil.parseObj(responseBody);
- } catch (Exception e) {
- log.error("HTTP POST请求失败: URL={}, error={}", url, e.getMessage(), e);
- return buildErrorResponse(e.getMessage());
- }
- }
-
- /**
- * 构建完整URL
- */
- private static String buildUrl(String baseUrl, String path) {
- String url = baseUrl;
- if (!url.endsWith("/")) {
- url += "/";
- }
- if (path.startsWith("/")) {
- path = path.substring(1);
- }
- return url + path;
- }
-
- /**
- * 构建错误响应
- */
- private static JSONObject buildErrorResponse(String errorMsg) {
- JSONObject error = new JSONObject();
- error.set("error", errorMsg);
- error.set("success", false);
- return error;
- }
-
- /**
- * 检查响应是否包含错误
- */
- public static boolean hasError(JSONObject response) {
- if (response == null) {
- return true;
- }
- // 检查error字段
- if (response.containsKey("error")) {
- return true;
- }
- // 检查code字段(非0表示错误)
- if (response.containsKey("code")) {
- Integer code = response.getInt("code");
- return code != null && code != 0;
- }
- // 检查success字段
- if (response.containsKey("success")) {
- Boolean success = response.getBool("success");
- return success == null || !success;
- }
- return false;
- }
-
- /**
- * 获取错误消息
- */
- public static String getErrorMessage(JSONObject response) {
- if (response == null) {
- return "响应为空";
- }
- if (response.containsKey("error")) {
- return response.getStr("error");
- }
- if (response.containsKey("msg")) {
- return response.getStr("msg");
- }
- if (response.containsKey("message")) {
- return response.getStr("message");
- }
- if (response.containsKey("errMsg")) {
- return response.getStr("errMsg");
- }
- return "未知错误";
- }
-
- /**
- * 从filters中提取token
- * 优先从token字段获取,其次从auth字段解析
- */
- private static String extractToken(Map filters) {
- if (filters == null) {
- return null;
- }
-
- // 优先使用token字段
- Object tokenObj = filters.get("token");
- if (tokenObj != null) {
- return String.valueOf(tokenObj);
- }
-
- // 兼容旧的auth字段(JSON格式)
- Object authObj = filters.get("auth");
- if (authObj != null) {
- try {
- String authStr = String.valueOf(authObj);
- if (authStr.startsWith("{")) {
- JSONObject authJson = JSONUtil.parseObj(authStr);
- if (authJson.containsKey("apiKey")) {
- return authJson.getStr("apiKey");
- }
- if (authJson.containsKey("token")) {
- return authJson.getStr("token");
- }
- } else {
- // 直接是token字符串
- return authStr;
- }
- } catch (Exception e) {
- log.warn("解析auth字段失败: {}", e.getMessage());
- }
- }
-
- return null;
- }
-
- /**
- * 构建查询参数(排除元数据字段)
- */
- private static Map buildQueryParams(Map filters) {
- Map params = new java.util.HashMap<>();
- if (filters == null) {
- return params;
- }
-
- // 排除的元数据字段
- java.util.Set excludeKeys = new java.util.HashSet<>();
- excludeKeys.add("endpoint");
- excludeKeys.add("auth");
- excludeKeys.add("token");
- excludeKeys.add("baseUrl");
- excludeKeys.add("apiKey");
-
- for (Map.Entry entry : filters.entrySet()) {
- if (!excludeKeys.contains(entry.getKey()) && entry.getValue() != null) {
- params.put(entry.getKey(), entry.getValue());
- }
- }
-
- return params;
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/cn-universal-protocol/cn-wvp-protocol/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 8291e33..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1 +0,0 @@
-cn.wvp.protocol.config.WvpAutoConfiguration
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/test/java/cn/wvp/protocol/service/WvpDeviceServiceTest.java b/cn-universal-protocol/cn-wvp-protocol/src/test/java/cn/wvp/protocol/service/WvpDeviceServiceTest.java
deleted file mode 100644
index 7780e40..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/test/java/cn/wvp/protocol/service/WvpDeviceServiceTest.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: WVP设备服务测试类
- * @Author: gitee.com/NexIoT
- *
- */
-package cn.wvp.protocol.service;
-
-import cn.hutool.core.util.RandomUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.service.impl.WvpDeviceServiceImpl;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-/**
- * WVP设备服务单元测试
- *
- * 使用说明: 1. 修改 WVP_BASE_URL 为你的 WVP 平台地址 2. 修改 DEVICE_ID 和 CHANNEL_ID 为真实的设备与通道ID 3. 运行测试方法验证各项功能
- */
-public class WvpDeviceServiceTest {
-
- private WvpDeviceServiceImpl wvpDeviceService;
-
- // ==================== 配置区域,请根据实际环境修改 ====================
-
- /** WVP平台地址 */
- private static final String WVP_BASE_URL = "http://192.168.31.100:18080";
-
- /** 测试设备ID(国标编号) */
- private static final String DEVICE_ID = "34020000001320000001";
-
- /** 测试通道ID(国标编号) */
- private static final String CHANNEL_ID = "34020000001310000001";
-
- /** WVP实例标识 */
- private static final String INSTANCE_KEY = "wvp20250115ABC";
-
- /** WVP API Key(如启用鉴权则必填) */
- private static final String API_KEY =
- "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNlNzk2NDZjNGRiYzQwODM4M2E5ZWVkMDlmMmI4NWFlIn0.eyJqdGkiOiJMLUI4cXBqUDdWdlU4VzFjbVU4bWpBIiwiaWF0IjoxNzYyNDI2MzYxLCJleHAiOjEwNTc0NzM0NjkxNDgwOSwibmJmIjoxNzYyNDI2MzYxLCJzdWIiOiJsb2dpbiIsImF1ZCI6IkF1ZGllbmNlIiwidXNlck5hbWUiOiJhZG1pbiIsImFwaUtleUlkIjoxfQ.YK1dbexi66p8dbztPsTWpG2r5pb8gGebH59A-tYZKPqrLstLC6KhiYtPBoB_KItc-OBdlEQDpL5mZAtYgYY-ogS4JwTpOzgvOUh8mbEa68tdiughRrSohO5O43kUF67iwmEk9XalA0OpuOLTZPFcElApAiwUULtWz21AYOU17kFtkQ4AXvugDpOgRDmhHVpAvxW7bMbq70BroieO2iYNVtfCNS-qEWmA7zG0nDiQY3kk4mX7ftVg5IrCnS8xD5vg0GBq3mib06UaagWUFJ10I8vIe5smAQOe2s96aKuT88y_Ok43xVdsAkCS9pO9qjFKRz-aXHnb6zZmMBwaL3KcSQ"; // 请从WVP后台获取
-
- // ====================================================================
-
- @BeforeEach
- public void setUp() {
- wvpDeviceService = new WvpDeviceServiceImpl();
- System.out.println("=".repeat(80));
- System.out.println("WVP平台地址: " + WVP_BASE_URL);
- System.out.println("测试设备ID: " + DEVICE_ID);
- System.out.println("测试通道ID: " + CHANNEL_ID);
- System.out.println("=".repeat(80));
- }
-
- /** 创建WVP下行请求对象 */
- private WvpDownRequest createWvpRequest(String deviceId, JSONObject data) {
- WvpDownRequest request = new WvpDownRequest();
- request.setDeviceId(deviceId);
- request.setData(data);
-
- Map wvpRequestData = new HashMap<>();
- wvpRequestData.put("endpoint", WVP_BASE_URL);
- // 添加API Key鉴权
- if (API_KEY != null && !API_KEY.equals("your_api_key_here")) {
- wvpRequestData.put("token", API_KEY);
- }
- request.setWvpRequestData(wvpRequestData);
-
- return request;
- }
-
- /** 打印测试结果 */
- private void printResult(String testName, R> result) {
- System.out.println("\n【" + testName + "】");
- System.out.println("成功: " + result.isSuccess());
- System.out.println("消息: " + result.getMsg());
- if (result.getData() != null) {
- System.out.println("数据: " + JSONUtil.toJsonPrettyStr(result.getData()));
- }
- System.out.println("-".repeat(80));
- }
-
- @Test
- public void testListDevices() {
- System.out.println("\n>>> 测试设备列表查询");
-
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("page", 1);
- filters.put("count", 10);
- JSONObject set = new JSONObject();
- set.put("apiKey", API_KEY);
- Map auth = new HashMap<>();
- filters.put("auth", set);
- R> result = wvpDeviceService.listDevices(INSTANCE_KEY, filters);
- printResult("设备列表查询", result);
- }
-
- @Test
- public void testListChannels() {
- System.out.println("\n>>> 测试通道列表查询");
-
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("page", 1); // 当前页
- filters.put("count", 20); // 每页查询数量
- // filters.put("query", null);
- // filters.put("online", true);
- filters.put("channelType", 0); // 0:国标设备,1:推流设备,2:拉流代理"
- // filters.put("groupDeviceId", null);// 0:国标设备,1:推流设备,2:拉流代理"
- JSONObject set = new JSONObject();
- set.put("apiKey", API_KEY);
- Map auth = new HashMap<>();
- filters.put("auth", set);
- R> result = wvpDeviceService.listChannels(DEVICE_ID, filters);
- printResult("通道列表查询", result);
- }
-
- @Test
- public void testStartPreview() {
- System.out.println("\n>>> 测试直播开始");
-
- JSONObject data = new JSONObject();
- data.put("endpoint", WVP_BASE_URL);
- data.set("channelId", CHANNEL_ID);
- data.set("protocol", "flv"); // 优先协议
- data.set("token", API_KEY);
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.startPreview(request);
- printResult("直播开始", result);
-
- if (result.isSuccess()) {
- System.out.println("\n播放地址已获取,可用于 jessibuca 播放器:");
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- JSONObject urls = resultData.getJSONObject("urls");
- if (urls != null) {
- System.out.println("FLV: " + urls.getStr("flv"));
- System.out.println("HLS: " + urls.getStr("hls"));
- System.out.println("优先协议: " + resultData.getStr("prefer"));
- }
- }
- }
-
- @Test
- public void testStopPreview() {
- System.out.println("\n>>> 测试直播停止");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.stopPreview(request);
- printResult("直播停止", result);
- }
-
- @Test
- public void testPtzControl() {
- System.out.println("\n>>> 测试云台控制");
-
- // 测试向左转
- JSONObject dataLeft = new JSONObject();
- dataLeft.set("channelId", CHANNEL_ID);
- dataLeft.set("command", "left");
- dataLeft.set("speed", 50);
-
- WvpDownRequest requestLeft = createWvpRequest(DEVICE_ID, dataLeft);
- R> resultLeft = wvpDeviceService.ptzControl(requestLeft);
- printResult("云台控制-左转", resultLeft);
-
- // 延时
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- }
-
- // 测试停止
- JSONObject dataStop = new JSONObject();
- dataStop.set("channelId", CHANNEL_ID);
- dataStop.set("command", "stop");
- dataStop.set("speed", 0);
-
- WvpDownRequest requestStop = createWvpRequest(DEVICE_ID, dataStop);
- R> resultStop = wvpDeviceService.ptzControl(requestStop);
- printResult("云台控制-停止", resultStop);
- }
-
- @Test
- public void testQueryPresets() {
- System.out.println("\n>>> 测试预置位查询");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("timeout", 15);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.queryPresets(request);
- printResult("预置位查询", result);
- }
-
- @Test
- public void testSnapshot() {
- System.out.println("\n>>> 测试抓拍");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("mark", "abc" + RandomUtil.randomString(3));
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.snapshot(request);
- printResult("抓拍", result);
-
- if (result.isSuccess()) {
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- System.out.println("\n抓拍图片URL: " + resultData.getStr("snapshotUrl"));
- }
- }
-
- @Test
- public void testStartPlayback() {
- System.out.println("\n>>> 测试历史回放");
-
- // 查询最近1小时的录像
- long endTime = System.currentTimeMillis() / 1000;
- long startTime = endTime - 3600; // 1小时前
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("startTime", startTime);
- data.set("endTime", endTime);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.startPlayback(request);
- printResult("历史回放", result);
-
- if (result.isSuccess()) {
- System.out.println("\n回放地址已获取:");
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- JSONObject urls = resultData.getJSONObject("urls");
- if (urls != null) {
- System.out.println("FLV: " + urls.getStr("flv"));
- System.out.println("HLS: " + urls.getStr("hls"));
- }
- }
- }
-
- /** 完整流程测试:设备列表 -> 通道列表 -> 直播 -> 云台 -> 停止 */
- @Test
- public void testCompleteFlow() {
- System.out.println("\n========== 完整流程测试 ==========");
-
- // 1. 查询设备列表
- System.out.println("\n步骤1: 查询设备列表");
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("limit", 5);
- R> devicesResult = wvpDeviceService.listDevices(INSTANCE_KEY, filters);
- printResult("设备列表", devicesResult);
-
- // 2. 查询通道列表
- System.out.println("\n步骤2: 查询通道列表");
- Map channelFilters = new HashMap<>();
- channelFilters.put("endpoint", WVP_BASE_URL);
- channelFilters.put("limit", 5);
- R> channelsResult = wvpDeviceService.listChannels(DEVICE_ID, channelFilters);
- printResult("通道列表", channelsResult);
-
- // 3. 开始直播
- System.out.println("\n步骤3: 开始直播");
- JSONObject previewData = new JSONObject();
- previewData.set("channelId", CHANNEL_ID);
- previewData.set("protocol", "flv");
- WvpDownRequest previewRequest = createWvpRequest(DEVICE_ID, previewData);
- R> previewResult = wvpDeviceService.startPreview(previewRequest);
- printResult("开始直播", previewResult);
-
- if (previewResult.isSuccess()) {
- // 4. 云台控制
- System.out.println("\n步骤4: 云台控制(向右转2秒)");
- JSONObject ptzData = new JSONObject();
- ptzData.set("channelId", CHANNEL_ID);
- ptzData.set("command", "right");
- ptzData.set("speed", 50);
- WvpDownRequest ptzRequest = createWvpRequest(DEVICE_ID, ptzData);
- R> ptzResult = wvpDeviceService.ptzControl(ptzRequest);
- printResult("云台控制", ptzResult);
-
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- }
-
- // 5. 停止云台
- System.out.println("\n步骤5: 停止云台");
- JSONObject stopPtzData = new JSONObject();
- stopPtzData.set("channelId", CHANNEL_ID);
- stopPtzData.set("command", "stop");
- stopPtzData.set("speed", 0);
- WvpDownRequest stopPtzRequest = createWvpRequest(DEVICE_ID, stopPtzData);
- wvpDeviceService.ptzControl(stopPtzRequest);
-
- // 6. 停止直播
- System.out.println("\n步骤6: 停止直播");
- JSONObject stopData = new JSONObject();
- stopData.set("channelId", CHANNEL_ID);
- WvpDownRequest stopRequest = createWvpRequest(DEVICE_ID, stopData);
- R> stopResult = wvpDeviceService.stopPreview(stopRequest);
- printResult("停止直播", stopResult);
- }
-
- System.out.println("\n========== 流程测试完成 ==========");
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/src/test/java/cn/wvp/protocol/service/WvpDeviceServiceTest2.java b/cn-universal-protocol/cn-wvp-protocol/src/test/java/cn/wvp/protocol/service/WvpDeviceServiceTest2.java
deleted file mode 100644
index 61d5070..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/src/test/java/cn/wvp/protocol/service/WvpDeviceServiceTest2.java
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- *
- * Copyright (c) 2025, NexIoT. All Rights Reserved.
- *
- * @Description: WVP设备服务测试类
- * @Author: gitee.com/NexIoT
- *
- */
-package cn.wvp.protocol.service;
-
-import cn.hutool.core.date.DateField;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.universal.common.domain.R;
-import cn.wvp.protocol.entity.WvpDownRequest;
-import cn.wvp.protocol.service.impl.WvpDeviceServiceImpl;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-/**
- * WVP设备服务单元测试
- *
- * 使用说明: 1. 修改 WVP_BASE_URL 为你的 WVP 平台地址 2. 修改 DEVICE_ID 和 CHANNEL_ID 为真实的设备与通道ID 3. 运行测试方法验证各项功能
- */
-public class WvpDeviceServiceTest2 {
-
- private WvpDeviceServiceImpl wvpDeviceService;
-
- // ==================== 配置区域,请根据实际环境修改 ====================
-
- /** WVP平台地址 */
- private static final String WVP_BASE_URL = "http://192.168.31.100:18080";
-
- /** 测试设备ID(国标编号) */
- private static final String DEVICE_ID = "34020000001320000001";
-
- /** 测试通道ID(国标编号) */
- private static final String CHANNEL_ID = "34020000001310000001";
-
- /** WVP实例标识 */
- private static final String INSTANCE_KEY = "wvp20250115ABC";
-
- /** WVP API Key(如启用鉴权则必填) */
- private static final String API_KEY =
- "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNlNzk2NDZjNGRiYzQwODM4M2E5ZWVkMDlmMmI4NWFlIn0.eyJqdGkiOiJMLUI4cXBqUDdWdlU4VzFjbVU4bWpBIiwiaWF0IjoxNzYyNDI2MzYxLCJleHAiOjEwNTc0NzM0NjkxNDgwOSwibmJmIjoxNzYyNDI2MzYxLCJzdWIiOiJsb2dpbiIsImF1ZCI6IkF1ZGllbmNlIiwidXNlck5hbWUiOiJhZG1pbiIsImFwaUtleUlkIjoxfQ.YK1dbexi66p8dbztPsTWpG2r5pb8gGebH59A-tYZKPqrLstLC6KhiYtPBoB_KItc-OBdlEQDpL5mZAtYgYY-ogS4JwTpOzgvOUh8mbEa68tdiughRrSohO5O43kUF67iwmEk9XalA0OpuOLTZPFcElApAiwUULtWz21AYOU17kFtkQ4AXvugDpOgRDmhHVpAvxW7bMbq70BroieO2iYNVtfCNS-qEWmA7zG0nDiQY3kk4mX7ftVg5IrCnS8xD5vg0GBq3mib06UaagWUFJ10I8vIe5smAQOe2s96aKuT88y_Ok43xVdsAkCS9pO9qjFKRz-aXHnb6zZmMBwaL3KcSQ"; // 请从WVP后台获取
-
- // ====================================================================
-
- @BeforeEach
- public void setUp() {
- wvpDeviceService = new WvpDeviceServiceImpl();
- System.out.println("=".repeat(80));
- System.out.println("WVP平台地址: " + WVP_BASE_URL);
- System.out.println("测试设备ID: " + DEVICE_ID);
- System.out.println("测试通道ID: " + CHANNEL_ID);
- System.out.println("=".repeat(80));
- }
-
- /** 创建WVP下行请求对象 */
- private WvpDownRequest createWvpRequest(String deviceId, JSONObject data) {
- WvpDownRequest request = new WvpDownRequest();
- request.setDeviceId(deviceId);
- request.setData(data);
-
- Map wvpRequestData = new HashMap<>();
- wvpRequestData.put("endpoint", WVP_BASE_URL);
- // 添加token鉴权
- if (API_KEY != null && !API_KEY.isEmpty()) {
- wvpRequestData.put("token", API_KEY);
- }
- request.setWvpRequestData(wvpRequestData);
-
- return request;
- }
-
- /** 打印测试结果 */
- private void printResult(String testName, R> result) {
- System.out.println("\n【" + testName + "】");
- System.out.println("成功: " + result.isSuccess());
- System.out.println("消息: " + result.getMsg());
- if (result.getData() != null) {
- System.out.println("数据: " + JSONUtil.toJsonPrettyStr(result.getData()));
- }
- System.out.println("-".repeat(80));
- }
-
- /** 打印测试结果 */
- private void printResult(String testName, String body) {
- System.out.println("\n【" + testName + "】");
- System.out.println("成功: " + body);
- }
-
- @Test
- public void testListDevices() {
- System.out.println("\n>>> 测试设备列表查询");
-
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("token", API_KEY);
- filters.put("page", 1);
- filters.put("count", 10);
-
- R> result = wvpDeviceService.listDevices(INSTANCE_KEY, filters);
- printResult("设备列表查询", result);
- }
-
- @Test
- public void testListOrgs() {
- System.out.println("\n>>> 测试组织列表查询");
-
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("token", API_KEY);
-
- R> result = wvpDeviceService.listOrgs(INSTANCE_KEY, filters);
- printResult("组织列表查询", result);
- }
-
- @Test
- public void testListChannels() {
- System.out.println("\n>>> 测试通道列表查询");
-
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("token", API_KEY);
- filters.put("page", 1);
- filters.put("count", 20);
-
- R> result = wvpDeviceService.listChannels(DEVICE_ID, filters);
- printResult("通道列表查询", result);
- }
-
- @Test
- public void testStartPreview() {
- System.out.println("\n>>> 测试直播开始");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("protocol", "flv"); // 优先协议
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.startPreview(request);
- printResult("直播开始", result);
-
- if (result.isSuccess()) {
- System.out.println("\n播放地址已获取,可用于 jessibuca 播放器:");
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- JSONObject urls = resultData.getJSONObject("urls");
- if (urls != null) {
- System.out.println("FLV: " + urls.getStr("flv"));
- System.out.println("HLS: " + urls.getStr("hls"));
- System.out.println("优先协议: " + resultData.getStr("prefer"));
- }
- }
- }
-
- @Test
- public void testStopPreview() {
- System.out.println("\n>>> 测试直播停止");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.stopPreview(request);
- printResult("直播停止", result);
- }
-
- @Test
- public void testPtzControl() {
- System.out.println("\n>>> 测试云台控制");
-
- // 测试向左转
- JSONObject dataLeft = new JSONObject();
- dataLeft.set("channelId", CHANNEL_ID);
- dataLeft.set("command", "left");
- dataLeft.set("speed", 50);
-
- WvpDownRequest requestLeft = createWvpRequest(DEVICE_ID, dataLeft);
- R> resultLeft = wvpDeviceService.ptzControl(requestLeft);
- printResult("云台控制-左转", resultLeft);
-
- // 延时
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- }
-
- // 测试停止
- JSONObject dataStop = new JSONObject();
- dataStop.set("channelId", CHANNEL_ID);
- dataStop.set("command", "stop");
- dataStop.set("speed", 0);
-
- WvpDownRequest requestStop = createWvpRequest(DEVICE_ID, dataStop);
- R> resultStop = wvpDeviceService.ptzControl(requestStop);
- printResult("云台控制-停止", resultStop);
- }
-
- @Test
- public void testQueryPresets() {
- System.out.println("\n>>> 测试预置位查询");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("timeout", 15);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.queryPresets(request);
- printResult("预置位查询", result);
- }
-
- @Test
- public void testSnapshot() {
- System.out.println("\n>>> 测试抓拍");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.snapshot(request);
- printResult("抓拍", result);
-
- if (result.isSuccess()) {
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- System.out.println("\n抓拍图片URL: " + resultData.getStr("snapshotUrl"));
- }
- }
-
- @Test
- public void testStartPlayback() {
- System.out.println("\n>>> 测试历史回放");
-
- // 查询最近1小时的录像
- long endTime = System.currentTimeMillis() / 1000;
- long startTime = endTime - 13600; // 1小时前
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("startTime", startTime);
- data.set("endTime", endTime);
-
-
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.startPlayback(request);
- printResult("历史回放", result);
-
- if (result.isSuccess()) {
- System.out.println("\n回放地址已获取:");
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- JSONObject urls = resultData.getJSONObject("urls");
- if (urls != null) {
- System.out.println("FLV: " + urls.getStr("flv"));
- System.out.println("HLS: " + urls.getStr("hls"));
- }
- }
- }
-
- @Test
- public void testStopPlayback() {
- System.out.println("\n>>> 测试停止回放");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.stopPlayback(request);
- printResult("停止回放", result);
- }
-
- @Test
- public void testQueryGBRecords() {
- System.out.println("\n>>> 测试国标录像查询");
-
- // 查询最近24小时的国标录像
- long endTime = System.currentTimeMillis() / 1000;
- long startTime = endTime - 86400; // 24小时前
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("startTime",DateUtil.formatDateTime(DateUtil.offset(new Date(), DateField.HOUR,-78)));
- data.set("endTime", DateUtil.now());
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.queryGBRecords(request);
- printResult("国标录像查询", result);
- }
-
- @Test
- public void testStartGBRecordDownload() {
- System.out.println("\n>>> 测试开始下载国标录像");
-
- // 查询最近1小时的录像
- long endTime = System.currentTimeMillis() / 1000;
- long startTime = endTime - 3600; // 1小时前
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("startTime", startTime);
- data.set("endTime", endTime);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.startGBRecordDownload(request);
- printResult("开始下载国标录像", result);
-
- if (result.isSuccess()) {
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- String downloadId = resultData.getStr("downloadId");
- System.out.println("\n下载ID: " + downloadId);
- System.out.println("可使用此ID查询下载进度或停止下载");
- }
- }
-
- @Test
- public void testStopGBRecordDownload() {
- System.out.println("\n>>> 测试停止下载国标录像");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("stream", "your_stream_id"); // 需要从开始下载接口获取
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.stopGBRecordDownload(request);
- printResult("停止下载国标录像", result);
- }
-
- @Test
- public void testGetGBRecordDownloadProgress() {
- System.out.println("\n>>> 测试查询国标录像下载进度");
-
- JSONObject data = new JSONObject();
- data.set("channelId", CHANNEL_ID);
- data.set("stream", "your_stream_id"); // 需要从开始下载接口获取
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.getGBRecordDownloadProgress(request);
- printResult("查询国标录像下载进度", result);
-
- if (result.isSuccess()) {
- JSONObject resultData = JSONUtil.parseObj(result.getData());
- System.out.println("\n下载进度: " + resultData.getInt("progress") + "%");
- }
- }
-
- @Test
- public void testQueryCloudRecordDates() {
- System.out.println("\n>>> 测试查询云端录像日期列表");
-
- JSONObject data = new JSONObject();
- data.set("app", "rtp");
- data.set("stream", DEVICE_ID + "_" + CHANNEL_ID);
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.queryCloudRecordDates(request);
- printResult("查询云端录像日期列表", result);
- }
-
- @Test
- public void testQueryCloudRecords() {
- System.out.println("\n>>> 测试查询云端录像列表");
-
- JSONObject data = new JSONObject();
- data.set("app", "rtp");
- data.set("stream", DEVICE_ID + "_" + CHANNEL_ID);
- data.set("page", 1);
- data.set("count", 20);
- data.set("startTime", "2025-11-01 00:00:00");
- data.set("endTime", "2025-11-31 23:59:59");
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.queryCloudRecords(request);
- printResult("查询云端录像列表", result);
- }
-
- @Test
- public void testLoadCloudRecord() {
- System.out.println("\n>>> 测试加载云端录像文件");
-
- JSONObject data = new JSONObject();
- data.set("app", "rtp");
- data.set("stream", DEVICE_ID + "_" + CHANNEL_ID);
- data.set("cloudRecordId", 64);
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.loadCloudRecord(request);
- printResult("加载云端录像文件", result);
- }
-
- @Test
- public void testSeekCloudRecord() {
- System.out.println("\n>>> 测试定位云端录像进度");
-
- JSONObject data = new JSONObject();
- data.set("app", "rtp");
- data.set("stream", DEVICE_ID + "_" + CHANNEL_ID);
- data.set("seek", 60000); // 定位到60秒处
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.seekCloudRecord(request);
- printResult("定位云端录像进度", result);
- }
-
- @Test
- public void testSetCloudRecordSpeed() {
- System.out.println("\n>>> 测试设置云端录像倍速");
-
- JSONObject data = new JSONObject();
- data.set("app", "rtp");
- data.set("stream", DEVICE_ID + "_" + CHANNEL_ID);
- data.set("speed", 2.0); // 2倍速播放
-
- WvpDownRequest request = createWvpRequest(DEVICE_ID, data);
- R> result = wvpDeviceService.setCloudRecordSpeed(request);
- printResult("设置云端录像倍速", result);
- }
-
- /** 完整流程测试:设备列表 -> 通道列表 -> 直播 -> 云台 -> 停止 */
- @Test
- public void testCompleteFlow() {
- System.out.println("\n========== 完整流程测试 ==========");
-
- // 1. 查询设备列表
- System.out.println("\n步骤1: 查询设备列表");
- Map filters = new HashMap<>();
- filters.put("endpoint", WVP_BASE_URL);
- filters.put("token", API_KEY);
- filters.put("page", 1);
- filters.put("count", 5);
- R> devicesResult = wvpDeviceService.listDevices(INSTANCE_KEY, filters);
- printResult("设备列表", devicesResult);
-
- // 2. 查询通道列表
- System.out.println("\n步骤2: 查询通道列表");
- Map channelFilters = new HashMap<>();
- channelFilters.put("endpoint", WVP_BASE_URL);
- channelFilters.put("token", API_KEY);
- channelFilters.put("page", 1);
- channelFilters.put("count", 5);
- R> channelsResult = wvpDeviceService.listChannels(DEVICE_ID, channelFilters);
- printResult("通道列表", channelsResult);
-
- // 3. 开始直播
- System.out.println("\n步骤3: 开始直播");
- JSONObject previewData = new JSONObject();
- previewData.set("channelId", CHANNEL_ID);
- previewData.set("protocol", "flv");
- WvpDownRequest previewRequest = createWvpRequest(DEVICE_ID, previewData);
- R> previewResult = wvpDeviceService.startPreview(previewRequest);
- printResult("开始直播", previewResult);
-
- if (previewResult.isSuccess()) {
- // 4. 云台控制
- System.out.println("\n步骤4: 云台控制(向右转2秒)");
- JSONObject ptzData = new JSONObject();
- ptzData.set("channelId", CHANNEL_ID);
- ptzData.set("command", "right");
- ptzData.set("speed", 50);
- WvpDownRequest ptzRequest = createWvpRequest(DEVICE_ID, ptzData);
- R> ptzResult = wvpDeviceService.ptzControl(ptzRequest);
- printResult("云台控制", ptzResult);
-
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- }
-
- // 5. 停止云台
- System.out.println("\n步骤5: 停止云台");
- JSONObject stopPtzData = new JSONObject();
- stopPtzData.set("channelId", CHANNEL_ID);
- stopPtzData.set("command", "stop");
- stopPtzData.set("speed", 0);
- WvpDownRequest stopPtzRequest = createWvpRequest(DEVICE_ID, stopPtzData);
- wvpDeviceService.ptzControl(stopPtzRequest);
-
- // 6. 停止直播
- System.out.println("\n步骤6: 停止直播");
- JSONObject stopData = new JSONObject();
- stopData.set("channelId", CHANNEL_ID);
- WvpDownRequest stopRequest = createWvpRequest(DEVICE_ID, stopData);
- R> stopResult = wvpDeviceService.stopPreview(stopRequest);
- printResult("停止直播", stopResult);
- }
-
- System.out.println("\n========== 流程测试完成 ==========");
- }
-
- /** 完整录像流程测试:国标录像查询 -> 录像回放 -> 停止回放 */
- @Test
- public void testRecordCompleteFlow() {
- System.out.println("\n========== 完整录像流程测试 ==========");
-
- long endTime = System.currentTimeMillis() / 1000;
- long startTime = endTime - 86400; // 24小时前
-
- // 1. 查询国标录像
- System.out.println("\n步骤1: 查询国标录像");
- JSONObject queryData = new JSONObject();
- queryData.set("channelId", CHANNEL_ID);
- queryData.set("startTime", startTime);
- queryData.set("endTime", endTime);
- WvpDownRequest queryRequest = createWvpRequest(DEVICE_ID, queryData);
- R> queryResult = wvpDeviceService.queryGBRecords(queryRequest);
- printResult("国标录像查询", queryResult);
-
- // 2. 开始录像回放
- System.out.println("\n步骤2: 开始录像回放");
- JSONObject playbackData = new JSONObject();
- playbackData.set("channelId", CHANNEL_ID);
- playbackData.set("startTime", startTime);
- playbackData.set("endTime", endTime);
- WvpDownRequest playbackRequest = createWvpRequest(DEVICE_ID, playbackData);
- R> playbackResult = wvpDeviceService.startPlayback(playbackRequest);
- printResult("开始录像回放", playbackResult);
-
- if (playbackResult.isSuccess()) {
- // 3. 等待5秒
- try {
- System.out.println("\n等待5秒...");
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- }
-
- // 4. 停止回放
- System.out.println("\n步骤3: 停止录像回放");
- JSONObject stopData = new JSONObject();
- stopData.set("channelId", CHANNEL_ID);
- WvpDownRequest stopRequest = createWvpRequest(DEVICE_ID, stopData);
- R> stopResult = wvpDeviceService.stopPlayback(stopRequest);
- printResult("停止录像回放", stopResult);
- }
-
- System.out.println("\n========== 录像流程测试完成 ==========");
- }
-
- /** 云端录像完整流程测试 */
- @Test
- public void testCloudRecordCompleteFlow() {
- System.out.println("\n========== 云端录像完整流程测试 ==========");
-
- String app = "rtp";
- String stream = DEVICE_ID + "_" + CHANNEL_ID;
-
- // 1. 查询云端录像日期列表
- System.out.println("\n步骤1: 查询云端录像日期列表");
- JSONObject dateData = new JSONObject();
- dateData.set("app", app);
- dateData.set("stream", stream);
- WvpDownRequest dateRequest = createWvpRequest(DEVICE_ID, dateData);
- R> dateResult = wvpDeviceService.queryCloudRecordDates(dateRequest);
- printResult("云端录像日期列表", dateResult);
-
- // 2. 查询云端录像列表
- System.out.println("\n步骤2: 查询云端录像列表");
- JSONObject listData = new JSONObject();
- listData.set("app", app);
- listData.set("stream", stream);
- listData.set("page", 1);
- listData.set("count", 20);
- WvpDownRequest listRequest = createWvpRequest(DEVICE_ID, listData);
- R> listResult = wvpDeviceService.queryCloudRecords(listRequest);
- printResult("云端录像列表", listResult);
-
- // 3. 加载云端录像文件
- System.out.println("\n步骤3: 加载云端录像文件");
- long endTime = System.currentTimeMillis();
- long startTime = endTime - 3600000; // 1小时前
- JSONObject loadData = new JSONObject();
- loadData.set("app", app);
- loadData.set("stream", stream);
- loadData.set("startTime", startTime);
- loadData.set("endTime", endTime);
- WvpDownRequest loadRequest = createWvpRequest(DEVICE_ID, loadData);
- R> loadResult = wvpDeviceService.loadCloudRecord(loadRequest);
- printResult("加载云端录像文件", loadResult);
-
- if (loadResult.isSuccess()) {
- // 4. 设置倍速播放
- System.out.println("\n步骤4: 设置2倍速播放");
- JSONObject speedData = new JSONObject();
- speedData.set("app", app);
- speedData.set("stream", stream);
- speedData.set("speed", 2.0);
- WvpDownRequest speedRequest = createWvpRequest(DEVICE_ID, speedData);
- R> speedResult = wvpDeviceService.setCloudRecordSpeed(speedRequest);
- printResult("设置倍速播放", speedResult);
-
- // 5. 定位录像进度
- System.out.println("\n步骤5: 定位到60秒处");
- JSONObject seekData = new JSONObject();
- seekData.set("app", app);
- seekData.set("stream", stream);
- seekData.set("seek", 60000); // 60秒
- WvpDownRequest seekRequest = createWvpRequest(DEVICE_ID, seekData);
- R> seekResult = wvpDeviceService.seekCloudRecord(seekRequest);
- printResult("定位录像进度", seekResult);
- }
-
- System.out.println("\n========== 云端录像流程测试完成 ==========");
- }
-}
diff --git a/cn-universal-protocol/cn-wvp-protocol/wvp_camera_thing_model.json b/cn-universal-protocol/cn-wvp-protocol/wvp_camera_thing_model.json
deleted file mode 100644
index 13f3b2c..0000000
--- a/cn-universal-protocol/cn-wvp-protocol/wvp_camera_thing_model.json
+++ /dev/null
@@ -1,123 +0,0 @@
-{
- "tags": [],
- "events": [
- {
- "id": "online",
- "name": "设备上线",
- "valueType": {"type": "string"}
- },
- {
- "id": "offline",
- "name": "设备下线",
- "valueType": {"type": "string"}
- }
- ],
- "functions": [
- {
- "id": "cameraLiveStream",
- "name": "实时预览",
- "config": false,
- "inputs": [
- {"id": "deviceId", "name": "设备ID", "valueType": {"type": "string"}},
- {"id": "channelId", "name": "通道ID", "valueType": {"type": "string"}},
- {"id": "streamType", "name": "码流类型", "valueType": {"type": "enum", "elements": [{"text": "主码流", "value": "main"}, {"text": "子码流", "value": "sub"}]}}
- ],
- "output": {}
- },
- {
- "id": "cameraTurn",
- "name": "云台控制",
- "config": false,
- "inputs": [
- {"id": "deviceId", "name": "设备ID", "valueType": {"type": "string"}},
- {"id": "channelId", "name": "通道ID", "valueType": {"type": "string"}},
- {"id": "command", "name": "控制命令", "valueType": {"type": "string"}},
- {"id": "speed", "name": "速度", "valueType": {"type": "int"}}
- ],
- "output": {}
- },
- {
- "id": "cameraPlayback",
- "name": "录像回放",
- "config": false,
- "inputs": [
- {"id": "deviceId", "name": "设备ID", "valueType": {"type": "string"}},
- {"id": "channelId", "name": "通道ID", "valueType": {"type": "string"}},
- {"id": "startTime", "name": "开始时间", "valueType": {"type": "long"}},
- {"id": "endTime", "name": "结束时间", "valueType": {"type": "long"}}
- ],
- "output": {}
- },
- {
- "id": "cameraSnapshot",
- "name": "抓拍",
- "config": false,
- "inputs": [
- {"id": "deviceId", "name": "设备ID", "valueType": {"type": "string"}},
- {"id": "channelId", "name": "通道ID", "valueType": {"type": "string"}}
- ],
- "output": {}
- },
- {
- "id": "queryRecords",
- "name": "查询录像",
- "config": false,
- "inputs": [
- {"id": "deviceId", "name": "设备ID", "valueType": {"type": "string"}},
- {"id": "channelId", "name": "通道ID", "valueType": {"type": "string"}},
- {"id": "startTime", "name": "开始时间", "valueType": {"type": "string"}},
- {"id": "endTime", "name": "结束时间", "valueType": {"type": "string"}}
- ],
- "output": {}
- },
- {
- "id": "queryCloudRecords",
- "name": "查询云端录像",
- "config": false,
- "inputs": [
- {"id": "app", "name": "应用名", "valueType": {"type": "string"}},
- {"id": "stream", "name": "流ID", "valueType": {"type": "string"}},
- {"id": "page", "name": "页码", "valueType": {"type": "int"}},
- {"id": "count", "name": "每页数量", "valueType": {"type": "int"}}
- ],
- "output": {}
- },
- {
- "id": "loadCloudRecord",
- "name": "加载云端录像",
- "config": false,
- "inputs": [
- {"id": "app", "name": "应用名", "valueType": {"type": "string"}},
- {"id": "stream", "name": "流ID", "valueType": {"type": "string"}},
- {"id": "cloudRecordId", "name": "录像ID", "valueType": {"type": "int"}}
- ],
- "output": {}
- }
- ],
- "properties": [
- {
- "id": "deviceStatus",
- "mode": "r",
- "name": "设备状态",
- "config": false,
- "source": "device",
- "valueType": {"type": "enum", "elements": [{"text": "在线", "value": "online"}, {"text": "离线", "value": "offline"}]}
- },
- {
- "id": "manufacturer",
- "mode": "r",
- "name": "厂商",
- "config": false,
- "source": "device",
- "valueType": {"type": "string"}
- },
- {
- "id": "model",
- "mode": "r",
- "name": "型号",
- "config": false,
- "source": "device",
- "valueType": {"type": "string"}
- }
- ]
-}
diff --git a/cn-universal-protocol/pom.xml b/cn-universal-protocol/pom.xml
index f4c9d30..4f292c5 100644
--- a/cn-universal-protocol/pom.xml
+++ b/cn-universal-protocol/pom.xml
@@ -15,8 +15,6 @@
cn-universal-mqtt-protocol
cn-universal-http-protocol
-
- cn-wvp-protocol
diff --git a/cn-universal-web/pom.xml b/cn-universal-web/pom.xml
index 7e1cb10..17d2c59 100644
--- a/cn-universal-web/pom.xml
+++ b/cn-universal-web/pom.xml
@@ -163,11 +163,6 @@
org.springframework.boot
spring-boot-starter-validation
-
- cn.universal.iot
- cn-wvp-protocol
- ${project.version}
-
cn.universal.iot
cn-universal-mqtt-protocol