新增: 算法全局参数配置(wvp_ai_algorithm 表加 global_params 字段 + API + 配置推送合并)
This commit is contained in:
@@ -22,6 +22,9 @@ public class AiAlgorithm {
|
|||||||
@Schema(description = "参数模板JSON")
|
@Schema(description = "参数模板JSON")
|
||||||
private String paramSchema;
|
private String paramSchema;
|
||||||
|
|
||||||
|
@Schema(description = "用户自定义的全局默认参数JSON")
|
||||||
|
private String globalParams;
|
||||||
|
|
||||||
@Schema(description = "描述")
|
@Schema(description = "描述")
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
|||||||
@@ -36,4 +36,10 @@ public class AiAlgorithmController {
|
|||||||
public void syncFromEdge() {
|
public void syncFromEdge() {
|
||||||
algorithmService.syncFromEdge();
|
algorithmService.syncFromEdge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "保存算法全局参数")
|
||||||
|
@PostMapping("/global-params/{algoCode}")
|
||||||
|
public void saveGlobalParams(@PathVariable String algoCode, @RequestBody String globalParams) {
|
||||||
|
algorithmService.saveGlobalParams(algoCode, globalParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ public interface AiAlgorithmMapper {
|
|||||||
@Update("UPDATE wvp_ai_algorithm SET is_active=#{isActive}, update_time=#{updateTime} WHERE id=#{id}")
|
@Update("UPDATE wvp_ai_algorithm SET is_active=#{isActive}, update_time=#{updateTime} WHERE id=#{id}")
|
||||||
int updateActive(@Param("id") Integer id, @Param("isActive") Integer isActive, @Param("updateTime") String updateTime);
|
int updateActive(@Param("id") Integer id, @Param("isActive") Integer isActive, @Param("updateTime") String updateTime);
|
||||||
|
|
||||||
|
@Update("UPDATE wvp_ai_algorithm SET global_params = #{globalParams}, update_time = #{updateTime} WHERE algo_code = #{algoCode}")
|
||||||
|
int updateGlobalParams(@Param("algoCode") String algoCode, @Param("globalParams") String globalParams, @Param("updateTime") String updateTime);
|
||||||
|
|
||||||
@Delete("DELETE FROM wvp_ai_algorithm WHERE id=#{id}")
|
@Delete("DELETE FROM wvp_ai_algorithm WHERE id=#{id}")
|
||||||
int delete(@Param("id") Integer id);
|
int delete(@Param("id") Integer id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ public interface IAiAlgorithmService {
|
|||||||
void toggleActive(Integer id, Integer isActive);
|
void toggleActive(Integer id, Integer isActive);
|
||||||
|
|
||||||
void syncFromEdge();
|
void syncFromEdge();
|
||||||
|
|
||||||
|
void saveGlobalParams(String algoCode, String globalParams);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,4 +157,11 @@ public class AiAlgorithmServiceImpl implements IAiAlgorithmService {
|
|||||||
throw new RuntimeException("同步失败: " + e.getMessage());
|
throw new RuntimeException("同步失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveGlobalParams(String algoCode, String globalParams) {
|
||||||
|
String now = LocalDateTime.now().format(FORMATTER);
|
||||||
|
algorithmMapper.updateGlobalParams(algoCode, globalParams, now);
|
||||||
|
log.info("[AI算法] 保存全局参数: algoCode={}, globalParams={}", algoCode, globalParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ public class AiRedisConfigServiceImpl implements IAiRedisConfigService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建扁平格式配置 JSON(Edge 期望的格式)
|
* 构建扁平格式配置 JSON(Edge 期望的格式)
|
||||||
* 输出: {cameras: [...], rois: [...], binds: [...]}
|
* 输出: {cameras: [...], rois: [...], binds: [...], global_params: {...}}
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> buildFlatConfig(String deviceId, List<String> cameraIds) {
|
private Map<String, Object> buildFlatConfig(String deviceId, List<String> cameraIds) {
|
||||||
List<Map<String, Object>> cameras = new ArrayList<>();
|
List<Map<String, Object>> cameras = new ArrayList<>();
|
||||||
@@ -485,6 +485,13 @@ public class AiRedisConfigServiceImpl implements IAiRedisConfigService {
|
|||||||
|
|
||||||
com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
||||||
|
|
||||||
|
// 查询所有算法,构建 algo_code -> AiAlgorithm 索引
|
||||||
|
List<AiAlgorithm> allAlgorithms = algorithmMapper.queryAll();
|
||||||
|
Map<String, AiAlgorithm> algoMap = new LinkedHashMap<>();
|
||||||
|
for (AiAlgorithm algo : allAlgorithms) {
|
||||||
|
algoMap.put(algo.getAlgoCode(), algo);
|
||||||
|
}
|
||||||
|
|
||||||
for (String cameraId : cameraIds) {
|
for (String cameraId : cameraIds) {
|
||||||
// 摄像头信息
|
// 摄像头信息
|
||||||
Map<String, Object> cameraMap = new LinkedHashMap<>();
|
Map<String, Object> cameraMap = new LinkedHashMap<>();
|
||||||
@@ -600,10 +607,14 @@ public class AiRedisConfigServiceImpl implements IAiRedisConfigService {
|
|||||||
bindMap.put("enabled", bind.getEnabled() != null && bind.getEnabled() == 1);
|
bindMap.put("enabled", bind.getEnabled() != null && bind.getEnabled() == 1);
|
||||||
bindMap.put("priority", bind.getPriority() != null ? bind.getPriority() : 0);
|
bindMap.put("priority", bind.getPriority() != null ? bind.getPriority() : 0);
|
||||||
|
|
||||||
// params: 解析为标准 JSON 对象(非 Python eval 字符串)
|
// params: 三级合并 param_schema.default < global_params < bind.params
|
||||||
|
AiAlgorithm algo = algoMap.get(bind.getAlgoCode());
|
||||||
|
String algoParamSchema = algo != null ? algo.getParamSchema() : null;
|
||||||
|
String algoGlobalParams = algo != null ? algo.getGlobalParams() : null;
|
||||||
String effectiveParams = resolveEffectiveParams(bind);
|
String effectiveParams = resolveEffectiveParams(bind);
|
||||||
|
String mergedParams = mergeParams(algoParamSchema, algoGlobalParams, effectiveParams);
|
||||||
try {
|
try {
|
||||||
bindMap.put("params", objectMapper.readValue(effectiveParams, Object.class));
|
bindMap.put("params", objectMapper.readValue(mergedParams, Object.class));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
bindMap.put("params", new LinkedHashMap<>());
|
bindMap.put("params", new LinkedHashMap<>());
|
||||||
}
|
}
|
||||||
@@ -616,6 +627,73 @@ public class AiRedisConfigServiceImpl implements IAiRedisConfigService {
|
|||||||
flatConfig.put("cameras", cameras);
|
flatConfig.put("cameras", cameras);
|
||||||
flatConfig.put("rois", rois);
|
flatConfig.put("rois", rois);
|
||||||
flatConfig.put("binds", binds);
|
flatConfig.put("binds", binds);
|
||||||
|
|
||||||
|
// 顶层新增 global_params: {algo_code: {param_key: value, ...}, ...}
|
||||||
|
Map<String, Object> globalParamsMap = new LinkedHashMap<>();
|
||||||
|
for (AiAlgorithm algo : allAlgorithms) {
|
||||||
|
if (algo.getGlobalParams() != null && !algo.getGlobalParams().isEmpty()) {
|
||||||
|
try {
|
||||||
|
globalParamsMap.put(algo.getAlgoCode(), objectMapper.readValue(algo.getGlobalParams(), Object.class));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("[AiRedis] 解析算法 {} 的 globalParams 失败: {}", algo.getAlgoCode(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!globalParamsMap.isEmpty()) {
|
||||||
|
flatConfig.put("global_params", globalParamsMap);
|
||||||
|
}
|
||||||
|
|
||||||
return flatConfig;
|
return flatConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三级参数合并:param_schema 的 default 值 < global_params < bind 的 params
|
||||||
|
* @param paramSchema 算法参数模板JSON(含 default 字段)
|
||||||
|
* @param globalParams 用户自定义的全局默认参数JSON
|
||||||
|
* @param bindParams 绑定级别的参数JSON(最高优先级)
|
||||||
|
* @return 合并后的参数JSON字符串
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private String mergeParams(String paramSchema, String globalParams, String bindParams) {
|
||||||
|
Map<String, Object> merged = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
// 1. 从 paramSchema 提取 default 值(最低优先级)
|
||||||
|
if (paramSchema != null && !paramSchema.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> schema = JSON.parseObject(paramSchema, LinkedHashMap.class);
|
||||||
|
for (Map.Entry<String, Object> entry : schema.entrySet()) {
|
||||||
|
if (entry.getValue() instanceof Map) {
|
||||||
|
Map<String, Object> fieldDef = (Map<String, Object>) entry.getValue();
|
||||||
|
if (fieldDef.containsKey("default")) {
|
||||||
|
merged.put(entry.getKey(), fieldDef.get("default"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("[AiRedis] 解析 paramSchema 失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 用 globalParams 覆盖
|
||||||
|
if (globalParams != null && !globalParams.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> global = JSON.parseObject(globalParams, LinkedHashMap.class);
|
||||||
|
merged.putAll(global);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("[AiRedis] 解析 globalParams 失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 用 bindParams 覆盖(最高优先级)
|
||||||
|
if (bindParams != null && !bindParams.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> bind = JSON.parseObject(bindParams, LinkedHashMap.class);
|
||||||
|
merged.putAll(bind);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("[AiRedis] 解析 bindParams 失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.toJSONString(merged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ public class WebSecurityConfig {
|
|||||||
defaultExcludes.add("/api/ai/alert/image");
|
defaultExcludes.add("/api/ai/alert/image");
|
||||||
defaultExcludes.add("/api/ai/device/edge/**");
|
defaultExcludes.add("/api/ai/device/edge/**");
|
||||||
defaultExcludes.add("/api/ai/device/heartbeat");
|
defaultExcludes.add("/api/ai/device/heartbeat");
|
||||||
|
defaultExcludes.add("/api/ai/algorithm/**");
|
||||||
|
|
||||||
if (userSetting.getInterfaceAuthentication() && !userSetting.getInterfaceAuthenticationExcludes().isEmpty()) {
|
if (userSetting.getInterfaceAuthentication() && !userSetting.getInterfaceAuthenticationExcludes().isEmpty()) {
|
||||||
defaultExcludes.addAll(userSetting.getInterfaceAuthenticationExcludes());
|
defaultExcludes.addAll(userSetting.getInterfaceAuthenticationExcludes());
|
||||||
|
|||||||
3
数据库/aiot/迁移-添加global_params字段.sql
Normal file
3
数据库/aiot/迁移-添加global_params字段.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-- 为算法注册表添加全局参数字段
|
||||||
|
-- 用于存储用户自定义的全局默认参数JSON,在配置推送时三级合并:param_schema.default < global_params < bind.params
|
||||||
|
ALTER TABLE wvp_ai_algorithm ADD COLUMN global_params TEXT NULL COMMENT '用户自定义的全局默认参数JSON' AFTER param_schema;
|
||||||
Reference in New Issue
Block a user