feat: 添加接待返回工作流支持

- 新增 VR 工作流配置键常量,用于存储接待返回工作流的 ID 和 API 密钥
- 在设置页面同步添加 VR 工作流的清除、获取与保存逻辑
- 重构门控工作流执行函数,使其通用化以支持接待返回工作流
- 当接待任务完成并返回基站时,自动触发接待返回工作流执行
This commit is contained in:
2026-04-21 12:50:02 +08:00
parent d5ca5966f4
commit 54b762abbf
3 changed files with 60 additions and 4 deletions

View File

@@ -25,6 +25,8 @@ object HttpManager {
const val PREF_KEY_OD_WF_KEY = "od_wf_key"
const val PREF_KEY_CD_WFID = "cd_wfid"
const val PREF_KEY_CD_WF_KEY = "cd_wf_key"
const val PREF_KEY_VR_WFID = "vr_wfid"
const val PREF_KEY_VR_WF_KEY = "vr_wf_key"
fun getBaseUrl(context: Context): String {
val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
@@ -98,6 +100,8 @@ object HttpManager {
.put(PREF_KEY_OD_WF_KEY)
.put(PREF_KEY_CD_WFID)
.put(PREF_KEY_CD_WF_KEY)
.put(PREF_KEY_VR_WFID)
.put(PREF_KEY_VR_WF_KEY)
.put(PREF_KEY_MQTT_PASSWORD)
val response = postJsonArray(context, "/system/config/getConfig", body, token)
if (response == null) {

View File

@@ -45,6 +45,9 @@ import kotlinx.coroutines.isActive
import kotlin.random.Random
import org.json.JSONObject
import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
@@ -99,6 +102,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
private var autoRechargeJob: Job? = null
private var latestYaw: Float? = null
private var receptionAnchorYaw: Float? = null
private var pendingReceptionReturnWorkflow: Boolean = false
private var lastWorkflowConfigRefreshAt: Long = 0L
private lateinit var telemetryManager: TelemetryManager
private lateinit var taskController: TaskController
@@ -232,6 +236,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
if (destination.isNullOrBlank()) {
return@setOnClickListener
}
pendingReceptionReturnWorkflow = true
val ttsRequest = TtsRequest.create("接待任务确认,请跟我来", false, language = TtsRequest.Language.ZH_CN)
robot.speak(ttsRequest)
navCon.goTo(destination, false)
@@ -404,6 +409,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
prefs.edit().putString("current_location", location).apply()
if (robotEventHandler.normalizeLocation(location) == "homebase") {
navCon.tiltAngle(20)
triggerReceptionReturnWorkflowIfNeeded(location)
}
if (taskController.currentTask == "patrol") {
taskController.handlePatrolArrival(location)
@@ -801,6 +807,16 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
private suspend fun executeDoorWorkflow(openDoor: Boolean): String? {
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 workflowName = if (openDoor) "open-door" else "close-door"
return executeConfiguredWorkflow(workflowIdKey, workflowApiKey, workflowName)
}
private suspend fun executeConfiguredWorkflow(
workflowIdKey: String,
workflowApiKey: String,
workflowName: String,
inputs: Any = emptyMap<String, Any>()
): String? {
var workflowId = prefs.getString(workflowIdKey, "").orEmpty().trim()
var apiKey = prefs.getString(workflowApiKey, "").orEmpty().trim()
if (workflowId.isEmpty() || apiKey.isEmpty()) {
@@ -811,7 +827,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
if (workflowId.isEmpty() || apiKey.isEmpty()) {
Log.w(
"MainActivity",
"Door workflow config missing after refresh: openDoor=$openDoor, " +
"Workflow config missing after refresh: workflow=$workflowName, " +
"workflowIdKey=$workflowIdKey, workflowApiKey=$workflowApiKey"
)
return null
@@ -820,10 +836,33 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
context = this@MainActivity,
apiKey = apiKey,
workflowId = workflowId,
inputs = emptyMap<String, Any>()
inputs = inputs
)
}
private fun triggerReceptionReturnWorkflowIfNeeded(location: String) {
if (!pendingReceptionReturnWorkflow) {
return
}
if (robotEventHandler.normalizeLocation(location) != "homebase") {
return
}
pendingReceptionReturnWorkflow = false
mainScope.launch {
val nowText = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
val inputs = mapOf("flag" to nowText)
val result = executeConfiguredWorkflow(
workflowIdKey = HttpManager.PREF_KEY_VR_WFID,
workflowApiKey = HttpManager.PREF_KEY_VR_WF_KEY,
workflowName = "reception-return-home",
inputs = inputs
)
if (result == null) {
showNetworkErrorBanner()
}
}
}
private suspend fun refreshWorkflowConfigsIfNeeded() {
val now = System.currentTimeMillis()
if (now - lastWorkflowConfigRefreshAt < 5000L) {
@@ -835,7 +874,9 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
HttpManager.PREF_KEY_OD_WFID,
HttpManager.PREF_KEY_OD_WF_KEY,
HttpManager.PREF_KEY_CD_WFID,
HttpManager.PREF_KEY_CD_WF_KEY
HttpManager.PREF_KEY_CD_WF_KEY,
HttpManager.PREF_KEY_VR_WFID,
HttpManager.PREF_KEY_VR_WF_KEY
)
val editor = prefs.edit()
var changed = false

View File

@@ -103,6 +103,8 @@ class SettingsActivity : AppCompatActivity() {
.remove(HttpManager.PREF_KEY_OD_WF_KEY)
.remove(HttpManager.PREF_KEY_CD_WFID)
.remove(HttpManager.PREF_KEY_CD_WF_KEY)
.remove(HttpManager.PREF_KEY_VR_WFID)
.remove(HttpManager.PREF_KEY_VR_WF_KEY)
binding.etActivationCode.setText("")
binding.etDeviceName.setText("")
updateActivationUi(false)
@@ -154,8 +156,15 @@ class SettingsActivity : AppCompatActivity() {
val odWfKey = runtimeConfigs?.get(HttpManager.PREF_KEY_OD_WF_KEY).orEmpty()
val cdWfid = runtimeConfigs?.get(HttpManager.PREF_KEY_CD_WFID).orEmpty()
val cdWfKey = runtimeConfigs?.get(HttpManager.PREF_KEY_CD_WF_KEY).orEmpty()
val vrWfid = runtimeConfigs?.get(HttpManager.PREF_KEY_VR_WFID).orEmpty()
val vrWfKey = runtimeConfigs?.get(HttpManager.PREF_KEY_VR_WF_KEY).orEmpty()
val mqttReady = mqttUser.isNotBlank() && mqttPass.isNotBlank()
val workflowReady = odWfid.isNotBlank() && odWfKey.isNotBlank() && cdWfid.isNotBlank() && cdWfKey.isNotBlank()
val workflowReady = odWfid.isNotBlank() &&
odWfKey.isNotBlank() &&
cdWfid.isNotBlank() &&
cdWfKey.isNotBlank() &&
vrWfid.isNotBlank() &&
vrWfKey.isNotBlank()
val configReady = mqttReady && workflowReady
val editor = prefs.edit()
.putString(HttpManager.PREF_KEY_ACTIVATION_CODE, activationCode)
@@ -168,6 +177,8 @@ class SettingsActivity : AppCompatActivity() {
.putString(HttpManager.PREF_KEY_OD_WF_KEY, odWfKey)
.putString(HttpManager.PREF_KEY_CD_WFID, cdWfid)
.putString(HttpManager.PREF_KEY_CD_WF_KEY, cdWfKey)
.putString(HttpManager.PREF_KEY_VR_WFID, vrWfid)
.putString(HttpManager.PREF_KEY_VR_WF_KEY, vrWfKey)
editor.apply()
updateActivationUi(true)
if (!configReady) {