liusuyi
2026-06-01 3496700a5ba18be8ca0590a79e21a867782d1ea9
优化
59 files deleted
15 files added
18 files modified
12737 ■■■■■ changed files
ard-api/ard-api-gb28181/src/main/java/com/ard/gb28181/api/domain/GbChannelDTO.java 54 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-gb28181/src/main/java/com/ard/gb28181/api/domain/GbDeviceDTO.java 51 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/pom.xml 28 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/RemoteQsDeviceService.java 157 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/common/CivilCodePo.java 47 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/domain/QsDevice.java 162 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/domain/QsGroup.java 58 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/domain/QsRegion.java 54 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/factory/RemoteQsDeviceFallbackFactory.java 99 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/utils/CivilCodeUtil.java 103 ●●●●● patch | view | raw | blame | history
ard-api/ard-api-qs/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 1 ●●●● patch | view | raw | blame | history
ard-api/pom.xml 1 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/api/Gb28181ApiController.java 177 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/domain/GbChannel.java 58 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/domain/GbDevice.java 55 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/mapper/GbChannelMapper.java 38 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/mapper/GbDeviceMapper.java 29 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/IGbChannelService.java 32 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/IGbDeviceService.java 28 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/impl/GbChannelServiceImpl.java 68 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/impl/GbDeviceServiceImpl.java 57 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/resources/mapper/gb28181/GbChannelMapper.xml 140 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-gb28181/src/main/resources/mapper/gb28181/GbDeviceMapper.xml 118 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/pom.xml 132 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/ArdQSApplication.java 35 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/api/QsDeviceApiController.java 176 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/common/GbCode.java 56 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/common/SystemAllInfo.java 54 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/common/VideoManagerConstants.java 13 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/config/CivilCodeFileConf.java 77 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/config/ThreadPoolTaskConfig.java 67 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsDeviceController.java 393 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsGroupController.java 109 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsRegionController.java 127 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsServerController.java 61 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceStats.java 26 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceToGroupParam.java 14 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceToRegionParam.java 28 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceType.java 58 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceTypeEnum.java 98 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/IndustryCodeType.java 59 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/IndustryCodeTypeEnum.java 55 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/NetworkIdentificationType.java 45 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/NetworkIdentificationTypeEnum.java 51 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/Preset.java 30 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/QsGroupTree.java 66 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/QsRegionTree.java 66 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/RecordPlanParam.java 27 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/mapper/QsDeviceMapper.java 348 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/mapper/QsGroupMapper.java 129 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/mapper/QsRegionMapper.java 93 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/runner/QsCommandLineRunner.java 38 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IQsDeviceService.java 432 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IQsGroupService.java 63 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IQsRegionService.java 69 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IRedisCatchStorageService.java 30 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/QsDeviceServiceImpl.java 1293 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/QsGroupServiceImpl.java 236 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/QsRegionServiceImpl.java 186 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/RedisCatchStorageServiceImpl.java 106 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/task/SystemInfoTimerTask.java 41 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/DateUtil.java 229 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/StreamDetector.java 96 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/SystemInfoUtils.java 186 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/VideoSnapshotUtil.java 90 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/banner.txt 8 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/bootstrap.yml 28 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/civilCode.csv 3224 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/gb_dict.json 439 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/logback.xml 74 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/mapper/qs/QsDeviceMapper.xml 729 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/mapper/qs/QsGroupMapper.xml 219 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-qs/src/main/resources/mapper/qs/QsRegionMapper.xml 147 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-work/pom.xml 4 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/api/ArdChannelApiController.java 9 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/mapper/ArdChannelMapper.java 1 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/service/IArdChannelService.java 1 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/service/impl/ArdChannelServiceImpl.java 19 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-work/src/main/java/com/ard/work/websocket/config/PTZWebSocketInitializer.java 24 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/pom.xml 5 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java 102 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/domain/StreamChannel.java 60 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/IDevicePlayService.java 2 ●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/IMediaServerService.java 16 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/ISourcePlayService.java 2 ●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/ZlmStreamService.java 107 ●●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/DevicePlayServiceImpl.java 2 ●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java 275 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServiceImpl.java 14 ●●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/SourcePlayServiceImpl.java 2 ●●● patch | view | raw | blame | history
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/ZlmRecordPlanServiceImpl.java 20 ●●●● patch | view | raw | blame | history
ard-modules/pom.xml 1 ●●●● patch | view | raw | blame | history
ard-api/ard-api-gb28181/src/main/java/com/ard/gb28181/api/domain/GbChannelDTO.java
New file
@@ -0,0 +1,54 @@
package com.ard.gb28181.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
 * 国标通道 DTO(播放用)
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GbChannelDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    /** 主键ID */
    private Long id;
    /** 父设备国标编码 */
    private String gbDeviceId;
    /** 国标通道编码 */
    private String gbChannelId;
    /** 通道名称 */
    private String channelName;
    /** 流标识(用于ZLM) */
    private String deviceCode;
    /** 数据流传输模式 */
    private String streamMode;
    /** 开启mp4录制 */
    private String enableMp4;
    /** 流状态 */
    private String streamStatus;
    /** 流媒体服务ID */
    private String mediaServerId;
    /** stream key */
    private String streamKey;
    /** 截图路径 */
    private String snap;
}
ard-api/ard-api-gb28181/src/main/java/com/ard/gb28181/api/domain/GbDeviceDTO.java
New file
@@ -0,0 +1,51 @@
package com.ard.gb28181.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
 * 国标设备 DTO(设备列表展示用)
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GbDeviceDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    /** 主键ID */
    private Long id;
    /** 国标设备编码 */
    private String gbDeviceId;
    /** 设备名称 */
    private String deviceName;
    /** 设备编码 */
    private String deviceCode;
    /** 设备IP地址 */
    private String ip;
    /** 设备端口 */
    private Integer port;
    /** 设备厂商 */
    private String manufacturer;
    /** 设备型号 */
    private String model;
    /** 固件版本 */
    private String firmware;
    /** 在线状态 */
    private Boolean onLine;
}
ard-api/ard-api-qs/pom.xml
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/RemoteQsDeviceService.java
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/common/CivilCodePo.java
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/domain/QsDevice.java
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/domain/QsGroup.java
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/domain/QsRegion.java
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/factory/RemoteQsDeviceFallbackFactory.java
File was deleted
ard-api/ard-api-qs/src/main/java/com/ard/qs/api/utils/CivilCodeUtil.java
File was deleted
ard-api/ard-api-qs/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
File was deleted
ard-api/pom.xml
@@ -13,7 +13,6 @@
        <module>ard-api-work</module>
        <module>ard-api-vtdu</module>
        <module>ard-api-zlm</module>
        <module>ard-api-qs</module>
        <module>ard-api-gb28181</module>
    </modules>
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/api/Gb28181ApiController.java
@@ -809,181 +809,4 @@
        dto.setSnap(c.getSnap());
        return dto;
    }
    /**
     * 一键迁移:将 Redis 中已注册的国标设备同步到 MySQL(供首次执行 SQL 后使用)
     */
    @Operation(summary = "迁移Redis国标设备到MySQL")
    @PostMapping("/migrateGbDevices")
    public R<String> migrateGbDevices() {
        List<Device> allDevices = deviceService.getAllDevices();
        int deviceCount = 0;
        int channelCount = 0;
        for (Device device : allDevices) {
            try {
                // 创建设备记录
                GbDevice existingDevice = gbDeviceService.selectGbDeviceByGbDeviceId(device.getDeviceId());
                if (existingDevice == null) {
                    GbDevice gbDevice = new GbDevice();
                    gbDevice.setGbDeviceId(device.getDeviceId());
                    gbDevice.setDeviceName(StringUtils.hasText(device.getName()) ? device.getName() : device.getDeviceId());
                    gbDevice.setDeviceCode(device.getDeviceId());
                    gbDevice.setIp(device.getIp());
                    gbDevice.setPort(device.getPort());
                    gbDevice.setManufacturer(device.getManufacturer());
                    gbDevice.setModel(device.getModel());
                    gbDevice.setFirmware(device.getFirmware());
                    gbDevice.setOnLine(device.isOnLine());
                    gbDeviceService.insertGbDevice(gbDevice);
                    deviceCount++;
                    log.info("[迁移] 创建设备: {}", device.getDeviceId());
                }
                // 创建默认通道(设备自身)
                GbChannel existingDefaultChannel = gbChannelService.selectByGbDeviceIdAndGbChannelId(
                        device.getDeviceId(), device.getDeviceId());
                if (existingDefaultChannel == null) {
                    GbChannel gbChannel = new GbChannel();
                    gbChannel.setGbDeviceId(device.getDeviceId());
                    gbChannel.setGbChannelId(device.getDeviceId());
                    gbChannel.setChannelName(StringUtils.hasText(device.getName()) ? device.getName() : device.getDeviceId());
                    gbChannel.setDeviceCode(device.getDeviceId());
                    gbChannel.setStreamMode(device.getStreamMode() != null ? device.getStreamMode() : "TCP-PASSIVE");
                    gbChannel.setEnableMp4("0");
                    gbChannelService.insertGbChannel(gbChannel);
                    channelCount++;
                }
                // 创建所有通道
                List<DeviceChannel> channels = deviceService.getChannelsByDeviceId(device.getDeviceId());
                if (channels != null) {
                    for (DeviceChannel channel : channels) {
                        String channelId = channel.getDeviceId();
                        if (channelId == null || channelId.length() <= 8) {
                            continue;
                        }
                        if (channelId.length() == 20) {
                            try {
                                com.ard.gb28181.api.domain.GbCode gbCode = com.ard.gb28181.api.domain.GbCode.decode(channelId);
                                if (gbCode != null && ("215".equals(gbCode.getTypeCode()) || "216".equals(gbCode.getTypeCode()))) {
                                    continue;
                                }
                            } catch (Exception ignored) {}
                        }
                        GbChannel existing = gbChannelService.selectByGbDeviceIdAndGbChannelId(device.getDeviceId(), channelId);
                        if (existing == null) {
                            GbChannel gbChannel = new GbChannel();
                            gbChannel.setGbDeviceId(device.getDeviceId());
                            gbChannel.setGbChannelId(channelId);
                            gbChannel.setChannelName(StringUtils.hasText(channel.getName()) ? channel.getName() : channelId);
                            gbChannel.setDeviceCode(channelId);
                            gbChannel.setStreamMode(device.getStreamMode() != null ? device.getStreamMode() : "TCP-PASSIVE");
                            gbChannel.setEnableMp4("0");
                            gbChannelService.insertGbChannel(gbChannel);
                            channelCount++;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("[迁移] 处理设备失败: {}", device.getDeviceId(), e);
            }
        }
        return R.ok("迁移完成: 设备 " + deviceCount + " 条, 通道 " + channelCount + " 条");
    }
    /**
     * 从 Redis 同步通道数据到 MySQL,使 ard_gb_channel 与 Redis 一致
     */
    @Operation(summary = "从Redis同步通道到MySQL")
    @PostMapping("/syncGbChannelsFromRedis")
    public R<String> syncGbChannelsFromRedis() {
        List<Device> allDevices = deviceService.getAllRedisDevices();
        int createdCount = 0;
        int deletedCount = 0;
        int skippedCount = 0;
        for (Device device : allDevices) {
            try {
                String deviceId = device.getDeviceId();
                List<DeviceChannel> redisChannels = deviceService.getChannelsByDeviceId(deviceId);
                if (redisChannels == null) {
                    redisChannels = new ArrayList<>();
                }
                Set<String> redisChannelIds = new HashSet<>();
                boolean hasRealSubChannel = false;
                for (DeviceChannel ch : redisChannels) {
                    String channelId = ch.getDeviceId();
                    if (channelId == null || channelId.length() <= 8) {
                        continue;
                    }
                    if (channelId.length() == 20) {
                        try {
                            GbCode gbCode = GbCode.decode(channelId);
                            if (gbCode != null && ("215".equals(gbCode.getTypeCode()) || "216".equals(gbCode.getTypeCode()))) {
                                continue;
                            }
                        } catch (Exception ignored) {}
                    }
                    redisChannelIds.add(channelId);
                    if (!channelId.equals(deviceId)) {
                        hasRealSubChannel = true;
                    }
                    GbChannel existing = gbChannelService.selectByGbDeviceIdAndGbChannelId(deviceId, channelId);
                    if (existing == null) {
                        GbChannel gbChannel = new GbChannel();
                        gbChannel.setGbDeviceId(deviceId);
                        gbChannel.setGbChannelId(channelId);
                        gbChannel.setChannelName(StringUtils.hasText(ch.getName()) ? ch.getName() : channelId);
                        gbChannel.setDeviceCode(channelId);
                        gbChannel.setStreamMode(device.getStreamMode() != null ? device.getStreamMode() : "TCP-PASSIVE");
                        gbChannel.setEnableMp4("0");
                        gbChannelService.insertGbChannel(gbChannel);
                        createdCount++;
                        log.info("[同步] 创建通道: deviceId={}, channelId={}", deviceId, channelId);
                    } else if (StringUtils.hasText(ch.getName())
                            && !ch.getName().equals(existing.getChannelName())) {
                        existing.setChannelName(ch.getName());
                        gbChannelService.updateGbChannel(existing);
                        log.info("[同步] 更新通道名称: deviceId={}, channelId={}, {} -> {}",
                                deviceId, channelId, existing.getChannelName(), ch.getName());
                    }
                }
                List<GbChannel> mysqlChannels = gbChannelService.selectGbChannelByGbDeviceId(deviceId);
                for (GbChannel mysqlCh : mysqlChannels) {
                    if (!redisChannelIds.contains(mysqlCh.getGbChannelId())) {
                        if ("1".equals(mysqlCh.getStreamStatus())) {
                            skippedCount++;
                            continue;
                        }
                        gbChannelService.deleteGbChannelById(mysqlCh.getId());
                        deletedCount++;
                    }
                }
                if (hasRealSubChannel) {
                    GbChannel defaultChannel = gbChannelService.selectByGbDeviceIdAndGbChannelId(deviceId, deviceId);
                    if (defaultChannel != null && !redisChannelIds.contains(deviceId)) {
                        if (!"1".equals(defaultChannel.getStreamStatus())) {
                            gbChannelService.deleteGbChannelById(defaultChannel.getId());
                            deletedCount++;
                        } else {
                            skippedCount++;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("[同步] 处理设备失败: {}", device.getDeviceId(), e);
            }
        }
        return R.ok(String.format("同步完成: 创建 %d 条, 删除 %d 条, 跳过 %d 条(推流中)",
                createdCount, deletedCount, skippedCount));
    }
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/domain/GbChannel.java
New file
@@ -0,0 +1,58 @@
package com.ard.gb28181.domain;
import com.ard.common.core.web.domain.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
 * 国标设备通道对象 ard_gb_channel
 * <p>
 * 存储国标设备下的通道信息,用于播放。
 * 一个 NVR 下的每个摄像头通道对应一条记录。
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GbChannel extends BaseEntity {
    private static final long serialVersionUID = 1L;
    /** 主键ID */
    private Long id;
    /** 父设备国标编码(关联 ard_gb_device.gb_device_id) */
    private String gbDeviceId;
    /** 国标通道编码 */
    private String gbChannelId;
    /** 通道名称 */
    private String channelName;
    /** 流标识(用于ZLM,默认等同gbChannelId) */
    private String deviceCode;
    /** 数据流传输模式(UDP/TCP-ACTIVE/TCP-PASSIVE) */
    private String streamMode;
    /** 开启mp4录制(0=关闭, 1=开启) */
    private String enableMp4;
    /** 流状态(0=停止, 1=直播中) */
    private String streamStatus;
    /** 当前拉流使用的流媒体服务ID */
    private String mediaServerId;
    /** 拉流时zlm返回的stream key */
    private String streamKey;
    /** 截图路径 */
    private String snap;
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/domain/GbDevice.java
New file
@@ -0,0 +1,55 @@
package com.ard.gb28181.domain;
import com.ard.common.core.web.domain.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
 * 国标设备对象 ard_gb_device
 * <p>
 * 存储国标设备的注册信息和业务展示数据。
 * 一个 NVR/IPC 设备对应一条记录。
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GbDevice extends BaseEntity {
    private static final long serialVersionUID = 1L;
    /** 主键ID */
    private Long id;
    /** 国标设备编码(20位) */
    private String gbDeviceId;
    /** 设备名称(来自注册/设备信息查询) */
    private String deviceName;
    /** 设备编码(业务用) */
    private String deviceCode;
    /** 设备IP地址 */
    private String ip;
    /** 设备端口 */
    private Integer port;
    /** 设备厂商 */
    private String manufacturer;
    /** 设备型号 */
    private String model;
    /** 固件版本 */
    private String firmware;
    /** 在线状态(true=在线, false=离线) */
    private Boolean onLine;
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/mapper/GbChannelMapper.java
New file
@@ -0,0 +1,38 @@
package com.ard.gb28181.mapper;
import com.ard.gb28181.domain.GbChannel;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
 * 国标通道Mapper接口
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
@Mapper
@Repository
public interface GbChannelMapper {
    GbChannel selectGbChannelById(Long id);
    List<GbChannel> selectGbChannelByGbDeviceId(String gbDeviceId);
    GbChannel selectByGbDeviceIdAndGbChannelId(@Param("gbDeviceId") String gbDeviceId,
                                                @Param("gbChannelId") String gbChannelId);
    List<GbChannel> selectGbChannelList(GbChannel gbChannel);
    int insertGbChannel(GbChannel gbChannel);
    int updateGbChannel(GbChannel gbChannel);
    int updateGbChannelStream(GbChannel gbChannel);
    int deleteGbChannelById(Long id);
    int deleteGbChannelByIds(String[] ids);
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/mapper/GbDeviceMapper.java
New file
@@ -0,0 +1,29 @@
package com.ard.gb28181.mapper;
import com.ard.gb28181.domain.GbDevice;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
 * 国标设备Mapper接口
 */
@Mapper
@Repository
public interface GbDeviceMapper {
    GbDevice selectGbDeviceById(Long id);
    GbDevice selectGbDeviceByGbDeviceId(String gbDeviceId);
    List<GbDevice> selectGbDeviceList(GbDevice gbDevice);
    int insertGbDevice(GbDevice gbDevice);
    int updateGbDevice(GbDevice gbDevice);
    int deleteGbDeviceById(Long id);
    int deleteGbDeviceByIds(String[] ids);
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/IGbChannelService.java
New file
@@ -0,0 +1,32 @@
package com.ard.gb28181.service;
import com.ard.gb28181.domain.GbChannel;
import java.util.List;
/**
 * 国标通道Service接口
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
public interface IGbChannelService {
    GbChannel selectGbChannelById(Long id);
    List<GbChannel> selectGbChannelByGbDeviceId(String gbDeviceId);
    GbChannel selectByGbDeviceIdAndGbChannelId(String gbDeviceId, String gbChannelId);
    List<GbChannel> selectGbChannelList(GbChannel gbChannel);
    int insertGbChannel(GbChannel gbChannel);
    int updateGbChannel(GbChannel gbChannel);
    int updateGbChannelStream(GbChannel gbChannel);
    int deleteGbChannelById(Long id);
    int deleteGbChannelByIds(String[] ids);
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/IGbDeviceService.java
New file
@@ -0,0 +1,28 @@
package com.ard.gb28181.service;
import com.ard.gb28181.domain.GbDevice;
import java.util.List;
/**
 * 国标设备Service接口
 *
 * @author 刘苏义
 * @date 2026-05-30
 */
public interface IGbDeviceService {
    GbDevice selectGbDeviceById(Long id);
    GbDevice selectGbDeviceByGbDeviceId(String gbDeviceId);
    List<GbDevice> selectGbDeviceList(GbDevice gbDevice);
    int insertGbDevice(GbDevice gbDevice);
    int updateGbDevice(GbDevice gbDevice);
    int deleteGbDeviceById(Long id);
    int deleteGbDeviceByIds(String[] ids);
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/impl/GbChannelServiceImpl.java
New file
@@ -0,0 +1,68 @@
package com.ard.gb28181.service.impl;
import com.ard.gb28181.domain.GbChannel;
import com.ard.gb28181.mapper.GbChannelMapper;
import com.ard.gb28181.service.IGbChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
 * 国标通道Service实现
 */
@Service
public class GbChannelServiceImpl implements IGbChannelService {
    @Autowired
    private GbChannelMapper gbChannelMapper;
    @Override
    public GbChannel selectGbChannelById(Long id) {
        return gbChannelMapper.selectGbChannelById(id);
    }
    @Override
    public List<GbChannel> selectGbChannelByGbDeviceId(String gbDeviceId) {
        return gbChannelMapper.selectGbChannelByGbDeviceId(gbDeviceId);
    }
    @Override
    public GbChannel selectByGbDeviceIdAndGbChannelId(String gbDeviceId, String gbChannelId) {
        return gbChannelMapper.selectByGbDeviceIdAndGbChannelId(gbDeviceId, gbChannelId);
    }
    @Override
    public List<GbChannel> selectGbChannelList(GbChannel gbChannel) {
        return gbChannelMapper.selectGbChannelList(gbChannel);
    }
    @Override
    public int insertGbChannel(GbChannel gbChannel) {
        gbChannel.setCreateTime(new Date());
        return gbChannelMapper.insertGbChannel(gbChannel);
    }
    @Override
    public int updateGbChannel(GbChannel gbChannel) {
        gbChannel.setUpdateTime(new Date());
        return gbChannelMapper.updateGbChannel(gbChannel);
    }
    @Override
    public int updateGbChannelStream(GbChannel gbChannel) {
        gbChannel.setUpdateTime(new Date());
        return gbChannelMapper.updateGbChannelStream(gbChannel);
    }
    @Override
    public int deleteGbChannelById(Long id) {
        return gbChannelMapper.deleteGbChannelById(id);
    }
    @Override
    public int deleteGbChannelByIds(String[] ids) {
        return gbChannelMapper.deleteGbChannelByIds(ids);
    }
}
ard-modules/ard-modules-gb28181/src/main/java/com/ard/gb28181/service/impl/GbDeviceServiceImpl.java
New file
@@ -0,0 +1,57 @@
package com.ard.gb28181.service.impl;
import com.ard.gb28181.domain.GbDevice;
import com.ard.gb28181.mapper.GbDeviceMapper;
import com.ard.gb28181.service.IGbDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
 * 国标设备Service实现
 */
@Service
public class GbDeviceServiceImpl implements IGbDeviceService {
    @Autowired
    private GbDeviceMapper gbDeviceMapper;
    @Override
    public GbDevice selectGbDeviceById(Long id) {
        return gbDeviceMapper.selectGbDeviceById(id);
    }
    @Override
    public GbDevice selectGbDeviceByGbDeviceId(String gbDeviceId) {
        return gbDeviceMapper.selectGbDeviceByGbDeviceId(gbDeviceId);
    }
    @Override
    public List<GbDevice> selectGbDeviceList(GbDevice gbDevice) {
        return gbDeviceMapper.selectGbDeviceList(gbDevice);
    }
    @Override
    public int insertGbDevice(GbDevice gbDevice) {
        gbDevice.setCreateTime(new Date());
        return gbDeviceMapper.insertGbDevice(gbDevice);
    }
    @Override
    public int updateGbDevice(GbDevice gbDevice) {
        gbDevice.setUpdateTime(new Date());
        return gbDeviceMapper.updateGbDevice(gbDevice);
    }
    @Override
    public int deleteGbDeviceById(Long id) {
        return gbDeviceMapper.deleteGbDeviceById(id);
    }
    @Override
    public int deleteGbDeviceByIds(String[] ids) {
        return gbDeviceMapper.deleteGbDeviceByIds(ids);
    }
}
ard-modules/ard-modules-gb28181/src/main/resources/mapper/gb28181/GbChannelMapper.xml
New file
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ard.gb28181.mapper.GbChannelMapper">
    <resultMap type="com.ard.gb28181.domain.GbChannel" id="GbChannelResult">
        <id property="id" column="id"/>
        <result property="gbDeviceId" column="gb_device_id"/>
        <result property="gbChannelId" column="gb_channel_id"/>
        <result property="channelName" column="channel_name"/>
        <result property="deviceCode" column="device_code"/>
        <result property="streamMode" column="stream_mode"/>
        <result property="enableMp4" column="enable_mp4"/>
        <result property="streamStatus" column="stream_status"/>
        <result property="mediaServerId" column="media_server_id"/>
        <result property="streamKey" column="stream_key"/>
        <result property="snap" column="snap"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="remark" column="remark"/>
    </resultMap>
    <sql id="selectGbChannelVo">
        select id, gb_device_id, gb_channel_id, channel_name, device_code, stream_mode, enable_mp4,
               stream_status, media_server_id, stream_key, snap,
               create_by, create_time, update_by, update_time, remark
        from ard_gb_channel
    </sql>
    <select id="selectGbChannelById" parameterType="Long" resultMap="GbChannelResult">
        <include refid="selectGbChannelVo"/> where id = #{id}
    </select>
    <select id="selectGbChannelByGbDeviceId" parameterType="String" resultMap="GbChannelResult">
        <include refid="selectGbChannelVo"/> where gb_device_id = #{gbDeviceId}
        order by id
    </select>
    <select id="selectByGbDeviceIdAndGbChannelId" resultMap="GbChannelResult">
        <include refid="selectGbChannelVo"/>
        where gb_device_id = #{gbDeviceId} and gb_channel_id = #{gbChannelId}
    </select>
    <select id="selectGbChannelList" parameterType="com.ard.gb28181.domain.GbChannel" resultMap="GbChannelResult">
        <include refid="selectGbChannelVo"/>
        <where>
            <if test="gbDeviceId != null and gbDeviceId != ''">
                and gb_device_id like concat('%', #{gbDeviceId}, '%')
            </if>
            <if test="gbChannelId != null and gbChannelId != ''">
                and gb_channel_id like concat('%', #{gbChannelId}, '%')
            </if>
            <if test="channelName != null and channelName != ''">
                and channel_name like concat('%', #{channelName}, '%')
            </if>
        </where>
    </select>
    <insert id="insertGbChannel" parameterType="com.ard.gb28181.domain.GbChannel" useGeneratedKeys="true" keyProperty="id">
        insert into ard_gb_channel
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="gbDeviceId != null">gb_device_id,</if>
            <if test="gbChannelId != null">gb_channel_id,</if>
            <if test="channelName != null">channel_name,</if>
            <if test="deviceCode != null">device_code,</if>
            <if test="streamMode != null">stream_mode,</if>
            <if test="enableMp4 != null">enable_mp4,</if>
            <if test="streamStatus != null">stream_status,</if>
            <if test="mediaServerId != null">media_server_id,</if>
            <if test="streamKey != null">stream_key,</if>
            <if test="snap != null">snap,</if>
            <if test="createBy != null">create_by,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="remark != null">remark,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="gbDeviceId != null">#{gbDeviceId},</if>
            <if test="gbChannelId != null">#{gbChannelId},</if>
            <if test="channelName != null">#{channelName},</if>
            <if test="deviceCode != null">#{deviceCode},</if>
            <if test="streamMode != null">#{streamMode},</if>
            <if test="enableMp4 != null">#{enableMp4},</if>
            <if test="streamStatus != null">#{streamStatus},</if>
            <if test="mediaServerId != null">#{mediaServerId},</if>
            <if test="streamKey != null">#{streamKey},</if>
            <if test="snap != null">#{snap},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="remark != null">#{remark},</if>
        </trim>
    </insert>
    <update id="updateGbChannel" parameterType="com.ard.gb28181.domain.GbChannel">
        update ard_gb_channel
        <trim prefix="SET" suffixOverrides=",">
            <if test="channelName != null">channel_name = #{channelName},</if>
            <if test="deviceCode != null">device_code = #{deviceCode},</if>
            <if test="streamMode != null">stream_mode = #{streamMode},</if>
            <if test="enableMp4 != null">enable_mp4 = #{enableMp4},</if>
            <if test="streamStatus != null">stream_status = #{streamStatus},</if>
            <if test="mediaServerId != null">media_server_id = #{mediaServerId},</if>
            <if test="streamKey != null">stream_key = #{streamKey},</if>
            <if test="snap != null">snap = #{snap},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="remark != null">remark = #{remark},</if>
        </trim>
        where id = #{id}
    </update>
    <update id="updateGbChannelStream">
        update ard_gb_channel
        <trim prefix="SET" suffixOverrides=",">
            <if test="streamStatus != null">stream_status = #{streamStatus},</if>
            <if test="streamKey != null">stream_key = #{streamKey},</if>
            <if test="mediaServerId != null">media_server_id = #{mediaServerId},</if>
            <if test="snap != null">snap = #{snap},</if>
            update_by = #{updateBy},
            update_time = #{updateTime}
        </trim>
        where id = #{id}
    </update>
    <delete id="deleteGbChannelById" parameterType="Long">
        delete from ard_gb_channel where id = #{id}
    </delete>
    <delete id="deleteGbChannelByIds" parameterType="String">
        delete from ard_gb_channel where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach>
    </delete>
</mapper>
ard-modules/ard-modules-gb28181/src/main/resources/mapper/gb28181/GbDeviceMapper.xml
New file
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ard.gb28181.mapper.GbDeviceMapper">
    <resultMap type="com.ard.gb28181.domain.GbDevice" id="GbDeviceResult">
        <id property="id" column="id"/>
        <result property="gbDeviceId" column="gb_device_id"/>
        <result property="deviceName" column="device_name"/>
        <result property="deviceCode" column="device_code"/>
        <result property="ip" column="ip"/>
        <result property="port" column="port"/>
        <result property="manufacturer" column="manufacturer"/>
        <result property="model" column="model"/>
        <result property="firmware" column="firmware"/>
        <result property="onLine" column="online"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="remark" column="remark"/>
    </resultMap>
    <sql id="selectGbDeviceVo">
        select id, gb_device_id, device_name, device_code, ip, port,
               manufacturer, model, firmware, online,
               create_by, create_time, update_by, update_time, remark
        from ard_gb_device
    </sql>
    <select id="selectGbDeviceById" parameterType="Long" resultMap="GbDeviceResult">
        <include refid="selectGbDeviceVo"/> where id = #{id}
    </select>
    <select id="selectGbDeviceByGbDeviceId" parameterType="String" resultMap="GbDeviceResult">
        <include refid="selectGbDeviceVo"/> where gb_device_id = #{gbDeviceId}
    </select>
    <select id="selectGbDeviceList" parameterType="com.ard.gb28181.domain.GbDevice" resultMap="GbDeviceResult">
        <include refid="selectGbDeviceVo"/>
        <where>
            <if test="gbDeviceId != null and gbDeviceId != ''">
                and gb_device_id like concat('%', #{gbDeviceId}, '%')
            </if>
            <if test="deviceName != null and deviceName != ''">
                and device_name like concat('%', #{deviceName}, '%')
            </if>
            <if test="deviceCode != null and deviceCode != ''">
                and device_code like concat('%', #{deviceCode}, '%')
            </if>
        </where>
    </select>
    <insert id="insertGbDevice" parameterType="com.ard.gb28181.domain.GbDevice" useGeneratedKeys="true" keyProperty="id">
        insert into ard_gb_device
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="gbDeviceId != null">gb_device_id,</if>
            <if test="deviceName != null">device_name,</if>
            <if test="deviceCode != null">device_code,</if>
            <if test="ip != null">ip,</if>
            <if test="port != null">port,</if>
            <if test="manufacturer != null">manufacturer,</if>
            <if test="model != null">model,</if>
            <if test="firmware != null">firmware,</if>
            <if test="onLine != null">online,</if>
            <if test="createBy != null">create_by,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="remark != null">remark,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="gbDeviceId != null">#{gbDeviceId},</if>
            <if test="deviceName != null">#{deviceName},</if>
            <if test="deviceCode != null">#{deviceCode},</if>
            <if test="ip != null">#{ip},</if>
            <if test="port != null">#{port},</if>
            <if test="manufacturer != null">#{manufacturer},</if>
            <if test="model != null">#{model},</if>
            <if test="firmware != null">#{firmware},</if>
            <if test="onLine != null">#{onLine},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="remark != null">#{remark},</if>
        </trim>
    </insert>
    <update id="updateGbDevice" parameterType="com.ard.gb28181.domain.GbDevice">
        update ard_gb_device
        <trim prefix="SET" suffixOverrides=",">
            <if test="deviceName != null">device_name = #{deviceName},</if>
            <if test="deviceCode != null">device_code = #{deviceCode},</if>
            <if test="ip != null">ip = #{ip},</if>
            <if test="port != null">port = #{port},</if>
            <if test="manufacturer != null">manufacturer = #{manufacturer},</if>
            <if test="model != null">model = #{model},</if>
            <if test="firmware != null">firmware = #{firmware},</if>
            <if test="onLine != null">online = #{onLine},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="remark != null">remark = #{remark},</if>
        </trim>
        where id = #{id}
    </update>
    <delete id="deleteGbDeviceById" parameterType="Long">
        delete from ard_gb_device where id = #{id}
    </delete>
    <delete id="deleteGbDeviceByIds" parameterType="String">
        delete from ard_gb_device where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach>
    </delete>
</mapper>
ard-modules/ard-modules-qs/pom.xml
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/ArdQSApplication.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/api/QsDeviceApiController.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/common/GbCode.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/common/SystemAllInfo.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/common/VideoManagerConstants.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/config/CivilCodeFileConf.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/config/ThreadPoolTaskConfig.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsDeviceController.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsGroupController.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsRegionController.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/controller/QsServerController.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceStats.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceToGroupParam.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceToRegionParam.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceType.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/DeviceTypeEnum.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/IndustryCodeType.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/IndustryCodeTypeEnum.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/NetworkIdentificationType.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/NetworkIdentificationTypeEnum.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/Preset.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/QsGroupTree.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/QsRegionTree.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/domain/RecordPlanParam.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/mapper/QsDeviceMapper.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/mapper/QsGroupMapper.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/mapper/QsRegionMapper.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/runner/QsCommandLineRunner.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IQsDeviceService.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IQsGroupService.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IQsRegionService.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/IRedisCatchStorageService.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/QsDeviceServiceImpl.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/QsGroupServiceImpl.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/QsRegionServiceImpl.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/service/impl/RedisCatchStorageServiceImpl.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/task/SystemInfoTimerTask.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/DateUtil.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/StreamDetector.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/SystemInfoUtils.java
File was deleted
ard-modules/ard-modules-qs/src/main/java/com/ard/qs/utils/VideoSnapshotUtil.java
File was deleted
ard-modules/ard-modules-qs/src/main/resources/banner.txt
File was deleted
ard-modules/ard-modules-qs/src/main/resources/bootstrap.yml
File was deleted
ard-modules/ard-modules-qs/src/main/resources/civilCode.csv
File was deleted
ard-modules/ard-modules-qs/src/main/resources/gb_dict.json
File was deleted
ard-modules/ard-modules-qs/src/main/resources/logback.xml
File was deleted
ard-modules/ard-modules-qs/src/main/resources/mapper/qs/QsDeviceMapper.xml
File was deleted
ard-modules/ard-modules-qs/src/main/resources/mapper/qs/QsGroupMapper.xml
File was deleted
ard-modules/ard-modules-qs/src/main/resources/mapper/qs/QsRegionMapper.xml
File was deleted
ard-modules/ard-modules-work/pom.xml
@@ -193,10 +193,6 @@
            <artifactId>spring-test</artifactId>
            <version>5.3.18</version>
        </dependency>
        <dependency>
            <groupId>com.ard</groupId>
            <artifactId>ard-api-qs</artifactId>
        </dependency>
    </dependencies>
    <build>
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/api/ArdChannelApiController.java
@@ -1,20 +1,11 @@
package com.ard.work.device.channel.api;
import com.ard.common.core.domain.R;
import com.ard.common.core.utils.poi.ExcelUtil;
import com.ard.common.core.web.controller.BaseController;
import com.ard.common.core.web.domain.AjaxResult;
import com.ard.common.core.web.page.TableDataInfo;
import com.ard.common.log.annotation.Log;
import com.ard.common.log.enums.BusinessType;
import com.ard.common.security.annotation.InnerAuth;
import com.ard.common.security.annotation.RequiresPermissions;
import com.ard.qs.api.domain.QsDevice;
import com.ard.work.api.domian.ArdChannel;
import com.ard.work.device.channel.service.IArdChannelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/mapper/ArdChannelMapper.java
@@ -1,6 +1,5 @@
package com.ard.work.device.channel.mapper;
import com.ard.qs.api.domain.QsDevice;
import com.ard.work.api.domian.ArdChannel;
import org.apache.ibatis.annotations.Param;
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/service/IArdChannelService.java
@@ -1,6 +1,5 @@
package com.ard.work.device.channel.service;
import com.ard.qs.api.domain.QsDevice;
import com.ard.work.api.domian.ArdChannel;
import java.util.List;
ard-modules/ard-modules-work/src/main/java/com/ard/work/device/channel/service/impl/ArdChannelServiceImpl.java
@@ -1,17 +1,8 @@
package com.ard.work.device.channel.service.impl;
import com.ard.common.core.constant.CacheConstants;
import com.ard.common.core.constant.Constants;
import com.ard.common.core.constant.SecurityConstants;
import com.ard.common.core.constant.UserConstants;
import com.ard.common.core.domain.R;
import com.ard.common.core.enums.LiveStreamType;
import com.ard.common.core.utils.uuid.IdUtils;
import com.ard.common.redis.service.RedisService;
import com.ard.qs.api.RemoteQsDeviceService;
import com.ard.qs.api.domain.QsDevice;
import com.ard.work.api.domian.ArdCamera;
import com.ard.work.api.domian.ArdCameraHepu;
import com.ard.work.api.domian.ArdChannel;
import com.ard.work.device.channel.mapper.ArdChannelMapper;
import com.ard.work.device.channel.service.IArdChannelService;
@@ -19,9 +10,9 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
 * 通道管理Service业务层处理
@@ -34,8 +25,6 @@
public class ArdChannelServiceImpl implements IArdChannelService {
    @Resource
    private ArdChannelMapper ardChannelMapper;
    @Resource
    private RemoteQsDeviceService remoteQsDeviceService;
    @Resource
    private RedisService redisService;
@@ -105,11 +94,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteArdChannelByIds(String[] ids) {
        int i = ardChannelMapper.deleteArdChannelByIds(ids);
        if (i > 0) {
            R<Boolean> delR = remoteQsDeviceService.removeQsDevice(ids, SecurityConstants.INNER);
        }
        return i;
        return ardChannelMapper.deleteArdChannelByIds(ids);
    }
    /**
ard-modules/ard-modules-work/src/main/java/com/ard/work/websocket/config/PTZWebSocketInitializer.java
New file
@@ -0,0 +1,24 @@
package com.ard.work.websocket.config;
import com.ard.work.websocket.utils.PTZWebSocketUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
/**
 * 将 wsPushExecutor 静态注入 PTZWebSocketUtils,启用异步并行广播
 *
 * @author 刘苏义
 */
@Component
public class PTZWebSocketInitializer {
    @Resource(name = "wsPushExecutor")
    private ThreadPoolTaskExecutor wsPushExecutor;
    @PostConstruct
    public void init() {
        PTZWebSocketUtils.setPushExecutor(wsPushExecutor);
    }
}
ard-modules/ard-modules-zlm/pom.xml
@@ -92,11 +92,6 @@
            <groupId>com.ard</groupId>
            <artifactId>ard-api-zlm</artifactId>
        </dependency>
        <!-- 泉视 接口 -->
        <dependency>
            <groupId>com.ard</groupId>
            <artifactId>ard-api-qs</artifactId>
        </dependency>
        <!-- gb28181 接口 -->
        <dependency>
            <groupId>com.ard</groupId>
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/controller/ZlmController.java
@@ -11,8 +11,8 @@
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.zlm.domain.StreamChannel;
import com.ard.zlm.service.ZlmStreamService;
import com.ard.work.api.RemoteCameraService;
import com.ard.zlm.api.domain.*;
import com.ard.zlm.common.InviteErrorCode;
@@ -68,7 +68,7 @@
    private RemoteGb28181Service remoteGb28181Service;
    @Resource
    private RemoteQsDeviceService remoteQsDeviceService;
    private ZlmStreamService zlmStreamService;
    @Resource
    @Lazy
@@ -502,50 +502,50 @@
        log.info("[gb28181 开始点播] id:{} ", id);
        Assert.notNull(id, "设备id");
        R<QsDevice> qsDevicer = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
        R<StreamChannel> qsDevicer = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
        if (qsDevicer.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("获取设备信息失败 id:" + id);
        }
        Assert.notNull(qsDevicer.getData(), "设备不存在 id:" + id);
        QsDevice qsDevice = qsDevicer.getData();
        StreamChannel streamChannel = qsDevicer.getData();
        if ("OFFLINE".equals(qsDevice.getDeviceStatus())) {
        if (!Boolean.TRUE.equals(streamChannel.getDeviceOnLine())) {
            throw new RuntimeException("设备不在线 id:" + id);
        }
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(qsDevice.getGbDeviceId(), SecurityConstants.INNER);
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(streamChannel.getGbDeviceId(), SecurityConstants.INNER);
        if (deviceR.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("gb28181 获取设备信息失败 id:" + qsDevice.getGbDeviceId());
            throw new RuntimeException("gb28181 获取设备信息失败 id:" + streamChannel.getGbDeviceId());
        }
        Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 id:" + qsDevice.getGbDeviceId());
        Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 id:" + streamChannel.getGbDeviceId());
        if (!deviceR.getData().isOnLine()) {
            throw new RuntimeException("gb28181 国标设备不在线失败 id:" + qsDevice.getGbDeviceId());
            throw new RuntimeException("gb28181 国标设备不在线失败 id:" + streamChannel.getGbDeviceId());
        }
        R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(qsDevice.getGbDeviceId(), qsDevice.getGbChannelId(), SecurityConstants.INNER);
        R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(streamChannel.getGbDeviceId(), streamChannel.getGbChannelId(), SecurityConstants.INNER);
        if (deviceChannelR.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + qsDevice.getGbDeviceId() + ",gbChannelId:" + qsDevice.getGbChannelId());
            throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + streamChannel.getGbDeviceId() + ",gbChannelId:" + streamChannel.getGbChannelId());
        }
        Assert.notNull(deviceChannelR.getData(), "gb28181 获取设备通道失败不存在 gbDeviceId:" + qsDevice.getGbDeviceId() + ",gbChannelId:" + qsDevice.getGbChannelId());
        Assert.notNull(deviceChannelR.getData(), "gb28181 获取设备通道失败不存在 gbDeviceId:" + streamChannel.getGbDeviceId() + ",gbChannelId:" + streamChannel.getGbChannelId());
        if (!"ON".equals(deviceChannelR.getData().getStatus())) {
            throw new RuntimeException("gb28181 国标设备通道不在线失败 gbDeviceId:" + qsDevice.getGbDeviceId() + ",gbChannelId:" + qsDevice.getGbChannelId());
            throw new RuntimeException("gb28181 国标设备通道不在线失败 gbDeviceId:" + streamChannel.getGbDeviceId() + ",gbChannelId:" + streamChannel.getGbChannelId());
        }
        DeferredResult<R<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
        result.onTimeout(() -> {
            log.info("[点播等待超时] gbDeviceId:{}, gbChannelId:{}, ", qsDevice.getGbDeviceId(), qsDevice.getGbChannelId());
            log.info("[点播等待超时] gbDeviceId:{}, gbChannelId:{}, ", streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
            // 释放rtpserver
            R<StreamContent> wvpResult = R.fail();
            wvpResult.setMsg("点播超时");
            result.setResult(wvpResult);
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, qsDevice.getId());
            mediaServerService.stopGb28181Play(InviteSessionType.PLAY, qsDevice, deviceR.getData(), qsDevice.getDeviceCode());
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
            mediaServerService.stopGb28181Play(InviteSessionType.PLAY, streamChannel, deviceR.getData(), streamChannel.getDeviceCode());
        });
        ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
@@ -578,8 +578,8 @@
            }
        };
        qsDevice.setStreamMode(deviceR.getData().getStreamMode());
        mediaServerService.startGb28181Play(qsDevice, deviceR.getData(), callback);
        streamChannel.setStreamMode(deviceR.getData().getStreamMode());
        mediaServerService.startGb28181Play(streamChannel, deviceR.getData(), callback);
        return result;
    }
@@ -595,43 +595,43 @@
        log.info("[gb28181 停止点播] id:{} ", id);
        Assert.notNull(id, "设备id");
        R<QsDevice> qsDevicer = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
        R<StreamChannel> qsDevicer = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
        if (qsDevicer.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("获取设备信息失败 id:" + id);
        }
        Assert.notNull(qsDevicer.getData(), "设备不存在 id:" + id);
        QsDevice qsDevice = qsDevicer.getData();
        StreamChannel streamChannel = qsDevicer.getData();
        if ("OFFLINE".equals(qsDevice.getDeviceStatus())) {
        if (!Boolean.TRUE.equals(streamChannel.getDeviceOnLine())) {
            throw new RuntimeException("设备不在线 id:" + id);
        }
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(qsDevice.getGbDeviceId(), SecurityConstants.INNER);
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(streamChannel.getGbDeviceId(), SecurityConstants.INNER);
        if (deviceR.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("gb28181 获取设备信息失败 id:" + qsDevice.getGbDeviceId());
            throw new RuntimeException("gb28181 获取设备信息失败 id:" + streamChannel.getGbDeviceId());
        }
        Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 id:" + qsDevice.getGbDeviceId());
        Assert.notNull(deviceR.getData(), "gb28181 国标设备不存在 id:" + streamChannel.getGbDeviceId());
        if (!deviceR.getData().isOnLine()) {
            throw new RuntimeException("gb28181 国标设备不在线失败 id:" + qsDevice.getGbDeviceId());
            throw new RuntimeException("gb28181 国标设备不在线失败 id:" + streamChannel.getGbDeviceId());
        }
        R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(qsDevice.getGbDeviceId(), qsDevice.getGbChannelId(), SecurityConstants.INNER);
        R<DeviceChannel> deviceChannelR = remoteGb28181Service.getDeviceChannelByChannelId(streamChannel.getGbDeviceId(), streamChannel.getGbChannelId(), SecurityConstants.INNER);
        if (deviceChannelR.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + qsDevice.getGbDeviceId() + ",gbChannelId:" + qsDevice.getGbChannelId());
            throw new RuntimeException("gb28181 获取设备通道失败 gbDeviceId:" + streamChannel.getGbDeviceId() + ",gbChannelId:" + streamChannel.getGbChannelId());
        }
        Assert.notNull(deviceChannelR.getData(), "gb28181 获取设备通道失败不存在 gbDeviceId:" + qsDevice.getGbDeviceId() + ",gbChannelId:" + qsDevice.getGbChannelId());
        Assert.notNull(deviceChannelR.getData(), "gb28181 获取设备通道失败不存在 gbDeviceId:" + streamChannel.getGbDeviceId() + ",gbChannelId:" + streamChannel.getGbChannelId());
        if (!"ON".equals(deviceChannelR.getData().getStatus())) {
            throw new RuntimeException("gb28181 国标设备通道不在线失败 gbDeviceId:" + qsDevice.getGbDeviceId() + ",gbChannelId:" + qsDevice.getGbChannelId());
            throw new RuntimeException("gb28181 国标设备通道不在线失败 gbDeviceId:" + streamChannel.getGbDeviceId() + ",gbChannelId:" + streamChannel.getGbChannelId());
        }
        mediaServerService.stopGb28181Play(InviteSessionType.PLAY, qsDevice, deviceR.getData(), qsDevice.getDeviceCode());
        mediaServerService.stopGb28181Play(InviteSessionType.PLAY, streamChannel, deviceR.getData(), streamChannel.getDeviceCode());
        JSONObject json = new JSONObject();
        json.put("deviceId", qsDevice.getGbDeviceId());
        json.put("channelId", qsDevice.getGbChannelId());
        json.put("deviceId", streamChannel.getGbDeviceId());
        json.put("channelId", streamChannel.getGbChannelId());
        return AjaxResult.success(json);
    }
@@ -662,7 +662,7 @@
        }
        Assert.notNull(channelR.getData(), "GbChannel不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
        GbChannelDTO gbChannelDTO = channelR.getData();
        StreamChannel streamChannel = ZlmStreamService.toStreamChannel(channelR.getData());
        // 2. 查询国标设备
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
@@ -694,8 +694,8 @@
            fail.setMsg("点播超时");
            result.setResult(fail);
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
            mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO, deviceR.getData(), gbChannelDTO.getDeviceCode());
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
            mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, streamChannel, deviceR.getData(), streamChannel.getDeviceCode());
        });
        ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
@@ -728,7 +728,7 @@
            }
        };
        mediaServerService.startGb28181PlayByGbChannel(gbChannelDTO, deviceR.getData(), callback);
        mediaServerService.startGb28181PlayByGbChannel(streamChannel, deviceR.getData(), callback);
        return result;
    }
@@ -755,7 +755,7 @@
            throw new RuntimeException("GbChannel不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
        }
        GbChannelDTO gbChannelDTO = channelR.getData();
        StreamChannel streamChannel = ZlmStreamService.toStreamChannel(channelR.getData());
        // 2. 查询国标设备
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
@@ -771,8 +771,8 @@
        }
        Assert.notNull(deviceChannelR.getData(), "gb28181 国标设备通道不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
        mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO,
                deviceR.getData(), gbChannelDTO.getDeviceCode());
        mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, streamChannel,
                deviceR.getData(), streamChannel.getDeviceCode());
        JSONObject json = new JSONObject();
        json.put("gbDeviceId", gbDeviceId);
@@ -803,9 +803,9 @@
        }
        Assert.notNull(channelR.getData(), "GbChannel不存在 channelId:" + channelId);
        GbChannelDTO gbChannelDTO = channelR.getData();
        String gbDeviceId = gbChannelDTO.getGbDeviceId();
        String gbChannelId = gbChannelDTO.getGbChannelId();
        StreamChannel streamChannel = ZlmStreamService.toStreamChannel(channelR.getData());
        String gbDeviceId = streamChannel.getGbDeviceId();
        String gbChannelId = streamChannel.getGbChannelId();
        // 2. 查询国标设备
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
@@ -837,8 +837,8 @@
            fail.setMsg("点播超时");
            result.setResult(fail);
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
            mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO, deviceR.getData(), gbChannelDTO.getDeviceCode());
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
            mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, streamChannel, deviceR.getData(), streamChannel.getDeviceCode());
        });
        ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
