diff --git a/cn-universal-protocol/cn-wvp-protocol/pom.xml b/cn-universal-protocol/cn-wvp-protocol/pom.xml deleted file mode 100644 index fdc19fe..0000000 --- a/cn-universal-protocol/cn-wvp-protocol/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - 4.0.0 - - cn-universal-protocol - cn.universal.iot - 1.5-SNAPSHOT - - cn-wvp-protocol - cn-wvp-protocol - WVP 视频平台协议下发转换模块 - - - 21 - 21 - UTF-8 - - - - - cn.universal.iot - cn-universal-common - ${project.version} - - - cn.universal.iot - cn-universal-core - ${project.version} - - - cn.universal.iot - cn-universal-persistence - ${project.version} - - - cn.universal.iot - cn-universal-dm - ${project.version} - - - org.springframework.boot - spring-boot-starter - - - org.junit.jupiter - junit-jupiter - test - - - diff --git a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/adapter/WvpPlatformAdapter.java b/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/adapter/WvpPlatformAdapter.java deleted file mode 100644 index a52b9f0..0000000 --- a/cn-universal-protocol/cn-wvp-protocol/src/main/java/cn/wvp/protocol/adapter/WvpPlatformAdapter.java +++ /dev/null @@ -1,765 +0,0 @@ -/* - * - * Copyright (c) 2025, NexIoT. All Rights Reserved. - * - * @Description: WVP平台适配器实现 - * @Author: gitee.com/NexIoT - * - */ -package cn.wvp.protocol.adapter; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONArray; -import cn.hutool.json.JSONObject; -import cn.universal.common.domain.R; -import cn.universal.dm.device.service.action.IoTDeviceActionAfterService; -import cn.universal.dm.video.VideoPlatformAdapter; -import cn.universal.dm.video.VideoPlatformInstanceAdapter; -import cn.universal.persistence.entity.VideoPlatformInstance; -import cn.universal.persistence.mapper.VideoPlatformInstanceMapper; -import cn.wvp.protocol.entity.WvpDownRequest; -import cn.wvp.protocol.service.WvpDeviceService; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Component; - -/** WVP平台适配器实现 将WvpDeviceService的能力适配到VideoPlatformAdapter统一接口 */ -@Slf4j -@Component("wvpPlatformAdapter") -@RequiredArgsConstructor -public class WvpPlatformAdapter implements VideoPlatformAdapter, VideoPlatformInstanceAdapter { - - private final WvpDeviceService wvpDeviceService; - - private final IoTDeviceActionAfterService ioTDeviceActionAfterService; - - private final VideoPlatformInstanceMapper videoPlatformInstanceMapper; - - @Override - public String getSupportedPlatformType() { - return "wvp"; - } - - /** 构建通用filters参数 */ - private Map buildFilters(VideoPlatformInstance instance) { - Map filters = new HashMap<>(); - filters.put("endpoint", instance.getEndpoint()); - - // 从auth字段中提取token - if (instance.getAuth() != null && !instance.getAuth().isEmpty()) { - try { - JSONObject auth = new JSONObject(instance.getAuth()); - if (auth.containsKey("token")) { - filters.put("token", auth.getStr("token")); - } else if (auth.containsKey("apiKey")) { - filters.put("token", auth.getStr("apiKey")); - } - } catch (Exception e) { - log.warn("解析WVP auth配置失败: {}", e.getMessage()); - } - } - - return filters; - } - - /** 构建WvpDownRequest */ - private WvpDownRequest buildDownRequest( - VideoPlatformInstance instance, String deviceId, JSONObject data) { - WvpDownRequest request = new WvpDownRequest(); - request.setDeviceId(deviceId); - request.setData(data); - request.setWvpRequestData(buildFilters(instance)); - return request; - } - - @Override - public Map testConnection(VideoPlatformInstance instance) { - Map result = new HashMap<>(); - long start = System.currentTimeMillis(); - - try { - Map filters = buildFilters(instance); - filters.put("page", 1); - filters.put("count", 1); - - R response = wvpDeviceService.listDevices(instance.getInstanceKey(), filters); - long latency = System.currentTimeMillis() - start; - - if (response.isSuccess()) { - result.put("reachable", true); - result.put("latencyMs", latency); - result.put("message", "WVP连接正常"); - } else { - result.put("reachable", false); - result.put("latencyMs", latency); - result.put("message", "WVP响应异常:" + response.getMsg()); - } - } catch (Exception e) { - long latency = System.currentTimeMillis() - start; - log.error("WVP连接测试失败:{}", e.getMessage()); - result.put("reachable", false); - result.put("latencyMs", latency); - result.put("message", "连接失败:" + e.getMessage()); - } - - return result; - } - - @Override - public List> listDevices( - VideoPlatformInstance instance, Map filters) { - List> devices = new ArrayList<>(); - - try { - Map mergedFilters = buildFilters(instance); - if (filters != null) { - mergedFilters.putAll(filters); - } - - // 如果没有指定分页参数,使用默认值 - if (!mergedFilters.containsKey("page")) { - mergedFilters.put("page", 1); - } - if (!mergedFilters.containsKey("count")) { - mergedFilters.put("count", 100); - } - - R response = wvpDeviceService.listDevices(instance.getInstanceKey(), mergedFilters); - - if (response.isSuccess() && response.getData() != null) { - - // 转换响应数据格式 - Object data = response.getData(); - if (data instanceof Map) { - JSONObject dataJson = new JSONObject(data); - if (dataJson.containsKey("list")) { - JSONArray list = dataJson.getJSONArray("list"); - for (int i = 0; i < list.size(); i++) { - JSONObject item = list.getJSONObject(i); - Map device = new HashMap<>(); - // 主表公共字段 - String deviceId = item.getStr("deviceId"); - device.put("deviceId", deviceId); - device.put("name", item.getStr("name", "")); - device.put("manufacturer", item.getStr("manufacturer", "")); - device.put("model", item.getStr("model", "")); - // 根据onLine字段设置状态 - Boolean onLine = item.getBool("onLine", false); - String status = onLine ? "online" : "offline"; - device.put("status", status); - device.put("channelCount", item.getInt("channelCount", 0)); - device.put("ip", item.getStr("ip", "")); - device.put("port", item.getInt("port", 0)); - // WVP扩展表特有字段 - device.put("charset", item.getStr("charset", "")); - device.put("transport", item.getStr("transport", "")); - device.put("streamMode", item.getStr("streamMode", "")); - device.put("hostAddress", item.getStr("hostAddress", "")); - device.put("registerTime", item.getStr("registerTime", "")); - device.put("keepaliveTime", item.getStr("keepaliveTime", "")); - device.put("expires", item.getInt("expires", 3600)); - device.put("mediaServerId", item.getStr("mediaServerId", "")); - - // 只在forceSync时查询通道列表(用于同步写入数据库) - // 常规查询应该从video_platform_channel表读取 - boolean isForceSync = - mergedFilters.containsKey("forceSync") - && "true".equalsIgnoreCase(String.valueOf(mergedFilters.get("forceSync"))); - if (isForceSync) { - List> channelList = getDeviceChannels(instance, deviceId); - device.put("channelList", channelList); - } - - devices.add(device); - } - } - } - } else { - log.warn("WVP设备列表查询失败:{}", response.getMsg()); - } - } catch (Exception e) { - log.error("WVP设备列表查询异常:{}", e.getMessage(), e); - } - - return devices; - } - - @Override - public Map getStreamUrl( - VideoPlatformInstance instance, String deviceId, String channelId, String streamType) { - Map urls = new HashMap<>(); - - try { - JSONObject data = new JSONObject(); - data.set("channelId", channelId != null ? channelId : deviceId); - data.set("protocol", "flv"); // 默认FLV - - WvpDownRequest request = buildDownRequest(instance, deviceId, data); - R response = wvpDeviceService.startPreview(request); - - log.info("WVP预览响应: success={}, data={}", response.isSuccess(), response.getData()); - - if (response.isSuccess() && response.getData() != null) { - JSONObject result = new JSONObject(response.getData()); - log.info("WVP预览结果: {}", result.toString()); - - if (result.containsKey("urls")) { - JSONObject urlsObj = result.getJSONObject("urls"); - // 遍历所有返回的流地址 - for (String key : urlsObj.keySet()) { - Object value = urlsObj.get(key); - // 过滤掉null值 - if (value != null && !"null".equals(String.valueOf(value))) { - urls.put(key, String.valueOf(value)); - } - } - } else { - // 如果没有urls字段,直接使用根对象的所有流地址字段 - // 常见的流地址字段 - String[] streamKeys = { - "flv", - "https_flv", - "ws_flv", - "wss_flv", - "fmp4", - "https_fmp4", - "ws_fmp4", - "wss_fmp4", - "hls", - "https_hls", - "ws_hls", - "wss_hls", - "ts", - "https_ts", - "ws_ts", - "wss_ts", - "rtmp", - "rtmps", - "rtsp", - "rtsps", - "rtc", - "rtcs", - "webrtc" - }; - - for (String key : streamKeys) { - if (result.containsKey(key)) { - Object value = result.get(key); - // 过滤掉null值 - if (value != null && !"null".equals(String.valueOf(value))) { - urls.put(key, String.valueOf(value)); - } - } - } - } - log.info("WVP解析后的URLs: {}", urls); - } - } catch (Exception e) { - log.error("WVP播放地址获取异常:{}", e.getMessage(), e); - } - ioTDeviceActionAfterService.online(instance.getInstanceKey(), deviceId); - return urls; - } - - @Override - public void controlPTZ( - VideoPlatformInstance instance, - String extDeviceId, - String channelId, - String command, - int speed) { - try { - JSONObject data = new JSONObject(); - data.set("channelId", channelId); - data.set("command", command); - data.set("speed", speed); - - WvpDownRequest request = buildDownRequest(instance, extDeviceId, data); - R response = wvpDeviceService.ptzControl(request); - - if (!response.isSuccess()) { - log.error("WVP PTZ控制失败:{}", response.getMsg()); - } - } catch (Exception e) { - log.error("WVP PTZ控制异常:{}", e.getMessage(), e); - } - } - - @Override - public List> queryRecords( - VideoPlatformInstance instance, - String extDeviceId, - String channelId, - long startTime, - long endTime) { - List> records = new ArrayList<>(); - - try { - // WVP要求时间格式为 yyyy-MM-dd HH:mm:ss - java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String reqStartTime = sdf.format(new java.util.Date(startTime)); - String reqEndTime = sdf.format(new java.util.Date(endTime)); - - JSONObject data = new JSONObject(); - data.set("channelId", channelId); - data.set("startTime", reqStartTime); - data.set("endTime", reqEndTime); - - WvpDownRequest request = buildDownRequest(instance, extDeviceId, data); - R response = wvpDeviceService.queryGBRecords(request); - - if (response.isSuccess() && response.getData() != null) { - // 转换响应数据格式 - Object dataObj = response.getData(); - if (dataObj instanceof Map) { - JSONObject dataJson = new JSONObject(dataObj); - if (dataJson.containsKey("recordList")) { - // WVP返回的录像列表在recordList字段中 - JSONArray list = dataJson.getJSONArray("recordList"); - - for (int i = 0; i < list.size(); i++) { - JSONObject item = list.getJSONObject(i); - Map record = new HashMap<>(); - - // 生成唯一ID - record.put("id", i + 1); - - // 将WVP的时间字符串转为时间戳(毫秒) - try { - String respStartTime = item.getStr("startTime", ""); - String respEndTime = item.getStr("endTime", ""); - if (!respStartTime.isEmpty()) { - record.put("startTime", sdf.parse(respStartTime).getTime()); - } - if (!respEndTime.isEmpty()) { - record.put("endTime", sdf.parse(respEndTime).getTime()); - } - } catch (Exception e) { - log.warn("录像时间解析失败: {}", e.getMessage()); - } - - // 文件大小转换为可读格式 - long fileSize = item.getLong("fileSize", 0L); - record.put("fileSize", formatFileSize(fileSize)); - record.put("fileSizeBytes", fileSize); - - // 其他字段 - record.put("name", item.getStr("name", "")); - record.put("filePath", item.getStr("filePath", "")); - record.put("address", item.getStr("address", "")); - record.put("secrecy", item.getInt("secrecy", 0)); - record.put("type", item.getStr("type", "time")); - - records.add(record); - } - } - } - } - } catch (Exception e) { - log.error("WVP录像查询异常:{}", e.getMessage(), e); - } - - return records; - } - - @Override - public List> listOrganizations( - VideoPlatformInstance instance, Map filters) { - // WVP无组织体系,返回空列表 - return List.of(); - } - - @Override - public void subscribe(VideoPlatformInstance instance, List topics, String callback) { - // WVP订阅暂不实现,通常通过Webhook配置 - log.info( - "WVP订阅:instanceKey={}, topics={}, callback={}", - instance.getInstanceKey(), - topics, - callback); - } - - @Override - public void unsubscribe(VideoPlatformInstance instance, List topics) { - log.info("WVP取消订阅:instanceKey={}, topics={}", instance.getInstanceKey(), topics); - } - - @Override - public Map getPlaybackUrl( - VideoPlatformInstance instance, - String deviceId, - String channelId, - long startTime, - long endTime) { - Map result = new HashMap<>(); - - try { - JSONObject data = new JSONObject(); - data.set("channelId", channelId != null ? channelId : deviceId); - data.set("startTime", startTime); - data.set("endTime", endTime); - - WvpDownRequest request = buildDownRequest(instance, deviceId, data); - R response = wvpDeviceService.startPlayback(request); - - log.info("WVP回放响应: success={}, data={}", response.isSuccess(), response.getData()); - - if (response.isSuccess() && response.getData() != null) { - // 解析响应数据 - Object responseData = response.getData(); - if (responseData instanceof Map) { - @SuppressWarnings("unchecked") - Map dataMap = (Map) responseData; - - // 直接使用返回的所有字段(包括流地址和其他字段) - result.putAll(dataMap); - - log.info("WVP解析后的回放数据: {}", result); - } else { - log.warn("WVP回放响应数据格式异常: {}", responseData); - } - } else { - log.error("WVP回放失败: {}", response.getMsg()); - throw new RuntimeException("WVP回放失败: " + response.getMsg()); - } - } catch (Exception e) { - log.error("WVP回放地址获取异常:{}", e.getMessage(), e); - throw new RuntimeException("获取回放地址失败: " + e.getMessage(), e); - } - - return result; - } - - /** 获取设备的通道列表 */ - private List> getDeviceChannels( - VideoPlatformInstance instance, String deviceId) { - List> channels = new ArrayList<>(); - - try { - Map channelFilters = buildFilters(instance); - channelFilters.put("page", 1); - channelFilters.put("count", 100); // 通道一般不会太多 - - R response = wvpDeviceService.listChannels(deviceId, channelFilters); - - if (response.isSuccess() && response.getData() != null) { - Object data = response.getData(); - if (data instanceof Map) { - JSONObject dataJson = new JSONObject(data); - if (dataJson.containsKey("list")) { - JSONArray list = dataJson.getJSONArray("list"); - for (int i = 0; i < list.size(); i++) { - JSONObject item = list.getJSONObject(i); - Map channel = new HashMap<>(); - - // 通道公共字段 - channel.put("channelId", item.getStr("deviceId")); // WVP中通道的deviceId就是通道ID - channel.put("name", item.getStr("name", "")); - channel.put("manufacturer", item.getStr("manufacturer", "")); - channel.put("model", item.getStr("model", "")); - channel.put("owner", item.getStr("owner", "")); - channel.put("civilCode", item.getStr("civilCode", "")); - channel.put("address", item.getStr("address", "")); - channel.put("parental", item.getInt("parental", 0)); - channel.put("parentId", item.getStr("parentId", "")); - channel.put("safetyWay", item.getInt("safetyWay")); - channel.put("registerWay", item.getInt("registerWay")); - channel.put("secrecy", item.getInt("secrecy", 0)); - channel.put("ipAddress", item.getStr("ipAddress", "")); - channel.put("port", item.getInt("port")); - channel.put("status", item.getStr("status", "OFF")); - channel.put("longitude", item.getStr("longitude")); - channel.put("latitude", item.getStr("latitude")); - channel.put("ptzType", item.getInt("ptzType", 0)); - channel.put("positionType", item.getInt("positionType")); - - // WVP通道级特有字段 - channel.put("streamId", item.getStr("streamId", "")); - channel.put("hasAudio", item.getBool("hasAudio", false)); - channel.put("subCount", item.getInt("subCount", 0)); - channel.put("streamIdentification", item.getStr("streamIdentification", "")); - channel.put("channelType", item.getInt("channelType", 0)); - - channels.add(channel); - } - } - } - } - } catch (Exception e) { - log.error("WVP通道列表查询异常:deviceId={}, error={}", deviceId, e.getMessage()); - } - - return channels; - } - - /** 格式化文件大小 */ - private String formatFileSize(long bytes) { - if (bytes < 1024) { - return bytes + " B"; - } else if (bytes < 1024 * 1024) { - return String.format("%.2f KB", bytes / 1024.0); - } else if (bytes < 1024 * 1024 * 1024) { - return String.format("%.2f MB", bytes / (1024.0 * 1024)); - } else { - return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024)); - } - } - - // ==================== 国标录像下载公开方法 ==================== - - /** 开始国标录像下载 */ - public R> startGBRecordDownload( - VideoPlatformInstance instance, String deviceId, String channelId, Map data) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("channelId", channelId); - - // 从 data 中获取参数 - if (data.containsKey("startTime")) { - requestData.set("startTime", String.valueOf(data.get("startTime"))); - } - if (data.containsKey("endTime")) { - requestData.set("endTime", String.valueOf(data.get("endTime"))); - } - if (data.containsKey("downloadSpeed")) { - requestData.set("downloadSpeed", data.get("downloadSpeed")); - } - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.startGBRecordDownload(request); - - if (response.isSuccess() && response.getData() != null) { - @SuppressWarnings("unchecked") - Map result = (Map) 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); - } - } - - /** 停止国标录像下载 */ - public R stopGBRecordDownload( - VideoPlatformInstance instance, String deviceId, String channelId, Map data) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("channelId", channelId); - if (data.containsKey("stream")) { - requestData.set("stream", String.valueOf(data.get("stream"))); - } - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.stopGBRecordDownload(request); - - if (response.isSuccess()) { - return R.ok(); - } - return R.error(response.getMsg()); - } catch (Exception e) { - log.error("WVP停止录像下载失败:{}", e.getMessage(), e); - return R.error("停止下载失败:" + e.getMessage()); - } - } - - /** 获取国标录像下载进度 */ - public R> getGBRecordDownloadProgress( - VideoPlatformInstance instance, String deviceId, String channelId, String stream) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("channelId", channelId); - requestData.set("stream", stream); - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.getGBRecordDownloadProgress(request); - - if (response.isSuccess() && response.getData() != null) { - @SuppressWarnings("unchecked") - Map result = (Map) 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); - } - } - - // ==================== 云端录像公开方法 ==================== - - /** 查询云端录像日期列表 */ - public R> queryCloudRecordDates( - VideoPlatformInstance instance, - String deviceId, - String channelId, - Map params) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("app", params.getOrDefault("app", "rtp")); - requestData.set("stream", deviceId + "_" + channelId); - if (params.containsKey("year")) { - requestData.set("year", Integer.parseInt(params.get("year"))); - } - if (params.containsKey("month")) { - requestData.set("month", Integer.parseInt(params.get("month"))); - } - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.queryCloudRecordDates(request); - - if (response.isSuccess() && response.getData() != null) { - @SuppressWarnings("unchecked") - List dates = (List) response.getData(); - return R.ok(dates); - } - return R.error(response.getMsg(), null); - } catch (Exception e) { - log.error("WVP云端录像日期查询失败:{}", e.getMessage(), e); - return R.error("查询失败:" + e.getMessage(), null); - } - } - - /** 查询云端录像列表 */ - public R> queryCloudRecords( - VideoPlatformInstance instance, - String deviceId, - String channelId, - Map params) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("app", params.getOrDefault("app", "rtp")); - requestData.set("stream", deviceId + "_" + channelId); - requestData.set("page", Integer.parseInt(params.getOrDefault("page", "1"))); - requestData.set("count", Integer.parseInt(params.getOrDefault("count", "20"))); - if (params.containsKey("startTime")) { - requestData.set("startTime", params.get("startTime")); - } - if (params.containsKey("endTime")) { - requestData.set("endTime", params.get("endTime")); - } - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.queryCloudRecords(request); - - if (response.isSuccess() && response.getData() != null) { - @SuppressWarnings("unchecked") - Map result = (Map) 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); - } - } - - /** 加载云端录像文件 */ - public R> loadCloudRecord( - VideoPlatformInstance instance, String deviceId, String channelId, Map data) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("app", data.getOrDefault("app", "rtp")); - requestData.set("stream", deviceId + "_" + channelId); - if (data.containsKey("cloudRecordId")) { - requestData.set("cloudRecordId", data.get("cloudRecordId")); - } - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.loadCloudRecord(request); - - if (response.isSuccess() && response.getData() != null) { - @SuppressWarnings("unchecked") - Map result = (Map) 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); - } - } - - /** 云端录像定位 */ - public R seekCloudRecord( - VideoPlatformInstance instance, String deviceId, String channelId, Map data) { - try { - JSONObject requestData = new JSONObject(); - requestData.putAll(data); - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.seekCloudRecord(request); - - if (response.isSuccess()) { - return R.ok(); - } - return R.error(response.getMsg()); - } catch (Exception e) { - log.error("WVP云端录像定位失败:{}", e.getMessage(), e); - return R.error("定位失败:" + e.getMessage()); - } - } - - /** 设置云端录像倍速 */ - public R setCloudRecordSpeed( - VideoPlatformInstance instance, String deviceId, String channelId, Map data) { - try { - JSONObject requestData = new JSONObject(); - requestData.putAll(data); - - WvpDownRequest request = buildDownRequest(instance, deviceId, requestData); - R response = wvpDeviceService.setCloudRecordSpeed(request); - - if (response.isSuccess()) { - return R.ok(); - } - return R.error(response.getMsg()); - } catch (Exception e) { - log.error("WVP云端录像倍速设置失败:{}", e.getMessage(), e); - return R.error("设置倍速失败:" + e.getMessage()); - } - } - - /** 获取云端录像下载地址 */ - public R> getCloudRecordPlayPath( - VideoPlatformInstance instance, Integer recordId) { - try { - JSONObject requestData = new JSONObject(); - requestData.set("recordId", recordId); - - WvpDownRequest request = buildDownRequest(instance, null, requestData); - R response = wvpDeviceService.getCloudRecordPlayPath(request); - - if (response.isSuccess() && response.getData() != null) { - @SuppressWarnings("unchecked") - Map result = (Map) 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