From a2e7e8ff9cfaa69b001d483710bddbda50d55c91 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Mon, 01 Jun 2026 16:14:19 +0800
Subject: [PATCH] 优化
---
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 290 insertions(+), 0 deletions(-)
diff --git a/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java b/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java
index 2783390..6f325da 100644
--- a/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java
+++ b/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java
@@ -10,6 +10,7 @@
import com.ard.gb28181.api.RemoteGb28181Service;
import com.ard.gb28181.api.domain.Device;
import com.ard.gb28181.api.domain.DeviceChannel;
+import com.ard.gb28181.api.domain.GbChannelDTO;
import com.ard.qs.api.RemoteQsDeviceService;
import com.ard.qs.api.domain.QsDevice;
import com.ard.work.api.RemoteCameraService;
@@ -23,6 +24,8 @@
import com.ard.zlm.service.IInviteStreamService;
import com.ard.zlm.service.IMediaServerService;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
@@ -490,6 +493,7 @@
* @param id 设备id
* @return
*/
+ @Operation(summary = "gb28181播放")
@GetMapping("/startGb28181Play/{id}")
public DeferredResult<R<StreamContent>> startGb28181Play(
HttpServletRequest request,
@@ -631,4 +635,290 @@
return AjaxResult.success(json);
}
+ /**
+ * gb28181 播放(基于GbDevice,不依赖QS,按国标编码播放)
+ *
+ * @param request
+ * @param gbDeviceId 国标设备编码
+ * @param gbChannelId 国标通道编码
+ * @return
+ */
+ @Operation(summary = "gb28181播放(按国标编码)")
+ @GetMapping("/startGb28181PlayByGbDeviceId/{gbDeviceId}/{gbChannelId}")
+ public DeferredResult<R<StreamContent>> startGb28181PlayByGbDeviceId(
+ HttpServletRequest request,
+ @PathVariable String gbDeviceId,
+ @PathVariable String gbChannelId
+ ) {
+ log.info("[gb28181 开始点播] gbDeviceId:{}, gbChannelId:{}", gbDeviceId, gbChannelId);
+ Assert.hasText(gbDeviceId, "国标设备编码不可为空");
+ Assert.hasText(gbChannelId, "国标通道编码不可为空");
+
+ // 1. 查询 GbChannel 配置
+ R<GbChannelDTO> channelR = remoteGb28181Service.getGbChannel(gbDeviceId, gbChannelId, SecurityConstants.INNER);
+ if (channelR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("获取GbChannel配置失败 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId
+ + "。设备注册后会自动创建,请确认设备已上线并完成目录同步。");
+ }
+ Assert.notNull(channelR.getData(), "GbChannel不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+
+ GbChannelDTO gbChannelDTO = channelR.getData();
+
+ // 2. 查询国标设备
+ R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
+ if (deviceR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备信息失败 deviceId:" + gbDeviceId);
+ }
+ Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 deviceId:" + gbDeviceId);
+
+ if (!deviceR.getData().isOnLine()) {
+ throw new RuntimeException("gb28181 国标设备不在线 deviceId:" + gbDeviceId);
+ }
+
+ // 3. 查询国标通道
+ R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(gbDeviceId, gbChannelId, SecurityConstants.INNER);
+ if (deviceChannelR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+ Assert.notNull(deviceChannelR.getData(), "gb28181 国标设备通道不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+
+ if (!"ON".equals(deviceChannelR.getData().getStatus())) {
+ throw new RuntimeException("gb28181 国标设备通道不在线 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+
+ DeferredResult<R<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
+
+ result.onTimeout(() -> {
+ log.info("[点播等待超时] gbDeviceId:{}, gbChannelId:{}", gbDeviceId, gbChannelId);
+ R<StreamContent> fail = R.fail();
+ fail.setMsg("点播超时");
+ result.setResult(fail);
+
+ inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
+ mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO, deviceR.getData(), gbChannelDTO.getDeviceCode());
+ });
+
+ ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
+ if (code == InviteErrorCode.SUCCESS.getCode()) {
+ R<StreamContent> r = R.ok();
+ if (streamInfo != null) {
+ if (userSetting.getUseSourceIpAsStreamIp()) {
+ streamInfo = streamInfo.clone();
+ String host;
+ try {
+ URL url = new URL(request.getRequestURL().toString());
+ host = url.getHost();
+ } catch (MalformedURLException e) {
+ host = request.getLocalAddr();
+ }
+ streamInfo.changeStreamIp(host);
+ }
+ if (!ObjectUtils.isEmpty(streamInfo.getMediaServer().getTranscodeSuffix())
+ && !"null".equalsIgnoreCase(streamInfo.getMediaServer().getTranscodeSuffix())) {
+ streamInfo.setStream(streamInfo.getStream() + "_" + streamInfo.getMediaServer().getTranscodeSuffix());
+ }
+ r.setData(new StreamContent(streamInfo));
+ } else {
+ r.setCode(code);
+ r.setMsg(msg);
+ }
+ result.setResult(r);
+ } else {
+ result.setResult(R.fail(code, msg));
+ }
+ };
+
+ mediaServerService.startGb28181PlayByGbChannel(gbChannelDTO, deviceR.getData(), callback);
+ return result;
+ }
+
+ /**
+ * gb28181 停止点播(基于GbDevice,不依赖QS,按国标编码停止)
+ *
+ * @param gbDeviceId 国标设备编码
+ * @param gbChannelId 国标通道编码
+ * @return
+ */
+ @Operation(summary = "gb28181停止点播(按国标编码)")
+ @GetMapping("/stopGb28181PlayByGbDeviceId/{gbDeviceId}/{gbChannelId}")
+ public AjaxResult stopGb28181PlayByGbDeviceId(
+ @PathVariable String gbDeviceId,
+ @PathVariable String gbChannelId
+ ) {
+ log.info("[gb28181 停止点播] gbDeviceId:{}, gbChannelId:{}", gbDeviceId, gbChannelId);
+ Assert.hasText(gbDeviceId, "国标设备编码不可为空");
+ Assert.hasText(gbChannelId, "国标通道编码不可为空");
+
+ // 1. 查询 GbChannel 配置
+ R<GbChannelDTO> channelR = remoteGb28181Service.getGbChannel(gbDeviceId, gbChannelId, SecurityConstants.INNER);
+ if (channelR.getCode() != Constants.SUCCESS || channelR.getData() == null) {
+ throw new RuntimeException("GbChannel不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+
+ GbChannelDTO gbChannelDTO = channelR.getData();
+
+ // 2. 查询国标设备
+ R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
+ if (deviceR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备信息失败 deviceId:" + gbDeviceId);
+ }
+ Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 deviceId:" + gbDeviceId);
+
+ // 3. 查询国标通道
+ R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(gbDeviceId, gbChannelId, SecurityConstants.INNER);
+ if (deviceChannelR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+ Assert.notNull(deviceChannelR.getData(), "gb28181 国标设备通道不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+
+ mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO,
+ deviceR.getData(), gbChannelDTO.getDeviceCode());
+
+ JSONObject json = new JSONObject();
+ json.put("gbDeviceId", gbDeviceId);
+ json.put("gbChannelId", gbChannelId);
+ return AjaxResult.success(json);
+ }
+
+ /**
+ * gb28181 播放(基于GbChannel主键ID)
+ *
+ * @param request
+ * @param channelId GbChannel主键ID
+ * @return
+ */
+ @Operation(summary = "gb28181播放(按通道主键ID)")
+ @GetMapping("/startGb28181PlayByChannelId/{channelId}")
+ public DeferredResult<R<StreamContent>> startGb28181PlayByChannelId(
+ HttpServletRequest request,
+ @PathVariable Long channelId
+ ) {
+ log.info("[gb28181 开始点播] channelId:{}", channelId);
+ Assert.notNull(channelId, "通道ID不可为空");
+
+ // 1. 根据主键ID查询 GbChannel
+ R<GbChannelDTO> channelR = remoteGb28181Service.getGbChannelById(channelId, SecurityConstants.INNER);
+ if (channelR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("获取GbChannel失败 channelId:" + channelId);
+ }
+ Assert.notNull(channelR.getData(), "GbChannel不存在 channelId:" + channelId);
+
+ GbChannelDTO gbChannelDTO = channelR.getData();
+ String gbDeviceId = gbChannelDTO.getGbDeviceId();
+ String gbChannelId = gbChannelDTO.getGbChannelId();
+
+ // 2. 查询国标设备
+ R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
+ if (deviceR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备信息失败 deviceId:" + gbDeviceId);
+ }
+ Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 deviceId:" + gbDeviceId);
+
+ if (!deviceR.getData().isOnLine()) {
+ throw new RuntimeException("gb28181 国标设备不在线 deviceId:" + gbDeviceId);
+ }
+
+ // 3. 查询国标通道
+ R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(gbDeviceId, gbChannelId, SecurityConstants.INNER);
+ if (deviceChannelR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+ Assert.notNull(deviceChannelR.getData(), "gb28181 国标设备通道不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+
+ if (!"ON".equals(deviceChannelR.getData().getStatus())) {
+ throw new RuntimeException("gb28181 国标设备通道不在线 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+
+ DeferredResult<R<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
+
+ result.onTimeout(() -> {
+ log.info("[点播等待超时] channelId:{}, gbDeviceId:{}, gbChannelId:{}", channelId, gbDeviceId, gbChannelId);
+ R<StreamContent> fail = R.fail();
+ fail.setMsg("点播超时");
+ result.setResult(fail);
+
+ inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
+ mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO, deviceR.getData(), gbChannelDTO.getDeviceCode());
+ });
+
+ ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
+ if (code == InviteErrorCode.SUCCESS.getCode()) {
+ R<StreamContent> r = R.ok();
+ if (streamInfo != null) {
+ if (userSetting.getUseSourceIpAsStreamIp()) {
+ streamInfo = streamInfo.clone();
+ String host;
+ try {
+ URL url = new URL(request.getRequestURL().toString());
+ host = url.getHost();
+ } catch (MalformedURLException e) {
+ host = request.getLocalAddr();
+ }
+ streamInfo.changeStreamIp(host);
+ }
+ if (!ObjectUtils.isEmpty(streamInfo.getMediaServer().getTranscodeSuffix())
+ && !"null".equalsIgnoreCase(streamInfo.getMediaServer().getTranscodeSuffix())) {
+ streamInfo.setStream(streamInfo.getStream() + "_" + streamInfo.getMediaServer().getTranscodeSuffix());
+ }
+ r.setData(new StreamContent(streamInfo));
+ } else {
+ r.setCode(code);
+ r.setMsg(msg);
+ }
+ result.setResult(r);
+ } else {
+ result.setResult(R.fail(code, msg));
+ }
+ };
+
+ mediaServerService.startGb28181PlayByGbChannel(gbChannelDTO, deviceR.getData(), callback);
+ return result;
+ }
+
+ /**
+ * gb28181 停止点播(基于GbChannel主键ID)
+ *
+ * @param channelId GbChannel主键ID
+ * @return
+ */
+ @Operation(summary = "gb28181停止点播(按通道主键ID)")
+ @GetMapping("/stopGb28181PlayByChannelId/{channelId}")
+ public AjaxResult stopGb28181PlayByChannelId(@PathVariable Long channelId) {
+ log.info("[gb28181 停止点播] channelId:{}", channelId);
+ Assert.notNull(channelId, "通道ID不可为空");
+
+ // 1. 根据主键ID查询 GbChannel
+ R<GbChannelDTO> channelR = remoteGb28181Service.getGbChannelById(channelId, SecurityConstants.INNER);
+ if (channelR.getCode() != Constants.SUCCESS || channelR.getData() == null) {
+ throw new RuntimeException("GbChannel不存在 channelId:" + channelId);
+ }
+
+ GbChannelDTO gbChannelDTO = channelR.getData();
+ String gbDeviceId = gbChannelDTO.getGbDeviceId();
+ String gbChannelId = gbChannelDTO.getGbChannelId();
+
+ // 2. 查询国标设备
+ R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
+ if (deviceR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备信息失败 deviceId:" + gbDeviceId);
+ }
+ Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 deviceId:" + gbDeviceId);
+
+ // 3. 查询国标通道
+ R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(gbDeviceId, gbChannelId, SecurityConstants.INNER);
+ if (deviceChannelR.getCode() != Constants.SUCCESS) {
+ throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+ }
+ Assert.notNull(deviceChannelR.getData(), "gb28181 国标设备通道不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
+
+ mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO,
+ deviceR.getData(), gbChannelDTO.getDeviceCode());
+
+ JSONObject json = new JSONObject();
+ json.put("channelId", channelId);
+ json.put("gbDeviceId", gbDeviceId);
+ json.put("gbChannelId", gbChannelId);
+ return AjaxResult.success(json);
+ }
+
}
--
Gitblit v1.9.3