CMVR-IOT/cmvr-iot-test/src/main/java/com/cmvr/test/service/FlowiseActionService.java

317 lines
11 KiB
Java
Raw Normal View History

2025-12-04 15:04:46 +08:00
package com.cmvr.test.service;
2025-12-08 14:51:58 +08:00
import cn.hutool.http.HttpRequest;
2025-12-17 18:43:18 +08:00
import cn.hutool.http.HttpUtil;
2025-12-09 17:30:08 +08:00
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
2025-12-08 14:51:58 +08:00
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.exception.GlobalException;
2025-12-05 17:04:51 +08:00
import com.cmvr.common.utils.http.CallAPIUtil;
2025-12-08 14:51:58 +08:00
import com.cmvr.common.utils.uuid.IdUtils;
2025-12-16 14:02:24 +08:00
import com.cmvr.edge.client.model.EdgeCommonVO;
import com.cmvr.edge.client.model.humanoid.EdgeMoveJVO;
2025-12-04 15:04:46 +08:00
import com.cmvr.edge.client.service.EdgeBioHeadService;
2025-12-16 14:02:24 +08:00
import com.cmvr.edge.client.service.EdgeHumanoidRobotService;
2025-12-04 15:04:46 +08:00
import com.cmvr.test.enums.FlowiseActionEnum;
import com.cmvr.test.flow.context.TaskContext;
import com.cmvr.test.flow.context.TaskContextManager;
import com.cmvr.test.flow.control.FlowControlService;
2025-12-17 18:43:18 +08:00
import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService;
2025-12-04 15:04:46 +08:00
import com.cmvr.test.model.vo.FlowiseActionRequestVO;
2025-12-08 15:51:26 +08:00
import com.cmvr.test.model.vo.FlowiseChatRequestVO;
import com.cmvr.test.model.vo.FlowiseStartRequestVO;
2025-12-04 15:04:46 +08:00
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
2025-12-08 14:51:58 +08:00
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
2025-12-04 15:04:46 +08:00
import org.springframework.stereotype.Service;
2025-12-08 14:51:58 +08:00
import javax.annotation.Resource;
2025-12-16 14:02:24 +08:00
import java.util.Collections;
2025-12-05 17:04:51 +08:00
import java.util.HashMap;
import java.util.Map;
2025-12-16 14:02:24 +08:00
import java.util.concurrent.atomic.AtomicBoolean;
2025-12-05 17:04:51 +08:00
2025-12-04 15:04:46 +08:00
@Slf4j
@Service
@RequiredArgsConstructor
public class FlowiseActionService {
2025-12-08 14:51:58 +08:00
2025-12-04 15:04:46 +08:00
private final EdgeBioHeadService edgeBioHeadService;
2025-12-16 14:02:24 +08:00
private final EdgeHumanoidRobotService edgeHumanoidRobotService;
private final TaskContextManager taskContextManager;
private final FlowControlService flowControlService;
2025-12-17 18:43:18 +08:00
private final FlowTaskRuntimeService flowTaskRuntimeService;
2025-12-04 15:04:46 +08:00
2025-12-08 14:51:58 +08:00
@Value("${flowise.tts}")
private String flowiseTts;
2025-12-09 17:30:08 +08:00
@Value("${flowise.query}")
private String flowiseQuery;
2025-12-08 14:51:58 +08:00
@Value("${flowise.start}")
private String flowiseStart;
@Value("${flowise.abort}")
private String flowiseAbort;
@Value("${flowise.api-key}")
private String flowiseApiKey;
@Resource(name = "threadPoolTaskExecutor")
private final ThreadPoolTaskExecutor executor;
2025-12-16 14:02:24 +08:00
/**
* 整个动作是否在运行张嘴 + 摆头
*/
private final AtomicBoolean actionRunning = new AtomicBoolean(true);
2025-12-08 14:51:58 +08:00
private final Object lock = new Object();
private String chatId = null;
2025-12-08 15:51:26 +08:00
public String start(FlowiseStartRequestVO request) {
2025-12-12 15:20:22 +08:00
log.info("flowise start: {}", System.currentTimeMillis());
2025-12-09 17:30:08 +08:00
abort();
2025-12-08 14:51:58 +08:00
synchronized (lock) {
if (chatId != null) {
2025-12-08 15:51:26 +08:00
throw new GlobalException("Flow is already running: " + chatId);
2025-12-08 14:51:58 +08:00
}
chatId = IdUtils.fastUUID();
JSONObject body = new JSONObject();
2025-12-08 15:51:26 +08:00
body.put("question", request.getQuestion());
2025-12-08 14:51:58 +08:00
body.put("chatId", chatId);
body.put("streaming", true);
executor.submit(() -> {
try {
HttpRequest.post(flowiseStart)
.header("Content-Type", "application/json")
2025-12-09 17:30:08 +08:00
.header("Authorization", "Bearer " + flowiseApiKey)
2025-12-08 14:51:58 +08:00
.body(body.toJSONString())
.timeout(0)
.execute()
.body();
} catch (Exception e) {
2025-12-08 15:51:26 +08:00
throw new GlobalException("flowise 流程执行失败: ", e.getMessage());
2025-12-08 14:51:58 +08:00
}
});
return chatId;
}
}
public String abort() {
CallAPIUtil.doPostJson(flowiseTts + "stop", null, null);
Map<String, TaskContext> instContextMap = taskContextManager.getInstContextMap();
2025-12-12 15:20:22 +08:00
instContextMap.forEach((key, value) -> flowControlService.stop(key));
2025-12-08 14:51:58 +08:00
synchronized (lock) {
if (chatId == null) {
2025-12-09 17:30:08 +08:00
return "No flow running.";
2025-12-08 14:51:58 +08:00
}
String id = chatId;
String result = HttpRequest.put(flowiseAbort + id)
.header("Authorization", "Bearer " + flowiseApiKey)
.execute()
.body();
chatId = null;
return result;
}
}
2025-12-05 17:04:51 +08:00
public String command(FlowiseActionRequestVO request) {
2025-12-12 15:20:22 +08:00
log.info("command start: {}", System.currentTimeMillis());
2025-12-04 15:04:46 +08:00
String action = request.getAction();
FlowiseActionEnum actionEnum = FlowiseActionEnum.fromAction(action);
2025-12-08 15:51:26 +08:00
String terminalId = "4ed1246c465b97975f96c9ef8371a3bd";
String bioId = "bio_head";
2025-12-04 15:04:46 +08:00
switch (actionEnum) {
// ==== 表情 ====
case SMILE:
2025-12-05 17:04:51 +08:00
return edgeBioHeadService.specialExpression(terminalId, bioId, 1);
2025-12-04 15:04:46 +08:00
case SAD:
2025-12-05 17:04:51 +08:00
return edgeBioHeadService.specialExpression(terminalId, bioId, 4);
2025-12-17 18:43:18 +08:00
case SURPRISED:
return edgeBioHeadService.specialExpression(terminalId, bioId, 2);
case TIRED:
2025-12-05 17:04:51 +08:00
return edgeBioHeadService.specialExpression(terminalId, bioId, 5);
2025-12-04 15:04:46 +08:00
2025-12-05 17:04:51 +08:00
// ==== 动作 ====
2025-12-17 18:43:18 +08:00
case AC_ON:
// TeTaskExecuteNormalVO teTaskExecuteNormalVO = new TeTaskExecuteNormalVO();
// teTaskExecuteNormalVO.setTerminalId(terminalId);
// teTaskExecuteNormalVO.setTaskId("bd19174754e6e2b84661a4771d04e212");
// flowTaskRuntimeService.executeTask(teTaskExecuteNormalVO);
HttpUtil.post("http://192.168.0.131:8000/action/one", "");
return "空调打开了";
case AC_OFF:
log.info("空调关闭了");
return "空调关闭了";
case MUSIC_ON:
log.info("音乐打开了");
return "音乐打开了";
case MUSIC_OFF:
log.info("音乐关闭了");
return "音乐关闭了";
case DRIVE_MODE_SPORT:
log.info("驾驶模式已切换为运动模式");
return "驾驶模式已切换为运动模式";
case DRIVE_MODE_COMFORT:
log.info("驾驶模式已切换为舒适模式");
return "驾驶模式已切换为舒适模式";
2025-12-04 15:04:46 +08:00
default:
throw new UnsupportedOperationException("未实现的 Flowise Action: " + action);
}
}
2025-12-05 17:04:51 +08:00
2025-12-08 15:51:26 +08:00
public String chat(FlowiseChatRequestVO requestVO) {
2025-12-12 15:20:22 +08:00
log.info("chat start: {}", System.currentTimeMillis());
2025-12-08 15:51:26 +08:00
Map<String, String> body = new HashMap<>();
body.put("text", requestVO.getText());
body.put("voice", "x4_yezi");
CallAPIUtil.doPostJson(flowiseTts + "play", null, body);
2025-12-05 17:04:51 +08:00
return "ok";
}
2025-12-09 17:30:08 +08:00
public JSONObject query(String chatId) {
String body = HttpRequest.get(flowiseQuery + chatId)
.header("Authorization", "Bearer " + flowiseApiKey)
.execute()
.body();
JSONObject root = JSON.parseObject(body);
String execStr = root.getString("executionData");
JSONArray execJson = JSON.parseArray(execStr);
root.put("executionData", execJson);
return root;
}
2025-12-16 14:02:24 +08:00
public String actionStart() {
// 防止重复启动
if (!actionRunning.compareAndSet(false, true)) {
log.warn("action 已在运行中");
return "already running";
}
String terminalId = "8c7c5d5d8c8b09df9d1e5fc9b76c46ab";
// String terminalId = "25d13e8ee0cbc2b1046e190f840b8ab0";
String bioId = "hc01";
String spkId = "spk1";
executor.execute(() -> {
EdgeCommonVO speakVO = new EdgeCommonVO();
speakVO.setTerminalId(terminalId);
speakVO.setDeviceId(spkId);
try {
// 张嘴
// edgeBioHeadService.speakStart(speakVO);
log.info("张嘴动作触发完成");
// 摆头循环
boolean toRight = true;
while (actionRunning.get()) {
double rad = toRight ? 0.1d : -0.1d;
EdgeMoveJVO moveJVO = buildHeadMoveJVO(
terminalId,
bioId,
rad
);
long t0 = System.currentTimeMillis();
log.info(">>> moveJ start, rad={},time={}", rad, t0);
String res = edgeHumanoidRobotService.moveJ(moveJVO);
long t1 = System.currentTimeMillis();
log.info(">>> moveJ end, rad={}, cost={}", rad, t1 - t0);
// 判断返回
try {
JSONObject resJson = JSON.parseObject(res);
if (!resJson.getBooleanValue("success")) {
log.warn("moveJ 返回失败res={}", res);
}
} catch (Exception ignore) {
}
toRight = !toRight;
}
} catch (Exception e) {
log.error("action 执行异常", e);
} finally {
// 回正
try {
EdgeMoveJVO resetVO = buildHeadMoveJVO(
terminalId,
bioId,
0d
);
log.info("结束动作,头部回正 rad=0");
edgeHumanoidRobotService.moveJ(resetVO);
} catch (Exception e) {
log.error("头部回正异常", e);
}
// 停止张嘴
try {
// edgeBioHeadService.speakStop(speakVO);
log.info("speakStop 已调用");
} catch (Exception e) {
log.error("speakStop 调用失败", e);
}
actionRunning.set(false);
log.info("action 线程结束");
}
});
return "ok";
}
public String actionStop() {
if (!actionRunning.get()) {
return "not running";
}
log.info("actionStop 调用,准备停止所有动作");
actionRunning.set(false);
return "ok";
}
private EdgeMoveJVO buildHeadMoveJVO(String terminalId,
String deviceId,
double rad) {
EdgeMoveJVO vo = new EdgeMoveJVO();
vo.setTerminalId(terminalId);
vo.setDeviceId(deviceId);
vo.setAcc(1d);
vo.setVel(1d);
EdgeMoveJVO.JointCmd headCmd = new EdgeMoveJVO.JointCmd();
headCmd.setJointName("HEAD_R");
headCmd.setRad(rad);
headCmd.setVel(0d);
vo.setCmds(Collections.singletonList(headCmd));
return vo;
}
2025-12-08 15:51:26 +08:00
}