@@ -871,7 +871,7 @@
            }
        };
        mediaServerService.startGb28181PlayByGbChannel(gbChannelDTO, deviceR.getData(), callback);
        mediaServerService.startGb28181PlayByGbChannel(streamChannel, deviceR.getData(), callback);
        return result;
    }
@@ -893,9 +893,9 @@
            throw new RuntimeException("GbChannel不存在 channelId:" + channelId);
        }
        GbChannelDTO gbChannelDTO = channelR.getData();
        String gbDeviceId = gbChannelDTO.getGbDeviceId();
        String gbChannelId = gbChannelDTO.getGbChannelId();
        StreamChannel streamChannel = ZlmStreamService.toStreamChannel(channelR.getData());
        String gbDeviceId = streamChannel.getGbDeviceId();
        String gbChannelId = streamChannel.getGbChannelId();
        // 2. 查询国标设备
        R<Device> deviceR = remoteGb28181Service.getDeviceByDeviceId(gbDeviceId, SecurityConstants.INNER);
@@ -911,8 +911,8 @@
        }
        Assert.notNull(deviceChannelR.getData(), "gb28181 国标设备通道不存在 gbDeviceId:" + gbDeviceId + " gbChannelId:" + gbChannelId);
        mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, gbChannelDTO,
                deviceR.getData(), gbChannelDTO.getDeviceCode());
        mediaServerService.stopGb28181PlayByGbChannel(InviteSessionType.PLAY, streamChannel,
                deviceR.getData(), streamChannel.getDeviceCode());
        JSONObject json = new JSONObject();
        json.put("channelId", channelId);
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/domain/StreamChannel.java
New file
@@ -0,0 +1,60 @@
package com.ard.zlm.domain;
import lombok.Data;
/**
 * ZLM 内部流通道对象
 * <p>
 * 统一表示可播放的通道,无论来源是国标设备(GbChannel)还是普通相机。
 */
