refactor(audio): 将terminalId替换为robotId以统一机器人标识
- 修改AudioService中terminalId为robotId,包括变量声明、参数传递和日志输出 - 更新BaseChannelSubscribeHandler中的注释和参数解析逻辑 - 修改CameraStreamTicketService中的方法参数和记录类定义 - 更新DeRobotConfig文档中的术语描述 - 替换DeviceListController和EdgeAgvController中的terminalId参数为robotId - 修改EdgeAgvServiceImpl中所有方法的参数引用 - 更新EdgeArmController中所有终端ID参数为机器人ID - 修改EdgeArmServiceImpl中所有gRPC客户端调用的参数 - 调整EdgeArmTeleopOpenVO中的字段定义顺序
This commit is contained in:
parent
7278d2c0f0
commit
86a8e02d85
19
README.md
19
README.md
@ -7,7 +7,7 @@ Java 包名、Maven 坐标统一使用 `com.cmvr`。旧项目 `cmvr-iot` 仅作
|
||||
## 主要功能
|
||||
|
||||
- 系统管理:用户、角色、部门、菜单、字典、参数、日志和通知。
|
||||
- 设备管理:设备注册、终端配置、设备档案和机器人配置。
|
||||
- 机器人设备:以边缘端上报的永久 `robotId` 作为唯一业务身份,自动同步机器人地址、在线状态和设备清单。
|
||||
- 测试业务:任务配置、任务编排、任务实例、检测项、语音唤醒、Flowise 和 AI 评估。
|
||||
- 智能巡检:机器人、地图、点位、任务、执行实例、巡检结果和告警。
|
||||
- 智能座舱:语音交互、触控交互、TTS、语料库和车机操作配置。
|
||||
@ -41,7 +41,7 @@ Java 包名、Maven 坐标统一使用 `com.cmvr`。旧项目 `cmvr-iot` 仅作
|
||||
| `cmvr-iot-system` | 用户、角色、菜单、字典、参数和通用分组 |
|
||||
| `cmvr-iot-quartz` | Quartz 任务调度和任务日志 |
|
||||
| `cmvr-iot-generator` | 代码生成 |
|
||||
| `cmvr-iot-device` | 设备、终端和机器人配置 |
|
||||
| `cmvr-iot-device` | 设备协议模型、机器人配置和巡检告警监听 |
|
||||
| `cmvr-iot-test` | 测试任务、流程、检测项和执行实例 |
|
||||
| `cmvr-iot-vi` | 语音交互业务 |
|
||||
| `cmvr-iot-ti` | 触控交互业务 |
|
||||
@ -54,7 +54,7 @@ Java 包名、Maven 坐标统一使用 `com.cmvr`。旧项目 `cmvr-iot` 仅作
|
||||
| `cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-client` | 原有机器人 gRPC 客户端 |
|
||||
| `cmvr-iot-quic-contract` | QUIC 控制、节点事件和媒体数据协议 |
|
||||
| `cmvr-iot-quic` | 与主应用同进程运行的 QUIC Gateway |
|
||||
| `ruoyi-ui` | Vue 3 管理控制台 |
|
||||
| `cmvr-iot-ui-lxl-dev-worktree` | Vue 3 管理控制台(同级独立前端仓库) |
|
||||
|
||||
## 环境准备
|
||||
|
||||
@ -79,7 +79,8 @@ Java 包名、Maven 坐标统一使用 `com.cmvr`。旧项目 `cmvr-iot` 仅作
|
||||
- `sql/aima_module.sql`:爱玛业务。
|
||||
- `sql/inspection_module.sql`、`inspection_result.sql`、`inspection_detection_alert.sql`:巡检业务。
|
||||
- `sql/tts_corpus_module.sql`:TTS 和语料业务。
|
||||
- `sql/quic_gateway_terminal_migration.sql`:QUIC 节点绑定及运行状态字段。
|
||||
- `sql/robot_quic_identity_migration.sql`:机器人 QUIC 身份、运行状态和设备快照表。
|
||||
- `sql/robot_id_only_migration.sql`:移除巡检机器人和任务实例中的历史终端 ID 字段。
|
||||
|
||||
补充脚本可能面向不同历史库版本。已有数据库升级前应先备份,并确认字段或索引尚未存在。
|
||||
|
||||
@ -111,7 +112,7 @@ Knife4j 只展示带原有 `@ApiOperation` 注解的正式接口,并沿用中
|
||||
## 前端运行
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
cd ../cmvr-iot-ui-lxl-dev-worktree
|
||||
pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
@ -120,7 +121,9 @@ pnpm dev
|
||||
|
||||
## gRPC 与 QUIC
|
||||
|
||||
原有机器人 gRPC 客户端与 proto 均保留。终端 gRPC 地址优先读取 `de_device_terminal_config` 的 `host` 和 `port`,没有终端配置时使用当前 profile 中的 `grpc.client.grpc-server.address`。
|
||||
原有机器人 gRPC 客户端与 proto 均保留,但业务调用只传永久 `robotId`。平台根据 `inspection_robot.robot_id` 查找 QUIC 最近同步的 `ip_address` 和 `port`,不再使用终端 ID 或终端配置解析 gRPC 地址。
|
||||
|
||||
边缘端通过 QUIC 上报设备快照后,平台按 `robotId + deviceId` 写入 `inspection_robot_device`。前端选择机器人后只展示该机器人当前在线且启用的设备;单一匹配设备会自动选中并锁定。
|
||||
|
||||
QUIC 不是独立服务,`cmvr-iot-quic` 已作为 `cmvr-iot-admin` 的运行时依赖。启用时主应用同时启动:
|
||||
|
||||
@ -139,7 +142,7 @@ mvn test
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 构建前端生产包
|
||||
cd ruoyi-ui
|
||||
cd ../cmvr-iot-ui-lxl-dev-worktree
|
||||
pnpm build:prod
|
||||
```
|
||||
|
||||
@ -148,6 +151,6 @@ Windows 下也可以使用 `bin/package.bat`、`bin/run.bat` 和 `bin/clean.bat`
|
||||
## 排查提示
|
||||
|
||||
- `ApplicationContext ... has been closed already`:彻底停止旧 Java 进程后重新启动,不要使用 DevTools 热重启。
|
||||
- `cannot find a NameResolver for static://...`:这是 gRPC target scheme 解析问题,不代表网络不通;检查 `GrpcServiceManager` 的通道创建方式和终端地址格式。
|
||||
- 找不到机器人或机器人离线:确认机器人表已登记相同的永久 `robotId`,并检查 QUIC 注册日志、`inspection_robot` 的地址和连接状态。
|
||||
- QUIC 启动失败:检查证书、私钥、ALPN、UDP 端口占用和 native library 对应的操作系统架构。
|
||||
- 数据库提示缺少字段:确认基础脚本版本及对应模块迁移脚本已经执行。
|
||||
|
||||
@ -28,9 +28,9 @@ public class DeviceListController {
|
||||
@PreAuthorize("@ss.hasPermi('device:profile:list')")
|
||||
@GetMapping("/addList")
|
||||
@ApiOperation("同步设备信息列表")
|
||||
public int addDeviceList(@RequestParam String terminalId){
|
||||
public int addDeviceList(@RequestParam String robotId){
|
||||
|
||||
List<DeDeviceRegistration> list = systemService.deviceList(terminalId);
|
||||
List<DeDeviceRegistration> list = systemService.deviceList(robotId);
|
||||
|
||||
return registrationService.addDeviceList(list);
|
||||
}
|
||||
|
||||
@ -51,11 +51,11 @@ public class EdgeAgvController {
|
||||
@ApiOperation("获取AGV运行时状态")
|
||||
@GetMapping("/getRuntimeState")
|
||||
public AjaxResult getRuntimeState(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true)
|
||||
@RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
AgvUtils.AgvRuntimeState state = edgeAgvService.getRuntimeState(vo);
|
||||
return AjaxResult.ok(toRuntimeStateMap(state));
|
||||
}
|
||||
@ -66,11 +66,11 @@ public class EdgeAgvController {
|
||||
@ApiOperation("获取导航状态")
|
||||
@GetMapping("/getNavigationStatus")
|
||||
public AjaxResult getNavigationStatus(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true)
|
||||
@RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
AgvUtils.AgvNavigationStatus status = edgeAgvService.getNavigationStatus(vo);
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("state", status.getState());
|
||||
@ -186,11 +186,11 @@ public class EdgeAgvController {
|
||||
@ApiOperation("列出所有地图")
|
||||
@GetMapping("/listMaps")
|
||||
public AjaxResult listMaps(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true)
|
||||
@RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
List<String> maps = edgeAgvService.listMaps(vo);
|
||||
return AjaxResult.ok(maps);
|
||||
}
|
||||
@ -201,11 +201,11 @@ public class EdgeAgvController {
|
||||
@ApiOperation("列出所有站点")
|
||||
@GetMapping("/listStations")
|
||||
public AjaxResult listStations(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久ID", required = true)
|
||||
@RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
List<AgvUtils.AgvStation> stations = edgeAgvService.listStations(vo);
|
||||
List<Map<String, Object>> stationList = new ArrayList<>();
|
||||
for (AgvUtils.AgvStation station : stations) {
|
||||
@ -240,14 +240,14 @@ public class EdgeAgvController {
|
||||
@ApiOperation("下载地图")
|
||||
@GetMapping("/downloadMap")
|
||||
public AjaxResult downloadMap(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true)
|
||||
@RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam("deviceId") String deviceId,
|
||||
@ApiParam(value = "地图名称", required = true)
|
||||
@RequestParam("mapName") String mapName) {
|
||||
EdgeAgvMapNameVO vo = new EdgeAgvMapNameVO();
|
||||
vo.setTerminalId(terminalId);
|
||||
vo.setRobotId(robotId);
|
||||
vo.setDeviceId(deviceId);
|
||||
vo.setMapName(mapName);
|
||||
String content = edgeAgvService.downloadMap(vo, vo.getMapName());
|
||||
@ -284,9 +284,9 @@ public class EdgeAgvController {
|
||||
/**
|
||||
* 将 protobuf 运行时状态转换为前端友好的 Map,避免直接暴露 protobuf 对象结构。
|
||||
*/
|
||||
private EdgeCommonVO commonVo(String terminalId, String deviceId) {
|
||||
private EdgeCommonVO commonVo(String robotId, String deviceId) {
|
||||
EdgeCommonVO vo = new EdgeCommonVO();
|
||||
vo.setTerminalId(terminalId);
|
||||
vo.setRobotId(robotId);
|
||||
vo.setDeviceId(deviceId);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@ -33,9 +33,9 @@ public class EdgeArmController {
|
||||
@ApiOperation("关闭力矩")
|
||||
@GetMapping("/torqueOff")
|
||||
public AjaxResult torqueOff(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
edgeArmService.torqueOff(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
@ -43,9 +43,9 @@ public class EdgeArmController {
|
||||
@ApiOperation("开启力矩")
|
||||
@GetMapping("/torqueOn")
|
||||
public AjaxResult torqueOn(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
edgeArmService.torqueOn(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
@ -56,9 +56,9 @@ public class EdgeArmController {
|
||||
@ApiOperation("清除故障")
|
||||
@GetMapping("/clearFault")
|
||||
public AjaxResult clearFault(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
edgeArmService.clearFault(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
@ -137,9 +137,9 @@ public class EdgeArmController {
|
||||
@ApiOperation("停止运动")
|
||||
@GetMapping("/stopMotion")
|
||||
public AjaxResult stopMotion(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
edgeArmService.stopMotion(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
@ -147,9 +147,9 @@ public class EdgeArmController {
|
||||
@ApiOperation("获取关节状态")
|
||||
@GetMapping("/getJointState")
|
||||
public AjaxResult getJointState(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO vo = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO vo = commonVo(robotId, deviceId);
|
||||
ArmCommand.JointResponse result = edgeArmService.getJointState(vo);
|
||||
ArmCommand.JointState state = result.getState();
|
||||
|
||||
@ -167,11 +167,11 @@ public class EdgeArmController {
|
||||
@ApiOperation("获取末端位姿")
|
||||
@GetMapping("/getPose")
|
||||
public AjaxResult getPose(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId,
|
||||
@ApiParam("基座连杆名称") @RequestParam(value = "baseLink", required = false) String baseLink,
|
||||
@ApiParam("末端执行器连杆名称") @RequestParam(value = "eeLink", required = false) String eeLink) {
|
||||
EdgeArmPoseQueryVO vo = poseQueryVo(terminalId, deviceId, baseLink, eeLink);
|
||||
EdgeArmPoseQueryVO vo = poseQueryVo(robotId, deviceId, baseLink, eeLink);
|
||||
ArmCommand.GetPose.Response result = edgeArmService.getPose(vo, vo.getBaseLink(), vo.getEeLink());
|
||||
ArmCommand.CartesianPose pose = result.getPose();
|
||||
|
||||
@ -190,11 +190,11 @@ public class EdgeArmController {
|
||||
@ApiOperation("标定零点")
|
||||
@GetMapping("/calibrateZeroQ")
|
||||
public AjaxResult calibrateZeroQ(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId,
|
||||
@ApiParam(value = "关节名称", required = true) @RequestParam("jointName") String jointName) {
|
||||
EdgeArmCalibrateZeroQVO vo = new EdgeArmCalibrateZeroQVO();
|
||||
vo.setTerminalId(terminalId);
|
||||
vo.setRobotId(robotId);
|
||||
vo.setDeviceId(deviceId);
|
||||
vo.setJointName(jointName);
|
||||
edgeArmService.calibrateZeroQ(vo, vo.getJointName());
|
||||
@ -204,11 +204,11 @@ public class EdgeArmController {
|
||||
@ApiOperation("获取位姿矩阵")
|
||||
@GetMapping("/getPoseMatrix")
|
||||
public AjaxResult getPoseMatrix(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId,
|
||||
@ApiParam("基座连杆名称") @RequestParam(value = "baseLink", required = false) String baseLink,
|
||||
@ApiParam("末端执行器连杆名称") @RequestParam(value = "eeLink", required = false) String eeLink) {
|
||||
EdgeArmPoseQueryVO vo = poseQueryVo(terminalId, deviceId, baseLink, eeLink);
|
||||
EdgeArmPoseQueryVO vo = poseQueryVo(robotId, deviceId, baseLink, eeLink);
|
||||
ArmCommand.GetPoseMatrix.Response result = edgeArmService.getPoseMatrix(vo, vo.getBaseLink(), vo.getEeLink());
|
||||
// 将TransformMatrix4x4转换为Map
|
||||
ArmCommand.TransformMatrix4x4 matrix = result.getMatrix();
|
||||
@ -263,16 +263,16 @@ public class EdgeArmController {
|
||||
return AjaxResult.ok(matrixMap);
|
||||
}
|
||||
|
||||
private EdgeCommonVO commonVo(String terminalId, String deviceId) {
|
||||
private EdgeCommonVO commonVo(String robotId, String deviceId) {
|
||||
EdgeCommonVO vo = new EdgeCommonVO();
|
||||
vo.setTerminalId(terminalId);
|
||||
vo.setRobotId(robotId);
|
||||
vo.setDeviceId(deviceId);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private EdgeArmPoseQueryVO poseQueryVo(String terminalId, String deviceId, String baseLink, String eeLink) {
|
||||
private EdgeArmPoseQueryVO poseQueryVo(String robotId, String deviceId, String baseLink, String eeLink) {
|
||||
EdgeArmPoseQueryVO vo = new EdgeArmPoseQueryVO();
|
||||
vo.setTerminalId(terminalId);
|
||||
vo.setRobotId(robotId);
|
||||
vo.setDeviceId(deviceId);
|
||||
vo.setBaseLink(baseLink);
|
||||
vo.setEeLink(eeLink);
|
||||
|
||||
@ -35,45 +35,45 @@ public class EdgeCameraController extends BaseController {
|
||||
@ApiOperation("获取相机状态")
|
||||
@GetMapping("/status")
|
||||
public AjaxResult status(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(JSON.toJSONString(edgeCameraService.status(edgeCommonVO)));
|
||||
}
|
||||
|
||||
@ApiOperation("开启相机")
|
||||
@GetMapping("/start")
|
||||
public AjaxResult start(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(edgeCameraService.start(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ApiOperation("关闭相机")
|
||||
@GetMapping("/stop")
|
||||
public AjaxResult stop(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(edgeCameraService.stop(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ApiOperation("获取图片")
|
||||
@GetMapping("/getRGBImage")
|
||||
public AjaxResult getRGBImage(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(edgeCameraService.getRGBImage(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ApiOperation("Get one depth image")
|
||||
@GetMapping("/getDepthImage")
|
||||
public AjaxResult getDepthImage(
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@RequestParam("robotId") String robotId,
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
return success(edgeCameraService.getDepthImage(commonVo(terminalId, deviceId)));
|
||||
return success(edgeCameraService.getDepthImage(commonVo(robotId, deviceId)));
|
||||
}
|
||||
|
||||
@ApiOperation("Control camera PTZ")
|
||||
@ -85,9 +85,9 @@ public class EdgeCameraController extends BaseController {
|
||||
@ApiOperation("Get a short-lived RGB video stream URL")
|
||||
@GetMapping("/rgb-stream-url")
|
||||
public AjaxResult rgbStreamUrl(
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@RequestParam("robotId") String robotId,
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
String ticket = cameraStreamTicketService.issue(terminalId, deviceId);
|
||||
String ticket = cameraStreamTicketService.issue(robotId, deviceId);
|
||||
return success((Object) ("/api/edge/camera/rgb-stream?ticket=" + ticket));
|
||||
}
|
||||
|
||||
@ -98,20 +98,20 @@ public class EdgeCameraController extends BaseController {
|
||||
if (target == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||
}
|
||||
return videoStreamResponse(target.terminalId(), target.deviceId());
|
||||
return videoStreamResponse(target.robotId(), target.deviceId());
|
||||
}
|
||||
|
||||
@ApiOperation("Public RGB fragmented MP4 live stream")
|
||||
@GetMapping(value = "/rgb-stream/public", produces = "video/mp4")
|
||||
public ResponseEntity<StreamingResponseBody> publicRgbStream(
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@RequestParam("robotId") String robotId,
|
||||
@RequestParam("deviceId") String deviceId) {
|
||||
return videoStreamResponse(terminalId, deviceId);
|
||||
return videoStreamResponse(robotId, deviceId);
|
||||
}
|
||||
|
||||
private ResponseEntity<StreamingResponseBody> videoStreamResponse(String terminalId, String deviceId) {
|
||||
private ResponseEntity<StreamingResponseBody> videoStreamResponse(String robotId, String deviceId) {
|
||||
StreamingResponseBody body = outputStream -> edgeCameraService.writeRGBVideoStream(
|
||||
terminalId, deviceId, outputStream);
|
||||
robotId, deviceId, outputStream);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType("video/mp4"))
|
||||
.cacheControl(CacheControl.noStore())
|
||||
@ -123,33 +123,33 @@ public class EdgeCameraController extends BaseController {
|
||||
@ApiOperation("开始录制视频")
|
||||
@GetMapping("/startRecording")
|
||||
public AjaxResult startRecording(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(edgeCameraService.startRecording(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ApiOperation("停止录制视频")
|
||||
@GetMapping("/stopRecording")
|
||||
public AjaxResult stopRecording(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(edgeCameraService.stopRecording(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ApiOperation("获取图片和视频")
|
||||
@GetMapping("/getRGBDImages")
|
||||
public AjaxResult getRGBDImages(
|
||||
@ApiParam(value = "终端设备ID", required = true) @RequestParam("terminalId") String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam("robotId") String robotId,
|
||||
@ApiParam(value = "设备ID", required = true) @RequestParam("deviceId") String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = commonVo(terminalId, deviceId);
|
||||
EdgeCommonVO edgeCommonVO = commonVo(robotId, deviceId);
|
||||
return success(edgeCameraService.getRGBDImages(edgeCommonVO));
|
||||
}
|
||||
|
||||
private EdgeCommonVO commonVo(String terminalId, String deviceId) {
|
||||
private EdgeCommonVO commonVo(String robotId, String deviceId) {
|
||||
EdgeCommonVO vo = new EdgeCommonVO();
|
||||
vo.setTerminalId(terminalId);
|
||||
vo.setRobotId(robotId);
|
||||
vo.setDeviceId(deviceId);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ public class EdgeDexHandController extends BaseController {
|
||||
@GetMapping("/status")
|
||||
public AjaxResult status(
|
||||
@RequestParam("deviceId") String deviceId,
|
||||
@RequestParam("terminalId") String terminalId
|
||||
@RequestParam("robotId") String robotId
|
||||
) {
|
||||
return success(JSON.parseObject(JSON.toJSONString(edgeDexHandService.getStatus(terminalId, deviceId)), Map.class));
|
||||
return success(JSON.parseObject(JSON.toJSONString(edgeDexHandService.getStatus(robotId, deviceId)), Map.class));
|
||||
}
|
||||
|
||||
|
||||
@ -35,11 +35,11 @@ public class EdgeDexHandController extends BaseController {
|
||||
@GetMapping("/angle")
|
||||
public AjaxResult setAngle(
|
||||
@RequestParam("deviceId") String deviceId,
|
||||
@RequestParam("terminalId") String terminalId,
|
||||
@RequestParam("robotId") String robotId,
|
||||
@RequestParam("id") int id,
|
||||
@RequestParam("value") float value
|
||||
) {
|
||||
edgeDexHandService.setDexHandAngle(terminalId, deviceId, id, value);
|
||||
edgeDexHandService.setDexHandAngle(robotId, deviceId, id, value);
|
||||
return success("ok");
|
||||
}
|
||||
|
||||
@ -48,8 +48,8 @@ public class EdgeDexHandController extends BaseController {
|
||||
@GetMapping("/sensor")
|
||||
public AjaxResult sensor(
|
||||
@RequestParam("deviceId") String deviceId,
|
||||
@RequestParam("terminalId") String terminalId
|
||||
@RequestParam("robotId") String robotId
|
||||
) {
|
||||
return success(JSON.parseObject(edgeDexHandService.getSensorData(terminalId, deviceId), Map.class));
|
||||
return success(JSON.parseObject(edgeDexHandService.getSensorData(robotId, deviceId), Map.class));
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("获取麦克风状态")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:query')")
|
||||
@GetMapping("/status")
|
||||
public AjaxResult getStatus(@ApiParam(value = "终端设备ID", required = true) @RequestParam String terminalId, @ApiParam (value = "设备ID", required = true) @RequestParam String deviceId) {
|
||||
public AjaxResult getStatus(@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam String robotId, @ApiParam (value = "设备ID", required = true) @RequestParam String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
return AjaxResult.success(microphoneService.getStatus(edgeCommonVO));
|
||||
}
|
||||
@ -75,9 +75,9 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("获取音量")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:volume')")
|
||||
@GetMapping("/volume")
|
||||
public AjaxResult getVolume(@ApiParam(value = "终端设备ID", required = true) @RequestParam String terminalId, @ApiParam (value = "设备ID", required = true) @RequestParam String deviceId) {
|
||||
public AjaxResult getVolume(@ApiParam(value = "机器人永久唯一ID", required = true) @RequestParam String robotId, @ApiParam (value = "设备ID", required = true) @RequestParam String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
return AjaxResult.success(microphoneService.getVolume(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ -33,13 +33,13 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:query')")
|
||||
@GetMapping("/status")
|
||||
public AjaxResult getStatus(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true)
|
||||
@RequestParam String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId) {
|
||||
try {
|
||||
// 获取扬声器状态
|
||||
SpeakerCommand.GetSpeakerStateCommand.Feedback feedback = speakerService.getStatus(terminalId, deviceId);
|
||||
SpeakerCommand.GetSpeakerStateCommand.Feedback feedback = speakerService.getStatus(robotId, deviceId);
|
||||
SpeakerCommand.SpeakerState state = feedback.getState();
|
||||
|
||||
// 构建返回结果
|
||||
@ -73,7 +73,7 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:play')")
|
||||
@PostMapping("/play")
|
||||
public AjaxResult playAudio(@RequestBody EdgeSpeakerPlayAudioVO edgeSpeakerPlayAudioVO) {
|
||||
speakerService.playAudio(edgeSpeakerPlayAudioVO.getTerminalId(), edgeSpeakerPlayAudioVO.getDeviceId(), edgeSpeakerPlayAudioVO.getAudioPath());
|
||||
speakerService.playAudio(edgeSpeakerPlayAudioVO.getRobotId(), edgeSpeakerPlayAudioVO.getDeviceId(), edgeSpeakerPlayAudioVO.getAudioPath());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:stop')")
|
||||
@PostMapping("/stop")
|
||||
public AjaxResult stopPlayback(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
speakerService.stopPlayback(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
speakerService.stopPlayback(edgeCommonVO.getRobotId(), edgeCommonVO.getDeviceId());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:pause')")
|
||||
@PostMapping("/pause")
|
||||
public AjaxResult pausePlayback(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
speakerService.pausePlayback(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
speakerService.pausePlayback(edgeCommonVO.getRobotId(), edgeCommonVO.getDeviceId());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:resume')")
|
||||
@PostMapping("/resume")
|
||||
public AjaxResult resumePlayback(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
speakerService.resumePlayback(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
speakerService.resumePlayback(edgeCommonVO.getRobotId(), edgeCommonVO.getDeviceId());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:volume')")
|
||||
@PostMapping("/volume")
|
||||
public AjaxResult setVolume(@RequestBody EdgeMicrophoneVolumeVO edgeMicrophoneVolumeVO) {
|
||||
speakerService.setVolume(edgeMicrophoneVolumeVO.getTerminalId(), edgeMicrophoneVolumeVO.getDeviceId(), edgeMicrophoneVolumeVO.getVolume());
|
||||
speakerService.setVolume(edgeMicrophoneVolumeVO.getRobotId(), edgeMicrophoneVolumeVO.getDeviceId(), edgeMicrophoneVolumeVO.getVolume());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -128,11 +128,11 @@ public class EdgeSpeakerController {
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:volume')")
|
||||
@GetMapping("/volume")
|
||||
public AjaxResult getVolume(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "机器人永久唯一ID", required = true)
|
||||
@RequestParam String robotId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId) {
|
||||
return AjaxResult.success(speakerService.getVolume(terminalId, deviceId));
|
||||
return AjaxResult.success(speakerService.getVolume(robotId, deviceId));
|
||||
}
|
||||
|
||||
@ApiOperation("获取所有音频")
|
||||
|
||||
@ -26,14 +26,14 @@ public class EdgeSystemController extends BaseController {
|
||||
|
||||
@ApiOperation("Get edge system information")
|
||||
@GetMapping("/info")
|
||||
public AjaxResult info(@RequestParam("terminalId") String terminalId) {
|
||||
return success(JSON.toJSONString(edgeSystemService.getSystemInfo(terminalId)));
|
||||
public AjaxResult info(@RequestParam("robotId") String robotId) {
|
||||
return success(JSON.toJSONString(edgeSystemService.getSystemInfo(robotId)));
|
||||
}
|
||||
|
||||
@ApiOperation("Get edge system runtime status")
|
||||
@GetMapping("/status")
|
||||
public AjaxResult status(@RequestParam("terminalId") String terminalId) {
|
||||
return success(JSON.toJSONString(edgeSystemService.getSystemStatus(terminalId)));
|
||||
public AjaxResult status(@RequestParam("robotId") String robotId) {
|
||||
return success(JSON.toJSONString(edgeSystemService.getSystemStatus(robotId)));
|
||||
}
|
||||
|
||||
@ApiOperation("Update edge device parameters")
|
||||
@ -50,7 +50,7 @@ public class EdgeSystemController extends BaseController {
|
||||
|
||||
@ApiOperation("停止所有设备")
|
||||
@GetMapping("/stopAll")
|
||||
public AjaxResult stopAll(@RequestParam("terminalId") String terminalId) {
|
||||
return AjaxResult.ok(edgeSystemService.stopAll(terminalId));
|
||||
public AjaxResult stopAll(@RequestParam("robotId") String robotId) {
|
||||
return AjaxResult.ok(edgeSystemService.stopAll(robotId));
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +70,25 @@ public class InspectionRobotController extends BaseController
|
||||
return success(inspectionRobotService.selectInspectionRobotById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("查询机器人自动发现的设备")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:query')")
|
||||
@GetMapping("/{id}/devices")
|
||||
public AjaxResult devices(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionRobotService.selectRobotDevices(id));
|
||||
}
|
||||
|
||||
@ApiOperation("按机器人ID查询自动发现的设备")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:query')")
|
||||
@GetMapping("/devices")
|
||||
public AjaxResult devicesByRobotId(
|
||||
@RequestParam @ApiParam(value = "机器人永久唯一ID", required = true) String robotId,
|
||||
@RequestParam(required = false) @ApiParam("设备类型") Integer deviceKind,
|
||||
@RequestParam(defaultValue = "true") @ApiParam("是否只查询在线且启用的设备") boolean onlineOnly)
|
||||
{
|
||||
return success(inspectionRobotService.selectRobotDevicesByRobotId(robotId, deviceKind, onlineOnly));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检机器人
|
||||
*/
|
||||
|
||||
@ -157,7 +157,7 @@ public class TeFlowController extends BaseController {
|
||||
|
||||
@PostMapping("/action")
|
||||
@ApiOperation(value = "单个节点执行",
|
||||
notes = "设备通用指令action=DEVICE_EXECUTE_JSON_COMMAND,payload需要terminalId、deviceId、requestJson;"
|
||||
notes = "设备通用指令action=DEVICE_EXECUTE_JSON_COMMAND,payload需要robotId、deviceId、requestJson;"
|
||||
+ "巡检仪表节点action=INSPECTION_METER_RECOGNIZE,payload使用InspectionMeterRecognizeConfigVO;"
|
||||
+ "人工判断节点action=INSPECTION_MANUAL_REVIEW_CREATE,payload使用InspectionManualReviewConfigVO。"
|
||||
+ "该接口用于试调节点,不会生成正式巡检任务结果")
|
||||
|
||||
@ -51,7 +51,7 @@ public class TeFlowiseController extends BaseController {
|
||||
runParams.put("5bb26d52e1861c6936f3c3149eaf17e8", runParams1);
|
||||
TeTaskExecuteNormalVO taskExecuteNormalVO = TeTaskExecuteNormalVO.builder()
|
||||
.taskId("b6ab5ffff783d9b25d0dc34f13be222d")
|
||||
.terminalId("4ed1246c465b97975f96c9ef8371a3bd")
|
||||
.robotId("4ed1246c465b97975f96c9ef8371a3bd")
|
||||
.runParams(JSONObject.from(runParams)).build();
|
||||
if (!taskInstIdList.isEmpty()) {
|
||||
try {
|
||||
|
||||
@ -13,11 +13,11 @@ public class CameraStreamTicketService {
|
||||
private static final long TICKET_LIFETIME_MILLIS = Duration.ofSeconds(30).toMillis();
|
||||
private final Map<String, StreamTarget> tickets = new ConcurrentHashMap<>();
|
||||
|
||||
public String issue(String terminalId, String deviceId) {
|
||||
public String issue(String robotId, String deviceId) {
|
||||
long now = System.currentTimeMillis();
|
||||
tickets.entrySet().removeIf(entry -> entry.getValue().expiresAt() < now);
|
||||
String ticket = UUID.randomUUID().toString().replace("-", "");
|
||||
tickets.put(ticket, new StreamTarget(terminalId, deviceId, now + TICKET_LIFETIME_MILLIS));
|
||||
tickets.put(ticket, new StreamTarget(robotId, deviceId, now + TICKET_LIFETIME_MILLIS));
|
||||
return ticket;
|
||||
}
|
||||
|
||||
@ -33,6 +33,6 @@ public class CameraStreamTicketService {
|
||||
return target;
|
||||
}
|
||||
|
||||
public record StreamTarget(String terminalId, String deviceId, long expiresAt) {
|
||||
public record StreamTarget(String robotId, String deviceId, long expiresAt) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,33 +62,33 @@ public class RobotAudioGrpcAdapter {
|
||||
private final GrpcServiceManager grpcServiceManager;
|
||||
private final ConcurrentMap<String, RobotAudioStream> streams = new ConcurrentHashMap<>();
|
||||
|
||||
public RobotAudioStream openStream(String terminalId,
|
||||
public RobotAudioStream openStream(String robotId,
|
||||
String deviceId,
|
||||
String sessionId,
|
||||
String operatorId,
|
||||
RobotAudioStreamListener listener) {
|
||||
return openStream(terminalId, deviceId, deviceId, sessionId, operatorId, listener);
|
||||
return openStream(robotId, deviceId, deviceId, sessionId, operatorId, listener);
|
||||
}
|
||||
|
||||
public RobotAudioStream openStream(String terminalId,
|
||||
public RobotAudioStream openStream(String robotId,
|
||||
String speakerDeviceId,
|
||||
String micDeviceId,
|
||||
String sessionId,
|
||||
String operatorId,
|
||||
RobotAudioStreamListener listener) {
|
||||
SpeakerServiceGrpc.SpeakerServiceStub speakerStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceStub.class);
|
||||
grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceStub micStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, MicPhoneServiceGrpc.MicPhoneServiceStub.class);
|
||||
grpcServiceManager.getGrpcClient(robotId, MicPhoneServiceGrpc.MicPhoneServiceStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub speakerBlockingStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub micBlockingStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
grpcServiceManager.getGrpcClient(robotId, MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
preflightDeviceStatus(speakerBlockingStub, micBlockingStub, speakerDeviceId, micDeviceId, sessionId);
|
||||
|
||||
RobotAudioStream stream = new RobotAudioStream(
|
||||
terminalId, speakerDeviceId, micDeviceId, sessionId, operatorId, speakerStub, micStub, listener);
|
||||
robotId, speakerDeviceId, micDeviceId, sessionId, operatorId, speakerStub, micStub, listener);
|
||||
RobotAudioStream exists = streams.putIfAbsent(sessionId, stream);
|
||||
if (exists != null) {
|
||||
throw new IllegalStateException("实时语音会话已存在:" + sessionId);
|
||||
@ -96,8 +96,8 @@ public class RobotAudioGrpcAdapter {
|
||||
|
||||
try {
|
||||
stream.start();
|
||||
log.info("实时对讲 gRPC 流已创建,sessionId={},terminalId={},speakerDeviceId={},micDeviceId={},operatorId={},sampleRate={},channels={},bits={},frameMs={},frameBytes={}",
|
||||
sessionId, terminalId, speakerDeviceId, micDeviceId, operatorId, SAMPLE_RATE, CHANNELS, BITS_PER_SAMPLE, FRAME_MS, FRAME_BYTES);
|
||||
log.info("实时对讲 gRPC 流已创建,sessionId={},robotId={},speakerDeviceId={},micDeviceId={},operatorId={},sampleRate={},channels={},bits={},frameMs={},frameBytes={}",
|
||||
sessionId, robotId, speakerDeviceId, micDeviceId, operatorId, SAMPLE_RATE, CHANNELS, BITS_PER_SAMPLE, FRAME_MS, FRAME_BYTES);
|
||||
return stream;
|
||||
} catch (RuntimeException e) {
|
||||
streams.remove(sessionId, stream);
|
||||
@ -163,7 +163,7 @@ public class RobotAudioGrpcAdapter {
|
||||
}
|
||||
|
||||
public class RobotAudioStream {
|
||||
private final String terminalId;
|
||||
private final String robotId;
|
||||
private final String speakerDeviceId;
|
||||
private final String micDeviceId;
|
||||
private final String sessionId;
|
||||
@ -190,7 +190,7 @@ public class RobotAudioGrpcAdapter {
|
||||
private volatile long lastStatsLogAt;
|
||||
private volatile byte[] pendingBrowserBytes = new byte[0];
|
||||
|
||||
private RobotAudioStream(String terminalId,
|
||||
private RobotAudioStream(String robotId,
|
||||
String speakerDeviceId,
|
||||
String micDeviceId,
|
||||
String sessionId,
|
||||
@ -198,7 +198,7 @@ public class RobotAudioGrpcAdapter {
|
||||
SpeakerServiceGrpc.SpeakerServiceStub speakerStub,
|
||||
MicPhoneServiceGrpc.MicPhoneServiceStub micStub,
|
||||
RobotAudioStreamListener listener) {
|
||||
this.terminalId = terminalId;
|
||||
this.robotId = robotId;
|
||||
this.speakerDeviceId = speakerDeviceId;
|
||||
this.micDeviceId = micDeviceId;
|
||||
this.sessionId = sessionId;
|
||||
@ -365,8 +365,8 @@ public class RobotAudioGrpcAdapter {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public String getTerminalId() {
|
||||
return terminalId;
|
||||
public String getRobotId() {
|
||||
return robotId;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
@ -639,8 +639,8 @@ public class RobotAudioGrpcAdapter {
|
||||
return;
|
||||
}
|
||||
Throwable actual = throwable == null ? new RuntimeException("audio stream failed") : throwable;
|
||||
log.error("实时对讲 gRPC 流异常,source={},sessionId={},terminalId={},speakerDeviceId={},micDeviceId={}",
|
||||
source, sessionId, terminalId, speakerDeviceId, micDeviceId, actual);
|
||||
log.error("实时对讲 gRPC 流异常,source={},sessionId={},robotId={},speakerDeviceId={},micDeviceId={}",
|
||||
source, sessionId, robotId, speakerDeviceId, micDeviceId, actual);
|
||||
sendExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -660,7 +660,7 @@ public class RobotAudioGrpcAdapter {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
log.info("实时对讲 gRPC 流远端结束,sessionId={},terminalId={},speakerDeviceId={},micDeviceId={}", sessionId, terminalId, speakerDeviceId, micDeviceId);
|
||||
log.info("实时对讲 gRPC 流远端结束,sessionId={},robotId={},speakerDeviceId={},micDeviceId={}", sessionId, robotId, speakerDeviceId, micDeviceId);
|
||||
sendExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@ -14,7 +14,7 @@ import java.util.function.Function;
|
||||
public class GrpcChannelCache {
|
||||
|
||||
private final long ttlSeconds; // 通道存活时间(秒)
|
||||
private final Map<String, ChannelWrapper> channelMap = new ConcurrentHashMap<>(); // 设备 ID -> 通道包装器
|
||||
private final Map<String, ChannelWrapper> channelMap = new ConcurrentHashMap<>(); // 机器人 ID -> 通道包装器
|
||||
|
||||
public GrpcChannelCache(long ttlSeconds) {
|
||||
this.ttlSeconds = ttlSeconds;
|
||||
@ -23,11 +23,11 @@ public class GrpcChannelCache {
|
||||
/**
|
||||
* 获取通道:存在则刷新时间,过期则重建,不存在则创建
|
||||
*/
|
||||
public ManagedChannel get(String terminalId, Function<String, ManagedChannel> supplier) {
|
||||
return channelMap.compute(terminalId, (k, v) -> {
|
||||
public ManagedChannel get(String robotId, Function<String, ManagedChannel> supplier) {
|
||||
return channelMap.compute(robotId, (k, v) -> {
|
||||
if (v == null || v.isExpired(ttlSeconds)) { // 为空或过期时重建
|
||||
if (v != null) v.close(); // 关闭旧通道
|
||||
return new ChannelWrapper(supplier.apply(terminalId)); // 创建新通道包装器
|
||||
return new ChannelWrapper(supplier.apply(robotId)); // 创建新通道包装器
|
||||
} else {
|
||||
v.refresh(); // 更新最后访问时间
|
||||
return v;
|
||||
@ -50,11 +50,11 @@ public class GrpcChannelCache {
|
||||
}
|
||||
|
||||
/**
|
||||
* 终端主动上报的gRPC地址发生变化时立即关闭旧通道。
|
||||
* 机器人主动上报的gRPC地址发生变化时立即关闭旧通道。
|
||||
* 下一次业务调用仍通过原有supplier创建ManagedChannel。
|
||||
*/
|
||||
public void invalidate(String terminalId) {
|
||||
ChannelWrapper wrapper = channelMap.remove(terminalId);
|
||||
public void invalidate(String robotId) {
|
||||
ChannelWrapper wrapper = channelMap.remove(robotId);
|
||||
if (wrapper != null) {
|
||||
wrapper.close();
|
||||
}
|
||||
|
||||
@ -2,9 +2,8 @@ package com.cmvr.edge.client.manage;
|
||||
|
||||
import cmvr.api.*;
|
||||
import cmvr.api.armteleop.v1.ArmTeleopServiceGrpc;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.cmvr.device.domain.DeDeviceTerminalConfig;
|
||||
import com.cmvr.device.service.IDeDeviceTerminalConfigService;
|
||||
import com.cmvr.common.robot.RobotEndpoint;
|
||||
import com.cmvr.common.robot.RobotEndpointResolver;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -25,7 +24,7 @@ import java.util.function.Function;
|
||||
@RequiredArgsConstructor
|
||||
public class GrpcServiceManager {
|
||||
|
||||
private final IDeDeviceTerminalConfigService deviceTerminalConfigService;
|
||||
private final RobotEndpointResolver robotEndpointResolver;
|
||||
|
||||
@Value("${grpc.client.grpc-server.address}")
|
||||
private String DEFAULT_GRPC_ADDRESS;
|
||||
@ -73,8 +72,8 @@ public class GrpcServiceManager {
|
||||
* 获取 gRPC 客户端 Stub
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getGrpcClient(String terminalId, Class<T> serviceClass) {
|
||||
ManagedChannel channel = grpcChannelCache.get(terminalId, this::createChannel);
|
||||
public <T> T getGrpcClient(String robotId, Class<T> serviceClass) {
|
||||
ManagedChannel channel = grpcChannelCache.get(robotId, this::createChannel);
|
||||
GrpcClientFactory<T> factory = (GrpcClientFactory<T>) clientFactories.get(serviceClass);
|
||||
|
||||
if (factory == null) {
|
||||
@ -87,8 +86,8 @@ public class GrpcServiceManager {
|
||||
/**
|
||||
* 创建gRPC通道
|
||||
*/
|
||||
private ManagedChannel createChannel(String terminalId) {
|
||||
InetSocketAddress endpoint = getGrpcServiceEndpoint(terminalId);
|
||||
private ManagedChannel createChannel(String robotId) {
|
||||
InetSocketAddress endpoint = getGrpcServiceEndpoint(robotId);
|
||||
return ManagedChannelBuilder.forAddress(endpoint.getHostString(), endpoint.getPort())
|
||||
.usePlaintext()
|
||||
.maxInboundMessageSize(50 * 1024 * 1024) // 50MB
|
||||
@ -98,12 +97,9 @@ public class GrpcServiceManager {
|
||||
/**
|
||||
* 获取终端地址
|
||||
*/
|
||||
private InetSocketAddress getGrpcServiceEndpoint(String terminalId) {
|
||||
DeDeviceTerminalConfig terminal = deviceTerminalConfigService.selectDeDeviceTerminalConfigById(terminalId);
|
||||
if (ObjUtil.isEmpty(terminal)) {
|
||||
return parseGrpcAddress(DEFAULT_GRPC_ADDRESS);
|
||||
}
|
||||
return createEndpoint(terminal.getHost(), terminal.getPort(), "终端 " + terminalId);
|
||||
private InetSocketAddress getGrpcServiceEndpoint(String robotId) {
|
||||
RobotEndpoint endpoint = robotEndpointResolver.resolve(robotId);
|
||||
return createEndpoint(endpoint.host(), (long) endpoint.port(), "机器人 " + robotId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,8 +168,8 @@ public class GrpcServiceManager {
|
||||
}
|
||||
|
||||
/** QUIC发现终端地址变化后,使指定终端的旧gRPC通道立即失效。 */
|
||||
public void invalidateTerminal(String terminalId) {
|
||||
grpcChannelCache.invalidate(terminalId);
|
||||
public void invalidateRobot(String robotId) {
|
||||
grpcChannelCache.invalidate(robotId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -10,9 +10,9 @@ import jakarta.validation.constraints.NotEmpty;
|
||||
@ApiModel("边缘系统通用VO")
|
||||
public class EdgeCommonVO {
|
||||
|
||||
@ApiModelProperty("终端ID")
|
||||
@NotEmpty(message = "终端ID不能为空")
|
||||
private String terminalId;
|
||||
@ApiModelProperty("机器人ID")
|
||||
@NotEmpty(message = "机器人ID不能为空")
|
||||
private String robotId;
|
||||
|
||||
@ApiModelProperty("设备ID")
|
||||
@NotEmpty(message = "设备ID不能为空")
|
||||
|
||||
@ -6,11 +6,10 @@ import java.util.List;
|
||||
|
||||
@Data
|
||||
public class EdgeArmTeleopOpenVO {
|
||||
private String terminalId;
|
||||
private String robotId;
|
||||
private Integer protocolMajor;
|
||||
private Integer protocolMinor;
|
||||
private String clientInstanceId;
|
||||
private String robotId;
|
||||
private String modelSha256;
|
||||
private String calibrationSha256;
|
||||
private List<String> jointNames;
|
||||
|
||||
@ -1,224 +0,0 @@
|
||||
package com.cmvr.edge.client.quic;
|
||||
|
||||
import com.cmvr.device.domain.DeDeviceTerminalConfig;
|
||||
import com.cmvr.device.service.IDeDeviceTerminalConfigService;
|
||||
import com.cmvr.edge.client.manage.GrpcServiceManager;
|
||||
import com.cmvr.quic.contract.QuicEventBus;
|
||||
import com.cmvr.quic.gateway.v1.NodeEvent;
|
||||
import com.cmvr.quic.gateway.v1.NodeEventType;
|
||||
import com.cmvr.quic.gateway.v1.NodeSnapshot;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** 直接订阅进程内 QUIC 节点事件,并同步已绑定终端的运行状态和 gRPC 地址。 */
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class QuicGatewayNodeSyncService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QuicGatewayNodeSyncService.class);
|
||||
private static final long HEARTBEAT_PERSIST_INTERVAL_MS = 15000L;
|
||||
|
||||
private final IDeDeviceTerminalConfigService terminalConfigService;
|
||||
private final GrpcServiceManager grpcServiceManager;
|
||||
private final QuicEventBus quicEventBus;
|
||||
|
||||
@Value("${cmvr.quic.enabled:false}")
|
||||
private boolean enabled;
|
||||
|
||||
/** observed-source 使用 QUIC 来源 IP;advertised 使用节点主动上报的 gRPC host。 */
|
||||
@Value("${cmvr.quic.grpc-host-source:observed-source}")
|
||||
private String grpcHostSource;
|
||||
|
||||
private final AtomicBoolean stopping = new AtomicBoolean(false);
|
||||
private final AtomicBoolean grpcHostSourceWarningLogged = new AtomicBoolean(false);
|
||||
private final Set<String> unknownNodes = ConcurrentHashMap.newKeySet();
|
||||
private final Set<String> grpcAddressMismatchNodes = ConcurrentHashMap.newKeySet();
|
||||
private final ConcurrentHashMap<String, Long> lastPersistedAt = new ConcurrentHashMap<String, Long>();
|
||||
private final ConcurrentHashMap<String, String> synchronizedTerminals =
|
||||
new ConcurrentHashMap<String, String>();
|
||||
private ExecutorService eventExecutor;
|
||||
private QuicEventBus.Subscription subscription;
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
if (!enabled) {
|
||||
log.info("QUIC 节点状态同步未启用");
|
||||
return;
|
||||
}
|
||||
eventExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable runnable) {
|
||||
Thread thread = new Thread(runnable, "quic-node-sync");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
subscription = quicEventBus.watchNodes(true, this::enqueueEvent);
|
||||
log.info("已通过进程内事件总线订阅 QUIC 节点事件");
|
||||
}
|
||||
|
||||
private void enqueueEvent(final NodeEvent event) {
|
||||
ExecutorService executor = eventExecutor;
|
||||
if (stopping.get() || executor == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleEventSafely(event);
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException ignored) {
|
||||
if (!stopping.get()) {
|
||||
log.warn("QUIC 节点事件线程已停止,忽略事件,nodeId={}", event.getNode().getNodeId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEventSafely(NodeEvent event) {
|
||||
try {
|
||||
syncNode(event);
|
||||
} catch (RuntimeException error) {
|
||||
log.error("同步 QUIC 终端状态失败,nodeId={},eventType={}",
|
||||
event.getNode().getNodeId(), event.getType(), error);
|
||||
}
|
||||
}
|
||||
|
||||
private void syncNode(NodeEvent event) {
|
||||
NodeSnapshot node = event.getNode();
|
||||
if (node.getNodeId().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
DeDeviceTerminalConfig terminal = terminalConfigService.selectByQuicNodeId(node.getNodeId());
|
||||
if (terminal == null) {
|
||||
if (unknownNodes.add(node.getNodeId())) {
|
||||
log.warn("QUIC 节点尚未绑定平台终端,忽略运行状态同步,nodeId={},remoteIp={}",
|
||||
node.getNodeId(), node.getObservedSourceIp());
|
||||
}
|
||||
return;
|
||||
}
|
||||
unknownNodes.remove(node.getNodeId());
|
||||
|
||||
boolean offline = event.getType() == NodeEventType.NODE_EVENT_TYPE_OFFLINE || !node.getOnline();
|
||||
if (offline) {
|
||||
synchronizedTerminals.remove(node.getNodeId());
|
||||
} else {
|
||||
synchronizedTerminals.put(node.getNodeId(), terminal.getId());
|
||||
}
|
||||
String grpcHost = offline ? null : resolveGrpcHost(node);
|
||||
Long grpcPort = offline || node.getGrpcEndpoint().getPort() == 0
|
||||
? null : Long.valueOf(node.getGrpcEndpoint().getPort());
|
||||
boolean endpointChanged = !offline && grpcHost != null && grpcPort != null
|
||||
&& (!grpcHost.equals(terminal.getHost()) || !grpcPort.equals(terminal.getPort()));
|
||||
long now = System.currentTimeMillis();
|
||||
Long previousPersisted = lastPersistedAt.get(node.getNodeId());
|
||||
boolean immediate = event.getType() == NodeEventType.NODE_EVENT_TYPE_REGISTERED
|
||||
|| event.getType() == NodeEventType.NODE_EVENT_TYPE_OFFLINE || endpointChanged;
|
||||
if (!immediate && previousPersisted != null
|
||||
&& now - previousPersisted.longValue() < HEARTBEAT_PERSIST_INTERVAL_MS) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalConfigService.updateQuicRuntimeState(terminal.getId(), grpcHost, grpcPort,
|
||||
node.getObservedSourceIp(), node.getSessionId(), node.getBootId(),
|
||||
node.getSoftwareVersion(), offline ? "0" : "1",
|
||||
new Date(event.getEventTimeUnixMs() == 0 ? now : event.getEventTimeUnixMs()));
|
||||
lastPersistedAt.put(node.getNodeId(), now);
|
||||
if (offline) {
|
||||
lastPersistedAt.remove(node.getNodeId());
|
||||
}
|
||||
if (endpointChanged || offline) {
|
||||
grpcServiceManager.invalidateTerminal(terminal.getId());
|
||||
}
|
||||
log.info("QUIC 终端状态已同步,terminalId={},nodeId={},online={},grpc={}:{}",
|
||||
terminal.getId(), node.getNodeId(), !offline,
|
||||
grpcHost == null ? terminal.getHost() : grpcHost,
|
||||
grpcPort == null ? terminal.getPort() : grpcPort);
|
||||
}
|
||||
|
||||
private String resolveGrpcHost(NodeSnapshot node) {
|
||||
String advertisedHost = emptyToNull(node.getGrpcEndpoint().getHost());
|
||||
if ("advertised".equalsIgnoreCase(grpcHostSource)) {
|
||||
return advertisedHost;
|
||||
}
|
||||
if (!"observed-source".equalsIgnoreCase(grpcHostSource)
|
||||
&& grpcHostSourceWarningLogged.compareAndSet(false, true)) {
|
||||
log.warn("未知的 QUIC gRPC 地址来源配置,按 observed-source 处理,value={}", grpcHostSource);
|
||||
}
|
||||
String observedHost = emptyToNull(node.getObservedSourceIp());
|
||||
if (observedHost == null) {
|
||||
log.warn("QUIC 节点缺少来源 IP,回退到节点上报地址,nodeId={},advertisedHost={}",
|
||||
node.getNodeId(), advertisedHost);
|
||||
return advertisedHost;
|
||||
}
|
||||
if (advertisedHost != null && !observedHost.equals(advertisedHost)
|
||||
&& grpcAddressMismatchNodes.add(node.getNodeId())) {
|
||||
log.info("QUIC 节点上报的 gRPC 地址与来源 IP 不同,使用来源 IP,nodeId={},"
|
||||
+ "observedHost={},advertisedHost={}",
|
||||
node.getNodeId(), observedHost, advertisedHost);
|
||||
} else if (observedHost.equals(advertisedHost)) {
|
||||
grpcAddressMismatchNodes.remove(node.getNodeId());
|
||||
}
|
||||
return observedHost;
|
||||
}
|
||||
|
||||
private void markSynchronizedTerminalsOffline() {
|
||||
for (Map.Entry<String, String> entry : synchronizedTerminals.entrySet()) {
|
||||
try {
|
||||
terminalConfigService.updateQuicRuntimeState(entry.getValue(), null, null,
|
||||
null, null, null, null, "0", new Date());
|
||||
grpcServiceManager.invalidateTerminal(entry.getValue());
|
||||
} catch (RuntimeException error) {
|
||||
log.error("标记 QUIC 终端离线失败,nodeId={},terminalId={}",
|
||||
entry.getKey(), entry.getValue(), error);
|
||||
}
|
||||
}
|
||||
synchronizedTerminals.clear();
|
||||
lastPersistedAt.clear();
|
||||
}
|
||||
|
||||
private static String emptyToNull(String value) {
|
||||
return value == null || value.trim().isEmpty() ? null : value.trim();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stop() {
|
||||
if (!stopping.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
QuicEventBus.Subscription currentSubscription = subscription;
|
||||
if (currentSubscription != null) {
|
||||
currentSubscription.close();
|
||||
}
|
||||
ExecutorService executor = eventExecutor;
|
||||
if (executor != null) {
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException interrupted) {
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
markSynchronizedTerminalsOffline();
|
||||
}
|
||||
}
|
||||
@ -176,7 +176,7 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
}
|
||||
|
||||
private void handleJoin(WebSocketSession webSocketSession, JsonNode jsonNode) {
|
||||
String terminalId = getText(jsonNode, "terminalId");
|
||||
String robotId = getText(jsonNode, "robotId");
|
||||
String deviceId = getText(jsonNode, "deviceId");
|
||||
String speakerDeviceId = getText(jsonNode, "speakerDeviceId");
|
||||
String micDeviceId = getText(jsonNode, "micDeviceId");
|
||||
@ -190,8 +190,8 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
micDeviceId = deviceId;
|
||||
}
|
||||
|
||||
if (terminalId == null || speakerDeviceId == null || micDeviceId == null) {
|
||||
sendError(webSocketSession, sessionId, "terminalId、speakerDeviceId、micDeviceId不能为空");
|
||||
if (robotId == null || speakerDeviceId == null || micDeviceId == null) {
|
||||
sendError(webSocketSession, sessionId, "robotId、speakerDeviceId、micDeviceId不能为空");
|
||||
return;
|
||||
}
|
||||
if (deviceId == null) {
|
||||
@ -213,7 +213,7 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
|
||||
AudioSession session = new AudioSession();
|
||||
session.sessionId = sessionId;
|
||||
session.terminalId = terminalId;
|
||||
session.robotId = robotId;
|
||||
session.deviceId = deviceId;
|
||||
session.speakerDeviceId = speakerDeviceId;
|
||||
session.micDeviceId = micDeviceId;
|
||||
@ -228,7 +228,7 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
sessionMap.put(sessionId, session);
|
||||
webSocketSessionMap.put(webSocketSession.getId(), sessionId);
|
||||
try {
|
||||
session.robotStream = robotAudioGrpcAdapter.openStream(terminalId, speakerDeviceId, micDeviceId, sessionId, operatorId, this);
|
||||
session.robotStream = robotAudioGrpcAdapter.openStream(robotId, speakerDeviceId, micDeviceId, sessionId, operatorId, this);
|
||||
} catch (Exception e) {
|
||||
sessionMap.remove(sessionId);
|
||||
webSocketSessionMap.remove(webSocketSession.getId());
|
||||
@ -236,7 +236,7 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
throw e;
|
||||
}
|
||||
sendState(session, "joined");
|
||||
log.info("实时语音会话创建成功,sessionId={},terminalId={},speakerDeviceId={},micDeviceId={}", sessionId, terminalId, speakerDeviceId, micDeviceId);
|
||||
log.info("实时语音会话创建成功,sessionId={},robotId={},speakerDeviceId={},micDeviceId={}", sessionId, robotId, speakerDeviceId, micDeviceId);
|
||||
} catch (Exception e) {
|
||||
log.error("创建实时语音会话失败,sessionId={}", sessionId, e);
|
||||
sendError(webSocketSession, sessionId, "创建实时语音会话失败:" + e.getMessage());
|
||||
@ -347,8 +347,8 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
continue;
|
||||
}
|
||||
if (now - session.lastRobotHeartbeatAt > ROBOT_HEARTBEAT_TIMEOUT_MS) {
|
||||
log.warn("机器人心跳超时,sessionId={},terminalId={},speakerDeviceId={},micDeviceId={}",
|
||||
session.sessionId, session.terminalId, session.speakerDeviceId, session.micDeviceId);
|
||||
log.warn("机器人心跳超时,sessionId={},robotId={},speakerDeviceId={},micDeviceId={}",
|
||||
session.sessionId, session.robotId, session.speakerDeviceId, session.micDeviceId);
|
||||
// 先从业务会话表摘除,避免 cancel/close 触发的异步回调再次进入同一个会话并重复关闭 native 对象。
|
||||
iterator.remove();
|
||||
session.state = AudioSessionState.ROBOT_OFFLINE;
|
||||
@ -466,7 +466,7 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
|
||||
private void sendState(AudioSession session, String type) {
|
||||
ObjectNode event = baseMessage(type, session.sessionId);
|
||||
event.put("terminalId", session.terminalId);
|
||||
event.put("robotId", session.robotId);
|
||||
event.put("deviceId", session.deviceId);
|
||||
event.put("speakerDeviceId", session.speakerDeviceId);
|
||||
event.put("micDeviceId", session.micDeviceId);
|
||||
@ -705,7 +705,7 @@ public class AudioService implements RobotAudioStreamListener {
|
||||
*/
|
||||
private static class AudioSession {
|
||||
private String sessionId;
|
||||
private String terminalId;
|
||||
private String robotId;
|
||||
private String deviceId;
|
||||
private String speakerDeviceId;
|
||||
private String micDeviceId;
|
||||
|
||||
@ -33,7 +33,7 @@ public interface EdgeArmService {
|
||||
/**
|
||||
* 清除机械臂故障状态。
|
||||
*
|
||||
* @param edgeCommonVO 边缘设备通用参数,包含 terminalId 和 deviceId
|
||||
* @param edgeCommonVO 边缘设备通用参数,包含 robotId 和 deviceId
|
||||
* @return 机器人终端返回的通用反馈
|
||||
*/
|
||||
Common.CommandHeader.Feedback clearFault(EdgeCommonVO edgeCommonVO);
|
||||
|
||||
@ -37,6 +37,6 @@ public interface EdgeBioHeadService {
|
||||
/**
|
||||
* 表情
|
||||
*/
|
||||
public String specialExpression(String terminalId,String deviceId,Integer expressKey);
|
||||
public String specialExpression(String robotId,String deviceId,Integer expressKey);
|
||||
|
||||
}
|
||||
|
||||
@ -58,9 +58,9 @@ public interface EdgeCameraService {
|
||||
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> getRGBImageStream(EdgeCommonVO edgeCommonVO);
|
||||
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> getRGBImageStream(String terminalId, String deviceId);
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> getRGBImageStream(String robotId, String deviceId);
|
||||
|
||||
void writeRGBVideoStream(String terminalId, String deviceId, OutputStream outputStream);
|
||||
void writeRGBVideoStream(String robotId, String deviceId, OutputStream outputStream);
|
||||
|
||||
void getDepthImageStream(EdgeCommonVO edgeCommonVO);
|
||||
void getRGBDImagesStream(EdgeCommonVO edgeCommonVO);
|
||||
|
||||
@ -8,12 +8,12 @@ import io.grpc.stub.StreamObserver;
|
||||
*/
|
||||
public interface EdgeDexHandService {
|
||||
// 基本控制
|
||||
DexhandCommand.DexHandState getStatus(String terminalId, String deviceId);
|
||||
void setDexHandPos(String terminalId, String deviceId);
|
||||
void setDexHandAngle(String terminalId, String deviceId, int id, float value) ;
|
||||
void setDexHandForce(String terminalId, String deviceId) ;
|
||||
void setDexHandSpeed(String terminalId, String deviceId) ;
|
||||
void setDexHandPresetAct(String terminalId, String deviceId);
|
||||
String getSensorData(String terminalId, String deviceId) ;
|
||||
StreamObserver<DexhandCommand.GetSensorDataStreamCommand.Request> getSensorDataStream(String terminalId, String deviceId) ;
|
||||
DexhandCommand.DexHandState getStatus(String robotId, String deviceId);
|
||||
void setDexHandPos(String robotId, String deviceId);
|
||||
void setDexHandAngle(String robotId, String deviceId, int id, float value) ;
|
||||
void setDexHandForce(String robotId, String deviceId) ;
|
||||
void setDexHandSpeed(String robotId, String deviceId) ;
|
||||
void setDexHandPresetAct(String robotId, String deviceId);
|
||||
String getSensorData(String robotId, String deviceId) ;
|
||||
StreamObserver<DexhandCommand.GetSensorDataStreamCommand.Request> getSensorDataStream(String robotId, String deviceId) ;
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ public interface EdgeHlcService {
|
||||
/**
|
||||
* 触控
|
||||
*/
|
||||
public String touch(File image, String terminalId, String deviceId, int x, int y, double maxForce);
|
||||
public String touch(File image, String robotId, String deviceId, int x, int y, double maxForce);
|
||||
|
||||
/**
|
||||
* 图片标注
|
||||
|
||||
@ -14,75 +14,75 @@ public interface EdgeSpeakerService {
|
||||
* 获取扬声器当前状态
|
||||
* 通过gRPC调用获取扬声器的运行状态,包括是否正在播放、音量等信息
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @return SpeakerState 返回扬声器的当前状态
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
SpeakerCommand.GetSpeakerStateCommand.Feedback getStatus(String terminalId, String deviceId);
|
||||
SpeakerCommand.GetSpeakerStateCommand.Feedback getStatus(String robotId, String deviceId);
|
||||
|
||||
/**
|
||||
* 播放音频文件
|
||||
* 通过gRPC调用播放指定路径的音频文件
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @param audioPath 音频文件的路径
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
String playAudio(String terminalId, String deviceId, String audioPath);
|
||||
String playAudio(String robotId, String deviceId, String audioPath);
|
||||
|
||||
/**
|
||||
* 停止当前播放
|
||||
* 通过gRPC调用停止扬声器的当前播放
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
void stopPlayback(String terminalId, String deviceId);
|
||||
void stopPlayback(String robotId, String deviceId);
|
||||
|
||||
/**
|
||||
* 暂停当前播放
|
||||
* 通过gRPC调用暂停扬声器的当前播放
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
void pausePlayback(String terminalId, String deviceId);
|
||||
void pausePlayback(String robotId, String deviceId);
|
||||
|
||||
/**
|
||||
* 恢复暂停的播放
|
||||
* 通过gRPC调用恢复扬声器之前暂停的播放
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
void resumePlayback(String terminalId, String deviceId);
|
||||
void resumePlayback(String robotId, String deviceId);
|
||||
|
||||
/**
|
||||
* 设置扬声器音量
|
||||
* 通过gRPC调用设置扬声器的音量大小
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @param volume 音量大小(0-100)
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
void setVolume(String terminalId, String deviceId, int volume);
|
||||
void setVolume(String robotId, String deviceId, int volume);
|
||||
|
||||
/**
|
||||
* 获取当前音量
|
||||
* 通过gRPC调用获取扬声器的当前音量大小
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @return int 返回当前音量大小(0-100)
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
int getVolume(String terminalId, String deviceId);
|
||||
int getVolume(String robotId, String deviceId);
|
||||
|
||||
/**
|
||||
* 获取所有音频文件
|
||||
|
||||
@ -12,20 +12,20 @@ import java.util.List;
|
||||
* 边缘系统服务接口
|
||||
*/
|
||||
public interface EdgeSystemService {
|
||||
SystemCommand.GetSystemInfoCommand.Feedback getSystemInfo(String terminalId);
|
||||
SystemCommand.GetSystemInfoCommand.Feedback getSystemInfo(String robotId);
|
||||
|
||||
/**
|
||||
* 获取系统状态
|
||||
* @return 系统状态信息,包含CPU使用率、内存使用情况、磁盘使用情况和设备列表
|
||||
*/
|
||||
SystemCommand.GetSystemStatusCommand.Feedback getSystemStatus(String terminalId);
|
||||
SystemCommand.GetSystemStatusCommand.Feedback getSystemStatus(String robotId);
|
||||
|
||||
Common.CommandHeader.Feedback updateParams(EdgeSystemUpdateParamsVO request);
|
||||
|
||||
Common.JsonDeviceCommand.Feedback executeJsonCommand(EdgeSystemJsonCommandVO request);
|
||||
|
||||
|
||||
public List<DeDeviceRegistration> deviceList(String terminalId);
|
||||
public List<DeDeviceRegistration> deviceList(String robotId);
|
||||
|
||||
public String stopAll(String terminalId);
|
||||
public String stopAll(String robotId);
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public AgvUtils.AgvRuntimeState getRuntimeState(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvRuntimeStateCommand.Request request = AgvCommand.AgvRuntimeStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -42,7 +42,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public AgvUtils.AgvNavigationStatus getNavigationStatus(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvNavigationStatusCommand.Request request = AgvCommand.AgvNavigationStatusCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -52,7 +52,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void emergencyStop(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.emergencyStop(request));
|
||||
}
|
||||
@ -60,7 +60,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void clearFault(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.clearFault(request));
|
||||
}
|
||||
@ -72,7 +72,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvNavigateToPoseCommand.Request request = AgvCommand.AgvNavigateToPoseCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setPose(pose)
|
||||
@ -87,7 +87,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvNavigateToStationCommand.Request request = AgvCommand.AgvNavigateToStationCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setStationId(stationId)
|
||||
@ -102,7 +102,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvFollowPathCommand.Request request = AgvCommand.AgvFollowPathCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.addAllPath(pathSegments)
|
||||
@ -113,7 +113,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void pauseNavigation(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.pauseNavigation(request));
|
||||
}
|
||||
@ -121,7 +121,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void resumeNavigation(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.resumeNavigation(request));
|
||||
}
|
||||
@ -129,7 +129,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void cancelNavigation(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.cancelNavigation(request));
|
||||
}
|
||||
@ -141,7 +141,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvSetVelocityCommand.Request request = AgvCommand.AgvSetVelocityCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setVelocity(velocity)
|
||||
@ -152,7 +152,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void stopVelocityControl(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.stopVelocityControl(request));
|
||||
}
|
||||
@ -160,7 +160,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public List<String> listMaps(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvListMapsCommand.Request request = AgvCommand.AgvListMapsCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -170,7 +170,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public List<AgvUtils.AgvStation> listStations(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvListStationsCommand.Request request = AgvCommand.AgvListStationsCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -184,7 +184,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvMapCommand.Request request = AgvCommand.AgvMapCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setMapName(mapName)
|
||||
@ -202,7 +202,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvMapCommand.Request request = AgvCommand.AgvMapCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setMapName(mapName)
|
||||
@ -218,7 +218,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
}
|
||||
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvMapCommand.Request request = AgvCommand.AgvMapCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setMapName(mapName)
|
||||
@ -229,7 +229,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public String startMapping(EdgeCommonVO edgeCommonVO, AgvUtils.AgvMapDimension dimension, String mapName, boolean realTime) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
AgvCommand.AgvStartMappingCommand.Request.Builder requestBuilder = AgvCommand.AgvStartMappingCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.setDimension(dimension != null ? dimension : AgvUtils.AgvMapDimension.AGV_MAP_DIMENSION_UNSPECIFIED)
|
||||
@ -246,7 +246,7 @@ public class EdgeAgvServiceImpl implements EdgeAgvService {
|
||||
@Override
|
||||
public void stopMapping(EdgeCommonVO edgeCommonVO) {
|
||||
AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
executeGrpcCall(() -> stub.stopMapping(request));
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public Common.CommandHeader.Feedback torqueOff(EdgeCommonVO edgeCommonVO) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
return executeGrpcCall(() -> stub.torqueOff(request));
|
||||
}
|
||||
@ -39,7 +39,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public Common.CommandHeader.Feedback torqueOn(EdgeCommonVO edgeCommonVO) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
return executeGrpcCall(() -> stub.torqueOn(request));
|
||||
}
|
||||
@ -47,7 +47,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public Common.CommandHeader.Feedback clearFault(EdgeCommonVO edgeCommonVO) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
return executeGrpcCall(() -> stub.clearFault(request));
|
||||
}
|
||||
@ -61,7 +61,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
}
|
||||
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
// 构建关节位置命令
|
||||
ArmCommand.JointPositionCommand targetCommand = ArmCommand.JointPositionCommand.newBuilder()
|
||||
@ -104,7 +104,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
double rx, double ry, double rz, String frame,
|
||||
Double velocity, Double acceleration, Double blendRadius) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
// 构建笛卡尔位姿
|
||||
ArmCommand.CartesianPose targetPose = ArmCommand.CartesianPose.newBuilder()
|
||||
@ -149,7 +149,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
}
|
||||
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
// 构建关节速度命令
|
||||
ArmCommand.JointVelocityCommand velocityCommand = ArmCommand.JointVelocityCommand.newBuilder()
|
||||
@ -177,7 +177,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
double wx, double wy, double wz, String frame,
|
||||
Double acceleration, Double duration) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
// 构建笛卡尔速度
|
||||
ArmCommand.CartesianVelocity velocity = ArmCommand.CartesianVelocity.newBuilder()
|
||||
@ -214,7 +214,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
}
|
||||
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
// 构建关节位置命令
|
||||
ArmCommand.JointPositionCommand targetCommand = ArmCommand.JointPositionCommand.newBuilder()
|
||||
@ -234,7 +234,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public Common.CommandHeader.Feedback stopMotion(EdgeCommonVO edgeCommonVO) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||
return executeGrpcCall(() -> stub.stopMotion(request));
|
||||
}
|
||||
@ -242,7 +242,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public ArmCommand.JointResponse getJointState(EdgeCommonVO edgeCommonVO) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
ArmCommand.JointRequest request = ArmCommand.JointRequest.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -252,7 +252,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public ArmCommand.GetPose.Response getPose(EdgeCommonVO edgeCommonVO, String baseLink, String eeLink) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
ArmCommand.GetPose.Request.Builder requestBuilder = ArmCommand.GetPose.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()));
|
||||
@ -270,7 +270,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public ArmCommand.CalibrateZeroQ.Response calibrateZeroQ(EdgeCommonVO edgeCommonVO, String jointName) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
ArmCommand.CalibrateZeroQ.Request.Builder requestBuilder = ArmCommand.CalibrateZeroQ.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()));
|
||||
@ -285,7 +285,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
@Override
|
||||
public ArmCommand.GetPoseMatrix.Response getPoseMatrix(EdgeCommonVO edgeCommonVO, String baseLink, String eeLink) {
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
ArmCommand.GetPoseMatrix.Request.Builder requestBuilder = ArmCommand.GetPoseMatrix.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()));
|
||||
@ -310,7 +310,7 @@ public class EdgeArmServiceImpl implements EdgeArmService {
|
||||
}
|
||||
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
|
||||
// 构建关节位置命令
|
||||
ArmCommand.JointPositionCommand jointsCommand = ArmCommand.JointPositionCommand.newBuilder()
|
||||
|
||||
@ -23,8 +23,8 @@ public class EdgeArmTeleopServiceImpl implements EdgeArmTeleopService {
|
||||
|
||||
@Override
|
||||
public String open(EdgeArmTeleopOpenVO request) {
|
||||
if (request.getTerminalId() == null || request.getTerminalId().trim().isEmpty()) {
|
||||
throw new GlobalException("terminalId cannot be empty");
|
||||
if (request.getRobotId() == null || request.getRobotId().trim().isEmpty()) {
|
||||
throw new GlobalException("robotId cannot be empty");
|
||||
}
|
||||
ArmTeleopV1.RobotManifest.Builder manifest = ArmTeleopV1.RobotManifest.newBuilder();
|
||||
if (request.getRobotId() != null) manifest.setRobotId(request.getRobotId());
|
||||
@ -49,7 +49,7 @@ public class EdgeArmTeleopServiceImpl implements EdgeArmTeleopService {
|
||||
if (request.getLeaseMs() != null) open.setRequestedLeaseMs(request.getLeaseMs());
|
||||
|
||||
ArmTeleopServiceGrpc.ArmTeleopServiceStub stub = grpcServiceManager.getGrpcClient(
|
||||
request.getTerminalId(), ArmTeleopServiceGrpc.ArmTeleopServiceStub.class);
|
||||
request.getRobotId(), ArmTeleopServiceGrpc.ArmTeleopServiceStub.class);
|
||||
return sessions.open(stub::teleoperate, ArmTeleopV1.ClientFrame.newBuilder().setOpen(open).build());
|
||||
}
|
||||
|
||||
|
||||
@ -23,9 +23,9 @@ public class EdgeBioHeadServiceImpl implements EdgeBioHeadService {
|
||||
|
||||
@Override
|
||||
public String setExpression(EdgeFacialExpressionVO facialExpressionVo) {
|
||||
String terminalId = facialExpressionVo.getTerminalId();
|
||||
String robotId = facialExpressionVo.getRobotId();
|
||||
String deviceId = facialExpressionVo.getDeviceId();
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
|
||||
// 请求头
|
||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(deviceId);
|
||||
@ -110,9 +110,9 @@ public class EdgeBioHeadServiceImpl implements EdgeBioHeadService {
|
||||
|
||||
@Override
|
||||
public String getSystemStatus(EdgeCommonVO edgeCommonVO) {
|
||||
String terminalId = edgeCommonVO.getTerminalId();
|
||||
String robotId = edgeCommonVO.getRobotId();
|
||||
String deviceId = edgeCommonVO.getDeviceId();
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
|
||||
// 请求头
|
||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(deviceId);
|
||||
@ -126,9 +126,9 @@ public class EdgeBioHeadServiceImpl implements EdgeBioHeadService {
|
||||
|
||||
@Override
|
||||
public String emergencyStop(EdgeCommonVO edgeCommonVO) {
|
||||
String terminalId = edgeCommonVO.getTerminalId();
|
||||
String robotId = edgeCommonVO.getRobotId();
|
||||
String deviceId = edgeCommonVO.getDeviceId();
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
|
||||
// 请求头
|
||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(deviceId);
|
||||
@ -142,9 +142,9 @@ public class EdgeBioHeadServiceImpl implements EdgeBioHeadService {
|
||||
|
||||
@Override
|
||||
public String speakStart(EdgeCommonVO edgeCommonVO) {
|
||||
String terminalId = edgeCommonVO.getTerminalId();
|
||||
String robotId = edgeCommonVO.getRobotId();
|
||||
String deviceId = edgeCommonVO.getDeviceId();
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
|
||||
// 请求头
|
||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(deviceId);
|
||||
@ -155,9 +155,9 @@ public class EdgeBioHeadServiceImpl implements EdgeBioHeadService {
|
||||
|
||||
@Override
|
||||
public String speakStop(EdgeCommonVO edgeCommonVO) {
|
||||
String terminalId = edgeCommonVO.getTerminalId();
|
||||
String robotId = edgeCommonVO.getRobotId();
|
||||
String deviceId = edgeCommonVO.getDeviceId();
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
|
||||
// 请求头
|
||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(deviceId);
|
||||
@ -167,8 +167,8 @@ public class EdgeBioHeadServiceImpl implements EdgeBioHeadService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String specialExpression(String terminalId, String deviceId, Integer expressKey) {
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
public String specialExpression(String robotId, String deviceId, Integer expressKey) {
|
||||
BioHeadServiceGrpc.BioHeadServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, BioHeadServiceGrpc.BioHeadServiceBlockingStub.class);
|
||||
|
||||
// 请求头
|
||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(deviceId);
|
||||
|
||||
@ -71,7 +71,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
|
||||
@Override
|
||||
public CameraCommand.CameraState status(EdgeCommonVO edgeCommonVO) {
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.GetCameraStateCommand.Request request = CameraCommand.GetCameraStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -89,7 +89,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
|
||||
@Override
|
||||
public String start(EdgeCommonVO edgeCommonVO) {
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.StartCameraCommand.Request request = CameraCommand.StartCameraCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -99,7 +99,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
|
||||
@Override
|
||||
public String stop(EdgeCommonVO edgeCommonVO) {
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.StopCameraCommand.Request request = CameraCommand.StopCameraCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -113,7 +113,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
if (!checkStatus(edgeCommonVO)) {
|
||||
start(edgeCommonVO);
|
||||
}
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.GetRGBImageCommand.Request request = CameraCommand.GetRGBImageCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -131,7 +131,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
} finally {
|
||||
deleteTempFile(filePath);
|
||||
// todo 暂时不关闭摄像头
|
||||
// stop(terminalId, deviceId);
|
||||
// stop(robotId, deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
start(edgeCommonVO);
|
||||
}
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.GetDepthImageCommand.Request request = CameraCommand.GetDepthImageCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -165,7 +165,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
if (!checkStatus(edgeCommonVO)) {
|
||||
start(edgeCommonVO);
|
||||
}
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
String videoPath = StrUtil.format("{}/{}_{}.mp4", "/home/share/assets/video", edgeCommonVO.getDeviceId(), System.currentTimeMillis());
|
||||
|
||||
CameraCommand.StartCameraRecordingCommand.Request request = CameraCommand.StartCameraRecordingCommand.Request.newBuilder()
|
||||
@ -178,7 +178,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
|
||||
@Override
|
||||
public String stopRecording(EdgeCommonVO edgeCommonVO) {
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.StopCameraRecordingCommand.Request request = CameraCommand.StopCameraRecordingCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -192,7 +192,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
start(edgeCommonVO);
|
||||
}
|
||||
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.GetRGBDImagesCommand.Request request = CameraCommand.GetRGBDImagesCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -221,7 +221,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
// deleteTempFile(filePath);
|
||||
// deleteTempFile(deepFilePath);
|
||||
// todo 暂时不关闭摄像头
|
||||
// stop(terminalId, deviceId);
|
||||
// stop(robotId, deviceId);
|
||||
}
|
||||
// return JSON.toJSONString(result);
|
||||
}
|
||||
@ -237,7 +237,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
throw new GlobalException("Invalid PTZ command or action");
|
||||
}
|
||||
CameraServiceGrpc.CameraServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
ptzVO.getTerminalId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
ptzVO.getRobotId(), CameraServiceGrpc.CameraServiceBlockingStub.class);
|
||||
CameraCommand.ControlPtzCommand.Request request = CameraCommand.ControlPtzCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(ptzVO.getDeviceId()))
|
||||
.setCommand(command)
|
||||
@ -249,13 +249,13 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
|
||||
@Override
|
||||
public StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> getRGBImageStream(EdgeCommonVO edgeCommonVO) {
|
||||
return getRGBImageStream(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
return getRGBImageStream(edgeCommonVO.getRobotId(), edgeCommonVO.getDeviceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> getRGBImageStream(String terminalId, String deviceId) {
|
||||
public StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> getRGBImageStream(String robotId, String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
CameraCommand.CameraState cameraState = status(edgeCommonVO);
|
||||
if (cameraState.getIsError()) {
|
||||
@ -266,8 +266,8 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
cameraState = status(edgeCommonVO);
|
||||
}
|
||||
int frameRate = cameraState.getFps();
|
||||
String channel = "edgeCameraServiceImpl/getRGBImageStream/" + terminalId + "/" + deviceId;
|
||||
String streamKey = terminalId + deviceId + "edgeCameraServiceImpl" + "getRGBImageStream";
|
||||
String channel = "edgeCameraServiceImpl/getRGBImageStream/" + robotId + "/" + deviceId;
|
||||
String streamKey = robotId + deviceId + "edgeCameraServiceImpl" + "getRGBImageStream";
|
||||
AtomicInteger sequence = new AtomicInteger();
|
||||
AtomicBoolean firstMediaChunk = new AtomicBoolean(true);
|
||||
AtomicReference<StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request>> requestObserverRef = new AtomicReference<>();
|
||||
@ -275,18 +275,18 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
H265Fmp4Transcoder transcoder;
|
||||
try {
|
||||
transcoder = new H265Fmp4Transcoder(
|
||||
terminalId + "-" + deviceId,
|
||||
robotId + "-" + deviceId,
|
||||
frameRate,
|
||||
chunk -> {
|
||||
int currentSequence = sequence.incrementAndGet();
|
||||
if (firstMediaChunk.compareAndSet(true, false)) {
|
||||
log.info("摄像头流已输出首个fMP4片段, terminalId: {}, deviceId: {}, bytes: {}",
|
||||
terminalId, deviceId, chunk.length);
|
||||
log.info("摄像头流已输出首个fMP4片段, robotId: {}, deviceId: {}, bytes: {}",
|
||||
robotId, deviceId, chunk.length);
|
||||
}
|
||||
messagePushService.pushH264Fmp4ToChannel(channel, chunk, currentSequence);
|
||||
},
|
||||
throwable -> {
|
||||
log.error("摄像头媒体转码失败, terminalId: {}, deviceId: {}", terminalId, deviceId, throwable);
|
||||
log.error("摄像头媒体转码失败, robotId: {}, deviceId: {}", robotId, deviceId, throwable);
|
||||
messagePushService.pushToChannel(channel, "500");
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> observer = requestObserverRef.get();
|
||||
if (observer != null) {
|
||||
@ -299,7 +299,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
throw new GlobalException("摄像头媒体转码器初始化失败: " + exception.getMessage());
|
||||
}
|
||||
|
||||
CameraServiceGrpc.CameraServiceStub stub = grpcServiceManager.getGrpcClient(terminalId, CameraServiceGrpc.CameraServiceStub.class);
|
||||
CameraServiceGrpc.CameraServiceStub stub = grpcServiceManager.getGrpcClient(robotId, CameraServiceGrpc.CameraServiceStub.class);
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Feedback> responseObserver = new StreamObserver<CameraCommand.GetRGBImageStreamCommand.Feedback>() {
|
||||
@Override
|
||||
public void onNext(CameraCommand.GetRGBImageStreamCommand.Feedback value) {
|
||||
@ -307,7 +307,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
CameraCommand.FrameData frame = value.getColorFrame();
|
||||
transcoder.write(frame.getData().toByteArray(), frame.getIsKeyFrame(), frame.getCodec());
|
||||
} catch (IOException exception) {
|
||||
log.error("写入摄像头媒体流失败, terminalId: {}, deviceId: {}", terminalId, deviceId, exception);
|
||||
log.error("写入摄像头媒体流失败, robotId: {}, deviceId: {}", robotId, deviceId, exception);
|
||||
transcoder.close();
|
||||
messagePushService.pushToChannel(channel, "500");
|
||||
}
|
||||
@ -319,7 +319,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
GrpcStreamManager.removeStream(streamKey);
|
||||
Status status = Status.fromThrowable(t);
|
||||
if (status.getCode() != Status.Code.CANCELLED) {
|
||||
log.error("摄像头gRPC流异常, terminalId: {}, deviceId: {}", terminalId, deviceId, t);
|
||||
log.error("摄像头gRPC流异常, robotId: {}, deviceId: {}", robotId, deviceId, t);
|
||||
messagePushService.pushToChannel(channel, "500");
|
||||
}
|
||||
}
|
||||
@ -328,7 +328,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
public void onCompleted() {
|
||||
transcoder.close();
|
||||
GrpcStreamManager.removeStream(streamKey);
|
||||
log.info("摄像头gRPC流结束, terminalId: {}, deviceId: {}", terminalId, deviceId);
|
||||
log.info("摄像头gRPC流结束, robotId: {}, deviceId: {}", robotId, deviceId);
|
||||
}
|
||||
};
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Request> grpcRequestObserver;
|
||||
@ -368,9 +368,9 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeRGBVideoStream(String terminalId, String deviceId, OutputStream outputStream) {
|
||||
public void writeRGBVideoStream(String robotId, String deviceId, OutputStream outputStream) {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
CameraCommand.CameraState cameraState = status(edgeCommonVO);
|
||||
if (cameraState.getIsError()) {
|
||||
@ -394,7 +394,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
H265Fmp4Transcoder transcoder;
|
||||
try {
|
||||
transcoder = new H265Fmp4Transcoder(
|
||||
"http-" + terminalId + "-" + deviceId,
|
||||
"http-" + robotId + "-" + deviceId,
|
||||
cameraState.getFps(),
|
||||
chunk -> {
|
||||
try {
|
||||
@ -406,8 +406,8 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
},
|
||||
throwable -> {
|
||||
if (!(throwable instanceof CameraStreamWriteException)) {
|
||||
log.error("HTTP camera media transcoding failed, terminalId: {}, deviceId: {}",
|
||||
terminalId, deviceId, throwable);
|
||||
log.error("HTTP camera media transcoding failed, robotId: {}, deviceId: {}",
|
||||
robotId, deviceId, throwable);
|
||||
}
|
||||
finishStream.run();
|
||||
}
|
||||
@ -418,7 +418,7 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
}
|
||||
|
||||
CameraServiceGrpc.CameraServiceStub stub = grpcServiceManager.getGrpcClient(
|
||||
terminalId, CameraServiceGrpc.CameraServiceStub.class);
|
||||
robotId, CameraServiceGrpc.CameraServiceStub.class);
|
||||
StreamObserver<CameraCommand.GetRGBImageStreamCommand.Feedback> responseObserver =
|
||||
new StreamObserver<CameraCommand.GetRGBImageStreamCommand.Feedback>() {
|
||||
@Override
|
||||
@ -427,8 +427,8 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
try {
|
||||
transcoder.write(frame.getData().toByteArray(), frame.getIsKeyFrame(), frame.getCodec());
|
||||
} catch (IOException exception) {
|
||||
log.error("Failed to write HTTP camera frame, terminalId: {}, deviceId: {}, codec: {}",
|
||||
terminalId, deviceId, frame.getCodec(), exception);
|
||||
log.error("Failed to write HTTP camera frame, robotId: {}, deviceId: {}, codec: {}",
|
||||
robotId, deviceId, frame.getCodec(), exception);
|
||||
finishStream.run();
|
||||
}
|
||||
}
|
||||
@ -437,8 +437,8 @@ public class EdgeCameraServiceImpl implements EdgeCameraService, EdgeStreamServi
|
||||
public void onError(Throwable throwable) {
|
||||
Status status = Status.fromThrowable(throwable);
|
||||
if (status.getCode() != Status.Code.CANCELLED && !streamFinished.get()) {
|
||||
log.warn("HTTP camera gRPC stream ended, terminalId: {}, deviceId: {}, status: {}",
|
||||
terminalId, deviceId, status);
|
||||
log.warn("HTTP camera gRPC stream ended, robotId: {}, deviceId: {}, status: {}",
|
||||
robotId, deviceId, status);
|
||||
}
|
||||
finishStream.run();
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@ public class EdgeDexHandServiceImpl implements EdgeDexHandService, EdgeStreamSer
|
||||
private final MessagePushService messagePushService;
|
||||
|
||||
@Override
|
||||
public DexhandCommand.DexHandState getStatus(String terminalId, String deviceId) {
|
||||
DexHandServiceGrpc.DexHandServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, DexHandServiceGrpc.DexHandServiceBlockingStub.class);
|
||||
public DexhandCommand.DexHandState getStatus(String robotId, String deviceId) {
|
||||
DexHandServiceGrpc.DexHandServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, DexHandServiceGrpc.DexHandServiceBlockingStub.class);
|
||||
DexhandCommand.GetDexHandStateCommand.Request request = DexhandCommand.GetDexHandStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(deviceId))
|
||||
.build();
|
||||
@ -33,13 +33,13 @@ public class EdgeDexHandServiceImpl implements EdgeDexHandService, EdgeStreamSer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDexHandPos(String terminalId, String deviceId) {
|
||||
public void setDexHandPos(String robotId, String deviceId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDexHandAngle(String terminalId, String deviceId, int id, float value) {
|
||||
DexHandServiceGrpc.DexHandServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, DexHandServiceGrpc.DexHandServiceBlockingStub.class);
|
||||
public void setDexHandAngle(String robotId, String deviceId, int id, float value) {
|
||||
DexHandServiceGrpc.DexHandServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, DexHandServiceGrpc.DexHandServiceBlockingStub.class);
|
||||
DexhandCommand.FreedomValue.Builder builder = DexhandCommand.FreedomValue.newBuilder();
|
||||
builder.setId(id);
|
||||
builder.setValue(value);
|
||||
@ -51,23 +51,23 @@ public class EdgeDexHandServiceImpl implements EdgeDexHandService, EdgeStreamSer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDexHandForce(String terminalId, String deviceId) {
|
||||
public void setDexHandForce(String robotId, String deviceId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDexHandSpeed(String terminalId, String deviceId) {
|
||||
public void setDexHandSpeed(String robotId, String deviceId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDexHandPresetAct(String terminalId, String deviceId) {
|
||||
public void setDexHandPresetAct(String robotId, String deviceId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSensorData(String terminalId, String deviceId) {
|
||||
DexHandServiceGrpc.DexHandServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, DexHandServiceGrpc.DexHandServiceBlockingStub.class);
|
||||
public String getSensorData(String robotId, String deviceId) {
|
||||
DexHandServiceGrpc.DexHandServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, DexHandServiceGrpc.DexHandServiceBlockingStub.class);
|
||||
DexhandCommand.GetSensorDataCommand.Request request = DexhandCommand.GetSensorDataCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(deviceId))
|
||||
.build();
|
||||
@ -76,14 +76,14 @@ public class EdgeDexHandServiceImpl implements EdgeDexHandService, EdgeStreamSer
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamObserver<DexhandCommand.GetSensorDataStreamCommand.Request> getSensorDataStream(String terminalId, String deviceId) {
|
||||
DexHandServiceGrpc.DexHandServiceStub stub = grpcServiceManager.getGrpcClient(terminalId, DexHandServiceGrpc.DexHandServiceStub.class);
|
||||
public StreamObserver<DexhandCommand.GetSensorDataStreamCommand.Request> getSensorDataStream(String robotId, String deviceId) {
|
||||
DexHandServiceGrpc.DexHandServiceStub stub = grpcServiceManager.getGrpcClient(robotId, DexHandServiceGrpc.DexHandServiceStub.class);
|
||||
StreamObserver<DexhandCommand.GetSensorDataStreamCommand.Feedback> responseObserver = new StreamObserver<DexhandCommand.GetSensorDataStreamCommand.Feedback>() {
|
||||
@Override
|
||||
public void onNext(DexhandCommand.GetSensorDataStreamCommand.Feedback value) {
|
||||
// 例如,将传感器数据转换为JSON字符串
|
||||
String playLoad = JSON.toJSONString(value.getSensorList());
|
||||
messagePushService.pushToChannel("edgeDexHandServiceImpl/getSensorDataStream/" + terminalId + "/" + deviceId, playLoad);
|
||||
messagePushService.pushToChannel("edgeDexHandServiceImpl/getSensorDataStream/" + robotId + "/" + deviceId, playLoad);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -26,8 +26,8 @@ public class EdgeHlcServiceImpl implements EdgeHlcService {
|
||||
private final GrpcServiceManager grpcServiceManager;
|
||||
|
||||
@Override
|
||||
public String touch(File image, String terminalId, String deviceId, int x, int y, double maxForce) {
|
||||
HlcServiceGrpc.HlcServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, HlcServiceGrpc.HlcServiceBlockingStub.class);
|
||||
public String touch(File image, String robotId, String deviceId, int x, int y, double maxForce) {
|
||||
HlcServiceGrpc.HlcServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, HlcServiceGrpc.HlcServiceBlockingStub.class);
|
||||
HlcCommand.Touch.Request request = HlcCommand.Touch.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(deviceId))
|
||||
.setU(x)
|
||||
@ -89,7 +89,7 @@ public class EdgeHlcServiceImpl implements EdgeHlcService {
|
||||
if (edgeTouchVO.getX() == edgeTouchVO.getY() && edgeTouchVO.getX() == 0) {
|
||||
throw new GlobalException("触控坐标不能为0");
|
||||
}
|
||||
HlcServiceGrpc.HlcServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeTouchVO.getTerminalId(), HlcServiceGrpc.HlcServiceBlockingStub.class);
|
||||
HlcServiceGrpc.HlcServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeTouchVO.getRobotId(), HlcServiceGrpc.HlcServiceBlockingStub.class);
|
||||
HlcCommand.Touch.Request request = HlcCommand.Touch.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeTouchVO.getDeviceId()))
|
||||
.setU(edgeTouchVO.getX())
|
||||
|
||||
@ -41,7 +41,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
@Override
|
||||
public String getStatus(EdgeCommonVO edgeCommonVO) {
|
||||
try {
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicrophoneCommand.GetMicStateCommand.Request request = MicrophoneCommand.GetMicStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||
.build();
|
||||
@ -63,7 +63,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
String deviceId = edgeCommonVO.getDeviceId();
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
String filePath = StrUtil.format("{}/{}_{}.wav", "/home/share/assets/video", deviceId, System.currentTimeMillis());
|
||||
|
||||
// 构建请求消息
|
||||
@ -89,7 +89,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
public String stopRecord(EdgeCommonVO edgeCommonVO) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
MicrophoneCommand.StopMicRecordingCommand.Request request = MicrophoneCommand.StopMicRecordingCommand.Request.newBuilder()
|
||||
@ -113,7 +113,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
public void pauseRecord(EdgeCommonVO edgeCommonVO) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
MicrophoneCommand.PauseMicRecordingCommand.Request request = MicrophoneCommand.PauseMicRecordingCommand.Request.newBuilder()
|
||||
@ -136,7 +136,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
public void resumeRecord(EdgeCommonVO edgeCommonVO) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
MicrophoneCommand.ResumeMicRecordingCommand.Request request = MicrophoneCommand.ResumeMicRecordingCommand.Request.newBuilder()
|
||||
@ -159,7 +159,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
public void setVolume(EdgeMicrophoneVolumeVO edgeMicrophoneVolumeVO) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeMicrophoneVolumeVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeMicrophoneVolumeVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
MicrophoneCommand.SetMicPhoneVolumeCommand.Request request = MicrophoneCommand.SetMicPhoneVolumeCommand.Request.newBuilder()
|
||||
@ -183,7 +183,7 @@ public class EdgeMicrophoneServiceImpl implements EdgeMicrophoneService {
|
||||
public int getVolume(EdgeCommonVO edgeCommonVO) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getTerminalId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub stub = grpcServiceManager.getGrpcClient(edgeCommonVO.getRobotId(), MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
MicrophoneCommand.GetMicPhoneVolumeCommand.Request request = MicrophoneCommand.GetMicPhoneVolumeCommand.Request.newBuilder()
|
||||
|
||||
@ -31,7 +31,7 @@ public class EdgeMotorServiceImpl implements EdgeMotorService {
|
||||
|
||||
@Override
|
||||
public MotorCommand.MotorCommandResponse setZero(EdgeMotorTargetVO request) {
|
||||
return blockingStub(request.getTerminalId()).setZero(MotorCommand.SetMotorZeroRequest.newBuilder()
|
||||
return blockingStub(request.getRobotId()).setZero(MotorCommand.SetMotorZeroRequest.newBuilder()
|
||||
.setTarget(buildTarget(request)).build());
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ public class EdgeMotorServiceImpl implements EdgeMotorService {
|
||||
.setTarget(buildTarget(request)).setWait(buildWait(request));
|
||||
if (request.getMaxVelocityRadS() != null) builder.setMaxVelocityRadS(request.getMaxVelocityRadS());
|
||||
if (request.getAccelerationRadS2() != null) builder.setAccelerationRadS2(request.getAccelerationRadS2());
|
||||
return blockingStub(request.getTerminalId()).moveToZero(builder.build());
|
||||
return blockingStub(request.getRobotId()).moveToZero(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,7 +55,7 @@ public class EdgeMotorServiceImpl implements EdgeMotorService {
|
||||
.setWait(buildWait(request));
|
||||
if (request.getMaxVelocityRadS() != null) builder.setMaxVelocityRadS(request.getMaxVelocityRadS());
|
||||
if (request.getAccelerationRadS2() != null) builder.setAccelerationRadS2(request.getAccelerationRadS2());
|
||||
return blockingStub(request.getTerminalId()).profilePosition(builder.build());
|
||||
return blockingStub(request.getRobotId()).profilePosition(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,30 +68,30 @@ public class EdgeMotorServiceImpl implements EdgeMotorService {
|
||||
.setTargetVelocityRadS(request.getTargetVelocityRadS())
|
||||
.setWait(buildWait(request));
|
||||
if (request.getAccelerationRadS2() != null) builder.setAccelerationRadS2(request.getAccelerationRadS2());
|
||||
return blockingStub(request.getTerminalId()).profileVelocity(builder.build());
|
||||
return blockingStub(request.getRobotId()).profileVelocity(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorCommand.MotorCommandResponse emergencyStop(EdgeMotorTargetVO request) {
|
||||
return blockingStub(request.getTerminalId()).emergencyStop(MotorCommand.EmergencyStopRequest.newBuilder()
|
||||
return blockingStub(request.getRobotId()).emergencyStop(MotorCommand.EmergencyStopRequest.newBuilder()
|
||||
.setTarget(buildTarget(request)).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorCommand.GetMotorStatusResponse getStatus(EdgeMotorTargetVO request) {
|
||||
return blockingStub(request.getTerminalId()).getStatus(MotorCommand.GetMotorStatusRequest.newBuilder()
|
||||
return blockingStub(request.getRobotId()).getStatus(MotorCommand.GetMotorStatusRequest.newBuilder()
|
||||
.setTarget(buildTarget(request)).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorCommand.MotorCommandResponse setEnabled(EdgeMotorEnabledVO request) {
|
||||
return blockingStub(request.getTerminalId()).setEnabled(MotorCommand.SetMotorEnabledRequest.newBuilder()
|
||||
return blockingStub(request.getRobotId()).setEnabled(MotorCommand.SetMotorEnabledRequest.newBuilder()
|
||||
.setTarget(buildTarget(request)).setEnabled(request.isEnabled()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String openCyclicPosition(EdgeMotorCyclicOpenVO request) {
|
||||
MotorServiceGrpc.MotorServiceStub stub = asyncStub(request.getTerminalId());
|
||||
MotorServiceGrpc.MotorServiceStub stub = asyncStub(request.getRobotId());
|
||||
MotorCommand.CyclicPositionRequest open = MotorCommand.CyclicPositionRequest.newBuilder()
|
||||
.setOpen(buildOpen(request)).build();
|
||||
String sessionId = positionStreams.open(stub::streamCyclicPosition, open);
|
||||
@ -115,7 +115,7 @@ public class EdgeMotorServiceImpl implements EdgeMotorService {
|
||||
|
||||
@Override
|
||||
public String openCyclicVelocity(EdgeMotorCyclicOpenVO request) {
|
||||
MotorServiceGrpc.MotorServiceStub stub = asyncStub(request.getTerminalId());
|
||||
MotorServiceGrpc.MotorServiceStub stub = asyncStub(request.getRobotId());
|
||||
MotorCommand.CyclicVelocityRequest open = MotorCommand.CyclicVelocityRequest.newBuilder()
|
||||
.setOpen(buildOpen(request)).build();
|
||||
String sessionId = velocityStreams.open(stub::streamCyclicVelocity, open);
|
||||
@ -179,11 +179,11 @@ public class EdgeMotorServiceImpl implements EdgeMotorService {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private MotorServiceGrpc.MotorServiceBlockingStub blockingStub(String terminalId) {
|
||||
return grpcServiceManager.getGrpcClient(terminalId, MotorServiceGrpc.MotorServiceBlockingStub.class);
|
||||
private MotorServiceGrpc.MotorServiceBlockingStub blockingStub(String robotId) {
|
||||
return grpcServiceManager.getGrpcClient(robotId, MotorServiceGrpc.MotorServiceBlockingStub.class);
|
||||
}
|
||||
|
||||
private MotorServiceGrpc.MotorServiceStub asyncStub(String terminalId) {
|
||||
return grpcServiceManager.getGrpcClient(terminalId, MotorServiceGrpc.MotorServiceStub.class);
|
||||
private MotorServiceGrpc.MotorServiceStub asyncStub(String robotId) {
|
||||
return grpcServiceManager.getGrpcClient(robotId, MotorServiceGrpc.MotorServiceStub.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,15 +40,15 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 获取扬声器当前状态
|
||||
* 通过gRPC调用获取扬声器的运行状态,包括是否正在播放、音量等信息
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @return SpeakerState 返回扬声器的当前状态
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public SpeakerCommand.GetSpeakerStateCommand.Feedback getStatus(String terminalId, String deviceId) {
|
||||
public SpeakerCommand.GetSpeakerStateCommand.Feedback getStatus(String robotId, String deviceId) {
|
||||
try {
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerCommand.GetSpeakerStateCommand.Request request = SpeakerCommand.GetSpeakerStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(deviceId))
|
||||
.build();
|
||||
@ -64,16 +64,16 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 播放音频文件
|
||||
* 通过gRPC调用播放指定路径的音频文件
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @param audioPath 音频文件的路径
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public String playAudio(String terminalId, String deviceId, String audioPath) {
|
||||
public String playAudio(String robotId, String deviceId, String audioPath) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
SpeakerCommand.PlayAudioCommand.Request request = SpeakerCommand.PlayAudioCommand.Request.newBuilder()
|
||||
@ -97,15 +97,15 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 停止当前播放
|
||||
* 通过gRPC调用停止扬声器的当前播放
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public void stopPlayback(String terminalId, String deviceId) {
|
||||
public void stopPlayback(String robotId, String deviceId) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
SpeakerCommand.StopSpeakerCommand.Request request = SpeakerCommand.StopSpeakerCommand.Request.newBuilder()
|
||||
@ -124,15 +124,15 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 暂停当前播放
|
||||
* 通过gRPC调用暂停扬声器的当前播放
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public void pausePlayback(String terminalId, String deviceId) {
|
||||
public void pausePlayback(String robotId, String deviceId) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
SpeakerCommand.PauseSpeakerCommand.Request request = SpeakerCommand.PauseSpeakerCommand.Request.newBuilder()
|
||||
@ -151,15 +151,15 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 恢复暂停的播放
|
||||
* 通过gRPC调用恢复扬声器之前暂停的播放
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public void resumePlayback(String terminalId, String deviceId) {
|
||||
public void resumePlayback(String robotId, String deviceId) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
SpeakerCommand.ResumeSpeakerCommand.Request request = SpeakerCommand.ResumeSpeakerCommand.Request.newBuilder()
|
||||
@ -178,16 +178,16 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 设置扬声器音量
|
||||
* 通过gRPC调用设置扬声器的音量大小
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @param volume 音量大小(0-100)
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public void setVolume(String terminalId, String deviceId, int volume) {
|
||||
public void setVolume(String robotId, String deviceId, int volume) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
SpeakerCommand.SetSpeakerVolumeCommand.Request request = SpeakerCommand.SetSpeakerVolumeCommand.Request.newBuilder()
|
||||
@ -207,16 +207,16 @@ public class EdgeSpeakerServiceImpl implements EdgeSpeakerService {
|
||||
* 获取当前音量
|
||||
* 通过gRPC调用获取扬声器的当前音量大小
|
||||
*
|
||||
* @param terminalId 终端设备ID
|
||||
* @param robotId 机器人永久唯一ID
|
||||
* @param deviceId 设备ID
|
||||
* @return int 返回当前音量大小(0-100)
|
||||
* @throws RuntimeException 当gRPC调用失败时抛出异常
|
||||
*/
|
||||
@Override
|
||||
public int getVolume(String terminalId, String deviceId) {
|
||||
public int getVolume(String robotId, String deviceId) {
|
||||
try {
|
||||
// 获取gRPC客户端存根
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub stub = grpcServiceManager.getGrpcClient(robotId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
|
||||
// 构建请求消息
|
||||
SpeakerCommand.GetSpeakerVolumeCommand.Request request = SpeakerCommand.GetSpeakerVolumeCommand.Request.newBuilder()
|
||||
|
||||
@ -37,9 +37,9 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
private final GrpcServiceManager grpcServiceManager;
|
||||
|
||||
@Override
|
||||
public SystemCommand.GetSystemInfoCommand.Feedback getSystemInfo(String terminalId) {
|
||||
public SystemCommand.GetSystemInfoCommand.Feedback getSystemInfo(String robotId) {
|
||||
SystemServiceGrpc.SystemServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
terminalId, SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
robotId, SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
return stub.getSystemInfo(SystemCommand.GetSystemInfoCommand.Request.newBuilder().build());
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
}
|
||||
}
|
||||
SystemServiceGrpc.SystemServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
request.getTerminalId(), SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
request.getRobotId(), SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
return stub.updateParams(requestBuilder.build()).getHeader();
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
.setRequestJson(request.getRequestJson() == null ? "" : request.getRequestJson())
|
||||
.build();
|
||||
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
request.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
request.getRobotId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||
return stub.executeJsonCommand(grpcRequest);
|
||||
}
|
||||
|
||||
@ -107,10 +107,10 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
|
||||
|
||||
@Override
|
||||
public List<DeDeviceRegistration> deviceList(String terminalId) {
|
||||
public List<DeDeviceRegistration> deviceList(String robotId) {
|
||||
try {
|
||||
SystemServiceGrpc.SystemServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
terminalId, SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
robotId, SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
SystemCommand.GetDeviceListCommand.Feedback response = stub.getDeviceList(
|
||||
SystemCommand.GetDeviceListCommand.Request.newBuilder().build());
|
||||
|
||||
@ -120,7 +120,7 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
DeDeviceRegistration registration = new DeDeviceRegistration();
|
||||
registration.setDeviceCode(device.getDeviceId());
|
||||
registration.setDeviceModel(toDeviceModel(device));
|
||||
registration.setIdDeDeviceTerminalConfig(terminalId);
|
||||
registration.setIdDeDeviceTerminalConfig(robotId);
|
||||
devices.add(registration);
|
||||
}
|
||||
|
||||
@ -173,9 +173,9 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stopAll(String terminalId) {
|
||||
public String stopAll(String robotId) {
|
||||
SystemServiceGrpc.SystemServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
terminalId,
|
||||
robotId,
|
||||
SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
SystemCommand.StopAllCommand.Request build = SystemCommand.StopAllCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(""))
|
||||
@ -192,11 +192,11 @@ public class EdgeSystemServiceImpl implements EdgeSystemService {
|
||||
* @return 系统状态信息,如果获取失败则返回null
|
||||
*/
|
||||
@Override
|
||||
public SystemCommand.GetSystemStatusCommand.Feedback getSystemStatus(String terminalId) {
|
||||
public SystemCommand.GetSystemStatusCommand.Feedback getSystemStatus(String robotId) {
|
||||
try {
|
||||
// 创建gRPC阻塞式存根,用于调用服务端方法
|
||||
SystemServiceGrpc.SystemServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||
terminalId,
|
||||
robotId,
|
||||
SystemServiceGrpc.SystemServiceBlockingStub.class);
|
||||
|
||||
// 构建请求对象,由于是获取系统状态,请求参数为空
|
||||
|
||||
@ -39,7 +39,7 @@ public class GrpcClientServiceImpl implements GrpcClientService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(boolean isStart, String terminalId, String deviceId, String service, String method) {
|
||||
public void send(boolean isStart, String robotId, String deviceId, String service, String method) {
|
||||
try {
|
||||
// 从 Map 中获取服务实例
|
||||
EdgeStreamService serviceInstance = serviceMap.get(service);
|
||||
@ -48,8 +48,8 @@ public class GrpcClientServiceImpl implements GrpcClientService {
|
||||
}
|
||||
|
||||
// 构造流键
|
||||
String key = terminalId + deviceId + service + method;
|
||||
String channel = service + "/" + method + "/" + terminalId + "/" + deviceId;
|
||||
String key = robotId + deviceId + service + method;
|
||||
String channel = service + "/" + method + "/" + robotId + "/" + deviceId;
|
||||
Object streamLock = streamLocks.computeIfAbsent(key, ignored -> new Object());
|
||||
|
||||
synchronized (streamLock) {
|
||||
@ -58,7 +58,7 @@ public class GrpcClientServiceImpl implements GrpcClientService {
|
||||
return;
|
||||
}
|
||||
Method streamMethod = serviceInstance.getClass().getMethod(method, String.class, String.class);
|
||||
StreamObserver<?> streamObserver = (StreamObserver<?>) streamMethod.invoke(serviceInstance, terminalId, deviceId);
|
||||
StreamObserver<?> streamObserver = (StreamObserver<?>) streamMethod.invoke(serviceInstance, robotId, deviceId);
|
||||
if (streamObserver != null) {
|
||||
GrpcStreamManager.addStream(key, streamObserver);
|
||||
}
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
package com.cmvr.common.robot;
|
||||
|
||||
/** Resolved gRPC endpoint for a permanently identified robot. */
|
||||
public record RobotEndpoint(String host, int port) {
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package com.cmvr.common.robot;
|
||||
|
||||
public interface RobotEndpointResolver {
|
||||
|
||||
RobotEndpoint resolve(String robotId);
|
||||
}
|
||||
@ -29,9 +29,9 @@ public class DeRobotConfig extends BaseEntity
|
||||
@TableId(value = "id" , type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
/** 配置ID,32位的UUID,可以是设备ID或终端ID。 */
|
||||
@Excel(name = "配置ID,32位的UUID,可以是设备ID或终端ID。")
|
||||
@ApiModelProperty("配置ID,32位的UUID,可以是设备ID或终端ID。")
|
||||
/** 配置ID,32位的UUID,可以是设备ID或机器人ID。 */
|
||||
@Excel(name = "配置ID,32位的UUID,可以是设备ID或机器人ID。")
|
||||
@ApiModelProperty("配置ID,32位的UUID,可以是设备ID或机器人ID。")
|
||||
private String configId;
|
||||
|
||||
/** 配置类型,区分是设备还是终端 */
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
package com.cmvr.device.service;
|
||||
|
||||
import com.cmvr.common.exception.GlobalException;
|
||||
import com.cmvr.device.domain.DeDeviceTerminalConfig;
|
||||
import com.cmvr.common.robot.RobotEndpoint;
|
||||
import com.cmvr.common.robot.RobotEndpointResolver;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -38,23 +39,23 @@ public class InspectionAlertListenService
|
||||
SUPPORTED_EVENT_TYPES = Collections.unmodifiableSet(values);
|
||||
}
|
||||
|
||||
private final IDeDeviceTerminalConfigService terminalConfigService;
|
||||
private final RobotEndpointResolver robotEndpointResolver;
|
||||
|
||||
/** key=grpcIp,value=当前IP下的工作流监听订阅。 */
|
||||
private final ConcurrentMap<String, ConcurrentMap<String, ListenSubscription>> subscriptions =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/** 兼容原有调用方式,创建一个不绑定工作流的监听。 */
|
||||
public ListenState startListen(String terminalId, Collection<String> eventTypes)
|
||||
public ListenState startListen(String robotId, Collection<String> eventTypes)
|
||||
{
|
||||
return startListen(terminalId, eventTypes, null, null, null, null, null);
|
||||
return startListen(robotId, eventTypes, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public ListenState startListen(String terminalId, Collection<String> eventTypes,
|
||||
public ListenState startListen(String robotId, Collection<String> eventTypes,
|
||||
String flowInstanceId, String taskId, String itemId,
|
||||
String nodeId, String listenerKey)
|
||||
{
|
||||
String grpcIp = resolveTerminalIp(terminalId);
|
||||
String grpcIp = resolveRobotIp(robotId);
|
||||
Set<String> normalizedTypes = normalizeEventTypes(eventTypes, true);
|
||||
ConcurrentMap<String, ListenSubscription> target =
|
||||
subscriptions.computeIfAbsent(grpcIp, key -> new ConcurrentHashMap<>());
|
||||
@ -63,7 +64,7 @@ public class InspectionAlertListenService
|
||||
{
|
||||
ListenSubscription subscription = new ListenSubscription();
|
||||
subscription.setSubscriptionId(buildSubscriptionId(flowInstanceId, itemId, listenerKey, eventType));
|
||||
subscription.setTerminalId(terminalId);
|
||||
subscription.setRobotId(robotId);
|
||||
subscription.setGrpcIp(grpcIp);
|
||||
subscription.setEventType(eventType);
|
||||
subscription.setFlowInstanceId(flowInstanceId);
|
||||
@ -75,28 +76,28 @@ public class InspectionAlertListenService
|
||||
target.put(subscription.getSubscriptionId(), subscription);
|
||||
}
|
||||
|
||||
log.info("开始监听巡检报警,terminalId={},grpcIp={},flowInstanceId={},itemId={},eventTypes={}",
|
||||
terminalId, grpcIp, flowInstanceId, itemId, normalizedTypes);
|
||||
return new ListenState(terminalId, grpcIp, currentTypes(target));
|
||||
log.info("开始监听巡检报警,robotId={},grpcIp={},flowInstanceId={},itemId={},eventTypes={}",
|
||||
robotId, grpcIp, flowInstanceId, itemId, normalizedTypes);
|
||||
return new ListenState(robotId, grpcIp, currentTypes(target));
|
||||
}
|
||||
|
||||
/** 兼容原有调用方式,移除该IP下指定类型的全部监听。 */
|
||||
public ListenState stopListen(String terminalId, Collection<String> eventTypes)
|
||||
public ListenState stopListen(String robotId, Collection<String> eventTypes)
|
||||
{
|
||||
return stopListen(terminalId, eventTypes, null, null, null);
|
||||
return stopListen(robotId, eventTypes, null, null, null);
|
||||
}
|
||||
|
||||
public ListenState stopListen(String terminalId, Collection<String> eventTypes,
|
||||
public ListenState stopListen(String robotId, Collection<String> eventTypes,
|
||||
String flowInstanceId, String itemId, String listenerKey)
|
||||
{
|
||||
String grpcIp = resolveTerminalIp(terminalId);
|
||||
String grpcIp = resolveRobotIp(robotId);
|
||||
Set<String> normalizedTypes = normalizeEventTypes(eventTypes, true);
|
||||
ConcurrentMap<String, ListenSubscription> current = subscriptions.get(grpcIp);
|
||||
if (current == null || current.isEmpty())
|
||||
{
|
||||
log.warn("结束监听巡检报警时未找到IP监听状态,terminalId={},grpcIp={},eventTypes={}",
|
||||
terminalId, grpcIp, normalizedTypes);
|
||||
return new ListenState(terminalId, grpcIp, Collections.emptyList());
|
||||
log.warn("结束监听巡检报警时未找到IP监听状态,robotId={},grpcIp={},eventTypes={}",
|
||||
robotId, grpcIp, normalizedTypes);
|
||||
return new ListenState(robotId, grpcIp, Collections.emptyList());
|
||||
}
|
||||
|
||||
for (String eventType : normalizedTypes)
|
||||
@ -104,8 +105,8 @@ public class InspectionAlertListenService
|
||||
int removed = removeMatching(current, eventType, flowInstanceId, itemId, listenerKey);
|
||||
if (removed == 0)
|
||||
{
|
||||
log.warn("结束监听巡检报警时未找到匹配订阅,terminalId={},grpcIp={},flowInstanceId={},itemId={},eventType={}",
|
||||
terminalId, grpcIp, flowInstanceId, itemId, eventType);
|
||||
log.warn("结束监听巡检报警时未找到匹配订阅,robotId={},grpcIp={},flowInstanceId={},itemId={},eventType={}",
|
||||
robotId, grpcIp, flowInstanceId, itemId, eventType);
|
||||
}
|
||||
}
|
||||
if (current.isEmpty())
|
||||
@ -114,9 +115,9 @@ public class InspectionAlertListenService
|
||||
}
|
||||
|
||||
List<String> remainingTypes = currentTypes(current);
|
||||
log.info("结束监听巡检报警,terminalId={},grpcIp={},flowInstanceId={},itemId={},remainingTypes={}",
|
||||
terminalId, grpcIp, flowInstanceId, itemId, remainingTypes);
|
||||
return new ListenState(terminalId, grpcIp, remainingTypes);
|
||||
log.info("结束监听巡检报警,robotId={},grpcIp={},flowInstanceId={},itemId={},remainingTypes={}",
|
||||
robotId, grpcIp, flowInstanceId, itemId, remainingTypes);
|
||||
return new ListenState(robotId, grpcIp, remainingTypes);
|
||||
}
|
||||
|
||||
/** 返回命中IP和任一标签的全部活动订阅。 */
|
||||
@ -187,10 +188,10 @@ public class InspectionAlertListenService
|
||||
}
|
||||
}
|
||||
|
||||
public ListenState getListenState(String terminalId)
|
||||
public ListenState getListenState(String robotId)
|
||||
{
|
||||
String grpcIp = resolveTerminalIp(terminalId);
|
||||
return new ListenState(terminalId, grpcIp, currentTypes(subscriptions.get(grpcIp)));
|
||||
String grpcIp = resolveRobotIp(robotId);
|
||||
return new ListenState(robotId, grpcIp, currentTypes(subscriptions.get(grpcIp)));
|
||||
}
|
||||
|
||||
private int removeMatching(ConcurrentMap<String, ListenSubscription> current, String eventType,
|
||||
@ -221,23 +222,18 @@ public class InspectionAlertListenService
|
||||
return flow + "|" + item + "|" + key + "|" + eventType;
|
||||
}
|
||||
|
||||
private String resolveTerminalIp(String terminalId)
|
||||
private String resolveRobotIp(String robotId)
|
||||
{
|
||||
String normalizedTerminalId = StringUtils.trimToNull(terminalId);
|
||||
if (normalizedTerminalId == null)
|
||||
String normalizedRobotId = StringUtils.trimToNull(robotId);
|
||||
if (normalizedRobotId == null)
|
||||
{
|
||||
throw new GlobalException("terminalId不能为空");
|
||||
throw new GlobalException("机器人ID不能为空");
|
||||
}
|
||||
DeDeviceTerminalConfig terminalConfig =
|
||||
terminalConfigService.selectDeDeviceTerminalConfigById(normalizedTerminalId);
|
||||
if (terminalConfig == null)
|
||||
{
|
||||
throw new GlobalException("未找到终端配置,terminalId=" + normalizedTerminalId);
|
||||
}
|
||||
String grpcIp = StringUtils.trimToNull(terminalConfig.getHost());
|
||||
RobotEndpoint endpoint = robotEndpointResolver.resolve(normalizedRobotId);
|
||||
String grpcIp = StringUtils.trimToNull(endpoint.host());
|
||||
if (grpcIp == null)
|
||||
{
|
||||
throw new GlobalException("终端配置host不能为空,terminalId=" + normalizedTerminalId);
|
||||
throw new GlobalException("机器人连接地址不能为空,robotId=" + normalizedRobotId);
|
||||
}
|
||||
return grpcIp;
|
||||
}
|
||||
@ -298,7 +294,7 @@ public class InspectionAlertListenService
|
||||
@Data
|
||||
public static class ListenState
|
||||
{
|
||||
private final String terminalId;
|
||||
private final String robotId;
|
||||
private final String grpcIp;
|
||||
private final List<String> eventTypes;
|
||||
}
|
||||
@ -308,9 +304,9 @@ public class InspectionAlertListenService
|
||||
{
|
||||
/** flowInstanceId、itemId、listenerKey、eventType组成的订阅唯一标识。 */
|
||||
private String subscriptionId;
|
||||
/** 工作流节点配置的终端ID。 */
|
||||
private String terminalId;
|
||||
/** 由终端配置解析出的gRPC IP,也是PPE事件匹配IP。 */
|
||||
/** 工作流节点配置的机器人永久唯一 ID。 */
|
||||
private String robotId;
|
||||
/** 由机器人在线信息解析出的 gRPC IP,也是 PPE 事件匹配 IP。 */
|
||||
private String grpcIp;
|
||||
/** 当前订阅监听的PPE事件类型。 */
|
||||
private String eventType;
|
||||
@ -331,7 +327,7 @@ public class InspectionAlertListenService
|
||||
{
|
||||
ListenSubscription copy = new ListenSubscription();
|
||||
copy.subscriptionId = subscriptionId;
|
||||
copy.terminalId = terminalId;
|
||||
copy.robotId = robotId;
|
||||
copy.grpcIp = grpcIp;
|
||||
copy.eventType = eventType;
|
||||
copy.flowInstanceId = flowInstanceId;
|
||||
|
||||
@ -21,13 +21,13 @@ public abstract class BaseChannelSubscribeHandler implements WSMessageHandler<WS
|
||||
|
||||
/**
|
||||
* 是否需要GRPC远程调用
|
||||
* true=格式 service/method/terminalId/deviceId 走grpc
|
||||
* true=格式 service/method/robotId/deviceId 走grpc
|
||||
* false=普通频道,只本地订阅,不调用grpc
|
||||
*/
|
||||
protected abstract boolean isNeedGrpc(String channel);
|
||||
|
||||
/**
|
||||
* 解析grpc四个参数 [service,method,terminalId,deviceId]
|
||||
* 解析grpc四个参数 [service,method,robotId,deviceId]
|
||||
* 只有isNeedGrpc=true才会进入执行
|
||||
*/
|
||||
protected abstract String[] parseGrpcParam(String channel);
|
||||
@ -70,11 +70,11 @@ public abstract class BaseChannelSubscribeHandler implements WSMessageHandler<WS
|
||||
String[] params = parseGrpcParam(channel);
|
||||
String service = params[0];
|
||||
String method = params[1];
|
||||
String terminalId = params[2];
|
||||
String robotId = params[2];
|
||||
String deviceId = params[3];
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
grpcClientService.send(true, terminalId, deviceId, service, method);
|
||||
grpcClientService.send(true, robotId, deviceId, service, method);
|
||||
} catch (Exception e) {
|
||||
log.error("频道{} grpc订阅异常", channel, e);
|
||||
}
|
||||
@ -92,11 +92,11 @@ public abstract class BaseChannelSubscribeHandler implements WSMessageHandler<WS
|
||||
String[] params = parseGrpcParam(channel);
|
||||
String service = params[0];
|
||||
String method = params[1];
|
||||
String terminalId = params[2];
|
||||
String robotId = params[2];
|
||||
String deviceId = params[3];
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
grpcClientService.send(false, terminalId, deviceId, service, method);
|
||||
grpcClientService.send(false, robotId, deviceId, service, method);
|
||||
} catch (Exception e) {
|
||||
log.error("频道{} grpc取消订阅异常", channel, e);
|
||||
} finally {
|
||||
|
||||
@ -7,9 +7,9 @@ public interface GrpcClientService {
|
||||
/**
|
||||
* 发送 gRPC 请求
|
||||
* @param isStart 是否开始
|
||||
* @param terminalId 终端ID
|
||||
* @param robotId 机器人永久唯一 ID
|
||||
* @param deviceId 设备ID
|
||||
* @param method 方法
|
||||
*/
|
||||
void send(boolean isStart, String terminalId, String deviceId, String service,String method);
|
||||
void send(boolean isStart, String robotId, String deviceId, String service,String method);
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ import lombok.NoArgsConstructor;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 巡检机器人对象 inspection_robot
|
||||
*
|
||||
@ -31,6 +33,11 @@ public class InspectionRobot extends BaseEntity
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
/** Permanent robot identity reported by QUIC. */
|
||||
@Excel(name = "机器人ID")
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
private String robotId;
|
||||
|
||||
/** 机器人编码 */
|
||||
@Excel(name = "机器人编码")
|
||||
@ApiModelProperty("机器人编码")
|
||||
@ -81,9 +88,29 @@ public class InspectionRobot extends BaseEntity
|
||||
@ApiModelProperty("当前位置")
|
||||
private String currentPosition;
|
||||
|
||||
/** 终端id */
|
||||
@Excel(name = "终端id")
|
||||
@ApiModelProperty("终端id")
|
||||
private String terminalId;
|
||||
/** QUIC runtime state, independent from the robot business status. */
|
||||
@ApiModelProperty("连接状态:0离线,1在线")
|
||||
private String connectStatus;
|
||||
|
||||
@ApiModelProperty("当前QUIC节点ID")
|
||||
private String quicNodeId;
|
||||
|
||||
@ApiModelProperty("当前QUIC会话ID")
|
||||
private String quicSessionId;
|
||||
|
||||
@ApiModelProperty("边缘端启动ID")
|
||||
private String quicBootId;
|
||||
|
||||
@ApiModelProperty("QUIC连接来源IP")
|
||||
private String observedIp;
|
||||
|
||||
@ApiModelProperty("边缘端软件版本")
|
||||
private String softwareVersion;
|
||||
|
||||
@ApiModelProperty("最后心跳时间")
|
||||
private Date lastHeartbeatTime;
|
||||
|
||||
@ApiModelProperty("归档状态:0正常,1归档")
|
||||
private String archivedStatus;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.cmvr.inspection.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("机器人设备")
|
||||
public class InspectionRobotDevice extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
private String robotId;
|
||||
|
||||
@ApiModelProperty("边缘端设备ID")
|
||||
private String deviceId;
|
||||
|
||||
private String deviceName;
|
||||
private Integer deviceKind;
|
||||
private String typeName;
|
||||
private String enabled;
|
||||
private Integer managerState;
|
||||
private Integer healthStatus;
|
||||
private String onlineStatus;
|
||||
private String hasError;
|
||||
private String errorMessage;
|
||||
private Date statusUpdatedTime;
|
||||
private Date lastSeenTime;
|
||||
private Date offlineTime;
|
||||
}
|
||||
@ -9,6 +9,8 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 巡检机器人视图对象(包含关联信息)
|
||||
*
|
||||
@ -28,6 +30,10 @@ public class InspectionRobotVo extends BaseEntity
|
||||
@ApiModelProperty("id")
|
||||
private String id;
|
||||
|
||||
@Excel(name = "机器人ID")
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
private String robotId;
|
||||
|
||||
/** 机器人编码 */
|
||||
@Excel(name = "机器人编码")
|
||||
@ApiModelProperty("机器人编码")
|
||||
@ -98,9 +104,34 @@ public class InspectionRobotVo extends BaseEntity
|
||||
@ApiModelProperty("修改人昵称")
|
||||
private String updateByName;
|
||||
|
||||
/** 终端id */
|
||||
@Excel(name = "终端id")
|
||||
@ApiModelProperty("终端id")
|
||||
private String terminalId;
|
||||
@ApiModelProperty("连接状态:0离线,1在线")
|
||||
private String connectStatus;
|
||||
|
||||
@ApiModelProperty("当前QUIC节点ID")
|
||||
private String quicNodeId;
|
||||
|
||||
@ApiModelProperty("当前QUIC会话ID")
|
||||
private String quicSessionId;
|
||||
|
||||
@ApiModelProperty("边缘端启动ID")
|
||||
private String quicBootId;
|
||||
|
||||
@ApiModelProperty("QUIC连接来源IP")
|
||||
private String observedIp;
|
||||
|
||||
@ApiModelProperty("边缘端软件版本")
|
||||
private String softwareVersion;
|
||||
|
||||
@ApiModelProperty("最后心跳时间")
|
||||
private Date lastHeartbeatTime;
|
||||
|
||||
@ApiModelProperty("设备总数")
|
||||
private Integer deviceTotal;
|
||||
|
||||
@ApiModelProperty("在线设备数")
|
||||
private Integer onlineDeviceCount;
|
||||
|
||||
@ApiModelProperty("故障设备数")
|
||||
private Integer faultDeviceCount;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package com.cmvr.inspection.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.inspection.domain.InspectionRobotDevice;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface InspectionRobotDeviceMapper extends BaseMapper<InspectionRobotDevice> {
|
||||
|
||||
List<InspectionRobotDevice> selectByRobotId(@Param("robotId") String robotId);
|
||||
|
||||
List<InspectionRobotDevice> selectByRobotIdAndKind(@Param("robotId") String robotId,
|
||||
@Param("deviceKind") Integer deviceKind,
|
||||
@Param("onlineOnly") boolean onlineOnly);
|
||||
|
||||
List<InspectionRobotDevice> selectByIdentity(@Param("robotId") String robotId,
|
||||
@Param("deviceId") String deviceId);
|
||||
|
||||
int updateRuntimeState(InspectionRobotDevice device);
|
||||
|
||||
int markMissingOffline(@Param("robotId") String robotId,
|
||||
@Param("deviceIds") List<String> deviceIds,
|
||||
@Param("offlineTime") Date offlineTime);
|
||||
|
||||
int markAllOffline(@Param("robotId") String robotId,
|
||||
@Param("offlineTime") Date offlineTime);
|
||||
}
|
||||
@ -1,9 +1,11 @@
|
||||
package com.cmvr.inspection.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.cmvr.inspection.domain.InspectionRobot;
|
||||
import com.cmvr.inspection.domain.vo.InspectionRobotVo;
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 巡检机器人Mapper接口
|
||||
@ -21,6 +23,12 @@ public interface InspectionRobotMapper extends MPJBaseMapper<InspectionRobot>
|
||||
*/
|
||||
InspectionRobot selectInspectionRobotById(String id);
|
||||
|
||||
List<InspectionRobot> selectByRobotId(String robotId);
|
||||
|
||||
int updateQuicRuntimeState(InspectionRobot robot);
|
||||
|
||||
int archiveInspectionRobotByIds(@Param("ids") String[] ids, @Param("updateBy") String updateBy);
|
||||
|
||||
/**
|
||||
* 新增巡检机器人
|
||||
*
|
||||
|
||||
@ -6,6 +6,7 @@ import java.util.List;
|
||||
import cmvr.msgs.AgvUtils;
|
||||
import com.baomidou.mybatisplus.spring.service.IService;
|
||||
import com.cmvr.inspection.domain.InspectionRobot;
|
||||
import com.cmvr.inspection.domain.InspectionRobotDevice;
|
||||
import com.cmvr.inspection.domain.vo.InspectionRobotVo;
|
||||
|
||||
/**
|
||||
@ -56,6 +57,11 @@ public interface IInspectionRobotService extends IService<InspectionRobot>
|
||||
*/
|
||||
int deleteInspectionRobotByIds(String[] ids);
|
||||
|
||||
List<InspectionRobotDevice> selectRobotDevices(String id);
|
||||
|
||||
List<InspectionRobotDevice> selectRobotDevicesByRobotId(String robotId, Integer deviceKind,
|
||||
boolean onlineOnly);
|
||||
|
||||
/**
|
||||
* 获取机器人地图列表(从AGV获取)
|
||||
*
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
package com.cmvr.inspection.service;
|
||||
|
||||
import com.cmvr.common.exception.GlobalException;
|
||||
import com.cmvr.common.robot.RobotEndpoint;
|
||||
import com.cmvr.common.robot.RobotEndpointResolver;
|
||||
import com.cmvr.inspection.domain.InspectionRobot;
|
||||
import com.cmvr.inspection.mapper.InspectionRobotMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InspectionRobotEndpointResolver implements RobotEndpointResolver {
|
||||
|
||||
private final InspectionRobotMapper robotMapper;
|
||||
|
||||
@Override
|
||||
public RobotEndpoint resolve(String robotId) {
|
||||
String normalized = StringUtils.trimToNull(robotId);
|
||||
if (normalized == null) {
|
||||
throw new GlobalException("机器人ID不能为空");
|
||||
}
|
||||
List<InspectionRobot> robots = robotMapper.selectByRobotId(normalized);
|
||||
if (robots.isEmpty()) {
|
||||
throw new GlobalException("机器人不存在:" + normalized);
|
||||
}
|
||||
if (robots.size() > 1) {
|
||||
throw new GlobalException("机器人ID存在重复数据:" + normalized);
|
||||
}
|
||||
InspectionRobot robot = robots.get(0);
|
||||
if ("1".equals(robot.getArchivedStatus())) {
|
||||
throw new GlobalException("机器人已归档:" + normalized);
|
||||
}
|
||||
if (!"1".equals(robot.getConnectStatus())) {
|
||||
throw new GlobalException("机器人当前离线:" + normalized);
|
||||
}
|
||||
if (StringUtils.isBlank(robot.getIpAddress()) || robot.getPort() == null) {
|
||||
throw new GlobalException("机器人尚未上报gRPC地址:" + normalized);
|
||||
}
|
||||
return new RobotEndpoint(robot.getIpAddress(), robot.getPort().intValue());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.cmvr.inspection.service;
|
||||
|
||||
import com.cmvr.test.flow.runtime.engine.RobotExecutionTarget;
|
||||
import com.cmvr.test.flow.runtime.engine.RobotExecutionTargetResolver;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InspectionRobotExecutionTargetResolver implements RobotExecutionTargetResolver {
|
||||
|
||||
private final InspectionRobotEndpointResolver endpointResolver;
|
||||
|
||||
@Override
|
||||
public RobotExecutionTarget resolve(String robotId) {
|
||||
String normalized = StringUtils.trimToNull(robotId);
|
||||
endpointResolver.resolve(normalized);
|
||||
return new RobotExecutionTarget(normalized);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package com.cmvr.inspection.service;
|
||||
|
||||
import com.cmvr.quic.contract.QuicEventBus;
|
||||
import com.cmvr.quic.gateway.v1.NodeEvent;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RobotQuicEventSubscriber {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RobotQuicEventSubscriber.class);
|
||||
|
||||
private final QuicEventBus eventBus;
|
||||
private final RobotQuicStateService stateService;
|
||||
|
||||
@Value("${cmvr.quic.enabled:false}")
|
||||
private boolean enabled;
|
||||
|
||||
private ExecutorService executor;
|
||||
private QuicEventBus.Subscription subscription;
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
executor = Executors.newSingleThreadExecutor(runnable -> {
|
||||
Thread thread = new Thread(runnable, "quic-robot-sync");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
subscription = eventBus.watchNodes(true, this::enqueue);
|
||||
log.info("已启动QUIC机器人身份和设备同步");
|
||||
}
|
||||
|
||||
private void enqueue(NodeEvent event) {
|
||||
try {
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
stateService.synchronize(event);
|
||||
} catch (RuntimeException error) {
|
||||
log.error("同步QUIC机器人失败,robotId={},nodeId={},eventType={}",
|
||||
event.getNode().getRobotId(), event.getNode().getNodeId(),
|
||||
event.getType(), error);
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException ignored) {
|
||||
log.debug("QUIC机器人同步线程已停止");
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stop() {
|
||||
if (subscription != null) {
|
||||
subscription.close();
|
||||
}
|
||||
if (executor != null) {
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException error) {
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
package com.cmvr.inspection.service;
|
||||
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.edge.client.manage.GrpcServiceManager;
|
||||
import com.cmvr.inspection.domain.InspectionRobot;
|
||||
import com.cmvr.inspection.domain.InspectionRobotDevice;
|
||||
import com.cmvr.inspection.mapper.InspectionRobotDeviceMapper;
|
||||
import com.cmvr.inspection.mapper.InspectionRobotMapper;
|
||||
import com.cmvr.quic.gateway.v1.ManagedDeviceStatus;
|
||||
import com.cmvr.quic.gateway.v1.NodeEvent;
|
||||
import com.cmvr.quic.gateway.v1.NodeEventType;
|
||||
import com.cmvr.quic.gateway.v1.NodeSnapshot;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RobotQuicStateService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RobotQuicStateService.class);
|
||||
|
||||
private final InspectionRobotMapper robotMapper;
|
||||
private final InspectionRobotDeviceMapper deviceMapper;
|
||||
private final GrpcServiceManager grpcServiceManager;
|
||||
|
||||
@Value("${cmvr.quic.grpc-host-source:observed-source}")
|
||||
private String grpcHostSource;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void synchronize(NodeEvent event) {
|
||||
NodeSnapshot node = event.getNode();
|
||||
String robotId = StringUtils.trimToNull(node.getRobotId());
|
||||
if (robotId == null) {
|
||||
log.warn("忽略未携带机器人ID的QUIC事件,nodeId={},eventType={}",
|
||||
node.getNodeId(), event.getType());
|
||||
return;
|
||||
}
|
||||
|
||||
List<InspectionRobot> matches = robotMapper.selectByRobotId(robotId);
|
||||
if (matches.isEmpty()) {
|
||||
log.warn("QUIC机器人尚未在平台登记,robotId={},nodeId={}", robotId, node.getNodeId());
|
||||
return;
|
||||
}
|
||||
if (matches.size() != 1) {
|
||||
log.error("机器人ID存在{}条重复记录,拒绝同步,robotId={}", matches.size(), robotId);
|
||||
return;
|
||||
}
|
||||
|
||||
InspectionRobot robot = matches.get(0);
|
||||
if ("1".equals(robot.getArchivedStatus())) {
|
||||
log.warn("已归档机器人尝试连接,拒绝同步,robotId={}", robotId);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean offline = event.getType() == NodeEventType.NODE_EVENT_TYPE_OFFLINE || !node.getOnline();
|
||||
if (offline && StringUtils.isNotBlank(robot.getQuicSessionId())
|
||||
&& !robot.getQuicSessionId().equals(node.getSessionId())) {
|
||||
log.info("忽略旧QUIC会话的离线事件,robotId={},activeSession={},eventSession={}",
|
||||
robotId, robot.getQuicSessionId(), node.getSessionId());
|
||||
return;
|
||||
}
|
||||
|
||||
Date eventTime = new Date(event.getEventTimeUnixMs() == 0
|
||||
? System.currentTimeMillis() : event.getEventTimeUnixMs());
|
||||
String oldHost = robot.getIpAddress();
|
||||
Long oldPort = robot.getPort();
|
||||
if (!offline) {
|
||||
String host = resolveGrpcHost(node);
|
||||
Long port = node.getGrpcEndpoint().getPort() == 0
|
||||
? null : Long.valueOf(node.getGrpcEndpoint().getPort());
|
||||
robot.setIpAddress(host);
|
||||
robot.setPort(port);
|
||||
}
|
||||
|
||||
robot.setConnectStatus(offline ? "0" : "1");
|
||||
robot.setQuicNodeId(node.getNodeId());
|
||||
robot.setQuicSessionId(node.getSessionId());
|
||||
robot.setQuicBootId(node.getBootId());
|
||||
robot.setObservedIp(node.getObservedSourceIp());
|
||||
robot.setSoftwareVersion(node.getSoftwareVersion());
|
||||
robot.setLastHeartbeatTime(eventTime);
|
||||
robot.setUpdateTime(DateUtils.getNowDate());
|
||||
robotMapper.updateQuicRuntimeState(robot);
|
||||
|
||||
if (offline) {
|
||||
deviceMapper.markAllOffline(robotId, eventTime);
|
||||
} else {
|
||||
synchronizeDevices(robotId, node, eventTime);
|
||||
}
|
||||
|
||||
if (offline || !Objects.equals(oldHost, robot.getIpAddress())
|
||||
|| !Objects.equals(oldPort, robot.getPort())) {
|
||||
grpcServiceManager.invalidateRobot(robotId);
|
||||
}
|
||||
if (event.getType() == NodeEventType.NODE_EVENT_TYPE_HEARTBEAT) {
|
||||
log.debug("QUIC机器人心跳已同步,robotId={},nodeId={},grpc={}:{},devices={}",
|
||||
robotId, node.getNodeId(), robot.getIpAddress(), robot.getPort(),
|
||||
node.getDeviceManager().getDevicesCount());
|
||||
} else {
|
||||
log.info("QUIC机器人状态已同步,robotId={},nodeId={},online={},grpc={}:{},devices={}",
|
||||
robotId, node.getNodeId(), !offline, robot.getIpAddress(), robot.getPort(),
|
||||
node.getDeviceManager().getDevicesCount());
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeDevices(String robotId, NodeSnapshot node, Date eventTime) {
|
||||
List<String> reportedIds = new ArrayList<>();
|
||||
for (ManagedDeviceStatus status : node.getDeviceManager().getDevicesList()) {
|
||||
String deviceId = StringUtils.trimToNull(status.getDeviceId());
|
||||
if (deviceId == null) {
|
||||
continue;
|
||||
}
|
||||
reportedIds.add(deviceId);
|
||||
List<InspectionRobotDevice> matches = deviceMapper.selectByIdentity(robotId, deviceId);
|
||||
if (matches.size() > 1) {
|
||||
log.error("机器人设备存在重复记录,跳过更新,robotId={},deviceId={},count={}",
|
||||
robotId, deviceId, matches.size());
|
||||
continue;
|
||||
}
|
||||
InspectionRobotDevice device = matches.isEmpty()
|
||||
? createDevice(robotId, deviceId, eventTime) : matches.get(0);
|
||||
device.setDeviceKind(status.getKind());
|
||||
device.setTypeName(status.getTypeName());
|
||||
device.setEnabled(status.getEnabled() ? "1" : "0");
|
||||
device.setManagerState(status.getManagerState());
|
||||
device.setHealthStatus(status.getHealth());
|
||||
device.setOnlineStatus("1");
|
||||
device.setHasError(status.getHasError() ? "1" : "0");
|
||||
device.setErrorMessage(status.getErrorMessage());
|
||||
device.setStatusUpdatedTime(status.getStatusUpdatedAtUnixMs() == 0
|
||||
? null : new Date(status.getStatusUpdatedAtUnixMs()));
|
||||
device.setLastSeenTime(eventTime);
|
||||
device.setOfflineTime(null);
|
||||
device.setUpdateBy("quic");
|
||||
device.setUpdateTime(eventTime);
|
||||
if (matches.isEmpty()) {
|
||||
deviceMapper.insert(device);
|
||||
} else {
|
||||
deviceMapper.updateRuntimeState(device);
|
||||
}
|
||||
}
|
||||
deviceMapper.markMissingOffline(robotId, reportedIds, eventTime);
|
||||
}
|
||||
|
||||
private InspectionRobotDevice createDevice(String robotId, String deviceId, Date now) {
|
||||
InspectionRobotDevice device = new InspectionRobotDevice();
|
||||
device.setRobotId(robotId);
|
||||
device.setDeviceId(deviceId);
|
||||
device.setDeviceName(deviceId);
|
||||
device.setCreateBy("quic");
|
||||
device.setCreateTime(now);
|
||||
return device;
|
||||
}
|
||||
|
||||
private String resolveGrpcHost(NodeSnapshot node) {
|
||||
String advertised = StringUtils.trimToNull(node.getGrpcEndpoint().getHost());
|
||||
String observed = StringUtils.trimToNull(node.getObservedSourceIp());
|
||||
if ("advertised".equalsIgnoreCase(grpcHostSource)) {
|
||||
return advertised != null ? advertised : observed;
|
||||
}
|
||||
return observed != null ? observed : advertised;
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,19 @@
|
||||
|
||||
package com.cmvr.inspection.service.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import cmvr.msgs.AgvUtils;
|
||||
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.device.domain.DeDeviceTerminalConfig;
|
||||
import com.cmvr.device.service.IDeDeviceTerminalConfigService;
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import com.cmvr.edge.client.service.EdgeAgvService;
|
||||
import com.cmvr.inspection.domain.InspectionMap;
|
||||
import com.cmvr.inspection.domain.InspectionRobotDevice;
|
||||
import com.cmvr.inspection.domain.vo.InspectionRobotVo;
|
||||
import com.cmvr.inspection.mapper.InspectionMapMapper;
|
||||
import com.cmvr.inspection.mapper.InspectionRobotDeviceMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
@ -43,7 +42,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
private EdgeAgvService edgeAgvService;
|
||||
|
||||
@Autowired
|
||||
private IDeDeviceTerminalConfigService deDeviceTerminalConfigService;
|
||||
private InspectionRobotDeviceMapper inspectionRobotDeviceMapper;
|
||||
|
||||
/**
|
||||
* 查询巡检机器人
|
||||
@ -76,17 +75,20 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertInspectionRobot(InspectionRobot inspectionRobot)
|
||||
public synchronized int insertInspectionRobot(InspectionRobot inspectionRobot)
|
||||
{
|
||||
DeDeviceTerminalConfig deDeviceTerminalConfig = new DeDeviceTerminalConfig();
|
||||
deDeviceTerminalConfig.setName(inspectionRobot.getRobotName());
|
||||
deDeviceTerminalConfig.setDescription("机器人终端");
|
||||
deDeviceTerminalConfig.setStatus("1");
|
||||
deDeviceTerminalConfig.setHost(inspectionRobot.getIpAddress());
|
||||
deDeviceTerminalConfig.setPort(inspectionRobot.getPort());
|
||||
// 自动创建设备管理模块的终端并将终端id保存机器人中
|
||||
deDeviceTerminalConfigService.insertDeDeviceTerminalConfig(deDeviceTerminalConfig);
|
||||
inspectionRobot.setTerminalId(deDeviceTerminalConfig.getId());
|
||||
String robotId = normalizeRobotId(inspectionRobot.getRobotId());
|
||||
if (StrUtil.isBlank(robotId)) {
|
||||
throw new GlobalException("机器人ID不能为空");
|
||||
}
|
||||
if (!inspectionRobotMapper.selectByRobotId(robotId).isEmpty()) {
|
||||
throw new GlobalException("机器人ID已存在:" + robotId);
|
||||
}
|
||||
inspectionRobot.setRobotId(robotId);
|
||||
inspectionRobot.setIpAddress(null);
|
||||
inspectionRobot.setPort(null);
|
||||
inspectionRobot.setConnectStatus("0");
|
||||
inspectionRobot.setArchivedStatus("0");
|
||||
// 生成UUID作为主键
|
||||
if (inspectionRobot.getId() == null || inspectionRobot.getId().isEmpty()) {
|
||||
inspectionRobot.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
@ -105,13 +107,18 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
@Override
|
||||
public int updateInspectionRobot(InspectionRobot inspectionRobot)
|
||||
{
|
||||
InspectionRobot existing = inspectionRobotMapper.selectInspectionRobotById(inspectionRobot.getId());
|
||||
if (existing == null) {
|
||||
throw new GlobalException("机器人不存在");
|
||||
}
|
||||
if (!java.util.Objects.equals(existing.getRobotId(), normalizeRobotId(inspectionRobot.getRobotId()))) {
|
||||
throw new GlobalException("机器人ID是永久身份标识,不允许修改");
|
||||
}
|
||||
inspectionRobot.setRobotId(null);
|
||||
inspectionRobot.setIpAddress(null);
|
||||
inspectionRobot.setPort(null);
|
||||
inspectionRobot.setUpdateTime(DateUtils.getNowDate());
|
||||
inspectionRobot.setUpdateBy(SecurityUtils.getUsername());
|
||||
DeDeviceTerminalConfig deDeviceTerminalConfig = deDeviceTerminalConfigService.selectDeDeviceTerminalConfigById(inspectionRobot.getTerminalId());
|
||||
deDeviceTerminalConfig.setName(inspectionRobot.getRobotName());
|
||||
deDeviceTerminalConfig.setHost(inspectionRobot.getIpAddress());
|
||||
deDeviceTerminalConfig.setPort(inspectionRobot.getPort());
|
||||
deDeviceTerminalConfigService.updateDeDeviceTerminalConfig(deDeviceTerminalConfig);
|
||||
return inspectionRobotMapper.updateInspectionRobot(inspectionRobot);
|
||||
}
|
||||
|
||||
@ -124,9 +131,40 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
@Override
|
||||
public int deleteInspectionRobotByIds(String[] ids)
|
||||
{
|
||||
List<InspectionRobot> inspectionRobots = inspectionRobotMapper.selectBatchIds(Arrays.asList(ids));
|
||||
deDeviceTerminalConfigService.deleteDeDeviceTerminalConfigByIds(inspectionRobots.stream().map(InspectionRobot::getTerminalId).toArray(String[]::new));
|
||||
return inspectionRobotMapper.deleteInspectionRobotByIds(ids);
|
||||
return inspectionRobotMapper.archiveInspectionRobotByIds(ids, SecurityUtils.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InspectionRobotDevice> selectRobotDevices(String id)
|
||||
{
|
||||
InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(id);
|
||||
if (robot == null) {
|
||||
throw new GlobalException("机器人不存在");
|
||||
}
|
||||
if (StrUtil.isBlank(robot.getRobotId())) {
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
return inspectionRobotDeviceMapper.selectByRobotId(robot.getRobotId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InspectionRobotDevice> selectRobotDevicesByRobotId(String robotId, Integer deviceKind,
|
||||
boolean onlineOnly)
|
||||
{
|
||||
String normalizedRobotId = normalizeRobotId(robotId);
|
||||
if (StrUtil.isBlank(normalizedRobotId)) {
|
||||
throw new GlobalException("机器人ID不能为空");
|
||||
}
|
||||
if (inspectionRobotMapper.selectByRobotId(normalizedRobotId).isEmpty()) {
|
||||
throw new GlobalException("机器人不存在:" + normalizedRobotId);
|
||||
}
|
||||
return inspectionRobotDeviceMapper.selectByRobotIdAndKind(
|
||||
normalizedRobotId, deviceKind, onlineOnly);
|
||||
}
|
||||
|
||||
private static String normalizeRobotId(String robotId)
|
||||
{
|
||||
return robotId == null ? null : robotId.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,7 +185,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
return edgeAgvService.listMaps(edgeCommonVO);
|
||||
@ -196,7 +234,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
return edgeAgvService.downloadMap(edgeCommonVO, mapName);
|
||||
@ -239,7 +277,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
|
||||
// 5. 从来源机器人下载地图JSON
|
||||
EdgeCommonVO sourceEdgeVO = new EdgeCommonVO();
|
||||
sourceEdgeVO.setTerminalId(sourceRobot.getTerminalId());
|
||||
sourceEdgeVO.setRobotId(sourceRobot.getRobotId());
|
||||
sourceEdgeVO.setDeviceId(sourceRobot.getRobotCode());
|
||||
|
||||
String mapContent = edgeAgvService.downloadMap(sourceEdgeVO, map.getMapSourceName());
|
||||
@ -250,7 +288,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
|
||||
// 6. 上传地图到目标机器人
|
||||
EdgeCommonVO targetEdgeVO = new EdgeCommonVO();
|
||||
targetEdgeVO.setTerminalId(targetRobot.getTerminalId());
|
||||
targetEdgeVO.setRobotId(targetRobot.getRobotId());
|
||||
targetEdgeVO.setDeviceId(targetRobot.getRobotCode());
|
||||
|
||||
edgeAgvService.uploadMap(targetEdgeVO, map.getMapSourceName(), mapContent);
|
||||
@ -273,7 +311,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
try {
|
||||
@ -317,7 +355,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
AgvUtils.AgvRuntimeState runtimeState = edgeAgvService.getRuntimeState(edgeCommonVO);
|
||||
@ -352,7 +390,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
.build();
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
// 调用边缘端接口进行导航
|
||||
@ -377,7 +415,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
AgvUtils.AgvMapDimension mapDimension = AgvUtils.AgvMapDimension.forNumber(dimension);
|
||||
@ -398,7 +436,7 @@ public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMappe
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(robot.getTerminalId());
|
||||
edgeCommonVO.setRobotId(robot.getRobotId());
|
||||
edgeCommonVO.setDeviceId(robot.getRobotCode());
|
||||
|
||||
edgeAgvService.stopMapping(edgeCommonVO);
|
||||
|
||||
@ -7,10 +7,12 @@ import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
|
||||
import com.cmvr.common.exception.ServiceException;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.inspection.domain.InspectionRobot;
|
||||
import com.cmvr.inspection.domain.InspectionTask;
|
||||
import com.cmvr.inspection.domain.dto.InspectionTaskInstanceQuery;
|
||||
import com.cmvr.inspection.domain.vo.InspectionTaskInstanceVo;
|
||||
import com.cmvr.inspection.enums.TaskStatusEnum;
|
||||
import com.cmvr.inspection.mapper.InspectionRobotMapper;
|
||||
import com.cmvr.inspection.service.IInspectionTaskService;
|
||||
import com.cmvr.test.flow.control.FlowControlService;
|
||||
import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService;
|
||||
@ -38,6 +40,8 @@ public class InspectionTaskInstanceServiceImpl extends ServiceImpl<InspectionTas
|
||||
private IInspectionTaskService inspectionTaskService;
|
||||
@Autowired
|
||||
private InspectionTaskInstanceMapper inspectionTaskInstanceMapper;
|
||||
@Autowired
|
||||
private InspectionRobotMapper inspectionRobotMapper;
|
||||
|
||||
@Autowired
|
||||
private ITeTaskOrchestrationService teTaskOrchestrationService;
|
||||
@ -155,12 +159,18 @@ public class InspectionTaskInstanceServiceImpl extends ServiceImpl<InspectionTas
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
update.setUpdateBy(SecurityUtils.getUsername());
|
||||
InspectionTask inspectionTask = inspectionTaskService.selectInspectionTaskById(instance.getTaskId());
|
||||
InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(instance.getRobotId());
|
||||
if (robot == null) {
|
||||
throw new ServiceException("巡检任务实例关联的机器人不存在");
|
||||
}
|
||||
JSONObject runParams = new JSONObject();
|
||||
// 获取所有的检测项id
|
||||
teTaskOrchestrationService.queryByTaskId(inspectionTask.getTaskConfigId()).forEach(item -> runParams.put(item.getItemId(), new JSONObject()));
|
||||
// 调用真正的执行
|
||||
String insId = flowTaskRuntimeService.executeTask(TeTaskExecuteNormalVO.builder()
|
||||
.taskId(inspectionTask.getTaskConfigId())
|
||||
.robotId(robot.getRobotId())
|
||||
.robotId(robot.getRobotId())
|
||||
.moduleCode(FlowExecutionModuleCodes.INSPECTION)
|
||||
.runParams(runParams)
|
||||
.build());
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.inspection.mapper.InspectionRobotDeviceMapper">
|
||||
<resultMap id="RobotDeviceResult" type="com.cmvr.inspection.domain.InspectionRobotDevice">
|
||||
<id property="id" column="id"/>
|
||||
<result property="robotId" column="robot_id"/>
|
||||
<result property="deviceId" column="device_id"/>
|
||||
<result property="deviceName" column="device_name"/>
|
||||
<result property="deviceKind" column="device_kind"/>
|
||||
<result property="typeName" column="type_name"/>
|
||||
<result property="enabled" column="enabled"/>
|
||||
<result property="managerState" column="manager_state"/>
|
||||
<result property="healthStatus" column="health_status"/>
|
||||
<result property="onlineStatus" column="online_status"/>
|
||||
<result property="hasError" column="has_error"/>
|
||||
<result property="errorMessage" column="error_message"/>
|
||||
<result property="statusUpdatedTime" column="status_updated_time"/>
|
||||
<result property="lastSeenTime" column="last_seen_time"/>
|
||||
<result property="offlineTime" column="offline_time"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="columns">id, robot_id, device_id, device_name, device_kind, type_name, enabled,
|
||||
manager_state, health_status, online_status, has_error, error_message,
|
||||
status_updated_time, last_seen_time, offline_time, create_by, create_time,
|
||||
update_by, update_time, remark</sql>
|
||||
|
||||
<select id="selectByRobotId" resultMap="RobotDeviceResult">
|
||||
select <include refid="columns"/> from inspection_robot_device
|
||||
where robot_id = #{robotId}
|
||||
order by online_status desc, device_kind, device_id
|
||||
</select>
|
||||
|
||||
<select id="selectByRobotIdAndKind" resultMap="RobotDeviceResult">
|
||||
select <include refid="columns"/> from inspection_robot_device
|
||||
where robot_id = #{robotId}
|
||||
<if test="deviceKind != null">
|
||||
and device_kind = #{deviceKind}
|
||||
</if>
|
||||
<if test="onlineOnly">
|
||||
and online_status = '1' and enabled = '1'
|
||||
</if>
|
||||
order by online_status desc, device_kind, device_name, device_id
|
||||
</select>
|
||||
|
||||
<select id="selectByIdentity" resultMap="RobotDeviceResult">
|
||||
select <include refid="columns"/> from inspection_robot_device
|
||||
where robot_id = #{robotId} and device_id = #{deviceId}
|
||||
</select>
|
||||
|
||||
<update id="updateRuntimeState" parameterType="com.cmvr.inspection.domain.InspectionRobotDevice">
|
||||
update inspection_robot_device
|
||||
set device_kind = #{deviceKind}, type_name = #{typeName}, enabled = #{enabled},
|
||||
manager_state = #{managerState}, health_status = #{healthStatus},
|
||||
online_status = #{onlineStatus}, has_error = #{hasError},
|
||||
error_message = #{errorMessage}, status_updated_time = #{statusUpdatedTime},
|
||||
last_seen_time = #{lastSeenTime}, offline_time = #{offlineTime},
|
||||
update_by = #{updateBy}, update_time = #{updateTime}
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="markMissingOffline">
|
||||
update inspection_robot_device
|
||||
set online_status = '0', offline_time = #{offlineTime},
|
||||
update_by = 'quic', update_time = #{offlineTime}
|
||||
where robot_id = #{robotId} and online_status != '0'
|
||||
<if test="deviceIds != null and deviceIds.size() > 0">
|
||||
and device_id not in
|
||||
<foreach collection="deviceIds" item="deviceId" open="(" separator="," close=")">
|
||||
#{deviceId}
|
||||
</foreach>
|
||||
</if>
|
||||
</update>
|
||||
|
||||
<update id="markAllOffline">
|
||||
update inspection_robot_device
|
||||
set online_status = '0', offline_time = #{offlineTime},
|
||||
update_by = 'quic', update_time = #{offlineTime}
|
||||
where robot_id = #{robotId} and online_status != '0'
|
||||
</update>
|
||||
</mapper>
|
||||
@ -6,6 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<resultMap type="InspectionRobot" id="InspectionRobotResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="robotId" column="robot_id" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
@ -21,11 +22,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="status" column="status" />
|
||||
<result property="batteryLevel" column="battery_level" />
|
||||
<result property="currentPosition" column="current_position" />
|
||||
<result property="terminalId" column="terminal_id" />
|
||||
<result property="connectStatus" column="connect_status" />
|
||||
<result property="quicNodeId" column="quic_node_id" />
|
||||
<result property="quicSessionId" column="quic_session_id" />
|
||||
<result property="quicBootId" column="quic_boot_id" />
|
||||
<result property="observedIp" column="observed_ip" />
|
||||
<result property="softwareVersion" column="software_version" />
|
||||
<result property="lastHeartbeatTime" column="last_heartbeat_time" />
|
||||
<result property="archivedStatus" column="archived_status" />
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="com.cmvr.inspection.domain.vo.InspectionRobotVo" id="InspectionRobotVoResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="robotId" column="robot_id" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
@ -45,17 +54,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="currentPosition" column="current_position" />
|
||||
<result property="createByName" column="create_by_name" />
|
||||
<result property="updateByName" column="update_by_name" />
|
||||
<result property="terminalId" column="terminal_id" />
|
||||
<result property="connectStatus" column="connect_status" />
|
||||
<result property="quicNodeId" column="quic_node_id" />
|
||||
<result property="quicSessionId" column="quic_session_id" />
|
||||
<result property="quicBootId" column="quic_boot_id" />
|
||||
<result property="observedIp" column="observed_ip" />
|
||||
<result property="softwareVersion" column="software_version" />
|
||||
<result property="lastHeartbeatTime" column="last_heartbeat_time" />
|
||||
<result property="deviceTotal" column="device_total" />
|
||||
<result property="onlineDeviceCount" column="online_device_count" />
|
||||
<result property="faultDeviceCount" column="fault_device_count" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectInspectionRobotVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, robot_code, robot_name, robot_model, robot_type, ip_address, port, current_map_id, status, battery_level, current_position, terminal_id from inspection_robot
|
||||
select id, robot_id, create_by, create_time, update_by, update_time, remark,
|
||||
robot_code, robot_name, robot_model, robot_type, ip_address, port,
|
||||
current_map_id, status, battery_level, current_position,
|
||||
connect_status, quic_node_id, quic_session_id, quic_boot_id,
|
||||
observed_ip, software_version, last_heartbeat_time, archived_status
|
||||
from inspection_robot
|
||||
</sql>
|
||||
|
||||
<select id="selectInspectionRobotList" parameterType="InspectionRobot" resultMap="InspectionRobotResult">
|
||||
<include refid="selectInspectionRobotVo"/>
|
||||
<where>
|
||||
<if test="robotCode != null and robotCode != ''"> and robot_code = #{robotCode}</if>
|
||||
<if test="robotId != null and robotId != ''"> and robot_id = #{robotId}</if>
|
||||
<if test="robotName != null and robotName != ''"> and robot_name like concat('%', #{robotName}, '%')</if>
|
||||
<if test="robotModel != null and robotModel != ''"> and robot_model = #{robotModel}</if>
|
||||
<if test="robotType != null and robotType != ''"> and robot_type = #{robotType}</if>
|
||||
@ -69,10 +93,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectByRobotId" parameterType="String" resultMap="InspectionRobotResult">
|
||||
<include refid="selectInspectionRobotVo"/>
|
||||
where robot_id = #{robotId}
|
||||
</select>
|
||||
|
||||
<insert id="insertInspectionRobot" parameterType="InspectionRobot">
|
||||
insert into inspection_robot
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if>
|
||||
<if test="robotId != null">robot_id,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
@ -88,10 +118,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="status != null">status,</if>
|
||||
<if test="batteryLevel != null">battery_level,</if>
|
||||
<if test="currentPosition != null">current_position,</if>
|
||||
<if test="terminalId != null">terminal_id,</if>
|
||||
<if test="connectStatus != null">connect_status,</if>
|
||||
<if test="archivedStatus != null">archived_status,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if>
|
||||
<if test="robotId != null">#{robotId},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
@ -107,7 +139,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="status != null">#{status},</if>
|
||||
<if test="batteryLevel != null">#{batteryLevel},</if>
|
||||
<if test="currentPosition != null">#{currentPosition},</if>
|
||||
<if test="terminalId != null">#{terminalId},</if>
|
||||
<if test="connectStatus != null">#{connectStatus},</if>
|
||||
<if test="archivedStatus != null">#{archivedStatus},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
@ -129,11 +162,29 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="status != null">status = #{status},</if>
|
||||
<if test="batteryLevel != null">battery_level = #{batteryLevel},</if>
|
||||
<if test="currentPosition != null">current_position = #{currentPosition},</if>
|
||||
<if test="terminalId != null">terminal_id = #{terminalId},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="updateQuicRuntimeState" parameterType="InspectionRobot">
|
||||
update inspection_robot
|
||||
set ip_address = #{ipAddress}, port = #{port}, connect_status = #{connectStatus},
|
||||
quic_node_id = #{quicNodeId}, quic_session_id = #{quicSessionId},
|
||||
quic_boot_id = #{quicBootId}, observed_ip = #{observedIp},
|
||||
software_version = #{softwareVersion}, last_heartbeat_time = #{lastHeartbeatTime},
|
||||
update_by = 'quic', update_time = #{updateTime}
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="archiveInspectionRobotByIds" parameterType="String">
|
||||
update inspection_robot set archived_status = '1', connect_status = '0',
|
||||
update_time = sysdate(), update_by = #{updateBy}
|
||||
where id in
|
||||
<foreach item="id" collection="ids" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteInspectionRobotById" parameterType="String">
|
||||
delete from inspection_robot where id = #{id}
|
||||
</delete>
|
||||
@ -147,20 +198,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="selectInspectionRobotVoList" parameterType="InspectionRobot" resultMap="InspectionRobotVoResult">
|
||||
select r.id, r.create_by, r.create_time, r.update_by, r.update_time, r.remark,
|
||||
r.robot_code, r.robot_name, r.robot_model, r.robot_type,
|
||||
r.robot_id, r.robot_code, r.robot_name, r.robot_model, r.robot_type,
|
||||
r.ip_address, r.port, r.current_map_id,
|
||||
m.map_name as current_map_name,
|
||||
r.status, r.battery_level, r.current_position, r.terminal_id,
|
||||
r.status, r.battery_level, r.current_position,
|
||||
r.connect_status, r.quic_node_id, r.quic_session_id, r.quic_boot_id,
|
||||
r.observed_ip, r.software_version, r.last_heartbeat_time,
|
||||
(select count(*) from inspection_robot_device d where d.robot_id = r.robot_id) as device_total,
|
||||
(select count(*) from inspection_robot_device d where d.robot_id = r.robot_id and d.online_status = '1') as online_device_count,
|
||||
(select count(*) from inspection_robot_device d where d.robot_id = r.robot_id and (d.health_status = 3 or d.has_error = '1')) as fault_device_count,
|
||||
u1.nick_name as create_by_name, u2.nick_name as update_by_name, m.map_source_name as robot_map_name
|
||||
from inspection_robot r
|
||||
left join inspection_map m on r.current_map_id = m.id
|
||||
left join sys_user u1 on r.create_by = u1.user_name <!-- 创建人关联用户 -->
|
||||
left join sys_user u2 on r.update_by = u2.user_name <!-- 更新人关联用户 -->
|
||||
<where>
|
||||
and coalesce(r.archived_status, '0') = '0'
|
||||
<if test="robotId != null and robotId != ''"> and r.robot_id = #{robotId}</if>
|
||||
<if test="robotCode != null and robotCode != ''"> and r.robot_code = #{robotCode}</if>
|
||||
<if test="robotName != null and robotName != ''"> and r.robot_name like concat('%', #{robotName}, '%')</if>
|
||||
<if test="robotModel != null and robotModel != ''"> and r.robot_model = #{robotModel}</if>
|
||||
<if test="robotType != null and robotType != ''"> and r.robot_type = #{robotType}</if>
|
||||
<if test="connectStatus != null and connectStatus != ''"> and r.connect_status = #{connectStatus}</if>
|
||||
<if test="status != null and status != ''"> and r.status = #{status}</if>
|
||||
<if test="currentMapId != null and currentMapId != ''"> and r.current_map_id = #{currentMapId}</if>
|
||||
<if test="ipAddress != null and ipAddress != ''"> and r.ip_address = #{ipAddress}</if>
|
||||
|
||||
@ -13,12 +13,12 @@ cmvr-es / 边缘节点
|
||||
cmvr-iot-admin
|
||||
|-- QuicGatewayServer
|
||||
|-- NodeEventBroker
|
||||
`-- QuicGatewayNodeSyncService(进程内直接订阅)
|
||||
`-- RobotQuicEventSubscriber(进程内直接订阅)
|
||||
v
|
||||
de_device_terminal_config + 原有机器人 gRPC 客户端
|
||||
inspection_robot + inspection_robot_device + 原有机器人 gRPC 客户端
|
||||
```
|
||||
|
||||
QUIC 链路不启动内部 gRPC Server,也不经过本机 TCP 端口。平台调用机器人设备的原有 gRPC 客户端保持不变,两者只在终端 endpoint 同步和 channel 失效处理处协作。
|
||||
QUIC 链路不启动内部 gRPC Server,也不经过本机 TCP 端口。QUIC 注册中的永久 `robotId` 是机器人唯一业务身份;平台据此同步机器人 gRPC endpoint、设备快照,并在地址变化时清理对应 channel。
|
||||
|
||||
## 组件职责
|
||||
|
||||
@ -27,7 +27,8 @@ QUIC 链路不启动内部 gRPC Server,也不经过本机 TCP 端口。平台
|
||||
- `ControlStreamHandler`:解析注册、心跳和设备快照控制帧。
|
||||
- `MediaReassembler`:按帧重组媒体 DATAGRAM,并限制内存和超时。
|
||||
- `NodeEventBroker`:Spring 单例,向当前 JVM 内的订阅者直接发布节点和媒体事件。
|
||||
- `QuicGatewayNodeSyncService`:把在线状态和 gRPC endpoint 同步到终端表,并清理旧 gRPC channel。
|
||||
- `RobotQuicEventSubscriber`:订阅当前 JVM 中的 QUIC 节点事件。
|
||||
- `RobotQuicStateService`:按永久 `robotId` 更新机器人、设备在线状态和 gRPC endpoint,并清理旧 gRPC channel。
|
||||
|
||||
协议定义位于:
|
||||
|
||||
@ -79,25 +80,25 @@ Linux 部署时将证书路径换成实际绝对路径。对应配置也可以
|
||||
首次使用前执行:
|
||||
|
||||
```text
|
||||
sql/quic_gateway_terminal_migration.sql
|
||||
sql/robot_quic_identity_migration.sql
|
||||
sql/robot_id_only_migration.sql
|
||||
```
|
||||
|
||||
然后把边缘节点的稳定 `node_id` 绑定到已有终端:
|
||||
先在机器人管理页面新增机器人并填写边缘端上报的永久 `robotId`。机器人首次连接后,平台自动补全地址、端口、QUIC 会话信息和设备清单,无需绑定终端:
|
||||
|
||||
```sql
|
||||
UPDATE de_device_terminal_config
|
||||
SET quic_node_id = 'robot-edge-001'
|
||||
WHERE id = '平台终端ID';
|
||||
INSERT INTO inspection_robot (id, robot_name, robot_id, connect_status, archived_status)
|
||||
VALUES ('业务主键', '测试机器人', '边缘端永久机器人ID', '0', '0');
|
||||
```
|
||||
|
||||
平台不会根据陌生 QUIC 节点自动创建设备。未绑定节点只记录警告,不更新业务数据。
|
||||
平台不会根据陌生 `robotId` 自动创建机器人,未登记的机器人只记录警告;已登记机器人上报的新设备会自动写入设备快照表,未继续上报的设备会标记为离线。
|
||||
|
||||
节点上线后,平台会根据 `cmvr.quic.grpc-host-source` 更新终端的 gRPC 地址:
|
||||
机器人上线后,平台会根据 `cmvr.quic.grpc-host-source` 更新机器人的 gRPC 地址:
|
||||
|
||||
- `observed-source`:使用 Gateway 观察到的连接源 IP,适合 QUIC 与机器人 gRPC 同机部署。
|
||||
- `advertised`:使用节点注册时主动上报的 gRPC host。
|
||||
|
||||
endpoint 变化或节点离线时,原有 `GrpcServiceManager` 缓存的 channel 会立即失效,下次业务调用建立新连接。
|
||||
endpoint 变化或机器人离线时,`GrpcServiceManager` 中按 `robotId` 缓存的 channel 会立即失效,下次业务调用使用最新地址建立连接。
|
||||
|
||||
## 构建与测试
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
<artifactId>cmvr-iot-grpc-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 设备终端配置,用于工作流报警监听组件按终端ID解析边缘端IP -->
|
||||
<!-- 设备服务,供工作流报警监听组件使用 -->
|
||||
<dependency>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-device</artifactId>
|
||||
|
||||
@ -41,10 +41,11 @@ public class TaskContext {
|
||||
*/
|
||||
private String itemId;
|
||||
|
||||
/**
|
||||
* 所属终端 ID
|
||||
*/
|
||||
private String terminalId;
|
||||
/** 机器人永久唯一 ID,用于执行路由和互斥。 */
|
||||
private String robotId;
|
||||
|
||||
/** 稳定的机器人锁键。 */
|
||||
private String lockKey;
|
||||
|
||||
/**
|
||||
* 当前运行状态(运行中/已完成/失败/暂停/终止)
|
||||
|
||||
@ -25,20 +25,20 @@ public class TaskContextManager {
|
||||
private final Map<String, TaskContext> instContextMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 终端 ID → 实例 ID(标识该终端被哪个任务占用)
|
||||
* 机器人锁键 → 实例 ID(标识该机器人被哪个任务占用)
|
||||
*/
|
||||
private final Map<String, String> terminalInstMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, String> robotInstMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 注册任务上下文(任务启动时调用)
|
||||
*/
|
||||
public void register(TaskContext context) {
|
||||
instContextMap.put(context.getInstId(), context);
|
||||
if (context.getTerminalId() != null) {
|
||||
terminalInstMap.put(context.getTerminalId(), context.getInstId());
|
||||
if (context.getLockKey() != null) {
|
||||
robotInstMap.put(context.getLockKey(), context.getInstId());
|
||||
}
|
||||
context.setTerminalStatus(TerminalStatusEnum.RUNNING);
|
||||
log.info("注册任务上下文:instId={}, terminalId={}", context.getInstId(), context.getTerminalId());
|
||||
log.info("注册任务上下文:instId={}, robotId={}", context.getInstId(), context.getRobotId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,10 +49,10 @@ public class TaskContextManager {
|
||||
if (ctx != null) {
|
||||
ctx.setTerminalStatus(TerminalStatusEnum.READY);
|
||||
ctx.setTerminalLocked(false);
|
||||
if (ctx.getTerminalId() != null) {
|
||||
terminalInstMap.remove(ctx.getTerminalId());
|
||||
if (ctx.getLockKey() != null) {
|
||||
robotInstMap.remove(ctx.getLockKey());
|
||||
}
|
||||
log.info("注销任务上下文:instId={}, terminalId={}", instId, ctx.getTerminalId());
|
||||
log.info("注销任务上下文:instId={}, robotId={}", instId, ctx.getRobotId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,25 +71,25 @@ public class TaskContextManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断某个终端是否已被占用(用于任务启动前判断)
|
||||
* 判断某个机器人是否已被占用(用于任务启动前判断)
|
||||
*/
|
||||
public boolean isTerminalLocked(String terminalId) {
|
||||
return terminalInstMap.containsKey(terminalId);
|
||||
public boolean isRobotLocked(String lockKey) {
|
||||
return robotInstMap.containsKey(lockKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断终端是否被其他任务占用(用于任务恢复时判断)
|
||||
* 判断机器人是否被其他任务占用(用于任务恢复时判断)
|
||||
*/
|
||||
public boolean isTerminalOccupied(String terminalId, String excludingInstId) {
|
||||
return terminalInstMap.containsKey(terminalId)
|
||||
&& !terminalInstMap.get(terminalId).equals(excludingInstId);
|
||||
public boolean isRobotOccupied(String lockKey, String excludingInstId) {
|
||||
return robotInstMap.containsKey(lockKey)
|
||||
&& !robotInstMap.get(lockKey).equals(excludingInstId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据终端ID获取正在执行的实例ID
|
||||
* 根据机器人锁键获取正在执行的实例ID
|
||||
*/
|
||||
public String getInstIdByTerminal(String terminalId) {
|
||||
return terminalInstMap.get(terminalId);
|
||||
public String getInstIdByRobot(String lockKey) {
|
||||
return robotInstMap.get(lockKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +97,7 @@ public class TaskContextManager {
|
||||
*/
|
||||
public void clearAll() {
|
||||
instContextMap.clear();
|
||||
terminalInstMap.clear();
|
||||
robotInstMap.clear();
|
||||
log.info("任务上下文已清空");
|
||||
}
|
||||
|
||||
|
||||
@ -39,8 +39,8 @@ public class TaskInstHolder {
|
||||
return taskContextManager.get(instId);
|
||||
}
|
||||
|
||||
public boolean isTerminalLocked(String terminalId) {
|
||||
return taskContextManager.isTerminalLocked(terminalId);
|
||||
public boolean isRobotLocked(String lockKey) {
|
||||
return taskContextManager.isRobotLocked(lockKey);
|
||||
}
|
||||
|
||||
public void markRunning(String instId, String taskId, String itemId,
|
||||
@ -87,7 +87,7 @@ public class TaskInstHolder {
|
||||
// 更新任务状态为SUCCESS
|
||||
syncStatus(instId, TaskStatusEnum.SUCCESS);
|
||||
|
||||
// 注销任务上下文(释放终端锁)
|
||||
// 注销任务上下文(释放机器人锁)
|
||||
taskContextManager.unregister(instId);
|
||||
|
||||
// 发布任务完成事件
|
||||
|
||||
@ -55,7 +55,7 @@ public class FlowControlService {
|
||||
throw new GlobalException("任务已终止,无需重复操作");
|
||||
}
|
||||
// 异步终止
|
||||
executor.execute(() -> edgeSystemService.stopAll(ctx.getTerminalId()));
|
||||
executor.execute(() -> edgeSystemService.stopAll(ctx.getRobotId()));
|
||||
|
||||
// 统一记录日志 + 设置上下文状态 + 数据库状态
|
||||
taskInstHolder.syncStatus(instId, TaskStatusEnum.STOPPED);
|
||||
@ -80,7 +80,7 @@ public class FlowControlService {
|
||||
throw new GlobalException("任务已处于暂停状态");
|
||||
}
|
||||
// 异步停止终端
|
||||
executor.execute(() -> edgeSystemService.stopAll(ctx.getTerminalId()));
|
||||
executor.execute(() -> edgeSystemService.stopAll(ctx.getRobotId()));
|
||||
ctx.setPaused(true);
|
||||
ctx.setTerminalStatus(TerminalStatusEnum.RUNNING);
|
||||
ctx.setStatus(TaskStatusEnum.PAUSED);
|
||||
|
||||
@ -28,17 +28,17 @@ public class FlowTaskAsyncDispatcher {
|
||||
*
|
||||
* @param instId 任务实例 ID
|
||||
* @param taskId 任务定义 ID
|
||||
* @param terminalId 终端 ID
|
||||
* @param robotId 终端 ID
|
||||
* @param runMode 运行模式(NORMAL / TRIAL)
|
||||
* @param items 所有检测项详情
|
||||
*/
|
||||
public void submit(String instId, String taskId, String terminalId,
|
||||
public void submit(String instId, String taskId, String robotId,
|
||||
RunModeEnum runMode, List<TeQueryTaskDetailDTO> items) {
|
||||
executor.submit(() -> {
|
||||
Thread.currentThread().setName("task-thread-" + Thread.currentThread().getId());
|
||||
try {
|
||||
log.info("异步任务开始执行:threadName={}, instId={}, taskId={}", Thread.currentThread().getName(), instId, taskId);
|
||||
taskEngine.run(instId, taskId, terminalId, runMode, items);
|
||||
taskEngine.run(instId, taskId, robotId, runMode, items);
|
||||
log.info("异步任务执行结束:threadName={}, instId={}, taskId={}", Thread.currentThread().getName(), instId, taskId);
|
||||
} catch (Exception e) {
|
||||
log.error("任务执行异常:threadName={}, instId={}, taskId={}, 错误={}", Thread.currentThread().getName(), instId, taskId, e.getMessage(), e);
|
||||
|
||||
@ -22,7 +22,7 @@ public class FlowTaskEngine {
|
||||
|
||||
private final FlowItemExecutor flowTaskExecutor;
|
||||
|
||||
public void run(String instId, String taskId, String terminalId,
|
||||
public void run(String instId, String taskId, String robotId,
|
||||
RunModeEnum runMode, List<TeQueryTaskDetailDTO> items) {
|
||||
TaskContext context = taskInstHolder.getContext(instId);
|
||||
context.setRunMode(runMode);
|
||||
@ -40,7 +40,7 @@ public class FlowTaskEngine {
|
||||
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
|
||||
message.setInstId(instId);
|
||||
message.setTaskId(taskId);
|
||||
message.setTerminalId(terminalId);
|
||||
message.setRobotId(robotId);
|
||||
message.setItemId(itemId);
|
||||
if (runMode.equals(RunModeEnum.VI_PROJECT)) {
|
||||
message.setLoopDetail(item.getSchemeInfo());
|
||||
|
||||
@ -24,6 +24,7 @@ import com.cmvr.test.service.ITeTaskOrchestrationService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
@ -41,13 +42,15 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
private final ITeDetectionItemService detectionItemService;
|
||||
private final TaskInstHolder taskInstHolder;
|
||||
private final FlowTaskAsyncDispatcher flowTaskAsyncDispatcher;
|
||||
private final ObjectProvider<RobotExecutionTargetResolver> targetResolverProvider;
|
||||
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String executeTask(TeTaskExecuteNormalVO taskExecuteNormalVO) {
|
||||
RobotExecutionTarget target = resolveTarget(taskExecuteNormalVO.getRobotId());
|
||||
return executeTaskInternal(
|
||||
taskExecuteNormalVO.getTerminalId(),
|
||||
target,
|
||||
taskExecuteNormalVO.getTaskId(),
|
||||
taskExecuteNormalVO.getModuleCode(),
|
||||
RunModeEnum.NORMAL,
|
||||
@ -59,12 +62,14 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String executeTrialTask(TeTaskExecuteTrailVO taskExecuteTrailVO) {
|
||||
JSONObject runParams = taskExecuteTrailVO.getRunParams();
|
||||
String terminalId = taskExecuteTrailVO.getTerminalId();
|
||||
if (StrUtil.isEmpty(terminalId)) {
|
||||
throw new GlobalException("终端ID不能为空");
|
||||
RobotExecutionTarget target = resolveTarget(taskExecuteTrailVO.getRobotId());
|
||||
String robotId = target.getRobotId();
|
||||
String lockKey = target.lockKey();
|
||||
if (lockKey == null) {
|
||||
throw new GlobalException("机器人ID不能为空");
|
||||
}
|
||||
if (taskInstHolder.isTerminalLocked(terminalId)) {
|
||||
throw new GlobalException("当前终端正在执行其他任务,请稍后再试");
|
||||
if (taskInstHolder.isRobotLocked(lockKey)) {
|
||||
throw new GlobalException("当前机器人正在执行其他任务,请稍后再试");
|
||||
}
|
||||
|
||||
// 构建试运行任务定义(临时任务)
|
||||
@ -78,7 +83,7 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
String taskId = taskOrchestrationService.buildTrialTask(itemId);
|
||||
|
||||
// 创建并保存任务实例
|
||||
TeTaskInst instance = createAndSaveTaskInstance(taskId, terminalId, RunModeEnum.TRIAL);
|
||||
TeTaskInst instance = createAndSaveTaskInstance(taskId, target, RunModeEnum.TRIAL);
|
||||
String instId = instance.getId();
|
||||
|
||||
try {
|
||||
@ -91,10 +96,10 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
List<TeQueryTaskDetailDTO> details = CollUtil.newArrayList(teQueryTaskDetailDTO);
|
||||
|
||||
// 注册上下文
|
||||
registerTaskContext(instId, taskId, null, terminalId, itemId, RunModeEnum.TRIAL, runParams);
|
||||
registerTaskContext(instId, taskId, null, target, itemId, RunModeEnum.TRIAL, runParams);
|
||||
|
||||
// 异步调度执行(与正式任务一致,只是模式为 TRIAL)
|
||||
flowTaskAsyncDispatcher.submit(instId, taskId, terminalId, RunModeEnum.TRIAL, details);
|
||||
flowTaskAsyncDispatcher.submit(instId, taskId, robotId, RunModeEnum.TRIAL, details);
|
||||
|
||||
return instId;
|
||||
} catch (Exception e) {
|
||||
@ -111,8 +116,9 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String executeProjectTask(TeTaskExecuteProjectVO taskExecuteProjectVO) {
|
||||
RobotExecutionTarget target = resolveTarget(taskExecuteProjectVO.getRobotId());
|
||||
return executeTaskInternal(
|
||||
taskExecuteProjectVO.getTerminalId(),
|
||||
target,
|
||||
taskExecuteProjectVO.getProjectId(),
|
||||
null,
|
||||
RunModeEnum.VI_PROJECT,
|
||||
@ -122,15 +128,18 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String executeTaskInternal(String terminalId, String taskId, String moduleCode,
|
||||
public String executeTaskInternal(String robotId, String taskId, String moduleCode,
|
||||
RunModeEnum runMode, JSONObject runParams, Object originalVO) {
|
||||
// 终端id可能为空
|
||||
if (StrUtil.isEmpty(terminalId)) {
|
||||
// throw new GlobalException("终端ID不能为空");
|
||||
return executeTaskInternal(new RobotExecutionTarget(robotId), taskId,
|
||||
moduleCode, runMode, runParams, originalVO);
|
||||
}
|
||||
// 检查终端状态
|
||||
if (!StrUtil.isEmpty(terminalId) && taskInstHolder.isTerminalLocked(terminalId)) {
|
||||
throw new GlobalException("当前终端正在执行其他任务,请稍后再试");
|
||||
|
||||
private String executeTaskInternal(RobotExecutionTarget target, String taskId, String moduleCode,
|
||||
RunModeEnum runMode, JSONObject runParams, Object originalVO) {
|
||||
String robotId = target.getRobotId();
|
||||
String lockKey = target.lockKey();
|
||||
if (lockKey != null && taskInstHolder.isRobotLocked(lockKey)) {
|
||||
throw new GlobalException("当前机器人正在执行其他任务,请稍后再试");
|
||||
}
|
||||
// 查询任务详情(检测项信息)
|
||||
List<TeQueryTaskDetailDTO> details = taskOrchestrationService.queryTaskDetail(taskId);
|
||||
@ -139,15 +148,15 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
throw new GlobalException("当前任务存在未发布的检测项!");
|
||||
}
|
||||
// 创建任务实例
|
||||
TeTaskInst instance = createAndSaveTaskInstance(taskId, terminalId, runMode);
|
||||
TeTaskInst instance = createAndSaveTaskInstance(taskId, target, runMode);
|
||||
String instId = instance.getId();
|
||||
|
||||
try {
|
||||
// 注册上下文
|
||||
registerTaskContext(instId, taskId, moduleCode, terminalId, null, runMode, runParams);
|
||||
registerTaskContext(instId, taskId, moduleCode, target, null, runMode, runParams);
|
||||
|
||||
// 异步提交执行
|
||||
flowTaskAsyncDispatcher.submit(instId, taskId, terminalId, runMode, details);
|
||||
flowTaskAsyncDispatcher.submit(instId, taskId, robotId, runMode, details);
|
||||
return instId;
|
||||
} catch (Exception e) {
|
||||
taskInstHolder.markFailed(
|
||||
@ -163,10 +172,10 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
/**
|
||||
* 创建并保存任务实例
|
||||
*/
|
||||
private TeTaskInst createAndSaveTaskInstance(String taskId, String terminalId, RunModeEnum runMode) {
|
||||
private TeTaskInst createAndSaveTaskInstance(String taskId, RobotExecutionTarget target, RunModeEnum runMode) {
|
||||
TeTaskInst instance = new TeTaskInst();
|
||||
instance.setTaskId(taskId);
|
||||
instance.setTerminalId(terminalId);
|
||||
instance.setRobotId(target.getRobotId());
|
||||
instance.setRunMode(runMode.name());
|
||||
instance.setStatus(String.valueOf(TaskStatusEnum.RUNNING.getCode()));
|
||||
boolean save = taskInstService.save(instance);
|
||||
@ -179,14 +188,15 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
/**
|
||||
* 注册上下文
|
||||
*/
|
||||
private void registerTaskContext(String instId, String taskId, String moduleCode, String terminalId,
|
||||
private void registerTaskContext(String instId, String taskId, String moduleCode, RobotExecutionTarget target,
|
||||
String itemId, RunModeEnum mode, JSONObject runParams) {
|
||||
TaskContext ctx = new TaskContext();
|
||||
ctx.setInstId(instId);
|
||||
ctx.setTaskId(taskId);
|
||||
ctx.setModuleCode(moduleCode);
|
||||
ctx.setRunMode(mode);
|
||||
ctx.setTerminalId(terminalId);
|
||||
ctx.setRobotId(target.getRobotId());
|
||||
ctx.setLockKey(target.lockKey());
|
||||
ctx.setItemId(itemId);
|
||||
ctx.setStatus(TaskStatusEnum.RUNNING);
|
||||
ctx.setTerminalLocked(true);
|
||||
@ -194,4 +204,16 @@ public class FlowTaskRuntimeEntry implements FlowTaskRuntimeService {
|
||||
|
||||
taskInstHolder.register(ctx);
|
||||
}
|
||||
|
||||
private RobotExecutionTarget resolveTarget(String robotId) {
|
||||
if (StrUtil.isNotBlank(robotId)) {
|
||||
RobotExecutionTargetResolver resolver = targetResolverProvider.getIfAvailable();
|
||||
if (resolver == null) {
|
||||
throw new GlobalException("机器人执行解析服务不可用");
|
||||
}
|
||||
return resolver.resolve(robotId);
|
||||
}
|
||||
// 纯逻辑工作流不调用边缘设备,可不绑定机器人。
|
||||
return new RobotExecutionTarget(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ public interface FlowTaskRuntimeService {
|
||||
/**
|
||||
* 执行正式任务(NORMAL 模式)
|
||||
*
|
||||
* @param taskExecuteNormalVO 任务执行请求对象(包含终端ID、任务ID等)
|
||||
* @param taskExecuteNormalVO 任务执行请求对象(包含机器人ID、任务ID等)
|
||||
* @return 返回任务实例ID(instId)
|
||||
*/
|
||||
String executeTask(TeTaskExecuteNormalVO taskExecuteNormalVO);
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package com.cmvr.test.flow.runtime.engine;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class RobotExecutionTarget {
|
||||
private String robotId;
|
||||
|
||||
public String lockKey() {
|
||||
if (robotId != null && !robotId.isBlank()) {
|
||||
return "robot:" + robotId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.cmvr.test.flow.runtime.engine;
|
||||
|
||||
public interface RobotExecutionTargetResolver {
|
||||
RobotExecutionTarget resolve(String robotId);
|
||||
}
|
||||
@ -77,9 +77,9 @@ public class FlowExecutionEvent {
|
||||
private JSONObject outputParams;
|
||||
|
||||
/**
|
||||
* 当前工作流绑定的终端ID。
|
||||
* 当前工作流绑定的机器人永久唯一 ID。
|
||||
*/
|
||||
private String terminalId;
|
||||
private String robotId;
|
||||
|
||||
/**
|
||||
* 循环节点迭代路径,用于区分同一节点的多次执行结果。
|
||||
|
||||
@ -58,7 +58,7 @@ public class FlowAfterInterceptor extends AbstractFlowMsgPreInterceptor{
|
||||
.nodeType(message.getNodeType())
|
||||
.action(message.getAction())
|
||||
.outputParams(result != null ? result.getOutputParams() : null)
|
||||
.terminalId(message.getTerminalId())
|
||||
.robotId(message.getRobotId())
|
||||
.iterations(message.getIterations() == null
|
||||
? new ArrayList<>() : new ArrayList<>(message.getIterations()))
|
||||
.errorMessage(errorMessage)
|
||||
|
||||
@ -78,9 +78,9 @@ public class TaskNodeExecuteMessage {
|
||||
private boolean trial;
|
||||
|
||||
/**
|
||||
* 所属终端ID
|
||||
* 所属机器人永久唯一 ID
|
||||
*/
|
||||
private String terminalId;
|
||||
private String robotId;
|
||||
|
||||
/**
|
||||
* 节点入参
|
||||
|
||||
@ -35,7 +35,7 @@ public class EdgeAgvOperateService implements EdgeOperateService {
|
||||
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
|
||||
// 从输入参数中获取机器人ID
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
@ -67,7 +67,7 @@ public class EdgeAgvOperateService implements EdgeOperateService {
|
||||
|
||||
// 构建边缘端通用参数
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
|
||||
// 直接调用边缘端AGV服务执行导航
|
||||
@ -85,7 +85,7 @@ public class EdgeAgvOperateService implements EdgeOperateService {
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
edgeAgvService.navigateToStation(edgeCommonVO, stationId.trim());
|
||||
log.info("AGV移动到指定站点任务下发成功,设备ID: {},站点ID: {}", deviceId, stationId);
|
||||
|
||||
@ -38,7 +38,7 @@ public class EdgeArmOperateService implements EdgeOperateService {
|
||||
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
|
||||
// 从输入参数中获取设备ID
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
@ -48,7 +48,7 @@ public class EdgeArmOperateService implements EdgeOperateService {
|
||||
}
|
||||
// 构建边缘端通用参数
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
|
||||
// 先调用开启力矩
|
||||
|
||||
@ -53,18 +53,18 @@ public class EdgeCameraOperateService implements EdgeOperateService {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
JSONObject upstreamOutput = message.getUpStreamOutput();
|
||||
|
||||
JSONObject output = new JSONObject();
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
|
||||
switch (action) {
|
||||
case CAMERA_START: {
|
||||
// String result = edgeCameraService.start(terminalId, deviceId);
|
||||
// String result = edgeCameraService.start(robotId, deviceId);
|
||||
String result = StrUtil.format("id为 [{}] 的相机开启了", deviceId);
|
||||
output.put("result", result);
|
||||
break;
|
||||
@ -72,7 +72,7 @@ public class EdgeCameraOperateService implements EdgeOperateService {
|
||||
|
||||
case CAMERA_STOP: {
|
||||
String result = StrUtil.format("id为 [{}] 的相机关闭了", deviceId);
|
||||
// String result = edgeCameraService.stop(terminalId, deviceId);
|
||||
// String result = edgeCameraService.stop(robotId, deviceId);
|
||||
output.put("result", result);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -28,10 +28,10 @@ public class EdgeDeviceCommandOperateService implements EdgeOperateService {
|
||||
@Override
|
||||
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
|
||||
JSONObject input = message.getInputParams() == null ? new JSONObject() : message.getInputParams();
|
||||
String terminalId = StringUtils.defaultIfBlank(message.getTerminalId(), input.getString("terminalId"));
|
||||
String robotId = StringUtils.defaultIfBlank(message.getRobotId(), input.getString("robotId"));
|
||||
String deviceId = StringUtils.trimToNull(input.getString("deviceId"));
|
||||
if (StringUtils.isBlank(terminalId)) {
|
||||
throw new GlobalException("终端ID(terminalId)不能为空");
|
||||
if (StringUtils.isBlank(robotId)) {
|
||||
throw new GlobalException("机器人ID(robotId)不能为空");
|
||||
}
|
||||
if (deviceId == null) {
|
||||
throw new GlobalException("设备ID(deviceId)不能为空");
|
||||
@ -40,7 +40,7 @@ public class EdgeDeviceCommandOperateService implements EdgeOperateService {
|
||||
Object rawRequest = input.get("requestJson");
|
||||
String requestJson = normalizeRequestJson(rawRequest);
|
||||
EdgeSystemJsonCommandVO request = new EdgeSystemJsonCommandVO();
|
||||
request.setTerminalId(terminalId);
|
||||
request.setRobotId(robotId);
|
||||
request.setDeviceId(deviceId);
|
||||
request.setRequestJson(requestJson);
|
||||
|
||||
|
||||
@ -27,27 +27,27 @@ public class EdgeHeadOperateService implements EdgeOperateService {
|
||||
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
|
||||
switch (action) {
|
||||
case BIO_HEAD_SPEAK_START: {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeBioHeadService.speakStart(edgeCommonVO);
|
||||
break;
|
||||
}
|
||||
case BIO_HEAD_SPEAK_STOP: {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeBioHeadService.speakStop(edgeCommonVO);
|
||||
break;
|
||||
}
|
||||
case BIO_HEAD_SPECIAL_EXPRESSION: {
|
||||
Integer expressKey = inputParams.getInteger("expressKey");
|
||||
edgeBioHeadService.specialExpression(terminalId,deviceId,expressKey);
|
||||
edgeBioHeadService.specialExpression(robotId,deviceId,expressKey);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ public class EdgeInspectionAlertOperateService implements EdgeOperateService
|
||||
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message)
|
||||
{
|
||||
JSONObject inputParams = message.getInputParams() == null ? new JSONObject() : message.getInputParams();
|
||||
String terminalId = StringUtils.defaultIfBlank(inputParams.getString("terminalId"), message.getTerminalId());
|
||||
String robotId = StringUtils.defaultIfBlank(inputParams.getString("robotId"), message.getRobotId());
|
||||
Collection<String> eventTypes = resolveEventTypes(inputParams);
|
||||
String listenerKey = inputParams.getString("listenerKey");
|
||||
|
||||
@ -43,12 +43,12 @@ public class EdgeInspectionAlertOperateService implements EdgeOperateService
|
||||
switch (message.getAction())
|
||||
{
|
||||
case INSPECTION_ALERT_LISTEN_START:
|
||||
state = inspectionAlertListenService.startListen(terminalId, eventTypes,
|
||||
state = inspectionAlertListenService.startListen(robotId, eventTypes,
|
||||
message.getInstId(), message.getTaskId(), message.getItemId(),
|
||||
message.getNodeId(), listenerKey);
|
||||
break;
|
||||
case INSPECTION_ALERT_LISTEN_STOP:
|
||||
state = inspectionAlertListenService.stopListen(terminalId, eventTypes,
|
||||
state = inspectionAlertListenService.stopListen(robotId, eventTypes,
|
||||
message.getInstId(), message.getItemId(), listenerKey);
|
||||
break;
|
||||
default:
|
||||
@ -56,7 +56,7 @@ public class EdgeInspectionAlertOperateService implements EdgeOperateService
|
||||
}
|
||||
|
||||
JSONObject output = new JSONObject();
|
||||
output.put("terminalId", state.getTerminalId());
|
||||
output.put("robotId", state.getRobotId());
|
||||
output.put("grpcIp", state.getGrpcIp());
|
||||
output.put("eventTypes", state.getEventTypes());
|
||||
return TaskNodeExecuteResult.success(output);
|
||||
|
||||
@ -45,12 +45,12 @@ public class EdgeMicrophoneOperateService implements EdgeOperateService {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
|
||||
JSONObject output = new JSONObject();
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
switch (action) {
|
||||
case MICROPHONE_START: {
|
||||
// String audioPath = edgeMicrophoneService.startRecord(edgeCommonVO);
|
||||
|
||||
@ -27,7 +27,7 @@ public class EdgeSpeakerOperateService implements EdgeOperateService {
|
||||
// ActionEnum action = message.getAction();
|
||||
// JSONObject inputParams = message.getInputParams();
|
||||
// String deviceId = inputParams.getString("deviceId");
|
||||
// String terminalId = message.getTerminalId();
|
||||
// String robotId = message.getRobotId();
|
||||
// switch (action) {
|
||||
// case SPEAKER_PLAYAUDIO: {
|
||||
// log.info("speaker play audio");
|
||||
@ -37,7 +37,7 @@ public class EdgeSpeakerOperateService implements EdgeOperateService {
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// int index = new Random().nextInt(all.size());
|
||||
// String audioUrl = "/home/share/assets/upload/" + all.get(index);
|
||||
// edgeSpeakerService.playAudio(terminalId, deviceId, audioUrl);
|
||||
// edgeSpeakerService.playAudio(robotId, deviceId, audioUrl);
|
||||
// // 等待播放完成
|
||||
// while (true) {
|
||||
// try {
|
||||
@ -45,7 +45,7 @@ public class EdgeSpeakerOperateService implements EdgeOperateService {
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// SpeakerCommand.GetSpeakerStateCommand.Feedback status = edgeSpeakerService.getStatus(terminalId, deviceId);
|
||||
// SpeakerCommand.GetSpeakerStateCommand.Feedback status = edgeSpeakerService.getStatus(robotId, deviceId);
|
||||
// boolean isRunning = status.getState().getIsRunning();
|
||||
// if (!isRunning) {
|
||||
// break;
|
||||
|
||||
@ -31,13 +31,13 @@ public class EdgeTouchOperateService implements EdgeOperateService {
|
||||
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
String touchParams = inputParams.getString("touchParams");
|
||||
|
||||
if (Objects.requireNonNull(action) == ActionEnum.TOUCH) {
|
||||
EdgeArmMoveJVO edgeArmMoveJVO = JSON.parseObject(touchParams, EdgeArmMoveJVO.class);
|
||||
edgeArmMoveJVO.setTerminalId(terminalId);
|
||||
edgeArmMoveJVO.setRobotId(robotId);
|
||||
edgeArmMoveJVO.setDeviceId(deviceId);
|
||||
|
||||
edgeArmService.moveJ(
|
||||
|
||||
@ -46,7 +46,7 @@ public class ViPlayOperateService implements EdgeOperateService {
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
String bioId = inputParams.getString("bioId");
|
||||
String audioPath = inputParams.getString("audioPath");
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
|
||||
// 仅当 bioId 不为空时才构造 VO
|
||||
EdgeCommonVO edgeCommonVO = null;
|
||||
@ -54,14 +54,14 @@ public class ViPlayOperateService implements EdgeOperateService {
|
||||
if (needBioSpeak) {
|
||||
edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setDeviceId(bioId);
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
}
|
||||
|
||||
log.info("语料播放成功,audioPath={}", audioPath);
|
||||
|
||||
/*try {
|
||||
// 播放音频
|
||||
edgeSpeakerService.playAudio(terminalId, deviceId, audioPath);
|
||||
edgeSpeakerService.playAudio(robotId, deviceId, audioPath);
|
||||
|
||||
// 播放开始时,若 bioId 存在才张嘴
|
||||
if (needBioSpeak) {
|
||||
@ -82,7 +82,7 @@ public class ViPlayOperateService implements EdgeOperateService {
|
||||
}
|
||||
|
||||
SpeakerCommand.GetSpeakerStateCommand.Feedback status =
|
||||
edgeSpeakerService.getStatus(terminalId, deviceId);
|
||||
edgeSpeakerService.getStatus(robotId, deviceId);
|
||||
|
||||
if (!status.getState().getIsRunning()) {
|
||||
break;
|
||||
|
||||
@ -39,7 +39,7 @@ public class LLMTouchOperateService implements LLMOperateService {
|
||||
ActionEnum action = message.getAction();
|
||||
JSONObject inputParams = message.getInputParams();
|
||||
String deviceId = inputParams.getString("deviceId");
|
||||
String terminalId = message.getTerminalId();
|
||||
String robotId = message.getRobotId();
|
||||
|
||||
JSONObject output = new JSONObject();
|
||||
switch (action) {
|
||||
@ -84,7 +84,7 @@ public class LLMTouchOperateService implements LLMOperateService {
|
||||
output.put("coordinates", cal);
|
||||
|
||||
// todo 获取坐标后调用边缘系统
|
||||
edgeHlcService.touch(image, terminalId, "hlc01", x, y, 100d);
|
||||
edgeHlcService.touch(image, robotId, "hlc01", x, y, 100d);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@ -19,8 +19,8 @@ public class TeTaskInst extends BaseEntity {
|
||||
@ApiModelProperty("任务id")
|
||||
private String taskId;
|
||||
|
||||
@ApiModelProperty("终端id")
|
||||
private String terminalId;
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
private String robotId;
|
||||
|
||||
@ApiModelProperty("任务配置信息(对应检测项参数)")
|
||||
private String config;
|
||||
|
||||
@ -22,7 +22,7 @@ public class FlowActionRequestVO {
|
||||
/**
|
||||
* 执行参数
|
||||
*/
|
||||
@ApiModelProperty(value = "节点参数。设备通用指令需要 terminalId、deviceId、requestJson",
|
||||
@ApiModelProperty(value = "节点参数。设备通用指令需要 robotId、deviceId、requestJson",
|
||||
required = true)
|
||||
private JSONObject payload;
|
||||
}
|
||||
|
||||
@ -23,9 +23,8 @@ public class TeTaskExecuteNormalVO {
|
||||
@ApiModelProperty("模块编码")
|
||||
private String moduleCode;
|
||||
|
||||
@ApiModelProperty("终端ID")
|
||||
@NotEmpty(message = "终端ID不能为空")
|
||||
private String terminalId;
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
private String robotId;
|
||||
|
||||
@ApiModelProperty(value = "运行时参数")
|
||||
private JSONObject runParams = new JSONObject();
|
||||
|
||||
@ -15,9 +15,8 @@ public class TeTaskExecuteProjectVO {
|
||||
@NotEmpty(message = "项目ID不能为空")
|
||||
private String projectId;
|
||||
|
||||
@ApiModelProperty("终端ID")
|
||||
@NotEmpty(message = "终端ID不能为空")
|
||||
private String terminalId;
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
private String robotId;
|
||||
|
||||
@ApiModelProperty(value = "运行时参数")
|
||||
private JSONObject runParams = new JSONObject();
|
||||
|
||||
@ -19,9 +19,9 @@ public class TeTaskExecuteTrailVO {
|
||||
@NotEmpty(message = "流程JSON数据不可为空")
|
||||
private String flowData;
|
||||
|
||||
@ApiModelProperty("终端ID")
|
||||
// @NotEmpty(message = "终端ID不能为空")
|
||||
private String terminalId;
|
||||
@ApiModelProperty("机器人永久唯一ID")
|
||||
@NotEmpty(message = "机器人ID不能为空")
|
||||
private String robotId;
|
||||
|
||||
@ApiModelProperty(value = "运行时参数")
|
||||
private JSONObject runParams = new JSONObject();
|
||||
|
||||
@ -66,10 +66,10 @@ public class FlowActionExecutorService {
|
||||
|
||||
private String executeEdgeAction(ActionEnum action, FlowActionRequestVO req) {
|
||||
JSONObject payload = req.getPayload() == null ? new JSONObject() : req.getPayload();
|
||||
String terminalId = payload.getString("terminalId");
|
||||
String robotId = payload.getString("robotId");
|
||||
String deviceId = payload.getString("deviceId");
|
||||
|
||||
// 巡检报警监听组件只需要终端ID和事件类型,不需要设备ID。
|
||||
// 巡检报警监听组件只需要机器人 ID 和事件类型,不需要设备 ID。
|
||||
if (ActionEnum.INSPECTION_ALERT_LISTEN_START.equals(action)
|
||||
|| ActionEnum.INSPECTION_ALERT_LISTEN_STOP.equals(action)) {
|
||||
return executeInspectionAlertAction(action, payload);
|
||||
@ -80,16 +80,16 @@ public class FlowActionExecutorService {
|
||||
}
|
||||
if (ActionEnum.DEVICE_EXECUTE_JSON_COMMAND.equals(action)) {
|
||||
TaskNodeExecuteMessage message = buildSingleNodeMessage(action, payload);
|
||||
message.setTerminalId(terminalId);
|
||||
message.setRobotId(robotId);
|
||||
return edgeDeviceCommandOperateService.execute(message).getOutputParams().toJSONString();
|
||||
}
|
||||
|
||||
if (StrUtil.isEmpty(terminalId) || StrUtil.isEmpty(deviceId)) {
|
||||
throw new GlobalException("EDGE 类型动作必须提供 terminalId 和 deviceId");
|
||||
if (StrUtil.isEmpty(robotId) || StrUtil.isEmpty(deviceId)) {
|
||||
throw new GlobalException("EDGE 类型动作必须提供 robotId 和 deviceId");
|
||||
}
|
||||
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setRobotId(robotId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
switch (action) {
|
||||
// ==== 相机 ====
|
||||
@ -119,7 +119,7 @@ public class FlowActionExecutorService {
|
||||
case ARM_MOVE_TO_POINT:
|
||||
case ARM_MOVE_TO_J: {
|
||||
TaskNodeExecuteMessage message = buildSingleNodeMessage(action, payload);
|
||||
message.setTerminalId(terminalId);
|
||||
message.setRobotId(robotId);
|
||||
edgeArmOperateService.execute(message);
|
||||
return action == ActionEnum.ARM_MOVE_TO_J
|
||||
? "机械臂关节空间运动任务下发成功"
|
||||
@ -129,7 +129,7 @@ public class FlowActionExecutorService {
|
||||
// ==== 语料 ====
|
||||
case VI_PLAY_CORPUS:
|
||||
String audioPath = payload.getString("audioPath");
|
||||
return edgeSpeakerService.playAudio(terminalId, deviceId, audioPath);
|
||||
return edgeSpeakerService.playAudio(robotId, deviceId, audioPath);
|
||||
|
||||
// ==== 头部 ====
|
||||
case BIO_HEAD_SPEAK_START:
|
||||
@ -138,7 +138,7 @@ public class FlowActionExecutorService {
|
||||
return edgeBioHeadService.speakStop(edgeCommonVO);
|
||||
case BIO_HEAD_SPECIAL_EXPRESSION:
|
||||
EdgeFacialExpressionVO edgeFacialExpressionVO = payload.to(EdgeFacialExpressionVO.class);
|
||||
edgeFacialExpressionVO.setTerminalId(terminalId);
|
||||
edgeFacialExpressionVO.setRobotId(robotId);
|
||||
edgeFacialExpressionVO.setDeviceId(deviceId);
|
||||
return edgeBioHeadService.setExpression(edgeFacialExpressionVO);
|
||||
|
||||
@ -193,14 +193,14 @@ public class FlowActionExecutorService {
|
||||
}
|
||||
|
||||
private String executeInspectionAlertAction(ActionEnum action, JSONObject payload) {
|
||||
String terminalId = payload.getString("terminalId");
|
||||
String robotId = payload.getString("robotId");
|
||||
java.util.List<String> types = resolveInspectionAlertEventTypes(payload);
|
||||
|
||||
InspectionAlertListenService.ListenState state;
|
||||
if (ActionEnum.INSPECTION_ALERT_LISTEN_START.equals(action)) {
|
||||
state = inspectionAlertListenService.startListen(terminalId, types);
|
||||
state = inspectionAlertListenService.startListen(robotId, types);
|
||||
} else {
|
||||
state = inspectionAlertListenService.stopListen(terminalId, types);
|
||||
state = inspectionAlertListenService.stopListen(robotId, types);
|
||||
}
|
||||
return JSONObject.toJSONString(state);
|
||||
}
|
||||
|
||||
@ -124,22 +124,22 @@ public class FlowiseActionService {
|
||||
log.info("command start: {}", System.currentTimeMillis());
|
||||
String action = request.getAction();
|
||||
FlowiseActionEnum actionEnum = FlowiseActionEnum.fromAction(action);
|
||||
String terminalId = "4ed1246c465b97975f96c9ef8371a3bd";
|
||||
String robotId = "4ed1246c465b97975f96c9ef8371a3bd";
|
||||
String bioId = "bio_head";
|
||||
switch (actionEnum) {
|
||||
// ==== 表情 ====
|
||||
case SMILE:
|
||||
log.info("高兴");
|
||||
return edgeBioHeadService.specialExpression(terminalId, bioId, 1);
|
||||
return edgeBioHeadService.specialExpression(robotId, bioId, 1);
|
||||
case SAD:
|
||||
log.info("悲伤");
|
||||
return edgeBioHeadService.specialExpression(terminalId, bioId, 4);
|
||||
return edgeBioHeadService.specialExpression(robotId, bioId, 4);
|
||||
case SURPRISED:
|
||||
log.info("惊讶");
|
||||
return edgeBioHeadService.specialExpression(terminalId, bioId, 2);
|
||||
return edgeBioHeadService.specialExpression(robotId, bioId, 2);
|
||||
case TIRED:
|
||||
log.info("累了");
|
||||
return edgeBioHeadService.specialExpression(terminalId, bioId, 5);
|
||||
return edgeBioHeadService.specialExpression(robotId, bioId, 5);
|
||||
|
||||
// ==== 动作 ====
|
||||
case AC_ON:
|
||||
@ -252,11 +252,11 @@ public class FlowiseActionService {
|
||||
|
||||
@NotNull
|
||||
private static EdgeCommonVO getEdgeCommonVO() {
|
||||
String terminalId = "4ed1246c465b97975f96c9ef8371a3bd";
|
||||
String robotId = "4ed1246c465b97975f96c9ef8371a3bd";
|
||||
String bioId = "bio_head";
|
||||
|
||||
EdgeCommonVO speakVO = new EdgeCommonVO();
|
||||
speakVO.setTerminalId(terminalId);
|
||||
speakVO.setRobotId(robotId);
|
||||
speakVO.setDeviceId(bioId);
|
||||
return speakVO;
|
||||
}
|
||||
|
||||
@ -136,11 +136,11 @@ public class TeDetectionItemServiceImpl extends ServiceImpl<TeDetectionItemMappe
|
||||
continue;
|
||||
}
|
||||
|
||||
// 移除"terminalId" 的参数
|
||||
// 移除"robotId" 的参数
|
||||
Iterator<Object> iterator = inputParams.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
JSONObject param = (JSONObject) iterator.next();
|
||||
if ("terminalId".equals(param.getString("name"))) {
|
||||
if ("robotId".equals(param.getString("name"))) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package com.cmvr.test.flow.runtime.engine;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class RobotExecutionTargetTest {
|
||||
|
||||
@Test
|
||||
public void robotIdentityIsUsedForLocking() {
|
||||
RobotExecutionTarget target = new RobotExecutionTarget("robot-001");
|
||||
|
||||
assertEquals("robot:robot-001", target.lockKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pureLogicWorkflowDoesNotCreateARobotLock() {
|
||||
RobotExecutionTarget target = new RobotExecutionTarget(null);
|
||||
|
||||
assertNull(target.lockKey());
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ public class EdgeDeviceCommandOperateServiceTest {
|
||||
|
||||
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
|
||||
message.setAction(ActionEnum.DEVICE_EXECUTE_JSON_COMMAND);
|
||||
message.setTerminalId("terminal-1");
|
||||
message.setRobotId("terminal-1");
|
||||
message.setInputParams(new JSONObject()
|
||||
.fluentPut("deviceId", "device-1")
|
||||
.fluentPut("requestJson", new JSONObject().fluentPut("command", "reset")));
|
||||
@ -35,7 +35,7 @@ public class EdgeDeviceCommandOperateServiceTest {
|
||||
TaskNodeExecuteResult result = service.execute(message);
|
||||
|
||||
assertTrue(result.isSuccess());
|
||||
assertEquals("terminal-1", captured.get().getTerminalId());
|
||||
assertEquals("terminal-1", captured.get().getRobotId());
|
||||
assertEquals("device-1", captured.get().getDeviceId());
|
||||
assertEquals("reset", JSONObject.parseObject(captured.get().getRequestJson()).getString("command"));
|
||||
assertEquals("ready", result.getOutputParams().getJSONObject("responseJson").getString("state"));
|
||||
@ -43,20 +43,20 @@ public class EdgeDeviceCommandOperateServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesTerminalIdFromTrialPayload() {
|
||||
public void usesRobotIdFromTrialPayload() {
|
||||
AtomicReference<EdgeSystemJsonCommandVO> captured = new AtomicReference<>();
|
||||
EdgeDeviceCommandOperateService service = new EdgeDeviceCommandOperateService(
|
||||
edgeSystemService(captured, feedback(true, "", "ok")));
|
||||
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
|
||||
message.setAction(ActionEnum.DEVICE_EXECUTE_JSON_COMMAND);
|
||||
message.setInputParams(new JSONObject()
|
||||
.fluentPut("terminalId", "trial-terminal")
|
||||
.fluentPut("robotId", "trial-terminal")
|
||||
.fluentPut("deviceId", "device-2")
|
||||
.fluentPut("requestJson", "{\"value\":1}"));
|
||||
|
||||
TaskNodeExecuteResult result = service.execute(message);
|
||||
|
||||
assertEquals("trial-terminal", captured.get().getTerminalId());
|
||||
assertEquals("trial-terminal", captured.get().getRobotId());
|
||||
assertEquals("ok", result.getOutputParams().getString("responseJson"));
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public class EdgeDeviceCommandOperateServiceTest {
|
||||
EdgeDeviceCommandOperateService service = new EdgeDeviceCommandOperateService(
|
||||
edgeSystemService(new AtomicReference<>(), feedback(true, "", "{}")));
|
||||
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
|
||||
message.setTerminalId("terminal-1");
|
||||
message.setRobotId("terminal-1");
|
||||
message.setInputParams(new JSONObject()
|
||||
.fluentPut("deviceId", "device-1")
|
||||
.fluentPut("requestJson", "{invalid}"));
|
||||
@ -78,7 +78,7 @@ public class EdgeDeviceCommandOperateServiceTest {
|
||||
EdgeDeviceCommandOperateService service = new EdgeDeviceCommandOperateService(
|
||||
edgeSystemService(new AtomicReference<>(), feedback(false, "command rejected", "")));
|
||||
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
|
||||
message.setTerminalId("terminal-1");
|
||||
message.setRobotId("terminal-1");
|
||||
message.setInputParams(new JSONObject()
|
||||
.fluentPut("deviceId", "device-1")
|
||||
.fluentPut("requestJson", "{}"));
|
||||
|
||||
@ -138,7 +138,8 @@ public class TiProjectServiceImpl extends ServiceImpl<TiProjectMapper, TiProject
|
||||
TeTaskExecuteProjectVO normalVO = new TeTaskExecuteProjectVO();
|
||||
normalVO.setProjectId(taskExecuteProjectVO.getProjectId());
|
||||
normalVO.setRunParams(taskExecuteProjectVO.getRunParams());
|
||||
normalVO.setTerminalId(taskExecuteProjectVO.getTerminalId());
|
||||
normalVO.setRobotId(taskExecuteProjectVO.getRobotId());
|
||||
normalVO.setRobotId(taskExecuteProjectVO.getRobotId());
|
||||
String instId = flowTaskRuntimeService.executeProjectTask(normalVO);
|
||||
// this.update(
|
||||
// new LambdaUpdateWrapper<TiProject>()
|
||||
|
||||
@ -135,7 +135,8 @@ public class ViProjectServiceImpl extends ServiceImpl<ViProjectMapper, ViProject
|
||||
TeTaskExecuteProjectVO normalVO = new TeTaskExecuteProjectVO();
|
||||
normalVO.setProjectId(taskExecuteProjectVO.getProjectId());
|
||||
normalVO.setRunParams(taskExecuteProjectVO.getRunParams());
|
||||
normalVO.setTerminalId(taskExecuteProjectVO.getTerminalId());
|
||||
normalVO.setRobotId(taskExecuteProjectVO.getRobotId());
|
||||
normalVO.setRobotId(taskExecuteProjectVO.getRobotId());
|
||||
String instId = flowTaskRuntimeService.executeProjectTask(normalVO);
|
||||
this.update(
|
||||
new ViProject(),
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
DROP TABLE IF EXISTS `inspection_robot`;
|
||||
CREATE TABLE `inspection_robot` (
|
||||
`id` varchar(64) NOT NULL COMMENT '主键ID',
|
||||
`robot_id` varchar(128) DEFAULT NULL COMMENT 'QUIC上报的永久机器人ID',
|
||||
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
@ -21,11 +22,49 @@ CREATE TABLE `inspection_robot` (
|
||||
`status` char(1) DEFAULT '0' COMMENT '状态(0在线 1离线 2充电中 3巡检中)',
|
||||
`battery_level` int(3) DEFAULT NULL COMMENT '电量百分比',
|
||||
`current_position` varchar(200) DEFAULT NULL COMMENT '当前位置',
|
||||
`terminal_id` varchar(64) DEFAULT NULL COMMENT '终端ID',
|
||||
`connect_status` char(1) NOT NULL DEFAULT '0' COMMENT '连接状态(0离线 1在线)',
|
||||
`quic_node_id` varchar(128) DEFAULT NULL COMMENT '当前QUIC节点实例',
|
||||
`quic_session_id` varchar(128) DEFAULT NULL COMMENT '当前QUIC会话',
|
||||
`quic_boot_id` varchar(128) DEFAULT NULL COMMENT '边缘端启动ID',
|
||||
`observed_ip` varchar(64) DEFAULT NULL COMMENT 'QUIC连接来源IP',
|
||||
`software_version` varchar(64) DEFAULT NULL COMMENT '边缘端软件版本',
|
||||
`last_heartbeat_time` datetime(3) DEFAULT NULL COMMENT '最后心跳时间',
|
||||
`archived_status` char(1) NOT NULL DEFAULT '0' COMMENT '归档状态(0正常 1归档)',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_robot_code` (`robot_code`)
|
||||
UNIQUE KEY `uk_robot_code` (`robot_code`),
|
||||
KEY `idx_inspection_robot_robot_id` (`robot_id`),
|
||||
KEY `idx_inspection_robot_connect_status` (`connect_status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='巡检机器人表';
|
||||
|
||||
-- 1.1 QUIC自动发现的机器人设备表(逻辑唯一性由后端校验)
|
||||
DROP TABLE IF EXISTS `inspection_robot_device`;
|
||||
CREATE TABLE `inspection_robot_device` (
|
||||
`id` varchar(64) NOT NULL COMMENT '主键ID',
|
||||
`robot_id` varchar(128) NOT NULL COMMENT '永久机器人ID',
|
||||
`device_id` varchar(128) NOT NULL COMMENT '边缘端设备ID',
|
||||
`device_name` varchar(128) DEFAULT NULL COMMENT '设备显示名称',
|
||||
`device_kind` int DEFAULT NULL COMMENT '设备类型',
|
||||
`type_name` varchar(128) DEFAULT NULL COMMENT '设备实现类型',
|
||||
`enabled` char(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
|
||||
`manager_state` int DEFAULT NULL COMMENT '设备管理状态',
|
||||
`health_status` int DEFAULT NULL COMMENT '健康状态',
|
||||
`online_status` char(1) NOT NULL DEFAULT '0' COMMENT '在线状态',
|
||||
`has_error` char(1) NOT NULL DEFAULT '0' COMMENT '是否有错误',
|
||||
`error_message` varchar(1000) DEFAULT NULL COMMENT '错误信息',
|
||||
`status_updated_time` datetime(3) DEFAULT NULL COMMENT '边缘端状态更新时间',
|
||||
`last_seen_time` datetime(3) DEFAULT NULL COMMENT '最后发现时间',
|
||||
`offline_time` datetime(3) DEFAULT NULL COMMENT '离线时间',
|
||||
`create_by` varchar(64) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`update_by` varchar(64) DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL,
|
||||
`remark` varchar(500) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_robot_device_robot_id` (`robot_id`),
|
||||
KEY `idx_robot_device_identity` (`robot_id`, `device_id`),
|
||||
KEY `idx_robot_device_online` (`robot_id`, `online_status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='机器人自动发现设备';
|
||||
|
||||
-- 2. 巡检地图表
|
||||
DROP TABLE IF EXISTS `inspection_map`;
|
||||
CREATE TABLE `inspection_map` (
|
||||
|
||||
4
sql/robot_id_only_migration.sql
Normal file
4
sql/robot_id_only_migration.sql
Normal file
@ -0,0 +1,4 @@
|
||||
-- The permanent robot_id is the only edge routing identity.
|
||||
-- Historical data is intentionally not migrated.
|
||||
alter table inspection_robot drop column terminal_id;
|
||||
alter table te_task_inst drop column terminal_id;
|
||||
45
sql/robot_quic_identity_migration.sql
Normal file
45
sql/robot_quic_identity_migration.sql
Normal file
@ -0,0 +1,45 @@
|
||||
-- Existing robot rows are intentionally left with robot_id = NULL.
|
||||
alter table inspection_robot
|
||||
add column robot_id varchar(128) null comment 'Permanent robot identity reported by QUIC' after id,
|
||||
add column connect_status char(1) not null default '0' comment '0 offline, 1 online' after robot_id,
|
||||
add column quic_node_id varchar(128) null comment 'Current QUIC node instance' after connect_status,
|
||||
add column quic_session_id varchar(128) null comment 'Current QUIC session' after quic_node_id,
|
||||
add column quic_boot_id varchar(128) null comment 'Current edge boot id' after quic_session_id,
|
||||
add column observed_ip varchar(64) null comment 'Observed QUIC source IP' after quic_boot_id,
|
||||
add column software_version varchar(64) null comment 'Edge software version' after observed_ip,
|
||||
add column last_heartbeat_time datetime(3) null comment 'Last accepted heartbeat time' after software_version,
|
||||
add column archived_status char(1) not null default '0' comment '0 active, 1 archived' after last_heartbeat_time,
|
||||
add index idx_inspection_robot_robot_id (robot_id),
|
||||
add index idx_inspection_robot_connect_status (connect_status);
|
||||
|
||||
create table inspection_robot_device (
|
||||
id varchar(64) not null,
|
||||
robot_id varchar(128) not null,
|
||||
device_id varchar(128) not null,
|
||||
device_name varchar(128) null,
|
||||
device_kind int null,
|
||||
type_name varchar(128) null,
|
||||
enabled char(1) not null default '1',
|
||||
manager_state int null,
|
||||
health_status int null,
|
||||
online_status char(1) not null default '0',
|
||||
has_error char(1) not null default '0',
|
||||
error_message varchar(1000) null,
|
||||
status_updated_time datetime(3) null,
|
||||
last_seen_time datetime(3) null,
|
||||
offline_time datetime(3) null,
|
||||
create_by varchar(64) null,
|
||||
create_time datetime null,
|
||||
update_by varchar(64) null,
|
||||
update_time datetime null,
|
||||
remark varchar(500) null,
|
||||
primary key (id),
|
||||
index idx_robot_device_robot_id (robot_id),
|
||||
index idx_robot_device_identity (robot_id, device_id),
|
||||
index idx_robot_device_online (robot_id, online_status)
|
||||
) comment='Devices discovered from robot QUIC heartbeat';
|
||||
|
||||
-- New task instances record the permanent identity. Legacy instances remain NULL.
|
||||
alter table te_task_inst
|
||||
add column robot_id varchar(128) null comment 'Permanent robot identity' after task_id,
|
||||
add index idx_te_task_inst_robot_id (robot_id);
|
||||
Loading…
Reference in New Issue
Block a user