[6.1.0][feat]新增平行驾驶状态View
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
package com.mogo.eagle.core.function.hmi.ui.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.commons.voice.AIAssist
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotActionsListener
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoParallelDrivingStatusListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotActionsListenerManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotActionsListenerManager.getUnableAutopilotReasons
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerParallelDrivingListenerManager
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.zhjt.mogo.adas.data.bean.UnableAutopilotReason
|
||||
import com.zhjt.mogo.adas.data.bean.UnableAutopilotReason.SourceType
|
||||
import mogo.yycp.paralleldriving.protocol.ParallelDrivingRequest.ParallelRequest
|
||||
import mogo.yycp.paralleldriving.protocol.ParallelTaskProcessNoticeOuterClass
|
||||
|
||||
/**
|
||||
* 平行驾驶状态View
|
||||
*/
|
||||
class ParallelDriveView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoAutopilotStatusListener,
|
||||
IMoGoAutopilotActionsListener, IMoGoParallelDrivingStatusListener {
|
||||
companion object {
|
||||
private const val TAG = "ParallelDriveView"
|
||||
private const val APP_REQUESTING = 1
|
||||
private const val AD_REQUESTING = 2
|
||||
private const val SYNCHRONIZING = 3
|
||||
private const val PARALLEL_DRIVING = 4
|
||||
private const val FAILURE = 5
|
||||
private const val ONE_EXCEPTION = 6
|
||||
private const val TWO_EXCEPTION = 7
|
||||
private const val UNAVAILABLE = 8
|
||||
}
|
||||
|
||||
//1:ready, 2:自动驾驶中, 7:平行驾驶中
|
||||
@Volatile
|
||||
private var autopilotState: Int = 1
|
||||
|
||||
// 初始状态为0
|
||||
private var state: Int = 0
|
||||
|
||||
private lateinit var rootLayout: ConstraintLayout
|
||||
private lateinit var statusIcon: ImageView
|
||||
private lateinit var statusTitle: TextView
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_parallel_drive, this, true)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
initView()
|
||||
CallerAutoPilotStatusListenerManager.addListener(TAG, this)
|
||||
CallerAutopilotActionsListenerManager.addListener(TAG, this)
|
||||
CallerParallelDrivingListenerManager.addListener(TAG, this)
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
rootLayout = findViewById(R.id.parDriveLayout)
|
||||
statusIcon = findViewById(R.id.ivStatusIcon)
|
||||
statusTitle = findViewById(R.id.tvAutopilotContent)
|
||||
rootLayout.setOnClickListener {
|
||||
when (state) {
|
||||
0 -> {
|
||||
state = APP_REQUESTING
|
||||
updateUI(APP_REQUESTING)
|
||||
reqParaDrive()
|
||||
}
|
||||
APP_REQUESTING -> {
|
||||
cancelParaDrive()
|
||||
ToastUtils.showShort("请求已取消!")
|
||||
checkAvailableAndUpdateUI()
|
||||
}
|
||||
UNAVAILABLE -> {
|
||||
ToastUtils.showShort("请P档驻车并松开油门刹车后请求")
|
||||
}
|
||||
}
|
||||
}
|
||||
checkAvailableAndUpdateUI()
|
||||
}
|
||||
|
||||
override fun onAutopilotStatusResponse(state: Int) {
|
||||
super.onAutopilotStatusResponse(state)
|
||||
if (state != autopilotState) {
|
||||
synchronized(this) {
|
||||
when (state) {
|
||||
7 -> {
|
||||
if (this.autopilotState != 7) {
|
||||
ThreadUtils.runOnUiThread({
|
||||
updateUI(PARALLEL_DRIVING)
|
||||
}, ThreadUtils.MODE.QUEUE)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (this.autopilotState == 7 && this.autopilotState != state) {
|
||||
ThreadUtils.runOnUiThread({
|
||||
checkAvailableAndUpdateUI()
|
||||
}, ThreadUtils.MODE.QUEUE)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.autopilotState = state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAutopilotAbility(
|
||||
isAutopilotAbility: Boolean,
|
||||
unableAutopilotReasons: ArrayList<UnableAutopilotReason>?
|
||||
) {
|
||||
// 是否可平行驾驶
|
||||
val isAvailable = isAvailable(unableAutopilotReasons)
|
||||
if (!isAvailable) {
|
||||
ThreadUtils.runOnUiThread({
|
||||
updateUI(UNAVAILABLE)
|
||||
}, ThreadUtils.MODE.QUEUE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onParallelDrivingResp(parallelTaskProcessNotice: ParallelTaskProcessNoticeOuterClass.ParallelTaskProcessNotice?) {
|
||||
parallelTaskProcessNotice?.let {
|
||||
ThreadUtils.runOnUiThread({
|
||||
when (it.code) {
|
||||
"START_SYNC" -> {// 同步中
|
||||
state = SYNCHRONIZING
|
||||
updateUI(SYNCHRONIZING)
|
||||
}
|
||||
"EXCEPTION_EXIT_SYNC" -> {// 同步异常结束
|
||||
state = ONE_EXCEPTION
|
||||
updateUI(ONE_EXCEPTION)
|
||||
}
|
||||
"TASK_REJECTED" -> {// 任务已被拒绝
|
||||
state = FAILURE
|
||||
updateUI(FAILURE)
|
||||
AIAssist.getInstance(context).speakTTSVoice("请求已被拒绝")
|
||||
}
|
||||
"PARALLEL_EXCEPTION_MANUAL_DRIVING" -> {// 异常请人工驾驶
|
||||
state = TWO_EXCEPTION
|
||||
updateUI(TWO_EXCEPTION)
|
||||
}
|
||||
"EXCEPTION_EXIT_PARALLEL_DRIVING" -> {// 平行驾驶异常结束
|
||||
state = ONE_EXCEPTION
|
||||
updateUI(ONE_EXCEPTION)
|
||||
}
|
||||
"EXIT_SYNC" -> {// 同步结束
|
||||
checkAvailableAndUpdateUI()
|
||||
}
|
||||
"UNABLE_TAKEOVER" -> {// 无法接管
|
||||
state = ONE_EXCEPTION
|
||||
updateUI(ONE_EXCEPTION)
|
||||
}
|
||||
"xxx" -> {// 请求中
|
||||
state = AD_REQUESTING
|
||||
updateUI(AD_REQUESTING)
|
||||
}
|
||||
}
|
||||
}, ThreadUtils.MODE.QUEUE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAvailable(unableAutopilotReasons: ArrayList<UnableAutopilotReason>?): Boolean {
|
||||
var unavailable = false
|
||||
unableAutopilotReasons?.forEach {
|
||||
if (it.source.ordinal == SourceType.CHASSIS.ordinal) {
|
||||
unavailable = true
|
||||
}
|
||||
}
|
||||
return !unavailable
|
||||
}
|
||||
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private fun updateUI(state: Int) {
|
||||
when (state) {
|
||||
0 -> {
|
||||
rootLayout.isEnabled = true
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_autopilot_status, null)
|
||||
statusTitle.text = context.getString(R.string.parallel_drive)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
}
|
||||
|
||||
APP_REQUESTING -> {
|
||||
rootLayout.isEnabled = true
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_para_requesting, null)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
statusTitle.text = context.getString(R.string.parallel_drive_requesting)
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
}
|
||||
|
||||
AD_REQUESTING -> {
|
||||
rootLayout.isEnabled = false
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_para_requesting, null)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
statusTitle.text = context.getString(R.string.parallel_drive_requesting)
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
}
|
||||
|
||||
SYNCHRONIZING -> {
|
||||
rootLayout.isEnabled = false
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_para_syn, null)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
statusTitle.text = context.getString(R.string.parallel_drive_synchronizing)
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
}
|
||||
|
||||
PARALLEL_DRIVING -> {
|
||||
rootLayout.isEnabled = false
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_autopilot_status, null)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
rootLayout.background =
|
||||
resources.getDrawable(R.drawable.bg_auto_pilot_running, null)
|
||||
statusTitle.text = context.getString(R.string.parallel_drive)
|
||||
}
|
||||
|
||||
FAILURE -> {
|
||||
rootLayout.isEnabled = false
|
||||
rootLayout.postDelayed({
|
||||
checkAvailableAndUpdateUI()
|
||||
}, 1000)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_fail_start, null)
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
statusTitle.text = context.getString(R.string.parallel_drive_failure)
|
||||
}
|
||||
|
||||
ONE_EXCEPTION -> {
|
||||
rootLayout.isEnabled = false
|
||||
rootLayout.postDelayed({
|
||||
checkAvailableAndUpdateUI()
|
||||
}, 1000)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_fail_start, null)
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
statusTitle.text = context.getString(R.string.parallel_drive_exception)
|
||||
}
|
||||
|
||||
TWO_EXCEPTION -> {
|
||||
rootLayout.isEnabled = false
|
||||
rootLayout.postDelayed({
|
||||
checkAvailableAndUpdateUI()
|
||||
}, 2000)
|
||||
statusTitle.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
statusIcon.imageAlpha = 255
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_fail_start, null)
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
statusTitle.text = context.getString(R.string.parallel_drive_exception)
|
||||
}
|
||||
|
||||
UNAVAILABLE -> {
|
||||
rootLayout.isEnabled = false
|
||||
statusIcon.background =
|
||||
resources.getDrawable(R.drawable.icon_autopilot_status, null)
|
||||
statusTitle.setTextColor(Color.parseColor("#66FFFFFF"))
|
||||
statusIcon.imageAlpha = 102
|
||||
rootLayout.background = resources.getDrawable(R.drawable.bg_auto_pilot, null)
|
||||
statusTitle.text = context.getString(R.string.parallel_drive)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reqParaDrive() {
|
||||
val sn = MoGoAiCloudClientConfig.getInstance().sn
|
||||
val parallelRequest = ParallelRequest.newBuilder()
|
||||
.setSn(sn)
|
||||
.setType(2)// 2:鹰眼请求
|
||||
.setTakeover(1)// 1:请求平行驾驶接管
|
||||
.setCode("PAD_ACTIVE")
|
||||
parallelRequest.reason = "鹰眼请求"
|
||||
CallerAutoPilotControlManager.sendParallelDrivingReq(
|
||||
System.currentTimeMillis().toString(), parallelRequest.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun cancelParaDrive() {
|
||||
val sn = MoGoAiCloudClientConfig.getInstance().sn
|
||||
val parallelRequest = ParallelRequest.newBuilder()
|
||||
.setSn(sn)
|
||||
.setType(2)// 2:鹰眼请求
|
||||
.setTakeover(2)// 2:取消平行驾驶接管
|
||||
.setCode("PAD_ACTIVE")
|
||||
parallelRequest.reason = "鹰眼请求"
|
||||
CallerAutoPilotControlManager.sendParallelDrivingReq(
|
||||
System.currentTimeMillis().toString(), parallelRequest.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkAvailableAndUpdateUI() {
|
||||
if (isAvailable(getUnableAutopilotReasons())) {
|
||||
state = 0
|
||||
updateUI(0)
|
||||
} else {
|
||||
state = UNAVAILABLE
|
||||
updateUI(UNAVAILABLE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerAutoPilotStatusListenerManager.removeListener(TAG)
|
||||
CallerAutopilotActionsListenerManager.removeListener(TAG)
|
||||
CallerParallelDrivingListenerManager.removeListener(TAG)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/parDriveLayout"
|
||||
android:layout_width="361dp"
|
||||
android:layout_height="180dp"
|
||||
android:background="@drawable/bg_auto_pilot"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivStatusIcon"
|
||||
android:layout_width="58dp"
|
||||
android:layout_height="58dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginStart="72dp"
|
||||
android:layout_marginTop="56dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAutopilotContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginEnd="72dp"
|
||||
android:layout_marginTop="60dp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="36sp"
|
||||
tools:text="远程代驾"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -86,4 +86,9 @@
|
||||
<string name="light_source_ai_cloud">云端下发</string>
|
||||
<string name="light_source_perception">自车感知</string>
|
||||
<string name="light_source_obu">\u2000OBU\u2000</string>
|
||||
<string name="parallel_drive">远程代驾</string>
|
||||
<string name="parallel_drive_requesting">请求中...</string>
|
||||
<string name="parallel_drive_synchronizing">同步中...</string>
|
||||
<string name="parallel_drive_failure">请求失败</string>
|
||||
<string name="parallel_drive_exception">异常</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user