From d68181ce2faef4821d6d8a8ffb8027480a6262c3 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Wed, 05 Nov 2025 17:01:20 +0800
Subject: [PATCH] 2025-11-5 zwy websockeet增加Type:livestream,开启机场和飞行器的直播接口, 增加LiveStreamHandler对开启直播和关闭直播的处理; redis增加WEBSOCKET_VideoId_PREFIX,存储videoid,关闭直播功能时使用;
---
ard-sample/src/main/java/com/ard/sample/component/websocket/handler/DockWebSocketHandler.java | 21 ++++++
ard-sample/src/main/java/com/ard/sample/component/websocket/enums/MessageType.java | 14 +++-
ard-sample/src/main/java/com/ard/sample/common/model/ResponseResult.java | 2
ard-common/src/main/java/com/ard/common/core/redis/RedisConst.java | 2
ard-sample/src/main/java/com/ard/sample/manage/service/impl/DockOnlineServiceImpl.java | 2
ard-sample/src/main/java/com/ard/sample/component/websocket/handler/LiveStreamHandler.java | 138 ++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 173 insertions(+), 6 deletions(-)
diff --git a/ard-common/src/main/java/com/ard/common/core/redis/RedisConst.java b/ard-common/src/main/java/com/ard/common/core/redis/RedisConst.java
index f3c7ec0..b408979 100644
--- a/ard-common/src/main/java/com/ard/common/core/redis/RedisConst.java
+++ b/ard-common/src/main/java/com/ard/common/core/redis/RedisConst.java
@@ -19,6 +19,8 @@
public static final Integer WEBSOCKET_ALIVE_SECOND = 60 * 60 * 24;
+ public static final String WEBSOCKET_VideoId_PREFIX = "videoid" + DELIMITER;
+
public static final String DEVICE_ONLINE_PREFIX = "online" + DELIMITER;
public static final String WEBSOCKET_PREFIX = "webSocket" + DELIMITER;
diff --git a/ard-sample/src/main/java/com/ard/sample/common/model/ResponseResult.java b/ard-sample/src/main/java/com/ard/sample/common/model/ResponseResult.java
index 50c2c94..809b7a1 100644
--- a/ard-sample/src/main/java/com/ard/sample/common/model/ResponseResult.java
+++ b/ard-sample/src/main/java/com/ard/sample/common/model/ResponseResult.java
@@ -24,6 +24,8 @@
private T data;
+ private String gateway;
+
public static <T> ResponseResult<T> success(T data) {
return ResponseResult.<T>builder()
.code(CODE_SUCCESS)
diff --git a/ard-sample/src/main/java/com/ard/sample/component/websocket/enums/MessageType.java b/ard-sample/src/main/java/com/ard/sample/component/websocket/enums/MessageType.java
index e46ea77..631dbe9 100644
--- a/ard-sample/src/main/java/com/ard/sample/component/websocket/enums/MessageType.java
+++ b/ard-sample/src/main/java/com/ard/sample/component/websocket/enums/MessageType.java
@@ -5,6 +5,7 @@
STATUS("status"),
CONTROL("control"),
PROGRESS("progress"),
+ LIVESTREAM("livestream"),
ALL("all");
private final String type;
@@ -17,12 +18,19 @@
return type;
}
- public static MessageType fromString(String type) {
+ public static boolean fromString(String type) {
+ // 遍历MessageType枚举的所有值
for (MessageType messageType : MessageType.values()) {
+ // 如果当前枚举值的type属性与传入的type字符串忽略大小写相等
if (messageType.type.equalsIgnoreCase(type)) {
- return messageType;
+ // 返回当前枚举值
+ //return messageType;
+ return true;
}
}
- throw new IllegalArgumentException("Unknown message type: " + type);
+ // 如果遍历完所有枚举值都没有找到匹配的,则抛出异常
+ //throw new IllegalArgumentException("Unknown message type: " + type);
+ return false;
}
+
}
diff --git a/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/DockWebSocketHandler.java b/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/DockWebSocketHandler.java
index 89b92a5..9d6cc61 100644
--- a/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/DockWebSocketHandler.java
+++ b/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/DockWebSocketHandler.java
@@ -1,8 +1,11 @@
package com.ard.sample.component.websocket.handler;
import com.alibaba.fastjson2.JSON;
+import com.ard.sample.component.websocket.enums.MessageType;
import com.ard.sample.component.websocket.model.Payload;
import com.ard.sample.component.websocket.model.WebSocketMessage;
+import org.checkerframework.checker.units.qual.A;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
@@ -15,6 +18,9 @@
@Component
public class DockWebSocketHandler extends TextWebSocketHandler {
+
+ @Autowired
+ private LiveStreamHandler _liveStreamService;
// 存储用户会话:userId -> WebSocketSession
private final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>();
@@ -58,11 +64,11 @@
Payload payload = webSocketMessage.getPayload();
// 验证消息类型是否合法
- if (!Arrays.asList("status", "control", "progress", "state").contains(type)) {
+ //if (!Arrays.asList("status", "control", "progress", "state").contains(type)) {
+ if(!MessageType.fromString(type)){
session.sendMessage(new TextMessage("不支持的消息类型:" + type));
return;
}
-
// 处理订阅/取消订阅
handleSubscription(userId, type, payload);
@@ -84,7 +90,18 @@
// 订阅操作
subscriptions.computeIfAbsent(subscriptionKey, k -> ConcurrentHashMap.newKeySet()).add(userId);
System.out.println("用户[" + userId + "]订阅了 设备[" + sn + "]的[" + type + "]类型消息");
+ if(MessageType.LIVESTREAM.getType().equals(type)){
+ // 开启直播
+ // 开启直播逻辑
+ System.out.println("开启直播");
+ _liveStreamService.StartLiveStreaming(sn);
+ }
} else {
+ // 停止直播
+ if(MessageType.LIVESTREAM.getType().equals(type)){
+ System.out.println("停止直播");
+ _liveStreamService.StopLiveStreaming(sn);
+ }
// 取消订阅操作
if (subscriptions.containsKey(subscriptionKey)) {
subscriptions.get(subscriptionKey).remove(userId);
diff --git a/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/LiveStreamHandler.java b/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/LiveStreamHandler.java
new file mode 100644
index 0000000..1ae5cec
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/component/websocket/handler/LiveStreamHandler.java
@@ -0,0 +1,138 @@
+package com.ard.sample.component.websocket.handler;
+
+import com.ard.common.core.redis.RedisConst;
+import com.ard.common.core.redis.RedisOpsUtils;
+import com.ard.sample.common.model.ResponseResult;
+import com.ard.sample.component.websocket.enums.MessageType;
+import com.ard.sample.manage.model.dto.*;
+import com.ard.sample.manage.service.IDeviceService;
+import com.ard.sample.manage.service.ILiveStreamService;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Component
+public class LiveStreamHandler {
+ @Autowired
+ private IDeviceService _deviceService;
+
+ @Autowired
+ private ILiveStreamService _liveStreamService;
+
+ @Autowired
+ private DockWebSocketHandler _dockWebSocketHandler;
+
+ @Autowired
+ protected ObjectMapper _objectMapper;
+
+ /**
+ * 开启直播
+ */
+ public void StartLiveStreaming(String sn) {
+ // 检查设备是否在线
+ if (!_deviceService.checkDeviceOnline(sn)) {
+ String jsonString = getResult(sn, "设备不在线,请检查网络连接!");
+ _dockWebSocketHandler.sendMessageToSubscribers(sn, MessageType.LIVESTREAM.getType(), jsonString);
+ return;
+ }
+ // 读取直播能力拼接参数
+ List<CapacityDeviceDTO> devicesList = _liveStreamService.getLiveCapacity();
+ if (devicesList == null || devicesList.isEmpty()) {
+ String jsonString = getResult(sn, "未获得设备直播能力!");
+ _dockWebSocketHandler.sendMessageToSubscribers(sn, MessageType.LIVESTREAM.getType(), jsonString);
+ return;
+ }
+ for (CapacityDeviceDTO device : devicesList) {
+ if (!device.getSn().equals(sn)) {
+ continue;
+ }
+ List<CapacityCameraDTO> camerasList = device.getCamerasList();
+ for (CapacityCameraDTO camera : camerasList) {
+ if (camera.getName()==null || camera.getName().isEmpty()) {
+ continue;
+ }
+ LiveTypeDTO param = new LiveTypeDTO();
+ String videoid = device.getSn() + "/" + camera.getIndex();
+ List<CapacityVideoDTO> videosList = camera.getVideosList();
+ for (CapacityVideoDTO video : videosList) {
+ videoid = videoid + "/" + video.getIndex();
+ param.setUrlType(1);
+ param.setUrl("");
+ param.setVideoId(videoid);
+ param.setVideoQuality(1);
+ param.setVideoType(video.getSwitchVideoTypes().get(0));
+ //调用开始直播
+ ResponseResult rlive = null;
+ String resultLive = "";
+ try {
+ rlive = _liveStreamService.liveStart(param);
+ if (rlive != null) {
+ if (rlive.getCode() == 513003) {
+ _liveStreamService.liveStop(param.getVideoId());
+ System.out.println("相机已经在直播中,关闭直播后重启直播!");
+ rlive = _liveStreamService.liveStart(param);
+ }
+ if(rlive.getCode() == 0){
+ // 直播成功后,在redis中存一个标记,将videoid保留,留给停止直播使用
+ System.out.println("开启直播成功!");
+ RedisOpsUtils.setWithExpire(RedisConst.WEBSOCKET_VideoId_PREFIX + sn, param.getVideoId(), RedisConst.WEBSOCKET_ALIVE_SECOND);
+ rlive.setGateway(sn);
+ }
+ }
+ resultLive = _objectMapper.writeValueAsString(rlive);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ _dockWebSocketHandler.sendMessageToSubscribers(sn, MessageType.LIVESTREAM.getType(), resultLive);
+ break;
+ }
+ }
+ }
+ }
+
+ public void StopLiveStreaming(String sn) {
+ // 停止直播逻辑
+ ResponseResult rlive = null;
+ String resultLive = "";
+// System.out.println("关闭直播");
+ String videoid = "";
+ if(!RedisOpsUtils.checkExist(RedisConst.WEBSOCKET_VideoId_PREFIX + sn)){
+ resultLive = getResult(sn, "未找到正在直播的相机!");
+ }
+ else {
+ videoid = String.valueOf(RedisOpsUtils.get(RedisConst.WEBSOCKET_VideoId_PREFIX + sn));
+ try {
+ rlive = _liveStreamService.liveStop(videoid);
+ rlive.setGateway(sn);
+ resultLive = _objectMapper.writeValueAsString(rlive);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ _dockWebSocketHandler.sendMessageToSubscribers(sn, MessageType.LIVESTREAM.getType(), resultLive);
+ }
+
+ public String getResult(String sn, String msg) {
+ Map<String, String> result = new HashMap<>();
+ result.put("gateway", sn);
+ result.put("code", "1");
+ result.put("message", msg);
+ result.put("data", null);
+ result.put("type", MessageType.LIVESTREAM.getType());
+ // 将Map转换为JSON字符串
+ String jsonString = "";
+ try {
+ jsonString = _objectMapper.writeValueAsString(result);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return jsonString;
+ }
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DockOnlineServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DockOnlineServiceImpl.java
index 3d30a70..bab84be 100644
--- a/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DockOnlineServiceImpl.java
+++ b/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DockOnlineServiceImpl.java
@@ -61,7 +61,7 @@
dockStatus = String.valueOf(RedisOpsUtils.get(RedisConst.OSD_STATUS_PREFIX + device.getDeviceSn()));
}
if(RedisOpsUtils.checkExist(RedisConst.OSD_STATUS_PREFIX + device.getChildDeviceSn())){
- droneStatus = String.valueOf(RedisOpsUtils.get(RedisConst.OSD_STATUS_PREFIX + device.getChildDeviceSn()));;
+ droneStatus = String.valueOf(RedisOpsUtils.get(RedisConst.OSD_STATUS_PREFIX + device.getChildDeviceSn()));
}
String json = getJSONString(MessageType.STATE.getType(), device.getDeviceSn(), dockStatus, droneStatus);
--
Gitblit v1.9.3