@Data
public class StreamChannel {
    /** 通道ID */
    private Long id;
    /** 通道名称 */
    private String channelName;
    /** 设备编码(流标识) */
    private String deviceCode;
    /** 流标识(ZLM stream key) */
    private String streamKey;
    /** 流媒体服务ID */
    private String mediaServerId;
    /** 流状态(0=停止, 1=直播中) */
    private String streamStatus;
    /** 开启mp4录制 */
    private String enableMp4;
    /** 截图路径 */
    private String snap;
    /** 国标设备编码(仅国标通道) */
    private String gbDeviceId;
    /** 国标通道编码(仅国标通道) */
    private String gbChannelId;
    /** 流传输模式 */
    private String streamMode;
    /** 通道类型:gb28181 / camera */
    private String channelType;
    /** 流接入类型(兼容旧QsDevice: 1=RTSP,2=RTMP,12=GB28181,13=PUSH) */
    private String type;
    /** 状态(兼容旧QsDevice: ENABLE/DEACTIVATE) */
    private String status;
    /** 直播流地址(兼容旧QsDevice,国标通道不需要) */
    private String liveAddress;
    /** 父设备在线状态(用于判断能否播放) */
    private Boolean deviceOnLine;
}
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/IDevicePlayService.java
@@ -1,6 +1,6 @@
package com.ard.zlm.service;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.domain.StreamChannel;
import com.ard.work.api.domian.ArdChannel;
import com.ard.zlm.api.domain.StreamInfo;
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/IMediaServerService.java
@@ -1,8 +1,8 @@
package com.ard.zlm.service;
import com.ard.gb28181.api.domain.Device;
import com.ard.gb28181.api.domain.GbChannelDTO;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.domain.StreamChannel;
import com.ard.zlm.domain.StreamChannel;
import com.ard.work.api.domian.ArdChannel;
import com.ard.zlm.api.domain.*;
import com.ard.zlm.common.InviteSessionType;
@@ -336,11 +336,11 @@
    /**
     * gb28181 播放
     *
     * @param qsDevice
     * @param streamChannel
     * @param gbDevice
     * @param callback
     */
    void startGb28181Play(QsDevice qsDevice, Device gbDevice, ErrorCallback<StreamInfo> callback);
    void startGb28181Play(StreamChannel streamChannel, Device gbDevice, ErrorCallback<StreamInfo> callback);
    /**
     * 连接rtp服务
@@ -357,19 +357,19 @@
     * gb28181 停止点播
     *
     * @param type
     * @param qsDevice
     * @param streamChannel
     * @param device
     * @param stream
     */
    void stopGb28181Play(InviteSessionType type, QsDevice qsDevice, Device device, String stream);
    void stopGb28181Play(InviteSessionType type, StreamChannel streamChannel, Device device, String stream);
    /**
     * gb28181 播放(基于GbChannel,不依赖QS)
     */
    void startGb28181PlayByGbChannel(GbChannelDTO gbChannelDTO, Device gbDevice, ErrorCallback<StreamInfo> callback);
    void startGb28181PlayByGbChannel(StreamChannel streamChannel, Device gbDevice, ErrorCallback<StreamInfo> callback);
    /**
     * gb28181 停止点播(基于GbChannel,不依赖QS)
     */
    void stopGb28181PlayByGbChannel(InviteSessionType type, GbChannelDTO gbChannelDTO, Device device, String stream);
    void stopGb28181PlayByGbChannel(InviteSessionType type, StreamChannel streamChannel, Device device, String stream);
}
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/ISourcePlayService.java
@@ -1,6 +1,6 @@
package com.ard.zlm.service;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.domain.StreamChannel;
import com.ard.work.api.domian.ArdChannel;
import com.ard.zlm.api.domain.StreamInfo;
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/ZlmStreamService.java
New file
@@ -0,0 +1,107 @@
package com.ard.zlm.service;
import com.ard.common.core.constant.SecurityConstants;
import com.ard.common.core.domain.R;
import com.ard.gb28181.api.RemoteGb28181Service;
import com.ard.gb28181.api.domain.GbChannelDTO;
import com.ard.zlm.domain.StreamChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * ZLM流媒体本地服务(统一管理国标通道和普通相机通道的流状态)
 */
