diff --git a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java index 1b40d17144..27fdd1e6c7 100644 --- a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java +++ b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java @@ -288,6 +288,10 @@ public class BusPassengerModel { private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener(){ + @Override + public void onAutopilotNotData(long timestamp) { + } + @Override public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java index 8f58e0116d..d9eb1a29eb 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java @@ -277,4 +277,8 @@ public class BusPresenter extends Presenter public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo) { } + + @Override + public void onAutopilotNotData(long timestamp) { + } } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java index 118dbfe391..75f488cb4f 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java @@ -482,6 +482,11 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener(){ + + @Override + public void onAutopilotNotData(long timestamp) { + } + @Override public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java index d4a8b77bfa..da90193b91 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java @@ -1042,6 +1042,10 @@ public class TaxiModel { private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener() { + @Override + public void onAutopilotNotData(long timestamp) { + } + @Override public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { diff --git a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.kt b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.kt index 1ab3f18cc3..938b2e661a 100644 --- a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.kt +++ b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.kt @@ -148,6 +148,11 @@ class MoGoAdasListenerImpl : OnAdasListener { CallerAutopilotVehicleStateListenerManager.invokeAutopilotSteeringData(vehicleState.steering) //挂挡档位数据 CallerAutopilotVehicleStateListenerManager.invokeAutopilotGearData(vehicleState.gear) + } else { + /** + * 底盘没有返回数据 + */ + CallerAutopilotVehicleStateListenerManager.invokeAutopilotNotData(header.timestamp.toLong()) } } diff --git a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoHandAdasMsgManager.java b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoHandAdasMsgManager.java index 5f787317e7..c83ee74773 100644 --- a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoHandAdasMsgManager.java +++ b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoHandAdasMsgManager.java @@ -149,4 +149,8 @@ public class MoGoHandAdasMsgManager implements } + @Override + public void onAutopilotNotData(long timestamp) { + + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/AndroidManifest.xml b/core/function-impl/mogo-core-function-devatools/src/main/AndroidManifest.xml index 7a02e164bc..dc9cf1b26e 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/AndroidManifest.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt index 19bbea383e..955ee6414c 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt @@ -13,6 +13,7 @@ import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager import com.zhjt.mogo_core_function_devatools.feedback.FeedbackManager import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchManager import com.zhjt.mogo_core_function_devatools.scene.SceneManager.Companion.sceneManager +import com.zhjt.mogo_core_function_devatools.status.* import com.zhjt.mogo_core_function_devatools.trace.TraceManager.Companion.traceManager import com.zhjt.mogo_core_function_devatools.upgrade.UpgradeManager.Companion.upgradeManager import record_cache.RecordPanelOuterClass @@ -97,4 +98,7 @@ class DevaToolsProvider : IDevaToolsProvider { upgradeManager.downLoadPackage(mContext!!, downloadKey,downloadUrl) } + override fun showStatusBar(ctx: Context) { + StatusManager.init(ctx) + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt index 6bb8c3fdae..f7d9efc4ed 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt @@ -27,7 +27,7 @@ import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.B import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCasePresenter import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCaseView import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord -import com.zhjt.mogo_core_function_devatools.ext.pop +import com.zhjt.mogo_core_function_devatools.ext.enqueuePop import com.zhjt.mogo_core_function_devatools.ext.toast import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel @@ -263,7 +263,7 @@ internal object BadCaseManager : LifecycleEventObserver { val activity = viewHolder?.get()?.context as? FragmentActivity ?: throw IllegalStateException("please ensure context is FragmentActivity.") BadCaseView(activity).also { itx -> itx.register(record, onDismiss, onSelect) - activity.pop(itx, 960.PX, WindowManager.LayoutParams.MATCH_PARENT, key = "BadCaseFloatWindow_").also { + activity.enqueuePop(itx, 960.PX, WindowManager.LayoutParams.MATCH_PARENT, key = "BadCaseFloatWindow_").also { hideFloat = it } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/ext/BadCaseExt.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/ext/Extentions.kt similarity index 62% rename from core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/ext/BadCaseExt.kt rename to core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/ext/Extentions.kt index 11c549a3bf..25a3ccdd0b 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/ext/BadCaseExt.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/ext/Extentions.kt @@ -17,6 +17,7 @@ import android.view.animation.AccelerateDecelerateInterpolator import android.widget.PopupWindow import android.widget.PopupWindow.INPUT_METHOD_NEEDED import android.widget.TextView +import androidx.core.view.* import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope import com.mogo.eagle.core.utilcode.kotlin.PX @@ -26,7 +27,6 @@ import com.mogo.eagle.core.utilcode.kotlin.shape import com.mogo.eagle.core.utilcode.reminder.Reminder import com.mogo.eagle.core.utilcode.reminder.api.impl.PopupWindowReminder import com.mogo.eagle.core.utilcode.util.BarUtils -import com.mogo.eagle.core.utilcode.util.WindowUtils import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.util.concurrent.TimeUnit @@ -67,7 +67,7 @@ internal fun Context.toast(text: CharSequence, duration: Long = 2, unit: TimeUni } @SuppressLint("ClickableViewAccessibility") -internal fun Context.pop(content: View, width: Int, height: Int, key: String, onOuterViewClicked:((focus: View) -> Unit)? = null): () -> Unit { +fun Context.enqueuePop(content: View, width: Int, height: Int, key: String = "", startX: Int = 0, startY: Int = 0, gravity: Int = Gravity.START, onOuterViewClicked:((focus: View) -> Unit)? = null, isOverride: Boolean = false, isFocusable: Boolean = true): () -> Unit { val activity = (this as? FragmentActivity) ?: throw IllegalStateException("please use Activity to trigger pop show.") val isImmersiveMode = BarUtils.isImmersiveMode(activity) var tempReminder: PopupWindowReminder? = null @@ -75,11 +75,11 @@ internal fun Context.pop(content: View, width: Int, height: Int, key: String, on val pop = PopupWindow(width, height).also { it.isOutsideTouchable = true it.isTouchable = true - it.isFocusable = true + it.isFocusable = isFocusable it.inputMethodMode = INPUT_METHOD_NEEDED it.isClippingEnabled = false - var startX = 0f - var startY = 0f + var x = 0f + var y = 0f val touchSlop = ViewConfiguration.get(activity).scaledTouchSlop var isClicked = false it.setTouchInterceptor { v, event -> @@ -91,12 +91,12 @@ internal fun Context.pop(content: View, width: Int, height: Int, key: String, on when(event.actionMasked) { MotionEvent.ACTION_DOWN -> { - startX = event.x - startY = event.y + x = event.x + y = event.y } MotionEvent.ACTION_MOVE -> { - val deltaX = event.x - startX - val deltaY = event.y - startY + val deltaX = event.x - x + val deltaY = event.y - y isClicked = !(abs(deltaX) > touchSlop || abs(deltaY) > touchSlop) } MotionEvent.ACTION_UP -> { @@ -115,7 +115,7 @@ internal fun Context.pop(content: View, width: Int, height: Int, key: String, on it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) } if (VERSION.SDK_INT >= VERSION_CODES.M) { - val transition = Slide(Gravity.START).also { + val transition = Slide(gravity).also { it.interpolator = AccelerateDecelerateInterpolator() it.duration = 200 } @@ -130,9 +130,9 @@ internal fun Context.pop(content: View, width: Int, height: Int, key: String, on } override fun show() { - pop.showAtLocation(activity.window.decorView, Gravity.START, 0, if (isImmersiveMode) 0 else BarUtils.getStatusBarHeight()) + pop.showAtLocation(activity.window.decorView, gravity, startX, if (isImmersiveMode) 0 else BarUtils.getStatusBarHeight() + startY) } - override fun isOverride(): Boolean = false + override fun isOverride(): Boolean = isOverride } tempReminder = reminder Reminder.enqueue(activity.lifeCycleOwner, reminder) @@ -142,6 +142,94 @@ internal fun Context.pop(content: View, width: Int, height: Int, key: String, on } } + +@SuppressLint("ClickableViewAccessibility") +fun Context.normalPop(content: View, width: Int, height: Int, key: String = "", startX: Int = 0, startY: Int = 0, gravity: Int = Gravity.START, onOuterViewClicked:((focus: View) -> Unit)? = null, isFocusable: Boolean = true): () -> Unit { + val activity = (this as? FragmentActivity) ?: throw IllegalStateException("please use Activity to trigger pop show.") + val isImmersiveMode = BarUtils.isImmersiveMode(activity) + var tempPop: PopupWindow? = null + activity.lifecycleScope.launchWhenResumed { + val pop = PopupWindow(width, height).also { + tempPop = it + it.isOutsideTouchable = true + it.isTouchable = true + it.isFocusable = isFocusable + it.inputMethodMode = INPUT_METHOD_NEEDED + it.isClippingEnabled = false + var x = 0f + var y = 0f + val touchSlop = ViewConfiguration.get(activity).scaledTouchSlop + var isClicked = false + it.setTouchInterceptor { v, event -> + val out = Rect() + v.getGlobalVisibleRect(out) + if (out.contains(event.x.toInt(), event.y.toInt()) && isVisibleOnPoint(content, event.x.toInt(), event.y.toInt())) { + return@setTouchInterceptor false + } + + when(event.actionMasked) { + MotionEvent.ACTION_DOWN -> { + x = event.x + y = event.y + } + MotionEvent.ACTION_MOVE -> { + val deltaX = event.x - x + val deltaY = event.y - y + isClicked = !(abs(deltaX) > touchSlop || abs(deltaY) > touchSlop) + } + MotionEvent.ACTION_UP -> { + if (isClicked) { + isClicked = false + onOuterViewClicked?.invoke(v) + } + } + } + try { + return@setTouchInterceptor true + } finally { + activity.window.decorView.dispatchTouchEvent(event) + } + } + it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + } + if (VERSION.SDK_INT >= VERSION_CODES.M) { + val transition = Slide(gravity).also { + it.interpolator = AccelerateDecelerateInterpolator() + it.duration = 200 + } + pop.enterTransition = transition + pop.exitTransition = transition + } + pop.contentView = content + pop.showAtLocation(activity.window.decorView, gravity, startX, if (isImmersiveMode) 0 else BarUtils.getStatusBarHeight() + startY) + } + return { + tempPop?.takeIf { it.isShowing }?.dismiss() + } +} + +fun isVisibleOnPoint(content: View, x: Int, y: Int): Boolean { + if (content is ViewGroup) { + for (i in 0 until content.childCount) { + val child = content.getChildAt(i) + val out = Rect() + child.getGlobalVisibleRect(out) + if (out.contains(x, y) && !child.isVisible) { + return false + } + val ret = isVisibleOnPoint(child, x, y) + if (!ret) { + return false + } + } + return true + } else { + val out = Rect() + content.getGlobalVisibleRect(out) + return !(out.contains(x, y) && !content.isVisible) + } +} + internal fun FragmentActivity.softKeyboardHeightChanged(block: ((height: Int) -> Unit)): ()-> Unit { val decor = window.decorView var softKeyboardDisplayed = false diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt index 39444462fe..9931f8ef79 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt @@ -25,7 +25,7 @@ import com.zhjt.mogo_core_function_devatools.R import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason import com.zhjt.mogo_core_function_devatools.badcase.toRecord -import com.zhjt.mogo_core_function_devatools.ext.pop +import com.zhjt.mogo_core_function_devatools.ext.enqueuePop import com.zhjt.mogo_core_function_devatools.ext.toast import com.zhjt.mogo_core_function_devatools.feedback.biz.FeedBackView import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase @@ -46,7 +46,7 @@ internal object FeedbackManager { fun showFeedbackWindow(ctx: Context) { val activity = ctx as? FragmentActivity ?: throw IllegalStateException("please ensure context is FragmentActivity.") - activity.pop(FeedBackView(ctx).also { itx -> + activity.enqueuePop(FeedBackView(ctx).also { itx -> itx.registerCallback(object : IFeedbackCallback { override fun onClose(v: View) { KeyboardUtils.hideSoftInput(v) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/StatusManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/StatusManager.kt new file mode 100644 index 0000000000..765655b9f2 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/StatusManager.kt @@ -0,0 +1,99 @@ +package com.zhjt.mogo_core_function_devatools.status + +import android.content.* +import android.util.* +import android.view.* +import androidx.core.view.* +import androidx.lifecycle.* +import androidx.lifecycle.Lifecycle.Event +import androidx.lifecycle.Lifecycle.Event.ON_CREATE +import androidx.lifecycle.Lifecycle.Event.ON_DESTROY +import com.mogo.eagle.core.utilcode.kotlin.* +import com.zhjt.mogo_core_function_devatools.ext.* +import com.zhjt.mogo_core_function_devatools.status.entity.* +import com.zhjt.mogo_core_function_devatools.status.entity.CanStatus +import com.zhjt.mogo_core_function_devatools.status.entity.GpsStatus +import com.zhjt.mogo_core_function_devatools.status.entity.IpcStatus +import com.zhjt.mogo_core_function_devatools.status.entity.NetStatus +import com.zhjt.mogo_core_function_devatools.status.entity.RTKStatus +import com.zhjt.mogo_core_function_devatools.status.entity.Status +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus +import com.zhjt.mogo_core_function_devatools.status.model.StatusModel +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import com.zhjt.mogo_core_function_devatools.status.flow.can.CanImpl +import com.zhjt.mogo_core_function_devatools.status.flow.gps.GpsImpl +import com.zhjt.mogo_core_function_devatools.status.flow.ipc.IpcImpl +import com.zhjt.mogo_core_function_devatools.status.flow.nets.NetsImpl +import com.zhjt.mogo_core_function_devatools.status.flow.rtk.* +import com.zhjt.mogo_core_function_devatools.status.flow.rtk.RTKImpl +import com.zhjt.mogo_core_function_devatools.status.flow.trace.TracingImpl +import com.zhjt.mogo_core_function_devatools.status.ui.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* + +object StatusManager { + + private lateinit var model: StatusModel + + private var hidePop: (() -> Unit)? = null + + private val flows: ArrayList> by lazy { + ArrayList() + } + + fun init(ctx: Context) { + val owner = ctx as? ViewModelStoreOwner ?: throw IllegalStateException("ctx: $ctx is a instance of ViewModelStoreOwner.") + model = ViewModelProvider(owner).get(StatusModel::class.java) + ctx.lifeCycleOwner.lifecycle.addObserver(object : LifecycleEventObserver { + override fun onStateChanged(source: LifecycleOwner, event: Event) { + if (event == ON_CREATE) { + onCreate(ctx) + } + if (event == ON_DESTROY) { + onDestroy(ctx) + } + } + }) + } + + private fun onCreate(ctx: Context) { + val values = model.status.value?.second ?: throw IllegalStateException("state is not right.") + values.map { + when (it) { + is CanStatus -> CanImpl(ctx) + is IpcStatus -> IpcImpl(ctx) + is NetStatus -> NetsImpl(ctx) + is GpsStatus -> GpsImpl(ctx) + is TracingStatus -> TracingImpl(ctx) + is RTKStatus -> RTKImpl(ctx) + } + }.also { flows += it } + for (f in flows) { + ctx.lifeCycleScope.launch(Dispatchers.Default) { + f.asFlow().collect { + model.update(it) + } + } + } + hidePop?.invoke() + val content = StatusView(model, ctx) + content.doOnAttach { + Log.d("OOOO", "--- onAttach -----") + for (f in flows) { + f.onCreate() + } + } + + ctx.normalPop(content, + width = 665.PX, + height = WindowManager.LayoutParams.WRAP_CONTENT, + gravity = Gravity.END, + startX = 55.PX, + isFocusable = false).also { hidePop = it } + } + + private fun onDestroy(ctx: Context) { + flows.clear() + hidePop?.invoke() + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/entity/Status.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/entity/Status.kt new file mode 100644 index 0000000000..44354fcbb6 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/entity/Status.kt @@ -0,0 +1,191 @@ +package com.zhjt.mogo_core_function_devatools.status.entity + +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.* + +internal sealed class Status + +/** + * 工控机 + */ +internal class IpcStatus(val enabled: Boolean = false): Status() { + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + other as IpcStatus + if (enabled != other.enabled) return false + return true + } + + override fun hashCode(): Int { + return enabled.hashCode() + } + + override fun toString(): String { + return "IpcStatus(enabled=$enabled)" + } +} + +internal class NetStatus(val enabled: Boolean = false, val name: String? = null, val speed: Speed? = null): Status() { + class Speed(val tx: Int, val rx: Int) { + + override fun toString(): String { + return "Speed(tx=$tx, rx=$rx)" + } + } + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + other as NetStatus + if (enabled != other.enabled) return false + if (name != other.name) return false + return true + } + + override fun hashCode(): Int { + var result = enabled.hashCode() + result = 31 * result + (name?.hashCode() ?: 0) + return result + } + + override fun toString(): String { + return "NetStatus(enabled=$enabled, name=$name, speed=$speed)" + } +} + +/** + * android系统定位状态 + */ +internal class GpsStatus(val enabled: Boolean = false, val isGranted: Boolean = false): Status() { + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + + other as GpsStatus + if (enabled != other.enabled) return false + if (isGranted != other.isGranted) return false + return true + } + + override fun hashCode(): Int { + var result = enabled.hashCode() + result = 31 * result + isGranted.hashCode() + return result + } + + override fun toString(): String { + return "GpsStatus(enabled=$enabled, isGranted=$isGranted)" + } +} + +/** + * RTK/GNSS定位状态 + */ +internal class RTKStatus(val enabled: Boolean = false): Status() { + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + other as RTKStatus + if (enabled != other.enabled) return false + return true + } + + override fun hashCode(): Int { + return enabled.hashCode() + } +} + +/** + * Can总线 + */ +internal class CanStatus(val enabled: Boolean = false): Status() { + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + other as CanStatus + if (enabled != other.enabled) return false + return true + } + + override fun hashCode(): Int { + return enabled.hashCode() + } + + override fun toString(): String { + return "CanStatus(enabled=$enabled)" + } + + +} + +/** + * 寻迹/算路/未知 + */ +internal class TracingStatus(val state: Tracing): Status() { + + enum class Tracing(val code: String? = "") { + /** + * 寻迹-已找到轨迹文件 + */ + TRACK_FINDED("IMAP_TRA_EXIST"), + + /** + * 寻迹-轨迹文件加载成功 + */ + TRACK_LOADED("IMAP_TRA_LOADED"), + + /** + * 寻迹-没有找到轨迹文件 + */ + TRACK_NOT_EXIST("EMAP_TRA_NOT_EXIST"), + + /** + * 寻迹-找到了轨迹文件,加载失败了 + */ + TRACK_LOAD_FAIL("EMAP_TRA_LOAD_FAILED"), + + /** + * 算路加载成功 + */ + ROUTE_LOADED("IMAP_TRA_ROUTING"), + + /** + * 算路失败 + */ + ROUTE_FAILED("EMAP_HADMAP_ENGINE_NO_ROUTING_INFO"), + + UNKNOWN; + + fun isException(): Boolean = this == TRACK_FINDED || this == TRACK_NOT_EXIST || this == TRACK_LOAD_FAIL || this == ROUTE_FAILED || this == UNKNOWN + } + + override fun toString(): String { + return "TracingStatus(state=$state)" + } + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + + other as TracingStatus + + if (state != other.state) return false + + return true + } + + override fun hashCode(): Int { + return state.hashCode() + } +} + +internal fun String.toState(): Tracing { + return when(this) { + "IMAP_TRA_EXIST" -> TRACK_FINDED + "IMAP_TRA_LOADED" -> TRACK_LOADED + "EMAP_TRA_NOT_EXIST" -> TRACK_NOT_EXIST + "EMAP_TRA_LOAD_FAILED" -> TRACK_LOAD_FAIL + "IMAP_TRA_ROUTING" -> ROUTE_LOADED + "EMAP_HADMAP_ENGINE_NO_ROUTING_INFO" -> ROUTE_FAILED + else -> UNKNOWN + } +} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/IFlow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/IFlow.kt new file mode 100644 index 0000000000..93ed3adf10 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/IFlow.kt @@ -0,0 +1,51 @@ +package com.zhjt.mogo_core_function_devatools.status.flow + +import android.content.* +import android.util.* +import androidx.annotation.* +import com.mogo.eagle.core.utilcode.kotlin.* +import com.zhjt.mogo_core_function_devatools.status.entity.Status +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* +import kotlinx.coroutines.channels.Channel.Factory.CONFLATED +import kotlinx.coroutines.flow.* +import kotlin.OptIn +import kotlin.coroutines.* + +internal abstract class IFlow< T : Status>(val ctx: Context) : CoroutineScope { + + private val chl: Channel by lazy { + Channel(CONFLATED) + } + + @Volatile + private var old: T? = null + + override val coroutineContext: CoroutineContext + get() = ctx.lifeCycleScope.coroutineContext + + abstract fun onCreate() + + @OptIn(ExperimentalCoroutinesApi::class) + fun asFlow(): Flow = channelFlow { + val it = chl.iterator() + while (it.hasNext()) { + send(it.next()) + } + } + + fun send(t: T) { + if (old == t) { + return + } + old = t + launch { + chl.send(t) + } + } + + @CallSuper + open fun onDestroy() { + chl.safeCancel() + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/can/CanImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/can/CanImpl.kt new file mode 100644 index 0000000000..2ef890282e --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/can/CanImpl.kt @@ -0,0 +1,59 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.can + +import android.content.* +import android.util.* +import chassis.Chassis.GearPosition +import chassis.Chassis.LightSwitch +import com.mogo.eagle.core.data.autopilot.* +import com.mogo.eagle.core.function.api.autopilot.* +import com.mogo.eagle.core.function.call.autopilot.* +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import com.zhjt.mogo_core_function_devatools.status.entity.CanStatus + +internal class CanImpl(ctx: Context): IFlow(ctx), IMoGoAutopilotVehicleStateListener, IMoGoAutopilotStatusListener { + + companion object { + const val TAG = "CanImpl" + } + + override fun onCreate() { + Log.d(TAG, "-- onCreate --") + send(CanStatus(false)) + CallerAutopilotVehicleStateListenerManager.addListener(TAG, this) + CallerAutoPilotStatusListenerManager.addListener(TAG, this) + } + + override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { + super.onAutopilotStatusResponse(autoPilotStatusInfo) + if (!CallerAutoPilotManager.isConnected()) { + send(CanStatus(false)) + } + } + + override fun onAutopilotLightSwitchData(lightSwitch: LightSwitch?) { + send(CanStatus(true)) + } + + override fun onAutopilotBrakeLightData(brakeLight: Boolean) { + send(CanStatus(true)) + } + + override fun onAutopilotSteeringData(steering: Float) { + send(CanStatus(true)) + } + + override fun onAutopilotGearData(gear: GearPosition) { + send(CanStatus(true)) + } + + override fun onAutopilotNotData(timestamp: Long) { + send(CanStatus(false)) + } + + override fun onDestroy() { + super.onDestroy() + Log.d(TAG, "-- onDestroy --") + CallerAutoPilotStatusListenerManager.removeListener(TAG) + CallerAutoPilotStatusListenerManager.removeListener(TAG) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/gps/GpsImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/gps/GpsImpl.kt new file mode 100644 index 0000000000..4230819edf --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/gps/GpsImpl.kt @@ -0,0 +1,85 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.gps + +import android.* +import android.content.* +import android.location.* +import android.util.* +import androidx.core.location.* +import com.mogo.eagle.core.utilcode.util.* +import com.mogo.eagle.core.utilcode.util.PermissionUtils.SimpleCallback +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import com.zhjt.mogo_core_function_devatools.status.entity.GpsStatus +import java.util.concurrent.atomic.* + +internal class GpsImpl(ctx: Context): IFlow(ctx) { + + companion object { + const val TAG = "RTKImpl" + } + + private val registered = AtomicBoolean(false) + + private var receiver: CheckLocationReceiver? = null + + inner class CheckLocationReceiver(private val onClose: ()->Unit, private val onOpen:()-> Unit) : BroadcastReceiver() { + + override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action == LocationManager.MODE_CHANGED_ACTION) { + if (isLocationEnabled()) { + onOpen.invoke() + } else { + onClose.invoke() + } + } + } + } + + private val onClose = { + send(false, PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)) + } + + private val onOpen = { + send(true, PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)) + } + + override fun onCreate() { + val isGranted = PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION) + send(isLocationEnabled(), isGranted) + if (!isGranted) { + PermissionUtils.requestAccessFineLocation(object : SimpleCallback { + override fun onGranted() { + Log.d(TAG,"权限: ${Manifest.permission.ACCESS_FINE_LOCATION} 被授予了....") + send(enabled = isLocationEnabled(), isGranted = false) + } + + override fun onDenied() { + ToastUtils.showShort("定位权限被拒绝, 可能导致RTK定位不准确,请开启~") + send(enabled = isLocationEnabled(), isGranted = false) + } + }) + } + + if (registered.compareAndSet(false, true)) { + ctx.registerReceiver(CheckLocationReceiver(onClose, onOpen).also { receiver = it }, IntentFilter().also { it.addAction(LocationManager.MODE_CHANGED_ACTION) }) + } + } + + private fun isLocationEnabled() = + LocationManagerCompat.isLocationEnabled(ctx.getSystemService(Context.LOCATION_SERVICE) as LocationManager) + + private fun send(enabled: Boolean, isGranted: Boolean) { + send(GpsStatus(enabled, isGranted)) + } + + override fun onDestroy() { + super.onDestroy() + try { + if (registered.compareAndSet(true, false) && receiver != null) { + ctx.unregisterReceiver(receiver) + } + } catch (t: Throwable) { + t.printStackTrace() + } + + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/ipc/IpcImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/ipc/IpcImpl.kt new file mode 100644 index 0000000000..f6611d3262 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/ipc/IpcImpl.kt @@ -0,0 +1,45 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.ipc + +import android.content.* +import android.util.* +import com.mogo.eagle.core.data.autopilot.* +import com.mogo.eagle.core.function.api.autopilot.* +import com.mogo.eagle.core.function.call.autopilot.* +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import com.zhjt.mogo_core_function_devatools.status.entity.IpcStatus + +internal class IpcImpl(ctx: Context): IFlow(ctx), IMoGoAutopilotStatusListener { + + companion object { + const val TAG = "IpcImpl" + } + + private var state: Int = -1 + + override fun onCreate() { + Log.d(TAG, "-- onCreate --") + checkAndSend() + CallerAutoPilotStatusListenerManager.addListener(TAG, this) + } + + + override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { + super.onAutopilotStatusResponse(autoPilotStatusInfo) + Log.d(TAG, "-- onAutopilotStatusResponse -- state: ${autoPilotStatusInfo.state}") + if (state != autoPilotStatusInfo.state) { + checkAndSend() + state = autoPilotStatusInfo.state + } + } + + private fun checkAndSend() { + Log.d(TAG, "-- checkAndSend --") + send(IpcStatus(CallerAutoPilotManager.isConnected())) + } + + override fun onDestroy() { + super.onDestroy() + Log.d(TAG, "-- onDestroy --") + CallerAutoPilotStatusListenerManager.removeListener(TAG) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/nets/NetsImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/nets/NetsImpl.kt new file mode 100644 index 0000000000..8c96e77dab --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/nets/NetsImpl.kt @@ -0,0 +1,132 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.nets + +import android.content.* +import android.net.* +import android.net.wifi.* +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES +import android.util.* +import com.mogo.eagle.core.utilcode.kotlin.* +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import com.zhjt.mogo_core_function_devatools.status.entity.NetStatus +import com.zhjt.mogo_core_function_devatools.status.entity.NetStatus.Speed +import kotlinx.coroutines.* +import java.util.concurrent.atomic.* + +internal class NetsImpl(ctx: Context): IFlow(ctx) { + + companion object { + const val TAG = "NetsImpl" + } + + private val registered = AtomicBoolean(false) + + private val connectMgr by lazy { + ctx.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + + private val wifiMgr by lazy { + ctx.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + } + + private val cb = object : ConnectivityManager.NetworkCallback() { + + override fun onAvailable(network: Network) { + super.onAvailable(network) + Log.d(TAG, "-- onAvailable --:: $network") + checkAndSend() + } + + override fun onLosing(network: Network, maxMsToLive: Int) { + super.onLosing(network, maxMsToLive) + Log.d(TAG, "-- onLosing --:: $network::$maxMsToLive") + } + + override fun onLost(network: Network) { + super.onLost(network) + Log.d(TAG, "-- onLost --:: $network") + checkAndSend() + } + + override fun onUnavailable() { + super.onUnavailable() + Log.d(TAG, "-- onUnavailable --") + checkAndSend() + } + + override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { + super.onCapabilitiesChanged(network, networkCapabilities) + Log.d(TAG, "-- onCapabilitiesChanged --:$network::$networkCapabilities") + checkAndSend() + } + + override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { + super.onLinkPropertiesChanged(network, linkProperties) + Log.d(TAG, "-- onLinkPropertiesChanged --:$network::$linkProperties") + } + + override fun onBlockedStatusChanged(network: Network, blocked: Boolean) { + super.onBlockedStatusChanged(network, blocked) + Log.d(TAG, "-- onBlockedStatusChanged --:$network::$blocked") + } + } + + + override fun onCreate() { + Log.d(TAG, "-- onCreate --") + checkAndSend() + val builder = NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + if (VERSION.SDK_INT >= VERSION_CODES.O) { + builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) + } + if (registered.compareAndSet(false, true)) { + connectMgr.registerNetworkCallback(builder.build(), cb) + } + } + + private var loopCheckAndSendJob: Job? = null + + private fun checkAndSend() { + val connectionInfo = wifiMgr.connectionInfo + val enabled = isNetConnected() + val name = connectionInfo.ssid?.replace(Regex("[\\W]"), "") + loopCheckAndSendJob?.safeCancel() + launch(Dispatchers.Default) { delay(1000); checkAndSend() }.also { loopCheckAndSendJob = it } + var tr = 0 + if (VERSION.SDK_INT >= VERSION_CODES.Q) { + tr = connectionInfo.txLinkSpeedMbps + } + var sr = 0 + if (VERSION.SDK_INT >= VERSION_CODES.Q) { + sr = connectionInfo.rxLinkSpeedMbps + } + val speed = Speed(tr, sr) + Log.d(TAG, "checkAndSend----:enable: $enabled :: name: $name") + send(enabled, name, speed) + } + + + private fun isNetConnected(): Boolean = + if (VERSION.SDK_INT >= VERSION_CODES.M) { + val networkCapabilities = connectMgr.getNetworkCapabilities(connectMgr.activeNetwork) + networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false + } else { + val activeNetworkInfo = connectMgr.activeNetworkInfo + activeNetworkInfo != null && activeNetworkInfo.isConnected + } + + private fun send(enabled: Boolean, name: String?, speed: Speed? = null) { + send(NetStatus(enabled, name, speed)) + } + + override fun onDestroy() { + super.onDestroy() + Log.d(TAG, "-- onDestroy --") + if (registered.compareAndSet(true, false)) { + connectMgr.unregisterNetworkCallback(cb) + } + loopCheckAndSendJob?.safeCancel() + + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/rtk/RTKImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/rtk/RTKImpl.kt new file mode 100644 index 0000000000..babb29092b --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/rtk/RTKImpl.kt @@ -0,0 +1,35 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.rtk + +import android.content.* +import android.util.* +import com.mogo.eagle.core.function.api.autopilot.* +import com.mogo.eagle.core.function.call.autopilot.* +import com.zhjt.mogo_core_function_devatools.status.entity.RTKStatus +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import mogo.telematics.pad.MessagePad.GnssInfo + +internal class RTKImpl(ctx: Context): IFlow(ctx), IMoGoAutopilotCarStateListener { + companion object { + const val TAG = "RTKImpl" + } + + override fun onCreate() { + send(RTKStatus(isRTKEnabled())) + Log.d(TAG, "-- onCreate --") + CallerAutopilotCarStatusListenerManager.addListener(TAG, this) + + } + + private fun isRTKEnabled() = + CallerAutoPilotManager.isConnected() && CallerAutoPilotStatusListenerManager.getAutoPilotReportMessageCode() != "EHW_RTK" && CallerAutopilotCarStatusListenerManager.getCurrentGnssInfo() != null + + override fun onAutopilotCarStateData(gnssInfo: GnssInfo?) { + send(RTKStatus(isRTKEnabled())) + } + + override fun onDestroy() { + super.onDestroy() + Log.d(TAG, "-- onDestroy --") + CallerAutopilotCarStatusListenerManager.removeListener(TAG) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/trace/TracingImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/trace/TracingImpl.kt new file mode 100644 index 0000000000..ddaf051dcd --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/trace/TracingImpl.kt @@ -0,0 +1,44 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.trace + +import android.content.* +import android.util.* +import com.mogo.eagle.core.function.api.autopilot.* +import com.mogo.eagle.core.function.call.autopilot.* +import com.zhjt.mogo_core_function_devatools.status.entity.* +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import mogo_msg.MogoReportMsg.MogoReportMessage + +internal class TracingImpl(ctx: Context): IFlow(ctx), IMoGoAutopilotStatusListener { + + companion object { + const val TAG = "TracingImpl" + } + + private var old: String = "" + + override fun onCreate() { + Log.d(TAG, "-- onCreate --") + val autoPilotReportMessageCode = CallerAutoPilotStatusListenerManager.getAutoPilotReportMessageCode() + old = autoPilotReportMessageCode + send(TracingStatus(autoPilotReportMessageCode.toState())) + CallerAutoPilotStatusListenerManager.addListener(TAG, this) + } + + + override fun onAutopilotGuardian(guardianInfo: MogoReportMessage?) { + super.onAutopilotGuardian(guardianInfo) + val current = guardianInfo?.code + if (current != null && current != old) { + Log.d(TAG, "-- onAutopilotGuardian --") + send(TracingStatus(current.toState())) + old = current + } + } + + override fun onDestroy() { + super.onDestroy() + Log.d(TAG, "-- onDestroy --") + CallerAutoPilotStatusListenerManager.removeListener(TAG) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/model/StatusModel.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/model/StatusModel.kt new file mode 100644 index 0000000000..67e36a34b4 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/model/StatusModel.kt @@ -0,0 +1,113 @@ +package com.zhjt.mogo_core_function_devatools.status.model + +import androidx.lifecycle.* +import com.mogo.eagle.core.function.call.autopilot.* +import com.zhjt.mogo_core_function_devatools.status.entity.CanStatus +import com.zhjt.mogo_core_function_devatools.status.entity.GpsStatus +import com.zhjt.mogo_core_function_devatools.status.entity.IpcStatus +import com.zhjt.mogo_core_function_devatools.status.entity.NetStatus +import com.zhjt.mogo_core_function_devatools.status.entity.RTKStatus +import com.zhjt.mogo_core_function_devatools.status.entity.Status +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.UNKNOWN +import java.util.concurrent.atomic.* +import kotlin.Pair + +internal class StatusModel : ViewModel() { + + companion object { + + const val TAG = "StatusModel" + val DEFAULTS = Pair(null, ArrayList().also { + it += IpcStatus(CallerAutoPilotManager.isConnected()) + it += NetStatus(false) + it += CanStatus(false) + it += TracingStatus(UNKNOWN) + it += RTKStatus(false) + it += GpsStatus(enabled = false, isGranted = false) + }) + } + + val status: MutableLiveData>> = MutableLiveData() + + private val preValue by lazy { AtomicReference>>() } + + + init { + status.value = DEFAULTS + } + + fun update(s: Status) { + synchronized(preValue) { + val v = preValue.get()?.second ?: status.value?.second ?: throw IllegalStateException("live data can't be null.") + val nv = ArrayList(v).also { it.updateOrInsert(s) } + val data = Pair(getExceptionStatus(nv), nv) + preValue.set(data) + status.postValue(data) + } + } + + private fun getExceptionStatus(l: ArrayList): Status? { + var ret: Status? = null + for (s in l) { + ret = when(s) { + is IpcStatus -> { + if (!s.enabled) { + s + } else { + null + } + } + is CanStatus -> { + if (CallerAutoPilotManager.isConnected() && !s.enabled) { + s + } else { + null + } + } + is NetStatus -> { + if (!s.enabled) { + s + } else { + null + } + } + is GpsStatus -> { + if (!s.enabled) { + s + } else { + null + } + } + is TracingStatus -> { + if (CallerAutoPilotManager.isConnected() && s.state.isException()) { + s + } else { + null + } + } + is RTKStatus -> { + if (!s.enabled) { + s + } else { + null + } + } + } + + if (ret != null) { + break + } + } + return ret + } + + private fun ArrayList.updateOrInsert(s: Status) { + val index = indexOfFirst { it.javaClass == s.javaClass } + if (index < 0) { + add(s) + } else { + set(index, s) + } + } +} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/StatusView.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/StatusView.kt new file mode 100644 index 0000000000..e8dcf1b2a7 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/StatusView.kt @@ -0,0 +1,106 @@ +package com.zhjt.mogo_core_function_devatools.status.ui + +import android.annotation.* +import android.content.* +import android.graphics.* +import android.graphics.drawable.* +import android.transition.* +import android.util.* +import android.view.* +import androidx.appcompat.widget.* +import androidx.constraintlayout.widget.* +import androidx.core.content.* +import androidx.lifecycle.* +import androidx.recyclerview.widget.* +import com.mogo.eagle.core.utilcode.kotlin.* +import com.mogo.eagle.core.utilcode.rv.divider.* +import com.zhjt.mogo_core_function_devatools.R +import com.zhjt.mogo_core_function_devatools.status.entity.* +import com.zhjt.mogo_core_function_devatools.status.entity.Status +import com.zhjt.mogo_core_function_devatools.status.model.StatusModel +import com.zhjt.mogo_core_function_devatools.status.ui.adapter.StatusAdapter +import com.zhjt.mogo_core_function_devatools.status.ui.diff.StatusDiffCallback +import java.util.ArrayList +import kotlin.Pair + +@SuppressLint("ViewConstructor") +internal class StatusView(private val model: StatusModel, ctx: Context): ConstraintLayout(ctx) { + + companion object { + const val TAG = "StatusView" + } + + private val iv: AppCompatImageView + private val rv: RecyclerView + private val dot: View + + private var observer: Observer>>? = null + init { + LayoutInflater.from(context).inflate(R.layout.layout_status_bar, this, true) + iv = findViewById(R.id.iv) + rv = findViewById(R.id.rv) + dot = findViewById(R.id.dot) + init() + } + + private fun init() { + isClickable = true + dot.background = shape(solid = Color.RED, shape = GradientDrawable.OVAL, width = 30.PX, height = 30.PX) + iv.also { + it.background = ContextCompat.getDrawable(context, R.drawable.icon_dev_status_un_fold) + it.onClick { v -> + val expand = v.tag as? Boolean ?: false + animate(expand) + v.tag = !expand + } + } + rv.also { itx -> + itx.itemAnimator?.run { + changeDuration = 0 + addDuration = 0 + moveDuration = 0 + removeDuration = 0 + } + itx.layoutManager = GridLayoutManager(context, 3, GridLayoutManager.VERTICAL, false) + itx.background = shape(solid = Color.parseColor("#80000000"), radius = 40.PX) + itx.addItemDecoration( + CommonDividerItemDecoration.Builder() + .horizontalExternalSpace(66.PX) + .verticalExternalSpace(60.PX) + .spanCountTBCare(false) + .verticalInnerSpace(50.PX) + .horizontalInnerSpace(116.PX) + .build() + ) + val adapter = model.status.value?.let { data -> StatusAdapter(context, data.second) }?.also { adapter -> itx.adapter = adapter } + adapter?.let { _ -> + model.status.observeForever(Observer>> { data -> + Log.d("OOOO", "--- observeForever -----") + + if (data.first != null) { + dot.visibility = View.VISIBLE + } else { + dot.visibility = View.INVISIBLE + } + val old = adapter.data + Log.d(TAG, "receive update --new - data: ${data.second.joinToString(",")}") + Log.d(TAG, "receive update --old - data: ${old.joinToString(",")}") + val result = DiffUtil.calculateDiff(StatusDiffCallback(old, data.second)) + adapter.data = data.second + result.dispatchUpdatesTo(adapter) + }.also { observer = it }) + } + } + + onDetach { + observer?.also { model.status.removeObserver(it) } + } + } + + private fun animate(expand: Boolean) { + iv.animate().rotation(if (expand) 0f else -180f).setDuration(200).start() + TransitionManager.beginDelayedTransition(this, AutoTransition().setDuration(200)) + rv.visibility = if (expand) View.VISIBLE else View.INVISIBLE + } + +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/adapter/StatusAdapter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/adapter/StatusAdapter.kt new file mode 100644 index 0000000000..727fb1d199 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/adapter/StatusAdapter.kt @@ -0,0 +1,99 @@ +package com.zhjt.mogo_core_function_devatools.status.ui.adapter + +import android.content.* +import android.view.* +import android.widget.* +import androidx.core.content.* +import androidx.recyclerview.widget.* +import com.zhjt.mogo_core_function_devatools.* +import com.zhjt.mogo_core_function_devatools.R.drawable +import com.zhjt.mogo_core_function_devatools.status.entity.* +import com.zhjt.mogo_core_function_devatools.status.entity.IpcStatus +import com.zhjt.mogo_core_function_devatools.status.entity.Status +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.* +import com.zhjt.mogo_core_function_devatools.status.ui.adapter.StatusAdapter.StatusViewHolder + +internal class StatusAdapter(val ctx: Context, var data: ArrayList): RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatusViewHolder = + StatusViewHolder(LayoutInflater.from(ctx).inflate(R.layout.layout_status_bar_item, parent, false)) + + override fun onBindViewHolder(holder: StatusViewHolder, position: Int) { + holder.bind(data[position]) + } + + override fun getItemCount(): Int = data.size + + internal class StatusViewHolder(item: View) : RecyclerView.ViewHolder(item) { + + private val iv: ImageView by lazy { + itemView.findViewById(R.id.iv) + } + + private val tv: TextView by lazy { + itemView.findViewById(R.id.tv) + } + + fun bind(status: Status) { + when(status) { + is IpcStatus -> { + if (status.enabled) { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_ipc_enable) + } else { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_ipc_disable) + } + tv.text = "工控机" + } + is CanStatus -> { + if (status.enabled) { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_can_enable) + } else { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_can_disable) + } + tv.text = "Can" + } + is NetStatus -> { + if (status.enabled) { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_net_enable) + tv.text = status.name ?: "Wi-Fi" + } else { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_net_disable) + tv.text = "Wi-Fi" + } + } + is GpsStatus -> { + if (status.enabled && status.isGranted) { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_gps_enable) + } else { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_gps_disable) + } + tv.text = "Gps" + } + is TracingStatus -> { + when(status.state) { + ROUTE_FAILED, TRACK_LOAD_FAIL, TRACK_NOT_EXIST, TRACK_FINDED, UNKNOWN -> { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_trace_unkown) + tv.text = "未知" + } + TRACK_LOADED -> { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_track_enable) + tv.text = "T" + } + ROUTE_LOADED -> { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_route_enable) + tv.text = "V" + } + } + } + is RTKStatus -> { + if (status.enabled) { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_rtk_enable) + } else { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_rtk_disable) + } + tv.text = "RTK" + } + } + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/diff/StatusDiffCallback.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/diff/StatusDiffCallback.kt new file mode 100644 index 0000000000..71d80bfa97 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/ui/diff/StatusDiffCallback.kt @@ -0,0 +1,21 @@ +package com.zhjt.mogo_core_function_devatools.status.ui.diff + +import androidx.recyclerview.widget.* +import com.zhjt.mogo_core_function_devatools.status.entity.Status + +internal class StatusDiffCallback(private val old: ArrayList, private val update: ArrayList): DiffUtil.Callback() { + + override fun getOldListSize(): Int = old.size + + override fun getNewListSize(): Int = update.size + + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return true + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + val oldStatus = old[oldItemPosition] + val updateStatus = update[newItemPosition] + return oldStatus == updateStatus + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_can_disable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_can_disable.png new file mode 100644 index 0000000000..6b518b07f1 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_can_disable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_can_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_can_enable.png new file mode 100644 index 0000000000..302775b794 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_can_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_gps_disable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_gps_disable.png new file mode 100644 index 0000000000..3574b7d2d1 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_gps_disable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_gps_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_gps_enable.png new file mode 100644 index 0000000000..939a047a33 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_gps_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_ipc_disable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_ipc_disable.png new file mode 100644 index 0000000000..2df0b2fb4b Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_ipc_disable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_ipc_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_ipc_enable.png new file mode 100644 index 0000000000..553f1a6854 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_ipc_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_net_disable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_net_disable.png new file mode 100644 index 0000000000..885b4603f0 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_net_disable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_net_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_net_enable.png new file mode 100644 index 0000000000..ea9f95dfa3 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_net_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_route_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_route_enable.png new file mode 100644 index 0000000000..6891e2c698 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_route_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_rtk_disable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_rtk_disable.png new file mode 100644 index 0000000000..8c73649eda Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_rtk_disable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_rtk_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_rtk_enable.png new file mode 100644 index 0000000000..bfea1399fd Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_rtk_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_trace_unkown.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_trace_unkown.png new file mode 100644 index 0000000000..d76f3d74b7 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_trace_unkown.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_track_enable.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_track_enable.png new file mode 100644 index 0000000000..43e1cff91a Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_track_enable.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_un_fold.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_un_fold.png new file mode 100644 index 0000000000..5bd76829ae Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_dev_status_un_fold.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_status_bar.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_status_bar.xml new file mode 100644 index 0000000000..99d3f38d46 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_status_bar.xml @@ -0,0 +1,37 @@ + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_status_bar_item.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_status_bar_item.xml new file mode 100644 index 0000000000..b9e7610987 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_status_bar_item.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-dispatch/src/main/java/com/zhjt/dispatch/DispatchAutoPilotManager.java b/core/function-impl/mogo-core-function-dispatch/src/main/java/com/zhjt/dispatch/DispatchAutoPilotManager.java index f7d0ffb66d..1c15ecad1c 100644 --- a/core/function-impl/mogo-core-function-dispatch/src/main/java/com/zhjt/dispatch/DispatchAutoPilotManager.java +++ b/core/function-impl/mogo-core-function-dispatch/src/main/java/com/zhjt/dispatch/DispatchAutoPilotManager.java @@ -334,4 +334,7 @@ public class DispatchAutoPilotManager implements IMogoOnMessageListener(), setProxyTrafficLightView(viewTrafficLightVr) setProxyLimitingSpeedView(viewLimitingVelocity) setProxyNotificationView(V2XNotificationView(view.context)) + + context?.also { + CallerDevaToolsManager.showStatusBar(it) + } } @OptIn(ExperimentalCoroutinesApi::class) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt index a1b21d7fe7..debcd6df89 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt @@ -1779,6 +1779,10 @@ class DebugSettingView @JvmOverloads constructor( } } + override fun onAutopilotNotData(timestamp: Long) { + + } + /** * 吐司提示 */ diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/SteeringWheelView.java b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/SteeringWheelView.java index 548572101a..01925b91be 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/SteeringWheelView.java +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/SteeringWheelView.java @@ -101,6 +101,10 @@ public class SteeringWheelView extends ConstraintLayout { } private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener() { + @Override + public void onAutopilotNotData(long timestamp) { + } + @Override public void onAutopilotArriveAtStation(@org.jetbrains.annotations.Nullable MessagePad.ArrivalNotification arrivalNotification) { @@ -146,6 +150,11 @@ public class SteeringWheelView extends ConstraintLayout { }; private final IMoGoAutopilotVehicleStateListener mIMoGoAutopilotVehicleStateListener = new IMoGoAutopilotVehicleStateListener() { + @Override + public void onAutopilotNotData(long timestamp) { + + } + /** * 车辆转向灯 * @param lightSwitch diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainActivity.java b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainActivity.java index a148257f3d..83e663512d 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainActivity.java +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/main/MainActivity.java @@ -75,6 +75,10 @@ public class MainActivity extends MvpActivity implement FragmentStackTransactionListener, IMoGoAutopilotStatusListener { + @Override + public void onAutopilotNotData(long timestamp) { + } + protected static final String TAG = "MainActivity"; private static final int REQUEST_CODE_DIALOG = 100; @@ -473,4 +477,8 @@ public class MainActivity extends MvpActivity implement .commitAllowingStateLoss(); } + @Override + public void onPointerCaptureChanged(boolean hasCapture) { + super.onPointerCaptureChanged(hasCapture); + } } diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/SmallMapFragment.java b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/SmallMapFragment.java index a673435510..70dc9085bf 100644 --- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/SmallMapFragment.java +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/SmallMapFragment.java @@ -55,6 +55,10 @@ public class SmallMapFragment extends BaseFragment SmpServiceManager.init(getContext()); } + @Override + public void onAutopilotNotData(long timestamp) { + } + @Override protected void initViews(Bundle savedInstanceState) { super.initViews(savedInstanceState); diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotStatusListener.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotStatusListener.kt index 4243a28958..9d3ef5986a 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotStatusListener.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotStatusListener.kt @@ -35,6 +35,11 @@ interface IMoGoAutopilotStatusListener { */ fun onAutopilotGuardian(guardianInfo: MogoReportMsg.MogoReportMessage?) {} + /** + * 工控机底盘没有返回数据 + */ + fun onAutopilotNotData(timestamp: Long) {} + companion object { /** diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotVehicleStateListener.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotVehicleStateListener.kt index a980b68591..97f8784495 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotVehicleStateListener.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotVehicleStateListener.kt @@ -30,4 +30,9 @@ interface IMoGoAutopilotVehicleStateListener { * @param gear 档位 */ fun onAutopilotGearData(gear: Chassis.GearPosition) + + /** + * 底盘没有返回数据 + */ + fun onAutopilotNotData(timestamp: Long) } \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt index ab690871e0..983ffb7f21 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt @@ -99,4 +99,9 @@ interface IDevaToolsProvider : IProvider { * 下载指定包 */ fun downLoadPackage(downloadKey: String, downloadUrl: String) + + /** + * 展示状态栏 + */ + fun showStatusBar(ctx: Context) } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotStatusListenerManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotStatusListenerManager.kt index 9c27fd9453..f76f04e807 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotStatusListenerManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotStatusListenerManager.kt @@ -4,6 +4,7 @@ import androidx.annotation.Nullable import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener import com.mogo.eagle.core.function.call.base.CallerBase +import com.mogo.eagle.core.utilcode.kotlin.* import com.mogo.eagle.core.utilcode.util.GsonUtils import mogo.telematics.pad.MessagePad import mogo_msg.MogoReportMsg @@ -23,6 +24,9 @@ object CallerAutoPilotStatusListenerManager : CallerBase() { private val M_AUTOPILOT_STATUS_LISTENERS: ConcurrentHashMap = ConcurrentHashMap() + @Volatile + private var autoPilotMessageCode: String = "" + /** * 查询AutoPilot状态 */ @@ -37,6 +41,8 @@ object CallerAutoPilotStatusListenerManager : CallerBase() { return GsonUtils.toJson(mAutopilotStatusInfo) } + fun getAutoPilotReportMessageCode(): String = autoPilotMessageCode + /** * 通过Gnss定位更新来同步更新自动驾驶状态 */ @@ -163,6 +169,7 @@ object CallerAutoPilotStatusListenerManager : CallerBase() { M_AUTOPILOT_STATUS_LISTENERS.forEach { val tag = it.key val listener = it.value + autoPilotMessageCode = guardianInfo?.code ?: "" listener.onAutopilotGuardian(guardianInfo) } } diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotCarStatusListenerManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotCarStatusListenerManager.kt index cceb3e912d..6429455cbd 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotCarStatusListenerManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotCarStatusListenerManager.kt @@ -17,6 +17,8 @@ object CallerAutopilotCarStatusListenerManager : CallerBase() { private val M_AUTOPILOT_STATUS_LISTENERS: ConcurrentHashMap = ConcurrentHashMap() + @Volatile + private var gnssInfo: MessagePad.GnssInfo? = null /** * 添加 ADAS车辆状态&定位 监听 @@ -56,12 +58,18 @@ object CallerAutopilotCarStatusListenerManager : CallerBase() { } } + + fun getCurrentGnssInfo():MessagePad.GnssInfo? { + return gnssInfo + } + /** * 车辆状态数据 回调 * @param gnssInfo */ @Synchronized fun invokeAutopilotCarStateData(gnssInfo: MessagePad.GnssInfo?) { + this.gnssInfo = gnssInfo M_AUTOPILOT_STATUS_LISTENERS.forEach { val tag = it.key val listener = it.value diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotVehicleStateListenerManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotVehicleStateListenerManager.kt index f08725d29c..2191ea3db8 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotVehicleStateListenerManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotVehicleStateListenerManager.kt @@ -113,4 +113,14 @@ object CallerAutopilotVehicleStateListenerManager : CallerBase() { fun getAutopilotTimeStamp(): Long { return this.timeStamp } + + /** + * 底盘没有返回数据 + */ + fun invokeAutopilotNotData(timestamp: Long) { + M_AUTOPILOT_VEHICLE_LISTENERS.forEach{ + val listener = it.value + listener.onAutopilotNotData(timestamp) + } + } } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt index 527c0ec6d2..ebe2f519d0 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt @@ -136,4 +136,11 @@ object CallerDevaToolsManager { fun downLoadPackage(downloadKey: String, downloadUrl: String) { devaToolsProviderApi?.downLoadPackage(downloadKey, downloadUrl) } + + /** + * 展示状态栏 + */ + fun showStatusBar(ctx: Context) { + devaToolsProviderApi?.showStatusBar(ctx) + } } \ No newline at end of file diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt index e88d988279..d1d75f6b85 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt @@ -8,8 +8,7 @@ import android.graphics.drawable.GradientDrawable import android.text.* import android.text.style.ForegroundColorSpan import android.util.TypedValue -import android.view.MotionEvent -import android.view.View +import android.view.* import android.widget.EditText import android.widget.TextView import androidx.annotation.ColorInt @@ -40,20 +39,38 @@ val T.lifecycleOwner: LifecycleOwner if (it.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) { it.currentState = Lifecycle.State.CREATED } + + if (it.currentState.isAtLeast(Lifecycle.State.CREATED)) { + it.currentState = Lifecycle.State.STARTED + } + + if (it.currentState.isAtLeast(Lifecycle.State.STARTED)) { + it.currentState = Lifecycle.State.RESUMED + } } } + + addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View?) { lifecycle.let { if (it.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) { it.currentState = Lifecycle.State.CREATED } + + if (it.currentState.isAtLeast(Lifecycle.State.CREATED)) { + it.currentState = Lifecycle.State.STARTED + } + + if (it.currentState.isAtLeast(Lifecycle.State.STARTED)) { + it.currentState = Lifecycle.State.RESUMED + } } } override fun onViewDetachedFromWindow(v: View?) { lifecycle.let { - if (it.currentState.isAtLeast(Lifecycle.State.CREATED)) { + if (it.currentState.isAtLeast(Lifecycle.State.RESUMED)) { this@lifecycleOwner.removeOnAttachStateChangeListener(this) it.currentState = Lifecycle.State.DESTROYED } @@ -159,7 +176,6 @@ val Int.PX: Int val Int.SP: Int get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), Utils.getApp().resources.displayMetrics).toInt() - fun T.watch(@IntRange(from = 1) maxCharCount: Int, onCountChanged:((count: Int) -> Unit)? = null, onTextChanged:((editable: Editable?) -> Unit)? = null, onReachMaxCountAction:((text: T) -> Unit)? = null, onGetFocus:((text: T) -> Unit)? = null) { doAfterTextChanged { itx -> onTextChanged?.invoke(itx) diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/rv/divider/CommonDividerItemDecoration.kt b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/rv/divider/CommonDividerItemDecoration.kt index 4b30d692f9..62a5dfd1d2 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/rv/divider/CommonDividerItemDecoration.kt +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/rv/divider/CommonDividerItemDecoration.kt @@ -2,7 +2,7 @@ package com.mogo.eagle.core.utilcode.rv.divider import android.graphics.Canvas import android.graphics.Rect -import android.util.Pair +import android.util.* import android.view.View import androidx.annotation.IntRange import androidx.recyclerview.widget.GridLayoutManager @@ -84,17 +84,23 @@ class CommonDividerItemDecoration internal constructor(builder: Builder) : ItemD } } else { val averageDistance = (((spanCount - 1) * mHorizontalInnerSpace + 2 * mHorizontalExternalSpace + deltaHL + deltaHR) * 1.0f / spanCount).toInt() + Log.d("UUUU", "step::0::$averageDistance: lastRight: $mLastRight : state: $state " ) if (spanIndex == 0) { outRect.left = mHorizontalExternalSpace + deltaHL outRect.right = averageDistance - outRect.left mLastRight = outRect.right + Log.d("UUUU", "step::1::$averageDistance: lastRight: $mLastRight" ) } else if (spanIndex == spanCount - 1) { outRect.right = mHorizontalExternalSpace + deltaHR outRect.left = averageDistance - outRect.right + Log.d("UUUU", "step::2::$averageDistance: lastRight: $mLastRight ::outRect.left: ${outRect.left}" ) } else { outRect.left = mHorizontalInnerSpace - mLastRight outRect.right = averageDistance - outRect.left - mLastRight = outRect.right + if (state.didStructureChange()) { + mLastRight = outRect.right + } + Log.d("UUUU", "step::2::$averageDistance: lastRight: $mLastRight ::outRect.left: ${outRect.left}" ) } } //所在的行数 if (lookUp.getSpanGroupIndex(childPosition, spanCount) == lookUp.getSpanGroupIndex(mFromPosition, spanCount)) { @@ -131,7 +137,9 @@ class CommonDividerItemDecoration internal constructor(builder: Builder) : ItemD } else { outRect.top = mVerticalInnerSpace - mLastBottom outRect.bottom = averageDistance - outRect.top - mLastBottom = outRect.bottom + if (state.didStructureChange()) { + mLastBottom = outRect.bottom + } } } if (lookUp.getSpanGroupIndex(childPosition, spanCount) == lookUp.getSpanGroupIndex(mFromPosition, spanCount)) { //第一列 @@ -222,7 +230,9 @@ class CommonDividerItemDecoration internal constructor(builder: Builder) : ItemD } else { outRect.left = mHorizontalInnerSpace - mLastRight outRect.right = averageDistance - outRect.left - mLastRight = outRect.right + if (state.didStructureChange()) { + mLastRight = outRect.right + } } } if (childPosition == mFromPosition) { @@ -279,7 +289,9 @@ class CommonDividerItemDecoration internal constructor(builder: Builder) : ItemD } else { outRect.top = mVerticalInnerSpace - mLastBottom outRect.bottom = averageDistance - outRect.top - mLastBottom = outRect.bottom + if (state.didStructureChange()) { + mLastBottom = outRect.bottom + } } } if (childPosition == mFromPosition) { diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/PermissionUtils.java b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/PermissionUtils.java index bacf93d9c3..229b6dd5f8 100755 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/PermissionUtils.java +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/PermissionUtils.java @@ -1,5 +1,6 @@ package com.mogo.eagle.core.utilcode.util; +import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.content.Intent; @@ -56,6 +57,7 @@ public final class PermissionUtils { private static SimpleCallback sSimpleCallback4WriteSettings; private static SimpleCallback sSimpleCallback4DrawOverlays; + private static SimpleCallback sSimpleCallback4AccessFineLocation; /** * Return the permissions used in application. @@ -152,6 +154,19 @@ public final class PermissionUtils { PermissionActivityImpl.start(PermissionActivityImpl.TYPE_WRITE_SETTINGS); } + public static void requestAccessFineLocation(final SimpleCallback callback) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (isGranted(Manifest.permission.ACCESS_FINE_LOCATION)) { + if (callback != null) { + callback.onGranted(); + } + return; + } + sSimpleCallback4AccessFineLocation = callback; + PermissionActivityImpl.start(PermissionActivityImpl.TYPE_ACCESS_FINE_LOCATION); + } + } + @TargetApi(Build.VERSION_CODES.M) private static void startWriteSettingsActivity(final Activity activity, final int requestCode) { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); @@ -424,6 +439,7 @@ public final class PermissionUtils { private static final int TYPE_RUNTIME = 0x01; private static final int TYPE_WRITE_SETTINGS = 0x02; private static final int TYPE_DRAW_OVERLAYS = 0x03; + private static final int TYPE_ACCESS_FINE_LOCATION = 0x04; private static int currentRequestCode = -1; @@ -483,6 +499,9 @@ public final class PermissionUtils { } else if (type == TYPE_DRAW_OVERLAYS) { currentRequestCode = TYPE_DRAW_OVERLAYS; startOverlayPermissionActivity(activity, TYPE_DRAW_OVERLAYS); + } else if (type == TYPE_ACCESS_FINE_LOCATION) { + currentRequestCode = TYPE_ACCESS_FINE_LOCATION; + startOverlayPermissionActivity(activity, TYPE_ACCESS_FINE_LOCATION); } else { activity.finish(); Log.e("PermissionUtils", "type is wrong."); @@ -550,6 +569,15 @@ public final class PermissionUtils { sSimpleCallback4DrawOverlays.onDenied(); } sSimpleCallback4DrawOverlays = null; + } else if (requestCode == TYPE_ACCESS_FINE_LOCATION) { + if (sSimpleCallback4AccessFineLocation == null) { + return; + } + if (isGranted(Manifest.permission.ACCESS_FINE_LOCATION)) { + sSimpleCallback4AccessFineLocation.onGranted(); + } else { + sSimpleCallback4AccessFineLocation.onDenied(); + } } } } diff --git a/modules/mogo-module-service/src/main/java/com/mogo/module/service/routeoverlay/MogoRouteOverlayManager.java b/modules/mogo-module-service/src/main/java/com/mogo/module/service/routeoverlay/MogoRouteOverlayManager.java index 2a9f94dcec..a59d3c5de3 100644 --- a/modules/mogo-module-service/src/main/java/com/mogo/module/service/routeoverlay/MogoRouteOverlayManager.java +++ b/modules/mogo-module-service/src/main/java/com/mogo/module/service/routeoverlay/MogoRouteOverlayManager.java @@ -210,4 +210,7 @@ public class MogoRouteOverlayManager implements } + @Override + public void onAutopilotNotData(long timestamp) { + } }