|
|
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pms.controller.admin.hikvision;
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|
|
+import cn.iocoder.yudao.module.pms.controller.admin.hikvision.vo.HikvisionPtzControlReqVO;
|
|
|
import cn.iocoder.yudao.module.pms.controller.admin.hikvision.vo.HikvisionTreeNodeRespVO;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
@@ -15,10 +16,13 @@ import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
+import javax.validation.Valid;
|
|
|
import javax.validation.constraints.NotBlank;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
@@ -52,6 +56,14 @@ public class HikvisionController {
|
|
|
private static final String SUB_REGIONS_ADDRESS = "/api/resource/v2/regions/subRegions";
|
|
|
/** 根据区域编号查询直属资源,不会查询子区域中的资源。 */
|
|
|
private static final String SUB_RESOURCES_ADDRESS = "/api/irds/v2/resource/subResources";
|
|
|
+ /** 获取监控点实时预览地址。 */
|
|
|
+ private static final String PREVIEW_URL_ADDRESS = "/api/video/v2/cameras/previewURLs";
|
|
|
+ /** 获取监控点对讲地址。 */
|
|
|
+ private static final String TALK_URL_ADDRESS = "/api/video/v1/cameras/talkURLs";
|
|
|
+ /** 根据监控点编号进行云台控制。 */
|
|
|
+ private static final String PTZ_CONTROL_ADDRESS = "/api/video/v1/ptzs/controlling";
|
|
|
+ /** Web 页面通过海康 H5player 使用 WebSocket Secure 协议。 */
|
|
|
+ private static final String H5PLAYER_PROTOCOL = "wss";
|
|
|
/** 返回给前端的区域节点类型。 */
|
|
|
private static final String NODE_TYPE_REGION = "region";
|
|
|
/** 返回给前端的监控点节点类型。 */
|
|
|
@@ -97,6 +109,106 @@ public class HikvisionController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取监控点的 WSS 实时预览地址。
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * 海康接口除 {@code cameraIndexCode} 外的参数均为可选参数。这里固定传入
|
|
|
+ * {@code protocol=wss},并将前端选择的 {@code streamType} 原样传给海康平台。
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param cameraIndexCode 监控点唯一标识
|
|
|
+ * @param streamType 码流类型;0 为主码流,1 为子码流,默认主码流
|
|
|
+ * @return WSS 实时预览地址
|
|
|
+ */
|
|
|
+ @GetMapping("/preview-url")
|
|
|
+ @Operation(summary = "获取海康监控点 WSS 实时预览地址")
|
|
|
+ public CommonResult<String> getPreviewUrl(
|
|
|
+ @Parameter(description = "监控点唯一标识", required = true) @RequestParam("cameraIndexCode") @NotBlank(message = "监控点编号不能为空") String cameraIndexCode,
|
|
|
+ @Parameter(description = "码流类型:0 主码流,1 子码流", example = "0") @RequestParam(value = "streamType", defaultValue = "0") Integer streamType) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
+ params.put("cameraIndexCode", cameraIndexCode);
|
|
|
+ params.put("streamType", streamType);
|
|
|
+ params.put("protocol", H5PLAYER_PROTOCOL);
|
|
|
+ JSONObject data = parseArtemisData(invokeArtemis(PREVIEW_URL_ADDRESS, params));
|
|
|
+ String url = data.getString("url");
|
|
|
+ if (StrUtil.isBlank(url)) {
|
|
|
+ throw new IllegalStateException("海康预览地址响应缺少 url");
|
|
|
+ }
|
|
|
+ return success(url);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取海康监控点预览地址失败,cameraIndexCode: {}, streamType: {}",
|
|
|
+ cameraIndexCode, streamType, e);
|
|
|
+ return error(500, "获取海康监控点预览地址失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取监控点的 WSS 对讲地址。
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * 海康对讲地址有效期为 5 分钟。接口固定传入 {@code protocol=wss},传输协议使用平台默认的
|
|
|
+ * TCP;前端应在开始对讲时调用本接口获取最新地址。
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param cameraIndexCode 监控点唯一标识
|
|
|
+ * @return WSS 对讲地址
|
|
|
+ */
|
|
|
+ @GetMapping("/talk-url")
|
|
|
+ @Operation(summary = "获取海康监控点 WSS 对讲地址")
|
|
|
+ public CommonResult<String> getTalkUrl(
|
|
|
+ @Parameter(description = "监控点唯一标识", required = true) @RequestParam("cameraIndexCode") @NotBlank(message = "监控点编号不能为空") String cameraIndexCode) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
+ params.put("cameraIndexCode", cameraIndexCode);
|
|
|
+ params.put("protocol", H5PLAYER_PROTOCOL);
|
|
|
+ JSONObject data = parseArtemisData(invokeArtemis(TALK_URL_ADDRESS, params));
|
|
|
+ String url = data.getString("url");
|
|
|
+ if (StrUtil.isBlank(url)) {
|
|
|
+ throw new IllegalStateException("海康对讲地址响应缺少 url");
|
|
|
+ }
|
|
|
+ return success(url);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取海康监控点对讲地址失败,cameraIndexCode: {}", cameraIndexCode, e);
|
|
|
+ return error(500, "获取海康监控点对讲地址失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 控制监控点云台。
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * speed 和 presetIndex 是可选参数,仅在前端传值时转发给海康平台,避免不支持这些参数的命令
|
|
|
+ * 收到无意义字段。持续动作由前端先发送 action=0 开始,再发送 action=1 停止。
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param reqVO 云台控制参数
|
|
|
+ * @return 是否控制成功
|
|
|
+ */
|
|
|
+ @PostMapping("/ptz-control")
|
|
|
+ @Operation(summary = "控制海康监控点云台")
|
|
|
+ public CommonResult<Boolean> controlPtz(@Valid @RequestBody HikvisionPtzControlReqVO reqVO) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
+ params.put("cameraIndexCode", reqVO.getCameraIndexCode());
|
|
|
+ params.put("action", reqVO.getAction());
|
|
|
+ params.put("command", reqVO.getCommand());
|
|
|
+ if (reqVO.getSpeed() != null) {
|
|
|
+ params.put("speed", reqVO.getSpeed());
|
|
|
+ }
|
|
|
+ if (reqVO.getPresetIndex() != null) {
|
|
|
+ params.put("presetIndex", reqVO.getPresetIndex());
|
|
|
+ }
|
|
|
+ parseArtemisData(invokeArtemis(PTZ_CONTROL_ADDRESS, params));
|
|
|
+ return success(true);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("控制海康监控点云台失败,cameraIndexCode: {}, action: {}, command: {}",
|
|
|
+ reqVO.getCameraIndexCode(), reqVO.getAction(), reqVO.getCommand(), e);
|
|
|
+ return error(500, "控制海康监控点云台失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取根区域,并将根区域的下一层节点放入 children。
|
|
|
*
|