@Slf4j
@Service
public class ZlmStreamService {
    @Autowired
    private RemoteGb28181Service remoteGb28181Service;
    /**
     * 根据ID获取通道信息
     */
    public R<StreamChannel> getQsDeviceInfo(Long id, String inner) {
        try {
            R<GbChannelDTO> r = remoteGb28181Service.getGbChannelById(id, SecurityConstants.INNER);
            if (r != null && r.getData() != null && r.getData().getId() != null) {
                return R.ok(toStreamChannel(r.getData()));
            }
        } catch (Exception e) {
            log.error("[ZlmStream] 查询通道信息失败 id={}", id, e);
        }
        return R.ok(new StreamChannel());
    }
    /**
     * 根据流标识获取通道
     */
    public R<StreamChannel> getQsDeviceStream(String stream, String inner) {
        log.debug("[ZlmStream] 查找流: stream={}", stream);
        return R.ok(new StreamChannel());
    }
    /**
     * 更新通道流信息
     */
    public R<Boolean> updateQsDevice(StreamChannel streamChannel, String inner) {
        try {
            if (streamChannel.getId() != null && streamChannel.getId() > 0) {
                GbChannelDTO dto = new GbChannelDTO();
                dto.setId(streamChannel.getId());
                dto.setStreamKey(streamChannel.getStreamKey());
                dto.setMediaServerId(streamChannel.getMediaServerId());
                dto.setStreamStatus(streamChannel.getStreamStatus());
                dto.setSnap(streamChannel.getSnap());
                R<Boolean> r = remoteGb28181Service.updateGbChannelStream(dto, SecurityConstants.INNER);
                if (r != null && r.getData() != null) {
                    return r;
                }
            }
        } catch (Exception e) {
            log.error("[ZlmStream] 更新流信息失败 id={}", streamChannel.getId(), e);
        }
        return R.ok(false);
    }
    /**
     * 新增通道
     */
    public R<Boolean> addQsDevice(StreamChannel streamChannel, String inner) {
        log.info("[ZlmStream] 新增通道请求: channelName={}, channelType={}",
                streamChannel.getChannelName(), streamChannel.getChannelType());
        return R.ok(true);
    }
    /**
     * 根据计划ID统计设备数量
     */
    public R<Integer> countRecordPlanDevice(Long planId, String inner) {
        return R.ok(0);
    }
    /**
     * 清理设备计划ID
     */
    public R<Void> cleanRecordPlanId(Long planId, String inner) {
        return R.ok();
    }
    public static StreamChannel toStreamChannel(GbChannelDTO c) {
        StreamChannel sc = new StreamChannel();
        sc.setId(c.getId());
        sc.setChannelName(c.getChannelName());
        sc.setDeviceCode(c.getDeviceCode());
        sc.setStreamKey(c.getStreamKey());
        sc.setMediaServerId(c.getMediaServerId());
        sc.setStreamStatus(c.getStreamStatus());
        sc.setSnap(c.getSnap());
        sc.setEnableMp4(c.getEnableMp4());
        sc.setGbDeviceId(c.getGbDeviceId());
        sc.setGbChannelId(c.getGbChannelId());
        sc.setStreamMode(c.getStreamMode());
        sc.setChannelType("gb28181");
        return sc;
    }
}
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/DevicePlayServiceImpl.java
@@ -1,7 +1,7 @@
package com.ard.zlm.service.impl;
import com.ard.common.core.enums.LiveStreamType;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.domain.StreamChannel;
import com.ard.work.api.domian.ArdChannel;
import com.ard.zlm.api.domain.StreamInfo;
import com.ard.zlm.service.ErrorCallback;
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java
@@ -11,9 +11,9 @@
import com.ard.common.core.utils.file.FileMultipartFile;
import com.ard.gb28181.api.RemoteGb28181Service;
import com.ard.gb28181.api.domain.Device;
import com.ard.gb28181.api.domain.GbChannelDTO;
import com.ard.qs.api.RemoteQsDeviceService;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.domain.StreamChannel;
import com.ard.zlm.service.ZlmStreamService;
import com.ard.zlm.domain.StreamChannel;
import com.ard.system.api.RemoteFileService;
import com.ard.system.api.domain.SysFile;
import com.ard.work.api.RemoteCameraService;
@@ -106,7 +106,7 @@
    private HookSubscribe subscribe;
    @Resource
    private RemoteQsDeviceService remoteQsDeviceService;
    private ZlmStreamService zlmStreamService;
    @Resource
    private RemoteChannelService remoteChannelService;
