liusuyi
2026-05-30 f4f4fc53260eb67483dce406a963628273786a61
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package com.ard.agent.tool;
 
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;
import com.ard.work.api.domian.ArdCamera;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
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.Objects;
 
@Slf4j
@Component
public class MonitorTools {
 
    @Resource
    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) {
        log.info("AI调用getCameraDetail工具,参数: cameraId={}", cameraId);
 
        if (cameraId == null || cameraId.isEmpty()) {
            return "错误:摄像机ID不能为空";
        }
 
        try {
            R<ArdCamera> result = remoteCameraService.getCameraInfoRpc(cameraId, SecurityConstants.INNER);
 
            if (result == null) {
                return "错误:服务返回空结果";
            }
 
            if (result.getCode() == R.SUCCESS) {
                ArdCamera camera = result.getData();
                if (camera == null) {
                    return "提示:未找到摄像机ID为 " + cameraId + " 的摄像机";
                }
                return JSON.toJSONString(camera);
            } else {
                return String.format("获取摄像机信息失败:%s (code: %d)", result.getMsg(), result.getCode());
            }
        } catch (Exception e) {
            log.error("调用getCameraInfoRpc异常", e);
            return "系统异常:" + e.getMessage();
        }
    }
    @Tool(description = "搜索摄像机,支持名称、IP、端口、用户名、密码、坐标、状态关键词模糊查询")
    public String searchCameras(@ToolParam(description = "搜索关键词,支持摄像机名称或ID") String keyword) {
        log.info("AI调用searchCameras工具,参数: keyword={}", keyword);
 
        try {
            R<List<ArdCamera>> result = remoteCameraService.getAllCamera(SecurityConstants.INNER);
 
            if (result == null) {
                return "错误:服务返回空结果";
            }
 
            if (result.getCode() != R.SUCCESS) {
                return String.format("获取摄像机列表失败:%s", result.getMsg());
            }
 
            List<ArdCamera> cameras = result.getData();
            if (cameras == null || cameras.isEmpty()) {
                return "未找到任何摄像机";
            }
 
            List<ArdCamera> filteredCameras = cameras;
            if (filteredCameras.isEmpty()) {
                return "未找到符合条件的摄像机";
            }
 
            StringBuilder resultStr = new StringBuilder();
            resultStr.append(String.format("找到%d台摄像机:\n", filteredCameras.size()));
            for (ArdCamera camera : filteredCameras) {
 
 
                resultStr.append(String.format("  - ID: %s, 名称: %s, IP: %s, 厂商: %s,状态: %s, 类型: %s\n",
                        camera.getId(),
                        camera.getName(),
                        camera.getIp(),
                        getFactoryName(camera.getFactory()),
                        Objects.equals(camera.getState(), "1") ? "在线" : "离线",
                        getCameraTypeName(camera.getType())
                       ));
            }
            return resultStr.toString();
        } catch (Exception e) {
            log.error("调用getAllCamera异常", e);
            return "系统异常:" + e.getMessage();
        }
    }
    @Tool(description = """
    修改摄像机信息。传入摄像机ID和需要修改的字段,不传的字段保持原值不变。
    
    使用示例:
    - "把CAM-001的名字改成大门摄像头" → 传入 {id:"CAM-001", name:"大门摄像头"}
    - "将CAM-002设置为离线" → 传入 {id:"CAM-002", state:"0"}
    
    注意:id为必填项。
    """)
    public String updateCameraInfo(
            @ToolParam(description = "摄像机对象,包含id和需要修改的字段") ArdCamera updateParams) {
 
        log.info("AI调用updateCameraInfo工具,参数: {}", updateParams);
 
        // 必填校验
        if (updateParams == null || updateParams.getId() == null || updateParams.getId().isEmpty()) {
            return "错误:摄像机ID不能为空";
        }
 
        String cameraId = updateParams.getId();
 
        try {
 
            // 3. 直接调用 Feign 接口
            R<Boolean> updateResult = remoteCameraService.updateCamera(updateParams, SecurityConstants.INNER);
 
            if (updateResult == null || updateResult.getCode() != R.SUCCESS) {
                return "修改失败:" + (updateResult != null ? updateResult.getMsg() : "服务返回空");
            }
            // 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);
            return "系统异常:" + e.getMessage();
        }
    }
}