fix: 优化接待任务逻辑并修复门控工作流配置刷新

- 减少重置当前任务的动作集合,仅对显式导航/终止命令中断任务
- 修复接待任务中空位置导致任务异常的问题,增加参数校验与默认值处理
- 优化接待任务中位置匹配逻辑,忽略前后空格并修正状态处理流程
- 修复门控工作流执行时配置缺失的问题,添加服务器配置刷新机制
This commit is contained in:
2026-04-21 11:11:15 +08:00
parent 7d28490cec
commit d5ca5966f4
3 changed files with 70 additions and 16 deletions

View File

@@ -99,6 +99,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
private var autoRechargeJob: Job? = null private var autoRechargeJob: Job? = null
private var latestYaw: Float? = null private var latestYaw: Float? = null
private var receptionAnchorYaw: Float? = null private var receptionAnchorYaw: Float? = null
private var lastWorkflowConfigRefreshAt: Long = 0L
private lateinit var telemetryManager: TelemetryManager private lateinit var telemetryManager: TelemetryManager
private lateinit var taskController: TaskController private lateinit var taskController: TaskController
private val robotEventHandler = RobotEventHandler() private val robotEventHandler = RobotEventHandler()
@@ -800,10 +801,19 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
private suspend fun executeDoorWorkflow(openDoor: Boolean): String? { private suspend fun executeDoorWorkflow(openDoor: Boolean): String? {
val workflowIdKey = if (openDoor) HttpManager.PREF_KEY_OD_WFID else HttpManager.PREF_KEY_CD_WFID val workflowIdKey = if (openDoor) HttpManager.PREF_KEY_OD_WFID else HttpManager.PREF_KEY_CD_WFID
val workflowApiKey = if (openDoor) HttpManager.PREF_KEY_OD_WF_KEY else HttpManager.PREF_KEY_CD_WF_KEY val workflowApiKey = if (openDoor) HttpManager.PREF_KEY_OD_WF_KEY else HttpManager.PREF_KEY_CD_WF_KEY
val workflowId = prefs.getString(workflowIdKey, "").orEmpty().trim() var workflowId = prefs.getString(workflowIdKey, "").orEmpty().trim()
val apiKey = prefs.getString(workflowApiKey, "").orEmpty().trim() var apiKey = prefs.getString(workflowApiKey, "").orEmpty().trim()
if (workflowId.isEmpty() || apiKey.isEmpty()) { if (workflowId.isEmpty() || apiKey.isEmpty()) {
Log.w("MainActivity", "Door workflow config missing: openDoor=$openDoor") refreshWorkflowConfigsIfNeeded()
workflowId = prefs.getString(workflowIdKey, "").orEmpty().trim()
apiKey = prefs.getString(workflowApiKey, "").orEmpty().trim()
}
if (workflowId.isEmpty() || apiKey.isEmpty()) {
Log.w(
"MainActivity",
"Door workflow config missing after refresh: openDoor=$openDoor, " +
"workflowIdKey=$workflowIdKey, workflowApiKey=$workflowApiKey"
)
return null return null
} }
return HttpManager.workflow_execute( return HttpManager.workflow_execute(
@@ -814,6 +824,37 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
) )
} }
private suspend fun refreshWorkflowConfigsIfNeeded() {
val now = System.currentTimeMillis()
if (now - lastWorkflowConfigRefreshAt < 5000L) {
return
}
lastWorkflowConfigRefreshAt = now
val runtimeConfigs = HttpManager.fetchRuntimeConfigs(this@MainActivity) ?: return
val workflowKeys = listOf(
HttpManager.PREF_KEY_OD_WFID,
HttpManager.PREF_KEY_OD_WF_KEY,
HttpManager.PREF_KEY_CD_WFID,
HttpManager.PREF_KEY_CD_WF_KEY
)
val editor = prefs.edit()
var changed = false
for (key in workflowKeys) {
val value = runtimeConfigs[key]?.trim().orEmpty()
if (value.isEmpty()) {
continue
}
if (prefs.getString(key, "").orEmpty() != value) {
editor.putString(key, value)
changed = true
}
}
if (changed) {
editor.apply()
Log.i("MainActivity", "Workflow configs refreshed from server.")
}
}
private fun isActivated(): Boolean { private fun isActivated(): Boolean {
if (!::prefs.isInitialized) { if (!::prefs.isInitialized) {
return false return false

View File

@@ -313,7 +313,8 @@ class MqttManager(
private fun handleJsonCommand(obj: JSONObject) { private fun handleJsonCommand(obj: JSONObject) {
val action = obj.optString("action", obj.optString("cmd", obj.optString("type", ""))).lowercase() val action = obj.optString("action", obj.optString("cmd", obj.optString("type", ""))).lowercase()
val actionsResetTask = setOf("recharge", "goto", "notification", "reception", "patrol", "repose", "turn", "tilt", "terminate") // Only interrupt current task for explicit navigation/termination commands.
val actionsResetTask = setOf("recharge", "goto", "terminate")
if (action in actionsResetTask) { if (action in actionsResetTask) {
scope.launch(Dispatchers.Main) { scope.launch(Dispatchers.Main) {
onSetCurrentTask("") onSetCurrentTask("")
@@ -424,9 +425,9 @@ class MqttManager(
} }
"reception" -> { "reception" -> {
speak("接到接待任务", "zh") speak("接到接待任务", "zh")
val location = obj.optString("location", "前台") val location = obj.optString("location", "前台").trim()
val text = obj.optString("text", "你是我要接待的贵宾吗?") val text = obj.optString("text", "你是我要接待的贵宾吗?").trim()
val destination = obj.optString("destination", "会议室") val destination = obj.optString("destination", "会议室").trim()
scope.launch(Dispatchers.Main) { scope.launch(Dispatchers.Main) {
onStartReceptionMode(location, text, destination) onStartReceptionMode(location, text, destination)
} }

View File

@@ -120,14 +120,21 @@ class TaskController(
} }
fun startReceptionMode(location: String, text: String, destination: String) { fun startReceptionMode(location: String, text: String, destination: String) {
val targetLocation = location.trim()
val promptText = text.trim()
val targetDestination = destination.trim()
if (targetLocation.isEmpty()) {
setCurrentTask("")
return
}
setCurrentTask("reception") setCurrentTask("reception")
receptionLocation = location receptionLocation = targetLocation
receptionText = text receptionText = promptText.ifEmpty { "你是我要接待的贵宾吗?" }
receptionDestination = destination receptionDestination = targetDestination
isReceptionPromptVisible = false isReceptionPromptVisible = false
setReceptionButtonVisible(false) setReceptionButtonVisible(false)
if (getLastArrivalLocation() != location) { if (getLastArrivalLocation()?.trim()?.equals(targetLocation, ignoreCase = true) != true) {
navController.goTo(location, false) navController.goTo(targetLocation, false)
} else { } else {
startTaskWaitTimeout() startTaskWaitTimeout()
} }
@@ -177,9 +184,13 @@ class TaskController(
speak("别妨碍我,我正在巡逻呢") speak("别妨碍我,我正在巡逻呢")
return true return true
} }
if (currentTask == "reception" && if (currentTask == "reception") {
getLastArrivalLocation()?.equals(receptionLocation, ignoreCase = true) == true val isAtReceptionLocation = getLastArrivalLocation()?.trim()
) { ?.equals(receptionLocation, ignoreCase = true) == true
if (!isAtReceptionLocation) {
// Not at reception spot yet, let upper layer continue default behavior.
return false
}
when (state) { when (state) {
DETECTED -> { DETECTED -> {
startTaskWaitTimeout() startTaskWaitTimeout()
@@ -194,8 +205,9 @@ class TaskController(
setReceptionButtonVisible(false) setReceptionButtonVisible(false)
} }
} }
return true
} }
return currentTask == "reception" return false
} }
fun endNonSpecialTask(reason: String) { fun endNonSpecialTask(reason: String) {