@@ -185,7 +185,7 @@
        }
        redisCatchStorage.updateStreamAuthorityInfo(event.getApp(), event.getStream(), streamAuthorityInfo);
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
        R<StreamChannel> r = zlmStreamService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
                SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            log.error("获取设备信息失败,stream:{}", event.getStream());
@@ -193,7 +193,7 @@
        }
        if (r.getData() == null) {
            r = remoteQsDeviceService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
            r = zlmStreamService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                log.error("获取设备信息失败,stream:{}", event.getStream());
                return;
@@ -201,10 +201,9 @@
        }
        if (r.getData() == null) {
            QsDevice device = new QsDevice();
            device.setDeviceStatus("ON");
            StreamChannel device = new StreamChannel();
            device.setMediaServerId(mediaInfo.getMediaServer().getId());
            device.setDeviceName("推流设备_" + event.getApp() + "_" + event.getStream());
            device.setChannelName("推流设备_" + event.getApp() + "_" + event.getStream());
            device.setType(LiveStreamType.PUSH.getCode());
            device.setStatus("ENABLE");
            device.setStreamStatus("1");
@@ -214,7 +213,7 @@
            String filePath = snapOnPlay(mediaInfo.getMediaServer(), event.getApp(), event.getStream());
            device.setSnap(filePath);
            R<Boolean> addR = remoteQsDeviceService.addQsDevice(device, SecurityConstants.INNER);
            R<Boolean> addR = zlmStreamService.addQsDevice(device, SecurityConstants.INNER);
            if (addR.getCode() != Constants.SUCCESS) {
                throw new RuntimeException("添加推流设备设备失败" + event.getApp() + "_" + event.getStream());
            }
@@ -223,15 +222,14 @@
                throw new RuntimeException("添加推流设备设备失败" + event.getApp() + "_" + event.getStream());
            }
        } else {
            QsDevice device = new QsDevice();
            device.setDeviceStatus("ON");
            StreamChannel device = new StreamChannel();
            device.setMediaServerId(mediaInfo.getMediaServer().getId());
            device.setStreamKey(r.getData().getDeviceCode());
            device.setStreamStatus("1");
            device.setId(r.getData().getId());
            String filePath = snapOnPlay(mediaInfo.getMediaServer(), event.getApp(), event.getStream());
            device.setSnap(filePath);
            R<Boolean> updateR = remoteQsDeviceService.updateQsDevice(device, SecurityConstants.INNER);
            R<Boolean> updateR = zlmStreamService.updateQsDevice(device, SecurityConstants.INNER);
            if (updateR.getCode() != Constants.SUCCESS) {
                throw new RuntimeException("修改推流设备设备失败" + event.getApp() + "_" + event.getStream());
            }
@@ -269,7 +267,7 @@
            if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) {
                inviteStreamService.removeInviteInfo(inviteInfo);
                R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(Long.valueOf(inviteInfo.getDeviceId()),
                R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(Long.valueOf(inviteInfo.getDeviceId()),
                        SecurityConstants.INNER);
                if (r.getCode() != Constants.SUCCESS) {
                    return;
@@ -301,7 +299,7 @@
        }
        if ("video_file".equals(event.getApp())) {
            R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
            R<StreamChannel> r = zlmStreamService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                return;
            }
@@ -310,12 +308,12 @@
                return;
            }
            QsDevice qsDevice = new QsDevice();
            qsDevice.setId(r.getData().getId());
            qsDevice.setStreamKey("");
            qsDevice.setMediaServerId("");
            qsDevice.setStreamStatus("0");
            R<Boolean> qsDevicer = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
            StreamChannel streamChannel = new StreamChannel();
            streamChannel.setId(r.getData().getId());
            streamChannel.setStreamKey("");
            streamChannel.setMediaServerId("");
            streamChannel.setStreamStatus("0");
            R<Boolean> qsDevicer = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
            if (qsDevicer.getCode() != Constants.SUCCESS) {
                log.error("更新设备失败");
            }
@@ -343,7 +341,7 @@
            redisCatchStorage.removePushListItem(event.getApp(), event.getStream(), event.getMediaServer().getId());
        }
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
        R<StreamChannel> r = zlmStreamService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
                SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            log.error("获取设备信息失败,stream:{}", event.getStream());
