From 005932613e4620b72b0a63e8eb3f00e14b65c21c Mon Sep 17 00:00:00 2001 From: Sucan <632190820@qq.com> Date: Wed, 11 Mar 2026 19:39:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=8E=A5=E5=BE=85?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=92=8CHTTP=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增接待模式:机器人可前往指定位置,检测到人后显示确认按钮 - 添加HttpManager用于执行HTTP工作流,支持Home Base的人员检测触发 - 移除repose监控功能,改用OnReposeStatusChangedListener回调 - 简化界面布局,移除随机表情和说话按钮 - 在AndroidManifest中添加usesCleartextTraffic以允许HTTP通信 --- app/src/main/AndroidManifest.xml | 1 + .../lzwcai_terminal_temi/HttpManager.kt | 71 ++++++++++ .../lzwcai_terminal_temi/MainActivity.kt | 134 +++++++++++++++--- .../lzwcai_terminal_temi/MqttManager.kt | 42 ++---- app/src/main/res/layout/activity_main.xml | 24 +--- 5 files changed, 204 insertions(+), 68 deletions(-) create mode 100644 app/src/main/java/com/example/lzwcai_terminal_temi/HttpManager.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3f065ee..f106cca 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Lzwcaiterminaltemi" + android:usesCleartextTraffic="true" tools:targetApi="31"> -> jsonBody.put("inputs", JSONObject(inputs)) + is List<*> -> jsonBody.put("inputs", JSONArray(inputs)) + is Array<*> -> jsonBody.put("inputs", JSONArray(inputs)) + else -> jsonBody.put("inputs", inputs) + } + + Log.d(TAG, "Request Body: $jsonBody") + + val writer = OutputStreamWriter(connection.outputStream) + writer.write(jsonBody.toString()) + writer.flush() + writer.close() + + val responseCode = connection.responseCode + if (responseCode == HttpURLConnection.HTTP_OK) { + val reader = connection.inputStream.bufferedReader() + result = reader.readText() + reader.close() + Log.i(TAG, "Workflow execute success: $result") + } else { + val errorStream = connection.errorStream + val errorMsg = errorStream?.bufferedReader()?.readText() ?: "Unknown error" + Log.e(TAG, "Workflow execute failed: $responseCode - $errorMsg") + } + connection.disconnect() + } catch (e: Exception) { + Log.e(TAG, "Workflow execute exception", e) + } + return@withContext result + } +} diff --git a/app/src/main/java/com/example/lzwcai_terminal_temi/MainActivity.kt b/app/src/main/java/com/example/lzwcai_terminal_temi/MainActivity.kt index ec8c7d2..323d9a1 100644 --- a/app/src/main/java/com/example/lzwcai_terminal_temi/MainActivity.kt +++ b/app/src/main/java/com/example/lzwcai_terminal_temi/MainActivity.kt @@ -12,14 +12,25 @@ import com.example.lzwcai_terminal_temi.databinding.ActivityMainBinding import com.robotemi.sdk.Robot import com.robotemi.sdk.TtsRequest import com.robotemi.sdk.Robot.TtsListener +import com.robotemi.sdk.listeners.OnDetectionStateChangedListener import com.robotemi.sdk.listeners.OnGoToLocationStatusChangedListener import com.robotemi.sdk.listeners.OnRobotReadyListener +import com.robotemi.sdk.listeners.OnDetectionStateChangedListener.Companion.DETECTED +import com.robotemi.sdk.listeners.OnDetectionStateChangedListener.Companion.IDLE +import com.robotemi.sdk.navigation.listener.OnReposeStatusChangedListener +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.cancel -class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnGoToLocationStatusChangedListener, SharedPreferences.OnSharedPreferenceChangeListener { +class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnGoToLocationStatusChangedListener, + OnDetectionStateChangedListener, OnReposeStatusChangedListener, SharedPreferences.OnSharedPreferenceChangeListener { private lateinit var robot: Robot private lateinit var binding: ActivityMainBinding private var mqttManager: MqttManager? = null + private val mainScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) private lateinit var prefs: SharedPreferences private lateinit var navCon: NavController private var lastArrivalLocation: String? = null @@ -27,6 +38,12 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG private val fixedFaceScale = 1.0f private val baseFaceSizeDp = 1000f + // Reception mode + private var isReceptionMode = false + private var receptionLocation: String = "" + private var receptionText: String = "" + private var receptionDestination: String = "" + @SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -44,16 +61,16 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG startActivity(Intent(this, SettingsActivity::class.java)) } - binding.btnRandomExpression.setOnClickListener { - binding.animatedEmojiView.currentExpression = AnimatedEmojiView.Expression.values().random() - } - - binding.btnSpeak.setOnClickListener { - speakLongSentence() - } - binding.animatedEmojiView.currentExpression = AnimatedEmojiView.Expression.SMILE applyFaceScale(fixedFaceScale) + + binding.btnReception.setOnClickListener { + val destination = receptionDestination + stopReceptionMode() + val ttsRequest = TtsRequest.create("接待任务确认,请跟我来", false, language = TtsRequest.Language.ZH_CN) + robot.speak(ttsRequest) + navCon.goTo(destination, false) + } updateMqttConnection() } @@ -63,6 +80,8 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG robot.addOnRobotReadyListener(this) robot.addTtsListener(this) robot.addOnGoToLocationStatusChangedListener(this) + robot.addOnDetectionStateChangedListener(this) + robot.addOnReposeStatusChangedListener(this) prefs.registerOnSharedPreferenceChangeListener(this) mqttManager?.connect() } @@ -72,6 +91,8 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG robot.removeOnRobotReadyListener(this) robot.removeTtsListener(this) robot.removeOnGoToLocationStatusChangedListener(this) + robot.removeOnDetectionStateChangedListener(this) + robot.removeOnReposeStatusChangedListener(this) prefs.unregisterOnSharedPreferenceChangeListener(this) mqttManager?.disconnect() } @@ -80,6 +101,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG super.onDestroy() mqttManager?.disconnect() LogManager.stopLogcatListener() + mainScope.cancel() Log.i("MainActivity", "All resources released on destroy.") } @@ -89,16 +111,8 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG } } - private fun speakLongSentence() { - val longSentence = "你好,我是一个智能机器人。我很高兴能为您服务。现在,我将为您展示我的各种表情和语音能力。希望您喜欢!" - val ttsRequest = TtsRequest.create(longSentence, false, language = TtsRequest.Language.ZH_CN) - robot.speak(ttsRequest) - } - override fun onTtsStatusChanged(ttsRequest: TtsRequest) { - // Forward TTS status to MqttManager for stream queue handling mqttManager?.handleTtsStatusChange(ttsRequest) - when (ttsRequest.status) { TtsRequest.Status.STARTED -> { Log.i("MainActivity", "TTS started: ${ttsRequest.speech}") @@ -137,6 +151,92 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG Log.i("MainActivity", "Arrived at $location, announcement sent.") } + override fun onDetectionStateChanged(state: Int) { + // Reception mode logic + if (isReceptionMode && lastArrivalLocation == receptionLocation) { + when (state) { + DETECTED -> { + if (binding.btnReception.visibility != android.view.View.VISIBLE) { + binding.btnReception.visibility = android.view.View.VISIBLE + val ttsRequest = TtsRequest.create(receptionText, false, language = TtsRequest.Language.ZH_CN) + robot.speak(ttsRequest) + Log.i("MainActivity", "Reception: Person detected (new session) at $receptionLocation") + } + } + IDLE -> { + binding.btnReception.visibility = android.view.View.GONE + Log.i("MainActivity", "Reception: Person left (IDLE)") + } + } + } + + // Home Base logic + if (lastArrivalLocation?.lowercase() == "home base") { + when (state) { + DETECTED -> { + mainScope.launch { + HttpManager.workflow_execute( + context = this@MainActivity, + apiKey = "wf_865e80f5fc1a4a319474a21d47470863", + workflowId = "2031297462423851009", + inputs = emptyMap() + ) + } + } + IDLE -> { + mainScope.launch { + HttpManager.workflow_execute( + context = this@MainActivity, + apiKey = "wf_c02aa853371345dbb29572641d083c24", + workflowId = "2031634633458520065", + inputs = emptyMap() + ) + } + } + } + } + } + + fun startReceptionMode(location: String, text: String, destination: String) { + isReceptionMode = true + receptionLocation = location + receptionText = text + receptionDestination = destination + Log.i("MainActivity", "Reception mode started: location=$location, text=$text, dest=$destination") + if (lastArrivalLocation != location) { + navCon.goTo(location, false) + } + } + + private fun stopReceptionMode() { + isReceptionMode = false + receptionLocation = "" + receptionText = "" + receptionDestination = "" + binding.btnReception.visibility = android.view.View.GONE + Log.i("MainActivity", "Reception mode stopped") + } + + override fun onReposeStatusChanged(status: Int, description: String) { + when (status) { + OnReposeStatusChangedListener.REPOSING_COMPLETE -> { + val ttsRequest = TtsRequest.create("重新定位成功", false, language = TtsRequest.Language.ZH_CN) + robot.speak(ttsRequest) + Log.i("MainActivity", "Repose complete") + } + OnReposeStatusChangedListener.REPOSING_ABORT -> { + val ttsRequest = TtsRequest.create("重新定位被中断", false, language = TtsRequest.Language.ZH_CN) + robot.speak(ttsRequest) + Log.w("MainActivity", "Repose aborted") + } + OnReposeStatusChangedListener.REPOSING_START -> { + val ttsRequest = TtsRequest.create("正在进行重新定位", false, language = TtsRequest.Language.ZH_CN) + robot.speak(ttsRequest) + Log.i("MainActivity", "Repose started") + } + } + } + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { if (key == "network_ip") { Log.i("MainActivity", "IP address changed, re-initializing MQTT connection.") diff --git a/app/src/main/java/com/example/lzwcai_terminal_temi/MqttManager.kt b/app/src/main/java/com/example/lzwcai_terminal_temi/MqttManager.kt index b7fa85b..5de334d 100644 --- a/app/src/main/java/com/example/lzwcai_terminal_temi/MqttManager.kt +++ b/app/src/main/java/com/example/lzwcai_terminal_temi/MqttManager.kt @@ -97,7 +97,6 @@ class MqttManager( } fun disconnect() { - robot.removeTtsListener(this) scope.launch { try { reconnectJob?.cancel() @@ -178,9 +177,7 @@ class MqttManager( } "repose" -> { val ok = navController.repose() - speak("正在进行重新定位") Log.i(TAG, "Repose command sent: $ok") - monitorReposeStatus() } "stop" -> { navController.stop() @@ -189,6 +186,12 @@ class MqttManager( "patrol" -> { navController.randomPatrol() } + "reception" -> { + val location = obj.optString("location", "前台") + val text = obj.optString("text", "你是我要接待的贵宾吗?") + val destination = obj.optString("destination", "会议室") + (context as? MainActivity)?.startReceptionMode(location, text, destination) + } else -> Log.w(TAG, "Unknown command action: $action") } } @@ -238,35 +241,6 @@ class MqttManager( } } - private fun monitorReposeStatus() { - scope.launch { - Log.i(TAG, "Starting repose monitoring...") - val timeout = 30000L - val startTime = System.currentTimeMillis() - var lastStatus: String? = null - - while (System.currentTimeMillis() - startTime < timeout) { - delay(1000L) - val status = robot.reposeStatus.toString().uppercase() - - if (status != lastStatus) { - Log.i(TAG, "Repose status: $status") - lastStatus = status - } - - if (status == "COMPLETE") { - speak("重新定位成功", null) - return@launch - } else if (status == "FAILURE" || status == "ABORTED") { - speak("重新定位失败", null) - return@launch - } - } - Log.w(TAG, "Repose monitoring timed out.") - speak("重新定位超时", null) - } - } - private fun goTo(location: String, backwards: Boolean = false) { val target = location.trim() if (target.isEmpty()) { @@ -298,7 +272,7 @@ class MqttManager( } } - override fun handleTtsStatusChange(ttsRequest: TtsRequest) { + fun handleTtsStatusChange(ttsRequest: TtsRequest) { scope.launch(Dispatchers.Main) { when (ttsRequest.status) { TtsRequest.Status.STARTED -> { @@ -307,7 +281,7 @@ class MqttManager( TtsRequest.Status.COMPLETED, TtsRequest.Status.CANCELED, TtsRequest.Status.ERROR, - TtsRequest.Status.ABORTED -> { + TtsRequest.Status.NOT_ALLOWED -> { isTtsBusy = false processNextTts() } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 74761e0..a8516f1 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -22,26 +22,16 @@ android:layout_height="500dp" android:layout_centerInParent="true" /> - - -