feat: 添加接待返回工作流支持
- 新增 VR 工作流配置键常量,用于存储接待返回工作流的 ID 和 API 密钥 - 在设置页面同步添加 VR 工作流的清除、获取与保存逻辑 - 重构门控工作流执行函数,使其通用化以支持接待返回工作流 - 当接待任务完成并返回基站时,自动触发接待返回工作流执行
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user