liusuyi
2026-05-30 f4f4fc53260eb67483dce406a963628273786a61
ard-modules/ard-modules-agent/src/main/java/com/ard/agent/tool/MonitorTools.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.JSON;
import com.ard.common.core.constant.SecurityConstants;
import com.ard.common.core.domain.R;
import com.ard.common.redis.service.RedisService;
import com.ard.system.api.RemoteDictService;
import com.ard.system.api.domain.SysDictData;
import com.ard.work.api.RemoteCameraService;
@@ -12,8 +13,8 @@
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Slf4j
@@ -24,6 +25,54 @@
    private RemoteCameraService remoteCameraService;
    @Resource
    private RemoteDictService remoteDictService;
    @Resource
    private RedisService redisService;  // 若依的RedisCache
    // 字典缓存Key前缀(若依默认)
    private static final String DICT_KEY_PREFIX = "sys_dict:";
    /**
     * 获取厂商名称(带Redis缓存)
     */
    private String getFactoryName(String factoryCode) {
        return getDictLabel("factory", factoryCode);
    }
    /**
     * 获取相机类型名称(带Redis缓存)
     */
    private String getCameraTypeName(String typeCode) {
        return getDictLabel("camera_type", typeCode);
    }
    /**
     * 获取字典标签(直接从Redis缓存读取)
     */
    private String getDictLabel(String dictType, String dictValue) {
        if (dictValue == null || dictValue.isEmpty()) {
            return "未知";
        }
        // 若依框架:从缓存获取字典数据
        List<SysDictData> dictDatas = redisService.getCacheObject("sys_dict:" + dictType);
        if (dictDatas == null || dictDatas.isEmpty()) {
            // 如果缓存为空,可以从远程服务加载一次
            R<List<SysDictData>> result = remoteDictService.dictTypeRpc(dictType, SecurityConstants.INNER);
            if (result != null && result.getCode() == R.SUCCESS) {
                dictDatas = result.getData();
                // 重新放入缓存
                redisService.setCacheObject("sys_dict:" + dictType, dictDatas);
            }
        }
        if (dictDatas != null) {
            return dictDatas.stream()
                    .filter(dict -> dictValue.equals(dict.getDictValue()))
                    .map(SysDictData::getDictLabel)
                    .findFirst()
                    .orElse("未知(" + dictValue + ")");
        }
        return "未知(" + dictValue + ")";
    }
    @Tool(description = "获取指定摄像机的详细信息,包括IP、名称、状态等")
    public String getCameraDetail(@ToolParam(description = "摄像机ID,如CAM-001") String cameraId) {
@@ -75,55 +124,23 @@
            }
            List<ArdCamera> filteredCameras = cameras;
