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 fc34e3643c..5401c0a2cf 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 @@ -205,7 +205,7 @@ class DevaToolsProvider : IDevaToolsProvider, IAppStateListener { // apmEnvProvider.init(if(DebugConfig.isDebug()) "0" else "1", "${ DebugConfig.getNetMode() }", mDockerVersion ?: "") BadCaseManager.init(mContext!!) ColdStartManager.init(mContext!!) -// OTAUpgradeManager.init(mContext!!) + OTAUpgradeManager.init(mContext!!) if (DebugConfig.isDebug()) { SdtManager.init(mContext!!, true, DetectResultImpl()) } 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 9962aa08aa..9cb2badf9e 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 @@ -156,6 +156,10 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis BadCaseConfig.setStartTime(currentDay) //删除前一天的接管记录 CallerTakeOverManager.deleteAllRecord(context) + //遍历是否有非当日的文件并删除 + RecordBitmapUtils.deleteExpiredFile(currentDay,"FrontCamera") + RecordBitmapUtils.deleteExpiredFile(currentDay,"RearCamera") + RecordBitmapUtils.deleteExpiredFile(currentDay,"MapScreen") } } @@ -417,7 +421,6 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { super.onAutopilotRecordResult(recordPanel) CallerLogger.d("$M_DEVA$TAG", "recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type}") - CallerLogger.i(TestTag,"onAutopilotRecordResult receive recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}") if(BadCaseConfig.notDisplayBagWindow){ //此时点击主动录包按钮,不能展示上报弹窗,需要在此处做主动录包弹窗中的一些逻辑 //开始录制 @@ -441,22 +444,18 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis CallerLogger.i(TestTag,"onAutopilotRecordResult contains recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}") //目前type == 3包括接管被动录包和其他一些故障录包 if(recordPanel.type == 3){ - CallerLogger.i(TestTag,"onAutopilotRecordResult 符合type=3 recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}") //录包成功 if(recordPanel.stat == 100 || recordPanel.stat == 101){ - CallerLogger.i(TestTag,"onAutopilotRecordResult 录包成功 recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}") val activity = AppStateManager.currentActivity() if (activity !is AppCompatActivity) { return } - CallerLogger.i(TestTag,"activity符合条件") val geocodeSearch = GeocodeSearch(activity) geocodeSearch.setOnGeocodeSearchListener(object: GeocodeSearch.OnGeocodeSearchListener { override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult?, p1: Int) { regeocodeResult?.regeocodeAddress?.formatAddress?.let { address = it } - CallerLogger.i(TestTag,"onRegeocodeSearched address=${address}") val takeOverRecordInfo = TakeOverRecordInfo(System.currentTimeMillis(), address,level1Id,level2Id,level3Id, level1Name, level2Name, level3Name, @@ -477,12 +476,12 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis val q = RegeocodeQuery(latLon,200f,GeocodeSearch.AMAP) geocodeSearch.getFromLocationAsyn(q) takeOverBagId = recordPanel.key -// //触发域控前后120度摄像头截图和高精地图截图 -// CallerAutoPilotControlManager.sendCaptureImgReqOnTakeOver(recordPanel.key) -// //高精地图屏幕截图 -// CallerMapScreenListenerManager.addListener(TAG,this) -// //开启高精地图截图 -// CallerMapUIServiceManager.getMapUIController()?.getMapScreenShot() + //触发域控前后120度摄像头截图和高精地图截图 + CallerAutoPilotControlManager.sendCaptureImgReqOnTakeOver(recordPanel.key) + //高精地图屏幕截图 + CallerMapScreenListenerManager.addListener(TAG,this) + //开启高精地图截图 + CallerMapUIServiceManager.getMapUIController()?.getMapScreenShot() } } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/util/RecordBitmapUtils.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/util/RecordBitmapUtils.kt index b65884d61d..a4864f5089 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/util/RecordBitmapUtils.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/util/RecordBitmapUtils.kt @@ -36,9 +36,11 @@ object RecordBitmapUtils { /** * 删除过期文件夹 + * @param currentDay 要删除的文件日期 + * @param deleteFile 要删除的文件目录 */ - fun deleteExpiredFile(currentDay: String){ - val checkFileName = Environment.getExternalStorageDirectory().absolutePath + File.separator+ "MapScreen" + fun deleteExpiredFile(currentDay: String,deleteFile: String){ + val checkFileName = Environment.getExternalStorageDirectory().absolutePath + File.separator+ deleteFile val checkFileFolder = File(checkFileName) if(checkFileFolder.exists()){ checkFileFolder.listFiles()?.forEach {dir-> diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverReasonWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverReasonWindow.kt index c57fd8122b..d0dea26197 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverReasonWindow.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverReasonWindow.kt @@ -3,7 +3,9 @@ package com.zhjt.mogo_core_function_devatools.workorder import android.annotation.SuppressLint import android.app.Activity import android.graphics.PixelFormat +import android.net.Uri import android.os.Bundle +import android.os.Environment import android.text.Editable import android.text.TextWatcher import android.util.DisplayMetrics @@ -41,13 +43,15 @@ import com.mogo.eagle.core.utilcode.util.BarUtils import com.mogo.eagle.core.utilcode.util.JsonParser import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.TimeUtils +import com.mogo.eagle.core.utilcode.util.TimeUtils.getMdFormat import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.tts.base.SpeechUtils 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.workorder.adapter.OrderReasonAdapter -import kotlin.math.absoluteValue +import java.io.File + /** * 接管原因编辑窗口 @@ -63,11 +67,7 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene private var mWindowParams: WindowManager.LayoutParams? = null private var mWindowManager: WindowManager? = null private lateinit var mFloatLayout: View - - private var mInViewX = 0f - private var mInViewY = 0f - private var mInScreenX = 0f - private var mInScreenY = 0f + private var takeOverSceneWindow: TakeOverSceneWindow ?= null // 语音听写对象 private var mIat: SpeechRecognizer? = null @@ -84,6 +84,9 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene private lateinit var tvTakeOverReason: AppCompatTextView private lateinit var etNoteInput: AppCompatEditText private lateinit var ivNoteAudio: ImageView + private lateinit var ivFrontCamera: ImageView + private lateinit var ivRearCamera: ImageView + private lateinit var ivMapScreen: ImageView private lateinit var tvTakeOverSave: TextView private lateinit var tvTakeOverCancel: TextView private lateinit var rvTakeOverList: RecyclerView @@ -132,7 +135,7 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene it.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL it.gravity = Gravity.START or Gravity.TOP it.width = 902 - it.height = 1530 + it.height = 1535 it.alpha = 1.0f } } @@ -143,6 +146,9 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene tvTakeOverReason = mFloatLayout.findViewById(R.id.tvTakeOverReason) etNoteInput = mFloatLayout.findViewById(R.id.etNoteInput) ivNoteAudio = mFloatLayout.findViewById(R.id.ivNoteAudio) + ivFrontCamera = mFloatLayout.findViewById(R.id.ivFrontCamera) + ivRearCamera = mFloatLayout.findViewById(R.id.ivRearCamera) + ivMapScreen = mFloatLayout.findViewById(R.id.ivMapScreen) tvTakeOverSave = mFloatLayout.findViewById(R.id.tvTakeOverSave) tvTakeOverCancel = mFloatLayout.findViewById(R.id.tvTakeOverCancel) rvTakeOverList = mFloatLayout.findViewById(R.id.rvTakeOverList) @@ -316,6 +322,13 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene } } + private fun showSceneWindow(frontCameraUri: Uri,rearCameraUri: Uri,mapScreenUri: Uri,currentItem: Int){ + if(takeOverSceneWindow == null){ + takeOverSceneWindow = TakeOverSceneWindow(mActivity) + } + takeOverSceneWindow?.showFloatWindow(frontCameraUri,rearCameraUri,mapScreenUri,currentItem) + } + private fun setAudio(status: Boolean){ if(status){ //开始录音 @@ -417,25 +430,6 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene @SuppressLint("ClickableViewAccessibility") override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean { -// when (motionEvent?.action) { -// MotionEvent.ACTION_DOWN -> { -// // 获取相对View的坐标,即以此View左上角为原点 -// mInViewX = motionEvent.x -// mInViewY = motionEvent.y -// // 获取相对屏幕的坐标,即以屏幕左上角为原点 -// mInScreenX = motionEvent.rawX -// mInScreenY = motionEvent.rawY -// } -// MotionEvent.ACTION_MOVE -> { -// // 更新浮动窗口位置参数 -// mInScreenX = motionEvent.rawX -// mInScreenY = motionEvent.rawY -// mWindowParams!!.x = (mInScreenX - mInViewX).toInt() -// mWindowParams!!.y = (mInScreenY - mInViewY).toInt() -// // 手指移动的时候更新小悬浮窗的位置 -// mWindowManager!!.updateViewLayout(mFloatLayout, mWindowParams) -// } -// } return true } @@ -457,6 +451,40 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene tvTakeOverTime.text = mActivity.resources.getString(R.string.take_over_time) + millis2String(mTakeOverRecordInfo.faultStartTime, TimeUtils.getHourMinSecondFormat()) } + //展示前向摄像头 + val frontCameraPath: String = ((Environment.getExternalStorageDirectory() + .absolutePath + File.separator) + + "FrontCamera" + File.separator + millis2String(System.currentTimeMillis(), getMdFormat()) + + File.separator + mTakeOverRecordInfo.bagId) + ".png" + val frontCameraUri = Uri.parse(frontCameraPath) + ivFrontCamera.setImageURI(frontCameraUri) + //展示后向摄像头 + val rearCameraPath: String = ((Environment.getExternalStorageDirectory() + .absolutePath + File.separator) + + "RearCamera" + File.separator + millis2String(System.currentTimeMillis(), getMdFormat()) + + File.separator + mTakeOverRecordInfo.bagId) + ".png" + val rearCameraUri = Uri.parse(rearCameraPath) + ivRearCamera.setImageURI(rearCameraUri) + //展示高精地图截图 + val mapScreenPath: String = ((Environment.getExternalStorageDirectory() + .absolutePath + File.separator) + + "MapScreen" + File.separator + millis2String(System.currentTimeMillis(), getMdFormat()) + + File.separator + mTakeOverRecordInfo.bagId) + ".png" + val mapScreenUri = Uri.parse(mapScreenPath) + ivMapScreen.setImageURI(mapScreenUri) + + //前向120°摄像头 + ivFrontCamera.setOnClickListener { + showSceneWindow(frontCameraUri,rearCameraUri,mapScreenUri,0) + } + //后向120°摄像头 + ivRearCamera.setOnClickListener { + showSceneWindow(frontCameraUri,rearCameraUri,mapScreenUri,1) + } + //高精地图截图 + ivMapScreen.setOnClickListener { + showSceneWindow(frontCameraUri,rearCameraUri,mapScreenUri,2) + } setWindowShowStatus(true) } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverSceneWindow.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverSceneWindow.kt new file mode 100644 index 0000000000..b4430a1172 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/TakeOverSceneWindow.kt @@ -0,0 +1,113 @@ +package com.zhjt.mogo_core_function_devatools.workorder + +import android.annotation.SuppressLint +import android.app.Activity +import android.graphics.PixelFormat +import android.net.Uri +import android.util.DisplayMetrics +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.WindowManager +import android.widget.ImageView +import androidx.viewpager.widget.ViewPager +import com.mogo.eagle.core.utilcode.util.BarUtils +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.zhjt.mogo_core_function_devatools.R +import com.zhjt.mogo_core_function_devatools.workorder.adapter.TakeOverSceneAdapter + +/** + * 场景图像查看窗口 + */ +class TakeOverSceneWindow constructor(activity: Activity) { + + companion object{ + const val TAG = "TakeOverSceneWindow" + } + + private var mActivity: Activity = activity + private var mWindowParams: WindowManager.LayoutParams? = null + private var mWindowManager: WindowManager? = null + private lateinit var mFloatLayout: View + private lateinit var vpSceneImage: ViewPager + private lateinit var ivSceneClose: ImageView + private lateinit var ivScenePrevious: ImageView + private lateinit var ivSceneNext: ImageView + private val takeOverSceneAdapter = TakeOverSceneAdapter() + private var currentIndex = 0 + + init { + initFloatWindow() + } + + private fun initFloatWindow(){ + mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_take_over_scene, null) as View + initView() + initEvent() + 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 = WindowManager.LayoutParams.MATCH_PARENT + it.height = 1535 + it.alpha = 1.0f + } + } + + private fun initView(){ + vpSceneImage = mFloatLayout.findViewById(R.id.vpSceneImage) + ivSceneClose = mFloatLayout.findViewById(R.id.ivSceneClose) + ivScenePrevious = mFloatLayout.findViewById(R.id.ivScenePrevious) + ivSceneNext = mFloatLayout.findViewById(R.id.ivSceneNext) + } + + private fun initEvent(){ + vpSceneImage.adapter =takeOverSceneAdapter + //关闭弹窗 + ivSceneClose.setOnClickListener { + hideFloatWindow() + } + //前一个场景 + ivScenePrevious.setOnClickListener { + if(currentIndex == 0){ + ToastUtils.showShort("没有上一个场景了") + }else{ + currentIndex = (currentIndex-1).coerceAtLeast(0) + vpSceneImage.currentItem = currentIndex + } + } + //后一个场景 + ivSceneNext.setOnClickListener { + if(currentIndex < 2){ + currentIndex = (currentIndex + 1).coerceAtMost(2) + vpSceneImage.currentItem = currentIndex + }else{ + ToastUtils.showShort("没有下一个场景了") + } + } + } + + @SuppressLint("SetTextI18n") + fun showFloatWindow(frontCameraUri: Uri, rearCameraUri: Uri, mapScreenUri: Uri, currentItem: Int) { + if (mFloatLayout.parent == null) { + val metrics = DisplayMetrics() + // 默认固定位置,靠屏幕右边缘的中间 + mWindowManager!!.defaultDisplay.getMetrics(metrics) + mWindowParams!!.x = 0 + mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight() + mWindowManager!!.addView(mFloatLayout, mWindowParams) + takeOverSceneAdapter.setSceneUri(frontCameraUri, rearCameraUri, mapScreenUri) + currentIndex = currentItem + vpSceneImage.currentItem = currentItem + } + } + + fun hideFloatWindow() { + if (mFloatLayout.parent != null){ + mWindowManager!!.removeView(mFloatLayout) + } + } + +} \ 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/workorder/adapter/TakeOverSceneAdapter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/adapter/TakeOverSceneAdapter.kt new file mode 100644 index 0000000000..f02a37b97b --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/workorder/adapter/TakeOverSceneAdapter.kt @@ -0,0 +1,69 @@ +package com.zhjt.mogo_core_function_devatools.workorder.adapter + +import android.net.Uri +import android.os.Environment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.viewpager.widget.PagerAdapter +import com.mogo.eagle.core.utilcode.util.TimeUtils.getMdFormat +import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String +import com.zhjt.mogo_core_function_devatools.R +import java.io.File + + +class TakeOverSceneAdapter: PagerAdapter() { + + private lateinit var mFrontCameraUri: Uri + private lateinit var mRearCameraUri: Uri + private lateinit var mMapScreenUri: Uri + + fun setSceneUri(frontCameraUri: Uri,rearCameraUri: Uri,mapScreenUri: Uri){ + mFrontCameraUri = frontCameraUri + mRearCameraUri = rearCameraUri + mMapScreenUri = mapScreenUri + } + + // 获取要滑动的控件的数量 + override fun getCount(): Int { + return 3 + } + + // 来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可 + override fun isViewFromObject(view: View, `object`: Any): Boolean { + return view == `object` + } + + // 当要显示的图片可以进行缓存的时候,会调用这个方法进行显示图片的初始化, + // 我们将要显示的ImageView加入到ViewGroup中,然后作为返回值返回即可 + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val inflater = LayoutInflater.from(container.context) + val view = inflater.inflate(R.layout.layout_scene_pager,container,false) + val sceneName: TextView = view.findViewById(R.id.tvSceneName) + val ivSceneImage: ImageView = view.findViewById(R.id.ivSceneImage) + when (position) { + 0 -> { + sceneName.text = container.resources.getString(R.string.take_over_front_camera) + ivSceneImage.setImageURI(mFrontCameraUri) + } + 1 -> { + sceneName.text = container.resources.getString(R.string.take_over_rear_camera) + ivSceneImage.setImageURI(mRearCameraUri) + } + else -> { + sceneName.text = container.resources.getString(R.string.take_over_map_screen) + ivSceneImage.setImageURI(mMapScreenUri) + } + } + container.addView(view) + return view + } + + // PagerAdapter只缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁 + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + container.removeView(`object` as View) + } + +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_close.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_close.png new file mode 100644 index 0000000000..84513b5885 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_close.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_left.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_left.png new file mode 100644 index 0000000000..ad46b155c6 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_left.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_right.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_right.png new file mode 100644 index 0000000000..b9c0a12a09 Binary files /dev/null and b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_scene_right.png differ diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bg_scene_name.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bg_scene_name.xml new file mode 100644 index 0000000000..dd0222ad49 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bg_scene_name.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_scene_pager.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_scene_pager.xml new file mode 100644 index 0000000000..d0dc4eebd0 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_scene_pager.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_take_over_reason.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_take_over_reason.xml index 2735fe0efb..70ad990d8d 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_take_over_reason.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/view_take_over_reason.xml @@ -145,6 +145,111 @@ android:contentDescription="@string/take_over_note_audio" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml index ba13a4df93..42e32d54ed 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml @@ -66,6 +66,13 @@ (选填) 手动输入 补充描述语音输入 + 场景图像 + 前向120°摄像头 + 后向120°摄像头 + 高精地图截图 + 上一个场景 + 关闭场景 + 下一个场景 上报 保存 取消 diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt index 551dfe6341..8fa7ff297c 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt @@ -18,6 +18,7 @@ import com.mogo.eagle.core.function.hmi.R import com.mogo.eagle.core.utilcode.kotlin.onClick import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.mogo.eagle.core.utilcode.util.SoundPoolUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.zhjt.mogo_core_function_devatools.status.StatusManager import com.zhjt.mogo_core_function_devatools.status.entity.AcceleratorStatus @@ -30,6 +31,7 @@ import com.zhjt.mogo_core_function_devatools.status.entity.IAutopilotBeforeLaunc import com.zhjt.mogo_core_function_devatools.status.entity.Status import com.zhjt.mogo_core_function_devatools.status.entity.SteerStatus import kotlinx.android.synthetic.main.view_start_autopilot_status.view.fSMStatusLayout +import kotlinx.android.synthetic.main.view_start_autopilot_status.view.ivFsmDemoModeError import kotlinx.android.synthetic.main.view_start_autopilot_status.view.iv_accelerator import kotlinx.android.synthetic.main.view_start_autopilot_status.view.iv_brake import kotlinx.android.synthetic.main.view_start_autopilot_status.view.iv_double_flash @@ -68,7 +70,8 @@ class StartAutoPilotStatusView @JvmOverloads constructor( } private val hasFSM by lazy { AtomicBoolean(true) } - + //是否进行了语音提示(当开启美化模式后,若fsm输出自车处于安全停车状态中提示音提示一次) + private var isAlreadyPrompted: Boolean = false init { LayoutInflater.from(context).inflate(R.layout.view_start_autopilot_status, this, true) @@ -87,9 +90,11 @@ class StartAutoPilotStatusView @JvmOverloads constructor( CallerLogger.i(TAG, "changeStatusContainer 切换展示,hasFSM=$hasFSMModule") if (hasFSMModule) { fSMStatusLayout?.visibility = View.VISIBLE + ivFsmDemoModeError?.visibility = View.GONE withoutFSMStatusLayout?.visibility = View.GONE } else { fSMStatusLayout?.visibility = View.GONE + ivFsmDemoModeError?.visibility = View.GONE withoutFSMStatusLayout?.visibility = View.VISIBLE } } @@ -104,11 +109,6 @@ class StartAutoPilotStatusView @JvmOverloads constructor( } hasFSM.set(newHasFSM) - if (FunctionBuildConfig.isDemoMode && status.isException()) { - // 美化模式下如果是异常的,修改成正常的 - status.state = FSMStateCode.ExistNormal - } - when (status.state) { FSMStateCode.UnKnown -> { fSMStatusLayout?.setOnClickListener(null) @@ -118,6 +118,8 @@ class StartAutoPilotStatusView @JvmOverloads constructor( R.drawable.icon_fsm_status_bg_unknown ) ) + ivFsmDemoModeError?.visibility = View.GONE + isAlreadyPrompted = false } FSMStateCode.NotExist -> { @@ -128,6 +130,8 @@ class StartAutoPilotStatusView @JvmOverloads constructor( R.drawable.icon_fsm_status_bg_unknown ) ) + ivFsmDemoModeError?.visibility = View.GONE + isAlreadyPrompted = false } FSMStateCode.ExistNormal -> { @@ -138,18 +142,41 @@ class StartAutoPilotStatusView @JvmOverloads constructor( R.drawable.icon_fsm_status_bg_normal ) ) + ivFsmDemoModeError?.visibility = View.GONE + isAlreadyPrompted = false } FSMStateCode.ExistError -> { - fSMStatusLayout?.onClick { - CallerHmiManager.showFSMExceptionStatusWindow(status.descList) - } - fSMStatusLayout?.setImageDrawable( - ContextCompat.getDrawable( - context, - R.drawable.icon_fsm_status_bg_error + if(FunctionBuildConfig.isDemoMode){ + fSMStatusLayout?.setOnClickListener(null) + fSMStatusLayout?.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_fsm_status_bg_normal + ) ) - ) + ivFsmDemoModeError?.visibility = View.VISIBLE + if(!isAlreadyPrompted){ + try { + SoundPoolUtils.getSoundPool().playSoundWithRedId(context,R.raw.weak_net_tips) + }catch (e: Exception){ + e.printStackTrace() + } + isAlreadyPrompted = true + } + }else{ + fSMStatusLayout?.onClick { + CallerHmiManager.showFSMExceptionStatusWindow(status.descList) + } + fSMStatusLayout?.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_fsm_status_bg_error + ) + ) + ivFsmDemoModeError?.visibility = View.GONE + isAlreadyPrompted = false + } } } notifyStatus(status.isException()) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/icon_fsm_demo_mode_error.png b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/icon_fsm_demo_mode_error.png new file mode 100644 index 0000000000..f61e1e87c5 Binary files /dev/null and b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/icon_fsm_demo_mode_error.png differ diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_car_info_tab.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_car_info_tab.xml index 214df8ce41..5a89b3bff5 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_car_info_tab.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_car_info_tab.xml @@ -194,7 +194,6 @@ app:layout_constraintBottom_toBottomOf="@+id/tvADVersion" app:layout_constraintRight_toRightOf="@+id/tvCarExit" app:layout_constraintTop_toTopOf="@+id/tvADVersion" - android:visibility="gone" /> + + 请联系管理员 关闭 + FSM美化模式状态下异常标识 + diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt index 40c67dccdb..e1e4b54f9a 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt @@ -11,6 +11,22 @@ import perception.FusionTrafficLightOuterClass */ interface IMoGoAutopilotIdentifyListener { + /** + * 判断是否有车龙 + */ + fun isLongVehicleQueue( + type: Int, + polygon: List? + ): Boolean { + // 检查 type 是否为 707 表示NED陈数据 + val isRoadCongested = type == 707 + // 检查 polygon 是否不为空且个数大于 1 + val hasEnoughPolygonPoints = (polygon?.size ?: 0) > 1 + // 同时满足两个条件 + return isRoadCongested && hasEnoughPolygonPoints + } + + /** * 识别交通元素数据发生更新 * diff --git a/libraries/mogo-adas-data/src/main/proto/EagleEyeRecommend.proto.back b/libraries/mogo-adas-data/src/main/proto/EagleEyeRecommend.proto.back new file mode 100644 index 0000000000..571d736032 --- /dev/null +++ b/libraries/mogo-adas-data/src/main/proto/EagleEyeRecommend.proto.back @@ -0,0 +1,82 @@ +syntax = "proto3"; +package mogo.nde.service.dto.protocol; +option java_package = "mogo.nde.service.dto.protocol"; +//TODO 仅做备份使用 +// 鹰眼推荐车道 +message AutoSteerInfo { + /** + * 道路Id + */ + string roadId = 1; + /** + * 生成时间 + */ + int64 systemTime = 2; + /** + * 具体内容 + */ + repeated RecommendInfo recommendInfo = 3; +} + +message RecommendInfo{ + /** + * 车龙id,如果有车龙的话,没有不传 + */ + string uuid = 1; + /** + * 车道号 + */ + int32 laneNum = 2; + /** + * 车龙车辆id集合,若无车龙则为空集合 + */ + repeated string uuids = 3; + /** + * 车辆轨迹,有车龙有值 + */ + repeated Point2D points = 4; + /** + * 车道线轨迹,车道中心线与停止线交点 + */ + repeated Point2D lanePoints = 5; + /** + * 车龙长度 + */ + double length = 6; + /** + * 是否是建议车道 + */ + bool suggestedLanes = 7; + + /** + 车道类型 + 直行 201 + 直行或左转 202 + 直行或右转 203 + 直行或掉头 204 + 左转 205 + 左转或掉头 206 + 左弯或向左合流 207 + 右转 208 + 右转或向右合流209 + 左右转弯 210 + 掉头211 + 禁止左转212 + 禁止右转213 + 禁止掉头214 + 直行或左转或右转215 + 直行或掉头或左转216 + 右转或掉头217 + 禁止右转或向右合流218 + */ + int32 arrowType = 8; +} + +//2维点 +message Point2D { + // 经度 + double lon = 1; + // 维度 + double lat = 2; +} + diff --git a/libraries/mogo-adas-data/src/main/proto/message_pad.proto b/libraries/mogo-adas-data/src/main/proto/message_pad.proto index b64521c2b8..04b716d7df 100644 --- a/libraries/mogo-adas-data/src/main/proto/message_pad.proto +++ b/libraries/mogo-adas-data/src/main/proto/message_pad.proto @@ -317,7 +317,9 @@ message TrackedObject uint32 drawLevel = 12; //危险等级 1 绿,2 黄,3 红 double driverTime = 13; //驱动感知时间, abandoned repeated TrackedSource tracked_source = 14; - repeated Location polygon = 15; + repeated Location polygon = 15;//当 type == 707 时 + //车龙轨迹对应NED原始PB EagleEyeRecommend.proto中的lanePoints字段(原始PB中那个points和lanePoints区别:points字段里面是车龙上的车辆中心点练起来的线,可能歪歪扭扭的。lanePoints字段里面是车龙所在车道的车道中心线连续,更平滑) + //此字段 size > 1 时表示有车龙轨迹,有车龙时仅longitude和latitude赋值 size == 1 时表示无车龙 geometry.Point center = 16; AdditionalAttribute add_attribute = 17; //事件类型 double angle = 18; //相对于自车x轴的角度,左正右负 @@ -326,7 +328,19 @@ message TrackedObject string camera_ip = 21; //来源IP uint64 detect_start_time = 22; //V2N事件生成UTC时间,单位毫秒 string v2x_uuid = 23; //V2X目标uuid - reserved 24 to 100; + //对应NED原始PB EagleEyeRecommend.proto中的uuid字段 + //与NED原始数据稍有不同。NED原石数据无车龙时不传参数;域控融合后的的数据,有车龙是id样式:2b9564b8-1b7f-4533-9c66-b472780c986a 无车龙id样式是数字:1、2、3、4、…… + string roadId = 24; //V2N车龙道路ID 对应NED原始PB EagleEyeRecommend.proto中的roadId字段 + int32 laneNum = 25; //V2N车龙彻车道号 对应NED原始PB EagleEyeRecommend.proto中的laneNum字段 + bool suggestedLanes = 26; //V2N车龙是否是建议车道 对应NED原始PB EagleEyeRecommend.proto中的suggestedLanes字段 + int32 arrowType = 27; //V2N车龙车道类型 + //对应NED原始PB EagleEyeRecommend.proto中的arrowType字段 + //目前除以下注释里面的值,其他的数字都没有意义 + //直行 201;直行或左转 202;直行或右转 203;直行或掉头 204; + //左转 205;左转或掉头 206;左弯或向左合流 207;右转 208;右转或向右合流 209; + //左右转弯 210,掉头 211,禁止左转 212,禁止右转 213,禁止掉头 214,直行或左转或右转 215; + //直行或掉头或左转 216;右转或掉头 217;禁止右转或向右合流 218; + reserved 28 to 100; string strUuid = 101;//String类型车辆ID } diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceivedAckManager.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceivedAckManager.java index 2a2373b769..32275156c4 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceivedAckManager.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceivedAckManager.java @@ -5,13 +5,11 @@ import androidx.annotation.NonNull; import com.zhjt.mogo.adas.common.MessageType; import com.zhjt.mogo.adas.data.bean.ReceivedAck; -import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; -import java.util.List; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; import mogo.telematics.pad.MessagePad; @@ -22,8 +20,8 @@ public class ReceivedAckManager { private static final String TAG = ReceivedAckManager.class.getSimpleName(); private volatile Timer timer; - private final List list = Collections.synchronizedList(new ArrayList<>()); - private final AtomicBoolean isSupport = new AtomicBoolean(false);//是否支持回执功能 + private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); + private final AtomicInteger isSupport = new AtomicInteger(-1);//是否支持回执功能 -1:未知; 0:不支持; 1:支持; private OnReceivedAckListener listener; public void setListener(OnReceivedAckListener listener) { @@ -47,10 +45,10 @@ public class ReceivedAckManager { } public void setSupport(int version) { - isSupport.set(version >= 30800); - CupidLogUtils.log(TAG, version + " 是否支持回执功能=" + isSupport.get()); - if (!isSupport.get()) { - stop(); + isSupport.set(version >= 30800 ? 1 : 0); + CupidLogUtils.log(TAG, version + " 是否支持回执功能=" + (isSupport.get() == 1)); + if (isSupport.get() != 1) { + destroy(); } } @@ -63,11 +61,13 @@ public class ReceivedAckManager { * @param sendData */ public void addNeedAckData(long sendTime, long msgId, MessageType messageType, byte[] sendData) { - if (isSupport.get()) { + if (isSupport.get() == -1 || isSupport.get() == 1) { + queue.add(new ReceivedAck(sendTime, msgId, messageType, sendData)); + } + if (isSupport.get() == 1) { start(); - list.add(new ReceivedAck(sendTime, msgId, messageType, sendData)); - } else { - stop(); + } else if (isSupport.get() == 0) { + destroy(); } } @@ -78,8 +78,13 @@ public class ReceivedAckManager { * @param receivedAck 回执数据 */ public void receiveReceivedAck(long time, MessagePad.ReceivedAck receivedAck) { + if (isSupport.get() != 1) { + isSupport.set(1); + CupidLogUtils.log(TAG, "当前域控版本支持回执功能"); + start(); + } int count = receivedAck.getMsgidsCount(); - if (count == 0 || list.isEmpty()) { + if (count == 0 || queue.isEmpty()) { if (listener != null) { ReceivedAck ack = new ReceivedAck(0, 0, MessageType.TYPE_DEFAULT, null); ack.setStatus(count == 0 ? ReceivedAck.Status.RECEIVED_ACK_DATA_ERROR : ReceivedAck.Status.WAITING_RECEIVED_ACK_LIST_EMPTY); @@ -89,7 +94,8 @@ public class ReceivedAckManager { } return; } - Iterator iterator = list.iterator(); + + Iterator iterator = queue.iterator(); while (iterator.hasNext()) { ReceivedAck ack = iterator.next(); for (int i = 0; i < count; i++) { @@ -114,9 +120,9 @@ public class ReceivedAckManager { timer.schedule(new TimerTask() { @Override public void run() { - if (!list.isEmpty()) { + if (!queue.isEmpty()) { long time = System.currentTimeMillis(); - Iterator iterator = list.iterator(); + Iterator iterator = queue.iterator(); while (iterator.hasNext()) { ReceivedAck ack = iterator.next(); long t = ack.getMessageType().timeoutMillis; @@ -136,8 +142,13 @@ public class ReceivedAckManager { } public void stop() { - if (!list.isEmpty()) { - list.clear(); + destroy(); + isSupport.set(-1); + } + + private void destroy() { + if (!queue.isEmpty()) { + queue.clear(); } if (timer != null) { timer.cancel();