diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ParallelDriveView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ParallelDriveView.kt new file mode 100644 index 0000000000..ac38c8e368 --- /dev/null +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ParallelDriveView.kt @@ -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? + ) { + // 是否可平行驾驶 + 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?): 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) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/bg_auto_pilot.png b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/bg_auto_pilot.png new file mode 100644 index 0000000000..352bbb650c Binary files /dev/null and b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/bg_auto_pilot.png differ diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/bg_auto_pilot_running.png b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/bg_auto_pilot_running.png new file mode 100644 index 0000000000..7e1d09125e Binary files /dev/null and b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/bg_auto_pilot_running.png differ diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_parallel_drive.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_parallel_drive.xml new file mode 100644 index 0000000000..e6df3a531d --- /dev/null +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_parallel_drive.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml index d994155d5b..f47fcdb292 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml @@ -86,4 +86,9 @@ 云端下发 自车感知 \u2000OBU\u2000 + 远程代驾 + 请求中... + 同步中... + 请求失败 + 异常 diff --git a/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_fail_start.png b/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_fail_start.png new file mode 100644 index 0000000000..6f9f1889b0 Binary files /dev/null and b/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_fail_start.png differ diff --git a/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_para_requesting.png b/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_para_requesting.png new file mode 100644 index 0000000000..fe8881797d Binary files /dev/null and b/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_para_requesting.png differ diff --git a/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_para_syn.png b/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_para_syn.png new file mode 100644 index 0000000000..059f2f3fae Binary files /dev/null and b/core/mogo-core-res/src/main/function-hmi-res/drawable-xhdpi/icon_para_syn.png differ