//            if (keyword != null && !keyword.isEmpty()) {
//                filteredCameras = cameras.stream()
//                        .filter(c -> (c.getName() != null && c.getName().contains(keyword)) ||
//                                (c.getId() != null && c.getId().contains(keyword)))
//                        .toList();
//            }
            if (filteredCameras.isEmpty()) {
                return "未找到符合条件的摄像机";
            }
            R<List<SysDictData>> getFactoryResult =
                    remoteDictService.dictTypeRpc("factory", SecurityConstants.INNER);
            if (getFactoryResult == null || getFactoryResult.getCode() != R.SUCCESS) {
                return String.format("获取厂商信息失败:%s",
                        getFactoryResult != null ? getFactoryResult.getMsg() : "服务返回空结果");
            }
            R<List<SysDictData>> getCameraTypeResult =
                    remoteDictService.dictTypeRpc("camera_type", SecurityConstants.INNER);
            if (getCameraTypeResult == null || getCameraTypeResult.getCode() != R.SUCCESS) {
                return String.format("获取相机类型失败:%s",
                        getCameraTypeResult != null ? getCameraTypeResult.getMsg() : "服务返回空结果");
            }
            StringBuilder resultStr = new StringBuilder();
            resultStr.append(String.format("找到%d台摄像机:\n", filteredCameras.size()));
            for (ArdCamera camera : filteredCameras) {
                String factoryName = getFactoryResult.getData().stream()
                        .filter(dict -> camera.getFactory().equals(dict.getDictValue()))
                        .findFirst()
                        .map(SysDictData::getDictLabel)
                        .orElseGet(() -> {
                            log.warn("未找到厂商代码对应的字典项: {}", camera.getFactory());
                            return "未知厂商(" + camera.getFactory() + ")";
                        });
                String cameraTypeName = getCameraTypeResult.getData().stream()
                        .filter(dict -> camera.getType().equals(dict.getDictValue()))
                        .findFirst()
                        .map(SysDictData::getDictLabel)
                        .orElseGet(() -> {
                            log.warn("未找到相机类型对应的字典项: {}", camera.getType());
                            return "未知厂商(" + camera.getType() + ")";
                        });
                resultStr.append(String.format("  - ID: %s, 名称: %s, IP: %s, 厂商: %s,状态: %s, 类型: %s\n",
                        camera.getId(),
                        camera.getName(),
                        camera.getIp(),
                        factoryName,
                        getFactoryName(camera.getFactory()),
                        Objects.equals(camera.getState(), "1") ? "在线" : "离线",
                        cameraTypeName));
                        getCameraTypeName(camera.getType())
                       ));
            }
            return resultStr.toString();
        } catch (Exception e) {
@@ -131,95 +148,55 @@
            return "系统异常:" + e.getMessage();
        }
    }
    @Tool(description = "修改摄像机信息,支持修改名称、IP地址、端口、位置、状态等字段。注意:摄像机ID不能修改")
    @Tool(description = """
    修改摄像机信息。传入摄像机ID和需要修改的字段,不传的字段保持原值不变。
    使用示例:
    - "把CAM-001的名字改成大门摄像头" → 传入 {id:"CAM-001", name:"大门摄像头"}
    - "将CAM-002设置为离线" → 传入 {id:"CAM-002", state:"0"}
    注意:id为必填项。
    """)
    public String updateCameraInfo(
            @ToolParam(description = "摄像机ID,如CAM-001") String cameraId,
            @ToolParam(description = "摄像机名称,如不需要修改可不传") String name,
            @ToolParam(description = "摄像机IP地址,如不需要修改可不传") String ip,
            @ToolParam(description = "摄像机位置/区域,如不需要修改可不传") String location,
            @ToolParam(description = "摄像机状态:1-在线,0-离线,如不需要修改可不传") String state,
            @ToolParam(description = "摄像机类型,如不需要修改可不传") String type,
            @ToolParam(description = "摄像机厂家/品牌,如不需要修改可不传") String factory
    ) {
        log.info("AI调用updateCameraInfo工具,参数: cameraId={}, name={}, ip={}, location={}, state={}, type={}, factory={}",
                cameraId, name, ip, location, state, type, factory);
            @ToolParam(description = "摄像机对象,包含id和需要修改的字段") ArdCamera updateParams) {
        // 参数校验
        if (cameraId == null || cameraId.isEmpty()) {
        log.info("AI调用updateCameraInfo工具,参数: {}", updateParams);
        // 必填校验
        if (updateParams == null || updateParams.getId() == null || updateParams.getId().isEmpty()) {
            return "错误:摄像机ID不能为空";
        }
        String cameraId = updateParams.getId();
        try {
            // 1. 先获取当前摄像机信息
            R<ArdCamera> getResult = remoteCameraService.getCameraInfoRpc(cameraId, SecurityConstants.INNER);
            if (getResult == null || getResult.getCode() != R.SUCCESS) {
                return String.format("获取摄像机信息失败:%s",
                        getResult != null ? getResult.getMsg() : "服务返回空结果");
            // 3. 直接调用 Feign 接口
            R<Boolean> updateResult = remoteCameraService.updateCamera(updateParams, SecurityConstants.INNER);
            if (updateResult == null || updateResult.getCode() != R.SUCCESS) {
                return "修改失败:" + (updateResult != null ? updateResult.getMsg() : "服务返回空");
            }
            ArdCamera camera = getResult.getData();
            if (camera == null) {
                return "错误:未找到摄像机ID为 " + cameraId + " 的摄像机";
            }
            // 2. 构建更新对象(只更新有值的字段)
            ArdCamera updateCamera = new ArdCamera();
            updateCamera.setId(cameraId);
            if (name != null && !name.isEmpty()) {
                updateCamera.setName(name);
            } else {
                updateCamera.setName(camera.getName());
            }
            if (ip != null && !ip.isEmpty()) {
                updateCamera.setIp(ip);
            } else {
                updateCamera.setIp(camera.getIp());
            }
            if (state != null && !state.isEmpty()) {
                updateCamera.setState(state);
            }
            if (type != null && !type.isEmpty()) {
                updateCamera.setType(type);
            }
            if (factory != null && !factory.isEmpty()) {
                updateCamera.setFactory(factory);
            }
            // 3. 调用更新接口(假设有 updateCamera 方法)
            R<Boolean> updateResult = remoteCameraService.updateCamera(updateCamera, SecurityConstants.INNER);
            if (updateResult == null) {
                return "错误:服务返回空结果";
            }
            if (updateResult.getCode() == R.SUCCESS) {
                // 返回更新后的信息
                R<ArdCamera> newResult = remoteCameraService.getCameraInfoRpc(cameraId, SecurityConstants.INNER);
                ArdCamera newCamera = newResult.getData();
                return String.format("摄像机信息修改成功!\n更新后的信息:\n" +
                                "  - ID: %s\n" +
                                "  - 名称: %s\n" +
                                "  - IP地址: %s\n" +
                                "  - 状态: %s\n" +
                                "  - 类型: %s\n" +
                                "  - 厂家: %s",
                        newCamera.getId(),
                        newCamera.getName(),
                        newCamera.getIp(),
                        Objects.equals(newCamera.getState(), "1") ? "在线" : "离线",
                        newCamera.getType(),
                        newCamera.getFactory());
            } else {
                return String.format("修改摄像机信息失败:%s (code: %d)",
                        updateResult.getMsg(), updateResult.getCode());
            }
            // 4. 返回最新信息
            R<ArdCamera> newResult = remoteCameraService.getCameraInfoRpc(cameraId, SecurityConstants.INNER);
            ArdCamera newCamera = newResult.getData();
            return String.format("✅ 摄像机信息修改成功!\n\n" +
                            "| 字段 | 修改后的值 |\n" +
                            "|------|-----------|\n" +
                            "| ID | %s |\n" +
                            "| 名称 | %s |\n" +
                            "| IP | %s |\n" +
                            "| 位置 | %s, %s |\n" +
                            "| 状态 | %s |\n" +
                            "| 类型 | %s |\n" +
                            "| 厂家 | %s |",
                    newCamera.getId(),
                    newCamera.getName(),
                    newCamera.getIp(),
                    newCamera.getLongitude(), newCamera.getLatitude(),
                    "1".equals(newCamera.getState()) ? "在线" : "离线",
                    getCameraTypeName(newCamera.getType()),
                    getFactoryName(newCamera.getFactory()));
        } catch (Exception e) {
            log.error("调用updateCamera异常", e);