[6.2.0]AI数据采集改版,数据由MIS后台动态获取

This commit is contained in:
xuxinchao
2023-11-15 19:54:47 +08:00
parent 70ce14ff58
commit 4d634a2a75
10 changed files with 252 additions and 240 deletions

View File

@@ -6,15 +6,18 @@ import android.graphics.PixelFormat
import android.os.SystemClock
import android.util.DisplayMetrics
import android.view.*
import android.widget.RadioButton
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.data.deva.badcase.AiDataEntity
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener
import com.mogo.eagle.core.function.api.devatools.badcase.BadCaseNetListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsNetManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
@@ -23,11 +26,15 @@ import com.mogo.eagle.core.utilcode.util.BarUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.TimeUtils
import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.zhjt.mogo_core_function_devatools.R
import com.zhjt.mogo_core_function_devatools.badcase.biz.adapter.AiDataListAdapter
import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.BadCaseNetManager
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import record_cache.RecordPanelOuterClass
import java.lang.StringBuilder
import java.util.*
/**
@@ -36,7 +43,7 @@ import java.util.*
* @since: 2022/7/12
*/
class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener,
IMoGoAutopilotRecordListener {
IMoGoAutopilotRecordListener , BadCaseNetListener {
companion object {
const val TAG = "AIDataCollectWindow"
@@ -49,18 +56,12 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
private lateinit var tvCollectNum: TextView //采集弹窗数量
private lateinit var tvCollectTime: TextView //采集时间
private lateinit var rbLargeCar: RadioButton //大型车
private lateinit var rbTrafficLight: RadioButton //交通灯
private lateinit var rbWater: RadioButton //积水
private lateinit var rbConstruction: RadioButton //施工
private lateinit var rbAccident: RadioButton //车祸路段
private lateinit var rbRain: RadioButton //中雨交通流
private lateinit var rbNightTraffic: RadioButton //夜间交通流
private lateinit var tvCollectReport: TextView //上报按钮
private lateinit var tvCollectCancel: TextView //取消按钮
private var collectReason: String = "大型车:大货、大巴、特种车辆"
private var collectReason: StringBuilder = StringBuilder()
private var aiDataListAdapter: AiDataListAdapter?= null
@Volatile
private var recordKey: String? = null //录制bag包key
@@ -77,6 +78,7 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
private var mInScreenY = 0f
private var clickListener: ClickListener? = null
private var rvCollectList: RecyclerView ?= null
init {
initFloatWindow();
@@ -93,15 +95,7 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
mFloatLayout.setOnTouchListener(this)
tvCollectNum = mFloatLayout.findViewById(R.id.tvCollectNum)
tvCollectTime = mFloatLayout.findViewById(R.id.tvCollectTime)
rbLargeCar = mFloatLayout.findViewById(R.id.rbLargeCar)
rbTrafficLight = mFloatLayout.findViewById(R.id.rbTrafficLight)
rbWater = mFloatLayout.findViewById(R.id.rbWater)
rbConstruction = mFloatLayout.findViewById(R.id.rbConstruction)
rbAccident = mFloatLayout.findViewById(R.id.rbAccident)
rbRain = mFloatLayout.findViewById(R.id.rbRain)
rbNightTraffic = mFloatLayout.findViewById(R.id.rbNightTraffic)
rvCollectList = mFloatLayout.findViewById(R.id.rvCollectList)
tvCollectReport = mFloatLayout.findViewById(R.id.tvCollectReport)
tvCollectCancel = mFloatLayout.findViewById(R.id.tvCollectCancel)
if (BadCaseConfig.windowNum < 1) {
@@ -120,107 +114,39 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
20,
12
)
//大型车
rbLargeCar.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = true,
trafficLightStatus = false,
waterStatus = false,
constructionStatus = false,
accidentStatus = false,
rainStatus = false,
nightTrafficStatus = false
)
collectReason = "大型车:大货、大巴、特种车辆"
}
//交通灯
rbTrafficLight.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = false,
trafficLightStatus = true,
waterStatus = false,
constructionStatus = false,
accidentStatus = false,
rainStatus = false,
nightTrafficStatus = false
)
collectReason = "交通灯:水平、箭头、雨天交通灯"
}
//积水
rbWater.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = false,
trafficLightStatus = false,
waterStatus = true,
constructionStatus = false,
accidentStatus = false,
rainStatus = false,
nightTrafficStatus = false
)
collectReason = "积水距离10米内面积大于1平米"
}
//施工
rbConstruction.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = false,
trafficLightStatus = false,
waterStatus = false,
constructionStatus = true,
accidentStatus = false,
rainStatus = false,
nightTrafficStatus = false
)
collectReason = "施工:锥桶、路障"
}
//车祸路段
rbAccident.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = false,
trafficLightStatus = false,
waterStatus = false,
constructionStatus = false,
accidentStatus = true,
rainStatus = false,
nightTrafficStatus = false
)
collectReason = "车祸路段:有三角板"
}
//中雨交通流
rbRain.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = false,
trafficLightStatus = false,
waterStatus = false,
constructionStatus = false,
accidentStatus = false,
rainStatus = true,
nightTrafficStatus = false
)
collectReason = "中雨交通流"
}
//夜间交通流
rbNightTraffic.setOnClickListener {
setRadioButtonStatus(
largeCarStatus = false,
trafficLightStatus = false,
waterStatus = false,
constructionStatus = false,
accidentStatus = false,
rainStatus = false,
nightTrafficStatus = true
)
collectReason = "夜间交通流"
}
val linearLayoutManager = LinearLayoutManager(mActivity)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
rvCollectList?.layoutManager = linearLayoutManager
aiDataListAdapter = AiDataListAdapter()
aiDataListAdapter?.setListener(object: AiDataListAdapter.AiDataClickListener{
override fun onClick(reason: String, isChecked: Boolean) {
if(isChecked){
collectReason.append(reason)
}else{
val index = collectReason.indexOf(reason)
collectReason.delete(index,index+reason.length)
}
}
})
rvCollectList?.adapter = aiDataListAdapter
//注册网络接口获取数据监听
CallerDevaToolsNetManager.addListener(TAG,this)
//获取数据
BadCaseNetManager.badCaseNetManager.getAiData()
//上报
tvCollectReport.setOnClickListener {
if(collectReason.isBlank()){
ToastUtils.showShort("请选择最少一个原因")
return@setOnClickListener
}
GlobalScope.launch {
val uploadResult = presenter.upload(mutableMapOf<String, String>().also { itx ->
itx["carLicense"] = AppConfigInfo.plateNumber ?: "" //车牌号
itx["filename"] = recordFileName ?: "" //bag包文件地址
itx["filesize"] = "0" //bag包文件大小
itx["key"] = recordKey ?: "" //key
itx["reason"] = collectReason //采集原因
itx["reason"] = collectReason.toString() //采集原因
itx["duration"] = "20" //采集时长固定为20S
itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式)
itx["channel"] = "AI" //渠道
@@ -279,24 +205,6 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
}
private fun setRadioButtonStatus(
largeCarStatus: Boolean,
trafficLightStatus: Boolean,
waterStatus: Boolean,
constructionStatus: Boolean,
accidentStatus: Boolean,
rainStatus: Boolean,
nightTrafficStatus: Boolean
) {
rbLargeCar.isChecked = largeCarStatus
rbTrafficLight.isChecked = trafficLightStatus
rbWater.isChecked = waterStatus
rbConstruction.isChecked = constructionStatus
rbAccident.isChecked = accidentStatus
rbRain.isChecked = rainStatus
rbNightTraffic.isChecked = nightTrafficStatus
}
override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean {
when (motionEvent?.action) {
MotionEvent.ACTION_DOWN -> {
@@ -336,6 +244,8 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
fun hideFloatWindow() {
//注销采集结果回调监听
CallerAutopilotRecordListenerManager.removeListener(this.hashCode().toString())
//注销网络接口监听
CallerDevaToolsNetManager.removeListener(this)
// 移除 ADAS车辆状态&定位 监听
CallerChassisLocationWGS84ListenerManager.removeListener(this.hashCode().toString())
if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout)
@@ -349,4 +259,11 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
fun closeWindow()
}
override fun onAiDataResponse(list: List<AiDataEntity>) {
if(list.isNotEmpty()){
//刷新列表
aiDataListAdapter?.setData(list)
}
}
}

View File

@@ -0,0 +1,62 @@
package com.zhjt.mogo_core_function_devatools.badcase.biz.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.RadioButton
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.data.deva.badcase.AiDataEntity
import com.zhjt.mogo_core_function_devatools.R
/**
* AI数据采集适配器
*/
class AiDataListAdapter: RecyclerView.Adapter<AiDataListAdapter.AiDataHolder>() {
private var data:List<AiDataEntity> ?= null
private var clickListener: AiDataClickListener ?= null
fun setData(data: List<AiDataEntity>){
this.data = data
notifyDataSetChanged()
}
fun setListener(listener: AiDataClickListener){
clickListener = listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AiDataHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_ai_data, parent, false)
return AiDataHolder(view)
}
override fun onBindViewHolder(holder: AiDataHolder, position: Int) {
data?.let {
val entity = it[position]
if(entity.content.isBlank()){
holder.rbDataSelect.text = entity.name
}else{
holder.rbDataSelect.text = "${entity.name}${entity.content}"
}
holder.rbDataSelect.isChecked = entity.isChecked
holder.rbDataSelect.tag = entity
holder.rbDataSelect.setOnCheckedChangeListener { _, isChecked ->
clickListener?.onClick(holder.rbDataSelect.text.toString(),isChecked)
entity.isChecked = isChecked
}
}
}
override fun getItemCount() = data?.size ?: 0
class AiDataHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
var rbDataSelect: CheckBox = itemView.findViewById(R.id.rbDataSelect)
}
interface AiDataClickListener{
fun onClick(reason: String,isChecked: Boolean)
}
}

View File

@@ -1,9 +1,13 @@
package com.zhjt.mogo_core_function_devatools.badcase.repository.net
import com.mogo.commons.constants.HostConst
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.network.apiCall
import com.mogo.eagle.core.network.request
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.BadCaseApi
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult
@@ -55,4 +59,31 @@ internal class BadCaseNetModel {
CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "upload_error:$t")
null
}
private fun getNetWorkApi(baseUrl: String ="http://eagle-qa.zhidaozhixing.com"): BadCaseApi{
return MoGoRetrofitFactory.getInstanceNoCallAdapter(baseUrl)
.create(BadCaseApi::class.java)
}
fun getAiData(onSuccess: ((String) -> Unit),onError: ((String) -> Unit)){
request<BaseResponse<Any?>>{
loader{
apiCall{
getNetWorkApi().getAiData()
}
}
onSuccess{
if(it.msg == "success"){
onSuccess.invoke(GsonUtils.toJson(it.result))
}else{
onError.invoke(it.msg)
}
}
onError{
it.message?.let { it1 -> onError.invoke(it1) }
}
}
}
}

