rebase
This commit is contained in:
@@ -3,6 +3,7 @@ package com.mogo.och.bus.fragment;
|
|||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -13,6 +14,8 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.constraintlayout.widget.Group;
|
import androidx.constraintlayout.widget.Group;
|
||||||
|
|
||||||
import com.mogo.commons.AbsMogoApplication;
|
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.MvpFragment;
|
||||||
import com.mogo.commons.mvp.Presenter;
|
import com.mogo.commons.mvp.Presenter;
|
||||||
import com.mogo.commons.voice.AIAssist;
|
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.api.autopilot.IMoGoAutopilotStatusListener;
|
||||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
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.function.call.hmi.CallerHmiManager;
|
||||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
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.BusArcView;
|
||||||
import com.mogo.och.bus.view.SlidePanelView;
|
import com.mogo.och.bus.view.SlidePanelView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
|
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
|
||||||
* <p>
|
* <p>
|
||||||
@@ -42,7 +54,7 @@ import com.mogo.och.bus.view.SlidePanelView;
|
|||||||
*
|
*
|
||||||
* @author tongchenfei
|
* @author tongchenfei
|
||||||
*/
|
*/
|
||||||
public abstract class BaseOchBusTabFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> implements IMogoMapListener {
|
public abstract class BaseOchBusTabFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> implements IMogoMapListener, IMoGoAutopilotIdentifyListener {
|
||||||
|
|
||||||
private static final String TAG = "BaseOchFragment";
|
private static final String TAG = "BaseOchFragment";
|
||||||
|
|
||||||
@@ -200,17 +212,45 @@ public abstract class BaseOchBusTabFragment<V extends IView, P extends Presenter
|
|||||||
|
|
||||||
// mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理
|
// mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理
|
||||||
mBadcaseBtn = findViewById(R.id.module_mogo_och_badcase_iv);
|
mBadcaseBtn = findViewById(R.id.module_mogo_och_badcase_iv);
|
||||||
CallerHmiManager.INSTANCE.registerBadCaseCallback(
|
// CallerHmiManager.INSTANCE.registerBadCaseCallback(
|
||||||
() -> { // onShow()
|
// () -> { // onShow()
|
||||||
return mBadcaseBtn; },
|
// return mBadcaseBtn; },
|
||||||
() -> { // onHide()
|
// () -> { // onHide()
|
||||||
return null; });
|
// 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);
|
mUpgradeTipIv = findViewById(R.id.module_och_bus_upgrade_red_tip);
|
||||||
CallerHmiManager.INSTANCE.registerUpgradeTipsCallback(() -> mUpgradeTipIv);
|
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> trafficData) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAutopilotWarnMessage(@Nullable AutopilotWarnMessage autopilotWarnMessage) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试到站
|
* 测试到站
|
||||||
*/
|
*/
|
||||||
@@ -367,11 +407,6 @@ public abstract class BaseOchBusTabFragment<V extends IView, P extends Presenter
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.mogo.och.taxi.ui;
|
|||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.drawable.AnimationDrawable;
|
import android.graphics.drawable.AnimationDrawable;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -15,6 +16,8 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.constraintlayout.widget.Group;
|
import androidx.constraintlayout.widget.Group;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
@@ -24,10 +27,17 @@ import com.mogo.commons.mvp.IView;
|
|||||||
import com.mogo.commons.mvp.MvpFragment;
|
import com.mogo.commons.mvp.MvpFragment;
|
||||||
import com.mogo.commons.mvp.Presenter;
|
import com.mogo.commons.mvp.Presenter;
|
||||||
import com.mogo.commons.voice.AIAssist;
|
import com.mogo.commons.voice.AIAssist;
|
||||||
|
import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult;
|
||||||
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters;
|
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters;
|
||||||
|
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.api.autopilot.IMoGoAutopilotStatusListener;
|
||||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
|
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
|
||||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
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.function.call.hmi.CallerHmiManager;
|
||||||
import com.mogo.eagle.core.function.call.map.CallerSmpManager;
|
import com.mogo.eagle.core.function.call.map.CallerSmpManager;
|
||||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||||
@@ -38,6 +48,8 @@ import com.mogo.module.common.constants.DataTypes;
|
|||||||
import com.mogo.module.common.view.OnPreventFastClickListener;
|
import com.mogo.module.common.view.OnPreventFastClickListener;
|
||||||
import com.mogo.och.taxi.R;
|
import com.mogo.och.taxi.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
|
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
|
||||||
@@ -46,7 +58,7 @@ import com.mogo.och.taxi.R;
|
|||||||
*
|
*
|
||||||
* @author tongchenfei
|
* @author tongchenfei
|
||||||
*/
|
*/
|
||||||
public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> implements IMogoMapListener {
|
public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> implements IMogoMapListener, IMoGoAutopilotIdentifyListener {
|
||||||
|
|
||||||
private static final String TAG = "BaseOchFragment";
|
private static final String TAG = "BaseOchFragment";
|
||||||
private LinearLayout ctvAutopilotStatus;
|
private LinearLayout ctvAutopilotStatus;
|
||||||
@@ -133,12 +145,18 @@ public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presente
|
|||||||
|
|
||||||
// mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理
|
// mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理
|
||||||
mBadcaseBtn = findViewById(R.id.module_och_taxi_badcase_iv);
|
mBadcaseBtn = findViewById(R.id.module_och_taxi_badcase_iv);
|
||||||
CallerHmiManager.INSTANCE.registerBadCaseCallback(
|
// CallerHmiManager.INSTANCE.registerBadCaseCallback(
|
||||||
() -> { // onShow()
|
// () -> { // onShow()
|
||||||
return mBadcaseBtn; },
|
// return mBadcaseBtn; },
|
||||||
() -> { // onHide()
|
// () -> { // onHide()
|
||||||
return null; });
|
// 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);
|
mUpgradeTipIv = findViewById(R.id.module_och_taxi_upgrade_red_tip);
|
||||||
CallerHmiManager.INSTANCE.registerUpgradeTipsCallback(() -> mUpgradeTipIv);
|
CallerHmiManager.INSTANCE.registerUpgradeTipsCallback(() -> mUpgradeTipIv);
|
||||||
@@ -240,6 +258,29 @@ public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presente
|
|||||||
protected void onGoToTaxiOrders(){
|
protected void onGoToTaxiOrders(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (!HmiBuildConfig.isShowBadCaseView) {
|
||||||
|
CallerAutopilotIdentifyListenerManager.INSTANCE.removeListener(TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAutopilotIdentifyDataUpdate(@Nullable ArrayList<TrafficData> 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) {
|
public void showNotice(String notice) {
|
||||||
getActivity().runOnUiThread(() -> {
|
getActivity().runOnUiThread(() -> {
|
||||||
AIAssist.getInstance(getContext()).speakTTSVoice(notice);
|
AIAssist.getInstance(getContext()).speakTTSVoice(notice);
|
||||||
@@ -409,11 +450,6 @@ public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presente
|
|||||||
return panelView;
|
return panelView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -234,16 +234,23 @@ dependencies {
|
|||||||
|
|
||||||
compileOnly rootProject.ext.dependencies.adasapi
|
compileOnly rootProject.ext.dependencies.adasapi
|
||||||
compileOnly rootProject.ext.dependencies.adasconfigapi
|
compileOnly rootProject.ext.dependencies.adasconfigapi
|
||||||
|
|
||||||
debugImplementation rootProject.ext.dependencies.debugleakcanary
|
debugImplementation rootProject.ext.dependencies.debugleakcanary
|
||||||
releaseImplementation rootProject.ext.dependencies.releaseleakcanary
|
releaseImplementation rootProject.ext.dependencies.releaseleakcanary
|
||||||
|
|
||||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||||
implementation rootProject.ext.dependencies.mogo_core_function_main
|
implementation rootProject.ext.dependencies.mogo_core_function_main
|
||||||
implementation rootProject.ext.dependencies.ttspad
|
implementation rootProject.ext.dependencies.ttspad
|
||||||
|
androidTestImplementation rootProject.ext.dependencies.mogo_core_function_call
|
||||||
|
androidTestImplementation rootProject.ext.dependencies.mogo_core_res
|
||||||
|
androidTestImplementation rootProject.ext.dependencies.mogo_core_function_hmi
|
||||||
|
androidTestImplementation rootProject.ext.dependencies.mogo_core_function_notice
|
||||||
} else {
|
} else {
|
||||||
implementation project(':core:function-impl:mogo-core-function-main')
|
implementation project(':core:function-impl:mogo-core-function-main')
|
||||||
implementation project(':tts:tts-pad')
|
implementation project(':tts:tts-pad')
|
||||||
|
androidTestImplementation project(':core:mogo-core-function-call')
|
||||||
|
androidTestImplementation project(':core:mogo-core-res')
|
||||||
|
androidTestImplementation project(':core:function-impl:mogo-core-function-hmi')
|
||||||
|
androidTestImplementation project(':core:function-impl:mogo-core-function-notice')
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "./functions/och.gradle"
|
apply from: "./functions/och.gradle"
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package com.mogo.functions.test
|
package com.mogo.functions.test
|
||||||
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.test.core.app.ActivityScenario
|
import androidx.test.core.app.ActivityScenario
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.LargeTest
|
import androidx.test.filters.LargeTest
|
||||||
import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
|
import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult
|
||||||
import com.mogo.eagle.core.function.hmi.ui.MoGoHmiFragment
|
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||||
import com.mogo.eagle.core.function.main.MainLauncherActivity
|
import com.mogo.eagle.core.function.main.MainLauncherActivity
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
@@ -14,7 +13,6 @@ import org.junit.Test
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@@ -31,14 +29,14 @@ class AutoPilotBadCaseTest {
|
|||||||
|
|
||||||
@ExperimentalCoroutinesApi @Test
|
@ExperimentalCoroutinesApi @Test
|
||||||
fun showBadCaseEntrance1(): Unit = runBlocking(Dispatchers.Main) {
|
fun showBadCaseEntrance1(): Unit = runBlocking(Dispatchers.Main) {
|
||||||
val f = ensureMoGoHmiFragmentShow()
|
delay(5000)
|
||||||
var index = 0
|
var index = 0
|
||||||
(1 until 50)
|
(1 until 50)
|
||||||
.map { it }
|
.map { it }
|
||||||
.asFlow()
|
.asFlow()
|
||||||
.onEach {
|
.onEach {
|
||||||
delay(TimeUnit.SECONDS.toMillis(5))
|
delay(TimeUnit.SECONDS.toMillis(5))
|
||||||
f.onAutopilotRecordResult(AutoPilotRecordResult().also {
|
CallerDevaToolsManager.onReceiveBadCaseRecord(AutoPilotRecordResult().also {
|
||||||
it.diskFree = (100 + index).toLong()
|
it.diskFree = (100 + index).toLong()
|
||||||
it.duration = 60.0
|
it.duration = 60.0
|
||||||
it.fileName = "/user/general/record_$index.log"
|
it.fileName = "/user/general/record_$index.log"
|
||||||
@@ -58,7 +56,7 @@ class AutoPilotBadCaseTest {
|
|||||||
|
|
||||||
@ExperimentalCoroutinesApi @Test
|
@ExperimentalCoroutinesApi @Test
|
||||||
fun showBadCaseEntrance2():Unit = runBlocking(Dispatchers.Main) {
|
fun showBadCaseEntrance2():Unit = runBlocking(Dispatchers.Main) {
|
||||||
val f = ensureMoGoHmiFragmentShow()
|
delay(5000)
|
||||||
var index = 0
|
var index = 0
|
||||||
(1 until 50)
|
(1 until 50)
|
||||||
.map { it }
|
.map { it }
|
||||||
@@ -69,7 +67,7 @@ class AutoPilotBadCaseTest {
|
|||||||
} else {
|
} else {
|
||||||
delay(Random(20).nextLong())
|
delay(Random(20).nextLong())
|
||||||
}
|
}
|
||||||
f.onAutopilotRecordResult(AutoPilotRecordResult().also {
|
CallerDevaToolsManager.onReceiveBadCaseRecord(AutoPilotRecordResult().also {
|
||||||
it.diskFree = (100 + index).toLong()
|
it.diskFree = (100 + index).toLong()
|
||||||
it.duration = 60.0
|
it.duration = 60.0
|
||||||
it.fileName = "/user/general/record_$index.log"
|
it.fileName = "/user/general/record_$index.log"
|
||||||
@@ -80,11 +78,6 @@ class AutoPilotBadCaseTest {
|
|||||||
it.timestamp = SimpleDateFormat("yyyyMMddHHmmss").format(Date())
|
it.timestamp = SimpleDateFormat("yyyyMMddHHmmss").format(Date())
|
||||||
index++
|
index++
|
||||||
})
|
})
|
||||||
|
|
||||||
if (index == 5) {
|
|
||||||
f.lifecycleScope.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.flowOn(Dispatchers.Default)
|
.flowOn(Dispatchers.Default)
|
||||||
.collect()
|
.collect()
|
||||||
@@ -93,14 +86,13 @@ class AutoPilotBadCaseTest {
|
|||||||
|
|
||||||
@ExperimentalCoroutinesApi @Test
|
@ExperimentalCoroutinesApi @Test
|
||||||
fun showBadCaseEntrance3(): Unit = runBlocking(Dispatchers.Main) {
|
fun showBadCaseEntrance3(): Unit = runBlocking(Dispatchers.Main) {
|
||||||
val f = ensureMoGoHmiFragmentShow()
|
|
||||||
var index = 0
|
var index = 0
|
||||||
(1 until 50)
|
(1 until 50)
|
||||||
.map { it }
|
.map { it }
|
||||||
.asFlow()
|
.asFlow()
|
||||||
.onEach {
|
.onEach {
|
||||||
delay(TimeUnit.SECONDS.toMillis(20))
|
delay(TimeUnit.SECONDS.toMillis(20))
|
||||||
f.onAutopilotRecordResult(AutoPilotRecordResult().also {
|
CallerDevaToolsManager.onReceiveBadCaseRecord(AutoPilotRecordResult().also {
|
||||||
it.diskFree = (100 + index).toLong()
|
it.diskFree = (100 + index).toLong()
|
||||||
it.duration = 60.0
|
it.duration = 60.0
|
||||||
it.fileName = "/user/general/record_$index.log"
|
it.fileName = "/user/general/record_$index.log"
|
||||||
@@ -116,30 +108,4 @@ class AutoPilotBadCaseTest {
|
|||||||
.collect()
|
.collect()
|
||||||
delay(TimeUnit.HOURS.toMillis(2))
|
delay(TimeUnit.HOURS.toMillis(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun ensureMoGoHmiFragmentShow(): MoGoHmiFragment = suspendCancellableCoroutine {
|
|
||||||
launch.onActivity { itx ->
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ plugins {
|
|||||||
id 'kotlin-android-extensions'
|
id 'kotlin-android-extensions'
|
||||||
id 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
id 'com.alibaba.arouter'
|
id 'com.alibaba.arouter'
|
||||||
|
id 'com.google.protobuf'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -39,21 +40,45 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_1_8
|
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 {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
|
||||||
implementation rootProject.ext.dependencies.coroutinescore
|
|
||||||
implementation rootProject.ext.dependencies.arouter
|
implementation rootProject.ext.dependencies.arouter
|
||||||
kapt rootProject.ext.dependencies.aroutercompiler
|
kapt rootProject.ext.dependencies.aroutercompiler
|
||||||
implementation rootProject.ext.dependencies.mogologlib
|
implementation rootProject.ext.dependencies.mogologlib
|
||||||
implementation rootProject.ext.dependencies.mogochainbase
|
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)) {
|
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||||
implementation rootProject.ext.dependencies.modulecommon
|
implementation rootProject.ext.dependencies.modulecommon
|
||||||
|
|
||||||
implementation rootProject.ext.dependencies.mogo_core_utils
|
implementation rootProject.ext.dependencies.mogo_core_utils
|
||||||
implementation rootProject.ext.dependencies.mogo_core_function_api
|
implementation rootProject.ext.dependencies.mogo_core_function_api
|
||||||
implementation rootProject.ext.dependencies.mogo_core_function_call
|
implementation rootProject.ext.dependencies.mogo_core_function_call
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package com.zhjt.mogo_core_function_devatools
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
import com.alibaba.android.arouter.facade.annotation.Route
|
import com.alibaba.android.arouter.facade.annotation.Route
|
||||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
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_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_ADAS_MSG
|
||||||
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CONNECT_STATUS
|
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.mogo.eagle.core.utilcode.util.Utils
|
||||||
import com.zhidao.loglib.fw.FileWriteManager
|
import com.zhidao.loglib.fw.FileWriteManager
|
||||||
import com.zhidao.loglib.fw.FwBuild
|
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.mogo_core_function_devatools.logcatch.MogoLogCatchManager
|
||||||
import com.zhjt.service.chain.core.ChainTraceStarter
|
import com.zhjt.service.chain.core.ChainTraceStarter
|
||||||
|
|
||||||
@@ -100,6 +103,14 @@ class DevaToolsProvider : IDevaToolsProvider {
|
|||||||
FileWriteManager.getInstance().operateChainMap(fwBuildMap)
|
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() {
|
override fun onDestroy() {
|
||||||
MogoLogCatchManager.onDestroy()
|
MogoLogCatchManager.onDestroy()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<View>? = null
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var dismissJob: Job? = null
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
private var channel: Channel<AutoPilotRecord> = 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<AutoPilotRecord>()) {
|
||||||
|
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<String, String>().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: View> 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
|
||||||
|
}
|
||||||
@@ -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<String, String>): Response<UploadResult>
|
||||||
|
|
||||||
|
@GET("/yycp-vehicle-management-service/tool/badcase/reasons")
|
||||||
|
suspend fun get(): Response<BadCaseResponse>
|
||||||
|
}
|
||||||
@@ -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<Reason>? = 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String>? = null
|
||||||
|
var success: Boolean = false
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "UploadResult(code=$code, msg=$msg, data=${data?.contentToString()}, success=$success)"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -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<AutoPilotRecord> {
|
||||||
|
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<String, String>): 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Reason>? = 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<Reason>) {
|
||||||
|
cases = causes
|
||||||
|
rv_take_over?.let {
|
||||||
|
it.layoutManager = LinearLayoutManager(it.context, LinearLayoutManager.VERTICAL, false)
|
||||||
|
it.adapter = object : RecyclerView.Adapter<BadCaseViewHolder>() {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Reason>
|
||||||
|
|
||||||
|
suspend fun updateLastModified(timestamp: Long)
|
||||||
|
|
||||||
|
suspend fun getLastModified(): Long
|
||||||
|
|
||||||
|
suspend fun upload(map: Map<String, String>): UploadResult?
|
||||||
|
|
||||||
|
suspend fun insertRecord(record: AutoPilotRecord)
|
||||||
|
|
||||||
|
suspend fun getUnConsumedRecords(): List<AutoPilotRecord>
|
||||||
|
|
||||||
|
suspend fun deleteRecord(record: AutoPilotRecord)
|
||||||
|
}
|
||||||
@@ -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<Reason> {
|
||||||
|
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<Reason> {
|
||||||
|
Log.d(BadCaseManager.TAG, "-- load cases from buildin -- 1 --")
|
||||||
|
val data = mutableListOf<Reason>()
|
||||||
|
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<String, String>): 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<AutoPilotRecord>? {
|
||||||
|
return db.dao().getAllUnConsumedRecords()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<AutoPilotRecord>?
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<String, String>): 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<BadCauses> {
|
||||||
|
|
||||||
|
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<Unit> {
|
||||||
|
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<BadCauses> by lazy {
|
||||||
|
DataStoreFactory.create(serializer = serializer) { File(Utils.getApp().filesDir, "bad_cases.pb") }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateRecords(reasons: List<Reason>): BadCauses {
|
||||||
|
Log.d(BadCaseManager.TAG, "--- updateRecords ---")
|
||||||
|
val data = mutableListOf<Cause>()
|
||||||
|
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<Reason> {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -38,6 +38,10 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -2,21 +2,14 @@ package com.mogo.eagle.core.function.hmi.ui
|
|||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.animation.OvershootInterpolator
|
import android.view.animation.OvershootInterpolator
|
||||||
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
|
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.transition.AutoTransition
|
|
||||||
import androidx.transition.TransitionManager
|
|
||||||
import com.alibaba.android.arouter.facade.annotation.Route
|
import com.alibaba.android.arouter.facade.annotation.Route
|
||||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
|
||||||
import com.mogo.commons.mvp.MvpFragment
|
import com.mogo.commons.mvp.MvpFragment
|
||||||
import com.mogo.commons.voice.AIAssist
|
import com.mogo.commons.voice.AIAssist
|
||||||
import com.mogo.eagle.core.data.autopilot.AdUpgradeStateHelper
|
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.autopilot.IMoGoAutopilotIdentifyListener
|
||||||
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWaringProvider
|
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.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.autopilot.CallerAutopilotIdentifyListenerManager
|
||||||
import com.mogo.eagle.core.function.call.check.CallerCheckManager
|
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.map.CallerMapDataCollectorManager
|
||||||
import com.mogo.eagle.core.function.call.monitor.CallerMonitorManager
|
import com.mogo.eagle.core.function.call.monitor.CallerMonitorManager
|
||||||
import com.mogo.eagle.core.function.hmi.R
|
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.notice.NoticeNormalBannerView
|
||||||
import com.mogo.eagle.core.function.hmi.ui.setting.DebugSettingView
|
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.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.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.mogo.logger.Logger
|
||||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||||
|
import com.mogo.eagle.core.utilcode.util.Utils
|
||||||
import com.mogo.module.common.enums.EventTypeEnum
|
import com.mogo.module.common.enums.EventTypeEnum
|
||||||
import kotlinx.android.synthetic.main.fragment_hmi.*
|
import kotlinx.android.synthetic.main.fragment_hmi.*
|
||||||
import kotlinx.coroutines.*
|
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.*
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiaoyuzhou
|
* @author xiaoyuzhou
|
||||||
@@ -94,132 +79,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
// 检测、自动驾驶速度设置
|
// 检测、自动驾驶速度设置
|
||||||
private var toolsViewFloat: WarningFloat.Builder? = null
|
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
|
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<AutoPilotRecordResult?>(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) {
|
override fun vipIdentification(visible: Boolean) {
|
||||||
ThreadUtils.runOnUiThread {
|
ThreadUtils.runOnUiThread {
|
||||||
Logger.d(TAG, "vipIdentification")
|
Logger.d(TAG, "vipIdentification")
|
||||||
@@ -260,18 +121,6 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
|
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
|
/*// TODO 这里后面需要改成独立进程通讯后台获取YUV
|
||||||
view.postDelayed({
|
view.postDelayed({
|
||||||
@@ -282,21 +131,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
override fun onAutopilotRecordResult(record: AutoPilotRecordResult?) {
|
override fun onAutopilotRecordResult(record: AutoPilotRecordResult?) {
|
||||||
record ?: return
|
record ?: return
|
||||||
Log.d("QQQ", "onAutopilotRecordResult:$record")
|
if (HmiBuildConfig.isShowBadCaseView && record.type == 1 && record.stat == 100) {
|
||||||
if (record.type == 1 && record.stat == 100) {
|
CallerDevaToolsManager.onReceiveBadCaseRecord(record)
|
||||||
lifecycleScope.launchWhenResumed {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
val dao = Repository.dao()
|
|
||||||
try {
|
|
||||||
dao.insertRecord(record)
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
t.printStackTrace()
|
|
||||||
}
|
|
||||||
record.also {
|
|
||||||
channel.send(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (record.type == 2 && (record.stat == 101 || record.stat == 100)) {
|
if (record.type == 2 && (record.stat == 101 || record.stat == 100)) {
|
||||||
CallerMapDataCollectorManager.finish(record.id, record.stat, "", record.fileName ?: "", record.note ?: "")
|
CallerMapDataCollectorManager.finish(record.id, record.stat, "", record.fileName ?: "", record.note ?: "")
|
||||||
@@ -308,61 +144,6 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
|
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的回调
|
*注册工控机升级提示圆点View的回调
|
||||||
@@ -391,116 +172,6 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<String, String>()
|
|
||||||
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() {
|
private fun showToolsFloat() {
|
||||||
Logger.d(TAG, "showToolsFloat")
|
Logger.d(TAG, "showToolsFloat")
|
||||||
@@ -597,6 +268,10 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
} else {
|
} else {
|
||||||
setToolsViewVisibility(View.GONE)
|
setToolsViewVisibility(View.GONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HmiBuildConfig.isShowBadCaseView) {
|
||||||
|
CallerDevaToolsManager.initBadCase(vsBadCaseToolsView)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLayoutId(): Int {
|
override fun getLayoutId(): Int {
|
||||||
@@ -1125,18 +800,54 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dismissBadCaseFloatView() {
|
override fun showBadCaseFloat(tag: String, floatView: View): () -> Unit {
|
||||||
autoPilotToolsFloat?.let {
|
WarningFloat.with(context ?: Utils.getApp())
|
||||||
WarningFloat.dismiss(it.config.floatTag, false)
|
.setTag(tag)
|
||||||
autoPilotToolsFloat = null
|
.setLayout(floatView)
|
||||||
autoPilotBadCaseView = null
|
.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() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
Log.d(TAG, "onDestroy")
|
Log.d(TAG, "onDestroy")
|
||||||
handler.removeCallbacksAndMessages(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<AutoPilotRecordResult>?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BadCaseApi {
|
|
||||||
|
|
||||||
@FormUrlEncoded
|
|
||||||
@POST("/yycp-vehicle-management-service/tool/badcase/add")
|
|
||||||
suspend fun post(@FieldMap map: Map<String, String>): Response<PostResult>
|
|
||||||
|
|
||||||
@GET("/yycp-vehicle-management-service/tool/badcase/reasons")
|
|
||||||
suspend fun get(): Response<BadCaseEntity>
|
|
||||||
}
|
|
||||||
|
|
||||||
@Keep
|
|
||||||
class BadCaseEntity {
|
|
||||||
var code: Int = -1
|
|
||||||
var data: List<Reason>? = 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<String>? = 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<String, String>): Response<PostResult> {
|
|
||||||
return MoGoRetrofitFactory.getInstance(getHost()).create(BadCaseApi::class.java).post(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun get(): Response<BadCaseEntity>? {
|
|
||||||
return try { MoGoRetrofitFactory.getInstance(getHost()).create(BadCaseApi::class.java).get() } catch (t: Throwable) { t.printStackTrace(); null}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun updateCache(entity: BadCaseEntity) = suspendCancellableCoroutine<Unit> {
|
|
||||||
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<Reason>()
|
|
||||||
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<Reason>? = 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<BadCaseViewHolder>() {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -98,14 +98,14 @@
|
|||||||
app:layout_constraintStart_toEndOf="@+id/viewPerspectiveSwitch"
|
app:layout_constraintStart_toEndOf="@+id/viewPerspectiveSwitch"
|
||||||
app:layout_goneMarginStart="50px" />
|
app:layout_goneMarginStart="50px" />
|
||||||
|
|
||||||
<ViewStub
|
<ImageView
|
||||||
android:id="@+id/vsBadCaseToolsView"
|
android:id="@+id/vsBadCaseToolsView"
|
||||||
android:inflatedId="@+id/badCaseToolsView"
|
|
||||||
android:layout_width="@dimen/module_hmi_check_size"
|
android:layout_width="@dimen/module_hmi_check_size"
|
||||||
android:layout_height="@dimen/module_hmi_check_size"
|
android:layout_height="@dimen/module_hmi_check_size"
|
||||||
android:layout_marginStart="25px"
|
android:layout_marginStart="25px"
|
||||||
android:layout_marginBottom="40px"
|
android:layout_marginBottom="40px"
|
||||||
android:layout="@layout/view_ap_badcase_entrance"
|
android:visibility="gone"
|
||||||
|
android:background="@drawable/icon_car_ap_badcase_entrance"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/ivToolsIcon"
|
app:layout_constraintStart_toEndOf="@+id/ivToolsIcon"
|
||||||
app:layout_goneMarginStart="50px"/>
|
app:layout_goneMarginStart="50px"/>
|
||||||
|
|||||||
@@ -44,13 +44,16 @@ dependencies {
|
|||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
||||||
implementation rootProject.ext.dependencies.arouter
|
implementation rootProject.ext.dependencies.arouter
|
||||||
|
implementation project(path: ':libraries:mogo-adas')
|
||||||
kapt rootProject.ext.dependencies.aroutercompiler
|
kapt rootProject.ext.dependencies.aroutercompiler
|
||||||
implementation rootProject.ext.dependencies.coroutinescore
|
implementation rootProject.ext.dependencies.coroutinescore
|
||||||
implementation rootProject.ext.dependencies.coroutinesandroid
|
implementation rootProject.ext.dependencies.coroutinesandroid
|
||||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||||
implementation rootProject.ext.dependencies.mogo_core_data
|
implementation rootProject.ext.dependencies.mogo_core_data
|
||||||
|
compileOnly rootProject.ext.dependencies.adasHigh
|
||||||
} else {
|
} else {
|
||||||
implementation project(':core:mogo-core-data')
|
implementation project(':core:mogo-core-data')
|
||||||
|
compileOnly project(':libraries:mogo-adas')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.mogo.eagle.core.function.api.devatools
|
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.data.chain.ChainLogParam
|
||||||
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
|
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
|
||||||
|
|
||||||
@@ -18,4 +20,17 @@ interface IDevaToolsProvider : IMoGoFunctionServerProvider {
|
|||||||
|
|
||||||
fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>)
|
fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化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)
|
||||||
}
|
}
|
||||||
@@ -186,13 +186,6 @@ interface IMoGoWaringProvider {
|
|||||||
fun showAdUpgradeStatus(upgradeMode : Int,downloadStatus : Int,currentProgress : Int,totalProgress : Int
|
fun showAdUpgradeStatus(upgradeMode : Int,downloadStatus : Int,currentProgress : Int,totalProgress : Int
|
||||||
,downloadVersion : String,upgradeStatus : Int)
|
,downloadVersion : String,upgradeStatus : Int)
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册badcase入口展示和隐藏的回调
|
|
||||||
* 当[onShow]被调用时,调用[showBadCaseEntrance]
|
|
||||||
* [onHide]回调不用关心,可以不注册
|
|
||||||
*/
|
|
||||||
fun registerBadCaseCallback(onShow:() -> View, onHide: (() -> Unit)?)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*注册工控机升级提示圆点View的回调
|
*注册工控机升级提示圆点View的回调
|
||||||
* @param 提示圆点View
|
* @param 提示圆点View
|
||||||
@@ -205,4 +198,11 @@ interface IMoGoWaringProvider {
|
|||||||
* @param msg
|
* @param msg
|
||||||
*/
|
*/
|
||||||
fun showDockerRebootResult(code: Int,msg: String)
|
fun showDockerRebootResult(code: Int,msg: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param floatView: 要展示的View
|
||||||
|
* @param tag: 唯一标识
|
||||||
|
* @return 触发消失时回调
|
||||||
|
*/
|
||||||
|
fun showBadCaseFloat(tag: String = "BadCaseFloat", floatView: View): () -> Unit
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.mogo.eagle.core.function.call.devatools
|
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.chain.ChainLogParam
|
||||||
import com.mogo.eagle.core.data.constants.MogoServicePaths
|
import com.mogo.eagle.core.data.constants.MogoServicePaths
|
||||||
import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider
|
import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider
|
||||||
@@ -7,7 +9,7 @@ import com.mogo.eagle.core.function.call.base.CallerBase
|
|||||||
|
|
||||||
object CallerDevaToolsManager {
|
object CallerDevaToolsManager {
|
||||||
|
|
||||||
private val devaToolsProviderApi: IDevaToolsProvider
|
private val devaToolsProviderApi: IDevaToolsProvider?
|
||||||
get() = CallerBase.getApiInstance(
|
get() = CallerBase.getApiInstance(
|
||||||
IDevaToolsProvider::class.java,
|
IDevaToolsProvider::class.java,
|
||||||
MogoServicePaths.PATH_DEVA_TOOLS
|
MogoServicePaths.PATH_DEVA_TOOLS
|
||||||
@@ -17,7 +19,7 @@ object CallerDevaToolsManager {
|
|||||||
* 开始抓取全量日志
|
* 开始抓取全量日志
|
||||||
*/
|
*/
|
||||||
fun startCatchLog() {
|
fun startCatchLog() {
|
||||||
devaToolsProviderApi.startLogCatch()
|
devaToolsProviderApi?.startLogCatch()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,27 +27,41 @@ object CallerDevaToolsManager {
|
|||||||
* duration 分钟数
|
* duration 分钟数
|
||||||
*/
|
*/
|
||||||
fun startCatchLog(duration: Int) {
|
fun startCatchLog(duration: Int) {
|
||||||
devaToolsProviderApi.startLogCatch(duration)
|
devaToolsProviderApi?.startLogCatch(duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止抓取全量日志
|
* 停止抓取全量日志
|
||||||
*/
|
*/
|
||||||
fun stopCatchLog() {
|
fun stopCatchLog() {
|
||||||
devaToolsProviderApi.stopLogCatch()
|
devaToolsProviderApi?.stopLogCatch()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新链路节点信息,是否写入
|
* 更新链路节点信息,是否写入
|
||||||
*/
|
*/
|
||||||
fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>) {
|
fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>) {
|
||||||
devaToolsProviderApi.refreshTraceInfo(map)
|
devaToolsProviderApi?.refreshTraceInfo(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取链路节点信息
|
* 获取链路节点信息
|
||||||
*/
|
*/
|
||||||
fun getTraceInfo(): HashMap<Int, ChainLogParam> {
|
fun getTraceInfo(): HashMap<Int, ChainLogParam> {
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,15 +264,6 @@ object CallerHmiManager : CallerBase() {
|
|||||||
waringProviderApi?.showAdUpgradeStatus(upgradeMode,downloadStatus, currentProgress, totalProgress, downloadVersion, upgradeStatus)
|
waringProviderApi?.showAdUpgradeStatus(upgradeMode,downloadStatus, currentProgress, totalProgress, downloadVersion, upgradeStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册badcase入口展示和隐藏的回调
|
|
||||||
* 当[onShow]被调用时, 表示达到展示条件,返回展示的入口控件
|
|
||||||
* [onHide]回调不用关心,可以不注册
|
|
||||||
*/
|
|
||||||
fun registerBadCaseCallback(onShow:() -> View, onHide: (() -> Unit)?) {
|
|
||||||
waringProviderApi?.registerBadCaseCallback(onShow, onHide)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*注册工控机升级提示圆点View的回调
|
*注册工控机升级提示圆点View的回调
|
||||||
* @param 提示圆点View
|
* @param 提示圆点View
|
||||||
@@ -290,4 +281,10 @@ object CallerHmiManager : CallerBase() {
|
|||||||
waringProviderApi?.showDockerRebootResult(code, msg)
|
waringProviderApi?.showDockerRebootResult(code, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展示BadCase浮层
|
||||||
|
*/
|
||||||
|
fun showBadCaseFloat(tag: String = "BadCaseFloat", floatView: View): (() -> Unit)? {
|
||||||
|
return waringProviderApi?.showBadCaseFloat(tag, floatView)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user