From 4a2d17fd0dd8e15481e988c760394a06e7c7244c Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Sat, 16 Jul 2022 18:48:25 +0800 Subject: [PATCH 01/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 完善逻辑 --- .../badcase/BadCaseManager.kt | 43 ++- .../badcase/biz/AIDataCollectWindow.kt | 81 ++++-- .../badcase/biz/InitiativeBadCaseWindow.kt | 249 ++++++++++++++++-- .../badcase/consts/BadCaseConfig.kt | 3 + .../badcase/consts/BadCaseHost.kt | 4 +- .../res/layout/view_initiative_bad_case.xml | 79 +++--- .../function/hmi/ui/widget/VersionNameView.kt | 3 + 7 files changed, 367 insertions(+), 95 deletions(-) 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 92769bd875..9fc80c2aad 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 @@ -23,8 +23,10 @@ import com.mogo.eagle.core.utilcode.reminder.Reminder import com.mogo.eagle.core.utilcode.reminder.api.IReminder import com.mogo.eagle.core.utilcode.reminder.api.IReminder.IGlobalStateChangeListener import com.mogo.eagle.core.utilcode.util.ClickUtils +import com.mogo.eagle.core.utilcode.util.NetworkUtils import com.mogo.eagle.core.utilcode.util.ToastUtils import com.zhjt.mogo_core_function_devatools.badcase.biz.* +import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig 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.ext.enqueuePop @@ -104,14 +106,21 @@ internal object BadCaseManager : LifecycleEventObserver { val activity = view.context as? FragmentActivity ?: throw IllegalStateException("please ensure context is FragmentActivity.") view.setOnClickListener { if(ClickUtils.isFastClick()){ - val initiativeBadCaseWindow = InitiativeBadCaseWindow(activity) - initiativeBadCaseWindow.setClickListener(object: InitiativeBadCaseWindow.ClickListener{ - override fun closeWindow() { - initiativeBadCaseWindow.hideFloatWindow() + if(NetworkUtils.isConnected()){ + if(BadCaseConfig.dockerVersion!=null){ + val initiativeBadCaseWindow = InitiativeBadCaseWindow(activity) + initiativeBadCaseWindow.setClickListener(object: InitiativeBadCaseWindow.ClickListener{ + override fun closeWindow() { + initiativeBadCaseWindow.hideFloatWindow() + } + }) + initiativeBadCaseWindow.showFloatWindow() + }else{ + ToastUtils.showShort("工控机连接状态异常") } - - }) - initiativeBadCaseWindow.showFloatWindow() + }else{ + ToastUtils.showShort("网络异常,请检查网络") + } }else{ ToastUtils.showShort("请勿连续点击,稍后再试") } @@ -126,13 +135,21 @@ internal object BadCaseManager : LifecycleEventObserver { val activity = view.context as? FragmentActivity ?: throw IllegalStateException("please ensure context is FragmentActivity.") view.setOnClickListener { if(ClickUtils.isFastClick()){ - val aiDataCollectWindow = AIDataCollectWindow(activity) - aiDataCollectWindow.setClickListener(object: AIDataCollectWindow.ClickListener{ - override fun closeWindow() { - aiDataCollectWindow.hideFloatWindow() + if(NetworkUtils.isConnected()){ + if(BadCaseConfig.dockerVersion!=null){ + val aiDataCollectWindow = AIDataCollectWindow(activity) + aiDataCollectWindow.setClickListener(object: AIDataCollectWindow.ClickListener{ + override fun closeWindow() { + aiDataCollectWindow.hideFloatWindow() + } + }) + aiDataCollectWindow.showFloatWindow() + }else{ + ToastUtils.showShort("工控机连接状态异常") } - }) - aiDataCollectWindow.showFloatWindow() + }else{ + ToastUtils.showShort("网络异常,请检查网络") + } }else{ ToastUtils.showShort("请勿连续点击,稍后再试") } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt index e727dc9cfb..06ffc73757 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt @@ -5,15 +5,21 @@ import android.app.Activity import android.graphics.PixelFormat import android.os.SystemClock import android.util.DisplayMetrics +import android.util.Log import android.view.* import android.widget.RadioButton import android.widget.TextView import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.data.app.AppConfigInfo +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotCarStateListener import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA import com.mogo.eagle.core.utilcode.mogo.toast.TipToast +import com.mogo.eagle.core.utilcode.util.AppUtils import com.mogo.eagle.core.utilcode.util.TimeUtils import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.zhjt.mogo_core_function_devatools.R @@ -21,6 +27,7 @@ import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig import com.zhjt.mogo_core_function_devatools.badcase.toRecord import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import mogo.telematics.pad.MessagePad import record_cache.RecordPanelOuterClass import java.lang.reflect.Field import java.util.* @@ -31,7 +38,7 @@ import java.util.* * @since: 2022/7/12 */ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener, - IMoGoAutopilotRecordListener { + IMoGoAutopilotRecordListener , IMoGoAutopilotCarStateListener { companion object { const val TAG = "AIDataCollectWindow" @@ -56,6 +63,10 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener private lateinit var tvCollectCancel: TextView //取消按钮 private var collectReason: String = "大型车:大货、大巴、特种车辆" + private var recordKey: String?=null //录制bag包key + private var recordFileName: String?=null //录制文件包名 + private var longitude: Double?=null + private var latitude: Double?=null private lateinit var mFloatLayout: View private var mInViewX = 0f @@ -96,14 +107,17 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener tvCollectNum.text = BadCaseConfig.windowNum.toString() BadCaseConfig.windowNum++ tvCollectTime.text ="时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" - + //采集结果回调监听 + CallerAutopilotRecordListenerManager.addListener(TAG,this) + // 添加 ADAS车辆状态&定位 监听 + CallerAutopilotCarStatusListenerManager.addListener(TAG, this) + //开始录制AI数据采集Bag包 CallerAutoPilotManager.recordPackage( 99, Random(SystemClock.elapsedRealtime()).nextInt(), 20, 12 ) - //大型车 rbLargeCar.setOnClickListener{ setRadioButtonStatus( @@ -200,26 +214,28 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener tvCollectReport.setOnClickListener { GlobalScope.launch{ val uploadResult = presenter.upload(mutableMapOf().also { itx -> - itx["carLicense"] = "DFD02313" - itx["filename"] = "/home/mogo/data/bags/badcase/20220706145143/20220706145143-265939904-rosmaster-XXXX000000.bag" - itx["filesize"] = "0" - itx["key"] = "265939904" - itx["reason"] = collectReason - itx["duration"] = "16" - itx["startTime"] = "20220706145203" - itx["channel"] = "AI" - itx["carSn"] = MoGoAiCloudClientConfig.getInstance().sn - itx["userRole"] = "安全员" - itx["audioUrl"] = "http://petchfile-1255510688.cos.ap-beijing.myqcloud.com/CarPad/mogopadlog/deviceId/2022-07-07/AUDIO_myTest.wav" - itx["mapVersion"] = "MAP-taxi-hq_RoboTaxi_hq_H9_2.3.0.5_20220410" - itx["eyeVersion"] = "2.8.0" - itx["coordinate"] = "" + itx["carLicense"] = AppConfigInfo.plateNumber?:"" //车牌号 + itx["filename"] = recordFileName?:"" //bag包文件地址 + itx["filesize"] = "0" //bag包文件大小 + itx["key"] = recordKey?:"" //key + itx["reason"] = collectReason //采集原因 + itx["duration"] = "20" //采集时长,固定为20S + itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) + itx["channel"] = "AI" //渠道 + itx["carSn"] = MoGoAiCloudClientConfig.getInstance().sn //SN + itx["userRole"] = "" //采集者角色 + itx["audioUrl"] = "" //音频COS地址 + itx["mapVersion"] = BadCaseConfig.dockerVersion ?:"" //工控机版本 + itx["eyeVersion"] = AppUtils.getAppVersionName() //鹰眼版本 + itx["coordinate"] = "latitude:${latitude};longitude:${longitude}" //坐标 }) if (uploadResult == null || uploadResult.code != 200) { TipToast.shortTip("上报失败") } else { TipToast.shortTip("上报成功") + BadCaseConfig.windowNum-- + clickListener?.closeWindow() } } @@ -241,17 +257,24 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener it.gravity = Gravity.START or Gravity.TOP it.width = 924 it.height = 668 - it.alpha = 0.9f + it.alpha = 1.0f } } + + override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") - when(recordPanel.toRecord().stat){ + if(recordKey==null){ + recordKey = recordPanel.key.toString() + } + if(recordFileName==null){ + recordFileName = recordPanel.filename + } + when(recordPanel.stat){ 100, 101 ->{ //成功结束录制 - TipToast.shortTip("bag录制成功") - + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制成功") } 300 ->{ //开始录制 @@ -259,7 +282,7 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener } 200 ->{ //录制失败 - TipToast.shortTip("bag录制失败") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制失败") } } } @@ -296,9 +319,6 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener // 手指移动的时候更新小悬浮窗的位置 mWindowManager!!.updateViewLayout(mFloatLayout, mWindowParams) } -// MotionEvent.ACTION_UP -> // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 -// if (mDownInScreenX === mInScreenX && mDownInScreenY === mInScreenY) { -// } } return true } @@ -309,12 +329,16 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener // 默认固定位置,靠屏幕右边缘的中间 mWindowManager!!.defaultDisplay.getMetrics(metrics) mWindowParams!!.x = metrics.widthPixels - mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity) + mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity)-350 mWindowManager!!.addView(mFloatLayout, mWindowParams) } } fun hideFloatWindow() { + //注销采集结果回调监听 + CallerAutopilotRecordListenerManager.removeListener(TAG) + // 移除 ADAS车辆状态&定位 监听 + CallerAutopilotCarStatusListenerManager.removeListener(TAG) if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout) } @@ -345,4 +369,9 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener fun closeWindow() } + override fun onAutopilotCarStateData(gnssInfo: MessagePad.GnssInfo?) { + latitude = gnssInfo?.latitude + longitude = gnssInfo?.longitude + } + } \ 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/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index 060208d2b6..b3f2953df8 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -3,25 +3,52 @@ package com.zhjt.mogo_core_function_devatools.badcase.biz import android.annotation.SuppressLint import android.app.Activity import android.graphics.PixelFormat +import android.os.CountDownTimer +import android.os.Handler import android.os.SystemClock import android.util.DisplayMetrics import android.view.* +import android.widget.CheckBox import android.widget.TextView +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.data.app.AppConfigInfo +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotCarStateListener +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA +import com.mogo.eagle.core.utilcode.mogo.toast.TipToast +import com.mogo.eagle.core.utilcode.util.AppUtils import com.mogo.eagle.core.utilcode.util.TimeUtils import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String +import com.zhidao.loglib.call.LogInfoManagerFactory +import com.zhidao.loglib.upload.OnUploadListener import com.zhjt.mogo_core_function_devatools.R import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig import com.zhjt.mogo_core_function_devatools.badcase.record.RecordManager +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import mogo.telematics.pad.MessagePad +import record_cache.RecordPanelOuterClass +import java.io.File +import java.lang.StringBuilder import java.lang.reflect.Field import java.util.* + /** * @author XuXinChao * @description BadCase主动录包 * @since: 2022/7/13 */ -class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchListener{ +class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchListener, + IMoGoAutopilotRecordListener, IMoGoAutopilotCarStateListener { + + companion object { + const val TAG = "InitiativeBadCaseWindow" + } private var mActivity: Activity = activity private var mWindowParams: WindowManager.LayoutParams? = null @@ -33,12 +60,27 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList private lateinit var tvInitiativeTime: TextView private lateinit var tvInitiativeIdentity: TextView + private lateinit var rbOne: CheckBox + private lateinit var rbTwo: CheckBox + private lateinit var rbThree: CheckBox + private lateinit var rbFour: CheckBox + private lateinit var rbFive: CheckBox + private lateinit var rbSix: CheckBox + private lateinit var viewAudioButton: View + private lateinit var tvAudioCountDown: TextView private lateinit var tvInitiativeReport: TextView private lateinit var tvInitiativeCancel: TextView private var audioStatus = false + private var audioFileName:String?=null //录音文件名称 + + private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签 + private var recordKey: String?=null //录制bag包key + private var recordFileName: String?=null //录制文件包名 + private var longitude: Double?=null + private var latitude: Double?=null private var mInViewX = 0f private var mInViewY = 0f @@ -66,7 +108,15 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList tvInitiativeTime = mFloatLayout.findViewById(R.id.tvInitiativeTime) tvInitiativeIdentity = mFloatLayout.findViewById(R.id.tvInitiativeIdentity) + rbOne = mFloatLayout.findViewById(R.id.rbOne) + rbTwo = mFloatLayout.findViewById(R.id.rbTwo) + rbThree = mFloatLayout.findViewById(R.id.rbThree) + rbFour = mFloatLayout.findViewById(R.id.rbFour) + rbFive = mFloatLayout.findViewById(R.id.rbFive) + rbSix = mFloatLayout.findViewById(R.id.rbSix) + viewAudioButton = mFloatLayout.findViewById(R.id.viewAudioButton) + tvAudioCountDown = mFloatLayout.findViewById(R.id.tvAudioCountDown) tvInitiativeReport = mFloatLayout.findViewById(R.id.tvInitiativeReport) tvInitiativeCancel = mFloatLayout.findViewById(R.id.tvInitiativeCancel) @@ -76,25 +126,59 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList tvInitiativeTime.text = "时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" tvInitiativeIdentity.text = "身份:${BadCaseConfig.identity}" - viewAudioButton.setOnClickListener { - audioStatus = !audioStatus - if(audioStatus){ - viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_select) - //开始录音 - RecordManager.getInstance().start("audio_test") - }else{ - viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_normal) - //结束录音 - RecordManager.getInstance().stop() - } - } - - tvInitiativeReport.setOnClickListener { - CallerAutoPilotManager.recordPackage(BadCaseConfig.type, + //采集结果回调监听 + CallerAutopilotRecordListenerManager.addListener(TAG,this) + // 添加 ADAS车辆状态&定位 监听 + CallerAutopilotCarStatusListenerManager.addListener(TAG, this) + //开启录包 + CallerAutoPilotManager.recordPackage(BadCaseConfig.type, Random(SystemClock.elapsedRealtime()).nextInt(), BadCaseConfig.totalDuration, BadCaseConfig.previousDuration ) + + viewAudioButton.setOnClickListener { + audioStatus = !audioStatus + setAudio(audioStatus) + } + + tvInitiativeReport.setOnClickListener { + if(!rbOne.isChecked && !rbTwo.isChecked && !rbThree.isChecked && + !rbFour.isChecked && !rbFive.isChecked && !rbSix.isChecked){ + TipToast.shortTip("请选择至少一个Case") + return@setOnClickListener + } + if(rbOne.isChecked){ + uploadReason.append("严重画龙 ") + } + if(rbTwo.isChecked){ + uploadReason.append("速度过慢 ") + } + if(rbThree.isChecked){ + uploadReason.append("感知、定位、地图等其他 ") + } + if(rbFour.isChecked){ + uploadReason.append("速度过快 ") + } + if(rbFive.isChecked){ + uploadReason.append("存在碰撞风险 ") + } + if(rbSix.isChecked){ + uploadReason.append("点刹、顿挫") + } + //点击上报时,如果没有停止录音则先停止录音 + //TODO 未结束录音,点击上报,未能上传语音成功 + if(audioStatus){ + audioStatus = !audioStatus + setAudio(audioStatus) + Handler().postDelayed({ + uploadAudio() + },1000) + }else{ + uploadAudio() + } + + } tvInitiativeCancel.setOnClickListener { BadCaseConfig.windowNum-- @@ -110,7 +194,100 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList it.gravity = Gravity.START or Gravity.TOP it.width = 924 it.height = 668 - it.alpha = 0.9f + it.alpha = 1.0f + } + } + + var countDownTimer: CountDownTimer?=null + + private fun setAudio(status: Boolean){ + if(status){ + //开始录音 + audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" + RecordManager.getInstance().start(audioFileName) + //更改录音按钮背景 + viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_select) + tvAudioCountDown.visibility = View.VISIBLE + //开始倒计时 + if(countDownTimer==null){ + countDownTimer = object : CountDownTimer(60000, 1000) { + + override fun onTick(millisUntilFinished: Long) { + tvAudioCountDown.text = "${millisUntilFinished/1000}S" + } + + override fun onFinish() { + tvAudioCountDown.visibility = View.GONE + //结束录音 + RecordManager.getInstance().stop() + //更改录音按钮背景 + viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_normal) + } + } + countDownTimer?.start() + } + }else{ + //结束倒计时 + countDownTimer?.cancel() + countDownTimer?.onFinish() + //将倒计时置空 + countDownTimer = null + } + + } + + private fun uploadAudio(){ + val singlePath = "/mnt/sdcard/mogo/DataCollection/${audioFileName}.wav" + val file = File(singlePath) + if(file.exists()){ + LogInfoManagerFactory.createAudioUpload(mActivity,"Audio",singlePath, + object : OnUploadListener { + override fun onUploadSuccess(filePath: String, downloadUrl: String) { + CallerLogger.d("$M_DEVA$TAG", "语音文件上传成功:downloadUrl=$downloadUrl") + //上传到服务器 + upload(downloadUrl) + } + + override fun onUploadFail(filePath: String) { + TipToast.shortTip("上传语音文件失败") + } + }) + }else{ + //上传到服务器 + upload(null) + } + } + + /** + * 将记录上传到服务器 + * @param downloadUrl 语音文件下载地址 + */ + private fun upload(downloadUrl: String?){ + GlobalScope.launch{ + val uploadResult = presenter.upload(mutableMapOf().also { itx -> + itx["carLicense"] = AppConfigInfo.plateNumber?:"" //车牌号 + itx["filename"] = recordFileName?:"" //bag包文件地址 + itx["filesize"] = "0" //bag包文件大小 + itx["key"] = recordKey?:"" //key + itx["reason"] = uploadReason.toString()?:"" //采集原因 + itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长,固定为20S + itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) + itx["channel"] = "1" //渠道 + itx["carSn"] = MoGoAiCloudClientConfig.getInstance().sn //SN + itx["userRole"] = BadCaseConfig.identity //采集者角色 + itx["audioUrl"] = downloadUrl?:"" //音频COS地址 + itx["mapVersion"] = BadCaseConfig.dockerVersion ?:"" //工控机版本 + itx["eyeVersion"] = AppUtils.getAppVersionName() //鹰眼版本 + itx["coordinate"] = "latitude:${latitude};longitude:${longitude}" //坐标 + + }) + if (uploadResult == null || uploadResult.code != 200) { + TipToast.shortTip("上报失败") + } else { + TipToast.shortTip("上报成功") + BadCaseConfig.windowNum-- + clickListener?.closeWindow() + } } } @@ -135,9 +312,6 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList // 手指移动的时候更新小悬浮窗的位置 mWindowManager!!.updateViewLayout(mFloatLayout, mWindowParams) } -// MotionEvent.ACTION_UP -> // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 -// if (mDownInScreenX === mInScreenX && mDownInScreenY === mInScreenY) { -// } } return true } @@ -148,12 +322,16 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList // 默认固定位置,靠屏幕右边缘的中间 mWindowManager!!.defaultDisplay.getMetrics(metrics) mWindowParams!!.x = metrics.widthPixels - mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity) + mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity)-350 mWindowManager!!.addView(mFloatLayout, mWindowParams) } } fun hideFloatWindow() { + //注销采集结果回调监听 + CallerAutopilotRecordListenerManager.removeListener(TAG) + // 移除 ADAS车辆状态&定位 监听 + CallerAutopilotCarStatusListenerManager.removeListener(TAG) if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout) } @@ -176,6 +354,30 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList return sbar } + override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { + CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") + if(recordKey==null){ + recordKey = recordPanel.key.toString() + } + if(recordFileName==null){ + recordFileName = recordPanel.filename + } + when(recordPanel.stat){ + 100, 101 ->{ + //成功结束录制 + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制成功") + } + 300 ->{ + //开始录制 + + } + 200 ->{ + //录制失败 + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制失败") + } + } + } + fun setClickListener(clickListener: ClickListener) { this.clickListener = clickListener } @@ -184,4 +386,9 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList fun closeWindow() } + override fun onAutopilotCarStateData(gnssInfo: MessagePad.GnssInfo?) { + latitude = gnssInfo?.latitude + longitude = gnssInfo?.longitude + } + } \ 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/consts/BadCaseConfig.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt index 004d7906e1..b6406f34b1 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt @@ -24,5 +24,8 @@ object BadCaseConfig { //BadCase采集和AI数据采集弹窗数量 @JvmField var windowNum = 1 + //工控机版本 + @JvmField + var dockerVersion:String ?= null } \ 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/consts/BadCaseHost.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseHost.kt index f3ce82af0a..241b3d941e 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseHost.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseHost.kt @@ -4,8 +4,8 @@ import com.mogo.commons.debug.DebugConfig internal object BadCaseHost { - private const val HOST_DEV = "http://dzt.zhidaozhixing.com/" - private const val HOST_RELEASE = "https://dzt-test.zhidaozhixing.com/" + private const val HOST_DEV = "http://dzt-test.zhidaozhixing.com/" + private const val HOST_RELEASE = "http://dzt.zhidaozhixing.com/" fun getHost(): String{ return when (DebugConfig.getNetMode()) { diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml index 6350e416c8..b75e0934f0 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml @@ -52,7 +52,7 @@ android:layout_marginEnd="@dimen/dp_50" /> - - - - + + - - - + + \ 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/VersionNameView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/VersionNameView.kt index 011782035c..12ff7aa0bc 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/VersionNameView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/VersionNameView.kt @@ -13,6 +13,7 @@ import com.mogo.eagle.core.function.hmi.R import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils import com.mogo.eagle.core.utilcode.util.AppUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig import kotlinx.android.synthetic.main.view_version_name.view.* /** @@ -88,6 +89,8 @@ class VersionNameView @JvmOverloads constructor( override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { dockerVersion = autoPilotStatusInfo.dockVersion showCurrentMapVersion() + //将工控机版本赋值给BadCase配置常量 + BadCaseConfig.dockerVersion = autoPilotStatusInfo.dockVersion } } \ No newline at end of file From b1083563151ae8790c24eaf526e479027e3281c8 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Mon, 18 Jul 2022 09:41:32 +0800 Subject: [PATCH 02/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加被动录包 --- .../DevaToolsProvider.kt | 5 +- .../badcase/BadCaseManager.kt | 48 +-- .../badcase/biz/InitiativeBadCaseWindow.kt | 3 +- .../badcase/biz/PassiveBadCaseWindow.kt | 374 ++++++++++++++++++ .../main/res/layout/view_passive_bad_case.xml | 153 +++++++ .../core/function/hmi/ui/MoGoHmiFragment.kt | 4 +- .../api/devatools/IDevaToolsProvider.kt | 3 +- .../call/devatools/CallerDevaToolsManager.kt | 5 +- 8 files changed, 552 insertions(+), 43 deletions(-) create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_passive_bad_case.xml 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 92d3962a96..12e2e97303 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 @@ -1,6 +1,7 @@ package com.zhjt.mogo_core_function_devatools import android.annotation.SuppressLint +import android.app.Activity import android.content.Context import android.view.View import com.alibaba.android.arouter.facade.annotation.Route @@ -86,8 +87,8 @@ class DevaToolsProvider : IDevaToolsProvider { BadCaseManager.initAiCollect(view) } - override fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel) { - BadCaseManager.onReceiveBadCaseRecord(record) + override fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel,activity: Activity) { + BadCaseManager.onReceiveBadCaseRecord(record,activity) } override fun showFeedbackWindow(ctx: Context) { 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 9fc80c2aad..adad4f9121 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 @@ -1,6 +1,7 @@ package com.zhjt.mogo_core_function_devatools.badcase +import android.app.Activity import android.content.Context import android.view.View import android.view.WindowManager @@ -58,9 +59,6 @@ internal object BadCaseManager : LifecycleEventObserver { @Volatile private var dismissJob: Job? = null - @Volatile - private var feedbackFloatShow = false - @OptIn(ExperimentalCoroutinesApi::class) private var channel: Channel = Channel(Channel.RENDEZVOUS) get() = if (field.isClosedForReceive || field.isClosedForSend) { @@ -236,17 +234,20 @@ internal object BadCaseManager : LifecycleEventObserver { return oldT == 0L || newT == 0L || (newT - oldT >= 0 && (newT - oldT) < CASE_EXPIRE_DURATION) } - fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel) { - if (feedbackFloatShow) { + fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel,activity: Activity) { + if(BadCaseConfig.windowNum>1){ return } - scope?.launch { - val newRecord = record.toRecord() - withContext(Dispatchers.IO) { - presenter.insertRecord(newRecord) - channel.send(newRecord) + val passiveBadCaseWindow = PassiveBadCaseWindow(activity) + passiveBadCaseWindow.setRecord(record.key.toString(),record.filename) + passiveBadCaseWindow.setClickListener(object: PassiveBadCaseWindow.ClickListener{ + override fun closeWindow() { + passiveBadCaseWindow.hideFloatWindow() } - } + + }) + passiveBadCaseWindow.showFloatWindow() + } private fun CoroutineScope.showBadCaseInternal(record: AutoPilotRecord) = launch { @@ -311,31 +312,10 @@ internal object BadCaseManager : LifecycleEventObserver { } } - - private val listener = object : IGlobalStateChangeListener { - override fun onShow(reminder: IReminder) { - if (reminder.key().startsWith("FeedBackFloatWindow_")) { - feedbackFloatShow = true - } - } - - override fun onHide(reminder: IReminder) { - if (reminder.key().startsWith("FeedBackFloatWindow_")) { - feedbackFloatShow = false - } - } - } - override fun onStateChanged(source: LifecycleOwner, event: Event) { - if (event == ON_CREATE) { - Reminder.registerGlobalStateChangeListener(listener) - } - if (event == ON_DESTROY) { - Reminder.unRegisterGlobalStateChangeListener(listener) - dismissJob?.takeIf { it.isActive }?.cancel() - hideFloat = null - } + } + } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index b3f2953df8..e8f7b46347 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -177,9 +177,8 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList }else{ uploadAudio() } - - } + tvInitiativeCancel.setOnClickListener { BadCaseConfig.windowNum-- clickListener?.closeWindow() diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt new file mode 100644 index 0000000000..55175223d4 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -0,0 +1,374 @@ +package com.zhjt.mogo_core_function_devatools.badcase.biz + +import android.annotation.SuppressLint +import android.app.Activity +import android.graphics.Color +import android.graphics.PixelFormat +import android.os.CountDownTimer +import android.os.Handler +import android.util.DisplayMetrics +import android.util.Log +import android.view.* +import android.widget.CheckBox +import android.widget.CompoundButton +import android.widget.TextView +import com.google.android.flexbox.FlexboxLayout +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.data.app.AppConfigInfo +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotCarStateListener +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarStatusListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA +import com.mogo.eagle.core.utilcode.mogo.toast.TipToast +import com.mogo.eagle.core.utilcode.util.AppUtils +import com.mogo.eagle.core.utilcode.util.SizeUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.eagle.core.utilcode.util.TimeUtils +import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String +import com.zhidao.loglib.call.LogInfoManagerFactory +import com.zhidao.loglib.upload.OnUploadListener +import com.zhjt.mogo_core_function_devatools.R +import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig +import com.zhjt.mogo_core_function_devatools.badcase.record.RecordManager +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import mogo.telematics.pad.MessagePad +import record_cache.RecordPanelOuterClass +import java.io.File +import java.lang.reflect.Field + +/** + * @author XuXinChao + * @description BadCase被动录包 + * @since: 2022/7/17 + */ +class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListener, + IMoGoAutopilotCarStateListener, CompoundButton.OnCheckedChangeListener { + + companion object { + const val TAG = "PassiveBadCaseWindow" + } + + private var mActivity: Activity = activity + private var mWindowParams: WindowManager.LayoutParams? = null + private var mWindowManager: WindowManager? = null + private lateinit var mFloatLayout: View + + private var audioStatus = false + private var audioFileName:String?=null //录音文件名称 + + private var uploadReason: String = String() //上报原因,标签 + private var recordKey: String?=null //录制bag包key + private var recordFileName: String?=null //录制文件包名 + private var longitude: Double?=null + private var latitude: Double?=null + + private var mInViewX = 0f + private var mInViewY = 0f + private var mDownInScreenX = 0f + private var mDownInScreenY = 0f + private var mInScreenX = 0f + private var mInScreenY = 0f + + private var clickListener: ClickListener? = null + var countDownTimer: CountDownTimer?=null + + private lateinit var tvPassiveNum: TextView + private lateinit var tvPassiveTime: TextView + private lateinit var tvPassiveIdentity: TextView + + private lateinit var viewAudioButton: View + private lateinit var tvAudioCountDown: TextView + + private lateinit var tvPassiveReport: TextView + private lateinit var tvPassiveCancel: TextView + + private lateinit var flReasonLayout: FlexboxLayout + + init { + initFloatWindow(); + } + + private val presenter by lazy { + BadCasePresenter() + } + + @SuppressLint("SetTextI18n") + private fun initFloatWindow(){ + mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_passive_bad_case, null) as View + mFloatLayout.setOnTouchListener(this) + tvPassiveNum = mFloatLayout.findViewById(R.id.tvPassiveNum) + tvPassiveTime = mFloatLayout.findViewById(R.id.tvPassiveTime) + tvPassiveIdentity = mFloatLayout.findViewById(R.id.tvPassiveIdentity) + viewAudioButton = mFloatLayout.findViewById(R.id.viewAudioButton) + tvAudioCountDown = mFloatLayout.findViewById(R.id.tvAudioCountDown) + tvPassiveReport = mFloatLayout.findViewById(R.id.tvPassiveReport) + tvPassiveCancel = mFloatLayout.findViewById(R.id.tvPassiveCancel) + flReasonLayout = mFloatLayout.findViewById(R.id.flReasonLayout) + tvPassiveNum.text = BadCaseConfig.windowNum.toString() + BadCaseConfig.windowNum++ + tvPassiveTime.text = "时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" + tvPassiveIdentity.text = "身份:${BadCaseConfig.identity}" + // 添加 ADAS车辆状态&定位 监听 + CallerAutopilotCarStatusListenerManager.addListener(TAG, this) + viewAudioButton.setOnClickListener { + audioStatus = !audioStatus + setAudio(audioStatus) + } + + tvPassiveReport.setOnClickListener { + if(uploadReason.isEmpty()){ + TipToast.shortTip("请选择至少一个Case") + return@setOnClickListener + } + //点击上报时,如果没有停止录音则先停止录音 + //TODO 未结束录音,点击上报,未能上传语音成功 + if(audioStatus){ + audioStatus = !audioStatus + setAudio(audioStatus) + Handler().postDelayed({ + uploadAudio() + },1000) + }else{ + uploadAudio() + } + } + + tvPassiveCancel.setOnClickListener { + BadCaseConfig.windowNum-- + clickListener?.closeWindow() + } + + mWindowParams = WindowManager.LayoutParams() + mWindowManager = mActivity.windowManager + mWindowParams?.let { + it.format = PixelFormat.RGBA_8888 + it.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + it.gravity = Gravity.START or Gravity.TOP + it.width = 924 + it.height = 668 + it.alpha = 1.0f + } + } + + private fun setAudio(status: Boolean){ + if(status){ + //开始录音 + audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" + RecordManager.getInstance().start(audioFileName) + //更改录音按钮背景 + viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_select) + tvAudioCountDown.visibility = View.VISIBLE + //开始倒计时 + if(countDownTimer==null){ + countDownTimer = object : CountDownTimer(60000, 1000) { + + override fun onTick(millisUntilFinished: Long) { + tvAudioCountDown.text = "${millisUntilFinished/1000}S" + } + + override fun onFinish() { + tvAudioCountDown.visibility = View.GONE + //结束录音 + RecordManager.getInstance().stop() + //更改录音按钮背景 + viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_normal) + } + } + countDownTimer?.start() + } + }else{ + //结束倒计时 + countDownTimer?.cancel() + countDownTimer?.onFinish() + //将倒计时置空 + countDownTimer = null + } + + } + + private fun uploadAudio(){ + val singlePath = "/mnt/sdcard/mogo/DataCollection/${audioFileName}.wav" + val file = File(singlePath) + if(file.exists()){ + LogInfoManagerFactory.createAudioUpload(mActivity,"Audio",singlePath, + object : OnUploadListener { + override fun onUploadSuccess(filePath: String, downloadUrl: String) { + CallerLogger.d("$M_DEVA$TAG", "语音文件上传成功:downloadUrl=$downloadUrl") + //上传到服务器 + upload(downloadUrl) + } + + override fun onUploadFail(filePath: String) { + TipToast.shortTip("上传语音文件失败") + } + }) + }else{ + //上传到服务器 + upload(null) + } + } + + /** + * 将记录上传到服务器 + * @param downloadUrl 语音文件下载地址 + */ + private fun upload(downloadUrl: String?){ + GlobalScope.launch{ + val uploadResult = presenter.upload(mutableMapOf().also { itx -> + itx["carLicense"] = AppConfigInfo.plateNumber?:"" //车牌号 + itx["filename"] = recordFileName?:"" //bag包文件地址 + itx["filesize"] = "0" //bag包文件大小 + itx["key"] = recordKey?:"" //key + itx["reason"] = uploadReason //采集原因 + itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长,固定为20S + itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) + itx["channel"] = "1" //渠道 + itx["carSn"] = MoGoAiCloudClientConfig.getInstance().sn //SN + itx["userRole"] = BadCaseConfig.identity //采集者角色 + itx["audioUrl"] = downloadUrl?:"" //音频COS地址 + itx["mapVersion"] = BadCaseConfig.dockerVersion ?:"" //工控机版本 + itx["eyeVersion"] = AppUtils.getAppVersionName() //鹰眼版本 + itx["coordinate"] = "latitude:${latitude};longitude:${longitude}" //坐标 + + }) + if (uploadResult == null || uploadResult.code != 200) { + TipToast.shortTip("上报失败") + } else { + TipToast.shortTip("上报成功") + BadCaseConfig.windowNum-- + clickListener?.closeWindow() + } + } + } + + override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean { + when (motionEvent?.action) { + MotionEvent.ACTION_DOWN -> { + // 获取相对View的坐标,即以此View左上角为原点 + mInViewX = motionEvent.x + mInViewY = motionEvent.y + // 获取相对屏幕的坐标,即以屏幕左上角为原点 + mDownInScreenX = motionEvent.rawX + mDownInScreenY = motionEvent.rawY - getSysBarHeight(mActivity) + mInScreenX = motionEvent.rawX + mInScreenY = motionEvent.rawY - getSysBarHeight(mActivity) + } + MotionEvent.ACTION_MOVE -> { + // 更新浮动窗口位置参数 + mInScreenX = motionEvent.rawX + mInScreenY = motionEvent.rawY - getSysBarHeight(mActivity) + mWindowParams!!.x = (mInScreenX - mInViewX).toInt() + mWindowParams!!.y = (mInScreenY - mInViewY).toInt() + // 手指移动的时候更新小悬浮窗的位置 + mWindowManager!!.updateViewLayout(mFloatLayout, mWindowParams) + } + } + return true + } + + fun showFloatWindow() { + if (mFloatLayout.parent == null) { + val metrics = DisplayMetrics() + // 默认固定位置,靠屏幕右边缘的中间 + mWindowManager!!.defaultDisplay.getMetrics(metrics) + mWindowParams!!.x = metrics.widthPixels + mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity)-350 + mWindowManager!!.addView(mFloatLayout, mWindowParams) + } + + GlobalScope.launch{ + presenter.loadBadCases(true).also { + ThreadUtils.runOnUiThread { + it.iterator().forEach { + val checkBox = CheckBox(mActivity) + checkBox.setTextColor(Color.WHITE) + val lp = FlexboxLayout.LayoutParams(FlexboxLayout.LayoutParams.WRAP_CONTENT, + FlexboxLayout.LayoutParams.WRAP_CONTENT) +// lp.setMargins( +// SizeUtils.dp2px(0f), +// SizeUtils.dp2px(0f), +// SizeUtils.dp2px(0f), +// SizeUtils.dp2px(0f) +// ) + checkBox.buttonDrawable = mActivity.resources.getDrawable(R.drawable.badcase_radio_button_style) + checkBox.setPadding(SizeUtils.dp2px(12f), + SizeUtils.dp2px(5f), + SizeUtils.dp2px(10f), + SizeUtils.dp2px(5f)) + checkBox.textSize = SizeUtils.sp2px(9f).toFloat() + checkBox.text = it.reason + checkBox.isChecked = it.isChecked + checkBox.setOnCheckedChangeListener(this@PassiveBadCaseWindow) + flReasonLayout.addView(checkBox,lp) + } + } + + } + } + + } + + override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + Log.i("onCheckedChanged","buttonView"+buttonView) + Log.i("onCheckedChanged","isChecked"+isChecked) + buttonView?.text?.let { + if(isChecked){ + if(!uploadReason.contains(it)){ + uploadReason += it + } + }else{ + if(uploadReason.contains(it)){ + uploadReason.replace(it.toString(),"") + + } + } + } + } + + + fun hideFloatWindow() { + // 移除 ADAS车辆状态&定位 监听 + CallerAutopilotCarStatusListenerManager.removeListener(TAG) + if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout) + } + + // 获取系统状态栏高度 + private fun getSysBarHeight(activity: Activity): Int { + val c: Class<*> + val obj: Any + val field: Field + val x: Int + var sbar = 0 + try { + c = Class.forName("com.android.internal.R\$dimen") + obj = c.newInstance() + field = c.getField("status_bar_height") + x = field.get(obj).toString().toInt() + sbar = activity.resources.getDimensionPixelSize(x) + } catch (e1: Exception) { + e1.printStackTrace() + } + return sbar + } + + fun setRecord(key:String,fileName:String){ + recordKey = key + recordFileName = fileName + } + + fun setClickListener(clickListener: ClickListener) { + this.clickListener = clickListener + } + + interface ClickListener { + fun closeWindow() + } + + override fun onAutopilotCarStateData(gnssInfo: MessagePad.GnssInfo?) { + latitude = gnssInfo?.latitude + longitude = gnssInfo?.longitude + } + +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_passive_bad_case.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_passive_bad_case.xml new file mode 100644 index 0000000000..68d8cf4076 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_passive_bad_case.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index 9ae0e79cfe..fc9218c2e8 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -200,8 +200,8 @@ import kotlin.collections.ArrayList override fun getNotificationView(): IViewNotification? = context?.let { V2XNotificationView(it) } override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { - if (HmiBuildConfig.isShowBadCaseView && recordPanel.type == 1 && recordPanel.stat == 100) { - CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel) + if (recordPanel.type == 1 && recordPanel.stat == 100) { + activity?.let { CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel, it) } } if (recordPanel.type == 2 && ( recordPanel.stat == 101 || //工控机采集完成-被动完成 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 dcda0fc29b..b0ad55d157 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 @@ -1,5 +1,6 @@ package com.mogo.eagle.core.function.api.devatools +import android.app.Activity import android.content.Context import android.view.View import com.alibaba.android.arouter.facade.template.IProvider @@ -86,7 +87,7 @@ interface IDevaToolsProvider : IProvider { /** * 当工控机回调时调用 */ - fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel) + fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel,activity: Activity) /** * 展示录包配置 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 107485c74e..37ec5a70cc 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 @@ -1,5 +1,6 @@ package com.mogo.eagle.core.function.call.devatools +import android.app.Activity import android.content.Context import android.view.View import com.mogo.eagle.core.data.constants.MogoServicePaths @@ -119,8 +120,8 @@ object CallerDevaToolsManager { /** * 收到工控机回调时触发 */ - fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel) { - devaToolsProviderApi?.onReceiveBadCaseRecord(record) + fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel,activity: Activity) { + devaToolsProviderApi?.onReceiveBadCaseRecord(record,activity) } /** From 1869bbbbb98f184a35e086f6cc3cf9fbc2d53beb Mon Sep 17 00:00:00 2001 From: wangmingjun Date: Mon, 18 Jul 2022 10:25:40 +0800 Subject: [PATCH 03/27] =?UTF-8?q?[282=20bus=E5=8F=B8=E6=9C=BA=E7=AB=AF]=20?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=A9=BE=E9=A9=B6=E5=9F=8B=E7=82=B9=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mogo/och/bus/util/BusAnalyticsManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java index b2be2ca72b..915070fad4 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java @@ -5,7 +5,9 @@ import android.text.TextUtils; import com.mogo.cloud.passport.MoGoAiCloudClientConfig; import com.mogo.commons.debug.DebugConfig; import com.mogo.eagle.core.data.app.AppConfigInfo; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; import com.mogo.eagle.core.function.call.analytics.AnalyticsManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; import com.mogo.eagle.core.utilcode.util.DateTimeUtils; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.och.bus.constant.BusConst; @@ -35,7 +37,9 @@ public class BusAnalyticsManager { private Runnable startAutopilotRunnable = () -> { // 15s内未开启,上报失败埋点 - mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT, false); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT + , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); }; From 7858e0f4dd5974559919e9b4dd7646166d7a68ca Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Mon, 18 Jul 2022 10:32:42 +0800 Subject: [PATCH 04/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 注释BUS和Taxi业务端Badcase监控 --- .../java/com/mogo/och/bus/fragment/BaseBusTabFragment.java | 6 +++--- .../main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java index df8826cbec..c3ee127ba2 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java @@ -245,9 +245,9 @@ public abstract class BaseBusTabFragment @Override public void onAutopilotRecordResult(@Nullable RecordPanelOuterClass.RecordPanel recordPanel) { - if (!HmiBuildConfig.isShowBadCaseView && recordPanel != null && recordPanel.getType() == 1 && recordPanel.getStat() == 100) { - CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(recordPanel); - } +// if (!HmiBuildConfig.isShowBadCaseView && recordPanel != null && recordPanel.getType() == 1 && recordPanel.getStat() == 100) { +// CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(recordPanel); +// } } @Override diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java index 17cc3cae09..b27834d575 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java @@ -254,9 +254,9 @@ public abstract class BaseTaxiTabFragment Date: Mon, 18 Jul 2022 15:22:56 +0800 Subject: [PATCH 05/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UI调整 --- .../badcase/biz/AIDataCollectWindow.kt | 2 -- .../badcase/biz/PassiveBadCaseWindow.kt | 2 +- .../src/main/res/drawable/ai_collect_title_bg.xml | 2 +- .../src/main/res/drawable/bad_case_audio_normal.xml | 4 ++-- .../src/main/res/drawable/bad_case_audio_select.xml | 2 +- .../src/main/res/layout/view_ai_data_collect.xml | 2 +- .../src/main/res/layout/view_initiative_bad_case.xml | 2 +- .../src/main/res/layout/view_passive_bad_case.xml | 2 +- 8 files changed, 8 insertions(+), 10 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt index 06ffc73757..ded9ca9532 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt @@ -5,7 +5,6 @@ import android.app.Activity import android.graphics.PixelFormat import android.os.SystemClock import android.util.DisplayMetrics -import android.util.Log import android.view.* import android.widget.RadioButton import android.widget.TextView @@ -24,7 +23,6 @@ import com.mogo.eagle.core.utilcode.util.TimeUtils import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.zhjt.mogo_core_function_devatools.R import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig -import com.zhjt.mogo_core_function_devatools.badcase.toRecord import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import mogo.telematics.pad.MessagePad diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index 55175223d4..95c3a84fca 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -224,7 +224,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene itx["reason"] = uploadReason //采集原因 itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长,固定为20S itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) - itx["channel"] = "1" //渠道 + itx["channel"] = "0" //渠道 itx["carSn"] = MoGoAiCloudClientConfig.getInstance().sn //SN itx["userRole"] = BadCaseConfig.identity //采集者角色 itx["audioUrl"] = downloadUrl?:"" //音频COS地址 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/ai_collect_title_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/ai_collect_title_bg.xml index 2683bf5e3b..fbbee12698 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/ai_collect_title_bg.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/ai_collect_title_bg.xml @@ -2,7 +2,7 @@ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml index cfba52bd49..db561fa63a 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml @@ -2,8 +2,8 @@ - - + + diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml index f4dbd3de53..b90bb936be 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml @@ -7,7 +7,7 @@ android:endColor="#0056FF" android:angle="145" /> - + diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml index 7badb003b5..c41ed98cf1 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml @@ -5,7 +5,7 @@ android:layout_width="924px" android:layout_height="668px" app:roundLayoutRadius="40px" - android:background="@color/module_switch_map_bg"> + android:background="#1B2966"> + android:background="#1B2966"> + android:background="#1B2966"> Date: Mon, 18 Jul 2022 16:04:51 +0800 Subject: [PATCH 06/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配置页面增加现场恢复,默认展示已保存内容 --- .../badcase/biz/BadCaseConfigView.kt | 30 ++++++++++++++----- .../main/res/layout/layout_badcase_config.xml | 1 - 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt index d4223e7944..bf16e5c77e 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt @@ -37,9 +37,9 @@ defStyleAttr: Int = 0 } private var clickListener: ClickListener? = null - private var mIdentity = "安全员" - private var mPreviousDuration = 12 - private var mBackDuration = 8 + private var mIdentity = BadCaseConfig.identity + private var mPreviousDuration = BadCaseConfig.previousDuration + private var mBackDuration = BadCaseConfig.backDuration private var mType = 1 init{ @@ -80,12 +80,12 @@ defStyleAttr: Int = 0 try { if(preTimeStr.isEmpty()){ - mPreviousDuration = 12 + mPreviousDuration = BadCaseConfig.previousDuration }else{ mPreviousDuration = preTimeStr.toInt() } if(afterTimeStr.isEmpty()){ - mBackDuration = 8 + mBackDuration = BadCaseConfig.backDuration }else{ mBackDuration = afterTimeStr.toInt() } @@ -125,6 +125,22 @@ defStyleAttr: Int = 0 clickListener?.onClose() } + //现场恢复 + when(BadCaseConfig.identity){ + "安全员"->{ + rbSafetyOfficer.isChecked = true + } + "QA、研发"->{ + rbDeveloper.isChecked = true + } + "产品、运营、演示"->{ + rbProduct.isChecked = true + } + } + + etInitiativePreTime.hint = "${BadCaseConfig.previousDuration}S" + etInitiativeAfterTime.hint = "${BadCaseConfig.backDuration}S" + // val test1 = TestBean(1,"人工接管自动录制") // val test2 = TestBean(2,"地图采集") // val test3 = TestBean(3,"画龙问题排查") @@ -172,7 +188,7 @@ defStyleAttr: Int = 0 // ) // radioButton.textSize = SizeUtils.sp2px(9f).toFloat() // radioButton.id = it.id -// radioButton.isChecked = it.id == 1 +// radioButton.isChecked = it.id == BadCaseConfig.type // //设置文字 // radioButton.text = it.src // //将radioButton添加到radioGroup中 @@ -218,7 +234,7 @@ defStyleAttr: Int = 0 ) radioButton.textSize = SizeUtils.sp2px(9f).toFloat() radioButton.id = it.id - radioButton.isChecked = it.id == 1 + radioButton.isChecked = it.id == BadCaseConfig.type //设置文字 radioButton.text = it.desc //将radioButton添加到radioGroup中 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml index f7fc0a4109..257adb9947 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml @@ -92,7 +92,6 @@ android:textColor="#FFFFFFFF" android:textSize="38px" android:button="@null" - android:checked="true" android:drawableLeft="@drawable/badcase_radio_button_style" android:drawablePadding="30px" android:paddingTop="@dimen/dp_30" From 6e48edd4c048d9ba1b1ce34dd1bfe65548e321e9 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Mon, 18 Jul 2022 18:34:13 +0800 Subject: [PATCH 07/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改被动触发弹窗逻辑 --- .../badcase/BadCaseManager.kt | 24 +++++++++++-------- .../badcase/biz/AIDataCollectWindow.kt | 4 ++-- .../badcase/biz/InitiativeBadCaseWindow.kt | 6 ++--- .../badcase/biz/PassiveBadCaseWindow.kt | 13 ++-------- .../badcase/biz/TestBean.kt | 13 ---------- .../core/function/hmi/ui/MoGoHmiFragment.kt | 5 ++-- 6 files changed, 23 insertions(+), 42 deletions(-) delete mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/TestBean.kt 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 adad4f9121..913464289c 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 @@ -25,6 +25,7 @@ import com.mogo.eagle.core.utilcode.reminder.api.IReminder import com.mogo.eagle.core.utilcode.reminder.api.IReminder.IGlobalStateChangeListener import com.mogo.eagle.core.utilcode.util.ClickUtils import com.mogo.eagle.core.utilcode.util.NetworkUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.ToastUtils import com.zhjt.mogo_core_function_devatools.badcase.biz.* import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig @@ -235,19 +236,22 @@ internal object BadCaseManager : LifecycleEventObserver { } fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel,activity: Activity) { + CallerLogger.d("$M_DEVA$TAG", "收到录包结果回调${record}") if(BadCaseConfig.windowNum>1){ return } - val passiveBadCaseWindow = PassiveBadCaseWindow(activity) - passiveBadCaseWindow.setRecord(record.key.toString(),record.filename) - passiveBadCaseWindow.setClickListener(object: PassiveBadCaseWindow.ClickListener{ - override fun closeWindow() { - passiveBadCaseWindow.hideFloatWindow() - } - - }) - passiveBadCaseWindow.showFloatWindow() - + CallerLogger.d("$M_DEVA$TAG", "开始创建被动录包弹窗,window num=${BadCaseConfig.windowNum}") + CallerLogger.d("$M_DEVA$TAG","key=${record.key};filename${record.filename}") + ThreadUtils.runOnUiThread { + val passiveBadCaseWindow = PassiveBadCaseWindow(activity) + passiveBadCaseWindow.setRecord(record.key.toString(),record.filename) + passiveBadCaseWindow.setClickListener(object: PassiveBadCaseWindow.ClickListener{ + override fun closeWindow() { + passiveBadCaseWindow.hideFloatWindow() + } + }) + passiveBadCaseWindow.showFloatWindow() + } } private fun CoroutineScope.showBadCaseInternal(record: AutoPilotRecord) = launch { diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt index ded9ca9532..12b7a1e3c4 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt @@ -272,7 +272,7 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener when(recordPanel.stat){ 100, 101 ->{ //成功结束录制 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制成功") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") } 300 ->{ //开始录制 @@ -280,7 +280,7 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener } 200 ->{ //录制失败 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制失败") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") } } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index e8f7b46347..27668b6007 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -166,8 +166,6 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList if(rbSix.isChecked){ uploadReason.append("点刹、顿挫") } - //点击上报时,如果没有停止录音则先停止录音 - //TODO 未结束录音,点击上报,未能上传语音成功 if(audioStatus){ audioStatus = !audioStatus setAudio(audioStatus) @@ -364,7 +362,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList when(recordPanel.stat){ 100, 101 ->{ //成功结束录制 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制成功") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") } 300 ->{ //开始录制 @@ -372,7 +370,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } 200 ->{ //录制失败 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}bag录制失败") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") } } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index 95c3a84fca..bdd07b6d6d 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -16,7 +16,7 @@ import com.google.android.flexbox.FlexboxLayout import com.mogo.cloud.passport.MoGoAiCloudClientConfig import com.mogo.eagle.core.data.app.AppConfigInfo import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotCarStateListener -import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener +import androidx.lifecycle.lifecycleScope import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarStatusListenerManager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA @@ -34,7 +34,7 @@ import com.zhjt.mogo_core_function_devatools.badcase.record.RecordManager import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import mogo.telematics.pad.MessagePad -import record_cache.RecordPanelOuterClass +import com.mogo.eagle.core.utilcode.kotlin.* import java.io.File import java.lang.reflect.Field @@ -122,8 +122,6 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene TipToast.shortTip("请选择至少一个Case") return@setOnClickListener } - //点击上报时,如果没有停止录音则先停止录音 - //TODO 未结束录音,点击上报,未能上传语音成功 if(audioStatus){ audioStatus = !audioStatus setAudio(audioStatus) @@ -286,12 +284,6 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene checkBox.setTextColor(Color.WHITE) val lp = FlexboxLayout.LayoutParams(FlexboxLayout.LayoutParams.WRAP_CONTENT, FlexboxLayout.LayoutParams.WRAP_CONTENT) -// lp.setMargins( -// SizeUtils.dp2px(0f), -// SizeUtils.dp2px(0f), -// SizeUtils.dp2px(0f), -// SizeUtils.dp2px(0f) -// ) checkBox.buttonDrawable = mActivity.resources.getDrawable(R.drawable.badcase_radio_button_style) checkBox.setPadding(SizeUtils.dp2px(12f), SizeUtils.dp2px(5f), @@ -304,7 +296,6 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene flReasonLayout.addView(checkBox,lp) } } - } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/TestBean.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/TestBean.kt deleted file mode 100644 index 43274f6d4a..0000000000 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/TestBean.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.zhjt.mogo_core_function_devatools.badcase.biz - -/** - * @author xuxinchao - * @description - * @since: 2022/7/11 - */ -data class TestBean( - var id: Int, - var src: String -) { - -} diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index fc9218c2e8..c3c7aefcdc 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -200,10 +200,11 @@ import kotlin.collections.ArrayList override fun getNotificationView(): IViewNotification? = context?.let { V2XNotificationView(it) } override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { - if (recordPanel.type == 1 && recordPanel.stat == 100) { + //处于非美化模式下弹窗 + if (!FunctionBuildConfig.isDemoMode && recordPanel.stat == 100) { activity?.let { CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel, it) } } - if (recordPanel.type == 2 && ( + if (!FunctionBuildConfig.isDemoMode && recordPanel.type == 2 && ( recordPanel.stat == 101 || //工控机采集完成-被动完成 recordPanel.stat == 100 || //工控机采集完成-主动完成 recordPanel.stat == 102 || //工控机达到最大采集时长 From 3e5871c7d71f239a765c9dec5c334d460cd1ce9d Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Tue, 19 Jul 2022 10:00:36 +0800 Subject: [PATCH 08/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bag包录制结果提示修改 --- .../badcase/biz/AIDataCollectWindow.kt | 28 +++++++++--------- .../badcase/biz/InitiativeBadCaseWindow.kt | 29 ++++++++++--------- .../badcase/consts/BadCaseConfig.kt | 2 ++ .../core/function/hmi/ui/MoGoHmiFragment.kt | 16 ++++++++++ 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt index 12b7a1e3c4..8004d73182 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt @@ -265,24 +265,26 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") if(recordKey==null){ recordKey = recordPanel.key.toString() + BadCaseConfig.recordKeyList.add(recordPanel.key) } if(recordFileName==null){ recordFileName = recordPanel.filename } - when(recordPanel.stat){ - 100, 101 ->{ - //成功结束录制 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") - } - 300 ->{ - //开始录制 - } - 200 ->{ - //录制失败 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") - } - } +// when(recordPanel.stat){ +// 100, 101 ->{ +// //成功结束录制 +// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") +// } +// 300 ->{ +// //开始录制 +// +// } +// 200 ->{ +// //录制失败 +// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") +// } +// } } private fun setRadioButtonStatus(largeCarStatus: Boolean,trafficLightStatus: Boolean,waterStatus: Boolean, diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index 27668b6007..15296500ad 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -355,24 +355,25 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") if(recordKey==null){ recordKey = recordPanel.key.toString() + BadCaseConfig.recordKeyList.add(recordPanel.key) } if(recordFileName==null){ recordFileName = recordPanel.filename } - when(recordPanel.stat){ - 100, 101 ->{ - //成功结束录制 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") - } - 300 ->{ - //开始录制 - - } - 200 ->{ - //录制失败 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") - } - } +// when(recordPanel.stat){ +// 100, 101 ->{ +// //成功结束录制 +// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") +// } +// 300 ->{ +// //开始录制 +// +// } +// 200 ->{ +// //录制失败 +// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") +// } +// } } fun setClickListener(clickListener: ClickListener) { diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt index b6406f34b1..5ea74fecef 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/consts/BadCaseConfig.kt @@ -28,4 +28,6 @@ object BadCaseConfig { @JvmField var dockerVersion:String ?= null + var recordKeyList:ArrayList = ArrayList() + } \ 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/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index c3c7aefcdc..bd8530560d 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -68,6 +68,7 @@ import com.mogo.eagle.core.utilcode.kotlin.* import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils import com.mogo.eagle.core.utilcode.mogo.logger.* import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI +import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.reminder.* import com.mogo.eagle.core.utilcode.reminder.api.* import com.mogo.eagle.core.utilcode.reminder.api.IReminder.IStateChangeListener @@ -75,8 +76,10 @@ import com.mogo.eagle.core.utilcode.reminder.api.impl.* import com.mogo.eagle.core.utilcode.util.SoundUtils import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.TimeUtils +import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.module.common.enums.* +import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig import kotlinx.android.synthetic.main.fragment_hmi.* import kotlinx.coroutines.* import mogo_msg.MogoReportMsg @@ -200,6 +203,19 @@ import kotlin.collections.ArrayList override fun getNotificationView(): IViewNotification? = context?.let { V2XNotificationView(it) } override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { + CallerLogger.d(TAG, "recordKey=${recordPanel.key},stat=${recordPanel.stat}") + if(BadCaseConfig.recordKeyList.contains(recordPanel.key)){ + if(recordPanel.stat == 100 || recordPanel.stat == 101){ + //成功结束录制 + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") + } + if(recordPanel.stat == 200){ + //录制失败 + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") + } + BadCaseConfig.recordKeyList.remove(recordPanel.key) + return + } //处于非美化模式下弹窗 if (!FunctionBuildConfig.isDemoMode && recordPanel.stat == 100) { activity?.let { CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel, it) } From 9604d444fc757129daf8e7df90c609e835327cda Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Tue, 19 Jul 2022 10:10:50 +0800 Subject: [PATCH 09/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加日志 --- .../com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index bd8530560d..0753a7da41 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -203,7 +203,7 @@ import kotlin.collections.ArrayList override fun getNotificationView(): IViewNotification? = context?.let { V2XNotificationView(it) } override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { - CallerLogger.d(TAG, "recordKey=${recordPanel.key},stat=${recordPanel.stat}") + CallerLogger.d("$M_HMI$TAG", "recordKey=${recordPanel.key},stat=${recordPanel.stat}") if(BadCaseConfig.recordKeyList.contains(recordPanel.key)){ if(recordPanel.stat == 100 || recordPanel.stat == 101){ //成功结束录制 @@ -217,7 +217,7 @@ import kotlin.collections.ArrayList return } //处于非美化模式下弹窗 - if (!FunctionBuildConfig.isDemoMode && recordPanel.stat == 100) { + if (!FunctionBuildConfig.isDemoMode && (recordPanel.stat == 100 || recordPanel.stat == 101)) { activity?.let { CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel, it) } } if (!FunctionBuildConfig.isDemoMode && recordPanel.type == 2 && ( From 35518052f763487bcf6a6e90c442e30998bce992 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Tue, 19 Jul 2022 10:39:33 +0800 Subject: [PATCH 10/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改吐司文案 --- .../com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index 0753a7da41..d4cca81c4f 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -207,11 +207,11 @@ import kotlin.collections.ArrayList if(BadCaseConfig.recordKeyList.contains(recordPanel.key)){ if(recordPanel.stat == 100 || recordPanel.stat == 101){ //成功结束录制 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())} bag录制成功") } if(recordPanel.stat == 200){ //录制失败 - TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") + TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())} bag录制失败") } BadCaseConfig.recordKeyList.remove(recordPanel.key) return From ac534f6c57f84ca785560b0f4e42e7e311baa82e Mon Sep 17 00:00:00 2001 From: renwj Date: Tue, 19 Jul 2022 10:41:41 +0800 Subject: [PATCH 11/27] =?UTF-8?q?[V2X]=E4=BF=AE=E6=AD=A3=E4=B9=98=E5=AE=A2?= =?UTF-8?q?=E7=AB=AF=E9=A2=84=E8=AD=A6=E5=BC=B9=E7=AA=97=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=8D=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/TaxiPassengerV2XNotificationView.java | 2 +- .../eagle/core/function/hmi/ui/MoGoHmiFragment.kt | 14 ++++++++++++-- .../function/hmi/ui/widget/V2XNotificationView.kt | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerV2XNotificationView.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerV2XNotificationView.java index 66a88666b7..c05c0d4fad 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerV2XNotificationView.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerV2XNotificationView.java @@ -48,7 +48,7 @@ public class TaxiPassengerV2XNotificationView extends IViewNotification { // 设置View的出场位置 setSidePattern(SidePattern.LEFT); - setLayoutGravity(Gravity.LEFT); + setLayoutGravity(Gravity.LEFT | Gravity.TOP); // 设置View的停留位置:相对屏幕左上角的位置 // setOffsetX(getResources(). // getDimensionPixelSize(R.dimen.taxi_p_v2x_notification_view_margin_left)); diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index d4cca81c4f..5eb2c966d5 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -28,6 +28,7 @@ import com.mogo.eagle.core.data.config.FunctionBuildConfig import com.mogo.eagle.core.data.config.HmiBuildConfig import com.mogo.eagle.core.data.constants.MoGoFragmentPaths import com.mogo.eagle.core.data.enums.SidePattern +import com.mogo.eagle.core.data.enums.SidePattern.* import com.mogo.eagle.core.data.enums.WarningDirectionEnum import com.mogo.eagle.core.data.notice.NoticeNormalData import com.mogo.eagle.core.data.notice.NoticeTrafficStylePushData @@ -140,6 +141,7 @@ import kotlin.collections.ArrayList private var speakJob: Job? = null + private var showingV2XTip: IReminder? = null override fun vipIdentification(visible: Boolean) { ThreadUtils.runOnUiThread { if (visible) { @@ -582,7 +584,13 @@ import kotlin.collections.ArrayList itx.isFocusable = false itx.isClippingEnabled = false itx.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - val transition = Slide(Gravity.TOP).also { t -> + val transition = Slide(when(content.sidePattern) { + LEFT, RESULT_LEFT-> Gravity.LEFT + RIGHT, RESULT_RIGHT -> Gravity.RIGHT + TOP, RESULT_TOP -> Gravity.TOP + BOTTOM, RESULT_BOTTOM -> Gravity.BOTTOM + else -> Gravity.TOP + }).also { t -> t.interpolator = AccelerateDecelerateInterpolator() t.duration = 200 } @@ -594,7 +602,7 @@ import kotlin.collections.ArrayList override fun show() { val parent = it.window.decorView parent.doOnAttach { - popupWindow.showAtLocation(parent, Gravity.TOP, 0, 0) + popupWindow.showAtLocation(parent, content.layoutGravity, 0, 0) } } @@ -624,6 +632,7 @@ import kotlin.collections.ArrayList if (reminder == null) { return } + showingV2XTip = reminder lifecycleScope.launch { delay(expireTime) reminder?.hide() @@ -662,6 +671,7 @@ import kotlin.collections.ArrayList activity?.let { WarningFloat.dismiss(tag) } + showingV2XTip?.takeIf { it.isShowing() }?.also { it.hide() } } /** diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/V2XNotificationView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/V2XNotificationView.kt index 104aed541a..2de467d3b4 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/V2XNotificationView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/V2XNotificationView.kt @@ -30,7 +30,7 @@ class V2XNotificationView @JvmOverloads constructor( LayoutInflater.from(context).inflate(R.layout.notification_v2x_msg_vr, this, true) // 设置View的出场位置 sidePattern = SidePattern.RESULT_TOP - layoutGravity = Gravity.CENTER_HORIZONTAL + layoutGravity = Gravity.CENTER_HORIZONTAL or Gravity.TOP // 设置View的停留位置 setPadding(0, 110, 0, 0) } From f704008b5b20893f58eb932a04812423b0e8076c Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Tue, 19 Jul 2022 10:56:19 +0800 Subject: [PATCH 12/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改上传文字赋值 --- .../badcase/biz/PassiveBadCaseWindow.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index bdd07b6d6d..6cc160c725 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -311,10 +311,10 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } }else{ if(uploadReason.contains(it)){ - uploadReason.replace(it.toString(),"") - + uploadReason = uploadReason.replace(it.toString(),"") } } + } } From 74f3b18fc4cfc497ae4f3b3dc0b241a9d5988f9f Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Tue, 19 Jul 2022 15:25:38 +0800 Subject: [PATCH 13/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 被动触发录包只在司机屏生效 --- .../com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index 5eb2c966d5..c3c9d35a19 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -220,7 +220,10 @@ import kotlin.collections.ArrayList } //处于非美化模式下弹窗 if (!FunctionBuildConfig.isDemoMode && (recordPanel.stat == 100 || recordPanel.stat == 101)) { - activity?.let { CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel, it) } + //只在司机屏生效,乘客屏不生效 + if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){ + activity?.let { CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel, it) } + } } if (!FunctionBuildConfig.isDemoMode && recordPanel.type == 2 && ( recordPanel.stat == 101 || //工控机采集完成-被动完成 From a52e49ffef53aafa368c7688e1ce92bee39e359b Mon Sep 17 00:00:00 2001 From: renwj Date: Wed, 20 Jul 2022 10:34:39 +0800 Subject: [PATCH 14/27] =?UTF-8?q?[V2X]=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=8E=92=E6=9F=A5=E4=B9=98=E5=AE=A2=E5=B1=8F=E9=A2=84=E8=AD=A6?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E5=BB=B6=E8=BF=9F10s+?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index c3c9d35a19..03476253ff 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -69,6 +69,7 @@ import com.mogo.eagle.core.utilcode.kotlin.* import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils import com.mogo.eagle.core.utilcode.mogo.logger.* import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_V2X import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.reminder.* import com.mogo.eagle.core.utilcode.reminder.api.* @@ -582,6 +583,7 @@ import kotlin.collections.ArrayList content.setWarningIcon(EventTypeEnum.getWarningIcon(v2xType)) content.setWarningContent(warningContent) var reminder: IReminder? = null + Log.d("$M_HMI$TAG", "--- show v2x dialog 1 ---: info -> v2x-type: $v2xType : expireTime: $expireTime") Reminder.enqueue(this@MoGoHmiFragment, object : PopupWindowReminder(PopupWindow(content, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).also { itx -> itx.isTouchable = false itx.isFocusable = false @@ -605,6 +607,7 @@ import kotlin.collections.ArrayList override fun show() { val parent = it.window.decorView parent.doOnAttach { + Log.d("$M_HMI$TAG", "--- show v2x dialog 2 ---: info -> v2x-type: $v2xType : expireTime: $expireTime") popupWindow.showAtLocation(parent, content.layoutGravity, 0, 0) } } @@ -617,7 +620,6 @@ import kotlin.collections.ArrayList override fun onShow(reminder: IReminder) { listener?.onShow() if (ttsContent != null && !TextUtils.isEmpty(ttsContent) && playTTS) { - CallerLogger.d("$M_HMI$TAG", "---> ttsContent = $ttsContent") lifecycleScope.launch { speak(it, ttsContent) }.also { @@ -674,6 +676,7 @@ import kotlin.collections.ArrayList activity?.let { WarningFloat.dismiss(tag) } + Log.d("$M_HMI$TAG", "--- disableWarningV2X ---") showingV2XTip?.takeIf { it.isShowing() }?.also { it.hide() } } From 4e5918d1d0480f69fe4abfe6062879650d2f9ea0 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Wed, 20 Jul 2022 12:07:10 +0800 Subject: [PATCH 15/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UI调整 --- .../badcase/biz/InitiativeBadCaseWindow.kt | 7 ++--- .../badcase/biz/PassiveBadCaseWindow.kt | 13 +++++----- .../res/drawable-xxhdpi/icon_audio_bg.png | Bin 0 -> 58717 bytes .../icon_bad_case_audio_normal.png | Bin 0 -> 8948 bytes .../icon_bad_case_audio_select.png | Bin 0 -> 14930 bytes .../res/drawable-xxhdpi/icon_cancel_bg.png | Bin 0 -> 19175 bytes .../main/res/drawable/bad_case_audio_bg.xml | 9 ------- .../res/drawable/bad_case_audio_normal.xml | 10 -------- .../res/drawable/bad_case_audio_select.xml | 14 ---------- .../main/res/drawable/cancel_button_bg.xml | 5 ---- .../main/res/layout/layout_badcase_config.xml | 4 +-- .../main/res/layout/view_ai_data_collect.xml | 2 +- .../res/layout/view_initiative_bad_case.xml | 24 +++++------------- .../main/res/layout/view_passive_bad_case.xml | 24 +++++------------- 14 files changed, 28 insertions(+), 84 deletions(-) create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_audio_bg.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_bad_case_audio_normal.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_bad_case_audio_select.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_cancel_bg.png delete mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_bg.xml delete mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml delete mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml delete mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_button_bg.xml diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index 15296500ad..1db9bb90cd 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -9,6 +9,7 @@ import android.os.SystemClock import android.util.DisplayMetrics import android.view.* import android.widget.CheckBox +import android.widget.ImageView import android.widget.TextView import com.mogo.cloud.passport.MoGoAiCloudClientConfig import com.mogo.eagle.core.data.app.AppConfigInfo @@ -67,7 +68,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList private lateinit var rbFive: CheckBox private lateinit var rbSix: CheckBox - private lateinit var viewAudioButton: View + private lateinit var viewAudioButton: ImageView private lateinit var tvAudioCountDown: TextView private lateinit var tvInitiativeReport: TextView @@ -203,7 +204,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" RecordManager.getInstance().start(audioFileName) //更改录音按钮背景 - viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_select) + viewAudioButton.setImageResource(R.drawable.icon_bad_case_audio_select) tvAudioCountDown.visibility = View.VISIBLE //开始倒计时 if(countDownTimer==null){ @@ -218,7 +219,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList //结束录音 RecordManager.getInstance().stop() //更改录音按钮背景 - viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_normal) + viewAudioButton.setImageResource(R.drawable.icon_bad_case_audio_normal) } } countDownTimer?.start() diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index 6cc160c725..ff05c2fdb1 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -11,6 +11,7 @@ import android.util.Log import android.view.* import android.widget.CheckBox import android.widget.CompoundButton +import android.widget.ImageView import android.widget.TextView import com.google.android.flexbox.FlexboxLayout import com.mogo.cloud.passport.MoGoAiCloudClientConfig @@ -78,7 +79,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene private lateinit var tvPassiveTime: TextView private lateinit var tvPassiveIdentity: TextView - private lateinit var viewAudioButton: View + private lateinit var viewAudioButton: ImageView private lateinit var tvAudioCountDown: TextView private lateinit var tvPassiveReport: TextView @@ -156,7 +157,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" RecordManager.getInstance().start(audioFileName) //更改录音按钮背景 - viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_select) + viewAudioButton.setImageResource(R.drawable.icon_bad_case_audio_select) tvAudioCountDown.visibility = View.VISIBLE //开始倒计时 if(countDownTimer==null){ @@ -171,7 +172,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene //结束录音 RecordManager.getInstance().stop() //更改录音按钮背景 - viewAudioButton.background = mActivity.getDrawable(R.drawable.bad_case_audio_normal) + viewAudioButton.setImageResource(R.drawable.icon_bad_case_audio_normal) } } countDownTimer?.start() @@ -285,10 +286,10 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene val lp = FlexboxLayout.LayoutParams(FlexboxLayout.LayoutParams.WRAP_CONTENT, FlexboxLayout.LayoutParams.WRAP_CONTENT) checkBox.buttonDrawable = mActivity.resources.getDrawable(R.drawable.badcase_radio_button_style) - checkBox.setPadding(SizeUtils.dp2px(12f), - SizeUtils.dp2px(5f), + checkBox.setPadding(SizeUtils.dp2px(10f), SizeUtils.dp2px(10f), - SizeUtils.dp2px(5f)) + SizeUtils.dp2px(10f), + SizeUtils.dp2px(10f)) checkBox.textSize = SizeUtils.sp2px(9f).toFloat() checkBox.text = it.reason checkBox.isChecked = it.isChecked diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_audio_bg.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_audio_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..c67751750d725ece4f432d53bd0517ff9e7ea604 GIT binary patch literal 58717 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�*mD#J_E<;80MNrxk5-B^P&lgf`|#I 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 literal 0 HcmV?d00001 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_bad_case_audio_normal.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xxhdpi/icon_bad_case_audio_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..cd3fee2a613530780c0fca31df49db39c1ef15ad GIT binary patch literal 8948 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 - - - - \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml deleted file mode 100644 index db561fa63a..0000000000 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_normal.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml deleted file mode 100644 index b90bb936be..0000000000 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bad_case_audio_select.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_button_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_button_bg.xml deleted file mode 100644 index 612a3e5afe..0000000000 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_button_bg.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml index 257adb9947..cb1134f4fe 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_config.xml @@ -145,7 +145,7 @@ android:textSize="38px" app:layout_constraintTop_toBottomOf="@id/rbProduct" app:layout_constraintLeft_toLeftOf="@id/rbProduct" - android:layout_marginTop="@dimen/dp_80" + android:layout_marginTop="@dimen/dp_50" /> diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml index c41ed98cf1..5c04822c7a 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_ai_data_collect.xml @@ -175,7 +175,7 @@ android:textColor="#FFFFFF" android:textSize="30px" android:gravity="center" - android:background="@drawable/cancel_button_bg" + android:background="@drawable/icon_cancel_bg" android:layout_marginBottom="@dimen/dp_40" /> diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml index d66f5135db..8afe1d5e5c 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_initiative_bad_case.xml @@ -172,40 +172,30 @@ android:textColor="#FFFFFF" android:textSize="30px" android:gravity="center" - android:background="@drawable/cancel_button_bg" + android:background="@drawable/icon_cancel_bg" android:layout_marginBottom="@dimen/dp_40" /> - - - - - - - - Date: Wed, 20 Jul 2022 13:19:51 +0800 Subject: [PATCH 16/27] =?UTF-8?q?[282=20taxi=E4=B9=98=E5=AE=A2=E5=B1=8F]?= =?UTF-8?q?=20=E7=A9=BA=E6=8C=87=E9=92=88=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mogo/och/common/module/wigets/sfv/BaseSurfaceView.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/wigets/sfv/BaseSurfaceView.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/wigets/sfv/BaseSurfaceView.java index a53cdfbce8..1ece70606f 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/wigets/sfv/BaseSurfaceView.java +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/wigets/sfv/BaseSurfaceView.java @@ -149,8 +149,10 @@ public abstract class BaseSurfaceView extends SurfaceView implements SurfaceHold getHolder().unlockCanvasAndPost(canvas); onFrameDrawFinish(); } - - handler.postDelayed(this, frameDuration); + + if (handler != null){ + handler.postDelayed(this, frameDuration); + } } } From 3b6f07aa81a82f335be365ebea106a358b015d30 Mon Sep 17 00:00:00 2001 From: wangmingjun Date: Wed, 20 Jul 2022 16:56:14 +0800 Subject: [PATCH 17/27] =?UTF-8?q?[282=20taxi=E4=B9=98=E5=AE=A2=E5=B1=8F]?= =?UTF-8?q?=20=E5=A4=84=E7=90=86=E5=90=AF=E5=8A=A8=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=A9=BE=E9=A9=B6=E6=8C=89=E9=92=AE=E5=8D=A1=E9=A1=BF=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/utils/AnimatorDrawableUtil.java | 261 ++++++++++++++++++ .../ui/TaxiPassengerStartAutopilotView.java | 67 +++-- 2 files changed, 307 insertions(+), 21 deletions(-) create mode 100644 OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java new file mode 100644 index 0000000000..bbf9d779eb --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java @@ -0,0 +1,261 @@ +package com.mogo.och.common.module.utils; + +import android.content.Context; +import android.content.res.XmlResourceParser; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Handler; +import android.os.Message; +import android.widget.ImageView; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +/** + * @author: wangmingjun + * @date: 2022/7/20 + */ +public class AnimatorDrawableUtil { + private static final int MSG_START = 0xf1; + private static final int MSG_STOP = 0xf2; + private static final int STATE_STOP = 0xf3; + private static final int STATE_RUNNING = 0xf4; + + //运行状态 + private int mState = STATE_RUNNING; + //显示图片的View + private ImageView mImageView = null; + //图片资源的ID列表 + private List mResourceIdList = null; + //定时任务器 + private Timer mTimer = null; + //定时任务 + private AnimTimerTask mTimeTask = null; + //记录播放位置 + private int mFrameIndex = 0; + //播放形式 + private boolean isLooping = false; + + public AnimatorDrawableUtil() { + mTimer = new Timer(); + } + + /** + * 设置动画播放资源 + */ + public void setAnimation(ImageView imageview, List resourceIdList) { + mImageView = imageview; + if(mResourceIdList==null){ + mResourceIdList = new ArrayList(); + }else{ + mResourceIdList.clear(); + } + mResourceIdList.addAll(resourceIdList); + } + + /** + * 设置动画播放资源 + */ + public void setAnimation(Context context, int resourceId, ImageView imageview) { + this.mImageView = imageview; + if(mResourceIdList==null){ + mResourceIdList = new ArrayList(); + }else{ + mResourceIdList.clear(); + } + + loadFromXml(context, resourceId, new OnParseListener() { + @Override + public void onParse(List res) { + mResourceIdList.addAll(res); + } + }); + } + + /** + * 解析xml + * + * @param context + * @param resourceId 资源id + */ + private void loadFromXml(final Context context, final int resourceId, + final OnParseListener onParseListener) { + if (context == null) { + return; + } + + final List res = new ArrayList(); + XmlResourceParser parser = context.getResources().getXml(resourceId); + + try { + int eventType = parser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_DOCUMENT) { + } else if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("item")) { + for (int i = 0; i < parser.getAttributeCount(); i++) { + if (parser.getAttributeName(i).equals("drawable")) { + int resId = Integer.parseInt(parser.getAttributeValue(i).substring(1)); + res.add(resId); + } + } + } + } else if (eventType == XmlPullParser.END_TAG) { + } else if (eventType == XmlPullParser.TEXT) { + } + + eventType = parser.next(); + } + } catch (IOException e) { + // TODO: handle exception + e.printStackTrace(); + } catch (XmlPullParserException e2) { + // TODO: handle exception + e2.printStackTrace(); + } finally { + parser.close(); + } + + if (onParseListener != null) { + onParseListener.onParse(res); + } + } + + private AnimationLisenter lisenter; + + + /** + * 开始播放动画 + * + * @param loop 是否循环播放 + * @param duration 动画播放时间间隔 + */ + public void start(boolean loop, int duration, AnimationLisenter lisenter) { + this.lisenter = lisenter; + stop(); + if (mResourceIdList == null || mResourceIdList.size() == 0) { + return; + } + if (mTimer == null) { + mTimer = new Timer(); + } + isLooping = loop; + mFrameIndex = 0; + mState = STATE_RUNNING; + mTimeTask = new AnimTimerTask(); + mTimer.schedule(mTimeTask, 0, duration); + if (lisenter != null){ + lisenter.startAnimation(); + } + } + + /** + * 停止动画播放 + */ + public void stop() { + if (mTimer != null) { + mTimer.purge(); + mTimer.cancel(); + mTimer = null; + } + if (mTimeTask != null) { + mFrameIndex = 0; + mState = STATE_STOP; + mTimeTask.cancel(); + mTimeTask = null; + } + //移除Handler消息 + if (AnimHandler != null) { + AnimHandler.removeMessages(MSG_START); + AnimHandler.removeMessages(MSG_STOP); + AnimHandler.removeCallbacksAndMessages(null); + } + } + + /** + * 定时器任务 + */ + class AnimTimerTask extends TimerTask { + + @Override + public void run() { + if (mFrameIndex < 0 || mState == STATE_STOP) { + return; + } + + if (mFrameIndex < mResourceIdList.size()) { + Message msg = AnimHandler.obtainMessage(MSG_START, 0, 0, null); + msg.sendToTarget(); + } else { + mFrameIndex = 0; + if (!isLooping) { + Message msg = AnimHandler.obtainMessage(MSG_STOP, 0, 0, null); + msg.sendToTarget(); + } + } + } + } + + /** + * Handler + */ + private Handler AnimHandler = new Handler() { + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_START: { + if (mFrameIndex >= 0 && mFrameIndex < mResourceIdList.size() && mState == STATE_RUNNING) { + //这里不能使用image.setImageResource 因为源码中也是创建了bitmap 所以这里我们自己创建 + Bitmap bitmap=readBitMap(mImageView.getContext(),mResourceIdList.get(mFrameIndex)); + mImageView.setImageBitmap(bitmap); + mFrameIndex++; + } + } + break; + case MSG_STOP: { + if (mTimeTask != null) { + mFrameIndex = 0; + mTimer.purge(); + mTimeTask.cancel(); + mState = STATE_STOP; + mTimeTask = null; + if (lisenter !=null){ + lisenter.endAnimation(); + } + if (isLooping) { + mImageView.setImageResource(0); + } + } + } + break; + default: + break; + } + } + }; + + public static Bitmap readBitMap(Context context, int resId) { + BitmapFactory.Options opt = new BitmapFactory.Options(); + opt.inPreferredConfig = Bitmap.Config.RGB_565; + opt.inPurgeable = true; + opt.inInputShareable = true; + InputStream is = context.getResources().openRawResource(resId); + return BitmapFactory.decodeStream(is, null, opt); + } + + public interface OnParseListener { + void onParse(List res); + } + + public interface AnimationLisenter { + void startAnimation(); + + void endAnimation(); + } +} diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java index 008854287c..41146e5982 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java @@ -4,7 +4,6 @@ import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAX import android.annotation.SuppressLint; import android.content.Context; -import android.graphics.drawable.AnimationDrawable; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; @@ -15,10 +14,10 @@ import com.elegant.utils.UiThreadHandler; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.util.OverlayViewUtils; import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.och.common.module.utils.AnimatorDrawableUtil; import com.mogo.och.common.module.wigets.sfv.FrameSurfaceView; import com.mogo.och.taxi.passenger.R; import com.mogo.och.taxi.passenger.callback.ITPClickStartAutopilotCallback; -import com.mogo.och.taxi.passenger.model.TaxiPassengerModel; import java.util.Arrays; @@ -35,11 +34,11 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V private ImageView mCloseIV; private ITPClickStartAutopilotCallback mClickCallback; public boolean isStarting = false; - private AnimationDrawable mAnimationBtnDrawable; private static final long TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L; private Context mContext; private View view; private FrameSurfaceView svCarStartingFrame; + private AnimatorDrawableUtil mAnimationDrawable ; private Integer[] startingAnimIds = new Integer[]{ R.drawable.light_00000, R.drawable.light_00001, @@ -56,6 +55,33 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V R.drawable.light_00012, R.drawable.light_00013 }; + private Integer[] startBtnBgAnimIds = new Integer[]{ + R.drawable.image_00000, R.drawable.image_00001, R.drawable.image_00002, R.drawable.image_00003, + R.drawable.image_00004, R.drawable.image_00005, R.drawable.image_00006, R.drawable.image_00007, + R.drawable.image_00008, R.drawable.image_00009, R.drawable.image_00010, R.drawable.image_00011, + R.drawable.image_00012, R.drawable.image_00013,R.drawable.image_00014,R.drawable.image_00015, + R.drawable.image_00016, R.drawable.image_00017,R.drawable.image_00018,R.drawable.image_00019, + R.drawable.image_00020, R.drawable.image_00021,R.drawable.image_00022,R.drawable.image_00023, + R.drawable.image_00024, R.drawable.image_00025,R.drawable.image_00026,R.drawable.image_00027, + R.drawable.image_00028, R.drawable.image_00029,R.drawable.image_00030,R.drawable.image_00031, + R.drawable.image_00032, R.drawable.image_00033,R.drawable.image_00034,R.drawable.image_00035, + R.drawable.image_00036, R.drawable.image_00037,R.drawable.image_00038,R.drawable.image_00039, + R.drawable.image_00040, R.drawable.image_00041,R.drawable.image_00042,R.drawable.image_00043, + R.drawable.image_00044, R.drawable.image_00045,R.drawable.image_00046,R.drawable.image_00047, + R.drawable.image_00048, R.drawable.image_00049,R.drawable.image_00050,R.drawable.image_00051, + R.drawable.image_00052, R.drawable.image_00053,R.drawable.image_00054,R.drawable.image_00055, + R.drawable.image_00056, R.drawable.image_00057,R.drawable.image_00058,R.drawable.image_00059, + R.drawable.image_00060, R.drawable.image_00061,R.drawable.image_00062,R.drawable.image_00063, + R.drawable.image_00064, R.drawable.image_00065,R.drawable.image_00066,R.drawable.image_00067, + R.drawable.image_00068,R.drawable.image_00069,R.drawable.image_00070, R.drawable.image_00071, + R.drawable.image_00072,R.drawable.image_00073, R.drawable.image_00074, R.drawable.image_00075, + R.drawable.image_00076,R.drawable.image_00077,R.drawable.image_00078,R.drawable.image_00079, + R.drawable.image_00080, R.drawable.image_00081, R.drawable.image_00082,R.drawable.image_00083, + R.drawable.image_00084, R.drawable.image_00085, R.drawable.image_00086,R.drawable.image_00087, + R.drawable.image_00088, R.drawable.image_00089, R.drawable.image_00090,R.drawable.image_00091, + R.drawable.image_00092, R.drawable.image_00093, R.drawable.image_00094,R.drawable.image_00095, + R.drawable.image_00096, R.drawable.image_00097, R.drawable.image_00098,R.drawable.image_00099, + }; public TaxiPassengerStartAutopilotView(Context context) { super(context); @@ -73,16 +99,20 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V mAutopilotBtnBg = view.findViewById(R.id.taxi_p_autopilot_btn_bg); + initBtnAnimatonDrawable(); + + initCarStartingFrame(); + } + + private void initCarStartingFrame() { svCarStartingFrame = view.findViewById(R.id.taxi_p_autopilot_starting); svCarStartingFrame.setBitmapIds(Arrays.asList(startingAnimIds)); svCarStartingFrame.setDuration(1300); -// svCarStartingFrame.setOnLongClickListener(new OnLongClickListener() { -// @Override -// public boolean onLongClick(View v) { -// TaxiPassengerModel.getInstance().startServicePilotDone(); -// return false; -// } -// }); + } + + private void initBtnAnimatonDrawable() { + mAnimationDrawable = new AnimatorDrawableUtil(); + mAnimationDrawable.setAnimation(mAutopilotBtnBg,Arrays.asList(startBtnBgAnimIds)); } public void setOnClickStartAutopilotBtnCallback(ITPClickStartAutopilotCallback clickCallback){ @@ -132,7 +162,6 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V mStartAutopilotBtn.setTextColor( mContext.getResources().getColor(R.color.taxi_p_start_autopilot_txt_color)); mStartAutopilotBtn.setBackground(null); - mAutopilotBtnBg.setBackground(mContext.getResources().getDrawable(R.drawable.anmi_flow)); }else { mStartAutopilotBtn.setBackground( mContext.getResources().getDrawable(R.drawable.taxi_p_start_autopilot_txt_btn_bg)); @@ -148,15 +177,12 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V public void startAutopilotBgAnimatorDrawable(boolean isStart){ if (isStart){ - if (mAnimationBtnDrawable == null) { - mAnimationBtnDrawable = (AnimationDrawable) mAutopilotBtnBg.getBackground(); + if (mAnimationDrawable == null){ + } - if (mAnimationBtnDrawable.isRunning()) { - CallerLogger.INSTANCE.d(M_TAXI_P+TAG,"mAnimationBtnDrawable.isRunning() = true"); - return; + if (mAnimationDrawable != null){ + mAnimationDrawable.start(true, 30, null); } - mAnimationBtnDrawable.selectDrawable(-1); - mAnimationBtnDrawable.start(); }else { clearBgAnimDrawable(); } @@ -194,10 +220,9 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V } public void clearBgAnimDrawable() { - if (mAnimationBtnDrawable != null) { - mAnimationBtnDrawable.stop(); + if (mAnimationDrawable != null){ + mAnimationDrawable.stop(); } - mAnimationBtnDrawable = null; } public void closeAllAnimsAndView(){ From ee9d2e23e0c7e7ec5ac967c78d5c30f7f5476d32 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Wed, 20 Jul 2022 17:52:25 +0800 Subject: [PATCH 18/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 被动弹窗允许多次弹窗 --- .../mogo_core_function_devatools/badcase/BadCaseManager.kt | 3 --- .../com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt | 1 - 2 files changed, 4 deletions(-) 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 913464289c..3306a57d94 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 @@ -237,9 +237,6 @@ internal object BadCaseManager : LifecycleEventObserver { fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel,activity: Activity) { CallerLogger.d("$M_DEVA$TAG", "收到录包结果回调${record}") - if(BadCaseConfig.windowNum>1){ - return - } CallerLogger.d("$M_DEVA$TAG", "开始创建被动录包弹窗,window num=${BadCaseConfig.windowNum}") CallerLogger.d("$M_DEVA$TAG","key=${record.key};filename${record.filename}") ThreadUtils.runOnUiThread { diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index 03476253ff..af08071653 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -216,7 +216,6 @@ import kotlin.collections.ArrayList //录制失败 TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())} bag录制失败") } - BadCaseConfig.recordKeyList.remove(recordPanel.key) return } //处于非美化模式下弹窗 From 69c398b3ad3afd85fd2b4e11405d63ac5f2dc5d2 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Wed, 20 Jul 2022 18:38:41 +0800 Subject: [PATCH 19/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加前溯时长为30S的判断 --- .../badcase/biz/BadCaseConfigView.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt index bf16e5c77e..f7d92b33d0 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseConfigView.kt @@ -90,20 +90,20 @@ defStyleAttr: Int = 0 mBackDuration = afterTimeStr.toInt() } - if(mPreviousDuration<0 || mPreviousDuration>300){ - ToastUtils.showLong("采集时长最长300S") + if(mPreviousDuration<0 || mPreviousDuration>30){ + ToastUtils.showLong("前溯采集时长最长30S") return@setOnClickListener } if(mBackDuration<0 || mBackDuration>300){ - ToastUtils.showLong("采集时长最长300S") + ToastUtils.showLong("采集总时长最长300S") return@setOnClickListener } if((mPreviousDuration+mBackDuration)<5){ - ToastUtils.showLong("采集时长最短5S") + ToastUtils.showLong("采集总时长最短5S") return@setOnClickListener } if((mPreviousDuration+mBackDuration)>300){ - ToastUtils.showLong("采集时长最长300S") + ToastUtils.showLong("采集总时长最长300S") return@setOnClickListener } BadCaseConfig.previousDuration = mPreviousDuration From f274e19e802618365cb60a2512c65276957b2527 Mon Sep 17 00:00:00 2001 From: renwj Date: Thu, 21 Jul 2022 14:51:31 +0800 Subject: [PATCH 20/27] =?UTF-8?q?[V2X]=E5=8E=BB=E6=8E=89=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt index 8fcb641014..b1012246cd 100644 --- a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt +++ b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt @@ -104,7 +104,6 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb V2XManager.init(V2XConfig.Builder().also { it.aiCloudConfig(MoGoAiCloudClientConfig.getInstance()) it.context(context) - it.loggable(true) it.distanceForTriggerRefresh(200f) //行驶超过200(包含)米,刷新道路周边信息(短链请求) it.durationForTriggerRefresh( 60, From e891bcf9065c41c742dc3ae6c301967bcc82a929 Mon Sep 17 00:00:00 2001 From: wangmingjun Date: Thu, 21 Jul 2022 15:56:13 +0800 Subject: [PATCH 21/27] =?UTF-8?q?[282=20taxi-d=20taxi-p]=201=E3=80=81?= =?UTF-8?q?=E8=A7=A3=E8=97=95=E8=AE=A2=E5=8D=95=E7=8A=B6=E6=80=81=E6=B5=81?= =?UTF-8?q?=E8=BD=AC=E5=92=8C=E8=87=AA=E5=8A=A8=E9=A9=BE=E9=A9=B6=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../passenger/model/TaxiPassengerModel.java | 6 +- .../com/mogo/och/taxi/model/TaxiModel.java | 58 +++++++++---------- .../och/taxi/presenter/TaxiPresenter.java | 5 +- .../com/mogo/och/taxi/ui/TaxiFragment.java | 6 +- .../och/taxi/utils/TaxiAnalyticsManager.java | 6 +- 5 files changed, 40 insertions(+), 41 deletions(-) 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 1b1fec85e7..56286e88ff 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 @@ -872,9 +872,8 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback return; } - if (mCurrentOCHOrder.orderStatus != TaxiPassengerOrderStatusEnum.UserArriveAtStart.getCode()) { - ToastUtils.showShort("当前订单状态异常!"); - return; + if (mCurrentOCHOrder.orderStatus == TaxiPassengerOrderStatusEnum.UserArriveAtStart.getCode()){ + startServicePilotDone(); } double startWgsLon = mCurrentOCHOrder.startSitePoint.get(0); @@ -903,6 +902,7 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback + " ,startSiteName=" + mCurrentOCHOrder.startSiteAddr + " ,endSiteName=" + mCurrentOCHOrder.endSiteAddr); + TaxiPassengerAnalyticsManager.getInstance().triggerStartAutopilotEvent(false, false, mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo); } 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 1c5aa3d454..3f672cc3b6 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 @@ -115,6 +115,8 @@ public class TaxiModel { private ITaxiControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等 private ITaxiOrderStatusCallback mOrderStatusCallback; //Model->Presenter:订单变更 + private volatile boolean isRestartAutopilot = false; + private List mRoutePoints = new ArrayList<>(); private double mLongitude, mLatitude; @@ -787,7 +789,7 @@ public class TaxiModel { new TaxiServiceCallback() { @Override public void onSuccess(TaxiDataBaseRespBean data) { - if (data != null && data.code == 0 && data.data.equals(true)) + if (data != null && data.code == 0) updateAutopilotStatus(data.data.equals(true)); } @@ -840,6 +842,7 @@ public class TaxiModel { mCurrentOCHOrder = null; TaxiTrajectoryManager.getInstance().syncTrajectoryInfo(); SharedPrefsMgr.getInstance(mContext).remove(TaxiConst.SP_KEY_OCH_TAXI_ORDER); + isRestartAutopilot = false; if (FunctionBuildConfig.isDemoMode) { // 当美化模式(演示模式)开启时: 取消或订单已完成时,置false FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; @@ -860,9 +863,7 @@ public class TaxiModel { /** * 以当前订单为基础,开启自动驾驶 - * - * @param isRestart 开启自动驾驶 - */ + **/ @ChainLog( linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT, linkCode = CHAIN_LINK_ADAS, @@ -871,20 +872,27 @@ public class TaxiModel { paramIndexes = {-1}, // clientPkFileName = "sn" ) - public void startAutoPilot(boolean isRestart) { + public void startAutoPilot() { if (!checkCurrentOCHOrder()) { CallerLogger.INSTANCE.e(M_TAXI + TAG, "no order or order is empty."); ToastUtils.showShort("当前订单不存在或异常!"); return; } - if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE == CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) { // TODO: 2021/11/28 工控机存在刚开始状态为0,但是可以开启变为2,工控机解决前不显示此toast // ToastUtils.showShort("自动驾驶状态为不可用!"); } + //点击开始自动驾驶按钮订单状态去流转, 不再与自动驾驶是否启动成功挂钩 + if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.UserArriveAtStart.getCode()){ + startServicePilotDone(); + isRestartAutopilot = false; + }else { + isRestartAutopilot = true; + } + double startWgsLon = mCurrentOCHOrder.startSitePoint.get(0); double startWgsLat = mCurrentOCHOrder.startSitePoint.get(1); double endWgsLon = mCurrentOCHOrder.endSitePoint.get(0); @@ -907,13 +915,9 @@ public class TaxiModel { CallerLogger.INSTANCE.d(M_TAXI + TAG, "start autopilot with parameter: %s", GsonUtil.jsonFromObject(parameters) + " ,startSiteName=" + mCurrentOCHOrder.startSiteAddr + " ,endSiteName=" + mCurrentOCHOrder.endSiteAddr); - TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestart, false, + TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestartAutopilot, false, mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo); - if (DebugConfig.isDebug()) { - // ToastUtils.showShort("Start autopilot!"); - } - // TODO: 2021/8/20 无工控机环境, 手动调起自动驾驶开启返回结果,有工控机环境要删除 // OCHTaxiUiController.getInstance().onAutoPilotStatusChanged( IMogoAdasOCHCallback.STATUS_AUTOPILOT_RUNNING, "开启自动驾驶" ); } @@ -1080,29 +1084,21 @@ public class TaxiModel { if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning(); if (mCurrentOCHOrder != null - && getCurOrderStatus() == TaxiOrderStatusEnum.UserArriveAtStart - && state != mPrevAPStatus) { - // 当高频返回autopilot 2时,不重复调用订单状态变更 - mPrevAPStatus = state; // 每个状态单独赋值,解决无订单时已经是2的状态导致的新订单来时无法进入此逻辑更新状态 + && TaxiOrderStatusEnum.OnTheWayToEnd.getCode() == mCurrentOCHOrder.orderStatus){ + if (state != mPrevAPStatus) { + // 当高频返回autopilot 2时,不重复调用订单状态变更 + mPrevAPStatus = state; // 每个状态单独赋值,解决无订单时已经是2的状态导致的新订单来时无法进入此逻辑更新状态 - startServicePilotDone(); + TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestartAutopilot, true, + mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo); - TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(false, true, - mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo); - - if (FunctionBuildConfig.isDemoMode) { - // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true - FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; - CallerAutoPilotManager.INSTANCE.setDemoMode(true); - CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为true(到达出发点且已开启自动驾驶)"); + if (FunctionBuildConfig.isDemoMode) { + // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotManager.INSTANCE.setDemoMode(true); + CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为true(到达出发点且已开启自动驾驶)"); + } } - } else if (mCurrentOCHOrder != null - && getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToEnd - && state != mPrevAPStatus) { - mPrevAPStatus = state; - // 接管后再次启动成功埋点 - TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(true, true, - mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo); } } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { mPrevAPStatus = state; diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java index f40200dc4c..3f2cdbd2ca 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java @@ -87,10 +87,9 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS /** * 开启自动驾驶 - * @param isRestart 是否是接管后重启自动驾驶 */ - public void startAutoPilot(boolean isRestart) { - TaxiModel.getInstance().startAutoPilot(isRestart); + public void startAutoPilot() { + TaxiModel.getInstance().startAutoPilot(); } /** diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiFragment.java index e7c81a0a9d..43db7243a5 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiFragment.java @@ -63,7 +63,7 @@ public class TaxiFragment extends BaseTaxiTabFragment { if (!isStarting){ - mPresenter.startAutoPilot(false); + mPresenter.startAutoPilot(); startOrStopLoadingAnim(true); } TaxiModel.getInstance().setOnTheWayToEndStation(); diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java index d0a2808a54..797a79d5e6 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java @@ -1,17 +1,19 @@ package com.mogo.och.taxi.utils; +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI; + import android.text.TextUtils; import com.mogo.cloud.passport.MoGoAiCloudClientConfig; import com.mogo.commons.debug.DebugConfig; import com.mogo.eagle.core.data.app.AppConfigInfo; import com.mogo.eagle.core.function.call.analytics.AnalyticsManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.util.DateTimeUtils; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.och.taxi.constant.TaxiConst; import java.util.HashMap; -import java.util.Map; /** * OCH Taxi埋点工具 @@ -63,6 +65,8 @@ public class TaxiAnalyticsManager { mStartAutopilotParams.put(TaxiConst.EVENT_PARAM_END_NAME, endName); mStartAutopilotParams.put(TaxiConst.EVENT_PARAM_ORDER_NUMBER, orderNo); +// CallerLogger.INSTANCE.d(M_TAXI + "埋点==","restart = "+restart+", send= "+send); + if (send) { // 开启成功,上报埋点 if (startAutopilotRunnable != null && From dbd71ee4a2a8d1d8eedb31125c3951a7ca6dcdc8 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Thu, 21 Jul 2022 16:59:04 +0800 Subject: [PATCH 22/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加判断,修复偶现window初始值为0的情况 --- .../badcase/biz/AIDataCollectWindow.kt | 4 +++- .../badcase/biz/InitiativeBadCaseWindow.kt | 4 +++- .../badcase/biz/PassiveBadCaseWindow.kt | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt index 8004d73182..a34fdb07f8 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt @@ -101,7 +101,9 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener tvCollectReport = mFloatLayout.findViewById(R.id.tvCollectReport) tvCollectCancel = mFloatLayout.findViewById(R.id.tvCollectCancel) - + if(BadCaseConfig.windowNum<1){ + BadCaseConfig.windowNum = 1 + } tvCollectNum.text = BadCaseConfig.windowNum.toString() BadCaseConfig.windowNum++ tvCollectTime.text ="时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index 1db9bb90cd..66e2f3c9cd 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -121,7 +121,9 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList tvInitiativeReport = mFloatLayout.findViewById(R.id.tvInitiativeReport) tvInitiativeCancel = mFloatLayout.findViewById(R.id.tvInitiativeCancel) - + if(BadCaseConfig.windowNum<1){ + BadCaseConfig.windowNum = 1 + } tvInitiativeNum.text = BadCaseConfig.windowNum.toString() BadCaseConfig.windowNum++ tvInitiativeTime.text = "时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index ff05c2fdb1..eaa36ce6d0 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -107,6 +107,9 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene tvPassiveReport = mFloatLayout.findViewById(R.id.tvPassiveReport) tvPassiveCancel = mFloatLayout.findViewById(R.id.tvPassiveCancel) flReasonLayout = mFloatLayout.findViewById(R.id.flReasonLayout) + if(BadCaseConfig.windowNum<1){ + BadCaseConfig.windowNum = 1 + } tvPassiveNum.text = BadCaseConfig.windowNum.toString() BadCaseConfig.windowNum++ tvPassiveTime.text = "时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" From 80faf9754b80b65900c05973f9dc60b1ed16df83 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Thu, 21 Jul 2022 17:26:09 +0800 Subject: [PATCH 23/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复上传COS时的内存泄漏问题 --- .../badcase/biz/InitiativeBadCaseWindow.kt | 2 +- .../badcase/biz/PassiveBadCaseWindow.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index 66e2f3c9cd..ee079ec0be 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -240,7 +240,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList val singlePath = "/mnt/sdcard/mogo/DataCollection/${audioFileName}.wav" val file = File(singlePath) if(file.exists()){ - LogInfoManagerFactory.createAudioUpload(mActivity,"Audio",singlePath, + LogInfoManagerFactory.createAudioUpload(mActivity.applicationContext,"Audio",singlePath, object : OnUploadListener { override fun onUploadSuccess(filePath: String, downloadUrl: String) { CallerLogger.d("$M_DEVA$TAG", "语音文件上传成功:downloadUrl=$downloadUrl") diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt index eaa36ce6d0..55693b0086 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/PassiveBadCaseWindow.kt @@ -194,7 +194,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene val singlePath = "/mnt/sdcard/mogo/DataCollection/${audioFileName}.wav" val file = File(singlePath) if(file.exists()){ - LogInfoManagerFactory.createAudioUpload(mActivity,"Audio",singlePath, + LogInfoManagerFactory.createAudioUpload(mActivity.applicationContext,"Audio",singlePath, object : OnUploadListener { override fun onUploadSuccess(filePath: String, downloadUrl: String) { CallerLogger.d("$M_DEVA$TAG", "语音文件上传成功:downloadUrl=$downloadUrl") From a594ad2092ca19f1db83d7317fd270a001e538e3 Mon Sep 17 00:00:00 2001 From: wangmingjun Date: Thu, 21 Jul 2022 19:50:27 +0800 Subject: [PATCH 24/27] =?UTF-8?q?[282=20taxi=E5=8F=B8=E6=9C=BA=E7=AB=AF]?= =?UTF-8?q?=20=E5=A4=84=E7=90=86=E5=81=B6=E7=8E=B0=E5=86=85=E5=AD=98?= =?UTF-8?q?=E6=B3=84=E6=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/och/bus/presenter/BusLinePresenter.java | 5 ++++- .../com/mogo/och/bus/ui/BusSwitchLineActivity.java | 12 ++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java index dd0b333e67..c2f6fb57da 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java @@ -64,6 +64,10 @@ public class BusLinePresenter extends Presenter implements IB BusLineModel.getInstance().commitSwitchLineId(lineId); } + public void removeListener(){ + BusLineModel.getInstance().setBusLinesCallback(null); + } + public void queryBusRoutes(){ BusOrderModel.getInstance().queryBusRoutes(); } @@ -71,6 +75,5 @@ public class BusLinePresenter extends Presenter implements IB @Override public void onDestroy(@NonNull LifecycleOwner owner) { super.onDestroy(owner); - BusLineModel.getInstance().setBusLinesCallback(null); } } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java index d79dac12d9..847071ba49 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java @@ -79,7 +79,7 @@ public class BusSwitchLineActivity extends MvpActivity Date: Thu, 21 Jul 2022 20:31:18 +0800 Subject: [PATCH 25/27] =?UTF-8?q?[282=20taxi=E4=B9=98=E5=AE=A2=E5=B1=8F]?= =?UTF-8?q?=20=E5=A4=84=E7=90=86=E5=90=AF=E5=8A=A8=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=A9=BE=E9=A9=B6=E6=8C=89=E9=92=AE=E5=8D=A1=E9=A1=BF=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/och/taxi/model/TaxiModel.java | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) 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 3f672cc3b6..8b03f98c22 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 @@ -1015,7 +1015,12 @@ public class TaxiModel { if (getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToStart) { judgeStartStation(location); } + if (getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToEnd && + mPrevAPStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ + judgeEndStation(location); + } } + mLongitude = location.getLongitude(); mLatitude = location.getLatitude(); if (mControllerStatusCallback != null) { @@ -1024,6 +1029,37 @@ public class TaxiModel { } }; + private void judgeEndStation(Location location) { + if (mCurrentOCHOrder == null || mCurrentOCHOrder.endSiteGcjPoint == null + || mCurrentOCHOrder.endSiteGcjPoint.size() < 2) { + return; + } + double startLon = mCurrentOCHOrder.endSiteGcjPoint.get(0); + double startLat = mCurrentOCHOrder.endSiteGcjPoint.get(1); + double distance = CoordinateUtils.calculateLineDistance( + startLon, startLat, + location.getLongitude(), location.getLatitude()); + + CallerLogger.INSTANCE.i(M_TAXI + TAG, "judgeEndStation() distance = " + distance); + + if (distance > TaxiConst.ARRIVE_AT_START_STATION_DISTANCE) { + distance = CoordinateUtils.calculateLineDistance(startLon, startLat, + CallerAutoPilotStatusListenerManager.INSTANCE.getCurWgs84Lon(), + CallerAutoPilotStatusListenerManager.INSTANCE.getCurWgs84Lat()); + } + + if (distance <= TaxiConst.ARRIVE_AT_START_STATION_DISTANCE) { + if (!checkCurrentOCHOrder() + || (getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)) { + CallerLogger.INSTANCE.i(M_TAXI + TAG, "order exception or order ArriveAtEnd"); + return; + } + arriveTerminal(); + return; + } + + } + /** * 订单流转debug START */ @@ -1134,10 +1170,8 @@ public class TaxiModel { || (getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)) { return; } - if (DebugConfig.isDebug()) { - // ToastUtils.showShort("到达目的地"); - } arriveTerminal(); + if (FunctionBuildConfig.isDemoMode) { // 当美化模式(演示模式)开启时: 到达目的地,置false FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; From e33c8bb78d4ba361081abbc5a2c1e9b18fa90721 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Fri, 22 Jul 2022 13:00:47 +0800 Subject: [PATCH 26/27] BadCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复主动点击两次采集,出来两个弹窗后,在第2个弹窗点击上报,上报成功后,又收到回调和弹窗 --- .../badcase/biz/AIDataCollectWindow.kt | 39 +++++++----------- .../badcase/biz/InitiativeBadCaseWindow.kt | 40 ++++++++----------- 2 files changed, 31 insertions(+), 48 deletions(-) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt index a34fdb07f8..c841efd260 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/AIDataCollectWindow.kt @@ -19,6 +19,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.util.AppUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.TimeUtils import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.zhjt.mogo_core_function_devatools.R @@ -61,7 +62,9 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener private lateinit var tvCollectCancel: TextView //取消按钮 private var collectReason: String = "大型车:大货、大巴、特种车辆" + @Volatile private var recordKey: String?=null //录制bag包key + @Volatile private var recordFileName: String?=null //录制文件包名 private var longitude: Double?=null private var latitude: Double?=null @@ -108,9 +111,9 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener BadCaseConfig.windowNum++ tvCollectTime.text ="时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" //采集结果回调监听 - CallerAutopilotRecordListenerManager.addListener(TAG,this) + CallerAutopilotRecordListenerManager.addListener(this.hashCode().toString(),this) // 添加 ADAS车辆状态&定位 监听 - CallerAutopilotCarStatusListenerManager.addListener(TAG, this) + CallerAutopilotCarStatusListenerManager.addListener(this.hashCode().toString(), this) //开始录制AI数据采集Bag包 CallerAutoPilotManager.recordPackage( 99, @@ -265,28 +268,16 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") - if(recordKey==null){ - recordKey = recordPanel.key.toString() - BadCaseConfig.recordKeyList.add(recordPanel.key) - } - if(recordFileName==null){ - recordFileName = recordPanel.filename + ThreadUtils.runOnUiThread{ + if(recordKey==null){ + recordKey = recordPanel.key.toString() + BadCaseConfig.recordKeyList.add(recordPanel.key) + } + if(recordFileName==null){ + recordFileName = recordPanel.filename + } } -// when(recordPanel.stat){ -// 100, 101 ->{ -// //成功结束录制 -// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") -// } -// 300 ->{ -// //开始录制 -// -// } -// 200 ->{ -// //录制失败 -// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") -// } -// } } private fun setRadioButtonStatus(largeCarStatus: Boolean,trafficLightStatus: Boolean,waterStatus: Boolean, @@ -338,9 +329,9 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener fun hideFloatWindow() { //注销采集结果回调监听 - CallerAutopilotRecordListenerManager.removeListener(TAG) + CallerAutopilotRecordListenerManager.removeListener(this.hashCode().toString()) // 移除 ADAS车辆状态&定位 监听 - CallerAutopilotCarStatusListenerManager.removeListener(TAG) + CallerAutopilotCarStatusListenerManager.removeListener(this.hashCode().toString()) if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout) } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt index ee079ec0be..68670208ff 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/InitiativeBadCaseWindow.kt @@ -22,6 +22,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA import com.mogo.eagle.core.utilcode.mogo.toast.TipToast import com.mogo.eagle.core.utilcode.util.AppUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.TimeUtils import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.zhidao.loglib.call.LogInfoManagerFactory @@ -78,7 +79,9 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList private var audioFileName:String?=null //录音文件名称 private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签 + @Volatile private var recordKey: String?=null //录制bag包key + @Volatile private var recordFileName: String?=null //录制文件包名 private var longitude: Double?=null private var latitude: Double?=null @@ -130,9 +133,9 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList tvInitiativeIdentity.text = "身份:${BadCaseConfig.identity}" //采集结果回调监听 - CallerAutopilotRecordListenerManager.addListener(TAG,this) + CallerAutopilotRecordListenerManager.addListener(this.hashCode().toString(),this) // 添加 ADAS车辆状态&定位 监听 - CallerAutopilotCarStatusListenerManager.addListener(TAG, this) + CallerAutopilotCarStatusListenerManager.addListener(this.hashCode().toString(), this) //开启录包 CallerAutoPilotManager.recordPackage(BadCaseConfig.type, Random(SystemClock.elapsedRealtime()).nextInt(), @@ -329,9 +332,9 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList fun hideFloatWindow() { //注销采集结果回调监听 - CallerAutopilotRecordListenerManager.removeListener(TAG) + CallerAutopilotRecordListenerManager.removeListener(this.hashCode().toString()) // 移除 ADAS车辆状态&定位 监听 - CallerAutopilotCarStatusListenerManager.removeListener(TAG) + CallerAutopilotCarStatusListenerManager.removeListener(this.hashCode().toString()) if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout) } @@ -356,27 +359,16 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") - if(recordKey==null){ - recordKey = recordPanel.key.toString() - BadCaseConfig.recordKeyList.add(recordPanel.key) + ThreadUtils.runOnUiThread { + if(recordKey==null){ + recordKey = recordPanel.key.toString() + BadCaseConfig.recordKeyList.add(recordPanel.key) + } + if(recordFileName==null){ + recordFileName = recordPanel.filename + } } - if(recordFileName==null){ - recordFileName = recordPanel.filename - } -// when(recordPanel.stat){ -// 100, 101 ->{ -// //成功结束录制 -// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制成功") -// } -// 300 ->{ -// //开始录制 -// -// } -// 200 ->{ -// //录制失败 -// TipToast.shortTip("${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}:bag录制失败") -// } -// } + } fun setClickListener(clickListener: ClickListener) { From 4bf8e215446d284753e4f2dad9fac0340658e1c7 Mon Sep 17 00:00:00 2001 From: xuxinchao <13522809046@163.com> Date: Mon, 25 Jul 2022 18:08:24 +0800 Subject: [PATCH 27/27] IPC Report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 异常上报弹窗改版,根据Result区分出Error和Warning --- .../core/function/report/IPCReportManager.kt | 43 ++++++++-- .../core/function/hmi/ui/MoGoHmiFragment.kt | 30 ++++--- .../hmi/ui/setting/IPCReportWindow.kt | 40 ++++++++-- .../res/drawable-xxhdpi/icon_ipc_close.png | Bin 0 -> 7314 bytes .../main/res/drawable/ipc_error_tab_bg.xml | 9 +++ .../src/main/res/layout/item_ipc_report.xml | 24 +++--- .../src/main/res/layout/view_ipc_report.xml | 74 ++++++++++-------- .../api/hmi/warning/IMoGoWaringProvider.kt | 6 +- .../function/call/hmi/CallerHmiManager.kt | 8 +- 9 files changed, 159 insertions(+), 75 deletions(-) create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ipc_close.png create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/res/drawable/ipc_error_tab_bg.xml diff --git a/core/function-impl/mogo-core-function-check/src/main/java/com/mogo/eagle/core/function/report/IPCReportManager.kt b/core/function-impl/mogo-core-function-check/src/main/java/com/mogo/eagle/core/function/report/IPCReportManager.kt index 1e158f6777..899ee755a8 100644 --- a/core/function-impl/mogo-core-function-check/src/main/java/com/mogo/eagle/core/function/report/IPCReportManager.kt +++ b/core/function-impl/mogo-core-function-check/src/main/java/com/mogo/eagle/core/function/report/IPCReportManager.kt @@ -16,13 +16,23 @@ import mogo_msg.MogoReportMsg */ class IPCReportManager : IMoGoAutopilotStatusListener { - private var ipcReportList = arrayListOf() + private var ipcErrorReportList = arrayListOf() //错误上报列表 + private var ipcWarningReportList = arrayListOf() //警告上报列表 companion object{ const val TAG ="IPCReportManager" val INSTANCE: IPCReportManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { IPCReportManager() } + //Warning + const val RESULT_AUTOPILOT_INFERIOR = "RESULT_AUTOPILOT_INFERIOR" + const val RESULT_SHOW_WARNING = "RESULT_SHOW_WARNING" + const val RESULT_REMOTEPILOT_INFERIOR = "RESULT_REMOTEPILOT_INFERIOR" + //Error + const val RESULT_AUTOPILOT_DISABLE = "RESULT_AUTOPILOT_DISABLE" + const val RESULT_AUTOPILOT_SYSTEM_UNSTARTED = "RESULT_AUTOPILOT_SYSTEM_UNSTARTED" + const val RESULT_REMOTEPILOT_DISABLE = "RESULT_REMOTEPILOT_DISABLE" + } fun initServer(){ @@ -38,17 +48,38 @@ class IPCReportManager : IMoGoAutopilotStatusListener { */ override fun onAutopilotGuardian(guardianInfo: MogoReportMsg.MogoReportMessage?) { guardianInfo?.let{ - if(it.level=="error"){ - if(ipcReportList.size>19){ - ipcReportList.removeLast() + + //Error 弹窗并有提示音 + if(it.resultList.contains(RESULT_AUTOPILOT_DISABLE) + || it.resultList.contains(RESULT_AUTOPILOT_SYSTEM_UNSTARTED) + || it.resultList.contains(RESULT_REMOTEPILOT_DISABLE)){ + if(ipcErrorReportList.size>19){ + ipcErrorReportList.removeLast() } - ipcReportList.add(0, + ipcErrorReportList.add(0, ReportEntity(TimeUtils.millis2String(System.currentTimeMillis()), it.src,it.level,it.msg,it.code,it.resultList,it.actionsList)) //当前不处于美化模式时,展示监控节点上报 if(!FunctionBuildConfig.isDemoMode){ if(FunctionBuildConfig.isReportWarning){ - CallerHmiManager.showIPCReportWindow(ipcReportList) + CallerHmiManager.showIPCReportWindow(ipcErrorReportList,ipcWarningReportList,1) + } + } + } + //Warning 不弹窗也不会有提示音 + else if(it.resultList.contains(RESULT_AUTOPILOT_INFERIOR) + || it.resultList.contains(RESULT_SHOW_WARNING) + || it.resultList.contains(RESULT_REMOTEPILOT_INFERIOR)){ + if(ipcWarningReportList.size>19){ + ipcWarningReportList.removeLast() + } + ipcWarningReportList.add(0, + ReportEntity(TimeUtils.millis2String(System.currentTimeMillis()), + it.src,it.level,it.msg,it.code,it.resultList,it.actionsList)) + //当前不处于美化模式时,展示监控节点上报 + if(!FunctionBuildConfig.isDemoMode){ + if(FunctionBuildConfig.isReportWarning){ + CallerHmiManager.showIPCReportWindow(ipcErrorReportList,ipcWarningReportList,2) } } } diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index 8d0f923de7..22497d9f1a 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -281,24 +281,28 @@ import java.util.* /** * 展示工控机监控上报数据 - * @param reportList 上报数据列表 + * @param errorReportList 错误级别上报数据列表 + * @param warningReportList 提醒级别上报数据列表 + * @param reportLevel 1:error级别 2:warning级别 */ - override fun showIPCReportWindow(reportList: ArrayList) { + override fun showIPCReportWindow(errorReportList: ArrayList,warningReportList: ArrayList,reportLevel: Int) { ThreadUtils.runOnUiThread{ - if(ipcReportWindow==null){ - ipcReportWindow= activity?.let { IPCReportWindow(it) } - ipcReportWindow?.setClickListener(object: IPCReportWindow.ClickListener{ - override fun closeWindow() { - ipcReportWindow?.hideFloatWindow() - ipcReportWindow =null + if(reportLevel == 1){ + if(ipcReportWindow==null){ + ipcReportWindow= activity?.let { IPCReportWindow(it) } + ipcReportWindow?.setClickListener(object: IPCReportWindow.ClickListener{ + override fun closeWindow() { + ipcReportWindow?.hideFloatWindow() + ipcReportWindow =null + } + }) + ipcReportWindow?.let { + SoundUtils.playRing(requireContext()) } - }) - ipcReportWindow?.let { - SoundUtils.playRing(requireContext()) } + ipcReportWindow?.showFloatWindow() } - ipcReportWindow?.showFloatWindow() - ipcReportWindow?.refreshData(reportList) + ipcReportWindow?.refreshData(errorReportList,warningReportList,reportLevel) } } diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/IPCReportWindow.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/IPCReportWindow.kt index aa4f8277a3..1c74fbaf9d 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/IPCReportWindow.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/IPCReportWindow.kt @@ -5,6 +5,7 @@ import android.graphics.PixelFormat import android.util.DisplayMetrics import android.view.* import android.widget.ImageView +import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.mogo.eagle.core.data.report.ReportEntity @@ -23,6 +24,8 @@ class IPCReportWindow constructor(activity: Activity) : View.OnTouchListener{ private var mWindowManager: WindowManager? = null private lateinit var rvIPCReport: RecyclerView private lateinit var ivIpcClose: ImageView + private lateinit var tvIpcErrorTab: TextView + private lateinit var tvIpcWarningTab: TextView private var ipcReportAdapter: IPCReportAdapter?=null private lateinit var mFloatLayout: View @@ -35,6 +38,9 @@ class IPCReportWindow constructor(activity: Activity) : View.OnTouchListener{ private var clickListener: ClickListener? = null + private var ipcErrorReportList: List? = null //错误上报列表 + private var ipcWarningReportList: List? = null//警告上报列表 + init { initFloatWindow(); } @@ -44,28 +50,47 @@ class IPCReportWindow constructor(activity: Activity) : View.OnTouchListener{ mFloatLayout.setOnTouchListener(this) rvIPCReport= mFloatLayout.findViewById(R.id.rv_ipc_report) ivIpcClose = mFloatLayout.findViewById(R.id.iv_ipc_close) + tvIpcErrorTab = mFloatLayout.findViewById(R.id.tv_ipc_error_tab) + tvIpcWarningTab = mFloatLayout.findViewById(R.id.tv_ipc_warning_tab) mWindowParams = WindowManager.LayoutParams() mWindowManager = mActivity.windowManager mWindowParams?.let { it.format = PixelFormat.RGBA_8888 it.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE it.gravity = Gravity.START or Gravity.TOP - it.width = 600 - it.height = 800 - it.alpha = 0.9f + it.width = 924 + it.height = 444 + it.alpha = 1.0f } ipcReportAdapter = IPCReportAdapter() rvIPCReport.layoutManager = WrapContentLinearLayoutManager(mActivity, LinearLayoutManager.VERTICAL,false) rvIPCReport.adapter = ipcReportAdapter - + //关闭按钮 ivIpcClose.setOnClickListener { clickListener?.closeWindow() } + //错误列表 + tvIpcErrorTab.setOnClickListener { + ipcReportAdapter?.setData(ipcErrorReportList) + ipcReportAdapter?.notifyDataSetChanged() + } + //预警列表 + tvIpcWarningTab.setOnClickListener { + ipcReportAdapter?.setData(ipcWarningReportList) + ipcReportAdapter?.notifyDataSetChanged() + } + } - fun refreshData(data:List){ - ipcReportAdapter?.setData(data) + fun refreshData(errorReportList:List,warningReportList:List,reportLevel: Int){ + if(reportLevel == 1){ + ipcReportAdapter?.setData(errorReportList) + ipcErrorReportList = errorReportList + }else{ + ipcReportAdapter?.setData(warningReportList) + ipcWarningReportList = warningReportList + } ipcReportAdapter?.notifyDataSetChanged() } @@ -103,7 +128,8 @@ class IPCReportWindow constructor(activity: Activity) : View.OnTouchListener{ // 默认固定位置,靠屏幕右边缘的中间 mWindowManager!!.defaultDisplay.getMetrics(metrics) mWindowParams!!.x = metrics.widthPixels - mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity) +// mWindowParams!!.y = metrics.heightPixels / 2 - getSysBarHeight(mActivity) + mWindowParams!!.y = metrics.heightPixels - getSysBarHeight(mActivity)-100 mWindowManager!!.addView(mFloatLayout, mWindowParams) } } diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ipc_close.png b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_ipc_close.png new file mode 100644 index 0000000000000000000000000000000000000000..99ed84f46440280b6ce36b511f2a55612679c94f GIT binary patch literal 7314 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

XhNAI=aYXUGm(olO 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 literal 0 HcmV?d00001 diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/ipc_error_tab_bg.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/ipc_error_tab_bg.xml new file mode 100644 index 0000000000..58a14ac5c7 --- /dev/null +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/ipc_error_tab_bg.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ipc_report.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ipc_report.xml index b055c72d90..1710d1291f 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ipc_report.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ipc_report.xml @@ -11,7 +11,7 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:text="@string/ipc_report_time" android:layout_marginTop="10dp" android:layout_marginStart="10dp" @@ -24,7 +24,7 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toRightOf="@id/tvReportTimeTitle" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:layout_marginTop="10dp" android:layout_marginEnd="10dp" /> @@ -36,7 +36,7 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@id/tvReportTimeTitle" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:text="@string/ipc_report_type" android:layout_marginTop="10dp" android:layout_marginStart="10dp" @@ -49,8 +49,8 @@ app:layout_constraintTop_toTopOf="@id/tvReportResultTitle" app:layout_constraintLeft_toRightOf="@id/tvReportResultTitle" app:layout_constraintRight_toRightOf="parent" - android:textColor="@color/color_FF0006" - android:textSize="14sp" + android:textColor="@color/color_FFFFFF" + android:textSize="16sp" android:minLines="1" android:layout_marginEnd="10dp" /> @@ -62,7 +62,7 @@ app:layout_constraintTop_toBottomOf="@id/tvReportResultContent" app:layout_constraintLeft_toLeftOf="parent" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:text="@string/ipc_report_msg" android:layout_marginTop="10dp" android:layout_marginStart="10dp" @@ -76,8 +76,8 @@ app:layout_constraintLeft_toRightOf="@id/tvReportMsgTitle" app:layout_constraintRight_toRightOf="parent" android:minLines="1" - android:textColor="@color/color_FF0006" - android:textSize="14sp" + android:textColor="@color/color_FFFFFF" + android:textSize="16sp" android:layout_marginEnd="10dp" /> @@ -88,7 +88,7 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@id/tvReportMsgContent" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:text="@string/ipc_report_action" android:layout_marginTop="10dp" android:layout_marginStart="10dp" @@ -103,7 +103,7 @@ app:layout_constraintRight_toRightOf="parent" android:minLines="1" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:layout_marginEnd="10dp" /> @@ -113,8 +113,10 @@ android:background="#F0F0F0" app:layout_constraintTop_toBottomOf="@id/tvReportActionContent" android:textColor="@color/color_FFFFFF" - android:textSize="14sp" + android:textSize="16sp" android:layout_marginTop="5dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" /> \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_ipc_report.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_ipc_report.xml index 066d30f6db..101153a73c 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_ipc_report.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_ipc_report.xml @@ -1,49 +1,57 @@ - - - - - - - - + app:roundLayoutRadius="40px"> + + + + + + + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/tv_ipc_error_tab" + app:layout_constraintBottom_toBottomOf="parent" + /> diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt index c766cc953d..319355e34a 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt @@ -243,9 +243,11 @@ interface IMoGoWaringProvider : IMoGoHmiViewProxy { /** * 展示工控机监控上报数据 - * @param reportList 上报数据列表 + * @param errorReportList 错误级别上报数据列表 + * @param warningReportList 提醒级别上报数据列表 + * @param reportLevel 1:error级别 2:warning级别 */ - fun showIPCReportWindow(reportList: ArrayList) + fun showIPCReportWindow(errorReportList: ArrayList,warningReportList: ArrayList,reportLevel: Int) fun showVideoDialog(url: String, isFlvUrl: Boolean) } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt index 6efce9500d..5079e905b4 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt @@ -352,10 +352,12 @@ object CallerHmiManager : CallerBase() { /** * 展示工控机监控上报数据 - * @param reportList 上报数据列表 + * @param errorReportList 错误级别上报数据列表 + * @param warningReportList 提醒级别上报数据列表 + * @param reportLevel 1:error级别 2:warning级别 */ - fun showIPCReportWindow(reportList: ArrayList){ - waringProviderApi?.showIPCReportWindow(reportList) + fun showIPCReportWindow(errorReportList: ArrayList,warningReportList: ArrayList,reportLevel: Int){ + waringProviderApi?.showIPCReportWindow(errorReportList,warningReportList,reportLevel) } @JvmOverloads