@@ -351,7 +349,7 @@
        }
        if (r.getData() == null) {
            r = remoteQsDeviceService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
            r = zlmStreamService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                log.error("获取设备信息失败,stream:{}", event.getStream());
                return;
@@ -361,13 +359,12 @@
        if (r.getData() == null) {
            return;
        }
        QsDevice device = new QsDevice();
        device.setDeviceStatus("OFFLINE");
        StreamChannel device = new StreamChannel();
        device.setMediaServerId("");
        device.setStreamKey("");
        device.setStreamStatus("0");
        device.setId(r.getData().getId());
        R<Boolean> updateR = remoteQsDeviceService.updateQsDevice(device, SecurityConstants.INNER);
        R<Boolean> updateR = zlmStreamService.updateQsDevice(device, SecurityConstants.INNER);
        if (updateR.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("修改推流设备设备失败" + event.getApp() + "_" + event.getStream());
        }
@@ -991,7 +988,7 @@
            return;
        }
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            callback.run(InviteErrorCode.FAIL.getCode(), "获取设备信息失败" + rtpServerParam.getId(), null);
            return;
@@ -1001,7 +998,7 @@
            return;
        }
        if ("OFFLINE".equals(r.getData().getDeviceStatus())) {
        if (!Boolean.TRUE.equals(Boolean.TRUE.equals(r.getData().getDeviceOnLine()))) {
            callback.run(InviteErrorCode.FAIL.getCode(), "设备不在线" + rtpServerParam.getId(), null);
            return;
        }
@@ -1024,7 +1021,7 @@
     * @param callback       回调
     * @return
     */
    private SSRCInfo play(ZlmMediaServer mediaServer, RTPServerParam rtpServerParam, QsDevice device, String ssrc,
    private SSRCInfo play(ZlmMediaServer mediaServer, RTPServerParam rtpServerParam, StreamChannel device, String ssrc,
                          ErrorCallback<StreamInfo> callback) {
        // 获取点播的状态信息
        InviteInfo inviteInfoInCatch = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY,
@@ -1123,13 +1120,13 @@
                    String filePath = snapOnPlay(streamInfo.getMediaServer(), streamInfo.getApp(),
                            streamInfo.getStream());
                    QsDevice qsDevice = new QsDevice();
                    qsDevice.setId(rtpServerParam.getId());
                    qsDevice.setStreamKey(rtpServerParam.getStreamId());
                    qsDevice.setMediaServerId(mediaServer.getId());
                    qsDevice.setStreamStatus("1");
                    qsDevice.setSnap(filePath);
                    R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
                    StreamChannel streamChannel = new StreamChannel();
                    streamChannel.setId(rtpServerParam.getId());
                    streamChannel.setStreamKey(rtpServerParam.getStreamId());
                    streamChannel.setMediaServerId(mediaServer.getId());
                    streamChannel.setStreamStatus("1");
                    streamChannel.setSnap(filePath);
                    R<Boolean> r = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                    if (r.getCode() != Constants.SUCCESS) {
                        throw new RuntimeException("更新设备失败");
                    }
@@ -1217,14 +1214,14 @@
     */
    @Override
    public void stopRtpPlay(RTPServerParam rtpServerParam) {
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("获取设备信息失败");
        }
        if (r.getData() == null) {
            throw new RuntimeException("设备不存在");
        }
        QsDevice device = r.getData();
        StreamChannel device = r.getData();
        String mediaServerId = device.getMediaServerId();
        ZlmMediaServer mediaServer = getOne(mediaServerId);
@@ -1241,12 +1238,12 @@
            }
        }
        QsDevice qsDevice = new QsDevice();
        qsDevice.setId(rtpServerParam.getId());
        qsDevice.setStreamKey("");
        qsDevice.setMediaServerId("");
        qsDevice.setStreamStatus("0");
        R<Boolean> devicer = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
        StreamChannel streamChannel = new StreamChannel();
        streamChannel.setId(rtpServerParam.getId());
        streamChannel.setStreamKey("");
        streamChannel.setMediaServerId("");
        streamChannel.setStreamStatus("0");
        R<Boolean> devicer = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
        if (devicer.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("更新设备失败");
        }
@@ -1287,7 +1284,7 @@
            return;
        }
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            callback.run(InviteErrorCode.FAIL.getCode(), "获取设备信息失败" + id, null);
            return;
