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();
|
}
|
}
|
}
|