From 088be3f4fbca7f57ae96e233c115ec8ebe610f30 Mon Sep 17 00:00:00 2001 From: xuxinchao Date: Wed, 22 Feb 2023 18:44:33 +0800 Subject: [PATCH] =?UTF-8?q?[dev=5Farch=5Fopt=5F3.0]=E5=BD=95=E5=8C=85?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E4=B8=89=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/bus/fragment/BaseBusTabFragment.java | 5 + .../fragment/BaseSweeperTabFragment.java | 4 + .../mogo/och/taxi/ui/BaseTaxiTabFragment.java | 5 + .../autopilot/MoGoAutopilotControlProvider.kt | 104 ++++ .../badcase/biz/BadCaseConfigView.kt | 1 - .../badcase/biz/BadCaseManagerView.kt | 494 ++++++++++++++++++ .../badcase/biz/BagUploadDialog.java | 121 +++++ .../badcase/biz/CaseListDialog.java | 5 + .../badcase/biz/CaseTopicListDialog.java | 5 + .../badcase/biz/InitiativeBadCaseWindow.kt | 146 +++--- .../badcase/biz/PassiveBadCaseWindow.kt | 122 +++-- .../badcase/biz/SpaceWarningDialog.java | 87 +++ .../biz/adapter/BagManagerListAdapter.kt | 175 +++++++ .../badcase/consts/BadCaseConfig.kt | 5 + .../badcase/record/Audition.java | 103 ++++ .../res/drawable-xhdpi/icon_bag_audio.png | Bin 0 -> 1658 bytes .../res/drawable-xhdpi/icon_bag_no_data.png | Bin 0 -> 17281 bytes .../res/drawable/bag_report_button_bg.xml | 9 + .../res/drawable/bag_reported_button_bg.xml | 9 + .../res/drawable/cancel_select_button_bg.xml | 9 + .../main/res/drawable/delete_button_bg.xml | 9 + .../src/main/res/drawable/icon_bag_edit.png | Bin 0 -> 926 bytes .../src/main/res/drawable/progress_bar_ct.xml | 18 + .../res/drawable/progress_bar_drawable.xml | 31 ++ .../res/drawable/select_all_button_bg.xml | 9 + .../main/res/drawable/space_percent_bg.xml | 27 + .../drawable/space_warning_progress_bg.xml | 38 ++ .../src/main/res/drawable/unused_space_bg.xml | 8 + .../res/drawable/upload_cloud_button_bg.xml | 9 + .../src/main/res/drawable/used_space_bg.xml | 8 + .../src/main/res/layout/dialog_bag_upload.xml | 97 ++++ .../main/res/layout/dialog_space_warning.xml | 83 +++ .../src/main/res/layout/item_bag_manager.xml | 88 ++++ .../main/res/layout/item_bag_time_title.xml | 16 + .../res/layout/layout_badcase_manager.xml | 228 ++++++++ .../core/function/hmi/ui/setting/ToolsView.kt | 4 + .../hmi/ui/tools/AutoPilotAndCheckView.kt | 5 + .../drawable-xhdpi/debug_icon_bag_manager.png | Bin 0 -> 17440 bytes .../main/res/layout/view_auto_pilot_check.xml | 29 + .../src/main/res/values/strings.xml | 1 + .../core/data/badcase/BagDescriptionEntity.kt | 12 + .../eagle/core/data/badcase/BagInfoEntity.kt | 20 + .../core/data/badcase/BagManagerEntity.kt | 15 + .../core/data/badcase/BagSpaceInfoEntity.kt | 11 + .../core/data/badcase/SpaceInfoEntity.kt | 13 + .../eagle/core/data/badcase/SubBagEntity.kt | 11 + .../core/data/badcase/UploadCosStatEntity.kt | 11 + .../IMoGoAutopilotControlProvider.kt | 7 + .../autopilot/IMoGoAutopilotRecordListener.kt | 6 + .../CallerAutoPilotControlManager.kt | 14 + .../CallerAutopilotRecordListenerManager.kt | 12 + gradle.properties | 2 +- 52 files changed, 2128 insertions(+), 123 deletions(-) create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseManagerView.kt create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BagUploadDialog.java create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/SpaceWarningDialog.java create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/adapter/BagManagerListAdapter.kt create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/record/Audition.java create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_bag_audio.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_bag_no_data.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bag_report_button_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bag_reported_button_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_select_button_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/delete_button_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/icon_bag_edit.png create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_ct.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_drawable.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/select_all_button_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_percent_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_warning_progress_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/unused_space_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/upload_cloud_button_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/drawable/used_space_bg.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_bag_upload.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_space_warning.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_manager.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_time_title.xml create mode 100644 core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_manager.xml create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/debug_icon_bag_manager.png create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagDescriptionEntity.kt create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagInfoEntity.kt create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagManagerEntity.kt create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagSpaceInfoEntity.kt create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SpaceInfoEntity.kt create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SubBagEntity.kt create mode 100644 core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/UploadCosStatEntity.kt 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 f7cea76f00..e8f76bb184 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 @@ -56,6 +56,7 @@ import org.greenrobot.eventbus.EventBus; import java.util.Objects; +import bag_manager.BagManagerOuterClass; import mogo.telematics.pad.MessagePad; import record_cache.RecordPanelOuterClass; @@ -320,6 +321,10 @@ public abstract class BaseBusTabFragment public void onAutopilotRecordConfig(@NonNull MessagePad.RecordDataConfig config) { } + @Override + public void onBagManagerResult(@NonNull BagManagerOuterClass.BagManager bagManager) { + } + /** * 测试到站 */ diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java index 473ab89f04..1abc7afcad 100644 --- a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java @@ -50,6 +50,7 @@ import com.mogo.och.sweeper.util.BDRouteDataTestUtils; import com.mogo.och.sweeper.view.SlidePanelView; import com.mogo.och.sweeper.view.SweeperTrafficDataView; +import bag_manager.BagManagerOuterClass; import mogo.telematics.pad.MessagePad; import record_cache.RecordPanelOuterClass; @@ -298,6 +299,9 @@ public abstract class BaseSweeperTabFragment0){ + selectedBagSize = 0 + selectedBagNum = 0 + bagManagerList.clear() + for(selectBagInfo in bagManagerEntity.bagsInfoResp){ + if(selectBagInfo.itemType == 0){ + selectBagInfo.selectStatus = true + selectedBagSize += selectBagInfo.totalSize + bagManagerList.add(selectBagInfo) + selectedBagNum++ + } + } + //显示选择包的个数和大小 + tvSelectedBagSize.text = "已选${selectedBagNum}个包,共${selectedBagSize/(1000*1024*1024)}G" + tvSelectedBagSize.visibility = View.VISIBLE + bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + } + } + //取消选中 + tvCancelSelect.setOnClickListener { + if(bagManagerEntity.bagsInfoResp.size>0){ + for(cancelBagInfo in bagManagerEntity.bagsInfoResp){ + cancelBagInfo.selectStatus = false + bagManagerList.remove(cancelBagInfo) + } + selectedBagNum = 0 + selectedBagSize = 0 + tvSelectedBagSize.visibility = View.GONE + bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + } + } + + + //上传Cos桶 + tvUploadCloud.setOnClickListener { + if(bagManagerList.size>0){ + bagManagerEntity.reqType = 3 + bagManagerEntity.keyReq = bagManagerList[0].key + Log.i("sendBagManagerCmd","bagManagerEntity.keyReq="+bagManagerEntity.keyReq) + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + + bagUploadDialog = BagUploadDialog(context) + bagUploadDialog?.setListener { //删除选择,取消上传 + bagManagerList.clear() + if (bagManagerEntity.bagsInfoResp.size > 0) { + for (cancelBagInfo in bagManagerEntity.bagsInfoResp) { + if(cancelBagInfo.itemType == 0){ + cancelBagInfo.selectStatus = false + bagManagerList.remove(cancelBagInfo) + } + } + selectedBagNum = 0 + selectedBagSize = 0 + tvSelectedBagSize.visibility = View.GONE + bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + } + } + bagUploadDialog?.show() + bagUploadDialog?.setAllUpload(selectedBagNum,selectedBagSize) + }else{ + ToastUtils.showShort("请先选择要上传的Bag包") + } + + } + //删除Bag包 + tvDeleteSelect.setOnClickListener { + if(bagManagerList.size>0){ + bagManagerEntity.reqType = 4 + bagManagerEntity.keyReq = bagManagerList[0].key + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + }else{ + ToastUtils.showShort("请先选择要删除的Bag包") + } + + } + + bagManagerListAdapter = BagManagerListAdapter() + bagManagerListAdapter?.setListener(object :BagManagerListAdapter.BagClickListener{ + override fun onClick(bagInfoEntity: BagInfoEntity, isChecked: Boolean) { + if(isChecked){ + bagInfoEntity.selectStatus = true + bagManagerList.add(bagInfoEntity) + selectedBagNum++ + selectedBagSize += bagInfoEntity.totalSize + tvSelectedBagSize.text = "已选${selectedBagNum}个包,共${selectedBagSize/(1000*1024*1024)}G" + tvSelectedBagSize.visibility = View.VISIBLE + }else{ + bagInfoEntity.selectStatus = false + bagManagerList.remove(bagInfoEntity) + selectedBagNum-- + selectedBagSize -= bagInfoEntity.totalSize + if(selectedBagNum == 0){ + tvSelectedBagSize.visibility = View.GONE + }else{ + tvSelectedBagSize.text = "已选${selectedBagNum}个包,共${selectedBagSize/(1000*1024*1024)}G" + tvSelectedBagSize.visibility = View.VISIBLE + } + } + + } + + override fun uploadBI(bagInfoEntity: BagInfoEntity) { + //展示上报弹窗 + val initiativeBadCaseWindow = InitiativeBadCaseWindow(context as Activity) + initiativeBadCaseWindow.setClickListener(object: InitiativeBadCaseWindow.ClickListener{ + override fun closeWindow() { + initiativeBadCaseWindow.hideFloatWindow() + } + }) + initiativeBadCaseWindow.showReportBIWindow(bagInfoEntity) + } + + override fun editDescription(key: Long, description: BagDescriptionEntity) { + //编辑Bag包描述信息 + isNameModify = true + bagManagerEntity.reqType = 5 + bagManagerEntity.keyReq = key + bagManagerEntity.descReq = description + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } + + override fun bagAudio(key: Long, audioUrl: String) { + DownloadManager.getInstance().init(context) + val downUrl = audioUrl.replace("http://petchfile-1255510688.cos.ap-beijing.myqcloud.com/","") + DownloadManager.getInstance().download(downUrl, + audioSavePath,"${key}.wav") + //延迟播放 + Handler().postDelayed({ + //音频文件播放 + Audition.getInstance().playOrStop("${audioSavePath}${key}.wav") + }, 1500) + } + + }) + val linearLayoutManager = LinearLayoutManager(context) + rvBagList.layoutManager = linearLayoutManager + rvBagList.adapter = bagManagerListAdapter + + //音频文件播放 +// Audition.getInstance().playOrStop("/mnt/sdcard/mogo/test.wav") +// +// 音频下载 +// DownloadManager.getInstance().init(context) +// DownloadManager.getInstance().download("CarPad/mogopadlog/X20202111230C01YYW/2023-01-30/Audio_1675049657187_BadCase.wav", +// "/mnt/sdcard/mogo/","test13.wav") + + } + + fun setOnClickListener(clickListener: ClickListener) { + this.clickListener = clickListener + } + + interface ClickListener { + fun onClose() + } + + override fun onBagManagerResult(bagManager: BagManagerOuterClass.BagManager) { + super.onBagManagerResult(bagManager) + UiThreadHandler.post { + Log.i(TAG,"onBagManagerResult Start") + Log.i(TAG,"keyReq="+bagManager.keyReq) + Log.i(TAG,"reqType="+bagManager.reqType) + Log.i(TAG,"uploadCosResp stat="+bagManager.uploadCosResp.stat) + Log.i(TAG,"descReq description="+bagManager.descReq.description + +" audioUrl="+bagManager.descReq.audioUrl + +" reportBI="+bagManager.descReq.reportBI + +" hasAudio="+bagManager.descReq.hasAudio) + for(logBag in bagManager.bagsInfoRespList){ + Log.i(TAG,"bagPath="+logBag.bagPath) + Log.i(TAG,"timestamp="+logBag.timestamp) + Log.i(TAG,"description="+logBag.description) + Log.i(TAG,"key="+logBag.key) + Log.i(TAG,"mergeStat="+logBag.mergeStat) + Log.i(TAG,"totalSize="+logBag.totalSize) + Log.i(TAG,"uploadStat="+logBag.uploadStat) + } + Log.i(TAG,"onBagManagerResult End") + + //获取空间使用信息 + if(bagManager.reqType == 1){ + //遍历各个主机的硬盘空间信息 + if(bagManager.spaceInfoRespCount>0){ + spaceTotal = 0 + spaceUsed = 0 + spaceFree = 0 + for(spaceInfo in bagManager.spaceInfoRespList){ + spaceInfo.diskSpaceInfo?.let { + spaceTotal += it.total + spaceUsed += it.used + spaceFree += it.free + } + } + //展示空间使用情况 + //已使用空间 + tvUsedSpaceContent.text = "${(spaceUsed/(1000*1024*1024L))}G" + //可使用空间 + tvFreeSpaceContent.text = "${(spaceFree/(1000*1024*1024L))}G" + //进度条展示空间 + pbSpacePercent.progress = (spaceUsed*100/spaceTotal).toInt() + } + } + //遍历所有bag + else if(bagManager.reqType == 2){ + clBagHaveDataLayout.visibility = View.VISIBLE + clBagNoDataLayout.visibility = View.GONE + if(bagManager.bagsInfoRespCount>0){ + bagManagerEntity.bagsInfoResp.clear() + val originBagInfoList = ArrayList() + for(bagInfo in bagManager.bagsInfoRespList){ + bagInfo?.let { + val descriptionEntity = BagDescriptionEntity(it.description.description,it.description.hasAudio,it.description.audioUrl,it.description.reportBI) + val bagInfoEntity = BagInfoEntity() + bagInfoEntity.key = it.key + bagInfoEntity.totalSize = it.totalSize + bagInfoEntity.timestamp = it.timestamp + bagInfoEntity.bagPath = it.bagPath + bagInfoEntity.mergeStat = it.mergeStat + bagInfoEntity.uploadStat = it.uploadStat + bagInfoEntity.itemType = 0 + bagInfoEntity.description = descriptionEntity + for(subBag in it.subBagsList){ + val subBagEntity = SubBagEntity(subBag.key,subBag.host,subBag.size) + bagInfoEntity.subBags.add(subBagEntity) + } + originBagInfoList.add(bagInfoEntity) + //对数组按照时间顺序进行倒序排序 + originBagInfoList.sortWith(Comparator { o1, o2 -> + o2.timestamp.compareTo(o1.timestamp) + }) + } + } + + for(originBagInfo in originBagInfoList){ + originBagInfo.let { + it.timestamp.let { time -> + val month = time.substring(4,6) + val day = time.substring(6,8) + val timeStr = "${month}月${day}日" + var containTime = false + for(bag in bagManagerEntity.bagsInfoResp){ + if(bag.timeStr == timeStr){ + containTime = true + } + } + if(!containTime || bagManagerEntity.bagsInfoResp.size ==0){ + //增加时间的 + val bagInfoTimeEntity = BagInfoEntity() + bagInfoTimeEntity.itemType = 1 + bagInfoTimeEntity.timeStr = timeStr + bagInfoTimeEntity.timestamp = time.substring(0,8) + bagManagerEntity.bagsInfoResp.add(bagInfoTimeEntity) + } + var containKey = false + for(bagInfoContain in bagManagerEntity.bagsInfoResp){ + if(bagInfoContain.key == it.key){ + containKey = true + } + } + if(!containKey){ + bagManagerEntity.bagsInfoResp.add(it) + } + } + } + } + + //更新List + bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + } + + // 开启定时查询速度 + Timer().schedule(timerTaskRefresh, Date(), 60*1000) + } + //上传Cos + else if(bagManager.reqType == 3){ + //此处应循环上传Cos + val uploadIterator = bagManagerEntity.bagsInfoResp.iterator() + while(uploadIterator.hasNext()){ + val uploadBagInfo = uploadIterator.next() + if(uploadBagInfo.key == bagManager.uploadCosResp.key && bagManager.uploadCosResp.stat!=1){ + bagManagerList.remove(uploadBagInfo) + if(bagManagerList.size>0){ + var remainSize = 0L + for(bagInfo in bagManagerList){ + remainSize += bagInfo.totalSize + } + bagUploadDialog?.updateRemainUpload(bagManagerList.size,remainSize) + //执行下一个上传Bag命令 + bagManagerEntity.reqType = 3 + bagManagerEntity.keyReq = bagManagerList[0].key + Log.i("sendBagManagerCmd","bagManagerEntity.keyReq="+bagManagerEntity.keyReq) + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } + } + } + //上传Cos执行完成 + if(bagManagerList.size == 0 && selectedBagNum != 0){ + ToastUtils.showShort("上传命令完成") + bagUploadDialog?.uploadCompleted() + tvCancelSelect.performClick() + } + + when (bagManager.uploadCosResp.stat) { + 0 -> { + ToastUtils.showShort("${bagManager.uploadCosResp.key} 上传cos桶成功") + } + 2 -> { + ToastUtils.showShort("${bagManager.uploadCosResp.key} 上传cos桶copy过程失败,原因:${bagManager.uploadCosResp.message}") + } + 3 -> { + ToastUtils.showShort("${bagManager.uploadCosResp.key} 上传cos桶合并过程失败,原因:${bagManager.uploadCosResp.message}") + } + 4 -> { + ToastUtils.showShort("${bagManager.uploadCosResp.key} 上传cos桶上传过程失败,原因:${bagManager.uploadCosResp.message}") + } + } + + } + //删除Bag + else if(bagManager.reqType == 4){ + //收到此回调就删除对应key的Bag + val iterator = bagManagerEntity.bagsInfoResp.iterator() + while(iterator.hasNext()){ + val deleteBagInfo = iterator.next() + if(deleteBagInfo.key == bagManager.keyReq){ + iterator.remove() + bagManagerList.remove(deleteBagInfo) + //更新列表 +// bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + if(bagManagerList.size>0){ + //继续执行删除命令 + bagManagerEntity.reqType = 4 + bagManagerEntity.keyReq = bagManagerList[0].key + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } + } + } + //遍历列表,如当天Bag全部删除,同时把日期标题也删除更新列表 + val titleIterator = bagManagerEntity.bagsInfoResp.iterator() + while(titleIterator.hasNext()){ + val titleBagInfo = titleIterator.next() + if(titleBagInfo.itemType == 1){ + val bagIterator = bagManagerEntity.bagsInfoResp.iterator() + var hasBag = false + while(bagIterator.hasNext()){ + val bagBagInfo = bagIterator.next() + if(bagBagInfo.itemType == 0){ + bagBagInfo.timestamp?.let { + if(it.contains(titleBagInfo.timestamp.toString())){ + hasBag = true + } + } + } + } + if(!hasBag){ + bagIterator.remove() + } + } + } + if(bagManagerList.size == 0){ + tvCancelSelect.performClick() + } + //更新列表 + bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + } + //修改bag附加信息 + else if(bagManager.reqType == 5){ + //更新Bag包上报状态 + for(bagInfo in bagManagerEntity.bagsInfoResp){ + if(bagInfo.key == bagManager.keyReq){ + bagInfo.description?.let { + it.reportBI = bagManager.descReq.reportBI + it.description = bagManager.descReq.description + it.hasAudio = bagManager.descReq.hasAudio + it.audioUrl = bagManager.descReq.audioUrl + } + } + } + if(!isNameModify){ + //更新List + bagManagerListAdapter?.setData(bagManagerEntity.bagsInfoResp) + } + isNameModify = false + } + } + + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + CallerAutopilotRecordListenerManager.addListener(TAG, this) + bagManagerEntity.reqType = 2 + //遍历所有bag + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerAutopilotRecordListenerManager.removeListener(TAG) + try { + timerTaskRefresh.cancel() + } catch (e: Exception) { + e.printStackTrace() + } + } + + private val timerTaskRefresh = object : TimerTask() { + override fun run() { + UiThreadHandler.post { + //获取空间使用信息,每隔1分钟获取一次 + bagManagerEntity.reqType = 1 + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } + } + } + +} \ 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/BagUploadDialog.java b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BagUploadDialog.java new file mode 100644 index 0000000000..00dd1145b0 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BagUploadDialog.java @@ -0,0 +1,121 @@ +package com.zhjt.mogo_core_function_devatools.badcase.biz; + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.WindowManager; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.zhjt.mogo_core_function_devatools.R; + +import java.text.DecimalFormat; + +/** + * @author XuXinChao + * @description Bag包上传进度展示弹窗 + * @since: 2022/2/1 + */ +public class BagUploadDialog extends Dialog { + + private TextView tvCancelUpload;//取消上传 + private TextView tvCancel;//取消 + private TextView tvUploadDetail;//上传详情 + private ProgressBar viewUploadProgress;//上传进度条 + + private int totalNum = 0; + private Long totalSize = 0L; + private int remainNum = 0; + private Long remainSize = 0L; + + private BagUploadListener uploadListener; + private DecimalFormat format = new DecimalFormat("0.0"); + + public BagUploadDialog(@NonNull Context context) { + super(context, R.style.bad_case_dialog); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_bag_upload); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.height = 688; + params.width = 1110; + getWindow().setAttributes(params);//向WindowManager设置属性 + setCanceledOnTouchOutside(false); + init(); + initEvent(); + } + + private void init(){ + tvCancelUpload = findViewById(R.id.tvCancelUpload); + tvCancel = findViewById(R.id.tvCancel); + tvUploadDetail = findViewById(R.id.tvUploadDetail); + viewUploadProgress = findViewById(R.id.viewUploadProgress); + } + + private void initEvent(){ + //取消上传 + tvCancelUpload.setOnClickListener(v -> { + if(uploadListener!=null){ + uploadListener.cancelUpload(); + } + dismiss(); + }); + //取消 + tvCancel.setOnClickListener(v -> { + dismiss(); + }); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + public void setListener(BagUploadListener listener){ + uploadListener = listener; + } + + @SuppressLint("SetTextI18n") + public void setAllUpload(int totalNum, Long totalSize){ + this.totalNum = totalNum; + this.totalSize = totalSize; + //更新进度条和进度文字 + String totalStr = format.format((totalSize/(1000*1024*1024.0))); + tvUploadDetail.setText("共计"+totalNum+"个包 ("+totalStr+"G) 已上传"+(0)+"个包 (" + +0+"G) 剩余"+totalNum+"个包 ("+ totalStr+"G)"); + } + + @SuppressLint("SetTextI18n") + public void updateRemainUpload(int remainNum, Long remainSize){ + this.remainNum = remainNum; + this.remainSize = remainSize; + //更新进度条和进度文字 + String updateTotalStr = format.format((totalSize/(1000*1024*1024.0))); + String updateUploadStr = format.format(((totalSize-remainSize)/(1000*1024*1024.0))); + String updateRemainStr = format.format((remainSize/(1000*1024*1024.0))); + tvUploadDetail.setText("共计"+totalNum+"个包 ("+updateTotalStr+"G) 已上传"+(totalNum-remainNum)+"个包 (" + +updateUploadStr+"G) 剩余"+remainNum+"个包 ("+ updateRemainStr +"G)"); + viewUploadProgress.setProgress((totalNum-remainNum)*100/totalNum); + } + + public void uploadCompleted(){ + dismiss(); + } + + interface BagUploadListener{ + //取消上传 + void cancelUpload(); + } + +} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseListDialog.java b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseListDialog.java index 959f43ee8f..a3c03232d5 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseListDialog.java +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseListDialog.java @@ -20,6 +20,7 @@ import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig; import java.util.ArrayList; +import bag_manager.BagManagerOuterClass; import mogo.telematics.pad.MessagePad; import record_cache.RecordPanelOuterClass; @@ -116,4 +117,8 @@ public class CaseListDialog extends Dialog implements IMoGoAutopilotRecordListen caseListAdapter.notifyDataSetChanged(); }); } + + @Override + public void onBagManagerResult(@NonNull BagManagerOuterClass.BagManager bagManager) { + } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseTopicListDialog.java b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseTopicListDialog.java index a0cd77525a..972abec769 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseTopicListDialog.java +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/CaseTopicListDialog.java @@ -28,6 +28,7 @@ import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig; import java.util.ArrayList; import java.util.List; +import bag_manager.BagManagerOuterClass; import mogo.telematics.pad.MessagePad; import record_cache.RecordPanelOuterClass; @@ -203,4 +204,8 @@ public class CaseTopicListDialog extends Dialog implements IMoGoAutopilotRecordL @Override public void onAutopilotRecordResult(@NonNull RecordPanelOuterClass.RecordPanel recordPanel) { } + + @Override + public void onBagManagerResult(@NonNull BagManagerOuterClass.BagManager bagManager) { + } } 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 1bcca50ca6..f2c675caec 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 @@ -13,6 +13,9 @@ import android.widget.ImageView import android.widget.TextView import com.mogo.cloud.passport.MoGoAiCloudClientConfig import com.mogo.eagle.core.data.app.AppConfigInfo +import com.mogo.eagle.core.data.badcase.BagDescriptionEntity +import com.mogo.eagle.core.data.badcase.BagInfoEntity +import com.mogo.eagle.core.data.badcase.BagManagerEntity import com.mogo.eagle.core.data.badcase.RecordCaseEntity import com.mogo.eagle.core.data.map.MogoLocation import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener @@ -36,8 +39,10 @@ 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.util.* @@ -77,17 +82,17 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList private lateinit var tvInitiativeCancel: TextView private var audioStatus = false - private var audioFileName: String? = null //录音文件名称 + private var audioFileName:String?=null //录音文件名称 private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签 - @Volatile - private var recordKey: String? = null //录制bag包key - + private var recordKey: String?=null //录制bag包key @Volatile - private var recordFileName: String? = null //录制文件包名 - private var longitude: Double? = null - private var latitude: Double? = null + private var recordFileName: String?=null //录制文件包名 + private var longitude: Double?=null + private var latitude: Double?=null + + private var bagManagerEntity: BagManagerEntity = BagManagerEntity() private var mInViewX = 0f private var mInViewY = 0f @@ -107,9 +112,8 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } @SuppressLint("SetTextI18n") - private fun initFloatWindow() { - mFloatLayout = - LayoutInflater.from(mActivity).inflate(R.layout.view_initiative_bad_case, null) as View + private fun initFloatWindow(){ + mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_initiative_bad_case, null) as View mFloatLayout.setOnTouchListener(this) tvInitiativeNum = mFloatLayout.findViewById(R.id.tvInitiativeNum) @@ -128,17 +132,16 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList tvInitiativeReport = mFloatLayout.findViewById(R.id.tvInitiativeReport) tvInitiativeCancel = mFloatLayout.findViewById(R.id.tvInitiativeCancel) - if (BadCaseConfig.windowNum < 1) { + if(BadCaseConfig.windowNum<1){ BadCaseConfig.windowNum = 1 } tvInitiativeNum.text = BadCaseConfig.windowNum.toString() BadCaseConfig.windowNum++ - tvInitiativeTime.text = - "时间:${millis2String(System.currentTimeMillis(), TimeUtils.getHourMinSecondFormat())}" + tvInitiativeTime.text = "时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" tvInitiativeIdentity.text = "身份:${BadCaseConfig.identity}" //采集结果回调监听 - CallerAutopilotRecordListenerManager.addListener(this.hashCode().toString(), this) + CallerAutopilotRecordListenerManager.addListener(this.hashCode().toString(),this) // 添加 ADAS车辆状态&定位 监听 CallerChassisLocationWGS84ListenerManager.addListener(this.hashCode().toString(), this) viewAudioButton.setOnClickListener { @@ -147,37 +150,37 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } tvInitiativeReport.setOnClickListener { - if (!rbOne.isChecked && !rbTwo.isChecked && !rbThree.isChecked && - !rbFour.isChecked && !rbFive.isChecked && !rbSix.isChecked - ) { + if(!rbOne.isChecked && !rbTwo.isChecked && !rbThree.isChecked && + !rbFour.isChecked && !rbFive.isChecked && !rbSix.isChecked){ TipToast.shortTip("请选择至少一个Case") return@setOnClickListener } - if (rbOne.isChecked) { + uploadReason.clear() + if(rbOne.isChecked){ uploadReason.append("严重画龙 ") } - if (rbTwo.isChecked) { + if(rbTwo.isChecked){ uploadReason.append("速度过慢 ") } - if (rbThree.isChecked) { + if(rbThree.isChecked){ uploadReason.append("感知、定位、地图等其他 ") } - if (rbFour.isChecked) { + if(rbFour.isChecked){ uploadReason.append("速度过快 ") } - if (rbFive.isChecked) { + if(rbFive.isChecked){ uploadReason.append("存在碰撞风险 ") } - if (rbSix.isChecked) { + if(rbSix.isChecked){ uploadReason.append("点刹、顿挫") } - if (audioStatus) { + if(audioStatus){ audioStatus = !audioStatus setAudio(audioStatus) Handler().postDelayed({ - uploadAudio() - }, 1000) - } else { + uploadAudio() + },1000) + }else{ uploadAudio() } } @@ -200,10 +203,10 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } } - var countDownTimer: CountDownTimer? = null + var countDownTimer: CountDownTimer?=null - private fun setAudio(status: Boolean) { - if (status) { + private fun setAudio(status: Boolean){ + if(status){ //开始录音 audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" RecordManager.getInstance().start(audioFileName) @@ -211,11 +214,11 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList viewAudioButton.setImageResource(R.drawable.icon_bad_case_audio_select) tvAudioCountDown.visibility = View.VISIBLE //开始倒计时 - if (countDownTimer == null) { + if(countDownTimer==null){ countDownTimer = object : CountDownTimer(60000, 1000) { override fun onTick(millisUntilFinished: Long) { - tvAudioCountDown.text = "${millisUntilFinished / 1000}S" + tvAudioCountDown.text = "${millisUntilFinished/1000}S" } override fun onFinish() { @@ -228,7 +231,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } countDownTimer?.start() } - } else { + }else{ //结束倒计时 countDownTimer?.cancel() countDownTimer?.onFinish() @@ -238,13 +241,11 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList } - private fun uploadAudio() { + private fun uploadAudio(){ val singlePath = "/mnt/sdcard/mogo/DataCollection/${audioFileName}.wav" val file = File(singlePath) - if (file.exists()) { - LogInfoManagerFactory.createAudioUpload(mActivity.applicationContext, - "Audio", - singlePath, + if(file.exists()){ + LogInfoManagerFactory.createAudioUpload(mActivity.applicationContext,"Audio",singlePath, object : OnUploadListener { override fun onUploadSuccess(filePath: String, downloadUrl: String) { CallerLogger.d("$M_DEVA$TAG", "语音文件上传成功:downloadUrl=$downloadUrl") @@ -260,7 +261,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList removeUploadListener(singlePath) } }) - } else { + }else{ //上传到服务器 upload(null) } @@ -270,7 +271,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList * 将语音文件上传Cos监听移除 * @param filePath 文件路径 */ - private fun removeUploadListener(filePath: String) { + private fun removeUploadListener(filePath: String){ val pkgInfo: List = filePath.substring( filePath.lastIndexOf("/") + 1, filePath.lastIndexOf(".") @@ -283,21 +284,21 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList * 将记录上传到服务器 * @param downloadUrl 语音文件下载地址 */ - private fun upload(downloadUrl: String?) { - GlobalScope.launch { + private fun upload(downloadUrl: String?){ + GlobalScope.launch{ val uploadResult = presenter.upload(mutableMapOf().also { itx -> - itx["carLicense"] = AppConfigInfo.plateNumber ?: "" //车牌号 - itx["filename"] = recordFileName ?: "" //bag包文件地址 + itx["carLicense"] = AppConfigInfo.plateNumber?:"" //车牌号 + itx["filename"] = recordFileName?:"" //bag包文件地址 itx["filesize"] = "0" //bag包文件大小 - itx["key"] = recordKey ?: "" //key - itx["reason"] = uploadReason.toString() ?: "" //采集原因 + 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["audioUrl"] = downloadUrl?:"" //音频COS地址 + itx["mapVersion"] = BadCaseConfig.dockerVersion ?:"" //工控机版本 itx["eyeVersion"] = AppUtils.getAppVersionName() //鹰眼版本 itx["coordinate"] = "latitude:${latitude};longitude:${longitude}" //坐标 @@ -306,6 +307,15 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList TipToast.shortTip("上报失败") } else { TipToast.shortTip("上报成功") + //将上报BI的结果同步给工控机记录保存 + recordKey?.let { + val hasAudio = downloadUrl != null + val descReqEntity = BagDescriptionEntity(uploadReason.toString(),hasAudio,downloadUrl.toString(),true) + bagManagerEntity.reqType = 5 + bagManagerEntity.keyReq = it.toLong() + bagManagerEntity.descReq = descReqEntity + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } BadCaseConfig.windowNum-- clickListener?.closeWindow() } @@ -346,19 +356,28 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight()-950 mWindowManager!!.addView(mFloatLayout, mWindowParams) //开启录包 - if (recordCaseEntity != null) { - CallerAutoPilotControlManager.recordPackage( - recordCaseEntity.caseId, - Random(SystemClock.elapsedRealtime()).nextInt(), - BadCaseConfig.totalDuration, - BadCaseConfig.previousDuration, - recordCaseEntity.topicList - ) - } else { - CallerAutoPilotControlManager.recordPackage( - BadCaseConfig.type, Random(SystemClock.elapsedRealtime()).nextInt(), - BadCaseConfig.totalDuration, BadCaseConfig.previousDuration - ) + if(recordCaseEntity!=null){ + CallerAutoPilotControlManager.recordPackage(recordCaseEntity.caseId,Random(SystemClock.elapsedRealtime()).nextInt(), + BadCaseConfig.totalDuration, BadCaseConfig.previousDuration,recordCaseEntity.topicList) + }else{ + CallerAutoPilotControlManager.recordPackage(BadCaseConfig.type,Random(SystemClock.elapsedRealtime()).nextInt(), + BadCaseConfig.totalDuration, BadCaseConfig.previousDuration) + } + } + } + + fun showReportBIWindow(bagInfoEntity: BagInfoEntity){ + if (mFloatLayout.parent == null) { + val metrics = DisplayMetrics() + // 默认固定位置,靠屏幕右边缘的中间 + mWindowManager!!.defaultDisplay.getMetrics(metrics) + mWindowParams!!.x = metrics.widthPixels + mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight()-950 + mWindowManager!!.addView(mFloatLayout, mWindowParams) + //已经录包无需再次启动录包,只要将录包信息同步到弹窗 + bagInfoEntity.let { + recordKey = it.key.toString() + recordFileName = it.bagPath } } } @@ -373,13 +392,12 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel") - ThreadUtils.runOnUiThread { - if (recordKey == null) { + if(recordKey==null){ recordKey = recordPanel.key.toString() BadCaseConfig.recordKeyList.add(recordPanel.key) } - if (recordFileName == null) { + if(recordFileName==null){ recordFileName = recordPanel.filename } } 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 3459ecf586..bf0429ecf6 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 @@ -6,6 +6,8 @@ import android.graphics.Color import android.graphics.PixelFormat import android.os.CountDownTimer import android.os.Handler +import android.os.Parcel +import android.os.Parcelable import android.util.DisplayMetrics import android.view.* import android.widget.CheckBox @@ -15,10 +17,13 @@ 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.data.badcase.BagDescriptionEntity +import com.mogo.eagle.core.data.badcase.BagManagerEntity import com.mogo.eagle.core.data.map.MogoLocation import com.mogo.eagle.core.data.msgbox.MsgBoxBean import com.mogo.eagle.core.data.msgbox.RecordBagMsg import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationWGS84Listener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger @@ -28,12 +33,13 @@ import com.mogo.eagle.core.utilcode.util.* import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String import com.zhidao.loglib.call.LogInfoManagerFactory import com.zhidao.loglib.upload.OnUploadListener -import com.zhidao.loglib.upload.UploadManager 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 com.zhidao.loglib.upload.UploadManager import me.jessyan.autosize.utils.AutoSizeUtils import org.greenrobot.eventbus.EventBus import java.io.File @@ -56,14 +62,16 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene private lateinit var mFloatLayout: View private var audioStatus = false - private var audioFileName: String? = null //录音文件名称 + private var audioFileName:String?=null //录音文件名称 + + private var bagManagerEntity: BagManagerEntity = BagManagerEntity() private var uploadReason: String = String() //上报原因,标签 - private var recordKey: String? = null //录制bag包key - private var recordFileName: String? = null //录制文件包名 - private var boxBean: MsgBoxBean? = null - private var longitude: Double? = null - private var latitude: Double? = null + private var recordKey: String?=null //录制bag包key + private var recordFileName: String?=null //录制文件包名 + private var boxBean: MsgBoxBean ?= null + private var longitude: Double?=null + private var latitude: Double?=null private var mInViewX = 0f private var mInViewY = 0f @@ -73,7 +81,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene private var mInScreenY = 0f private var clickListener: ClickListener? = null - var countDownTimer: CountDownTimer? = null + var countDownTimer: CountDownTimer?=null private lateinit var tvPassiveNum: TextView private lateinit var tvPassiveTime: TextView @@ -96,9 +104,8 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } @SuppressLint("SetTextI18n") - private fun initFloatWindow() { - mFloatLayout = - LayoutInflater.from(mActivity).inflate(R.layout.view_passive_bad_case, null) as View + 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) @@ -108,13 +115,12 @@ 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) { + if(BadCaseConfig.windowNum<1){ BadCaseConfig.windowNum = 1 } tvPassiveNum.text = BadCaseConfig.windowNum.toString() BadCaseConfig.windowNum++ - tvPassiveTime.text = - "时间:${millis2String(System.currentTimeMillis(), TimeUtils.getHourMinSecondFormat())}" + tvPassiveTime.text = "时间:${millis2String(System.currentTimeMillis(),TimeUtils.getHourMinSecondFormat())}" tvPassiveIdentity.text = "身份:${BadCaseConfig.identity}" // 添加 ADAS车辆状态&定位 监听 CallerChassisLocationWGS84ListenerManager.addListener(TAG, this) @@ -124,17 +130,17 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } tvPassiveReport.setOnClickListener { - if (uploadReason.isEmpty()) { + if(uploadReason.isEmpty()){ TipToast.shortTip("请选择至少一个Case") return@setOnClickListener } - if (audioStatus) { + if(audioStatus){ audioStatus = !audioStatus setAudio(audioStatus) Handler().postDelayed({ uploadAudio() - }, 1000) - } else { + },1000) + }else{ uploadAudio() } //删除记录 @@ -162,8 +168,8 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } } - private fun setAudio(status: Boolean) { - if (status) { + private fun setAudio(status: Boolean){ + if(status){ //开始录音 audioFileName = "Audio_${System.currentTimeMillis()}_BadCase" RecordManager.getInstance().start(audioFileName) @@ -171,11 +177,11 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene viewAudioButton.setImageResource(R.drawable.icon_bad_case_audio_select) tvAudioCountDown.visibility = View.VISIBLE //开始倒计时 - if (countDownTimer == null) { + if(countDownTimer==null){ countDownTimer = object : CountDownTimer(60000, 1000) { override fun onTick(millisUntilFinished: Long) { - tvAudioCountDown.text = "${millisUntilFinished / 1000}S" + tvAudioCountDown.text = "${millisUntilFinished/1000}S" } override fun onFinish() { @@ -188,7 +194,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } countDownTimer?.start() } - } else { + }else{ //结束倒计时 countDownTimer?.cancel() countDownTimer?.onFinish() @@ -198,13 +204,11 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene } - private fun uploadAudio() { + private fun uploadAudio(){ val singlePath = "/mnt/sdcard/mogo/DataCollection/${audioFileName}.wav" val file = File(singlePath) - if (file.exists()) { - LogInfoManagerFactory.createAudioUpload(mActivity.applicationContext, - "Audio", - singlePath, + if(file.exists()){ + LogInfoManagerFactory.createAudioUpload(mActivity.applicationContext,"Audio",singlePath, object : OnUploadListener { override fun onUploadSuccess(filePath: String, downloadUrl: String) { CallerLogger.d("$M_DEVA$TAG", "语音文件上传成功:downloadUrl=$downloadUrl") @@ -220,7 +224,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene removeUploadListener(singlePath) } }) - } else { + }else{ //上传到服务器 upload(null) } @@ -230,7 +234,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene * 将语音文件上传Cos监听移除 * @param filePath 文件路径 */ - private fun removeUploadListener(filePath: String) { + private fun removeUploadListener(filePath: String){ val pkgInfo: List = filePath.substring( filePath.lastIndexOf("/") + 1, filePath.lastIndexOf(".") @@ -243,21 +247,21 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene * 将记录上传到服务器 * @param downloadUrl 语音文件下载地址 */ - private fun upload(downloadUrl: String?) { - GlobalScope.launch { + private fun upload(downloadUrl: String?){ + GlobalScope.launch{ val uploadResult = presenter.upload(mutableMapOf().also { itx -> - itx["carLicense"] = AppConfigInfo.plateNumber ?: "" //车牌号 - itx["filename"] = recordFileName ?: "" //bag包文件地址 + itx["carLicense"] = AppConfigInfo.plateNumber?:"" //车牌号 + itx["filename"] = recordFileName?:"" //bag包文件地址 itx["filesize"] = "0" //bag包文件大小 - itx["key"] = recordKey ?: "" //key + itx["key"] = recordKey?:"" //key itx["reason"] = uploadReason //采集原因 itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长,固定为20S itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式) itx["channel"] = "0" //渠道 itx["carSn"] = MoGoAiCloudClientConfig.getInstance().sn //SN itx["userRole"] = BadCaseConfig.identity //采集者角色 - itx["audioUrl"] = downloadUrl ?: "" //音频COS地址 - itx["mapVersion"] = BadCaseConfig.dockerVersion ?: "" //工控机版本 + itx["audioUrl"] = downloadUrl?:"" //音频COS地址 + itx["mapVersion"] = BadCaseConfig.dockerVersion ?:"" //工控机版本 itx["eyeVersion"] = AppUtils.getAppVersionName() //鹰眼版本 itx["coordinate"] = "latitude:${latitude};longitude:${longitude}" //坐标 @@ -266,6 +270,15 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene TipToast.shortTip("上报失败") } else { TipToast.shortTip("上报成功") + //将上报BI的结果同步给工控机记录保存 + recordKey?.let { + val hasAudio = downloadUrl != null + val descReqEntity = BagDescriptionEntity(uploadReason,hasAudio,downloadUrl.toString(),true) + bagManagerEntity.reqType = 5 + bagManagerEntity.keyReq = it.toLong() + bagManagerEntity.descReq = descReqEntity + CallerAutoPilotControlManager.sendBagManagerCmd(bagManagerEntity) + } BadCaseConfig.windowNum-- clickListener?.closeWindow() } @@ -309,33 +322,28 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene // 默认固定位置,靠屏幕右边缘的中间 mWindowManager!!.defaultDisplay.getMetrics(metrics) mWindowParams!!.x = metrics.widthPixels - mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight() - 950 + mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight()-950 mWindowManager!!.addView(mFloatLayout, mWindowParams) } - GlobalScope.launch { + 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 - ) - checkBox.buttonDrawable = - mActivity.resources.getDrawable(R.drawable.badcase_radio_button_style) - checkBox.setPadding( + 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(10f), SizeUtils.dp2px(10f), SizeUtils.dp2px(10f), - SizeUtils.dp2px(10f), - SizeUtils.dp2px(10f) - ) - checkBox.textSize = AutoSizeUtils.dp2px(mActivity, 18f).toFloat() + SizeUtils.dp2px(10f)) + checkBox.textSize = AutoSizeUtils.dp2px(mActivity,18f).toFloat() checkBox.text = it.reason checkBox.isChecked = it.isChecked checkBox.setOnCheckedChangeListener(this@PassiveBadCaseWindow) - flReasonLayout.addView(checkBox, lp) + flReasonLayout.addView(checkBox,lp) } } } @@ -345,13 +353,13 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { buttonView?.text?.let { - if (isChecked) { - if (!uploadReason.contains(it)) { + if(isChecked){ + if(!uploadReason.contains(it)){ uploadReason += it } - } else { - if (uploadReason.contains(it)) { - uploadReason = uploadReason.replace(it.toString(), "") + }else{ + if(uploadReason.contains(it)){ + uploadReason = uploadReason.replace(it.toString(),"") } } @@ -365,7 +373,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout) } - fun setRecord(msgBoxBean: MsgBoxBean) { + fun setRecord(msgBoxBean: MsgBoxBean){ boxBean = msgBoxBean val recordBagMsg = (msgBoxBean.bean as RecordBagMsg) recordKey = recordBagMsg.key.toString() diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/SpaceWarningDialog.java b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/SpaceWarningDialog.java new file mode 100644 index 0000000000..036f2cb2b0 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/SpaceWarningDialog.java @@ -0,0 +1,87 @@ +package com.zhjt.mogo_core_function_devatools.badcase.biz; + +import android.app.Activity; +import android.app.Dialog; +import android.os.Bundle; +import android.view.WindowManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager; +import com.zhjt.mogo_core_function_devatools.R; + +/** + * @author XuXinChao + * @description BadCase车端磁盘空间已满预警弹窗 + * @since: 2022/2/1 + */ +public class SpaceWarningDialog extends Dialog { + + private TextView tvCleanDisk;//清理磁盘 + private TextView tvCancel;//取消 + private Activity mActivity; + + private ClickListener clickListener; + + public SpaceWarningDialog(@NonNull Activity activity) { + super(activity, R.style.bad_case_dialog); + mActivity = activity; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_space_warning); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.height = 688; + params.width = 1110; + getWindow().setAttributes(params);//向WindowManager设置属性 + setCanceledOnTouchOutside(false); + init(); + initEvent(); + } + + private void init(){ + tvCleanDisk = findViewById(R.id.tvCleanDisk); + tvCancel = findViewById(R.id.tvCancel); + } + + private void initEvent(){ + //清理磁盘 + tvCleanDisk.setOnClickListener(v -> { + //跳转录包管理页面 +// if(mActivity!=null){ +// CallerDevaToolsManager.INSTANCE.showBadCaseManagerView(mActivity); +// } + if(clickListener!=null){ + clickListener.showBadCaseManagerView(); + } + dismiss(); + }); + //取消 + tvCancel.setOnClickListener(v -> { + //取消弹窗 + dismiss(); + }); + } + + public void setClickListener(ClickListener clickListener){ + this.clickListener = clickListener; + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + public interface ClickListener{ + void showBadCaseManagerView(); + } + +} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/adapter/BagManagerListAdapter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/adapter/BagManagerListAdapter.kt new file mode 100644 index 0000000000..d3c8abc803 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/adapter/BagManagerListAdapter.kt @@ -0,0 +1,175 @@ +package com.zhjt.mogo_core_function_devatools.badcase.biz.adapter + +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.EditText +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.mogo.eagle.core.data.badcase.BagDescriptionEntity +import com.mogo.eagle.core.data.badcase.BagInfoEntity +import com.zhjt.mogo_core_function_devatools.R +import java.text.DecimalFormat + +/** + * @author XuXinChao + * @description Bag包管理列表适配器 + * @since: 2022/12/19 + */ +class BagManagerListAdapter: RecyclerView.Adapter() { + + private var data:List ?= null + private var bagClickListener: BagClickListener ?= null + private val format = DecimalFormat("0.00") + + fun setData(data: List?){ + this.data = data + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if(viewType == 1){ + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_bag_time_title,parent,false) + return BagTimeTitleHolder(view) + }else{ + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_bag_manager, parent, false) + return BagManagerListHolder(view) + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when(holder){ + is BagTimeTitleHolder ->{ + data?.let { + holder.tvBagTimeTitle.text = it[position].timeStr + } + } + is BagManagerListHolder->{ + data?.let { + val bagInfoEntity = it[position] + holder.cbBagSelect.setOnCheckedChangeListener(null) + holder.cbBagSelect.isChecked = bagInfoEntity.selectStatus + holder.cbBagSelect.tag = bagInfoEntity + holder.cbBagSelect.setOnCheckedChangeListener { _, isChecked -> + bagClickListener?.onClick(bagInfoEntity,isChecked) + } + + val textWatcher: TextWatcher = object : TextWatcher { + override fun beforeTextChanged( + charSequence: CharSequence, + i: Int, + i1: Int, + i2: Int + ) { + } + + override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} + override fun afterTextChanged(editable: Editable) { + bagInfoEntity.description?.let { desc-> + val descriptionStr = editable.toString() + if(desc.description != descriptionStr){ + desc.description = descriptionStr + bagClickListener?.editDescription(bagInfoEntity.key,desc) + } + } + } + } + holder.etBagNameEdit.onFocusChangeListener = + View.OnFocusChangeListener { p0, hasFocus -> + val edit = p0 as EditText + if(hasFocus){ + edit.addTextChangedListener(textWatcher) + }else{ + edit.removeTextChangedListener(textWatcher) + } + } + + + bagInfoEntity.description?.let { des-> + if(des.reportBI){ + //已上报 + holder.tvBagReportStatus.text = "已上报" + holder.tvBagReportStatus.setBackgroundResource(R.drawable.bag_reported_button_bg) + }else{ + //未上报 + holder.tvBagReportStatus.text = "上报" + holder.tvBagReportStatus.setBackgroundResource(R.drawable.bag_report_button_bg) + holder.tvBagReportStatus.setOnClickListener { + bagClickListener?.uploadBI(bagInfoEntity) + } + } + if(des.description.isEmpty()){ + holder.etBagNameEdit.setText(bagInfoEntity.key.toString()) + }else{ + holder.etBagNameEdit.setText(des.description) + } + } + + + if(bagInfoEntity.description?.hasAudio == true){ + holder.ivBagAudio.visibility = View.VISIBLE + holder.ivBagAudio.setOnClickListener { + bagInfoEntity.description?.let { description-> + bagClickListener?.bagAudio(bagInfoEntity.key,description.audioUrl) + } + } + }else{ + holder.ivBagAudio.visibility = View.INVISIBLE + } + //大小 + val bagSize = format.format(bagInfoEntity.totalSize/(1000*1024*1024.0)) + holder.tvBagSize.text = "${bagSize}G" + + //时间 + bagInfoEntity.timestamp?.let { time-> + val hour = time.substring(8,10) + val min = time.substring(10,12) + val second = time.substring(12,14) + holder.tvBagTime.text = "${hour}:${min}:${second}" + } + } + } + } + } + + override fun getItemCount() = data?.size ?: 0 + + override fun getItemViewType(position: Int): Int { + return data!![position].itemType + } + + class BagTimeTitleHolder(itemView: View): RecyclerView.ViewHolder(itemView){ + var tvBagTimeTitle: TextView = itemView.findViewById(R.id.tvBagTimeTitle) + } + + class BagManagerListHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ + var cbBagSelect: CheckBox = itemView.findViewById(R.id.cbBagSelect) + var etBagNameEdit: EditText = itemView.findViewById(R.id.etBagNameEdit) + var tvBagReportStatus: TextView = itemView.findViewById(R.id.tvBagReportStatus) + var ivBagAudio: ImageView = itemView.findViewById(R.id.ivBagAudio) + var tvBagTime: TextView = itemView.findViewById(R.id.tvBagTime) + var tvBagSize: TextView = itemView.findViewById(R.id.tvBagSize) + } + + fun setListener(listener: BagClickListener){ + bagClickListener = listener + } + + interface BagClickListener{ + //选择Bag包 + fun onClick(bagInfoEntity: BagInfoEntity,isChecked: Boolean) + //上报BI平台 + fun uploadBI(bagInfoEntity: BagInfoEntity) + //编辑Bag包描述信息 + fun editDescription(key: Long,description: BagDescriptionEntity) + //听录音 + fun bagAudio(key: Long,audioUrl: String) + } + +} \ 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 44c7041d9a..f7c6fcd06f 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 @@ -1,5 +1,7 @@ package com.zhjt.mogo_core_function_devatools.badcase.consts +import com.mogo.eagle.core.data.badcase.BagInfoEntity + /** * @author XuXinChao * @description 录包配置参数 @@ -32,5 +34,8 @@ object BadCaseConfig { //自定义Topic清单列表 @JvmField var customTopicList: ArrayList = ArrayList() + //Bag包管理列表 + @JvmField + var bagManagerList: ArrayList = ArrayList() } \ 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/record/Audition.java b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/record/Audition.java new file mode 100644 index 0000000000..f4ec60ac13 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/record/Audition.java @@ -0,0 +1,103 @@ +package com.zhjt.mogo_core_function_devatools.badcase.record; + +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.text.TextUtils; + +//播放试听 +public class Audition implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener{ + private static volatile Audition INSTANCE; + public MediaPlayer mediaPlayer; + private String oldPath; + private OnAuditionListener listener; + + public interface OnAuditionListener { + void onAuditionCompletion(); + + } + + public void registerOnAuditionListener(OnAuditionListener listener) { + this.listener = listener; + } + + public void unregisterOnAuditionListener() { + this.listener = null; + } + + private Audition() { + } + + public static Audition getInstance() { + if (INSTANCE == null) { + synchronized (Audition.class) { + if (INSTANCE == null) { + INSTANCE = new Audition(); + } + } + } + return INSTANCE; + } + + + public boolean isPlaying() { + return mediaPlayer != null && mediaPlayer.isPlaying(); + } + + private void play(String path) { + oldPath = path; + if (mediaPlayer != null) { + mediaPlayer.release(); + mediaPlayer = null; + } + if (mediaPlayer == null) { + mediaPlayer = new MediaPlayer(); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mediaPlayer.setOnPreparedListener(this); + mediaPlayer.setOnCompletionListener(this); + } + try { + mediaPlayer.setDataSource(path); + } catch (Exception e) { + e.printStackTrace(); + } + mediaPlayer.prepareAsync(); + + } + + public void stop() { + oldPath = null; + if (mediaPlayer != null) { + mediaPlayer.stop(); + mediaPlayer.reset(); + } + + } + + public boolean playOrStop(String path) { + if (!TextUtils.equals(oldPath, path)) { + play(path); + return true; + } else { + stop(); + return false; + } + } + + public void onDestroy() { + stop(); + mediaPlayer = null; + } + + @Override + public void onPrepared(MediaPlayer mp) { + mp.start(); + } + + @Override + public void onCompletion(MediaPlayer mp) { + oldPath = null; + if (listener != null) { + listener.onAuditionCompletion(); + } + } +} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_bag_audio.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_bag_audio.png new file mode 100644 index 0000000000000000000000000000000000000000..2959045ff30d8eae9d56d7b4a4279a7cf5a9ba42 GIT binary patch literal 1658 zcmV-=28H>FP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91ET97b1ONa40RR91EC2ui0Q_#}qW}N}SA`GeR^%0?HI5u*qa< z7-2woZ1O4yV?#E!ZnWzP>#qNQ+TQi9TX%1Fhwe}Qp2z<<-#zy~_x$HH2z?+)l7h%Q zi`YbLAWrsTiRyL4wQe?3d4RYgC@6?!5040_k$5|C9kEto8@4s}J7O9noA?;9Uc|n# zbq7vP4a9r(LfMTU_RS&HcOpmp`Ww3$MDH#hqiy6BhKOSpUK+{ZyTm3lh zZ_!pwp!q5L8<7hC>Smf8am+r}`%N!}Z!^ER4yQXm)v1(3PsH&C)Bcejp7`HA5G5rgVDUl|BErLP z|NaB)-g6jt?^+Z(DjF{^R-R$bXGf?o@T+pCz7cER-;BLKlw!?$TX5A}qtKr}X9hAS zjTe2@7q8*cl^Y7ViUwoMV!$R9%6?TkIyw+SF?#KKEjTl;JY9uPw|$59cBgE|3-77v z8KP}#wWH+M3R$M1Vq(As4F=t+@`4&NBmp0;Ux8ssuFrVM(Fz=|IH%Az&X|UT_*l_* zielMrZ&S!sGz<)wk2Shb?$eVoJ8wF8Q8YHS;FrUHDEy8wj6zDvNYU45X+e|aoSCT_X zu4#t(HO^bG23O2Ck&qCFx8HmjuPvJ=4>N37B1Q~P!kzjiSgmc~cx9kWAtAwtkBb)d z<`x@T0|3l3tmy=M_WTvp)ZT$aR!#KU4;}eavACk6BM}$B;kG%daCtyHaTnys6 z$UHiJ$~p$j_XesdeZm;5UA+WTGAE$m#XRgP`dGYbkAt)4F5~YTw?%Vs{2;`}xI%zC z_~Gn!SH{MGV`DpI9{XO(T8?2&fZ5@qg4xKQJ5%Hbp`ju27;W_Wzy1Co9PTtSZ`P9( z9-Z=*dp1~_U0()%5Pn-4NdT6UV=czvw9R^x)7gQIo4-L>d8Jqsqzmy489BeDPIGQ72Nv10bfKR(~FM^1Pq zKAuLpn)9t<#wq}iLp~|%LXdKRlgu4*UV6%7C*{av7r|o&&`p91S%$fp?(>+;v_zk44rwV!AGr~m)}07*qoM6N<$ Ef}msa`v3p{ literal 0 HcmV?d00001 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_bag_no_data.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable-xhdpi/icon_bag_no_data.png new file mode 100644 index 0000000000000000000000000000000000000000..5f4ea0176bbdfed99a9cfa982a3e91b672f0dc9d GIT binary patch literal 17281 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

D zH*0CBvjpL*cYXUXTi(-21$-UsR{}!f;M=rSEGmdAXkB zjgr&!$(s=*qSN3mKD4-Z@Z z{Fx44EAFwdUs*GLgroPU*LqNr(UN0~>U;d5U?<+$=InXyMJfC6sh*?ptV%}YE*7Pn zsmkVmTFZK*NCl{vPA?Io=y&k0I3HCskG*i>Z4UYt-gFKD0oeNQzW@d~|6H4P9_kr* zej=JLzF>hGt9D%#ku}I8PbOU6*5IIJ2Zk82k|PQYHA+m_{C&!p&6T(Szh|x^2bDLT z{}{k7x66fBQRL`!@q3p-I{dnKyWGU5!HPPPA!b2(0sK}4EuSWAYDYBJm!7r;(tZWj$)r~%9p=GCjywY$>IqEYapiDzM%;| zu@R6G{&v!uT&yTfiwhyoUmq+oa?y_U?5Dcw!T-xhHw+IV9L43d4vpQIT!yni$o}$C z!I6ZCm;R4a2Bi>UitQe#`ll1#ej$WZU$OwMC>EiNcqw3KP$IM=_eV;Mgje3vCe=$_ z;Z7v#=Z*|7E&W4TAVW$v-7Au>K9+KUyl;7B2N@M+=q=i;jSLuXr#+b#>7|>tZDF_%8PIwJd@cr8dO)d_sVHmay z8dI*wKptkD?t^-w&*RS<+qWqp%MX`N$R$`a0cF7=`9Gj3#vW4iBgO_y9jggJP%@r` z)?;+M>Z16BMCY~eL;#DH=={G35CjD%x22Q}cWcD_<)tq!OUp;VHO=IkJ#f#W5reAn zSX%eHl3;E45>{CJKLQ2;`TnAL5l>+F4fEXjsm@&j>De~V%*~Bbn_WSlQ2jwgQQ?=N z|81|v&@p*@s57U>0=SUOa&$$-$ZZkJ}N zT}Am=Dg?0IgX<#ZY&xEfNwxE`PY1TY5;ns86!ZBp4dF+8$~L6gm}HeTTQB`| + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bag_reported_button_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bag_reported_button_bg.xml new file mode 100644 index 0000000000..40bd562159 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/bag_reported_button_bg.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_select_button_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_select_button_bg.xml new file mode 100644 index 0000000000..b08f6cbec3 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/cancel_select_button_bg.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/delete_button_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/delete_button_bg.xml new file mode 100644 index 0000000000..7bcbe63d19 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/delete_button_bg.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/icon_bag_edit.png b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/icon_bag_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..09ffe565d777f8880887c16cb1f22af8aee20211 GIT binary patch literal 926 zcmV;P17ZA$P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$?2uVaiR9Fecmq}<8K@^6klNgbp zsKot{gC2x{7lR-X#FH2zi6SV9pdg3{qKFGf@Zfd`UPKf@RFEKoh~OnIAPk5L4lV@I zgNJ|~H6}>ZaT&kA=T#`1nPGYnAN=#G-e2{o=H{{L39ClXX2mmi$&oZz%`5C`zHk;J{P>T zByzvN7Pmm!?FwRJnHPX)D;SbGHUbJ^tNetmqdgTowpbz40uY@6^f=2#!7?x%xY&2v zFM#YT=*+AD#HN9#K=uW!@V0yw{nsMQR7h9Iy9hqVq9aRE%$w%!0Tt!#57xsqHI zX|~((^p{vnI~K&g1WeM(224aN+wR1jCwA6&x&1CKPrt+C;uXL|t?ZH~u*(;>1gAaz zNCiGs0p~sOy%oeyc>J*_Zv`eR0O5X5{BTqpuFvE9qrB@gCVl}-(m~_?wv}h66O^Za zKtZ!JJ{N5>CQ$)hCjQa9ZoX|2$M3P2+yxLsllp!5LnH*TflQCzWi`yM;AIGU_&yjEc%yw^D^cB?x2mdtMvQ3#u8_L5D-A>^_73D& z?QkWrEMg5=h@{a_0Ywv-lSU}U+<7*($j*k>Ri9)X;5gT(1)uiQ%=9a|nM4m6qrBl! z+D+pBVdb}CE25VQ^zNR;=XtHgNWTEO!`1Wi2YsMk8!-a?0000007*qoM6N<$f(+h` ASO5S3 literal 0 HcmV?d00001 diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_ct.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_ct.xml new file mode 100644 index 0000000000..e5075f161d --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_ct.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_drawable.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_drawable.xml new file mode 100644 index 0000000000..353d7da364 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/progress_bar_drawable.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/select_all_button_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/select_all_button_bg.xml new file mode 100644 index 0000000000..8db8728253 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/select_all_button_bg.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_percent_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_percent_bg.xml new file mode 100644 index 0000000000..c4425322f3 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_percent_bg.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_warning_progress_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_warning_progress_bg.xml new file mode 100644 index 0000000000..645b1b3df2 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/space_warning_progress_bg.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/unused_space_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/unused_space_bg.xml new file mode 100644 index 0000000000..efb8967e91 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/unused_space_bg.xml @@ -0,0 +1,8 @@ + + + + diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/upload_cloud_button_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/upload_cloud_button_bg.xml new file mode 100644 index 0000000000..fe4635f8aa --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/upload_cloud_button_bg.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/used_space_bg.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/used_space_bg.xml new file mode 100644 index 0000000000..8d23b4cb9f --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/used_space_bg.xml @@ -0,0 +1,8 @@ + + + + diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_bag_upload.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_bag_upload.xml new file mode 100644 index 0000000000..0f76ebdba2 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_bag_upload.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_space_warning.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_space_warning.xml new file mode 100644 index 0000000000..5cfa0f954f --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/dialog_space_warning.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_manager.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_manager.xml new file mode 100644 index 0000000000..8cd8a75b48 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_manager.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_time_title.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_time_title.xml new file mode 100644 index 0000000000..38ccd6bf86 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/item_bag_time_title.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_manager.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_manager.xml new file mode 100644 index 0000000000..6a86a27676 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_manager.xml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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/setting/ToolsView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt index 62341fb157..a81a76c890 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt @@ -53,6 +53,10 @@ class ToolsView private constructor() { override fun showSOPSettingView() { sopView.toggle(it) } + + override fun showBadCaseManagerView() { + ToastUtils.showShort("代码合并中") + } }) } toolsViewFloat = WarningFloat.with(it) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt index 4a40e3c053..f120cf33e1 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt @@ -100,6 +100,10 @@ internal class AutoPilotAndCheckView @JvmOverloads constructor( sopLayout.setOnClickListener { clickListener?.showSOPSettingView() } + managerLayout.setOnClickListener { + //录包管理页面 + clickListener?.showBadCaseManagerView() + } ivDebugPanel.setOnClickListener { clickListener?.showDebugPanelView() @@ -225,6 +229,7 @@ internal class AutoPilotAndCheckView @JvmOverloads constructor( fun showDebugPanelView() fun showFeedbackView() fun showSOPSettingView() + fun showBadCaseManagerView() } override fun onAutopilotCarConfig(carConfigResp: MessagePad.CarConfigResp) { diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/debug_icon_bag_manager.png b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xhdpi/debug_icon_bag_manager.png new file mode 100644 index 0000000000000000000000000000000000000000..8dc2dff73f1e0769f569aaa51277933fffafa463 GIT binary patch literal 17440 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 + + + + + + + + 调试面板 录包设置 运营面板 + 录包管理 车速设置 账户信息 系统运行 diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagDescriptionEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagDescriptionEntity.kt new file mode 100644 index 0000000000..823e6dfb24 --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagDescriptionEntity.kt @@ -0,0 +1,12 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description bag附加信息(录音,备注,接管信息) + * @since: 2023/2/2 + */ +data class BagDescriptionEntity(var description: String,// bag接管描述或重命名信息 + var hasAudio: Boolean,// 此bag是否具有录音文件 + var audioUrl: String,// bag附加录音文件的文件名 + var reportBI: Boolean //上报BI状态 + ) \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagInfoEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagInfoEntity.kt new file mode 100644 index 0000000000..8b15aee887 --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagInfoEntity.kt @@ -0,0 +1,20 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description 单个key值对应的包信息 + * @since: 2023/2/1 + */ +class BagInfoEntity(){ + var key: Long = 0// bag key值 + var totalSize: Long = 0// 所有子包或合并后的包的总大小 + var timestamp: String = ""// 时间戳 + var bagPath: String ?= null// bag所在路径 + var mergeStat: Boolean = false// 合并状态 + var uploadStat: Boolean = false// 上传cos桶状态 + var description: BagDescriptionEntity ?= null// 包描述信息 + var subBags: ArrayList =ArrayList()// 子包信息 + var selectStatus: Boolean = false //Bag包勾选状态,默认为未勾选 + var itemType: Int = 0 //0是正常Bag包,1为时间Title + var timeStr: String = "" +} \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagManagerEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagManagerEntity.kt new file mode 100644 index 0000000000..21bf91c857 --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagManagerEntity.kt @@ -0,0 +1,15 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description 包管理请求 + * @since: 2023/2/1 + */ +class BagManagerEntity(){ + var reqType: Int = 1// 请求类型:0-invalid 1-获取空间使用信息 2-遍历所有bag 3-上传cos 4-删除bag 5-为bag添加附加信息 + var keyReq: Long =0// 要操作的包的key值,发送请求且reqType=(3,4,5)时有效 + var descReq: BagDescriptionEntity ?= null// 更新包附加信息,发送请求且reqType=5时有效 + var spaceInfoResp: List = ArrayList()// 空间使用信息,获取响应且reqType=1时有效 + val bagsInfoResp: MutableList = ArrayList()// 包信息列表,获取响应且reqType=2时有效 + var uploadCosResp: UploadCosStatEntity ?=null//反馈上传cos桶结果,获取响应且reqType=3时有效 +} \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagSpaceInfoEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagSpaceInfoEntity.kt new file mode 100644 index 0000000000..ce7651e0f2 --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/BagSpaceInfoEntity.kt @@ -0,0 +1,11 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description bag目录空间使用情况 + * @since: 2023/2/1 + */ +data class BagSpaceInfoEntity(var host: String,// 主机名 + var diskSpaceInfo: SpaceInfoEntity,// 硬盘空间信息 + var BagDirsSpaceInfo: List// /home/mogo/data/bags下各子空间信息 + ) \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SpaceInfoEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SpaceInfoEntity.kt new file mode 100644 index 0000000000..fdf174bf4e --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SpaceInfoEntity.kt @@ -0,0 +1,13 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description 车端BadCase存储空间使用情况 + * @since: 2023/2/1 + */ +data class SpaceInfoEntity( + var directory: String,// 路径名,为空表示总空间,否则表示对应的/home/mogo/data/bags下的子目录 + var total: Long,// 总空间 + var free: Long,// 可用空间 + var used: Long // 已用空间 + ) \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SubBagEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SubBagEntity.kt new file mode 100644 index 0000000000..c52c375ab5 --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/SubBagEntity.kt @@ -0,0 +1,11 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description 各主机上报的包信息 + * @since: 2023/2/1 + */ +data class SubBagEntity(var key: Long,//bag key值 + var host: String,//主机名 + var size: Long //此子包的大小 + ) \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/UploadCosStatEntity.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/UploadCosStatEntity.kt new file mode 100644 index 0000000000..ae8d276ace --- /dev/null +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/badcase/UploadCosStatEntity.kt @@ -0,0 +1,11 @@ +package com.mogo.eagle.core.data.badcase + +/** + * @author XuXinChao + * @description 上传cos桶状态 + * @since: 2023/2/1 + */ +data class UploadCosStatEntity(var key: Long, + var stat: Int,// 0-成功 1-执行中 2-copy过程失败 3-合并过程失败 4-上传过程失败 + var message: String// 失败时的具体描述 + ) \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotControlProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotControlProvider.kt index e1c50cce6c..cc070805e1 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotControlProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotControlProvider.kt @@ -2,6 +2,7 @@ package com.mogo.eagle.core.function.api.autopilot import chassis.SpecialVehicleTaskCmdOuterClass import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters +import com.mogo.eagle.core.data.badcase.BagManagerEntity import com.mogo.eagle.core.data.trafficlight.TrafficLightResult import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider @@ -187,6 +188,12 @@ interface IMoGoAutopilotControlProvider : IMoGoFunctionServerProvider { */ fun getBadCaseConfig(reqType: Int,recordType: Int,topicsNeedToCache: List): Boolean + /** + * 获取Bag包管理信息 + * @param bagManagerEntity 包管理请求实体类 + */ + fun sendBagManagerCmd(bagManagerEntity: BagManagerEntity): Boolean + /** * 发送工控机所有节点重启命令 */ diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotRecordListener.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotRecordListener.kt index e622e30726..4cca4b7e3d 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotRecordListener.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotRecordListener.kt @@ -1,5 +1,6 @@ package com.mogo.eagle.core.function.api.autopilot +import bag_manager.BagManagerOuterClass import mogo.telematics.pad.MessagePad import record_cache.RecordPanelOuterClass @@ -20,4 +21,9 @@ interface IMoGoAutopilotRecordListener { */ fun onAutopilotRecordConfig(config: MessagePad.RecordDataConfig){} + /** + * 录包任务管理应答 + */ + fun onBagManagerResult(bagManager: BagManagerOuterClass.BagManager){} + } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotControlManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotControlManager.kt index 1140e23f39..6798098a60 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotControlManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotControlManager.kt @@ -3,6 +3,7 @@ package com.mogo.eagle.core.function.call.autopilot import android.os.SystemClock import chassis.SpecialVehicleTaskCmdOuterClass import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters +import com.mogo.eagle.core.data.badcase.BagManagerEntity import com.mogo.eagle.core.data.config.FunctionBuildConfig import com.mogo.eagle.core.data.constants.MogoServicePaths import com.mogo.eagle.core.data.deva.bizconfig.FuncBizConfig @@ -268,6 +269,19 @@ object CallerAutoPilotControlManager { } } + /** + * 获取Bag包管理信息 + * @param bagManagerEntity 包管理请求实体类 + */ + fun sendBagManagerCmd(bagManagerEntity: BagManagerEntity): Boolean?{ + // 司机屏才能查询数据采集的配置 + if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){ + return providerApi?.sendBagManagerCmd(bagManagerEntity) + }else{ + return false + } + } + /** * 向左变道 */ diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotRecordListenerManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotRecordListenerManager.kt index 5ae8d5a153..5eb0bfa59c 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotRecordListenerManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotRecordListenerManager.kt @@ -1,5 +1,6 @@ package com.mogo.eagle.core.function.call.autopilot +import bag_manager.BagManagerOuterClass import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener import com.mogo.eagle.core.function.call.base.CallerBase import mogo.telematics.pad.MessagePad @@ -34,4 +35,15 @@ object CallerAutopilotRecordListenerManager : CallerBase