@@ -1297,11 +1294,11 @@
            return;
        }
        if ("OFFLINE".equals(r.getData().getDeviceStatus())) {
        if (!Boolean.TRUE.equals(Boolean.TRUE.equals(r.getData().getDeviceOnLine()))) {
            throw new RuntimeException("设备不在线" + id);
        }
        QsDevice device = r.getData();
        StreamChannel device = r.getData();
        String videoPath = convertUrlToPath(device.getLiveAddress(), this.fileDomain, this.filePrefix, this.filePath);
        loadMP4File(mediaServer, "video_file", device.getDeviceCode(), id, videoPath, ((code, msg, streamInfo) -> {
@@ -1316,7 +1313,7 @@
     */
    @Override
    public void closeStreams(Long id) {
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("获取设备信息失败");
        }
@@ -1324,7 +1321,7 @@
            throw new RuntimeException("设备不存在");
        }
        QsDevice device = r.getData();
        StreamChannel device = r.getData();
        ZlmMediaServer mediaServer = getOne(device.getMediaServerId());
        if (mediaServer == null) {
@@ -1610,7 +1607,7 @@
     */
    @Override
    public Map<String, Object> getStreamPushAddress(Long id, String callId) {
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            throw new RuntimeException("获取设备信息失败");
        }
@@ -1640,7 +1637,7 @@
     */
    @Override
    public void streamPullPush(Long id, ErrorCallback<StreamInfo> callback) {
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
        if (r.getCode() != Constants.SUCCESS) {
            log.info("获取设备信息失败 id:{}", id);
            callback.run(InviteErrorCode.FAIL.getCode(), "获取设备信息失败", null);
@@ -1651,7 +1648,7 @@
            callback.run(InviteErrorCode.FAIL.getCode(), "设备不存在", null);
            return;
        }
        QsDevice device = r.getData();
        StreamChannel device = r.getData();
        if (!LiveStreamType.PUSH.getCode().equals(device.getType())) {
            log.info("直播流接入类型不对,应当是PUSH id:{}", id);
@@ -1672,10 +1669,10 @@
                callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(),
                        getStreamInfoByAppAndStream(mediaServer, "push", device.getDeviceCode(), mediaInfo));
                if ("0".equals(device.getStreamStatus())) {
                    QsDevice qsDevice = new QsDevice();
                    qsDevice.setId(id);
                    qsDevice.setStreamStatus("1");
                    R<Boolean> updateR = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
                    StreamChannel streamChannel = new StreamChannel();
                    streamChannel.setId(id);
                    streamChannel.setStreamStatus("1");
                    R<Boolean> updateR = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                    if (updateR.getCode() != Constants.SUCCESS) {
                        log.info("修改推流设备设备失败 id:{}", id);
                        throw new RuntimeException("修改推流设备设备失败");
@@ -1694,12 +1691,12 @@
    /**
     * gb28181 播放
     *
     * @param qsDevice
     * @param streamChannel
     * @param gbDevice
     * @param callback
     */
    @Override
    public void startGb28181Play(QsDevice qsDevice, Device gbDevice, ErrorCallback<StreamInfo> callback) {
    public void startGb28181Play(StreamChannel streamChannel, Device gbDevice, ErrorCallback<StreamInfo> callback) {
        ZlmMediaServer mediaServer = getMediaServerForMinimumLoad(null);
        if (mediaServer == null) {
@@ -1707,18 +1704,18 @@
            return;
        }
        int tcpMode = qsDevice.getStreamMode().equals("TCP-ACTIVE") ? 2 : (qsDevice.getStreamMode().equals("TCP" +
        int tcpMode = streamChannel.getStreamMode().equals("TCP-ACTIVE") ? 2 : (streamChannel.getStreamMode().equals("TCP" +
                "-PASSIVE") ? 1 : 0);
        RTPServerParam rtpServerParam = new RTPServerParam();
        rtpServerParam.setApp("gb28181");
        rtpServerParam.setMediaServer(mediaServer);
        rtpServerParam.setType(LiveStreamType.GB28181.getCode());
        rtpServerParam.setStreamId(qsDevice.getDeviceCode());
        rtpServerParam.setStreamId(streamChannel.getDeviceCode());
        rtpServerParam.setTcpMode(tcpMode);
        rtpServerParam.setId(qsDevice.getId());
        rtpServerParam.setId(streamChannel.getId());
        startGb28181PlayFun(mediaServer, qsDevice, gbDevice, rtpServerParam, null, callback);
        startGb28181PlayFun(mediaServer, streamChannel, gbDevice, rtpServerParam, null, callback);
    }
    /**
@@ -1744,21 +1741,21 @@
     * gb28181 停止点播
     *
     * @param type
     * @param qsDevice
     * @param streamChannel
     * @param device
     * @param stream
     */
    @Override
    public void stopGb28181Play(InviteSessionType type, QsDevice qsDevice, Device device, String stream) {
        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, qsDevice.getId(), stream);
    public void stopGb28181Play(InviteSessionType type, StreamChannel streamChannel, Device device, String stream) {
        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, streamChannel.getId(), stream);
        if (inviteInfo == null) {
            if (type == InviteSessionType.PLAY) {
                QsDevice qsDeviceUpdate = new QsDevice();
                qsDeviceUpdate.setId(qsDevice.getId());
                StreamChannel qsDeviceUpdate = new StreamChannel();
                qsDeviceUpdate.setId(streamChannel.getId());
                qsDeviceUpdate.setStreamKey("");
                qsDeviceUpdate.setMediaServerId("");
                qsDeviceUpdate.setStreamStatus("0");
                R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
                R<Boolean> r = zlmStreamService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
                if (r.getCode() != Constants.SUCCESS) {
                    throw new RuntimeException("更新设备失败");
                }
@@ -1768,18 +1765,18 @@
        inviteStreamService.removeInviteInfo(inviteInfo);
        if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
            try {
                log.info("[停止点播/回放/下载] {}/{}", qsDevice.getGbDeviceId(), qsDevice.getGbChannelId());
                log.info("[停止点播/回放/下载] {}/{}", streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
                RtpServerParam rtpServer = new RtpServerParam();
                rtpServer.setApp("gb28181");
                rtpServer.setStream(qsDevice.getDeviceCode());
                rtpServer.setGbDeviceId(qsDevice.getGbDeviceId());
                rtpServer.setGbChannelId(qsDevice.getGbChannelId());
                rtpServer.setStream(streamChannel.getDeviceCode());
                rtpServer.setGbDeviceId(streamChannel.getGbDeviceId());
                rtpServer.setGbChannelId(streamChannel.getGbChannelId());
                R<Void> r = remoteGb28181Service.streamByeCmd(rtpServer, SecurityConstants.INNER);
                if (r.getCode() != Constants.SUCCESS) {
                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", qsDevice.getGbDeviceId());
                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + qsDevice.getGbDeviceId());
                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", streamChannel.getGbDeviceId());
                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + streamChannel.getGbDeviceId());
                }
            } catch (Exception e) {
                log.error("[命令发送失败] 停止点播/回放/下载, 发送BYE: {}", e.getMessage());
@@ -1788,12 +1785,12 @@
        }
        if (inviteInfo.getType() == InviteSessionType.PLAY) {
            QsDevice qsDeviceUpdate = new QsDevice();
            qsDeviceUpdate.setId(qsDevice.getId());
            StreamChannel qsDeviceUpdate = new StreamChannel();
            qsDeviceUpdate.setId(streamChannel.getId());
            qsDeviceUpdate.setStreamKey("");
            qsDeviceUpdate.setMediaServerId("");
            qsDeviceUpdate.setStreamStatus("0");
            R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
            R<Boolean> r = zlmStreamService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                throw new RuntimeException("更新设备失败");
            }
@@ -1816,7 +1813,7 @@
     * gb28181 播放(基于GbDevice,不依赖QS)
     */
    @Override
    public void startGb28181PlayByGbChannel(GbChannelDTO gbChannelDTO, Device gbDevice, ErrorCallback<StreamInfo> callback) {
    public void startGb28181PlayByGbChannel(StreamChannel streamChannel, Device gbDevice, ErrorCallback<StreamInfo> callback) {
        ZlmMediaServer mediaServer = getMediaServerForMinimumLoad(null);
        if (mediaServer == null) {
@@ -1824,8 +1821,8 @@
            return;
        }
        String streamMode = gbChannelDTO.getStreamMode() != null
                ? gbChannelDTO.getStreamMode() : gbDevice.getStreamMode();
        String streamMode = streamChannel.getStreamMode() != null
                ? streamChannel.getStreamMode() : gbDevice.getStreamMode();
        int tcpMode = streamMode.equals("TCP-ACTIVE") ? 2
                : (streamMode.equals("TCP-PASSIVE") ? 1 : 0);
@@ -1833,27 +1830,27 @@
        rtpServerParam.setApp("gb28181");
        rtpServerParam.setMediaServer(mediaServer);
        rtpServerParam.setType(LiveStreamType.GB28181.getCode());
        rtpServerParam.setStreamId(gbChannelDTO.getDeviceCode());
        rtpServerParam.setStreamId(streamChannel.getDeviceCode());
        rtpServerParam.setTcpMode(tcpMode);
        rtpServerParam.setId(gbChannelDTO.getId());
        rtpServerParam.setId(streamChannel.getId());
        startGb28181PlayFunByGbChannel(mediaServer, gbChannelDTO, gbDevice, rtpServerParam, null, callback);
        startGb28181PlayFunByGbChannel(mediaServer, streamChannel, gbDevice, rtpServerParam, null, callback);
    }
    /**
     * gb28181 停止点播(基于GbDevice,不依赖QS)
     */
    @Override
    public void stopGb28181PlayByGbChannel(InviteSessionType type, GbChannelDTO gbChannelDTO, Device device, String stream) {
        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, gbChannelDTO.getId(), stream);
    public void stopGb28181PlayByGbChannel(InviteSessionType type, StreamChannel streamChannel, Device device, String stream) {
        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, streamChannel.getId(), stream);
        if (inviteInfo == null) {
            if (type == InviteSessionType.PLAY) {
                GbChannelDTO update = new GbChannelDTO();
                update.setId(gbChannelDTO.getId());
                StreamChannel update = new StreamChannel();
                update.setId(streamChannel.getId());
                update.setStreamKey("");
                update.setMediaServerId("");
                update.setStreamStatus("0");
                R<Boolean> r = remoteGb28181Service.updateGbChannelStream(update, SecurityConstants.INNER);
                R<Boolean> r = zlmStreamService.updateQsDevice(update, SecurityConstants.INNER);
                if (r.getCode() != Constants.SUCCESS) {
                    throw new RuntimeException("更新GbDevice失败");
                }
@@ -1863,18 +1860,18 @@
        inviteStreamService.removeInviteInfo(inviteInfo);
        if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
            try {
                log.info("[停止点播/回放/下载] {}/{}", gbChannelDTO.getGbDeviceId(), gbChannelDTO.getGbChannelId());
                log.info("[停止点播/回放/下载] {}/{}", streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
                RtpServerParam rtpServer = new RtpServerParam();
                rtpServer.setApp("gb28181");
                rtpServer.setStream(gbChannelDTO.getDeviceCode());
                rtpServer.setGbDeviceId(gbChannelDTO.getGbDeviceId());
                rtpServer.setGbChannelId(gbChannelDTO.getGbChannelId());
                rtpServer.setStream(streamChannel.getDeviceCode());
                rtpServer.setGbDeviceId(streamChannel.getGbDeviceId());
                rtpServer.setGbChannelId(streamChannel.getGbChannelId());
                R<Void> r = remoteGb28181Service.streamByeCmd(rtpServer, SecurityConstants.INNER);
                if (r.getCode() != Constants.SUCCESS) {
                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", gbChannelDTO.getGbDeviceId());
                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + gbChannelDTO.getGbDeviceId());
                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", streamChannel.getGbDeviceId());
                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + streamChannel.getGbDeviceId());
                }
            } catch (Exception e) {
                log.error("[命令发送失败] 停止点播/回放/下载, 发送BYE: {}", e.getMessage());
@@ -1883,12 +1880,12 @@
        }
        if (inviteInfo.getType() == InviteSessionType.PLAY) {
            GbChannelDTO update = new GbChannelDTO();
            update.setId(gbChannelDTO.getId());
            StreamChannel update = new StreamChannel();
            update.setId(streamChannel.getId());
            update.setStreamKey("");
            update.setMediaServerId("");
            update.setStreamStatus("0");
            R<Boolean> r = remoteGb28181Service.updateGbChannelStream(update, SecurityConstants.INNER);
            R<Boolean> r = zlmStreamService.updateQsDevice(update, SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                throw new RuntimeException("更新GbDevice失败");
            }
@@ -1917,7 +1914,7 @@
     * @param ssrc
     * @param callback
     */
    private SSRCInfo startGb28181PlayFun(ZlmMediaServer mediaServer, QsDevice device, Device gbDevice,
    private SSRCInfo startGb28181PlayFun(ZlmMediaServer mediaServer, StreamChannel device, Device gbDevice,
                                         RTPServerParam rtpServerParam, String ssrc,
                                         ErrorCallback<StreamInfo> callback) {
        // 获取点播的状态信息
@@ -2017,13 +2014,13 @@
                    String filePath = snapOnPlay(streamInfo.getMediaServer(), streamInfo.getApp(),
                            streamInfo.getStream());
                    QsDevice qsDevice = new QsDevice();
                    qsDevice.setId(rtpServerParam.getId());
                    qsDevice.setStreamKey(rtpServerParam.getStreamId());
                    qsDevice.setMediaServerId(mediaServer.getId());
                    qsDevice.setStreamStatus("1");
                    qsDevice.setSnap(filePath);
                    R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
                    StreamChannel streamChannel = new StreamChannel();
                    streamChannel.setId(rtpServerParam.getId());
                    streamChannel.setStreamKey(rtpServerParam.getStreamId());
                    streamChannel.setMediaServerId(mediaServer.getId());
                    streamChannel.setStreamStatus("1");
                    streamChannel.setSnap(filePath);
                    R<Boolean> r = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                    if (r.getCode() != Constants.SUCCESS) {
                        throw new RuntimeException("更新设备失败");
                    }
@@ -2127,24 +2124,24 @@
    /**
     * 开启国标28181播放(基于GbDevice,不依赖QS)
     */
    private SSRCInfo startGb28181PlayFunByGbChannel(ZlmMediaServer mediaServer, GbChannelDTO gbChannelDTO,
    private SSRCInfo startGb28181PlayFunByGbChannel(ZlmMediaServer mediaServer, StreamChannel streamChannel,
                                                    Device gbDevice, RTPServerParam rtpServerParam,
                                                    String ssrc, ErrorCallback<StreamInfo> callback) {
        // 获取点播的状态信息
        InviteInfo inviteInfoInCatch = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY,
                gbChannelDTO.getId());
                streamChannel.getId());
        if (inviteInfoInCatch != null) {
            if (inviteInfoInCatch.getStreamInfo() == null) {
                ssrcFactory.releaseSsrc(mediaServer.getId(), null);
                inviteStreamService.once(InviteSessionType.PLAY, gbChannelDTO.getId(), null, callback);
                log.info("[点播开始] 已经请求中,等待结果, deviceId: {}, channel: {}", gbChannelDTO.getId(), gbChannelDTO.getId());
                inviteStreamService.once(InviteSessionType.PLAY, streamChannel.getId(), null, callback);
                log.info("[点播开始] 已经请求中,等待结果, deviceId: {}, channel: {}", streamChannel.getId(), streamChannel.getId());
                return inviteInfoInCatch.getSsrcInfo();
            } else {
                StreamInfo streamInfo = inviteInfoInCatch.getStreamInfo();
                String streamId = streamInfo.getStream();
                if (streamId == null) {
                    callback.run(InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "点播失败, redis缓存streamId等于null", null);
                    inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null,
                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
                            InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "点播失败, redis缓存streamId等于null", null);
                    return inviteInfoInCatch.getSsrcInfo();
                }
@@ -2154,18 +2151,18 @@
                    if (callback != null) {
                        callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
                    }
                    inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null,
                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
                            InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
                    log.info("[点播已存在] 直接返回, 设备编号: {}", gbChannelDTO.getId());
                    log.info("[点播已存在] 直接返回, 设备编号: {}", streamChannel.getId());
                    return inviteInfoInCatch.getSsrcInfo();
                } else {
                    inviteStreamService.once(InviteSessionType.PLAY, gbChannelDTO.getId(), null, callback);
                    inviteStreamService.once(InviteSessionType.PLAY, streamChannel.getId(), null, callback);
                    RTPServerParam stopRtp = new RTPServerParam();
                    stopRtp.setId(gbChannelDTO.getId());
                    stopRtp.setId(streamChannel.getId());
                    stopRtp.setType(rtpServerParam.getType());
                    stopRtp.setStreamId(rtpServerParam.getStreamId());
                    stopRtpPlay(stopRtp);
                    inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
                    inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
                }
            }
        }
@@ -2192,7 +2189,7 @@
                        callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
                                InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
                    }
                    inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null,
                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
                    if (result != null && result.getSsrcInfo() != null) {
@@ -2203,11 +2200,11 @@
                }
                if (callback != null) {
                    callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
                    inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null,
                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
                            InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
                    InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(
                            InviteSessionType.PLAY, gbChannelDTO.getId());
                            InviteSessionType.PLAY, streamChannel.getId());
                    if (inviteInfo != null) {
                        inviteInfo.setStatus(InviteSessionStatus.ok);
                        inviteInfo.setStreamInfo(streamInfo);
@@ -2218,13 +2215,13 @@
                            streamInfo.getStream());
                    // 更新GbDevice流状态
                    GbChannelDTO update = new GbChannelDTO();
                    StreamChannel update = new StreamChannel();
                    update.setId(rtpServerParam.getId());
                    update.setStreamKey(rtpServerParam.getStreamId());
                    update.setMediaServerId(mediaServer.getId());
                    update.setStreamStatus("1");
                    update.setSnap(filePath);
                    R<Boolean> r = remoteGb28181Service.updateGbChannelStream(update, SecurityConstants.INNER);
                    R<Boolean> r = zlmStreamService.updateQsDevice(update, SecurityConstants.INNER);
                    if (r.getCode() != Constants.SUCCESS) {
                        throw new RuntimeException("更新GbDevice失败");
                    }
@@ -2234,8 +2231,8 @@
                if (callback != null) {
                    callback.run(code, msg, null);
                }
                inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null, code, msg, null);
                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
                inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null, code, msg, null);
                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
                if (result != null && result.getSsrcInfo() != null) {
                    closeRTPServer(mediaServer, result.getSsrcInfo().getStream());
                    ssrcFactory.releaseSsrc(mediaServer.getId(), result.getSsrcInfo().getSsrc());
@@ -2244,12 +2241,12 @@
        });
        if (ssrcInfo == null || ssrcInfo.getPort() <= 0) {
            log.info("[点播端口/SSRC]获取失败,设备编号:{}, 通道编号:{}, ssrcInfo: {}", gbChannelDTO.getId(), gbChannelDTO.getId(), ssrcInfo);
            log.info("[点播端口/SSRC]获取失败,设备编号:{}, 通道编号:{}, ssrcInfo: {}", streamChannel.getId(), streamChannel.getId(), ssrcInfo);
            if (rtpServerParam.getPresetSsrc() == null) {
                ssrcFactory.releaseSsrc(mediaServer.getId(), ssrc);
            }
            callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "获取端口或者ssrc失败", null);
            inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null,
            inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
                    InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(),
                    InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
            return null;
@@ -2263,27 +2260,27 @@
        rtpServer.setId(rtpServerParam.getId());
        rtpServer.setSsrc(rtpServerParam.getSsrc());
        rtpServer.setGbDeviceId(gbDevice.getDeviceId());
        rtpServer.setGbChannelId(gbChannelDTO.getGbChannelId());
        rtpServer.setGbChannelId(streamChannel.getGbChannelId());
        rtpServer.setStreamMode(gbDevice.getStreamMode());
        rtpServer.setMediaServerId(mediaServer.getId());
        rtpServer.setApp(rtpServerParam.getApp());
        rtpServer.setStream(rtpServerParam.getStreamId());
        log.info("[国标28181点播开始(基于GbDevice)] ===============================");
        log.info("[国标28181] GbDeviceId: {}, 设备国标ID: {}, 通道国标ID: {}", gbChannelDTO.getId(),
                gbDevice.getDeviceId(), gbChannelDTO.getGbChannelId());
        log.info("[国标28181] GbDeviceId: {}, 设备国标ID: {}, 通道国标ID: {}", streamChannel.getId(),
                gbDevice.getDeviceId(), streamChannel.getGbChannelId());
        log.info("[国标28181] 流模式: {}, ZLM tcpMode: {}, ssrcCheck: {}", gbDevice.getStreamMode(),
                rtpServerParam.getTcpMode(), rtpServerParam.isSsrcCheck());
        log.info("[国标28181] ZLM媒体服务器IP: {}, 收流端口: {}, 流ID: {}, SSRC: {}", ip, port, ssrcInfo.getStream(),
                ssrcInfo.getSsrc());
        log.info("[国标28181] =======================================");
        InviteInfo inviteInfo = InviteInfo.getInviteInfo(gbChannelDTO.getId().toString(), gbChannelDTO.getId(),
        InviteInfo inviteInfo = InviteInfo.getInviteInfo(streamChannel.getId().toString(), streamChannel.getId(),
                ssrcInfo.getStream(), ssrcInfo, mediaServer.getId(), mediaServer.getSdpIp(), ssrcInfo.getPort(),
                gbDevice.getStreamMode(), InviteSessionType.PLAY, InviteSessionStatus.ready,
                userSetting.getRecordSip());
        if ("1".equals(gbChannelDTO.getEnableMp4())) {
        if ("1".equals(streamChannel.getEnableMp4())) {
            inviteInfo.setRecord(true);
        }
@@ -2293,8 +2290,8 @@
        if (r.getCode() != Constants.SUCCESS) {
            log.info("[点播失败]{}:{} deviceId: {}, channelId:{}", r.getCode(), r.getMsg(),
                    gbChannelDTO.getGbDeviceId(), gbChannelDTO.getGbChannelId());
            inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.PLAY, gbChannelDTO.getId(),
                    streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
            inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.PLAY, streamChannel.getId(),
                    rtpServerParam.getStreamId());
            if (inviteInfo != null) {
                inviteStreamService.removeInviteInfo(inviteInfo);
@@ -2307,9 +2304,9 @@
            if (callback != null) {
                callback.run(r.getCode(), r.getMsg(), null);
            }
            inviteStreamService.call(InviteSessionType.PLAY, gbChannelDTO.getId(), null,
            inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
                    r.getCode(), r.getMsg(), null);
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, gbChannelDTO.getId());
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
            return ssrcInfo;
        }
        return ssrcInfo;
@@ -2360,12 +2357,12 @@
            if (callback != null) {
                callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
                QsDevice qsDevice = new QsDevice();
                qsDevice.setId(id);
                qsDevice.setStreamKey(stream);
                qsDevice.setMediaServerId(mediaServer.getId());
                qsDevice.setStreamStatus("1");
                R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
                StreamChannel streamChannel = new StreamChannel();
                streamChannel.setId(id);
                streamChannel.setStreamKey(stream);
                streamChannel.setMediaServerId(mediaServer.getId());
                streamChannel.setStreamStatus("1");
                R<Boolean> r = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                if (r.getCode() != Constants.SUCCESS) {
                    log.error("更新设备失败");
                    callback.run(InviteErrorCode.FAIL.getCode(), "更新设备失败", null);
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServiceImpl.java
@@ -5,8 +5,8 @@
import com.ard.common.core.domain.R;
import com.ard.gb28181.api.RemoteGb28181Service;
import com.ard.gb28181.api.domain.Device;
import com.ard.qs.api.RemoteQsDeviceService;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.service.ZlmStreamService;
import com.ard.zlm.domain.StreamChannel;
import com.ard.zlm.api.domain.RTPServerParam;
import com.ard.zlm.api.domain.StreamPullPlay;
import com.ard.zlm.api.domain.ZlmMediaServer;
@@ -31,7 +31,7 @@
public class MediaServiceImpl implements IMediaService {
    @Autowired
    private RemoteQsDeviceService remoteQsDeviceService;
    private ZlmStreamService zlmStreamService;
    @Autowired
    private IMediaServerService mediaServerService;
@@ -51,12 +51,12 @@
    @Override
    public boolean closeStreamOnNoneReader(String mediaServerId, String app, String stream, String schema) {
//        R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream(stream, SecurityConstants.INNER);
//        R<StreamChannel> r = zlmStreamService.getQsDeviceStream(stream, SecurityConstants.INNER);
//        if (r.getCode() != Constants.SUCCESS) {
//            return false;
//        }
//
//        QsDevice data = r.getData();
//        StreamChannel data = r.getData();
//        if (data == null) {
//            return false;
//        }
@@ -115,7 +115,7 @@
        // 海康sdk 海康isup 大华sdk
        if ("haikang".equals(app) || "haikang_isup".equals(app) || "dahua".equals(app)) {
            R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream(stream, SecurityConstants.INNER);
            R<StreamChannel> r = zlmStreamService.getQsDeviceStream(stream, SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                result.setEnable_mp4(false);
@@ -127,7 +127,7 @@
        }
        // 推流
        if ("push".equals(app)) {
            R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream(stream, SecurityConstants.INNER);
            R<StreamChannel> r = zlmStreamService.getQsDeviceStream(stream, SecurityConstants.INNER);
            if (r.getCode() != Constants.SUCCESS) {
                result.setEnable_mp4(false);
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/SourcePlayServiceImpl.java
@@ -1,7 +1,7 @@
package com.ard.zlm.service.impl;
import com.ard.common.core.constant.HttpStatus;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.domain.StreamChannel;
import com.ard.work.api.domian.ArdChannel;
import com.ard.zlm.api.domain.StreamInfo;
import com.ard.zlm.service.ErrorCallback;
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/ZlmRecordPlanServiceImpl.java
@@ -8,8 +8,8 @@
import com.ard.common.core.domain.R;
import com.ard.common.core.enums.LiveStreamType;
import com.ard.common.core.utils.DateUtils;
import com.ard.qs.api.RemoteQsDeviceService;
import com.ard.qs.api.domain.QsDevice;
import com.ard.zlm.service.ZlmStreamService;
import com.ard.zlm.domain.StreamChannel;
import com.ard.zlm.api.domain.MediaInfo;
import com.ard.zlm.api.domain.RTPServerParam;
import com.ard.zlm.api.domain.StreamInfo;
@@ -51,7 +51,7 @@
    private ZlmRecordPlanItemMapper zlmRecordPlanItemMapper;
    @Resource
    private RemoteQsDeviceService remoteQsDeviceService;
    private ZlmStreamService zlmStreamService;
    @Resource
    private RemoteChannelService remoteChannelService;
    @Resource
@@ -76,7 +76,7 @@
        }
        // 重新拉起
        R<ArdChannel> r = remoteChannelService.getInfo(deviceId, SecurityConstants.INNER);
        //  R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
        //  R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
        if (r.getCode() != HttpStatus.SUCCESS) {
            throw new RuntimeException("根据设备id查询设备信息失败");
        }
@@ -91,7 +91,7 @@
            return;
        }
//        if ("OFFLINE".equals(device.getDeviceStatus())) {
//        if (!Boolean.TRUE.equals(device.getDeviceOnLine())) {
//            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不在线, id: {}", deviceId);
//            return;
//        }
@@ -147,7 +147,7 @@
    public List<ZlmRecordPlan> selectZlmRecordPlanList(ZlmRecordPlan zlmRecordPlan) {
        List<ZlmRecordPlan> zlmRecordPlans = zlmRecordPlanMapper.selectZlmRecordPlanList(zlmRecordPlan);
        for (ZlmRecordPlan recordPlan : zlmRecordPlans) {
            R<Integer> r = remoteQsDeviceService.countRecordPlanDevice(recordPlan.getId(), SecurityConstants.INNER);
            R<Integer> r = zlmStreamService.countRecordPlanDevice(recordPlan.getId(), SecurityConstants.INNER);
            if (r.getCode() != HttpStatus.SUCCESS) {
                throw new RuntimeException("删除录像计划失败");
            }
@@ -214,7 +214,7 @@
    public int deleteZlmRecordPlanByIds(Long[] ids) {
        for (Long id : ids) {
            zlmRecordPlanItemMapper.cleanItems(id);
            R<Void> r = remoteQsDeviceService.cleanRecordPlanId(id, SecurityConstants.INNER);
            R<Void> r = zlmStreamService.cleanRecordPlanId(id, SecurityConstants.INNER);
            if (r.getCode() != HttpStatus.SUCCESS) {
                throw new RuntimeException("删除录像计划失败");
            }
@@ -248,7 +248,7 @@
//            recordStreamMap.keySet().forEach(startDeviceIdList::remove);
//            if (!startDeviceIdList.isEmpty()) {
//                // 获取所有的关联的设备
//              //  R<List<QsDevice>> r = remoteQsDeviceService.queryByIds(startDeviceIdList, SecurityConstants.INNER);
//              //  R<List<StreamChannel>> r = zlmStreamService.queryByIds(startDeviceIdList, SecurityConstants.INNER);
//                R<List<ArdChannel>> r = remoteChannelService.queryByIds(startDeviceIdList, SecurityConstants.INNER);
//                if (r.getCode() != HttpStatus.SUCCESS) {
//                    throw new RuntimeException("根据设备id集合查询设备信息失败");
@@ -257,7 +257,7 @@
//                if (!deviceList.isEmpty()) {
//                    // 查找是否已经开启录像, 如果没有则开启录像
//                    for (ArdChannel device : deviceList) {
////                        if ("OFFLINE".equals(device.getDeviceStatus())) {
////                        if (!Boolean.TRUE.equals(device.getDeviceOnLine())) {
////                            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不在线, id: {}", device.getId());
////                            return;
////                        }
@@ -302,7 +302,7 @@
                        streamInfo.getApp(), streamInfo.getStream());
                if (mediaInfo.getReaderCount() == null || mediaInfo.getReaderCount() == 0) {
                    R<ArdChannel> r = remoteChannelService.getInfo(deviceId, SecurityConstants.INNER);
                    // R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
                    // R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
                    if (r.getCode() != HttpStatus.SUCCESS) {
                        throw new RuntimeException("根据通道id查询设备信息失败");
                    }
ard-modules/pom.xml
@@ -14,7 +14,6 @@
        <module>ard-modules-job</module>
        <module>ard-modules-file</module>
        <module>ard-modules-zlm</module>
        <module>ard-modules-qs</module>
        <module>ard-modules-gb28181</module>
        <module>ard-modules-agent</module>
        <module>ard-modules-work</module>