diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseOchBusTabFragment.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseOchBusTabFragment.java
index fe02bfef81..c881ebcc7d 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseOchBusTabFragment.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseOchBusTabFragment.java
@@ -3,6 +3,7 @@ package com.mogo.och.bus.fragment;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.graphics.Color;
+import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -13,6 +14,8 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.Group;
import com.mogo.commons.AbsMogoApplication;
@@ -21,8 +24,15 @@ import com.mogo.commons.mvp.IView;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.commons.mvp.Presenter;
import com.mogo.commons.voice.AIAssist;
+import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult;
+import com.mogo.eagle.core.data.autopilot.AutopilotWarnMessage;
+import com.mogo.eagle.core.data.config.HmiBuildConfig;
+import com.mogo.eagle.core.data.traffic.TrafficData;
+import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
+import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager;
+import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
@@ -35,6 +45,8 @@ import com.mogo.och.bus.R;
import com.mogo.och.bus.view.BusArcView;
import com.mogo.och.bus.view.SlidePanelView;
+import java.util.ArrayList;
+
/**
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
*
@@ -42,7 +54,7 @@ import com.mogo.och.bus.view.SlidePanelView;
*
* @author tongchenfei
*/
-public abstract class BaseOchBusTabFragment> extends MvpFragment implements IMogoMapListener {
+public abstract class BaseOchBusTabFragment> extends MvpFragment implements IMogoMapListener, IMoGoAutopilotIdentifyListener {
private static final String TAG = "BaseOchFragment";
@@ -200,17 +212,45 @@ public abstract class BaseOchBusTabFragment { // onShow()
- return mBadcaseBtn; },
- () -> { // onHide()
- return null; });
+// CallerHmiManager.INSTANCE.registerBadCaseCallback(
+// () -> { // onShow()
+// return mBadcaseBtn; },
+// () -> { // onHide()
+// return null; });
+ if (mBadcaseBtn != null) {
+ CallerDevaToolsManager.INSTANCE.initBadCase(mBadcaseBtn, null, null);
+ if (!HmiBuildConfig.isShowBadCaseView) {
+ CallerAutopilotIdentifyListenerManager.INSTANCE.addListener(TAG, this);
+ }
+ }
//设置升级小红点提示 默认隐藏
mUpgradeTipIv = findViewById(R.id.module_och_bus_upgrade_red_tip);
CallerHmiManager.INSTANCE.registerUpgradeTipsCallback(() -> mUpgradeTipIv);
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (!HmiBuildConfig.isShowBadCaseView) {
+ CallerAutopilotIdentifyListenerManager.INSTANCE.removeListener(TAG);
+ }
+ }
+
+
+ @Override
+ public void onAutopilotRecordResult(@Nullable AutoPilotRecordResult record) {
+ if (!HmiBuildConfig.isShowBadCaseView && record != null && record.getType() == 1 && record.getStat() == 100) {
+ CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(record);
+ }
+ }
+
+ @Override
+ public void onAutopilotIdentifyDataUpdate(@Nullable ArrayList trafficData) { }
+
+ @Override
+ public void onAutopilotWarnMessage(@Nullable AutopilotWarnMessage autopilotWarnMessage) { }
+
/**
* 测试到站
*/
@@ -367,11 +407,6 @@ public abstract class BaseOchBusTabFragment> extends MvpFragment implements IMogoMapListener {
+public abstract class BaseOchTaxiTabFragment> extends MvpFragment implements IMogoMapListener, IMoGoAutopilotIdentifyListener {
private static final String TAG = "BaseOchFragment";
private LinearLayout ctvAutopilotStatus;
@@ -133,12 +145,18 @@ public abstract class BaseOchTaxiTabFragment { // onShow()
- return mBadcaseBtn; },
- () -> { // onHide()
- return null; });
+// CallerHmiManager.INSTANCE.registerBadCaseCallback(
+// () -> { // onShow()
+// return mBadcaseBtn; },
+// () -> { // onHide()
+// return null; });
+ if (mBadcaseBtn != null) {
+ CallerDevaToolsManager.INSTANCE.initBadCase(mBadcaseBtn, null, null);
+ if (!HmiBuildConfig.isShowBadCaseView) {
+ CallerAutopilotIdentifyListenerManager.INSTANCE.addListener(TAG, this);
+ }
+ }
//设置升级小红点提示 默认隐藏
mUpgradeTipIv = findViewById(R.id.module_och_taxi_upgrade_red_tip);
CallerHmiManager.INSTANCE.registerUpgradeTipsCallback(() -> mUpgradeTipIv);
@@ -240,6 +258,29 @@ public abstract class BaseOchTaxiTabFragment trafficData) { }
+
+ @Override
+ public void onAutopilotRecordResult(@Nullable AutoPilotRecordResult record) {
+ if (!HmiBuildConfig.isShowBadCaseView && record != null && record.getType() == 1 && record.getStat() == 100) {
+ CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(record);
+ }
+ }
+
+ @Override
+ public void onAutopilotWarnMessage(@Nullable AutopilotWarnMessage autopilotWarnMessage) { }
+
public void showNotice(String notice) {
getActivity().runOnUiThread(() -> {
AIAssist.getInstance(getContext()).speakTTSVoice(notice);
@@ -409,11 +450,6 @@ public abstract class BaseOchTaxiTabFragment
- val executor = Executors.newSingleThreadScheduledExecutor()
- executor.scheduleAtFixedRate({
- var find =
- itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
- while (find == null) {
- find =
- itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
-
- }
- while (!find.isResumed) {
- Thread.sleep(500)
- }
- it.resumeWith(Result.success(find))
- try {
- Thread.sleep(500)
- executor.shutdownNow()
- } catch (e: Throwable) {
- e.printStackTrace()
- }
- }, 50, 500, TimeUnit.MILLISECONDS)
- }
- }
}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/build.gradle b/core/function-impl/mogo-core-function-devatools/build.gradle
index 56c8d2e062..9874e99d32 100644
--- a/core/function-impl/mogo-core-function-devatools/build.gradle
+++ b/core/function-impl/mogo-core-function-devatools/build.gradle
@@ -4,6 +4,7 @@ plugins {
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'com.alibaba.arouter'
+ id 'com.google.protobuf'
}
android {
@@ -39,21 +40,45 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
+ kotlinOptions {
+ jvmTarget = "1.8"
+ freeCompilerArgs += [
+ "-Xopt-in=kotlin.RequiresOptIn"
+ ]
+ }
+ protobuf {
+ protoc {
+ artifact = rootProject.ext.dependencies.google_protoc
+ }
+ generateProtoTasks {
+ all().each { task ->
+ task.builtins {
+ java {}
+ }
+ }
+ }
+ }
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation rootProject.ext.dependencies.kotlinstdlibjdk7
- implementation rootProject.ext.dependencies.coroutinescore
implementation rootProject.ext.dependencies.arouter
kapt rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.mogologlib
implementation rootProject.ext.dependencies.mogochainbase
+ kapt rootProject.ext.dependencies.androidxroomcompiler
+ implementation rootProject.ext.dependencies.androidxroomruntime
+ implementation rootProject.ext.dependencies.androidxroomktx
+ implementation rootProject.ext.dependencies.androidx_datastore
+ implementation rootProject.ext.dependencies.google_proto_java
+ implementation rootProject.ext.dependencies.androidxappcompat
+ implementation rootProject.ext.dependencies.androidxconstraintlayout
+ implementation rootProject.ext.dependencies.androidxrecyclerview
+
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
implementation rootProject.ext.dependencies.mogoserviceapi
implementation rootProject.ext.dependencies.modulecommon
-
implementation rootProject.ext.dependencies.mogo_core_utils
implementation rootProject.ext.dependencies.mogo_core_function_api
implementation rootProject.ext.dependencies.mogo_core_function_call
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt
index faa6260712..6b2c12162b 100644
--- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt
@@ -2,8 +2,10 @@ package com.zhjt.mogo_core_function_devatools
import android.annotation.SuppressLint
import android.content.Context
+import android.view.View
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
+import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_ADAS_INIT
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_ADAS_MSG
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CONNECT_STATUS
@@ -18,6 +20,7 @@ import com.mogo.eagle.core.utilcode.util.DeviceUtils
import com.mogo.eagle.core.utilcode.util.Utils
import com.zhidao.loglib.fw.FileWriteManager
import com.zhidao.loglib.fw.FwBuild
+import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchManager
import com.zhjt.service.chain.core.ChainTraceStarter
@@ -100,6 +103,14 @@ class DevaToolsProvider : IDevaToolsProvider {
FileWriteManager.getInstance().operateChainMap(fwBuildMap)
}
+ override fun initBadCase(view: View, onShow: (() -> Unit)?, onHide: (() -> Unit)?) {
+ BadCaseManager.init(view, onShow, onHide)
+ }
+
+ override fun onReceiveBadCaseRecord(record: AutoPilotRecordResult) {
+ BadCaseManager.onReceiveBadCaseRecord(record)
+ }
+
override fun onDestroy() {
MogoLogCatchManager.onDestroy()
}
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt
new file mode 100644
index 0000000000..922bf86078
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt
@@ -0,0 +1,281 @@
+package com.zhjt.mogo_core_function_devatools.badcase
+
+import android.transition.AutoTransition
+import android.transition.TransitionManager
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import androidx.lifecycle.Lifecycle.Event
+import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
+import androidx.lifecycle.LifecycleCoroutineScope
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import com.mogo.cloud.passport.MoGoAiCloudClientConfig
+import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
+import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
+import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner
+import com.mogo.eagle.core.utilcode.kotlin.onClick
+import com.mogo.eagle.core.utilcode.util.ToastUtils
+import com.mogo.eagle.core.utilcode.util.Utils
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason
+import com.zhjt.mogo_core_function_devatools.badcase.mvp.BadCasePresenter
+import com.zhjt.mogo_core_function_devatools.badcase.mvp.BadCaseView
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.Channel
+import java.lang.ref.WeakReference
+import java.util.concurrent.TimeUnit
+
+internal object BadCaseManager : LifecycleEventObserver {
+
+ const val TAG = "BadCase"
+
+ /**
+ * 超过此时间,case入口自动消失
+ */
+
+ private val CASE_EXPIRE_DURATION: Long = TimeUnit.HOURS.toMillis(4)/* TimeUnit.SECONDS.toMillis(10) */
+
+ private var onShow: (() -> Unit)? = null
+ private var onHide: (() -> Unit)? = null
+
+ private var hideFloat: (() -> Unit)? = null
+
+ @Volatile
+ private var record: AutoPilotRecord? = null
+
+ @Volatile
+ private var viewHolder : WeakReference? = null
+
+ @Volatile
+ private var dismissJob: Job? = null
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ private var channel: Channel = Channel(Channel.RENDEZVOUS)
+ get() = if (field.isClosedForReceive || field.isClosedForSend) {
+ field = Channel(Channel.RENDEZVOUS)
+ field
+ } else {
+ field
+ }
+
+ private val presenter by lazy {
+ BadCasePresenter()
+ }
+
+ @Volatile
+ private var scope: LifecycleCoroutineScope? = null
+ get() = if (field == null) {
+ field = viewHolder?.get()?.lifecycleOwner?.lifecycleScope
+ field
+ } else {
+ field
+ }
+
+ fun init(view: View, onShow: (() -> Unit)?, onHide: (() -> Unit)?) {
+ this.viewHolder = WeakReference(view)
+ view.lifecycleOwner.lifecycle.addObserver(this)
+ this.onShow = onShow
+ this.onHide = onHide
+ register()
+ recoverBadCase()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ private fun register() {
+ scope?.launch(Dispatchers.Default) {
+ while (true) {
+ Log.d(TAG, "---- 开始监听BadCase事件 ----")
+ val old = record
+ if (old == null || old.consumed) {
+ Log.d(TAG, "---- 当前事件已消费 -- value: $old")
+ var receive = channel.receive()
+ var oldT = record?.toLongTime() ?: 0L
+ var newT = receive.toLongTime()
+ if (isValid(oldT, newT)) {
+ record = receive
+ Log.d(TAG, "---- 时间有效,开始展示入口 ---")
+ withContext(Dispatchers.Main) {
+ showBadCaseInternal(receive)
+ }
+ continue
+ }
+ Log.d(TAG, "---- 时间无效,移除管道中无用数据 ---")
+ presenter.deleteRecord(receive)
+ while (oldT != 0L && newT != 0L && (newT - oldT) >= CASE_EXPIRE_DURATION) {
+ oldT = newT
+ receive = channel.receive()
+ newT = receive.toLongTime()
+ presenter.deleteRecord(receive)
+ }
+ receive.takeIf { it.key != old?.key }?.also {
+ Log.d(TAG, "record: [$record] is displaying for rest ...")
+ record = receive
+ withContext(Dispatchers.Main) {
+ showBadCaseInternal(it)
+ }
+ }
+ } else {
+ Log.d(TAG, "record: [$old] hasn't been consumed~~~~")
+ withContext(Dispatchers.Main) {
+ showEntry()
+ }
+ delay(1000)
+ }
+ }
+ }
+ }
+
+
+ private fun recoverBadCase() {
+ scope?.launchWhenCreated {
+ val lastModified = presenter.getLastModified()
+ val list = withContext(Dispatchers.IO) {
+ try {
+ Log.d(TAG, " --- 1 ----")
+ Log.d(TAG, "恢复持久化的数据 - 最后修改时间:$lastModified")
+ presenter.getUnConsumedRecords().fold(mutableListOf()) {
+ acc, record ->
+ if (isValid(lastModified, record.toLongTime())) {
+ acc.add(record)
+ } else {
+ presenter.deleteRecord(record)
+ }
+ acc
+ }
+ } catch (t: Throwable) {
+ emptyList()
+ }
+ }
+ if (list.isEmpty()) {
+ Log.d(TAG, "没有要恢复的数据")
+ } else {
+ list.forEach {
+ Log.d(TAG, "恢复的接管数据:$it")
+ channel.send(it)
+ }
+ }
+
+ }
+ }
+
+ private fun isValid(oldT: Long, newT: Long): Boolean {
+ return oldT == 0L || newT == 0L || (newT - oldT >= 0 && (newT - oldT) < CASE_EXPIRE_DURATION)
+ }
+
+ fun onReceiveBadCaseRecord(record: AutoPilotRecordResult) {
+ scope?.launch {
+ val newRecord = record.toRecord()
+ withContext(Dispatchers.IO) {
+ presenter.insertRecord(newRecord)
+ channel.send(newRecord)
+ }
+ }
+ }
+
+ private fun CoroutineScope.showBadCaseInternal(record: AutoPilotRecord) = launch {
+ viewHolder?.get()?.also {
+ presenter.updateLastModified(record.toLongTime())
+ showEntry()
+ it.onClick {
+ showBadCaseFloat(
+ onDismiss = {
+ hideFloat?.invoke()
+ hideFloat = null
+ },
+ onSelect = { reason ->
+ val uploadResult = presenter.upload(mutableMapOf().also { itx ->
+ itx["carLicense"] = MoGoAiCloudClientConfig.getInstance().sn
+ itx["filename"] = record.fileName ?: ""
+ itx["filesize"] = record.total.toString()
+ itx["key"] = record.key ?: ""
+ itx["reason"] = reason.reason ?: ""
+ itx["duration"] = record.duration.toInt().toString()
+ itx["timestamp"] = record.timestamp
+ })
+ if (uploadResult == null || uploadResult.code != 200) {
+ ToastUtils.showShort("接管反馈失败")
+ } else {
+ ToastUtils.showShort("接管反馈成功")
+ record.consumed = true
+ withContext(Dispatchers.IO) {
+ presenter.deleteRecord(record)
+ }
+ hideEntry()
+ hideFloat?.invoke()
+ hideFloat = null
+ }
+ })
+ }
+ dismissAfterDelay()?.also { dismissJob = it }
+ }
+ }
+
+ private fun dismissAfterDelay(): Job? {
+ dismissJob?.takeIf { it.isActive }?.cancel()
+ return scope?.launch {
+ delay(CASE_EXPIRE_DURATION)
+ hideEntry()
+ record?.also {
+ it.consumed = true
+ withContext(Dispatchers.IO) {
+ presenter.deleteRecord(it)
+ }
+ }
+ }
+ }
+
+ private fun showEntry() {
+ viewHolder?.get()?.takeIf { it.visibility != View.VISIBLE }?.also {
+ it.toggle(true)
+ onShow?.invoke()
+ }
+ }
+
+ private fun hideEntry() {
+ viewHolder?.get()?.takeIf { it.visibility == View.VISIBLE }?.also {
+ it.toggle(false)
+ onHide?.invoke()
+ }
+ }
+
+ private fun showBadCaseFloat(onDismiss: () -> Unit, onSelect:suspend (reason: Reason) -> Unit) {
+ val context = viewHolder?.get()?.context ?: Utils.getApp()
+ BadCaseView(context).also {
+ it.register(record, onDismiss, onSelect)
+ hideFloat = CallerHmiManager.showBadCaseFloat(floatView = it)
+ }
+ }
+
+ override fun onStateChanged(source: LifecycleOwner, event: Event) {
+ if (event == ON_DESTROY) {
+ dismissJob?.takeIf { it.isActive }?.cancel()
+ onHide = null
+ onShow = null
+ hideFloat = null
+ }
+ }
+}
+
+fun T.toggle(show: Boolean) {
+ val group = (parent as? ViewGroup) ?: return
+ val target = if (show) View.VISIBLE else View.GONE
+ takeIf { it.visibility != target }?.also {
+ TransitionManager.beginDelayedTransition(group, AutoTransition())
+ it.visibility = target
+ }
+}
+
+internal fun AutoPilotRecordResult.toRecord(): AutoPilotRecord = AutoPilotRecord().also {
+ it.id = this.id
+ it.stat = this.stat
+ it.key = this.key
+ it.note = this.note
+ it.type = this.type
+ it.total = this.total
+ it.fileName = this.fileName
+ it.duration = this.duration
+ it.diskFree = this.diskFree
+ it.consumed = false
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/BadCaseApi.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/BadCaseApi.kt
new file mode 100644
index 0000000000..07350f1355
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/BadCaseApi.kt
@@ -0,0 +1,19 @@
+package com.zhjt.mogo_core_function_devatools.badcase.api
+
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult
+import retrofit2.Response
+import retrofit2.http.FieldMap
+import retrofit2.http.FormUrlEncoded
+import retrofit2.http.GET
+import retrofit2.http.POST
+
+internal interface BadCaseApi {
+
+ @FormUrlEncoded
+ @POST("/yycp-vehicle-management-service/tool/badcase/add")
+ suspend fun post(@FieldMap map: Map): Response
+
+ @GET("/yycp-vehicle-management-service/tool/badcase/reasons")
+ suspend fun get(): Response
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/BadCaseResponse.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/BadCaseResponse.kt
new file mode 100644
index 0000000000..e4d4382e7e
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/BadCaseResponse.kt
@@ -0,0 +1,28 @@
+package com.zhjt.mogo_core_function_devatools.badcase.api.entity
+
+import androidx.annotation.Keep
+import com.google.gson.annotations.Expose
+
+@Keep
+internal class BadCaseResponse {
+ var code: Int = -1
+ var data: List? = null
+ var msg: String? = null
+ var success: Boolean = false
+ var total: Int = -1
+
+ @Expose(serialize = false, deserialize = false)
+ var isBuildIn: Boolean = false
+
+ @Keep
+ class Reason {
+ var id: String? = null
+ var reason: String? = null
+
+ /**
+ * 业务字段,不参与序列化和反序列化
+ */
+ @Expose(deserialize = false, serialize = false)
+ var isChecked: Boolean = false
+ }
+}
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/UploadResult.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/UploadResult.kt
new file mode 100644
index 0000000000..8661560732
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/UploadResult.kt
@@ -0,0 +1,15 @@
+package com.zhjt.mogo_core_function_devatools.badcase.api.entity
+
+import androidx.annotation.Keep
+
+@Keep
+internal class UploadResult {
+ var code: Int = -1
+ var msg: String? = null
+ var data: Array? = null
+ var success: Boolean = false
+
+ override fun toString(): String {
+ return "UploadResult(code=$code, msg=$msg, data=${data?.contentToString()}, success=$success)"
+ }
+}
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseHost.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseHost.kt
new file mode 100644
index 0000000000..2a7e072aa0
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseHost.kt
@@ -0,0 +1,8 @@
+package com.zhjt.mogo_core_function_devatools.badcase.consts
+
+import com.mogo.commons.debug.DebugConfig
+
+internal object BadCaseHost {
+
+ fun getHost(): String = if (DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE) "http://dzt.zhidaozhixing.com" else "http://front.zdjs-private-test.myghost.zhidaoauto.com"
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/BadCasePresenter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/BadCasePresenter.kt
new file mode 100644
index 0000000000..cc70f3ab1d
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/BadCasePresenter.kt
@@ -0,0 +1,54 @@
+package com.zhjt.mogo_core_function_devatools.badcase.mvp
+
+import android.util.Log
+import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult
+import com.zhjt.mogo_core_function_devatools.badcase.mvp.biz.IBadCasePresenter
+import com.zhjt.mogo_core_function_devatools.badcase.repository.Repository
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+import kotlinx.coroutines.flow.Flow
+
+internal class BadCasePresenter: IBadCasePresenter {
+
+ private val repository by lazy {
+ Repository()
+ }
+
+ override suspend fun loadBadCases() = repository.loadBadCases()
+
+ override suspend fun insertRecord(record: AutoPilotRecord) {
+ try {
+ repository.insert(record)
+ } catch (t: Throwable) {
+ Log.d(BadCaseManager.TAG, "-- 插入数据失败 -- msg: $t")
+ }
+ }
+
+ override suspend fun getUnConsumedRecords(): List {
+ return try {
+ repository.getAllUnConsumedRecord() ?: emptyList()
+ } catch (t: Throwable) {
+ Log.d(BadCaseManager.TAG, "-- 获取所有未消费的数据失败 -- msg: $t")
+ emptyList()
+ }
+ }
+
+ override suspend fun deleteRecord(record: AutoPilotRecord) {
+ try {
+ repository.deleteRecord(record)
+ } catch (t: Throwable) {
+ Log.d(BadCaseManager.TAG, "-- 删除某条记录失败 -- msg: $t")
+ }
+ }
+
+ override suspend fun upload(map: Map): UploadResult? = repository.upload(map)
+
+ override suspend fun updateLastModified(timestamp: Long) {
+ repository.uploadLastModified(timestamp)
+ }
+
+ override suspend fun getLastModified(): Long {
+ Log.d(BadCaseManager.TAG, " --- 2 ----")
+ return repository.getLastModified()
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/BadCaseView.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/BadCaseView.kt
new file mode 100644
index 0000000000..435605a055
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/BadCaseView.kt
@@ -0,0 +1,176 @@
+package com.zhjt.mogo_core_function_devatools.badcase.mvp
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.StateListDrawable
+import android.util.AttributeSet
+import android.util.StateSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
+import com.mogo.eagle.core.utilcode.kotlin.*
+import com.zhjt.mogo_core_function_devatools.R
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+import kotlinx.android.synthetic.main.layout_badcase_collect.view.*
+import kotlinx.coroutines.launch
+import java.text.SimpleDateFormat
+import java.util.*
+
+internal class BadCaseView: ConstraintLayout {
+
+ @Volatile
+ private var selectCase: Reason? = null
+
+ @Volatile
+ private var cases: List? = null
+
+ private val presenter by lazy {
+ BadCasePresenter()
+ }
+
+ private var onDismiss: (() -> Unit)? = null
+ private var onSelect:(suspend (reason: Reason) -> Unit)? = null
+
+ private val scope by lazy {
+ lifecycleOwner.lifecycleScope
+ }
+
+ private var record: AutoPilotRecord? = null
+
+ constructor(context: Context) : this(context, null)
+
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+
+ @SuppressLint("SetTextI18n") constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
+ LayoutInflater.from(context).inflate(R.layout.layout_badcase_collect, this, true)
+ background = ColorDrawable(Color.parseColor("#F0151D41"))
+ isClickable = true
+ layoutParams = ViewGroup.LayoutParams(960.toPixels().toInt(), 1528.toPixels().toInt())
+ close?.onClick {
+ onDismiss?.invoke()
+ }
+ cancel?.also {
+ it.background = shape(solid = Color.parseColor("#3B4577"), radius = 16)
+ it.onClick {
+ onDismiss?.invoke()
+ }
+ }
+ ok?.also {
+ val enabled = gradient(radius = 16.toPixels().toInt(), orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(35, 146, 252), endColor = Color.rgb(28, 75, 252))
+ val disabled = gradient(radius = 16.toPixels().toInt(), orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(24, 71, 129), endColor = Color.rgb(21, 46, 129))
+ it.background = object : StateListDrawable() {}.also { itx ->
+ itx.addState(intArrayOf(android.R.attr.state_enabled), enabled)
+ itx.addState(StateSet.WILD_CARD, disabled)
+ }
+ it.onClick {
+ selectCase?.run {
+ scope.launch {
+ onSelect?.invoke(this@run)
+ }
+ }
+ }
+ }
+ scope.launchWhenCreated {
+ time_of_take_over?.text = "接管时间:${SimpleDateFormat("yyyy.MM.dd HH:mm", Locale.getDefault()).format(record?.toLongTime() ?: System.currentTimeMillis())}"
+ showLoading()
+ presenter.loadBadCases().also {
+ cases = it
+ refresh(it)
+ }
+ hideLoading()
+ }
+ }
+
+ private fun refresh(causes: List) {
+ cases = causes
+ rv_take_over?.let {
+ it.layoutManager = LinearLayoutManager(it.context, LinearLayoutManager.VERTICAL, false)
+ it.adapter = object : RecyclerView.Adapter() {
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BadCaseViewHolder = BadCaseViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_badcase_item, parent, false))
+ override fun onBindViewHolder(holder: BadCaseViewHolder, position: Int) {
+ val cases = cases
+ if (cases == null || cases.isEmpty()) {
+ return
+ }
+ if (position >= cases.size) {
+ return
+ }
+ val case = cases[position]
+ holder.bindData(case)
+ }
+ override fun getItemCount(): Int = cases?.size ?: 0
+ }
+ }
+ }
+
+ private fun showLoading() {
+ pb?.let {
+ it.visibility = View.VISIBLE
+ }
+ }
+
+ private fun hideLoading() {
+ pb?.let {
+ it.visibility = View.INVISIBLE
+ }
+ }
+
+ private inner class BadCaseViewHolder(item: View) : RecyclerView.ViewHolder(item) {
+
+ private val check: ImageView = item.findViewById(R.id.check)
+ private val reason: TextView = item.findViewById(R.id.reason)
+
+ init {
+ check.background = StateListDrawable().also {
+ it.addState(intArrayOf(android.R.attr.state_selected), ContextCompat.getDrawable(itemView.context, R.drawable.icon_ap_badcase_check))
+ it.addState(StateSet.WILD_CARD, ContextCompat.getDrawable(itemView.context, R.drawable.icon_ap_badcase_default))
+ }
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ fun bindData(case: Reason) {
+ check.isSelected = case.isChecked
+ reason.text = case.reason ?: ""
+ if (case.isChecked) {
+ ok?.isSelected = true
+ }
+ itemView.onClick {
+ case.isChecked = !case.isChecked
+ selectCase = case
+ cancelOtherChecked(case)
+ ok?.isEnabled = hasCheckedItem()
+ rv_take_over?.adapter?.notifyDataSetChanged()
+ }
+ }
+
+ private fun hasCheckedItem(): Boolean = cases?.find { it.isChecked } != null
+
+ private fun cancelOtherChecked(case: Reason) {
+ val cases = cases
+ if (cases == null || cases.isEmpty()) {
+ return
+ }
+ cases.filterNot { it == case }.forEach {
+ it.isChecked = false
+ }
+ }
+ }
+
+ fun register(record: AutoPilotRecord?, onDismiss: () -> Unit, onSelect:suspend (reason: Reason) -> Unit) {
+ this.record = record
+ this.onDismiss = onDismiss
+ this.onSelect = onSelect
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/biz/IBadCasePresenter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/biz/IBadCasePresenter.kt
new file mode 100644
index 0000000000..4652dc9f60
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/mvp/biz/IBadCasePresenter.kt
@@ -0,0 +1,24 @@
+package com.zhjt.mogo_core_function_devatools.badcase.mvp.biz
+
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+import kotlinx.coroutines.flow.Flow
+
+
+internal interface IBadCasePresenter {
+
+ suspend fun loadBadCases(): List
+
+ suspend fun updateLastModified(timestamp: Long)
+
+ suspend fun getLastModified(): Long
+
+ suspend fun upload(map: Map): UploadResult?
+
+ suspend fun insertRecord(record: AutoPilotRecord)
+
+ suspend fun getUnConsumedRecords(): List
+
+ suspend fun deleteRecord(record: AutoPilotRecord)
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt
new file mode 100644
index 0000000000..db0456fc37
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt
@@ -0,0 +1,93 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository
+
+import android.util.Log
+import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.BadCaseDbModel
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+import com.zhjt.mogo_core_function_devatools.badcase.repository.net.BadCaseNetModel
+import com.zhjt.mogo_core_function_devatools.badcase.repository.store.BadCaseStore
+import kotlinx.coroutines.flow.Flow
+
+internal class Repository {
+
+ private val net by lazy {
+ BadCaseNetModel()
+ }
+
+ private val db by lazy {
+ BadCaseDbModel()
+ }
+
+ private val store by lazy {
+ BadCaseStore
+ }
+
+ suspend fun loadBadCases(): List {
+ return net.get()?.data?.takeIf { it.isNotEmpty() }?.also { store.updateRecords(it) } ?: store.records().takeIf { it.isNotEmpty() } ?: getBuildIn()
+ }
+
+ suspend fun uploadLastModified(timestamp: Long) {
+ store.updateLastModified(timestamp)
+ }
+
+ suspend fun getLastModified(): Long {
+ Log.d(BadCaseManager.TAG, " --- 3 ----")
+ return store.getLastModified()
+ }
+
+ private fun getBuildIn(): List {
+ Log.d(BadCaseManager.TAG, "-- load cases from buildin -- 1 --")
+ val data = mutableListOf()
+ data += Reason().also {
+ it.id = "1"
+ it.reason = "变道有干扰"
+ }
+ data += Reason().also {
+ it.id = "2"
+ it.reason = "遇红绿灯未停车"
+ }
+ data += Reason().also {
+ it.id = "3"
+ it.reason = "遇障碍物未停车"
+ }
+ data += Reason().also {
+ it.id = "4"
+ it.reason = "无法绕行"
+ }
+ data += Reason().also {
+ it.id = "5"
+ it.reason = "画龙"
+ }
+ data += Reason().also {
+ it.id = "6"
+ it.reason = "转弯过于靠近路侧"
+ }
+ data += Reason().also {
+ it.id = "7"
+ it.reason = "无故退出自动驾驶"
+ }
+ data += Reason().also {
+ it.id = "8"
+ it.reason = "其它"
+ }
+ return data
+ }
+
+ suspend fun upload(map: Map): UploadResult? {
+ return net.upload(map)
+ }
+
+ suspend fun insert(record: AutoPilotRecord) {
+ db.dao().insertRecord(record)
+ }
+
+ suspend fun deleteRecord(record: AutoPilotRecord) {
+ db.dao().deleteRecord(record)
+ }
+
+ suspend fun getAllUnConsumedRecord(): List? {
+ return db.dao().getAllUnConsumedRecords()
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/BadCaseDb.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/BadCaseDb.kt
new file mode 100644
index 0000000000..ec4dd92965
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/BadCaseDb.kt
@@ -0,0 +1,16 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository.db
+
+import androidx.room.Database
+import androidx.room.RoomDatabase
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.dao.IBadCaseRecordDao
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+
+@Database(entities = [
+ AutoPilotRecord::class
+ ],
+ version = 1,
+ exportSchema = false)
+internal abstract class BadCaseDb : RoomDatabase() {
+
+ abstract fun dao(): IBadCaseRecordDao
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/BadCaseDbModel.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/BadCaseDbModel.kt
new file mode 100644
index 0000000000..360a8b0658
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/BadCaseDbModel.kt
@@ -0,0 +1,12 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository.db
+
+import androidx.room.Room
+import com.mogo.eagle.core.utilcode.util.Utils
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.dao.IBadCaseRecordDao
+
+internal class BadCaseDbModel {
+
+ fun dao(): IBadCaseRecordDao {
+ return Room.databaseBuilder(Utils.getApp(), BadCaseDb::class.java, "bad-cases").build().dao()
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/dao/IBadCaseRecordDao.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/dao/IBadCaseRecordDao.kt
new file mode 100644
index 0000000000..c40d2e22bb
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/dao/IBadCaseRecordDao.kt
@@ -0,0 +1,19 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository.db.dao
+
+import androidx.room.*
+import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
+
+@Dao
+internal interface IBadCaseRecordDao {
+
+ @Transaction
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertRecord(record: AutoPilotRecord): Long
+
+ @Transaction
+ @Delete
+ suspend fun deleteRecord(record: AutoPilotRecord): Int
+
+ @Query("SELECT * FROM record ORDER BY timestamp ASC")
+ suspend fun getAllUnConsumedRecords(): List?
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/entity/AutoPilotRecord.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/entity/AutoPilotRecord.kt
new file mode 100644
index 0000000000..2a55730795
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/db/entity/AutoPilotRecord.kt
@@ -0,0 +1,89 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.text.SimpleDateFormat
+import java.util.*
+@Entity(tableName = "record")
+internal class AutoPilotRecord {
+
+ /**
+ * 磁盘可用空间(M)
+ */
+ @ColumnInfo(name = "disk_free")
+ var diskFree: Long = 0
+
+ /**
+ * 采集时长
+ */
+ var duration: Double = 0.0
+
+
+ /**
+ * 保存的文件名
+ */
+ @ColumnInfo(name = "file_name")
+ var fileName: String? = ""
+
+
+ /**
+ * 其他信息,包含错误信息等
+ */
+ var note: String? = ""
+
+ /**
+ * 域控制器定义的bag key
+ */
+ var key: String? = ""
+
+ /**
+ * 采集状态:
+ * 100 - 采集成功,自动结束
+ * 101 - 采集成功,收到结束指令
+ * 200 - 采集失败
+ * 201 - 采集中
+ * 300 - 开始采集
+ */
+ var stat: Int = 0
+
+
+ /**
+ * 任务类型:1-badcase采集任务,2-地图数据采集任务
+ */
+ var type: Int = 0
+
+ /**
+ * 任务ID
+ */
+ var id: Int = 0
+
+ /**
+ * 时间戳,格式:YYYY-MM-DD-hh-mm-ss
+ */
+ @PrimaryKey
+ var timestamp: String = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(Date())
+
+ /**
+ * 此次采集数据总大小(M)
+ */
+ var total: Long? = 0
+
+ /**
+ * 记录此条数据是否已消费
+ */
+ @Volatile
+ var consumed: Boolean = false
+
+
+ override fun toString(): String {
+ return "AutoPilotRecord(diskFree=$diskFree, duration=$duration, fileName=$fileName, note=$note, key=$key, stat=$stat, type=$type, id=$id, timestamp='$timestamp', total=$total, consumed=$consumed)"
+ }
+
+ fun toLongTime(): Long = try {
+ SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(this.timestamp)?.time ?: 0L
+ } catch (t: Throwable) {
+ 0L
+ }
+}
+
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt
new file mode 100644
index 0000000000..6388faa7f3
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt
@@ -0,0 +1,44 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository.net
+
+import android.util.Log
+import com.mogo.eagle.core.network.MoGoRetrofitFactory
+import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
+import com.zhjt.mogo_core_function_devatools.badcase.api.BadCaseApi
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult
+import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseHost
+
+internal class BadCaseNetModel {
+
+ suspend fun get(): BadCaseResponse? = try {
+ Log.d(BadCaseManager.TAG, "-- load cases from net -- 1 --")
+ MoGoRetrofitFactory
+ .getInstance(BadCaseHost.getHost())
+ .create(BadCaseApi::class.java)
+ .get()
+ .takeIf {
+ val body = it.body()
+ it.isSuccessful && body != null && (body.code == 0 || body.code == 200)
+ }
+ ?.body()?.also {
+ Log.d(BadCaseManager.TAG, "-- load cases from net -- 2 --")
+ }
+ } catch (t: Throwable) {
+ Log.d(BadCaseManager.TAG, "-- load cases from net -- 3 --")
+ null
+ }
+
+ suspend fun upload(map: Map): UploadResult? = try {
+ MoGoRetrofitFactory
+ .getInstance(BadCaseHost.getHost())
+ .create(BadCaseApi::class.java)
+ .post(map)
+ .takeIf {
+ val body = it.body()
+ return@takeIf it.isSuccessful && (body != null) && (body.code == 0 || body.code == 200)
+ }
+ ?.body()
+ } catch (t: Throwable) {
+ null
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt
new file mode 100644
index 0000000000..3d906b63c8
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt
@@ -0,0 +1,109 @@
+package com.zhjt.mogo_core_function_devatools.badcase.repository.store
+
+import android.util.Log
+import androidx.datastore.core.DataStore
+import androidx.datastore.core.DataStoreFactory
+import androidx.datastore.core.Serializer
+import com.mogo.eagle.core.utilcode.util.Utils
+import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse
+import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason
+import com.zhjt.mogo_core_function_devatools.badcase.generated.BadCauses
+import com.zhjt.mogo_core_function_devatools.badcase.generated.Cause
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import kotlin.math.log
+
+internal object BadCaseStore {
+
+ private val serializer = object : Serializer {
+
+ override val defaultValue: BadCauses
+ get() = BadCauses.getDefaultInstance()
+
+ override suspend fun readFrom(input: InputStream): BadCauses = suspendCancellableCoroutine {
+ Log.d(BadCaseManager.TAG, "--- readFrom ---")
+ it.invokeOnCancellation {
+ Thread.currentThread().interrupt()
+ }
+ try {
+ it.resumeWith(Result.success(BadCauses.parseFrom(input)))
+ } catch (t: Throwable) {
+ it.resumeWith(Result.failure(t))
+ }
+ }
+
+ override suspend fun writeTo(t: BadCauses, output: OutputStream) = suspendCancellableCoroutine {
+ it.invokeOnCancellation {
+ Thread.currentThread().interrupt()
+ }
+ try {
+ t.writeTo(output)
+ it.resumeWith(Result.success(Unit))
+ } catch (t: Throwable) {
+ it.resumeWith(Result.failure(t))
+ }
+ }
+ }
+
+
+ private val store: DataStore by lazy {
+ DataStoreFactory.create(serializer = serializer) { File(Utils.getApp().filesDir, "bad_cases.pb") }
+ }
+
+ suspend fun updateRecords(reasons: List): BadCauses {
+ Log.d(BadCaseManager.TAG, "--- updateRecords ---")
+ val data = mutableListOf()
+ reasons.forEach { itx ->
+ data += Cause.newBuilder().let {
+ it.id = itx.id
+ it.reason = itx.reason
+ it.build()
+ }
+ }
+ return store.updateData { itx ->
+ itx.toBuilder().clearData().addAllData(data).build()
+ }
+ }
+
+ suspend fun updateLastModified(timestamp: Long): BadCauses {
+ Log.d(BadCaseManager.TAG, "--- updateLastModified ---")
+ return store.updateData { itx ->
+ itx.toBuilder().setLastModified(timestamp).build()
+ }
+ }
+
+ suspend fun getLastModified(): Long {
+ Log.d(BadCaseManager.TAG, " --- 4 ----")
+ return store
+ .data
+ .catch {
+ if (it is IOException) {
+ emit(BadCauses.getDefaultInstance())
+ }
+ }
+ .map {
+ it.lastModified
+ }.firstOrNull() ?: 0L
+
+ }
+
+ @OptIn(FlowPreview::class)
+ suspend fun records(): List {
+ Log.d(BadCaseManager.TAG, "-- load cases from pb -- 1 -- ")
+ val causes = store.data.firstOrNull()
+ return causes?.dataList?.map {
+ Reason().also { itx ->
+ itx.id = it.id
+ itx.reason = it.reason
+ }
+ }?.fold(mutableListOf()) { acc, reason ->
+ acc += reason
+ acc
+ } ?: emptyList()
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto b/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto
new file mode 100644
index 0000000000..d76f5ad9a0
--- /dev/null
+++ b/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto
@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "com.zhjt.mogo_core_function_devatools.badcase.generated";
+option java_outer_classname = "BadCausesProto";
+
+message BadCauses {
+ int64 lastModified = 1;
+ repeated Cause data = 2 ;
+}
+
+message Cause {
+ string id = 1;
+ string reason = 2;
+}
+
+
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ap_badcase_check.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_ap_badcase_check.png
similarity index 100%
rename from core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ap_badcase_check.png
rename to core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_ap_badcase_check.png
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ap_badcase_default.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_ap_badcase_default.png
similarity index 100%
rename from core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ap_badcase_default.png
rename to core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_ap_badcase_default.png
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/layout_badcase_collect.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_collect.xml
similarity index 100%
rename from core/function-impl/mogo-core-function-hmi/src/main/res/layout/layout_badcase_collect.xml
rename to core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_collect.xml
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/layout_badcase_item.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_item.xml
similarity index 100%
rename from core/function-impl/mogo-core-function-hmi/src/main/res/layout/layout_badcase_item.xml
rename to core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_item.xml
diff --git a/core/function-impl/mogo-core-function-hmi/build.gradle b/core/function-impl/mogo-core-function-hmi/build.gradle
index eacd9256cd..5fba5dc7e4 100644
--- a/core/function-impl/mogo-core-function-hmi/build.gradle
+++ b/core/function-impl/mogo-core-function-hmi/build.gradle
@@ -38,6 +38,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+
}
dependencies {
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt
index bcd0564a1d..ab6032e8cb 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt
+++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt
@@ -2,21 +2,14 @@ package com.mogo.eagle.core.function.hmi.ui
import android.animation.Animator
import android.os.Bundle
-import android.os.Handler
import android.text.TextUtils
import android.util.Log
import android.view.Gravity
import android.view.View
-import android.view.ViewGroup
import android.view.WindowManager
import android.view.animation.OvershootInterpolator
-import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
-import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.lifecycleScope
-import androidx.transition.AutoTransition
-import androidx.transition.TransitionManager
import com.alibaba.android.arouter.facade.annotation.Route
-import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.mvp.MvpFragment
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.data.autopilot.AdUpgradeStateHelper
@@ -30,9 +23,9 @@ import com.mogo.eagle.core.data.notice.NoticeTrafficStylePushData
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWaringProvider
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
-import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.check.CallerCheckManager
+import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager
import com.mogo.eagle.core.function.call.monitor.CallerMonitorManager
import com.mogo.eagle.core.function.hmi.R
@@ -45,23 +38,15 @@ import com.mogo.eagle.core.function.hmi.ui.notice.NoticeBannerView
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeNormalBannerView
import com.mogo.eagle.core.function.hmi.ui.setting.DebugSettingView
import com.mogo.eagle.core.function.hmi.ui.tools.AutoPilotAndCheckView
-import com.mogo.eagle.core.function.hmi.ui.tools.AutoPilotBadCaseView
-import com.mogo.eagle.core.function.hmi.ui.tools.Repository
-import com.mogo.eagle.core.function.hmi.ui.tools.post
import com.mogo.eagle.core.function.hmi.ui.widget.V2XNotificationView
-import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner
-import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
+import com.mogo.eagle.core.utilcode.util.Utils
import com.mogo.module.common.enums.EventTypeEnum
import kotlinx.android.synthetic.main.fragment_hmi.*
import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
-import java.text.SimpleDateFormat
import java.util.*
-import java.util.concurrent.TimeUnit
/**
* @author xiaoyuzhou
@@ -94,132 +79,8 @@ class MoGoHmiFragment : MvpFragment
// 检测、自动驾驶速度设置
private var toolsViewFloat: WarningFloat.Builder? = null
- @Volatile
- private var autoPilotBadCaseEntrance: View? = null
-
- private var autoPilotBadCaseView: AutoPilotBadCaseView? = null
-
- private var onBadCaseShow: (() -> View)? = null
- private var onBadCaseHide: (() -> Unit)? = null
-
private var upgradeTipsView: (() -> View)? = null
- companion object {
- private const val MSG_WHAT_DISMISS_BAD_CASE_ENTRY = 0x1010
- private val CASE_EXPIRE_DURATION = TimeUnit.HOURS.toMillis(4)
- }
-
- @ExperimentalCoroutinesApi
- private val channel by lazy {
- Channel(UNLIMITED).also {
- lifecycleScope.launchWhenResumed {
- withContext(Dispatchers.Default) {
- while (!it.isClosedForReceive) {
- try {
- val entrance = autoPilotBadCaseEntrance
- val old = entrance?.getTag(R.id.autopilot_badcase_record) as? AutoPilotRecordResult
- if (entrance == null || old == null || old.consumed) {
- Log.d("QQQ", "-- step -- 1 --")
- var oldT = try {
- old?.timestamp?.takeIf { it.isNotBlank() }?.let {
- SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time
- ?: 0L
- } ?: 0L
- } catch (t: Throwable) {
- t.printStackTrace()
- 0L
- }
- var record: AutoPilotRecordResult? = null
- var newT = try {
- it.receive()?.also { record = it }?.timestamp?.takeIf { it.isNotBlank() }?.let {
- SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time
- ?: 0L
- } ?: 0L
- } catch (t: Throwable) {
- t.printStackTrace()
- 0L
- }
-
- if (oldT == 0L || (newT > 0L && (newT - oldT > 0L) && (newT - oldT) < CASE_EXPIRE_DURATION)) {
- Log.d("QQQ", "-- step -- 2 --")
- record?.takeIf { it.key != old?.key && it.timestamp != old?.timestamp }?.also {
- Log.d("QQQ", "record: [$record] is displaying and consuming ~~~")
- showBadCaseEntrance(it)
- }
- continue
- }
-
- while (oldT != 0L && newT != 0L && (newT - oldT) >= CASE_EXPIRE_DURATION) {
- Log.d("QQQ", "record: [$record] has been discarded, because it has been timeout.")
- oldT = newT
- newT = try {
- it.receive()?.also {
- record = it
- }?.timestamp?.takeIf { it.isNotBlank() }?.let {
- SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time
- ?: 0L
- } ?: 0L
- } catch (t: Throwable) {
- t.printStackTrace()
- 0L
- }
- }
- record?.takeIf { it.key != old?.key && it.timestamp != old?.timestamp }?.also {
- Log.d("QQQ", "record: [$record] is displaying for rest ...")
- showBadCaseEntrance(it)
- }
- } else {
- withContext(Dispatchers.Main) {
- entrance.takeIf { it.visibility != View.VISIBLE }?.also {
- (entrance.parent as? ViewGroup)?.let { g ->
- TransitionManager.beginDelayedTransition(g, AutoTransition())
- }
- it.visibility = View.VISIBLE
- }
- }
- Log.d("QQQ", "record: [$old] hasn't been consumed~~~~")
- }
- } finally {
- delay(1000)
- }
- }
- }
- }
- }
- }
-
- private val handler by lazy {
- Handler(Handler.Callback { it ->
- if (it.what == MSG_WHAT_DISMISS_BAD_CASE_ENTRY) {
- val entrance = autoPilotBadCaseEntrance
- if (entrance != null && entrance.visibility == View.VISIBLE) {
- val record = entrance.getTag(R.id.autopilot_badcase_record) as? AutoPilotRecordResult
- record?.consumed = true
- record?.let { itx ->
- lifecycleScope.launch(Dispatchers.IO) {
- try {
- val i = Repository.dao().deleteRecord(itx)
- Log.d("QQQ", "delete result: $i")
- } catch (t: Throwable) {
- Log.d("QQQ", "---- delete error: ${t.message}")
- }
- }
- }
- dismissBadCaseFloatView()
- if (entrance.visibility != View.GONE) {
- (entrance.parent as? ViewGroup)?.let { g ->
- TransitionManager.beginDelayedTransition(g, AutoTransition())
- }
- entrance.visibility = View.GONE
- onBadCaseHide?.invoke()
- }
- }
- return@Callback true
- }
- return@Callback false
- })
- }
-
override fun vipIdentification(visible: Boolean) {
ThreadUtils.runOnUiThread {
Logger.d(TAG, "vipIdentification")
@@ -260,18 +121,6 @@ class MoGoHmiFragment : MvpFragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
- lifecycleScope.launchWhenResumed {
- withContext(Dispatchers.IO) {
- val dao = Repository.dao()
- try {
- dao.getAllUnConsumedRecords()?.forEach {
- channel.send(it)
- }
- } catch (t: Throwable) {
- t.printStackTrace()
- }
- }
- }
/*// TODO 这里后面需要改成独立进程通讯后台获取YUV
view.postDelayed({
@@ -282,21 +131,8 @@ class MoGoHmiFragment : MvpFragment
@OptIn(ExperimentalCoroutinesApi::class)
override fun onAutopilotRecordResult(record: AutoPilotRecordResult?) {
record ?: return
- Log.d("QQQ", "onAutopilotRecordResult:$record")
- if (record.type == 1 && record.stat == 100) {
- lifecycleScope.launchWhenResumed {
- withContext(Dispatchers.IO) {
- val dao = Repository.dao()
- try {
- dao.insertRecord(record)
- } catch (t: Throwable) {
- t.printStackTrace()
- }
- record.also {
- channel.send(it)
- }
- }
- }
+ if (HmiBuildConfig.isShowBadCaseView && record.type == 1 && record.stat == 100) {
+ CallerDevaToolsManager.onReceiveBadCaseRecord(record)
}
if (record.type == 2 && (record.stat == 101 || record.stat == 100)) {
CallerMapDataCollectorManager.finish(record.id, record.stat, "", record.fileName ?: "", record.note ?: "")
@@ -308,61 +144,6 @@ class MoGoHmiFragment : MvpFragment
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
}
- private fun showBadCaseEntrance(record: AutoPilotRecordResult) {
- Log.d("QQQ", "showBadCaseEntrance:$record")
- lifecycleScope.launch {
- if (HmiBuildConfig.isShowBadCaseView) {
- if (vsBadCaseToolsView?.parent != null) {
- val inflateView = vsBadCaseToolsView.inflate()
- autoPilotBadCaseEntrance = inflateView
- }
- }
- val entrance = autoPilotBadCaseEntrance
- Log.d("QQQ", "show --- 1 ----")
- if (entrance != null) {
- if (entrance.visibility != View.VISIBLE) {
- (entrance.parent as? ViewGroup)?.let { g ->
- TransitionManager.beginDelayedTransition(g, AutoTransition())
- }
- entrance.visibility = View.VISIBLE
- }
- entrance.setTag(R.id.autopilot_badcase_record, record)
- entrance.onClick {
- showBadCasesFloat {
- if (it.visibility != View.GONE) {
- (entrance.parent as? ViewGroup)?.let { g ->
- TransitionManager.beginDelayedTransition(g, AutoTransition())
- }
- it.visibility = View.GONE
- onBadCaseHide?.invoke()
- }
- }
- }
- dismissBadCaseEntryAfterSomeTime()
- } else {
- val view = onBadCaseShow?.invoke()
- if (view != null) {
- view.lifecycleOwner.lifecycle.addObserver(badCaseEntranceObserver)
- view.visibility = View.GONE
- autoPilotBadCaseEntrance = view
- showBadCaseEntrance(record)
- }
- }
- }
- }
-
- private val badCaseEntranceObserver = LifecycleEventObserver { _, event ->
- if (event == ON_DESTROY) {
- onBadCaseShow = null
- onBadCaseHide = null
- autoPilotBadCaseEntrance = null
- }
- }
-
- override fun registerBadCaseCallback(onShow: () -> View, onHide: (() -> Unit)?) {
- onBadCaseShow = onShow
- onBadCaseHide = onHide
- }
/**
*注册工控机升级提示圆点View的回调
@@ -391,116 +172,6 @@ class MoGoHmiFragment : MvpFragment
}
}
- private fun showBadCasesFloat(dismiss: (() -> Unit)?) {
- Log.d("QQQ", "showBadCaseToolsFloat")
- context?.let { it ->
- if (autoPilotToolsFloat == null) {
- if (autoPilotBadCaseView == null) {
- autoPilotBadCaseView = AutoPilotBadCaseView(it).also { itx ->
- val record =
- autoPilotBadCaseEntrance?.getTag(R.id.autopilot_badcase_record) as? AutoPilotRecordResult
- itx.tag = record
- itx.onDismiss {
- dismissBadCaseFloatView()
- }
- itx.onSelect {
- lifecycleScope.launch {
- try {
- val params = mutableMapOf()
- autoPilotBadCaseEntrance?.apply {
- params["carLicense"] =
- MoGoAiCloudClientConfig.getInstance().sn
- params["filename"] = record?.fileName ?: ""
- params["filesize"] = record?.total.toString()
- params["key"] = record?.key ?: ""
- params["reason"] = it.reason ?: ""
- params["duration"] = record?.duration?.toInt()?.toString()
- ?: ""
- params["timestamp"] = record?.timestamp ?: ""
- }
- val response = post(params)
- if (response.isSuccessful) {
- val body = response.body()
- if (body == null) {
- Log.e("QQQ", "返回的body是空的~~~")
- return@launch
- }
- if (body.code == 200) {
- Logger.i(TAG, "ok:${body}")
- dismissBadCaseFloatView()
- dismiss?.invoke()
- CallerAutoPilotManager.recordCause(
- record?.key,
- record?.fileName,
- it.id, it.reason)
- ToastUtils.showShort("接管反馈成功~")
- record?.also {
- it.consumed = true
- withContext(Dispatchers.IO) {
- try {
- Repository.dao().deleteRecord(record)
- } catch (t: Throwable) {
- Log.d("QQQ", "---- delete error 2: ${t.message}")
- }
- }
- }
- return@launch
- }
- Log.e("QQQ", "fail:${body}")
- }
- } catch (t: Throwable) {
- t.printStackTrace()
- ToastUtils.showShort("网络请求失败,请尝试联网~")
- Log.e("QQQ", "exception:${t.message}")
- }
- }
- }
- }
- }
- autoPilotToolsFloat = WarningFloat.with(it)
- .setTag("BadCaseCollectFloat")
- .setLayout(autoPilotBadCaseView!!)
- .setSidePattern(SidePattern.LEFT)
- .setGravity(Gravity.LEFT, offsetY = 72)
- .setImmersionStatusBar(true)
- .setAnimator(object : DefaultAnimator() {
- override fun enterAnim(
- view: View,
- params: WindowManager.LayoutParams,
- windowManager: WindowManager,
- sidePattern: SidePattern
- ): Animator? =
- super.enterAnim(view, params, windowManager, sidePattern)
- ?.apply {
- interpolator = OvershootInterpolator()
- }
-
- override fun exitAnim(
- view: View,
- params: WindowManager.LayoutParams,
- windowManager: WindowManager,
- sidePattern: SidePattern
- ): Animator? =
- super.exitAnim(view, params, windowManager, sidePattern)
- ?.setDuration(200)
- })
- .addWarningStatusListener(object : IMoGoWarningStatusListener {
- override fun onDismiss() {
- autoPilotToolsFloat = null
- autoPilotBadCaseView = null
- }
- })
- .show()
- } else {
- autoPilotToolsFloat?.show()
- }
- }
- }
-
- private fun dismissBadCaseEntryAfterSomeTime() {
- handler.removeMessages(MSG_WHAT_DISMISS_BAD_CASE_ENTRY)
- handler.sendEmptyMessageDelayed(MSG_WHAT_DISMISS_BAD_CASE_ENTRY, CASE_EXPIRE_DURATION)
- }
private fun showToolsFloat() {
Logger.d(TAG, "showToolsFloat")
@@ -597,6 +268,10 @@ class MoGoHmiFragment : MvpFragment
} else {
setToolsViewVisibility(View.GONE)
}
+
+ if (HmiBuildConfig.isShowBadCaseView) {
+ CallerDevaToolsManager.initBadCase(vsBadCaseToolsView)
+ }
}
override fun getLayoutId(): Int {
@@ -1125,18 +800,54 @@ class MoGoHmiFragment : MvpFragment
}
- private fun dismissBadCaseFloatView() {
- autoPilotToolsFloat?.let {
- WarningFloat.dismiss(it.config.floatTag, false)
- autoPilotToolsFloat = null
- autoPilotBadCaseView = null
+ override fun showBadCaseFloat(tag: String, floatView: View): () -> Unit {
+ WarningFloat.with(context ?: Utils.getApp())
+ .setTag(tag)
+ .setLayout(floatView)
+ .setSidePattern(SidePattern.LEFT)
+ .setGravity(Gravity.START, offsetY = 72)
+ .setImmersionStatusBar(true)
+ .setAnimator(object : DefaultAnimator() {
+ override fun enterAnim(
+ view: View,
+ params: WindowManager.LayoutParams,
+ windowManager: WindowManager,
+ sidePattern: SidePattern
+ ): Animator? =
+ super.enterAnim(view, params, windowManager, sidePattern)
+ ?.apply {
+ interpolator = OvershootInterpolator()
+ }
+
+ override fun exitAnim(
+ view: View,
+ params: WindowManager.LayoutParams,
+ windowManager: WindowManager,
+ sidePattern: SidePattern
+ ): Animator? =
+ super.exitAnim(view, params, windowManager, sidePattern)
+ ?.setDuration(200)
+ })
+ .addWarningStatusListener(object : IMoGoWarningStatusListener {
+ override fun onDismiss() {
+ autoPilotToolsFloat = null
+ }
+ })
+ .also {
+ autoPilotToolsFloat = it
+ }
+ .show()
+ return {
+ autoPilotToolsFloat?.let {
+ WarningFloat.dismiss(it.config.floatTag, false)
+ autoPilotToolsFloat = null
+ }
}
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
- handler.removeCallbacksAndMessages(null)
}
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotBadCase.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotBadCase.kt
deleted file mode 100644
index 28e6ce710c..0000000000
--- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotBadCase.kt
+++ /dev/null
@@ -1,404 +0,0 @@
-package com.mogo.eagle.core.function.hmi.ui.tools
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.content.Context.MODE_PRIVATE
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.graphics.drawable.GradientDrawable
-import android.graphics.drawable.StateListDrawable
-import android.os.Handler
-import android.util.AttributeSet
-import android.util.StateSet
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.annotation.Keep
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.core.content.ContextCompat
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import androidx.room.*
-import com.google.gson.annotations.Expose
-import com.mogo.commons.debug.DebugConfig
-import com.mogo.commons.debug.DebugConfig.getNetMode
-import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
-import com.mogo.eagle.core.function.hmi.R
-import com.mogo.eagle.core.function.hmi.ui.tools.BadCaseEntity.Reason
-import com.mogo.eagle.core.network.MoGoRetrofitFactory
-import com.mogo.eagle.core.network.utils.GsonUtil
-import com.mogo.eagle.core.utilcode.kotlin.*
-import com.mogo.eagle.core.utilcode.util.ThreadUtils
-import com.mogo.eagle.core.utilcode.util.Utils
-import kotlinx.android.synthetic.main.layout_badcase_collect.view.*
-import kotlinx.coroutines.*
-import kotlinx.coroutines.android.asCoroutineDispatcher
-import retrofit2.Response
-import retrofit2.http.FieldMap
-import retrofit2.http.FormUrlEncoded
-import retrofit2.http.GET
-import retrofit2.http.POST
-import java.text.SimpleDateFormat
-import java.util.*
-import kotlin.Result.Companion.failure
-import kotlin.Result.Companion.success
-
-private typealias OnDismissCallback = () -> Unit
-private typealias OnSelectCallback = (Reason) -> Unit
-
-
-object Repository {
-
- fun dao(): Dao {
- return Room.databaseBuilder(Utils.getApp(), RecordDb::class.java, "bad-cases").build().dao()
- }
-
- @Database(entities = [
- AutoPilotRecordResult::class
- ],
- version = 1,
- exportSchema = false)
- abstract class RecordDb : RoomDatabase() {
- abstract fun dao(): Dao
- }
-
- @androidx.room.Dao
- interface Dao {
-
- @Transaction
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- suspend fun insertRecord(record: AutoPilotRecordResult): Long
-
- @Transaction
- @Delete
- suspend fun deleteRecord(record: AutoPilotRecordResult): Int
-
- @Query("SELECT * FROM record ORDER BY timestamp ASC")
- suspend fun getAllUnConsumedRecords(): List?
- }
-}
-
-interface BadCaseApi {
-
- @FormUrlEncoded
- @POST("/yycp-vehicle-management-service/tool/badcase/add")
- suspend fun post(@FieldMap map: Map): Response
-
- @GET("/yycp-vehicle-management-service/tool/badcase/reasons")
- suspend fun get(): Response
-}
-
-@Keep
-class BadCaseEntity {
- var code: Int = -1
- var data: List? = null
- var msg: String? = null
- var success: Boolean = false
- var total: Int = -1
-
- @Expose(serialize = false, deserialize = false)
- var isBuildIn: Boolean = false
-
- @Keep
- class Reason {
- var id: String? = null
- var reason: String? = null
-
- /**
- * 业务字段,不参与序列化和反序列化
- */
- @Expose(deserialize = false, serialize = false)
- var isChecked: Boolean = false
- }
-}
-
-@Keep
-class PostResult {
- var code: Int = -1
- var msg: String? = null
- var data: Array? = null
- var success: Boolean = false
-
- override fun toString(): String {
- return "Result(code=$code, msg=$msg, data=${data?.contentToString()}, success=$success)"
- }
-}
-
-private fun getHost(): String = if (getNetMode() == DebugConfig.NET_MODE_RELEASE) "http://dzt.zhidaozhixing.com" else "http://front.zdjs-private-test.myghost.zhidaoauto.com"
-
-internal suspend fun post(map: Map): Response {
- return MoGoRetrofitFactory.getInstance(getHost()).create(BadCaseApi::class.java).post(map)
-}
-
-private suspend fun get(): Response? {
- return try { MoGoRetrofitFactory.getInstance(getHost()).create(BadCaseApi::class.java).get() } catch (t: Throwable) { t.printStackTrace(); null}
-}
-
-private suspend fun updateCache(entity: BadCaseEntity) = suspendCancellableCoroutine {
- try {
- val future = ThreadUtils.getIoPool().submit {
- try {
- val gson = GsonUtil.jsonFromObject(entity)
- Sp.saveBody(gson)
- it.resumeWith(success(Unit))
- } catch (t: Throwable) {
- it.resumeWith(failure(t))
- }
- }
- it.invokeOnCancellation {
- future.cancel(true)
- }
- } catch (e: Throwable) {
- it.resumeWith(failure(e))
- }
-}
-
-private suspend fun getCache(): BadCaseEntity? = suspendCancellableCoroutine {
- try {
- val body = Sp.getBody()
- if (body != null && body.isNotEmpty()) {
- val future = ThreadUtils.getIoPool().submit {
- try {
- val result = GsonUtil.objectFromJson(body, BadCaseEntity::class.java)
- it.resumeWith(success(result))
- } catch (t: Throwable) {
- it.resumeWith(success(null))
- }
- }
- it.invokeOnCancellation {
- future.cancel(true)
- }
- }
- } catch (t: Throwable) {
- it.resumeWith(success(null))
- }
-}
-
-private fun getBuildIn(): BadCaseEntity = BadCaseEntity().also { itx ->
- val data = mutableListOf()
- data += Reason().also {
- it.id = "1"
- it.reason = "变道有干扰"
- }
- data += Reason().also {
- it.id = "2"
- it.reason = "遇红绿灯未停车"
- }
- data += Reason().also {
- it.id = "3"
- it.reason = "遇障碍物未停车"
- }
- data += Reason().also {
- it.id = "4"
- it.reason = "无法绕行"
- }
- data += Reason().also {
- it.id = "5"
- it.reason = "画龙"
- }
- data += Reason().also {
- it.id = "6"
- it.reason = "转弯过于靠近路侧"
- }
- data += Reason().also {
- it.id = "7"
- it.reason = "无故退出自动驾驶"
- }
- data += Reason().also {
- it.id = "8"
- it.reason = "其它"
- }
- itx.data = data
- itx.isBuildIn = true
-}
-
-internal object Sp {
-
- private val sp by lazy {
- Utils.getApp().getSharedPreferences("bad_case_prefs", MODE_PRIVATE)
- }
-
- @SuppressLint("ApplySharedPref")
- fun saveBody(body: String) {
- sp.edit().putString("prefs", body).commit()
- }
-
- fun getBody(): String? {
- return sp.getString("prefs", null)
- }
-}
-
-class AutoPilotBadCaseView: ConstraintLayout {
-
- private var dismiss: OnDismissCallback? = null
- private var select: OnSelectCallback? = null
- private var cases: List? = null
-
- private var selectCase: Reason? = null
-
- private val scope = CoroutineScope(Handler().asCoroutineDispatcher() + SupervisorJob())
-
- constructor(context: Context) : this(context, null)
-
- constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
-
- constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
- LayoutInflater.from(context).inflate(R.layout.layout_badcase_collect, this, true)
- background = ColorDrawable(Color.parseColor("#F0151D41"))
- isClickable = true
- layoutParams = ViewGroup.LayoutParams(960.toPixels().toInt(), 1528.toPixels().toInt())
- close?.onClick {
- dismiss?.invoke()
- }
- cancel?.also {
- it.background = shape(solid = Color.parseColor("#3B4577"), radius = 16)
- it.onClick {
- dismiss?.invoke()
- }
- }
- ok?.also {
- val enabled = gradient(radius = 16.toPixels().toInt(), orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(35, 146, 252), endColor = Color.rgb(28, 75, 252))
- val disabled = gradient(radius = 16.toPixels().toInt(), orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(24, 71, 129), endColor = Color.rgb(21, 46, 129))
- it.background = object : StateListDrawable() {}.also { itx ->
- itx.addState(intArrayOf(android.R.attr.state_enabled), enabled)
- itx.addState(StateSet.WILD_CARD, disabled)
- }
- it.onClick {
- val case = selectCase
- if (case != null) {
- select?.invoke(case)
- }
- }
- }
- }
-
- override fun onAttachedToWindow() {
- super.onAttachedToWindow()
- val adapter = rv_take_over?.adapter
- if (adapter != null && adapter.itemCount > 0) {
- return
- }
- time_of_take_over?.text = "接管时间: ${(tag as? AutoPilotRecordResult)?.timestamp?.let {
- try {
- SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.let { itx ->
- SimpleDateFormat("yyyy.MM.dd HH:mm", Locale.getDefault()).format(itx)
- }
- } catch (e: Throwable) {
- null
- } ?: SimpleDateFormat("yyyy.MM.dd HH:mm", Locale.getDefault()).format(Date())}}"
-
- scope.launch {
- showLoading()
- try {
- get()?.takeIf { it.isSuccessful && it.body() != null && it.body()?.code == 200 }?.let {
- val entity = it.body()!!
- try {
- updateCache(entity)
- } catch (t: Throwable) {
- t.printStackTrace()
- } finally {
- updateBadCaseList(entity)
- }
- }
- ?:
- getCache()?.also {
- updateBadCaseList(it)
- }
- ?:
- updateBadCaseList(getBuildIn())
- } finally {
- hideLoading()
- }
- }
- }
-
- private fun updateBadCaseList(body: BadCaseEntity) {
- cases = body.data
- rv_take_over?.let {
- it.layoutManager = LinearLayoutManager(it.context, LinearLayoutManager.VERTICAL, false)
- it.adapter = object : RecyclerView.Adapter() {
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BadCaseViewHolder = BadCaseViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_badcase_item, parent, false))
- override fun onBindViewHolder(holder: BadCaseViewHolder, position: Int) {
- val cases = cases
- if (cases == null || cases.isEmpty()) {
- return
- }
- if (position >= cases.size) {
- return
- }
- val case = cases[position]
- holder.bindData(case)
- }
- override fun getItemCount(): Int = cases?.size ?: 0
- }
- }
- }
-
- override fun onDetachedFromWindow() {
- super.onDetachedFromWindow()
- scope.cancel("Cancel all for AutoPilotBadCaseView#onDetachedFromWindow")
- }
-
- private fun showLoading() {
- pb?.let {
- it.visibility = View.VISIBLE
- }
- }
-
- private fun hideLoading() {
- pb?.let {
- it.visibility = View.INVISIBLE
- }
- }
-
- private inner class BadCaseViewHolder(item: View) : RecyclerView.ViewHolder(item) {
-
- private val check: ImageView = item.findViewById(R.id.check)
- private val reason: TextView = item.findViewById(R.id.reason)
-
- init {
- check.background = StateListDrawable().also {
- it.addState(intArrayOf(android.R.attr.state_selected), ContextCompat.getDrawable(itemView.context, R.drawable.icon_ap_badcase_check))
- it.addState(StateSet.WILD_CARD, ContextCompat.getDrawable(itemView.context, R.drawable.icon_ap_badcase_default))
- }
- }
-
- @SuppressLint("NotifyDataSetChanged")
- fun bindData(case: Reason) {
- check.isSelected = case.isChecked
- reason.text = case.reason ?: ""
- if (case.isChecked) {
- ok?.isSelected = true
- }
- itemView.onClick {
- case.isChecked = !case.isChecked
- selectCase = case
- cancelOtherChecked(case)
- ok?.isEnabled = hasCheckedItem()
- rv_take_over?.adapter?.notifyDataSetChanged()
- }
- }
-
- private fun hasCheckedItem(): Boolean = cases?.find { it.isChecked } != null
-
- private fun cancelOtherChecked(case: Reason) {
- val cases = cases
- if (cases == null || cases.isEmpty()) {
- return
- }
- cases.filterNot { it == case }.forEach {
- it.isChecked = false
- }
- }
- }
-
- fun onDismiss(dismiss:() -> Unit) {
- this.dismiss = dismiss
- }
-
- fun onSelect(cb:(Reason) -> Unit) {
- this.select = cb
- }
-}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/fragment_hmi.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/fragment_hmi.xml
index fbbc1af7f3..e88f74560e 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/fragment_hmi.xml
+++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/fragment_hmi.xml
@@ -98,14 +98,14 @@
app:layout_constraintStart_toEndOf="@+id/viewPerspectiveSwitch"
app:layout_goneMarginStart="50px" />
-
diff --git a/core/mogo-core-function-api/build.gradle b/core/mogo-core-function-api/build.gradle
index a9303fa9ca..56faa70676 100644
--- a/core/mogo-core-function-api/build.gradle
+++ b/core/mogo-core-function-api/build.gradle
@@ -44,13 +44,16 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
implementation rootProject.ext.dependencies.arouter
+ implementation project(path: ':libraries:mogo-adas')
kapt rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.coroutinescore
implementation rootProject.ext.dependencies.coroutinesandroid
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
implementation rootProject.ext.dependencies.mogo_core_data
+ compileOnly rootProject.ext.dependencies.adasHigh
} else {
implementation project(':core:mogo-core-data')
+ compileOnly project(':libraries:mogo-adas')
}
}
diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt
index 18d9f6b400..c14aa1283f 100644
--- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt
+++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt
@@ -1,5 +1,7 @@
package com.mogo.eagle.core.function.api.devatools
+import android.view.View
+import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
import com.mogo.eagle.core.data.chain.ChainLogParam
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
@@ -18,4 +20,17 @@ interface IDevaToolsProvider : IMoGoFunctionServerProvider {
fun refreshTraceInfo(map: HashMap)
+ /**
+ * 初始化BadCase入口
+ * @param view: 展示入口
+ * @param onShow: BadCase入口展示时回调
+ * @param onHide: BadCase入口隐藏时回调
+ * 注: 此方法必须在[recoverBadCase]和[onReceiveBadCaseRecord]之前调用
+ */
+ fun initBadCase(view: View, onShow: (() -> Unit)? = null, onHide: (() -> Unit)? = null)
+
+ /**
+ * 当工控机回调时调用
+ */
+ fun onReceiveBadCaseRecord(record: AutoPilotRecordResult)
}
\ No newline at end of file
diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt
index 3f0f3304a4..343015d06f 100644
--- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt
+++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt
@@ -186,13 +186,6 @@ interface IMoGoWaringProvider {
fun showAdUpgradeStatus(upgradeMode : Int,downloadStatus : Int,currentProgress : Int,totalProgress : Int
,downloadVersion : String,upgradeStatus : Int)
- /**
- * 注册badcase入口展示和隐藏的回调
- * 当[onShow]被调用时,调用[showBadCaseEntrance]
- * [onHide]回调不用关心,可以不注册
- */
- fun registerBadCaseCallback(onShow:() -> View, onHide: (() -> Unit)?)
-
/**
*注册工控机升级提示圆点View的回调
* @param 提示圆点View
@@ -205,4 +198,11 @@ interface IMoGoWaringProvider {
* @param msg
*/
fun showDockerRebootResult(code: Int,msg: String)
+
+ /**
+ * @param floatView: 要展示的View
+ * @param tag: 唯一标识
+ * @return 触发消失时回调
+ */
+ fun showBadCaseFloat(tag: String = "BadCaseFloat", floatView: View): () -> Unit
}
\ No newline at end of file
diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt
index 115f9ac4cf..0b8b83a655 100644
--- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt
+++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt
@@ -1,5 +1,7 @@
package com.mogo.eagle.core.function.call.devatools
+import android.view.View
+import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
import com.mogo.eagle.core.data.chain.ChainLogParam
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider
@@ -7,7 +9,7 @@ import com.mogo.eagle.core.function.call.base.CallerBase
object CallerDevaToolsManager {
- private val devaToolsProviderApi: IDevaToolsProvider
+ private val devaToolsProviderApi: IDevaToolsProvider?
get() = CallerBase.getApiInstance(
IDevaToolsProvider::class.java,
MogoServicePaths.PATH_DEVA_TOOLS
@@ -17,7 +19,7 @@ object CallerDevaToolsManager {
* 开始抓取全量日志
*/
fun startCatchLog() {
- devaToolsProviderApi.startLogCatch()
+ devaToolsProviderApi?.startLogCatch()
}
/**
@@ -25,27 +27,41 @@ object CallerDevaToolsManager {
* duration 分钟数
*/
fun startCatchLog(duration: Int) {
- devaToolsProviderApi.startLogCatch(duration)
+ devaToolsProviderApi?.startLogCatch(duration)
}
/**
* 停止抓取全量日志
*/
fun stopCatchLog() {
- devaToolsProviderApi.stopLogCatch()
+ devaToolsProviderApi?.stopLogCatch()
}
/**
* 更新链路节点信息,是否写入
*/
fun refreshTraceInfo(map: HashMap) {
- devaToolsProviderApi.refreshTraceInfo(map)
+ devaToolsProviderApi?.refreshTraceInfo(map)
}
/**
* 获取链路节点信息
*/
fun getTraceInfo(): HashMap {
- return devaToolsProviderApi.getTraceInfo()
+ return devaToolsProviderApi?.getTraceInfo() ?: HashMap()
+ }
+
+ /**
+ * 初始化BadCase相关配置
+ */
+ fun initBadCase(view: View, onShow: (() -> Unit)? = null, onHide: (() -> Unit)? = null) {
+ devaToolsProviderApi?.initBadCase(view, onShow, onHide)
+ }
+
+ /**
+ * 收到工控机回调时触发
+ */
+ fun onReceiveBadCaseRecord(record: AutoPilotRecordResult) {
+ devaToolsProviderApi?.onReceiveBadCaseRecord(record)
}
}
\ No newline at end of file
diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt
index a7f5173590..14d166e65f 100644
--- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt
+++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt
@@ -264,15 +264,6 @@ object CallerHmiManager : CallerBase() {
waringProviderApi?.showAdUpgradeStatus(upgradeMode,downloadStatus, currentProgress, totalProgress, downloadVersion, upgradeStatus)
}
- /**
- * 注册badcase入口展示和隐藏的回调
- * 当[onShow]被调用时, 表示达到展示条件,返回展示的入口控件
- * [onHide]回调不用关心,可以不注册
- */
- fun registerBadCaseCallback(onShow:() -> View, onHide: (() -> Unit)?) {
- waringProviderApi?.registerBadCaseCallback(onShow, onHide)
- }
-
/**
*注册工控机升级提示圆点View的回调
* @param 提示圆点View
@@ -290,4 +281,10 @@ object CallerHmiManager : CallerBase() {
waringProviderApi?.showDockerRebootResult(code, msg)
}
+ /**
+ * 展示BadCase浮层
+ */
+ fun showBadCaseFloat(tag: String = "BadCaseFloat", floatView: View): (() -> Unit)? {
+ return waringProviderApi?.showBadCaseFloat(tag, floatView)
+ }
}
\ No newline at end of file