Merge branch 'dev_robotaxi-d_250620_8.1.0_new_ota' into dev_robotaxi-d_250804_8.2.0
# Conflicts: # core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt
This commit is contained in:
@@ -1556,6 +1556,14 @@ class MoGoAutopilotControlProvider :
|
||||
return AdasManager.getInstance().sendSsmFuncOtaStatusQuery(token)>-1
|
||||
}
|
||||
|
||||
/**
|
||||
* OTA2.0查询
|
||||
* @param queryStr {"cmd":"PAD_QUERY_UPGRADE_STATUS","token":"123"} JSON
|
||||
*/
|
||||
override fun sendOtaPadMsgQuery(queryStr: String): Boolean {
|
||||
return AdasManager.getInstance().sendOtaPadMsgQuery(queryStr) > -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 人工接管时获取前方和后方摄像头数据
|
||||
* 一次请求域控回调次两次摄像头数据 根据{@link MessagePad.CaptureImgOnTakeOver#getUuid()}进行区分是否是哪次请求
|
||||
|
||||
@@ -622,6 +622,9 @@ class MoGoAdasListenerImpl : OnAdasListener {
|
||||
timestamp: Long,
|
||||
status: SsmInfo.PureStr?
|
||||
) {
|
||||
if(status != null){
|
||||
CallerOTAManager.invokeOtaPureStr(token,timestamp,status)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,4 +28,26 @@ object OTAUpgradeConfig {
|
||||
//已经提示过升级成功的列表
|
||||
@JvmField
|
||||
var upgradeFinish: ArrayList<String> = ArrayList()
|
||||
|
||||
//OTA2.0 Token
|
||||
@JvmField
|
||||
var token: String = ""
|
||||
|
||||
//已经提示过升级的列表
|
||||
var promptedUpgradeTwo: ArrayList<String> = ArrayList()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -46,6 +46,8 @@ object OTAUpgradeManager: IMoGoAutopilotStatusListener, IDataCenterBizListener,
|
||||
private var responseTimeoutNum: Int = 0 //响应超时次数
|
||||
private var shouldShowColdStartWindow: Boolean = false //是否需要展示冷启动页面
|
||||
|
||||
private var versionTwoTimeoutNum: Int = 0 //OTA2.0版本响应超时次数
|
||||
|
||||
private val handler =object : Handler(Looper.getMainLooper()){
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
@@ -68,6 +70,24 @@ object OTAUpgradeManager: IMoGoAutopilotStatusListener, IDataCenterBizListener,
|
||||
//司机屏弹窗提示用车人执行车辆下电操作
|
||||
CallerHmiManager.showOTAPowerOffFinishDialog()
|
||||
shouldShowColdStartWindow = true
|
||||
}else if(msg.what == 3){
|
||||
//OTA2.0超时查询
|
||||
if(versionTwoTimeoutNum<40){
|
||||
versionTwoTimeoutNum++
|
||||
//30秒没有收到OTA升级推送主动进行查询
|
||||
Log.i(TAG,"30秒没有收到OTA升级推送主动进行查询")
|
||||
//查询OTA升级
|
||||
val query = JSONObject()
|
||||
query.put("cmd","PAD_QUERY_UPGRADE_STATUS")
|
||||
query.put("token",OTAUpgradeConfig.token)
|
||||
Log.i("xuxinchao",query.toString())
|
||||
CallerAutoPilotControlManager.sendOtaPadMsgQuery(query.toString())
|
||||
this.sendEmptyMessageDelayed(3,30000)
|
||||
}else{
|
||||
Log.i(TAG,"20分钟没有收到OTA升级推送置为失败")
|
||||
CallerHmiManager.showOTADownloadStatusDialog(false, emptyList())
|
||||
CallerHmiManager.showOTAResultDialog(isShow = true, result = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,6 +414,133 @@ object OTAUpgradeManager: IMoGoAutopilotStatusListener, IDataCenterBizListener,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* OTA 2.0 新接口
|
||||
* @param token PadSsmMsg唯一消息ID
|
||||
* @param timestamp 消息发送时间 单位:毫秒
|
||||
* @param status OTA 2.0 数据
|
||||
*/
|
||||
override fun onOtaPureStr(token: Long, timestamp: Long, status: SsmInfo.PureStr) {
|
||||
super.onOtaPureStr(token, timestamp, status)
|
||||
Log.i(TAG, "onOtaPureStr token=$token")
|
||||
Log.i(TAG, "onOtaPureStr timestamp=$timestamp")
|
||||
Log.i(TAG, "onOtaPureStr status=$status")
|
||||
Log.i(TAG, "onOtaPureStr status.data=${status.data}")
|
||||
val jsonObject = JSONObject(status.data)
|
||||
val cmd = jsonObject.optString("cmd")
|
||||
|
||||
//无升级任务
|
||||
if("ASK_PAD_NO_UPGRADE" == cmd){
|
||||
ToastUtils.showShort("暂无OTA升级任务")
|
||||
return
|
||||
}
|
||||
|
||||
val otaToken = jsonObject.optString("token")
|
||||
val otaStatus = jsonObject.optString("status")
|
||||
val upgradeReason = jsonObject.optString("upgrade_reason")
|
||||
val isDelay = jsonObject.optBoolean("is_delay")
|
||||
val isCancel = jsonObject.optBoolean("is_cancel")
|
||||
|
||||
Log.i(TAG, "cmd=$cmd")
|
||||
Log.i(TAG, "otaToken=$otaToken")
|
||||
Log.i(TAG, "otaStatus=$otaStatus")
|
||||
Log.i(TAG, "upgradeReason=$upgradeReason")
|
||||
Log.i(TAG, "isDelay=$isDelay")
|
||||
Log.i(TAG, "isCancel=$isCancel")
|
||||
|
||||
OTAUpgradeConfig.token = otaToken
|
||||
|
||||
val products = jsonObject.optString("products")
|
||||
val productsArray = JSONArray(products)
|
||||
val otaUpgradeList = ArrayList<OtaUpgradeInfo>()
|
||||
if(productsArray.length() > 0){
|
||||
for(index in 0 until productsArray.length()){
|
||||
val productInfo = productsArray[index] as JSONObject
|
||||
val productStatus = productInfo.optString("status")
|
||||
val failReason = productInfo.optString("fail_reason")
|
||||
val speed = productInfo.optDouble("speed")
|
||||
val leftTime = productInfo.optInt("left_time")
|
||||
val name = productInfo.optString("name")
|
||||
val curSize = productInfo.optDouble("cur_size")
|
||||
val totalSize = productInfo.optDouble("total_size")
|
||||
|
||||
Log.i(TAG, "productStatus=$productStatus")
|
||||
Log.i(TAG, "failReason=$failReason")
|
||||
Log.i(TAG, "speed=$speed")
|
||||
Log.i(TAG, "leftTime=$leftTime")
|
||||
Log.i(TAG, "name=$name")
|
||||
Log.i(TAG, "curSize=$curSize")
|
||||
Log.i(TAG, "totalSize=$totalSize")
|
||||
|
||||
val otaUpgradeInfo = OtaUpgradeInfo(otaToken, getProjectStatus(productStatus),failReason,upgradeReason,
|
||||
0,0,1,name,true,isDelay,curSize,totalSize,leftTime)
|
||||
otaUpgradeList.add(otaUpgradeInfo)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//请求升级
|
||||
if(cmd == "ASK_PAD_UPGRADE" && otaStatus == "init"){
|
||||
//冷启动已完成(包括成功/失败),且驾驶状态为非自驾状态,且当前无订单进行强提示,否则为弱提示
|
||||
if(OTAUpgradeConfig.coldStartCompleted && !OTAUpgradeConfig.autopilotStatus
|
||||
&& !OTAUpgradeConfig.inOrder){
|
||||
//触发强提示升级
|
||||
CallerHmiManager.showOTAUpgradeDialog(true,upgradeReason)
|
||||
}else{
|
||||
//触发弱提示升级
|
||||
//冷启动未完成(进行中),或驾驶状态为自驾状态,或当前有订单,直接默认选择稍后升级,
|
||||
// 并toast提示“收到车辆部署任务,请在车辆空闲时发起升级”
|
||||
|
||||
val reason = if(OTAUpgradeConfig.autopilotStatus){
|
||||
"处于自驾中"
|
||||
}else if(OTAUpgradeConfig.inOrder){
|
||||
"处于订单中"
|
||||
}else{
|
||||
"冷启动未完成"
|
||||
}
|
||||
val query = JSONObject()
|
||||
query.put("cmd","ASK_PAD_UPGRADE_RES")
|
||||
query.put("token",OTAUpgradeConfig.token)
|
||||
query.put("allow_upgrade",false)
|
||||
query.put("reason",reason)
|
||||
Log.i("xuxinchao",query.toString())
|
||||
CallerAutoPilotControlManager.sendOtaPadMsgQuery(query.toString())
|
||||
|
||||
ToastUtils.showLong("收到车辆部署任务,请在车辆空闲时发起升级")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//升级中
|
||||
if(cmd == "PAD_UPGRADE_REPORT"){
|
||||
CallerHmiManager.showOTADownloadStatusDialog(true,otaUpgradeList)
|
||||
versionTwoTimeoutNum = 0
|
||||
handler.removeMessages(3)
|
||||
handler.sendEmptyMessageDelayed(3,30000)
|
||||
}
|
||||
//升级完成
|
||||
if(otaStatus == "fail"){
|
||||
CallerHmiManager.showOTADownloadStatusDialog(false,emptyList())
|
||||
CallerHmiManager.showOTAResultDialog(isShow = true, result = false)
|
||||
versionTwoTimeoutNum = 0
|
||||
handler.removeMessages(3)
|
||||
CallerOTAManager.invokeOtaDownloadStatus(false)
|
||||
}
|
||||
if(otaStatus == "success"){
|
||||
//升级成功,自动执行优雅停服
|
||||
CallerAutoPilotControlManager.sendIpcPowerOff()
|
||||
//当优雅停服完成、需要车辆下电的时候(比如当前是停服触发60s后),车端告知鹰眼,司机屏弹窗提示用车人执行车辆下电操作
|
||||
handler.sendEmptyMessageDelayed(2,60000)
|
||||
CallerOTAManager.invokeOtaDownloadStatus(false)
|
||||
CallerHmiManager.showOTADownloadStatusDialog(false,emptyList())
|
||||
CallerHmiManager.showOTAResultDialog(isShow = true, result = true)
|
||||
versionTwoTimeoutNum = 0
|
||||
handler.removeMessages(3)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private val pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+")
|
||||
|
||||
/**
|
||||
@@ -438,5 +585,32 @@ object OTAUpgradeManager: IMoGoAutopilotStatusListener, IDataCenterBizListener,
|
||||
return version
|
||||
}
|
||||
|
||||
private fun getProjectStatus(status: String): Int{
|
||||
return when(status){
|
||||
"init"->{
|
||||
0
|
||||
}
|
||||
"downloading"->{
|
||||
1
|
||||
}
|
||||
"sync_slave"->{
|
||||
2
|
||||
}
|
||||
"upgrading"->{
|
||||
2
|
||||
}
|
||||
"success"->{
|
||||
3
|
||||
}
|
||||
"fail"->{
|
||||
4
|
||||
}
|
||||
else->{
|
||||
0
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -154,14 +154,24 @@ class CarInfoTabView @JvmOverloads constructor(
|
||||
"${SceneConstant.M_HMI}${TAG}",
|
||||
"ad version view clicked"
|
||||
)
|
||||
if(OTAUpgradeConfig.supportOTA){
|
||||
//查询OTA状态
|
||||
OTAUpgradeConfig.isQuery = true
|
||||
OTAUpgradeConfig.promptedUpgrade.remove(OTAUpgradeConfig.otaToken)
|
||||
CallerAutoPilotControlManager.sendSsmFuncOtaStatusQuery(OTAUpgradeConfig.otaToken)
|
||||
}else{
|
||||
ToastUtils.showLong("当前SSM节点未成功启动或当前版本不支持OTA升级")
|
||||
}
|
||||
// if(OTAUpgradeConfig.supportOTA){
|
||||
// //查询OTA状态
|
||||
// OTAUpgradeConfig.isQuery = true
|
||||
// OTAUpgradeConfig.promptedUpgrade.remove(OTAUpgradeConfig.otaToken)
|
||||
// CallerAutoPilotControlManager.sendSsmFuncOtaStatusQuery(OTAUpgradeConfig.otaToken)
|
||||
// }else{
|
||||
// ToastUtils.showLong("当前SSM节点未成功启动或当前版本不支持OTA升级")
|
||||
// }
|
||||
|
||||
|
||||
//查询OTA升级
|
||||
val query = JSONObject()
|
||||
query.put("cmd","PAD_QUERY_UPGRADE_STATUS")
|
||||
query.put("token",OTAUpgradeConfig.token)
|
||||
Log.i("xuxinchao",query.toString())
|
||||
CallerAutoPilotControlManager.sendOtaPadMsgQuery(query.toString())
|
||||
|
||||
|
||||
}
|
||||
tvHDMapVersion.text = tvHDMapVersion.text.toString() + DebugConfig.getMapVersion()
|
||||
//高精地图 检查更新
|
||||
|
||||
@@ -8,25 +8,31 @@ import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.mogo.commons.env.ProjectUtils
|
||||
import com.mogo.commons.voice.AIAssist
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.data.deva.report.ReportEntity
|
||||
import com.mogo.eagle.core.data.enums.DataSourceType
|
||||
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
|
||||
import com.mogo.eagle.core.data.msgbox.FMInfoMsg
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxCountDownBean
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxType
|
||||
import com.mogo.eagle.core.data.msgbox.MsgCategory
|
||||
import com.mogo.eagle.core.data.msgbox.MsgFmData
|
||||
import com.mogo.eagle.core.data.takeover.TAKE_OVER_REQUEST
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoNodeStateListener
|
||||
import com.mogo.eagle.core.function.api.datacenter.IDataCenterBizListener
|
||||
import com.mogo.eagle.core.function.api.datacenter.msgbox.IMsgBoxListener
|
||||
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
|
||||
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.CallerNodeStateListenerManager
|
||||
import com.mogo.eagle.core.function.call.datacenter.CallerDataCenterBizListener
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
|
||||
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxEventListenerManager
|
||||
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxListenerManager
|
||||
import com.mogo.eagle.core.function.call.setting.CallerTakeOverManager
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import com.mogo.eagle.core.function.hmi.ui.msgbox.adapter.DriverMsgBoxBubbleAdapter
|
||||
import com.mogo.eagle.core.function.msgbox.MsgBoxConfig
|
||||
@@ -149,41 +155,98 @@ class DriverMsgBoxBubbleView @JvmOverloads constructor(
|
||||
} else if (category == MsgCategory.FM_INFO) {
|
||||
CallerMsgBoxEventListenerManager.invokeUpdateTipListener(true)
|
||||
if (FunctionBuildConfig.isTakeoverRemind) {
|
||||
//属于停车警示(包括择机靠边停车、立即舒适停车、就地紧急停车)时,需要弹出消息气泡并伴有提示音
|
||||
|
||||
// //属于停车警示(包括择机靠边停车、立即舒适停车、就地紧急停车)时,需要弹出消息气泡并伴有提示音
|
||||
// var curFaultLevel = 5 //默认级别,遍历数组找出级别最高的(level数越小,级别越高)
|
||||
// fmInfoMsg.fmInfoList?.forEach { faultInfo ->
|
||||
// if (faultInfo.faultActionCount > 0) {
|
||||
// faultInfo.faultActionList.forEach { actionCode ->
|
||||
// //获取建议操作级别,得到建议操作级别最高的操作
|
||||
// if (MsgFmData.FaultAction.getFaultLevel(actionCode) < curFaultLevel) {
|
||||
// curFaultLevel =
|
||||
// MsgFmData.FaultAction.getFaultLevel(actionCode)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// //P0级消息弹出时需要判断驾驶状态,非自动驾驶、非平行驾驶状态不弹出,其余状态弹出
|
||||
// if (curFaultLevel == 0) {
|
||||
// //自动驾驶状态 0是不可用 1是ready 2是自动驾驶中 7:平行驾驶中
|
||||
// if (CallerAutoPilotStatusListenerManager.getState() == 2
|
||||
// || CallerAutoPilotStatusListenerManager.getState() == 7
|
||||
// ) {
|
||||
// // 6.6.0 ,因为 FSM 模块也会弹修改为只有没有 FSM 模块才弹
|
||||
// // 6.6.0 ,20240823 考虑到 FSM 初期消息不一定全,先不加限制,产品先观察功能后再考虑是否过滤
|
||||
// // if (hasNoneFSMNode()) {
|
||||
// //语音提示
|
||||
// try {
|
||||
// SoundPoolUtils.getSoundPool()
|
||||
// .playSoundWithRedId(context, R.raw.weak_net_tips)
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// //展示消息
|
||||
// showData(msgBoxBean)
|
||||
// //}
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 8.2.0需求:定义三种不同提示强度的异常提示交互
|
||||
* 不判断驾驶状态,发生相应故障时立即有相应的提醒
|
||||
* 若同一时间触发多个多种级别异常,则按照最高级别的异常交互元素做提醒,低级别的异常不做特殊提醒
|
||||
* 若同一时间触发多个同一级别异常,则同一时刻只提醒一次,不互相打断
|
||||
* 除此以外不做其他提示频率限制
|
||||
*
|
||||
* 一级:安全停车
|
||||
* FM_DP_EMERGENCY_STOP(就地紧急停车)、FM_DP_COMFORTABLE_STOP(立刻舒适停车)、FM_DP_PNC_CHOOSE_STOP(择机靠边停车)
|
||||
* 交互:图像、TTS、消息盒子
|
||||
*
|
||||
* 二级:降速行驶
|
||||
* FM_DP_SPEED_LIMIT3(三级降速)、FM_DP_SPEED_LIMIT2(二级降速)、FM_DP_SPEED_LIMIT1(一级降速)
|
||||
* 交互:TTS、消息盒子
|
||||
*
|
||||
* 三级:无操作
|
||||
* FM_DP_ONLY_WARNING(警示)、FM_DP_NO_ACTION(报告)
|
||||
* ps:以上异常提醒受司机屏工具箱-运营面板-美化模式-接管提醒开关控制,默认开启有全量提示,关闭后无语音/图像提示,只有消息盒子红点展示
|
||||
*/
|
||||
val fmInfoMsg = msgBoxBean.bean as FMInfoMsg
|
||||
var curFaultLevel = 5 //默认级别,遍历数组找出级别最高的(level数越小,级别越高)
|
||||
fmInfoMsg.fmInfoList?.forEach { faultInfo ->
|
||||
if (faultInfo.faultActionCount > 0) {
|
||||
faultInfo.faultActionList.forEach { actionCode ->
|
||||
//获取建议操作级别,得到建议操作级别最高的操作
|
||||
if (MsgFmData.FaultAction.getFaultLevel(actionCode) < curFaultLevel) {
|
||||
curFaultLevel =
|
||||
MsgFmData.FaultAction.getFaultLevel(actionCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//P0级消息弹出时需要判断驾驶状态,非自动驾驶、非平行驾驶状态不弹出,其余状态弹出
|
||||
if (curFaultLevel == 0) {
|
||||
//自动驾驶状态 0是不可用 1是ready 2是自动驾驶中 7:平行驾驶中
|
||||
if (CallerAutoPilotStatusListenerManager.getState() == 2
|
||||
|| CallerAutoPilotStatusListenerManager.getState() == 7
|
||||
) {
|
||||
// 6.6.0 ,因为 FSM 模块也会弹修改为只有没有 FSM 模块才弹
|
||||
// 6.6.0 ,20240823 考虑到 FSM 初期消息不一定全,先不加限制,产品先观察功能后再考虑是否过滤
|
||||
// if (hasNoneFSMNode()) {
|
||||
//语音提示
|
||||
try {
|
||||
SoundPoolUtils.getSoundPool()
|
||||
.playSoundWithRedId(context, R.raw.weak_net_tips)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
//展示消息
|
||||
when(MsgFmData.getFmPolicyLevel(fmInfoMsg.policyCode)){
|
||||
//一级
|
||||
MsgFmData.LEVEL_ONE->{
|
||||
//接管图像提示、语音提示
|
||||
CallerDevaToolsManager.takeOver(TAKE_OVER_REQUEST)
|
||||
CallerHmiManager.warningV2X(
|
||||
EventTypeEnumNew.TAKE_OVER_EVENT.poiType,
|
||||
EventTypeEnumNew.TAKE_OVER_EVENT.content,
|
||||
"识别车辆故障,建议立即接管安全停车,查看操作建议",
|
||||
object : IMoGoWarningStatusListener {
|
||||
override fun onShow() {
|
||||
CallerTakeOverManager.invokeTakeOverEvent(true)
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
CallerTakeOverManager.invokeTakeOverEvent(false)
|
||||
}
|
||||
},expireTime =3000L, isFromObu = false
|
||||
)
|
||||
//展示消息盒子消息
|
||||
showData(msgBoxBean)
|
||||
//}
|
||||
}
|
||||
//二级
|
||||
MsgFmData.LEVEL_TWO->{
|
||||
//语音提示
|
||||
AIAssist.getInstance(context).speakTTSVoice("识别车辆异常,建议尽快安全停车,查看操作建议")
|
||||
//展示消息盒子消息
|
||||
showData(msgBoxBean)
|
||||
}
|
||||
//三级
|
||||
MsgFmData.LEVEL_THREE->{
|
||||
//在消息盒子图标上,可查看到红点标记,无其他元素特殊提醒;点进消息盒子可查看到详细信息
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
if (msgBoxBean.sourceType == DataSourceType.SUMMARY) {
|
||||
|
||||
@@ -8,23 +8,29 @@ import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.mogo.commons.env.ProjectUtils
|
||||
import com.mogo.commons.voice.AIAssist
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.data.deva.report.ReportEntity
|
||||
import com.mogo.eagle.core.data.enums.DataSourceType
|
||||
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
|
||||
import com.mogo.eagle.core.data.msgbox.FMInfoMsg
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxCountDownBean
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxType
|
||||
import com.mogo.eagle.core.data.msgbox.MsgCategory
|
||||
import com.mogo.eagle.core.data.msgbox.MsgFmData
|
||||
import com.mogo.eagle.core.data.takeover.TAKE_OVER_REQUEST
|
||||
import com.mogo.eagle.core.function.api.datacenter.IDataCenterBizListener
|
||||
import com.mogo.eagle.core.function.api.datacenter.msgbox.IMsgBoxListener
|
||||
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerIpcConnectStateToastManager
|
||||
import com.mogo.eagle.core.function.call.datacenter.CallerDataCenterBizListener
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
|
||||
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxEventListenerManager
|
||||
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxListenerManager
|
||||
import com.mogo.eagle.core.function.call.setting.CallerTakeOverManager
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import com.mogo.eagle.core.function.hmi.ui.msgbox.adapter.MsgBoxToastAdapter
|
||||
import com.mogo.eagle.core.function.msgbox.MsgBoxConfig
|
||||
@@ -141,41 +147,96 @@ class MsgBoxToastView @JvmOverloads constructor(
|
||||
} else if (category == MsgCategory.FM_INFO) {
|
||||
CallerMsgBoxEventListenerManager.invokeUpdateTipListener(true)
|
||||
if (FunctionBuildConfig.isTakeoverRemind) {
|
||||
//属于停车警示(包括择机靠边停车、立即舒适停车、就地紧急停车)时,需要弹出消息气泡并伴有提示音
|
||||
// //属于停车警示(包括择机靠边停车、立即舒适停车、就地紧急停车)时,需要弹出消息气泡并伴有提示音
|
||||
// var curFaultLevel = 5 //默认级别,遍历数组找出级别最高的(level数越小,级别越高)
|
||||
// fmInfoMsg.fmInfoList?.forEach { faultInfo ->
|
||||
// if (faultInfo.faultActionCount > 0) {
|
||||
// faultInfo.faultActionList.forEach { actionCode ->
|
||||
// //获取建议操作级别,得到建议操作级别最高的操作
|
||||
// if (MsgFmData.FaultAction.getFaultLevel(actionCode) < curFaultLevel) {
|
||||
// curFaultLevel =
|
||||
// MsgFmData.FaultAction.getFaultLevel(actionCode)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// //P0级消息弹出时需要判断驾驶状态,非自动驾驶、非平行驾驶状态不弹出,其余状态弹出
|
||||
// if (curFaultLevel == 0) {
|
||||
// //自动驾驶状态 0是不可用 1是ready 2是自动驾驶中 7:平行驾驶中
|
||||
// if (CallerAutoPilotStatusListenerManager.getState() == 2
|
||||
// || CallerAutoPilotStatusListenerManager.getState() == 7
|
||||
// ) {
|
||||
// // 6.6.0 ,因为 FSM 模块也会弹修改为只有没有 FSM 模块才弹
|
||||
// // 6.6.0 ,20240823 考虑到 FSM 初期消息不一定全,先不加限制,产品先观察功能后再考虑是否过滤
|
||||
// // if (hasNoneFSMNode()) {
|
||||
// //语音提示
|
||||
// try {
|
||||
// SoundPoolUtils.getSoundPool()
|
||||
// .playSoundWithRedId(context, R.raw.weak_net_tips)
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// //展示消息
|
||||
// showData(msgBoxBean)
|
||||
// //}
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 8.2.0需求:定义三种不同提示强度的异常提示交互
|
||||
* 不判断驾驶状态,发生相应故障时立即有相应的提醒
|
||||
* 若同一时间触发多个多种级别异常,则按照最高级别的异常交互元素做提醒,低级别的异常不做特殊提醒
|
||||
* 若同一时间触发多个同一级别异常,则同一时刻只提醒一次,不互相打断
|
||||
* 除此以外不做其他提示频率限制
|
||||
*
|
||||
* 一级:安全停车
|
||||
* FM_DP_EMERGENCY_STOP(就地紧急停车)、FM_DP_COMFORTABLE_STOP(立刻舒适停车)、FM_DP_PNC_CHOOSE_STOP(择机靠边停车)
|
||||
* 交互:图像、TTS、消息盒子
|
||||
*
|
||||
* 二级:降速行驶
|
||||
* FM_DP_SPEED_LIMIT3(三级降速)、FM_DP_SPEED_LIMIT2(二级降速)、FM_DP_SPEED_LIMIT1(一级降速)
|
||||
* 交互:TTS、消息盒子
|
||||
*
|
||||
* 三级:无操作
|
||||
* FM_DP_ONLY_WARNING(警示)、FM_DP_NO_ACTION(报告)
|
||||
* ps:以上异常提醒受司机屏工具箱-运营面板-美化模式-接管提醒开关控制,默认开启有全量提示,关闭后无语音/图像提示,只有消息盒子红点展示
|
||||
*/
|
||||
val fmInfoMsg = msgBoxBean.bean as FMInfoMsg
|
||||
var curFaultLevel = 5 //默认级别,遍历数组找出级别最高的(level数越小,级别越高)
|
||||
fmInfoMsg.fmInfoList?.forEach { faultInfo ->
|
||||
if (faultInfo.faultActionCount > 0) {
|
||||
faultInfo.faultActionList.forEach { actionCode ->
|
||||
//获取建议操作级别,得到建议操作级别最高的操作
|
||||
if (MsgFmData.FaultAction.getFaultLevel(actionCode) < curFaultLevel) {
|
||||
curFaultLevel =
|
||||
MsgFmData.FaultAction.getFaultLevel(actionCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//P0级消息弹出时需要判断驾驶状态,非自动驾驶、非平行驾驶状态不弹出,其余状态弹出
|
||||
if (curFaultLevel == 0) {
|
||||
//自动驾驶状态 0是不可用 1是ready 2是自动驾驶中 7:平行驾驶中
|
||||
if (CallerAutoPilotStatusListenerManager.getState() == 2
|
||||
|| CallerAutoPilotStatusListenerManager.getState() == 7
|
||||
) {
|
||||
// 6.6.0 ,因为 FSM 模块也会弹修改为只有没有 FSM 模块才弹
|
||||
// 6.6.0 ,20240823 考虑到 FSM 初期消息不一定全,先不加限制,产品先观察功能后再考虑是否过滤
|
||||
// if (hasNoneFSMNode()) {
|
||||
//语音提示
|
||||
try {
|
||||
SoundPoolUtils.getSoundPool()
|
||||
.playSoundWithRedId(context, R.raw.weak_net_tips)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
//展示消息
|
||||
when(MsgFmData.getFmPolicyLevel(fmInfoMsg.policyCode)){
|
||||
//一级
|
||||
MsgFmData.LEVEL_ONE->{
|
||||
//接管图像提示、语音提示
|
||||
CallerDevaToolsManager.takeOver(TAKE_OVER_REQUEST)
|
||||
CallerHmiManager.warningV2X(
|
||||
EventTypeEnumNew.TAKE_OVER_EVENT.poiType,
|
||||
EventTypeEnumNew.TAKE_OVER_EVENT.content,
|
||||
"识别车辆故障,建议立即接管安全停车,查看操作建议",
|
||||
object : IMoGoWarningStatusListener {
|
||||
override fun onShow() {
|
||||
CallerTakeOverManager.invokeTakeOverEvent(true)
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
CallerTakeOverManager.invokeTakeOverEvent(false)
|
||||
}
|
||||
},expireTime =3000L, isFromObu = false
|
||||
)
|
||||
//展示消息盒子消息
|
||||
showData(msgBoxBean)
|
||||
//}
|
||||
}
|
||||
//二级
|
||||
MsgFmData.LEVEL_TWO->{
|
||||
//语音提示
|
||||
AIAssist.getInstance(context).speakTTSVoice("识别车辆异常,建议尽快安全停车,查看操作建议")
|
||||
//展示消息盒子消息
|
||||
showData(msgBoxBean)
|
||||
}
|
||||
//三级
|
||||
MsgFmData.LEVEL_THREE->{
|
||||
//在消息盒子图标上,可查看到红点标记,无其他元素特殊提醒;点进消息盒子可查看到详细信息
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (msgBoxBean.sourceType == DataSourceType.SUMMARY) {
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
package com.mogo.eagle.core.function.hmi.ui.setting;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class ScreenUtilsTest {
|
||||
|
||||
/**
|
||||
* 获取当前屏幕截图,包含状态栏
|
||||
*
|
||||
* @param activity activity
|
||||
* @return Bitmap
|
||||
*/
|
||||
public static Bitmap captureWithStatusBar(Activity activity) {
|
||||
View view = activity.getWindow().getDecorView();
|
||||
view.setDrawingCacheEnabled(true);
|
||||
view.buildDrawingCache();
|
||||
Bitmap bmp = view.getDrawingCache();
|
||||
int width = getScreenWidth(activity);
|
||||
int height = getScreenHeight(activity);
|
||||
Bitmap ret = Bitmap.createBitmap(bmp, 0, 0, width, height);
|
||||
view.destroyDrawingCache();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前屏幕截图,不包含状态栏
|
||||
*
|
||||
* @param activity activity
|
||||
* @return Bitmap
|
||||
*/
|
||||
public static Bitmap captureWithoutStatusBar(Activity activity) {
|
||||
View view = activity.getWindow().getDecorView();
|
||||
view.setDrawingCacheEnabled(true);
|
||||
view.buildDrawingCache();
|
||||
Bitmap bmp = view.getDrawingCache();
|
||||
int statusBarHeight = getStatusBarHeight(activity);
|
||||
int width = getScreenWidth(activity);
|
||||
int height = getScreenHeight(activity);
|
||||
Bitmap ret = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight);
|
||||
view.destroyDrawingCache();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到屏幕的高
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static int getScreenHeight(Context context) {
|
||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
int height = wm.getDefaultDisplay().getHeight();
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到屏幕的宽
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static int getScreenWidth(Context context) {
|
||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
int width = wm.getDefaultDisplay().getWidth();
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态栏高度
|
||||
*
|
||||
* @param context 上下文
|
||||
* @return 状态栏高度
|
||||
*/
|
||||
public static int getStatusBarHeight(Context context) {
|
||||
int result = 0;
|
||||
int resourceId = context.getResources()
|
||||
.getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = context.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static Bitmap mergeBitmaps(Bitmap background, Bitmap foreground) {
|
||||
// 创建一个新的Bitmap,大小为两个Bitmap的最大宽度和最大高度
|
||||
int width = Math.max(background.getWidth(), foreground.getWidth());
|
||||
int height = Math.max(background.getHeight(), foreground.getHeight());
|
||||
Bitmap mergedBitmap = Bitmap.createBitmap(width, height, background.getConfig());
|
||||
|
||||
Canvas canvas = new Canvas(mergedBitmap);
|
||||
// 绘制背景图
|
||||
canvas.drawBitmap(background, 0, 0, null);
|
||||
// 绘制前景图,可以调整位置
|
||||
canvas.drawBitmap(foreground, 0, 0, null); // 根据需要调整位置
|
||||
|
||||
return mergedBitmap;
|
||||
}
|
||||
|
||||
|
||||
public static Bitmap overlayBitmaps(Bitmap bitmap1, Bitmap bitmap2, int xOffset, int yOffset) {
|
||||
// 创建一个新的Bitmap,其大小足以容纳两个重叠的bitmap
|
||||
int width = Math.max(bitmap1.getWidth(), bitmap2.getWidth());
|
||||
int height = bitmap1.getHeight() + bitmap2.getHeight(); // 假定重叠在垂直方向
|
||||
Bitmap result = Bitmap.createBitmap(width, height, bitmap1.getConfig());
|
||||
|
||||
// 使用Canvas绘制bitmap1和bitmap2
|
||||
Canvas canvas = new Canvas(result);
|
||||
canvas.drawBitmap(bitmap1, 0, 0, null); // 首先绘制bitmap1
|
||||
canvas.drawBitmap(bitmap2, xOffset, bitmap1.getHeight() + yOffset, null); // 然后绘制bitmap2,根据需要调整xOffset和yOffset
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将2张图片合成
|
||||
* @param downBitmap 底部图片
|
||||
* @param upBitmap 置顶的图片
|
||||
* @return
|
||||
*/
|
||||
public static Bitmap compoundBitmap(Bitmap downBitmap,Bitmap upBitmap)
|
||||
{
|
||||
Bitmap mBitmap = downBitmap.copy(Bitmap.Config.ARGB_8888, true);
|
||||
//如果遇到黑色,则显示downBitmap里面的颜色值,如果不是则显示upBitmap里面的颜色值
|
||||
//循环获得bitmap所有像素点
|
||||
int mBitmapWidth = mBitmap.getWidth();
|
||||
int mBitmapHeight = mBitmap.getHeight();
|
||||
//首先保证downBitmap和 upBitmap是一致的高宽大小
|
||||
Log.i("xuxinchao","mBitmapWidth="+mBitmapWidth);
|
||||
Log.i("xuxinchao","mBitmapHeight="+mBitmapHeight);
|
||||
Log.i("xuxinchao","upBitmap.getWidth()="+upBitmap.getWidth());
|
||||
Log.i("xuxinchao","upBitmap.getHeight()="+upBitmap.getHeight());
|
||||
// if(mBitmapWidth==upBitmap.getWidth() && mBitmapHeight==upBitmap.getHeight())
|
||||
// {
|
||||
// for (int i = 0; i < mBitmapHeight; i++) {
|
||||
// for (int j = 0; j < mBitmapWidth; j++) {
|
||||
// //获得Bitmap 图片中每一个点的color颜色值
|
||||
// //将需要填充的颜色值如果不是
|
||||
// //在这说明一下 如果color 是全透明 或者全黑 返回值为 0
|
||||
// //getPixel()不带透明通道 getPixel32()才带透明部分 所以全透明是0x00000000
|
||||
// //而不透明黑色是0xFF000000 如果不计算透明部分就都是0了
|
||||
// int color = upBitmap.getPixel(j, i);
|
||||
// Log.i("xuxinchao","color="+color);
|
||||
// //将颜色值存在一个数组中 方便后面修改
|
||||
// if (color != Color.BLACK) {
|
||||
// mBitmap.setPixel(j, i, upBitmap.getPixel(j, i)); //将白色替换成透明色
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
for (int i = 0; i < mBitmapHeight; i++) {
|
||||
for (int j = 0; j < mBitmapWidth; j++) {
|
||||
//获得Bitmap 图片中每一个点的color颜色值
|
||||
//将需要填充的颜色值如果不是
|
||||
//在这说明一下 如果color 是全透明 或者全黑 返回值为 0
|
||||
//getPixel()不带透明通道 getPixel32()才带透明部分 所以全透明是0x00000000
|
||||
//而不透明黑色是0xFF000000 如果不计算透明部分就都是0了
|
||||
int color = upBitmap.getPixel(j, i);
|
||||
Log.i("xuxinchao","color="+color);
|
||||
//将颜色值存在一个数组中 方便后面修改
|
||||
if (color != Color.BLACK) {
|
||||
mBitmap.setPixel(j, i, upBitmap.getPixel(j, i)); //将白色替换成透明色
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// downBitmap.recycle();
|
||||
// upBitmap.recycle();
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import com.zhjt.mogo_core_function_devatools.ota.OTAUpgradeConfig
|
||||
import kotlinx.android.synthetic.main.dialog_ota_upgrade.tvUpgradeContent
|
||||
import kotlinx.android.synthetic.main.dialog_ota_upgrade.tv_upgrade_later
|
||||
import kotlinx.android.synthetic.main.dialog_ota_upgrade.tv_upgrade_now
|
||||
import org.json.JSONObject
|
||||
import system_master.SsmInfo
|
||||
|
||||
/**
|
||||
@@ -40,22 +41,42 @@ class OTAUpgradeDialog(context: Context) :
|
||||
private fun initView(){
|
||||
//立即升级
|
||||
tv_upgrade_now.setOnClickListener {
|
||||
val result = CallerAutoPilotControlManager.sendSsmFuncOtaDownloadResponse(OTAUpgradeConfig.otaToken,SsmInfo.IfUpgrade.IMMEDIATELY)
|
||||
if(result){
|
||||
ToastUtils.showShort("立即升级命令发送成功")
|
||||
}else{
|
||||
ToastUtils.showShort("立即升级命令发送失败")
|
||||
}
|
||||
// val result = CallerAutoPilotControlManager.sendSsmFuncOtaDownloadResponse(OTAUpgradeConfig.otaToken,SsmInfo.IfUpgrade.IMMEDIATELY)
|
||||
// if(result){
|
||||
// ToastUtils.showShort("立即升级命令发送成功")
|
||||
// }else{
|
||||
// ToastUtils.showShort("立即升级命令发送失败")
|
||||
// }
|
||||
|
||||
val query = JSONObject()
|
||||
query.put("cmd","ASK_PAD_UPGRADE_RES")
|
||||
query.put("token",OTAUpgradeConfig.token)
|
||||
query.put("allow_upgrade",true)
|
||||
query.put("reason","")
|
||||
Log.i("xuxinchao",query.toString())
|
||||
CallerAutoPilotControlManager.sendOtaPadMsgQuery(query.toString())
|
||||
|
||||
|
||||
dismiss()
|
||||
}
|
||||
//稍后升级
|
||||
tv_upgrade_later.setOnClickListener {
|
||||
val delayResult = CallerAutoPilotControlManager.sendSsmFuncOtaDownloadResponse(OTAUpgradeConfig.otaToken,SsmInfo.IfUpgrade.DELAY)
|
||||
if(delayResult){
|
||||
ToastUtils.showShort("稍后升级命令发送成功")
|
||||
}else{
|
||||
ToastUtils.showShort("稍后升级命令发送失败")
|
||||
}
|
||||
// val delayResult = CallerAutoPilotControlManager.sendSsmFuncOtaDownloadResponse(OTAUpgradeConfig.otaToken,SsmInfo.IfUpgrade.DELAY)
|
||||
// if(delayResult){
|
||||
// ToastUtils.showShort("稍后升级命令发送成功")
|
||||
// }else{
|
||||
// ToastUtils.showShort("稍后升级命令发送失败")
|
||||
// }
|
||||
|
||||
//不允许OTA升级
|
||||
val query = JSONObject()
|
||||
query.put("cmd","ASK_PAD_UPGRADE_RES")
|
||||
query.put("token",OTAUpgradeConfig.token)
|
||||
query.put("allow_upgrade",false)
|
||||
query.put("reason","user click")
|
||||
Log.i("xuxinchao",query.toString())
|
||||
CallerAutoPilotControlManager.sendOtaPadMsgQuery(query.toString())
|
||||
|
||||
dismiss()
|
||||
}
|
||||
upgradeWaitingTimer = object: CountDownTimer(UPGRADE_WAITING_TIME,UPGRADE_WAITING_TIME){
|
||||
|
||||
@@ -762,6 +762,22 @@
|
||||
android:layout_height="1dp"
|
||||
android:background="#F0F0F0" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivScreenTest"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="600dp"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivScreenTestTwo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="600dp"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivScreenTestThree"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="600dp"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ rootProject.gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
|
||||
def packageTask = (PackageApplication) t2
|
||||
def outDir = packageTask.outputDirectory
|
||||
def apkNames = packageTask.apkNames
|
||||
if (apkNames != null && apkNames.size() > 0) {
|
||||
if (false) {
|
||||
apkNames.forEach { apkName ->
|
||||
def apk = new File(outDir, apkName)
|
||||
def lp = new File(rootProject.rootDir, "local.properties")
|
||||
|
||||
Reference in New Issue
Block a user