diff --git a/OCH/common/biz/src/main/res/layout/biz_login_view.xml b/OCH/common/biz/src/main/res/layout/biz_login_view.xml
index e9a131814d..b77d3de518 100644
--- a/OCH/common/biz/src/main/res/layout/biz_login_view.xml
+++ b/OCH/common/biz/src/main/res/layout/biz_login_view.xml
@@ -180,4 +180,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
+
+
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ColdStartView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ColdStartView.kt
index 21d71e9d08..e131dc9053 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ColdStartView.kt
+++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/ColdStartView.kt
@@ -1,15 +1,37 @@
package com.mogo.eagle.core.function.hmi.ui.widget
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.content.Context
+import android.os.CountDownTimer
import android.util.AttributeSet
import android.view.LayoutInflater
+import android.view.View
+import android.view.animation.LinearInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.content.ContextCompat
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
+import com.mogo.eagle.core.function.api.autopilot.IMoGoColdStartStateListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
+import com.mogo.eagle.core.function.call.autopilot.CallerColdStartStateListenerManager
import com.mogo.eagle.core.function.hmi.R
+import com.mogo.eagle.core.utilcode.util.ResourceUtils
+import com.mogo.eagle.core.utilcode.util.ThreadUtils
+import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.zhjt.mogo.adas.data.AdasConstants
+import kotlinx.android.synthetic.main.view_cold_start.view.ivColdStartStatus
+import kotlinx.android.synthetic.main.view_cold_start.view.ivIpcConnectStatus
+import kotlinx.android.synthetic.main.view_cold_start.view.ivSsmConnectStatus
+import kotlinx.android.synthetic.main.view_cold_start.view.tvColdStartContent
+import kotlinx.android.synthetic.main.view_cold_start.view.tvColdStartNodeState
+import kotlinx.android.synthetic.main.view_cold_start.view.tvIpcConnectContent
+import kotlinx.android.synthetic.main.view_cold_start.view.tvSsmConnectContent
+import kotlinx.android.synthetic.main.view_cold_start.view.tvSystemStartupTitle
+import kotlinx.android.synthetic.main.view_cold_start.view.viewColdStartDivider
+import kotlinx.android.synthetic.main.view_cold_start.view.viewSsmConnectDivider
import system_master.SsmInfo
import system_master.SystemStatusInfo
+import java.lang.StringBuilder
/**
* 冷启动呈现二期
@@ -19,41 +41,185 @@ class ColdStartView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoAutopilotStatusListener {
+) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoAutopilotStatusListener,
+ IMoGoColdStartStateListener {
companion object {
const val TAG = "ColdStartView"
+ const val LOAD_SSM_WAITING_TIME = 60000L //SSM加载超时等待时间
+ const val COLD_START_WAITING_TIME = 300000L //冷启动超时等待时间
}
+ private var ipcConnectStatus = false //连接域控状态,默认是未连接
+ private var ssmConnectStatus = false //SSM连接状态,默认是未连接
+ private var coldStartStatus = false //冷启动状态,默认是未冷启动成功
+
+ private var ssmRotationAnim: ObjectAnimator?= null //SSM连接状态动画
+ private var connectSSMTimer: CountDownTimer?= null //连接SSM等待倒计时
+
+ private var coldStartRotationAnim: ObjectAnimator?= null //冷启动连接状态动画
+ private var connectColdStartTimer: CountDownTimer?= null //连接冷启动等待倒计时
+
+ private val nodeStatusSb = StringBuilder() //冷启动关键节点启动详情
+
+ private var coldStartResultListener: ColdStartResultListener ?= null
+
init {
LayoutInflater.from(context).inflate(R.layout.view_cold_start, this, true)
initView()
}
private fun initView(){
+ var num = 1
+ tvSystemStartupTitle.setOnClickListener {
+ if(num == 1){
+ val state = SsmInfo.ModeState.MODE_RUN_READY
+ val info = SsmInfo.SsmStatusInf
+ .newBuilder()
+ .setModeState(state)
+ .setAutoPilotReady(false)
+ .setRemotePilotReady(false)
+ .build()
+
+ CallerAutoPilotStatusListenerManager.invokeSystemStatus(info)
+ num = 2
+ }
+ else if(num == 2){
+ val nodeOne = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("毫米波融合")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_FINISH)
+ .setEventCode("")
+ .build()
+
+ val nodeTwo = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("后融合")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_STARTING)
+ .setEventCode("")
+ .build()
+
+ val nodeThree = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("控制节点")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_STARTING)
+ .setEventCode("")
+ .build()
+
+ val nodeFour = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("地图引擎")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_STARTING)
+ .setEventCode("")
+ .build()
+
+ val list = ArrayList()
+ list.add(nodeOne)
+ list.add(nodeTwo)
+ list.add(nodeThree)
+ list.add(nodeFour)
+
+ val coldStartState = SsmInfo.ColdStartState
+ .newBuilder()
+ .setEventStatus(SsmInfo.CSState.COLD_START_STARTING)
+ .setProcessStatus(SsmInfo.CSState.COLD_START_STARTING)
+ .addAllNode(list)
+ .build()
+
+ CallerColdStartStateListenerManager.invokeColdStartState(
+ 123,
+ System.currentTimeMillis(),
+ false,
+ coldStartState
+ )
+ num = 3
+ }else if(num == 3){
+ val nodeOne = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("毫米波融合")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_FINISH)
+ .setEventCode("")
+ .build()
+
+ val nodeTwo = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("后融合")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_FINISH)
+ .setEventCode("")
+ .build()
+
+ val nodeThree = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("控制节点")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_FINISH)
+ .setEventCode("")
+ .build()
+
+ val nodeFour = SsmInfo.ColdStartNode
+ .newBuilder()
+ .setNodeName("地图引擎")
+ .setDesc("")
+ .setStatus(SsmInfo.NodeStatus.NODE_FINISH)
+ .setEventCode("")
+ .build()
+
+ val list = ArrayList()
+ list.add(nodeOne)
+ list.add(nodeTwo)
+ list.add(nodeThree)
+ list.add(nodeFour)
+
+ val coldStartState = SsmInfo.ColdStartState
+ .newBuilder()
+ .setEventStatus(SsmInfo.CSState.COLD_START_READY)
+ .setProcessStatus(SsmInfo.CSState.COLD_START_READY)
+ .addAllNode(list)
+ .build()
+
+ CallerColdStartStateListenerManager.invokeColdStartState(
+ 123,
+ System.currentTimeMillis(),
+ false,
+ coldStartState
+ )
+ }
+ }
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
CallerAutoPilotStatusListenerManager.addListener(TAG, this)
+ CallerColdStartStateListenerManager.addListener(TAG,this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
CallerAutoPilotStatusListenerManager.removeListener(TAG)
+ CallerColdStartStateListenerManager.removeListener(TAG)
}
override fun onAutopilotIpcConnectStatusChanged(
status: AdasConstants.IpcConnectionStatus,
reason: String?
){
- if(status == AdasConstants.IpcConnectionStatus.CONNECTED){
- //域控连接成功
-
- }else{
- //域控连接失败
-
+ ThreadUtils.runOnUiThread {
+ ipcConnectStatus = if(status == AdasConstants.IpcConnectionStatus.CONNECTED){
+ //域控连接成功
+ showIPCConnectSuccessView()
+ true
+ }else{
+ //域控连接失败
+ showIPCConnectFailView(reason)
+ false
+ }
}
}
@@ -63,7 +229,10 @@ class ColdStartView @JvmOverloads constructor(
* HQ、M1 MAP350开始弃用,其他车型MAP360开始弃用
*/
override fun onAutopilotStatusRespByQuery(status: SystemStatusInfo.StatusInfo) {
-
+ ThreadUtils.runOnUiThread {
+ //SSM连接成功
+ connectSSMSuccess()
+ }
}
@@ -74,7 +243,289 @@ class ColdStartView @JvmOverloads constructor(
* @param statusInf 数据
*/
override fun onSystemStatus(statusInf: SsmInfo.SsmStatusInf) {
+ ThreadUtils.runOnUiThread {
+ //SSM连接成功
+ connectSSMSuccess()
+ }
+ }
+
+ /**
+ * 冷启动状态变更上报以及查询状态
+ *
+ * @param token 唯一消息ID
+ * @param timestamp 消息发送时间 单位:毫秒
+ * @param isQuery 是否是查询 ture:查询相应的结果 false:表示状态变动域控主动推送
+ * @param coldStartState 数据 null表示 PadSsmMsg中的消息体为null
+ */
+ override fun onColdStartState(
+ token: Long,
+ timestamp: Long,
+ isQuery: Boolean,
+ coldStartState: SsmInfo.ColdStartState?
+ ) {
+ coldStartState?.let {
+ ThreadUtils.runOnUiThread {
+ if(it.eventStatus == SsmInfo.CSState.COLD_START_READY){
+ //冷启动就绪
+ showColdStartSuccessView()
+ }
+ tvColdStartContent.text = getColdStartEventStatus(it.eventStatus)
+ nodeStatusSb.clear()
+ it.nodeList.forEach {node->
+ nodeStatusSb.append("【")
+ nodeStatusSb.append(node.nodeName)
+ nodeStatusSb.append(" ")
+ nodeStatusSb.append(getColdStartNodeStatus(node.status))
+ nodeStatusSb.append("】\n")
+ }
+ tvColdStartNodeState.text = nodeStatusSb.toString()
+ }
+ }
+ }
+
+ /**
+ * 冷启动状态
+ */
+ private fun getColdStartEventStatus(state: SsmInfo.CSState): String{
+ return when(state){
+ // 未开始
+ SsmInfo.CSState.COLD_START_DEFAULT->{
+ "启动中…"
+ }
+ // 启动中
+ SsmInfo.CSState.COLD_START_STARTING->{
+ "启动中…"
+ }
+ // 就绪
+ SsmInfo.CSState.COLD_START_READY->{
+ "系统启动成功,即将进入主页"
+ }
+ // 有异常未就绪
+ SsmInfo.CSState.COLD_START_UNREADY->{
+ "系统启动异常,建议重启车辆并上报问题"
+ }
+ // 超时
+ SsmInfo.CSState.COLD_START_TIMEOUT->{
+ "系统启动异常,建议重启车辆并上报问题"
+ }
+ }
+ }
+
+ /**
+ * 获取节点启动状态
+ */
+ private fun getColdStartNodeStatus(nodeStatus: SsmInfo.NodeStatus): String{
+ return when(nodeStatus){
+ // 启动中
+ SsmInfo.NodeStatus.NODE_STARTING->{
+ "启动中"
+ }
+ // 启动成功
+ SsmInfo.NodeStatus.NODE_FINISH->{
+ "启动成功"
+ }
+ // 启动失败
+ SsmInfo.NodeStatus.NODE_FAILED->{
+ "启动失败"
+ }
+ // 启动超时
+ SsmInfo.NodeStatus.NODE_TIMEOUT->{
+ "启动超时"
+ }
+
+ }
+ }
+
+
+ /**
+ * 展示域控连接成功视图
+ */
+ private fun showIPCConnectSuccessView(){
+ ivIpcConnectStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_success))
+ tvIpcConnectContent.text = resources.getString(R.string.ipc_connect_success)
+ //开启连接SSM倒计时
+ connectSSMProcess()
+ //域控连接成功后开始展示SSM连接状态
+ viewSsmConnectDivider.visibility = View.VISIBLE
+ ivSsmConnectStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_process))
+ //旋转动画
+ ssmRotationAnim = ObjectAnimator.ofFloat(ivSsmConnectStatus, "rotation", 0f, 360f)
+ ssmRotationAnim?.repeatCount = ValueAnimator.INFINITE
+ ssmRotationAnim?.repeatMode = ValueAnimator.RESTART
+ ssmRotationAnim?.duration = 1500
+ ssmRotationAnim?.interpolator = LinearInterpolator()
+ ssmRotationAnim?.start()
+ //设置SSM连接文案为连接中
+ tvSsmConnectContent.text = resources.getString(R.string.ssm_connect_loading)
+ tvSsmConnectContent.setTextColor(ContextCompat.getColor(context, android.R.color.white))
+ //隐藏冷启动相关视图
+ viewColdStartDivider.visibility = View.GONE
+ ivColdStartStatus.visibility = View.GONE
+ tvColdStartContent.visibility = View.GONE
+ }
+
+ /**
+ * 展示域控连接失败视图
+ */
+ private fun showIPCConnectFailView(reason: String?){
+ ivIpcConnectStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_fail))
+ reason?.let {
+ tvIpcConnectContent.text = it
+ }
+ //隐藏SSM相关视图
+ viewSsmConnectDivider.visibility = View.GONE
+ ivSsmConnectStatus.visibility = View.GONE
+ tvSsmConnectContent.visibility = View.GONE
+ //隐藏冷启动相关视图
+ viewColdStartDivider.visibility = View.GONE
+ ivColdStartStatus.visibility = View.GONE
+ tvColdStartContent.visibility = View.GONE
}
+ /**
+ * SSM连接成功
+ */
+ private fun connectSSMSuccess(){
+ if(!ssmConnectStatus){
+ showSSMConnectSuccessView()
+ //取消连接SSM超时等待倒计时
+ connectSSMTimer?.cancel()
+ //开始启动冷启动等待倒计时
+ coldStartProcess()
+ }
+ ssmConnectStatus = true
+ coldStartStatus = false
+ }
+
+ /**
+ * 展示SSM连接成功视图
+ */
+ private fun showSSMConnectSuccessView(){
+ //取消旋转动画
+ ssmRotationAnim?.cancel()
+ //取消连接SSM超时等待倒计时
+ connectSSMTimer?.cancel()
+ //展示SSM连接成功视图
+ ivSsmConnectStatus.rotation = 0f
+ ivSsmConnectStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_success))
+ tvSsmConnectContent.text = resources.getString(R.string.ssm_connect_success)
+ tvSsmConnectContent.setTextColor(ContextCompat.getColor(context, R.color.white))
+ //展示冷启动连接过程视图
+ viewColdStartDivider.visibility = View.VISIBLE
+ ivColdStartStatus.visibility = View.VISIBLE
+ tvColdStartContent.visibility = View.VISIBLE
+ tvColdStartContent.text = "启动中…"
+ ivColdStartStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_process))
+ //开启冷启动连接状态动画
+ coldStartRotationAnim = ObjectAnimator.ofFloat(ivColdStartStatus, "rotation", 0f, 360f)
+ coldStartRotationAnim?.repeatCount = ValueAnimator.INFINITE
+ coldStartRotationAnim?.repeatMode = ValueAnimator.RESTART
+ coldStartRotationAnim?.duration = 1500
+ coldStartRotationAnim?.interpolator = LinearInterpolator()
+ coldStartRotationAnim?.start()
+ }
+
+ /**
+ * 展示SSM连接失败视图
+ */
+ private fun showSSMConnectFailView(){
+ //取消旋转动画
+ ssmRotationAnim?.cancel()
+ ivSsmConnectStatus.rotation = 0f
+ ivSsmConnectStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_fail))
+ tvSsmConnectContent.text = resources.getString(R.string.ssm_connect_fail)
+ tvSsmConnectContent.setTextColor(ContextCompat.getColor(context, R.color.cold_start_fail))
+ }
+
+ /**
+ * 连接SSM过程
+ */
+ private fun connectSSMProcess(){
+ ThreadUtils.runOnUiThread {
+ connectSSMTimer = object: CountDownTimer(LOAD_SSM_WAITING_TIME,LOAD_SSM_WAITING_TIME){
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ //将SSM连接状态置为false
+ ssmConnectStatus = false
+ coldStartStatus = false
+ //取消连接SSM超时等待倒计时
+ connectSSMTimer?.cancel()
+ //展示连接SSM失败视图
+ showSSMConnectFailView()
+ }
+ }
+ connectSSMTimer?.start()
+ }
+ }
+
+ /**
+ * 冷启动过程
+ */
+ private fun coldStartProcess(){
+ ThreadUtils.runOnUiThread {
+ connectColdStartTimer = object: CountDownTimer(COLD_START_WAITING_TIME,COLD_START_WAITING_TIME){
+ override fun onTick(millisUntilFinished: Long) {
+ }
+
+ override fun onFinish() {
+ //将冷启动状态置为false
+ coldStartStatus = false
+ //展示冷启动失败视图
+ showColdStartFailView()
+ }
+ }
+ connectColdStartTimer?.start()
+ }
+ }
+
+ /**
+ * 冷启动失败视图
+ */
+ private fun showColdStartFailView(){
+ coldStartRotationAnim?.cancel()
+ ivColdStartStatus.rotation = 0f
+ ivColdStartStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_fail))
+ tvColdStartContent.text = resources.getString(R.string.cold_start_fail_content)
+ coldStartResultListener?.coldStartFail()
+ }
+
+ /**
+ * 冷启动成功视图
+ */
+ private fun showColdStartSuccessView(){
+ tvSystemStartupTitle.text = resources.getString(R.string.cold_start_success_title)
+ coldStartRotationAnim?.cancel()
+ ivColdStartStatus.rotation = 0f
+ ivColdStartStatus.setImageDrawable(ResourceUtils.getDrawable(R.drawable.icon_cold_start_success))
+ tvColdStartContent.text = resources.getString(R.string.cold_start_success_content)
+ connectColdStartTimer?.cancel()
+ hideColdStartView()
+ }
+
+ /**
+ * 隐藏冷启动视图
+ */
+ private fun hideColdStartView(){
+ UiThreadHandler.postDelayed({
+ this@ColdStartView.visibility = View.GONE
+ coldStartResultListener?.coldStartSuccess()
+ }, 2000)
+ }
+
+ /**
+ * 冷启动接管监听接口
+ */
+ interface ColdStartResultListener{
+ fun coldStartSuccess()
+ fun coldStartFail()
+ }
+
+ fun setColdStartResultListener(listener: ColdStartResultListener){
+ coldStartResultListener = listener
+ }
+
}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_cold_start.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_cold_start.xml
index 1da924a954..8c3e142080 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_cold_start.xml
+++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_cold_start.xml
@@ -2,7 +2,9 @@
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:background="#7F000000"
+ >
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/values/color.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/values/color.xml
index f286b4bedd..99dcf87443 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/res/values/color.xml
+++ b/core/function-impl/mogo-core-function-hmi/src/main/res/values/color.xml
@@ -92,4 +92,6 @@
#131415
+ #FFCD3D
+
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml
index a219598048..ff00a195de 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml
+++ b/core/function-impl/mogo-core-function-hmi/src/main/res/values/strings.xml
@@ -215,5 +215,14 @@
域控连接状态图标
SSM连接状态图标
+ 冷启动状态图标
+ 已连接域控
+ 系统启动中…
+ 系统启动成功
+ 正在连接SSM…
+ 已连接SSM
+ SSM连接异常,建议重启车辆并上报问题
+ 系统启动成功,即将进入主页
+ 系统启动异常,建议重启车辆并上报问题