From a419361def2febb24554f1c8ea602c00aa8ff4fe Mon Sep 17 00:00:00 2001 From: aibingbing Date: Tue, 13 Aug 2024 18:48:17 +0800 Subject: [PATCH] =?UTF-8?q?[6.6.0][FSM]=20feat:=20=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A0=8F=E5=A2=9E=E5=8A=A0=20FSM=20=E7=8A=B6=E6=80=81=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../status/StatusManager.kt | 2 + .../status/entity/Status.kt | 51 +++++++- .../status/flow/fsm/FSMImpl.kt | 91 +++++++++++++++ .../status/model/StatusModel.kt | 1 + .../status/ui/adapter/StatusAdapter.kt | 110 +++++++++++++----- .../icon_dev_status_fsm_error.png | Bin 0 -> 7129 bytes .../icon_dev_status_fsm_normal.png | Bin 0 -> 6365 bytes .../icon_dev_status_fsm_not_exist.png | Bin 0 -> 5977 bytes 8 files changed, 228 insertions(+), 27 deletions(-) create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/fsm/FSMImpl.kt create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_error.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_normal.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_not_exist.png 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 index 76baf933df..85480dad7a 100644 --- 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 @@ -32,6 +32,7 @@ import com.zhjt.mogo_core_function_devatools.status.flow.autopilot.RouteDownload import com.zhjt.mogo_core_function_devatools.status.flow.autopilot.SpeedImpl import com.zhjt.mogo_core_function_devatools.status.flow.autopilot.SteerImpl import com.zhjt.mogo_core_function_devatools.status.flow.can.CanImpl +import com.zhjt.mogo_core_function_devatools.status.flow.fsm.FSMImpl 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.rtk.RTKImpl @@ -91,6 +92,7 @@ object StatusManager { is GpsStatus -> GpsImpl(ctx) is TracingStatus -> TracingImpl(ctx) is RTKStatus -> RTKImpl(ctx) + is FSMStatus -> FSMImpl(ctx) is OverViewStatus -> OverViewImpl(ctx) is SteerStatus -> SteerImpl(ctx) is AcceleratorStatus -> AcceleratorImpl(ctx) 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 index 9a51c2a21c..221f0e1c0b 100644 --- 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 @@ -6,7 +6,16 @@ import com.zhjt.mogo_core_function_devatools.status.entity.RouteState.RouteFaile import com.zhjt.mogo_core_function_devatools.status.entity.RouteState.RouteNone import com.zhjt.mogo_core_function_devatools.status.entity.RouteState.RouteStart import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing -import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.* +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.MAP_DATA_EXIST +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.MAP_DATA_NOT_EXIST +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.MAP_TRA_TYPE +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.ROUTE_FAILED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.ROUTE_LOADED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_FINDED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_LOADED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_LOAD_FAIL +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_NOT_EXIST +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.UNKNOWN sealed class Status(var rawData: Any? = null) { @@ -119,6 +128,46 @@ class RTKStatus(var desc: String = "", var state: Int): Status() { override fun isException(): Boolean = desc.isEmpty() || (desc == "RTK") && state != 0 } +/** + * FSM模块状态码定义 + */ +enum class FSMStateCode { + IpcNotConnected, + NoneExist, + Normal, + Error +} + +/** + * FSM模块状态 + */ +class FSMStatus(var state: FSMStateCode, var desc: String = ""): Status() { + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + other as FSMStatus + if (desc != other.desc) { + return false + } + if (state != other.state) { + return false + } + return true + } + + override fun hashCode(): Int { + var result = desc.hashCode() + result = 31 * result + state.hashCode() + return result + } + + override fun toString(): String { + return "FSMStatus(state=$state, desc='$desc', raw_data=$rawData)" + } + + override fun isException(): Boolean = state == FSMStateCode.Error +} + /** * Can总线 */ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/fsm/FSMImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/fsm/FSMImpl.kt new file mode 100644 index 0000000000..13f33e6228 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/fsm/FSMImpl.kt @@ -0,0 +1,91 @@ +package com.zhjt.mogo_core_function_devatools.status.flow.fsm + +import android.content.Context +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener +import com.mogo.eagle.core.function.api.autopilot.IMoGoFsm2024Listener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerFsm2024ListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA +import com.zhjt.mogo.adas.data.AdasConstants +import com.zhjt.mogo_core_function_devatools.status.entity.FSMStateCode +import com.zhjt.mogo_core_function_devatools.status.entity.FSMStatus +import com.zhjt.mogo_core_function_devatools.status.flow.IFlow +import fsm.Fsm2024 +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.util.concurrent.atomic.AtomicReference + +internal class FSMImpl(ctx: Context) : IFlow(ctx), IMoGoAutopilotStatusListener, + IMoGoFsm2024Listener { + + companion object { + const val TAG = "FSMImpl" + } + + private val fsmStateMsg by lazy { + AtomicReference(null) + } + + private fun getDesc(): String { + return fsmStateMsg.get()?.pilotNotStandbyReason ?: "" + } + + private fun getStateCode(): FSMStateCode { + val isIpcConnected = CallerAutoPilotStatusListenerManager.isConnect() + if (!isIpcConnected) { + return FSMStateCode.IpcNotConnected + } else if (fsmStateMsg.get()?.pilotStandbyFlag == true) { + // TODO 判断是否有 FSM 模块 + return FSMStateCode.Normal + } else { + return FSMStateCode.Error + } + } + + override fun onCreate() { + send(FSMStatus(getStateCode(), getDesc())) + CallerLogger.d("$M_DEVA$TAG", "-- onCreate --") + CallerAutoPilotStatusListenerManager.addListener(TAG, this) + CallerFsm2024ListenerManager.addListener(TAG, this) + } + + override fun onAutopilotIpcConnectStatusChanged( + status: AdasConstants.IpcConnectionStatus, + reason: String? + ) { + super.onAutopilotIpcConnectStatusChanged(status, reason) + if (!CallerAutoPilotStatusListenerManager.isConnect()) { + CallerLogger.d("$M_DEVA$TAG", "工控机断开了....") + fsmStateMsg.set(null) + send(FSMStatus(FSMStateCode.IpcNotConnected, "工控机断开了")) + } else { + CallerLogger.d("$M_DEVA$TAG", "工控机已连接....") + launch(Dispatchers.Default) { + CallerAutoPilotControlManager.sendStatusQueryReq() + } + } + } + + override fun onFSM2024State(fsmState: Fsm2024.FSMStateMsg) { + CallerLogger.d( + "$M_DEVA$TAG", + "-- fsmState[pilotStandbyFlag=${fsmState.pilotStandbyFlag}, pilotNotStandbyReason=${fsmState.pilotNotStandbyReason}] --" + ) + fsmStateMsg.set(fsmState) + // TODO 判断是否有 FSM 模块 + if (fsmState.pilotStandbyFlag) { + send(FSMStatus(FSMStateCode.Normal, "")) + } else { + send(FSMStatus(FSMStateCode.Error, fsmState.pilotNotStandbyReason)) + } + } + + override fun onDestroy() { + super.onDestroy() + CallerLogger.d("$M_DEVA$TAG", "-- onDestroy --") + CallerAutoPilotStatusListenerManager.removeListener(TAG) + CallerFsm2024ListenerManager.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 index 15a5e480ca..1e254e84e9 100644 --- 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 @@ -14,6 +14,7 @@ internal class StatusModel : ViewModel() { const val TAG = "StatusModel" val DEFAULTS = Pair(null, ArrayList().also { it += OverViewStatus() + it += FSMStatus(FSMStateCode.IpcNotConnected, "") it += IpcStatus(CallerAutoPilotStatusListenerManager.isConnect()) it += CanStatus(false) // it += TracingStatus(UNKNOWN) 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 index a1c611de11..31703d7969 100644 --- 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 @@ -1,20 +1,37 @@ 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 android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView import com.mogo.eagle.core.function.call.hmi.CallerHmiManager -import com.mogo.eagle.core.utilcode.kotlin.* -import com.mogo.eagle.core.utilcode.mogo.logger.* +import com.mogo.eagle.core.utilcode.kotlin.onClick +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA import com.zhjt.mogo_core_function_devatools.R 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.CanStatus +import com.zhjt.mogo_core_function_devatools.status.entity.FSMStateCode +import com.zhjt.mogo_core_function_devatools.status.entity.FSMStatus +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.OverViewStatus +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.Tracing.* +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.MAP_DATA_EXIST +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.MAP_DATA_NOT_EXIST +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.MAP_TRA_TYPE +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.ROUTE_FAILED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.ROUTE_LOADED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_FINDED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_LOADED +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_LOAD_FAIL +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.TRACK_NOT_EXIST +import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.UNKNOWN import com.zhjt.mogo_core_function_devatools.status.ui.adapter.StatusAdapter.StatusViewHolder import me.jessyan.autosize.AutoSizeCompat @@ -116,6 +133,22 @@ internal class StatusAdapter(val ctx: Context, var data: List): Recycler iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_rtk_unknow) } } + is FSMStatus -> { + when (status.state) { + FSMStateCode.IpcNotConnected -> { + iv.setImageDrawable(null) + } + FSMStateCode.NoneExist -> { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_fsm_not_exist) + } + FSMStateCode.Normal -> { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_fsm_normal) + } + FSMStateCode.Error -> { + iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_fsm_error) + } + } + } is OverViewStatus -> { if (status.hasException) { iv.scaleType = ImageView.ScaleType.FIT_CENTER @@ -128,47 +161,72 @@ internal class StatusAdapter(val ctx: Context, var data: List): Recycler } } - private fun getText(status: Status): String = when(status) { - is CanStatus -> "CAN:${ if (status.enabled) "状态正常" else "非正常连接" }" - is GpsStatus -> "GPS:${ if (status.enabled) "状态正常" else "非正常连接" }" - is IpcStatus -> "工控机:${ if (status.enabled) "状态正常" else "非正常连接" }" + private fun getText(status: Status): String = when (status) { + is CanStatus -> "CAN:${if (status.enabled) "状态正常" else "非正常连接"}" + is GpsStatus -> "GPS:${if (status.enabled) "状态正常" else "非正常连接"}" + is IpcStatus -> "工控机:${if (status.enabled) "状态正常" else "非正常连接"}" // is NetStatus -> "WIFI:${ if (status.enabled) "${status.name}" else "非正常连接" }" - is RTKStatus -> when(status.desc) { + is RTKStatus -> when (status.desc) { "RTK" -> - when(status.state) { + when (status.state) { 0 -> "RTK定位,状态良好" 1 -> "RTK定位,定位不可信" 2 -> "RTK定位,误差增大到米级" else -> "RTK定位,状态异常" } + "SLAM" -> "SLAM定位,状态良好" + else -> "定位异常" } + + is FSMStatus -> when (status.state) { + FSMStateCode.IpcNotConnected -> { + "FSM:非正常连接" + } + FSMStateCode.NoneExist -> { + "FSM:无FSM模块" + } + FSMStateCode.Normal -> { + "FSM:状态正常" + } + FSMStateCode.Error -> { + "FSM:状态异常" + } + } + is TracingStatus -> { val extra = status.state.extra - val extraDesc = if (extra != null && extra.isNotEmpty()) extra.values.joinToString(",") else "" - CallerLogger.d("$M_DEVA$TAG", "traceing_state: $status -> extra: $extraDesc :: extra: $extra") - when(status.state) { + val extraDesc = + if (extra != null && extra.isNotEmpty()) extra.values.joinToString(",") else "" + CallerLogger.d( + "$M_DEVA$TAG", + "traceing_state: $status -> extra: $extraDesc :: extra: $extra" + ) + when (status.state) { //"轨迹类型:${ if (status.state == TRACK_LOADED) "循迹" else if (status.state == ROUTE_LOADED) "自主算路" else "暂无轨迹" }" MAP_TRA_TYPE -> { "暂无轨迹" } - MAP_DATA_EXIST -> "地图数据存在,正在加载${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - MAP_DATA_NOT_EXIST -> "地图数据不存在${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - TRACK_FINDED -> "轨迹类型:循迹(已找到轨迹)${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - TRACK_LOADED -> "轨迹类型:循迹(加载成功)${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - TRACK_NOT_EXIST -> "轨迹类型:循迹(未找到轨迹)${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - TRACK_LOAD_FAIL -> "轨迹类型:循迹(加载失败)${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - ROUTE_LOADED -> "轨迹类型:自主算路(加载成功)${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" - ROUTE_FAILED -> "轨迹类型:自主算路(加载失败)${ if(extraDesc.isNotEmpty()) "\n[$extraDesc]" else "" }" + + MAP_DATA_EXIST -> "地图数据存在,正在加载${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + MAP_DATA_NOT_EXIST -> "地图数据不存在${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + TRACK_FINDED -> "轨迹类型:循迹(已找到轨迹)${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + TRACK_LOADED -> "轨迹类型:循迹(加载成功)${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + TRACK_NOT_EXIST -> "轨迹类型:循迹(未找到轨迹)${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + TRACK_LOAD_FAIL -> "轨迹类型:循迹(加载失败)${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + ROUTE_LOADED -> "轨迹类型:自主算路(加载成功)${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" + ROUTE_FAILED -> "轨迹类型:自主算路(加载失败)${if (extraDesc.isNotEmpty()) "\n[$extraDesc]" else ""}" UNKNOWN -> "暂无轨迹" } } + is OverViewStatus -> { "" } + else -> { throw AssertionError() } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_error.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_error.png new file mode 100644 index 0000000000000000000000000000000000000000..cc007561ff6974b81034c4edd60b3b06c6d3635e GIT binary patch literal 7129 zcmV;~8z$t5P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91bD#qN1ONa40RR91E&u=k017*Mp8x$Uej`<&mE zQR~X|omXsalhGU7s9oIJ^qkg4TU3i zDt^m$ZTf`+_A;1^L#JNOakUGl_>GmAWmoZ(ZgegIq%zo~J~|2qofLSNHBfwoQGD*F z?9j%}!mD=2V?6qdb=bY_tMqyC?UW_g>AG4OnZqnfW=A;hzTzSo|6V2R41;$eui|b}Q_&YuakjWq##eMKPKGPV3 z4`CI?ji)~L0tz3OCtJ3QZ@o;}Z0t@JOzVaw9mWPe>7^gM*6!Bz7G>#rI%95`$ZOP$ zMAiyq@R8amfk%~FVKo^dELs`HS8UqF>(-Rdwmt$UXRqT;X!o3E?kEp zY$1^Ai%Emfs=Tq1UcMYAZvz6`xW%sy%~DtLYvO^x!^Dq#wRVkQE`oFHtu2zecI5=d&Y{#N$YqAb2}ND$U0aARP6yv zM7J~0Lqx%>;HCT;8OBwZMBtZr?~BJ%m-T11+(t;nlQ5bFDqC_mY)iSq?&V7~YOHv# zM7NIHte%mzBFhnyklaj}vFj!V_*STy^Nn+c+;Q*6DQ@e+or>_)cQ2{CZ3!AXGPAx;&mk}uo> z7_cF%H=vkYvqIlER&Xy_v%*MDIf3HpTVVney~fbv*~S2E)ijOc!E9%s20AsBCCR|+0%Z@$B+m799F-_Ww=&JVV6&U880!0z;<+x>xK+vz)GI- zXBa~OAe9ucJ*9K-H{%qJrp+lA(nq>qJeDClJkkSJyRT`lFDN&U20V-t7_2hXWteEa zJ&YGmMGetDAUzK4;&T(+)a5Z5&||L0F;9Q%^(TFeeA1kdG~D(Ouzg8Z&P<-jA6F0TtR|Kw{B{q&l0ceP{w& zPwxrFL*5`3T_fM~hQUX`TNOJ(YfJ1^PM{J~$wIMdC6fK37hetcHO5wOq4&=B4prMu z*uy|6`RJ{6o-wmBbJcLW7**GV|6n1^~r7FBi-&;=$qF5|$4PGBIHec86O@kB^_TnE59JTS~0 zqwu>-+sLx&7^djz+m`Bk&^#9F-yJ1Cg01YsNtRgIZHU6L^iRF5Cez+!(rDM}8xoqd z0V;VN;ei+im$O+9_8?M8au7(UM)}8Tf~Nj7$DA~TO<%XT%p=E#7k0IaMibBs=rm@5 z(r-l?BvOeREd-*J?xIuIm?yO+5`F1FUkq6xoTdf6;scFKJjB&DsaEksP|YwyE`>dG z)CeUp{xJ8MHA%yfN@9<&hAy;$r;t+{d=zS5QIV9XS60wH1kC{v|H`shG^Q^nMqt3F z&)^@?S91(cVT&*tB(4z$T(_QGaL9)-a#^8?> zhE69T)q4^Gj9t2gEo!=vbTAk;4h`8M|9}`_n+wKrW%p55t1Gh=c+JXIT<)H`L%C0-wbbiirqgIsVg%b%jNNY1QZT#djZJ&MEx35j_z1Oy& zr3%T!Hm`CK9S$JeP`!P7Ysa6cZu+zH4o^}$1E2DREVe{aLo_CdXq8W~+K$3?|KV>s z&4Oy!;9M^}jEN6p=ob%JF)@`eUWtV#`8;E{9^b~l`}Tom2_=m&J3^f>vBI*SI0ruT z4{iCTuZn{tMlhWG4IA3*#h10oFTc2rW|c&W#tRp$r8{@F#sB(DTl&fuLx*TQmST&K z$uU0d^fr0NyDg6V%ALE~p+EgY+lGs*Y9`Rc@L`*i>KLS$(8quBXZi$lrseSG(3{`X zra#zan}`iG>~|F2t5Uct>XVF_XZ>v3^t#_{qix4q|B%2Aw~fbba`riG z^4o80D=)pY&Hw%1w&|YTwwle2)yZTcaF|?PkIp)~jfB7Sjhj3{y{g4gJQMhB4--o^ zGKru4oHkM-DdjIZ{8$faOd`pm2i@h1v1(PK#09RQleC{+>7xPs5^%DT5qW5JF=n2m z!&a-(i?bAF4R2?JVQR%9tAg4AUkrBMjA|><{TRGF_m&iuWo^p@pq+bu+w@yk>Wkzy z^E#36%{|l>wY4sju*F4>Af$l>x<~KC=#IA)$(L;QG(C`Ro2YlB3@eeE=e)3X)6W)iyNJb1$Bs z3g*hVZT+?1P-?ZbsjUJ!eSfJ$72V8Ab5+F&W-1u*JhriU+aVq=D}NTZ2PYM zJDb6(;84YCX-f-j>E^Gsd5v#-(Z%iHm%h-NCIw0HK}NEEehG8LM8Z~V*JWE(Z+gWm z+x&OFC7P0;wZ*U#iSHt!hQ!QVrd64;B`*g5=DjE$%0$c)#3#*y zJplE>ed5-)?L?=gm!sW{<2&lX=BbLPVi)uu}l1v((8_Ho1XhTA7~bT zaHpSrtg0E9unKV!^u#B%@z4FdWtsF&Dl96C;$09A6OnCp2E{5&PDRHqSKH6-w8KnC zc>^a3fx*Z=d5oaEXlV$^urrKP!oFyOK_4FYOQvX|JINV*lI%oeUuho1EZSp>KzGD* zl0skC!tT4`S)>)oVWWSp@qE)i161>C=6uqxt`N8BalREmeO7QM_Kc$iGyN~0R+g2 zwM(lo(E1{SLMH1n0J@8utEL)mro%=SKdTYveW;NfZQ|NP167)%Rv_-*XALA0+UTTH z6krlbpkgxE3~b^bbzjJx7}y>?VjhUN9$I*Tr-e=1E_!}zC!Z2Y5!RxNL?20AIq~>5 z^MV&zw(J4ZcFA9!mkZLuA&8YZT*BcjVN>uOOAt((4S19{eZ&+(pD5bUC{)!iB_7Ig z^AxXYV?nfus>4WD-juH>S&*0t7p|D08c)X}f)NbxQ190V@j5`r+;g{e5qJW4;%i>- zeTz0LGZM;H4lb-|TSN=(=2t`8UnJ2(jCe9k+uT=gaN9cd+vyWH*=7R0Dm7PGWwRGw z+D7`|U|XeU{)R6D>%wc9SFhBOR8KawZI?LI%v;4=6cj$j5-StoK55nNYuYa9JZ*x6 zcGuarg{(?9R2RSa6ev3lD+$&f1zVhUAwpN}LLxb+L=Ww8joQ+#@B0pgAT^IzCzx1Zu5k-&IfvjUMszG}6-GEH8+rOj|1)JKDdzRpJq?3=ceUh*sYx^%p^ z%Oy=iUR9R$rD@A0ms%gT9{Bo=?ciN^h8BEPiNrCAes+sj|26SBh8$&5E{YMah^O53b!`U@9X-+^y`v+euP2io+Wdxm87rgxs1 zA60X=f3H1w>n-hsXFu2Woc6Ly+un~~)0Q<^#(Ex}@QTX^-u>VDW_$3q+uC*|lM}nY zdi&d^a?@BF7e(f0nuAGf(1{->=xaKFUG4680$>;QhQs=Y}s^r!#Td)kJl zKT}ZJ-bG`Mu?=!T=;c9Ra_#=uM{FN9&1e;#e90w#_HF&ei`tA1MbNqKy;eyUAebc5 z`bDR37ng3)k6?NzXlCfgbL=RqSeXbp4!WU`b|tiGXHx@CR%)^37?FJ{+GX_m+C#B2 zm-gM)7Jt0gfv~vuoEY;8l`86`y+2yT13xDfFaD%tY4;D?PyX@!4&>zYGunnHpVekg zJ*{ofyWhq$&uSaB{enZlIjEd;<=fhi-m34kT3yhsi&|Lbu?{P-8*~5r?KbzFZ?~-% zT*yc}RbP|#eDag+)K|SGLpEv$@3_4^aLY}$A)bh49d1lM@OfsB^<|2_ea^cXgD}WE zmd2y}J+q*(A}yh=QnX66`~5hKA?uZ*@wu;kS+oAbdQamEkb;*JgAa5(TV$BOw9M$i zna=`ib5JzFSY2!@e3PiMeD_^#UI!3fb&My>4Lf$U)311I+j#nu%r@D&wH^0@7q|IO z|3@ZMWbuIo6jmEjv`WD4Yd+G>|MS0evNxV|Qak6(Z)=-{OY(`w9<54VJ&lc zL03FH9b)3Zpf>(i0q1cjYq!|~WHr`hgEg>5pE}idT^#_rHqCX0+DT*DZL>RgqER0v z!U@8xF%Azio8XLPVx;PKHDD_NC3|? zZ?*Lps0k@+2mx~U-*R)C`|fQ{2J$ECy|a?Fu=}32?}jgljSm9w%T9brT|+pe3%J9I z==NIt$68k3GqIct(Eb`Uh+ea)6c^vXqejuHt}$dqvqO#&yn6S9FY_9iq$Ao8g#;iM zBv$`o#VDET_!6F1w7@wv^0|#!S~GRwu3c^M-X9wg{WDKEIbPzGD1Via3|qFUIJ{UT z2}vB`@4n`vgFM6FkkH*cD`gk5TqvzJyO8Y=Gg$SRvR;e)BZA|E;IWtT7t7)z&{*nP z4O^DchNsHVMoz?>`8Dhs90oc0RzVJ4lFQPes47;Tg;BlNL#vQ=P*~-8q!qB-pPMYLh4z)l4L>dfB>1uO(@{>ph?R zL>uWhQ&w8(LJn#4fMfr3_q#K6DTEi?A%3M#^kXTCm(-yVK%!K&QBg?4H&cSVu5Xs4 z9mz0g{8No8>mdMInQT2INv9y!{HnpTkR;B?>o^caQlSAb*}S=Jy7KL9qF00cAH2FP z-g>hZm7;{Ku28}}LffdF_IrQex{~zJ%{P0?<^v-^CAiExR;KM!lQQfInjp-P2floL z+k5^6ZK5wf{9bzBXFlTzhz#PCVe5=;Bsu+_)WkkgjFSIYsyHYDP9iClP}*47E2drj z8l(0eg+P{p4}Q_O1n=3}1q_Yk5%$qUD~nmHjA0Z%myv4PTwb}*wrpvefB)@meC7_n zM{ar3AGM|1Z)*!Tex)tk@!hukzyob%NohLa32lr1vS7hjX0U~q6H!gfl*Jys|QoK>6J$;?`d)-m+E*}(&C>8ihO(~Do(W?%BMHl5uN z!RZqx`@G^Lj|P%-Kz}l__n$x5_Uj`+OeT$_&hST!Dp=_4RlfRLs;QvZ0r$9JI#eGz zy3;HxuXZ5#%9nUnYD_S3MN%Uofd&7ul+}+0pkSdBm5|n?o9lFlHkT7iovXIws>W4j zYw@dD_zsr3IO>Rq$1_;^qvroMnt||`e$7XHn&1=Yr><>_pZ{zd|I!QF%!N;H;~nSf z3lCEviUX=YP1*mw+uHq~{?9h2Khxx05PL?NIdN!-KHI5nL4|CH&wyjwq9K(CJnN7$ zRyKyDm=ZUhxc*Cqi~-yv*ITR{W6MPk^g8jn9pcA)A5GtN#hwbXYar8UzX#Iy7nMpH z<6T?dAzk3X2`dU)=R$uAXK5pu4oR=+^=M{)dALfnh7+Kt$3A2(K63 zV&%HGRDcYxmwf+p#w$hqu+0}Ate76B|3jNjt}7$`wa)y5dbhmKUzg%Xa0`ch*a|L5 zlD$kI|Ft}`k0JXfR`aP3U;13UKDe1zW3m-qb^~AHB?SH**D;ZgBH)MLgH`MK)@DTW zV?`QBsr=2L&voGsa^l54@t~2U#x&13ipJT2$!dMZa`c3@TD$WYZ!@xX zUKVXx^|+9vZSW2Y=|k%2^htKnlBeX{)y)nwgB3)L5x5EOf=VQ-m-jnnZoKTX6~PA& zLCa(i6UmJ9Ef;m(=7hz;g&EJU_za+`iq)z^@O*kr0?#?-kY5!fU#s}HL6roDqsk3BB8dHo+OMmuGW{@_yu%RIF( zfwnFO$-QW2Qf+E-0LAk1e%L@!nb6N-ZkiSS2=m81)8gc0~#h1cGfALH~%WEsfxNbwSfbAZY22 zG29;xFzPXj(BtU_z6*HJbr-h37OAFRG_#pq8mu2m$fFaD{!HlA1rBzKtOZISZQpxk~hC@G3#-+iwI^|QZfqa#Nl9^0XDMyVc5?*$r4SA zql3v20d!L6>wgZY^x2-mr>}Ow+ZNe3*6PGQPab&bq=`lIVa&GZP?Td#4s_wC^%aI{ zAda!zE%~d*qjz4Vzx!`*5oE-+0_XifEI4GZR2NOnfkqqp`r2|qb`af+(;QnP4o&pA z$KOy#ESxma1Y%lr4H|G4z76OSxVBN z1ECw+H6`sp9y-A?7ILEa5`oDuOR{K-FJ5zk=CPuqS8e1XVQ~PfLs(2I*{tC68c{m@ zjF${6)uyO+!5+1Xj{Tf=Ib`80fws@tMi!bex?0VnDdg+5!nhux!ZLvWYh9zM{-#3z zZJ_CNhkhU0GOSDzSSyfsOPnCk&ID2qN=LOap P00000NkvXXu0mjftw7(^ literal 0 HcmV?d00001 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_normal.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..84fe2a8c11bf2082868a80709a93d3c73c2f24dd GIT binary patch literal 6365 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 literal 0 HcmV?d00001 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_not_exist.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_dev_status_fsm_not_exist.png new file mode 100644 index 0000000000000000000000000000000000000000..2adb8592f811fca6b4e486439a8ccd33efd213a0 GIT binary patch literal 5977 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 Hu0mjfJWI~} literal 0 HcmV?d00001