View File

@@ -1,5 +1,7 @@
package com.zhjt.mogo_core_function_devatools.badcase.repository.net.api
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.data.deva.badcase.AiDataEntity
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult
import retrofit2.Response
@@ -13,4 +15,10 @@ internal interface BadCaseApi {
@GET("eagle-eye-dns/yycp-vehicle-management-service/tool/badcase/reasons")
suspend fun get(@Query("channel", encoded = true) channel: String, @Query("pageNo") pageNo: Int): Response<BadCaseResponse>
/**
* 获取AI数据采集列表数据
*/
@GET("eagleEye-mis/dataGather/select/active")
suspend fun getAiData(): BaseResponse<List<AiDataEntity>>
}

View File

@@ -0,0 +1,44 @@
package com.zhjt.mogo_core_function_devatools.badcase.repository.net.api
import com.mogo.eagle.core.data.deva.badcase.AiDataEntity
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsNetManager
import com.zhjt.mogo_core_function_devatools.badcase.repository.net.BadCaseNetModel
import org.json.JSONArray
import org.json.JSONObject
class BadCaseNetManager {
companion object{
val badCaseNetManager: BadCaseNetManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED){
BadCaseNetManager()
}
}
private val badCaseNetModel = BadCaseNetModel()
fun getAiData(){
badCaseNetModel.getAiData(
onSuccess =
{
val list = ArrayList<AiDataEntity>()
val result = JSONArray(it)
if(result.length()>0){
for(i in 0 until result.length()){
val jsonObject = result[i] as JSONObject
val id = jsonObject.optInt("id")
val name = jsonObject.optString("name")
val content = jsonObject.optString("content")
val entity = AiDataEntity(id, name, content,false)
list.add(entity)
}
}
//将结果回调到调用页面
CallerDevaToolsNetManager.invokeAiDataResponse(list)
},
onError =
{
})
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rbDataSelect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"
android:textSize="@dimen/sp_34"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
android:layout_margin="@dimen/dp_15"
>
</CheckBox>

View File

@@ -23,7 +23,6 @@
android:textColor="#FFFFFFFF"
android:textSize="46dp"
android:gravity="center"
android:text="1"
/>
<TextView
@@ -33,120 +32,22 @@
app:layout_constraintLeft_toRightOf="@id/tvCollectNum"
app:layout_constraintTop_toTopOf="@id/tvCollectNum"
app:layout_constraintBottom_toBottomOf="@id/tvCollectNum"
android:text="时间14:23:10"
android:textColor="#FFFFFFFF"
android:textSize="38dp"
android:layout_marginStart="@dimen/dp_50"
/>
<RadioButton
android:id="@+id/rbLargeCar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="大型车:大货、大巴、特种车辆"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintLeft_toLeftOf="parent"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvCollectList"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0"
app:layout_constraintTop_toBottomOf="@id/tvCollectNum"
android:layout_marginStart="@dimen/dp_50"
android:layout_marginTop="@dimen/dp_50"
android:checked="true"
/>
<RadioButton
android:id="@+id/rbTrafficLight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="交通灯:水平、箭头、雨天交通灯"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintTop_toBottomOf="@id/rbLargeCar"
app:layout_constraintLeft_toLeftOf="@id/rbLargeCar"
android:layout_marginTop="@dimen/dp_30"
/>
<RadioButton
android:id="@+id/rbWater"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="积水距离10米内面积大于1平米"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintTop_toBottomOf="@id/rbTrafficLight"
app:layout_constraintLeft_toLeftOf="@id/rbTrafficLight"
android:layout_marginTop="@dimen/dp_30"
/>
<RadioButton
android:id="@+id/rbConstruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="施工:锥桶、路障"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintTop_toBottomOf="@id/rbWater"
app:layout_constraintLeft_toLeftOf="@id/rbWater"
android:layout_marginTop="@dimen/dp_30"
/>
<RadioButton
android:id="@+id/rbAccident"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="车祸路段:有三角板"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintTop_toTopOf="@id/rbConstruction"
app:layout_constraintBottom_toBottomOf="@id/rbConstruction"
app:layout_constraintLeft_toRightOf="@id/rbConstruction"
android:layout_marginStart="@dimen/dp_50"
/>
<RadioButton
android:id="@+id/rbRain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="中雨交通流"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintTop_toBottomOf="@id/rbConstruction"
app:layout_constraintLeft_toLeftOf="@id/rbConstruction"
android:layout_marginTop="@dimen/dp_30"
/>
<RadioButton
android:id="@+id/rbNightTraffic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="夜间交通流"
android:textColor="#FFFFFFFF"
android:textSize="34dp"
android:button="@null"
android:drawableLeft="@drawable/badcase_radio_button_style"
android:drawablePadding="@dimen/dp_20"
app:layout_constraintTop_toBottomOf="@id/rbAccident"
app:layout_constraintLeft_toLeftOf="@id/rbAccident"
android:layout_marginTop="@dimen/dp_30"
app:layout_constraintBottom_toTopOf="@id/tvCollectReport"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:layout_margin="@dimen/dp_25"
/>
<TextView