优化:边缘配置流程——device_id 从摄像头继承 + 取消自动推送

1. resolveDeviceId 优先从 stream_proxy.edge_device_id 获取,不再硬编码默认设备
2. 删除 save/delete/bindAlgo/unbindAlgo/updateAlgoParams 中的自动推送
3. pushConfig 时自动修正 ROI 的 device_id 为摄像头实际绑定的边缘设备
4. StreamProxyMapper 新增 selectEdgeDeviceIdByCameraCode 查询
This commit is contained in:
2026-03-30 14:14:18 +08:00
parent e2d404749a
commit 616ed4a7c2
3 changed files with 41 additions and 109 deletions

View File

@@ -225,10 +225,27 @@ public class AiConfigServiceImpl implements IAiConfigService {
ids.add(cameraId);
redisConfigService.publishConfigUpdate("full", ids);
// 5. 写入设备聚合配置 + Stream 通知(新格式,对接 Edge config_sync
String deviceId = roiMapper.queryDeviceIdByCameraId(cameraId);
// 5. 从摄像头配置获取正确的 edge_device_id修正 ROI 表中的 device_id
String correctDeviceId = streamProxyMapper.selectEdgeDeviceIdByCameraCode(cameraId);
if (correctDeviceId != null && !correctDeviceId.isEmpty()) {
List<AiRoi> rois = roiMapper.queryByCameraId(cameraId);
for (AiRoi roi : rois) {
if (!correctDeviceId.equals(roi.getDeviceId())) {
String oldDeviceId = roi.getDeviceId();
roi.setDeviceId(correctDeviceId);
roiMapper.update(roi);
log.info("[AiConfig] 修正 ROI device_id: roi={}, {} → {}",
roi.getRoiId(), oldDeviceId, correctDeviceId);
}
}
}
// 6. 写入设备聚合配置 + Stream 通知(新格式,对接 Edge config_sync
String deviceId = correctDeviceId;
if (deviceId == null || deviceId.isEmpty()) {
deviceId = roiMapper.queryDeviceIdByCameraId(cameraId);
}
if (deviceId == null || deviceId.isEmpty()) {
// 回退:从 edge 设备表获取默认设备
deviceId = getDefaultDeviceId();
log.info("[AiConfig] 摄像头 {} 未关联设备,使用默认设备: {}", cameraId, deviceId);
}
@@ -240,10 +257,10 @@ public class AiConfigServiceImpl implements IAiConfigService {
log.warn("[AiConfig] 无法确定设备ID跳过 Redis 聚合配置推送。请先注册边缘设备或为摄像头关联 device_id");
}
// 6. 本地调试:同步到 Edge HTTP 接口(保留原 Redis 流程)
// 7. 本地调试:同步到 Edge HTTP 接口(保留原 Redis 流程)
boolean httpSyncOk = pushConfigToLocalEdge(cameraId, config);
// 7. 返回推送结果
// 8. 返回推送结果
Map<String, Object> result = new LinkedHashMap<>();
result.put("camera_id", cameraId);
result.put("version", snapshot.getVersion());

View File

@@ -2,12 +2,11 @@ package com.genersoft.iot.vmp.aiot.service.impl;
import com.genersoft.iot.vmp.aiot.bean.*;
import com.genersoft.iot.vmp.aiot.dao.AiAlgorithmMapper;
import com.genersoft.iot.vmp.aiot.dao.AiEdgeDeviceMapper;
import com.genersoft.iot.vmp.aiot.dao.AiRoiAlgoBindMapper;
import com.genersoft.iot.vmp.aiot.dao.AiRoiMapper;
import com.genersoft.iot.vmp.aiot.service.IAiConfigLogService;
import com.genersoft.iot.vmp.aiot.service.IAiRedisConfigService;
import com.genersoft.iot.vmp.aiot.service.IAiRoiService;
import com.genersoft.iot.vmp.streamProxy.dao.StreamProxyMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
@@ -36,14 +35,11 @@ public class AiRoiServiceImpl implements IAiRoiService {
private AiAlgorithmMapper algorithmMapper;
@Autowired
private AiEdgeDeviceMapper edgeDeviceMapper;
private StreamProxyMapper streamProxyMapper;
@Autowired
private IAiConfigLogService configLogService;
@Autowired
private IAiRedisConfigService redisConfigService;
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
@@ -82,42 +78,27 @@ public class AiRoiServiceImpl implements IAiRoiService {
roiMapper.add(roi);
configLogService.addLog("ROI", roi.getRoiId(), null, toJson(roi), null);
}
// 推送配置到 Edge新增/更新操作)
String deviceId = roi.getDeviceId();
if (deviceId != null && !deviceId.isEmpty()) {
try {
redisConfigService.writeDeviceAggregatedConfig(deviceId, "UPDATE");
log.info("[AiRoi] {}ROI后推送配置到Edgecamera_id={}, device_id={}",
isUpdate ? "更新" : "新增", cameraId, deviceId);
} catch (Exception e) {
log.error("[AiRoi] {}ROI后推送配置失败camera_id={}, device_id={}",
isUpdate ? "更新" : "新增", cameraId, deviceId, e);
}
} else {
log.warn("[AiRoi] {}ROI但device_id为空跳过推送配置camera_id={}",
isUpdate ? "更新" : "新增", cameraId);
}
}
/**
* 解析 deviceId
* 1. 优先从摄像头的已有 ROI 继承
* 2. 否则取系统中唯一的已注册边缘设备(单边缘场景)
* 1. 优先从摄像头配置继承 edge_device_idstream_proxy 表)
* 2. 兼容:从同摄像头已有 ROI 继承
* 3. 不再硬编码默认值,返回 null
*/
private String resolveDeviceId(String cameraId) {
// 从同摄像头已有 ROI 继承
String deviceId = roiMapper.queryDeviceIdByCameraId(cameraId);
// 1. 优先从摄像头配置继承 edge_device_id
String deviceId = streamProxyMapper.selectEdgeDeviceIdByCameraCode(cameraId);
if (deviceId != null && !deviceId.isEmpty()) {
return deviceId;
}
// 取系统中第一个已注册的边缘设备
List<AiEdgeDevice> devices = edgeDeviceMapper.queryAll();
if (devices != null && !devices.isEmpty()) {
log.info("[AiRoi] 使用默认边缘设备: {}", devices.get(0).getDeviceId());
return devices.get(0).getDeviceId();
// 2. 兼容:从同摄像头已有 ROI 继承
deviceId = roiMapper.queryDeviceIdByCameraId(cameraId);
if (deviceId != null && !deviceId.isEmpty()) {
return deviceId;
}
log.warn("[AiRoi] 无已注册边缘设备deviceId 为空");
// 3. 不再硬编码默认值,返回 null
log.warn("[AiRoi] 无法解析 deviceIdcameraId={}", cameraId);
return null;
}
@@ -131,17 +112,6 @@ public class AiRoiServiceImpl implements IAiRoiService {
bindMapper.deleteByRoiId(roiId);
roiMapper.deleteByRoiId(roiId);
configLogService.addLog("ROI", roiId, toJson(old), null, null);
// 推送配置到 Edge删除操作
if (deviceId != null && !deviceId.isEmpty()) {
try {
redisConfigService.writeDeviceAggregatedConfig(deviceId, "UPDATE");
log.info("[AiRoi] 删除ROI后推送配置到Edgecamera_id={}, device_id={}", cameraId, deviceId);
} catch (Exception e) {
log.error("[AiRoi] 删除ROI后推送配置失败camera_id={}, device_id={}", cameraId, deviceId, e);
}
} else {
log.warn("[AiRoi] 删除ROI但device_id为空跳过推送配置camera_id={}", cameraId);
}
}
}
@@ -200,27 +170,6 @@ public class AiRoiServiceImpl implements IAiRoiService {
bind.setUpdateTime(now);
bindMapper.add(bind);
configLogService.addLog("BIND", bind.getBindId(), null, toJson(bind), null);
// 推送配置到 Edge绑定算法
String roiId = bind.getRoiId();
if (roiId != null) {
AiRoi roi = roiMapper.queryByRoiId(roiId);
if (roi != null) {
String deviceId = roi.getDeviceId();
if (deviceId != null && !deviceId.isEmpty()) {
try {
redisConfigService.writeDeviceAggregatedConfig(deviceId, "UPDATE");
log.info("[AiRoi] 绑定算法后推送配置到Edgecamera_id={}, device_id={}, algo={}",
roi.getCameraId(), deviceId, bind.getAlgoCode());
} catch (Exception e) {
log.error("[AiRoi] 绑定算法后推送配置失败camera_id={}, device_id={}",
roi.getCameraId(), deviceId, e);
}
} else {
log.warn("[AiRoi] 绑定算法但device_id为空跳过推送配置camera_id={}", roi.getCameraId());
}
}
}
}
@Override
@@ -231,25 +180,6 @@ public class AiRoiServiceImpl implements IAiRoiService {
String roiId = old.getRoiId();
bindMapper.deleteByBindId(bindId);
configLogService.addLog("BIND", bindId, toJson(old), null, null);
// 推送配置到 Edge解绑算法
if (roiId != null) {
AiRoi roi = roiMapper.queryByRoiId(roiId);
if (roi != null) {
String deviceId = roi.getDeviceId();
if (deviceId != null && !deviceId.isEmpty()) {
try {
redisConfigService.writeDeviceAggregatedConfig(deviceId, "UPDATE");
log.info("[AiRoi] 解绑算法后推送配置到Edgecamera_id={}, device_id={}",
roi.getCameraId(), deviceId);
} catch (Exception e) {
log.error("[AiRoi] 解绑算法后推送配置失败camera_id={}, device_id={}",
roi.getCameraId(), deviceId, e);
}
} else {
log.warn("[AiRoi] 解绑算法但device_id为空跳过推送配置camera_id={}", roi.getCameraId());
}
}
}
}
}
@@ -270,27 +200,6 @@ public class AiRoiServiceImpl implements IAiRoiService {
bind.setUpdateTime(now);
bindMapper.updateByBindId(bind);
configLogService.addLog("BIND", bind.getBindId(), toJson(old), toJson(bind), null);
// 推送配置到 Edge更新算法参数
String roiId = old.getRoiId();
if (roiId != null) {
AiRoi roi = roiMapper.queryByRoiId(roiId);
if (roi != null) {
String deviceId = roi.getDeviceId();
if (deviceId != null && !deviceId.isEmpty()) {
try {
redisConfigService.writeDeviceAggregatedConfig(deviceId, "UPDATE");
log.info("[AiRoi] 更新算法参数后推送配置到Edgecamera_id={}, device_id={}, bind_id={}",
roi.getCameraId(), deviceId, bind.getBindId());
} catch (Exception e) {
log.error("[AiRoi] 更新算法参数后推送配置失败camera_id={}, device_id={}",
roi.getCameraId(), deviceId, e);
}
} else {
log.warn("[AiRoi] 更新算法参数但device_id为空跳过推送配置camera_id={}", roi.getCameraId());
}
}
}
}
private String toJson(Object obj) {

View File

@@ -127,4 +127,10 @@ public interface StreamProxyMapper {
*/
@Select("SELECT camera_code, camera_name FROM wvp_stream_proxy WHERE enable = 1 ORDER BY camera_name")
List<StreamProxy> selectAllCameraOptions();
/**
* 根据 camera_code 查询关联的边缘设备 ID
*/
@Select("SELECT edge_device_id FROM wvp_stream_proxy WHERE camera_code = #{cameraCode}")
String selectEdgeDeviceIdByCameraCode(@Param("cameraCode") String cameraCode);
}