Merge branch 'dev_arch_opt_3.0' into dev_robobus-m1-p-app-module_1.0.0_230112_1.0.0

# Conflicts:
#	app/src/main/java/com/mogo/launcher/stageone/ConfigStartUp.kt
This commit is contained in:
yangyakun
2023-01-30 15:12:39 +08:00
126 changed files with 5436 additions and 1643 deletions

View File

@@ -11,6 +11,7 @@ import com.mogo.eagle.function.biz.monitoring.CronTaskManager.Companion.cronTask
import com.mogo.eagle.function.biz.notice.NoticeSocketManager.Companion.noticeSocketManager
import com.mogo.eagle.function.biz.notice.network.NoticeNetWorkManager
import com.mogo.eagle.function.biz.v2x.speedlimit.SpeedLimitDataManager
import com.mogo.eagle.function.biz.v2x.speedlimit.SpeedLimitDispatcher
import com.mogo.eagle.function.biz.v2x.trafficlight.core.MogoTrafficLightManager
import com.mogo.eagle.function.biz.v2x.trafficlight.core.TrafficLightDispatcher
import com.mogo.eagle.function.biz.v2x.vip.VipCarManager
@@ -30,6 +31,7 @@ class FuncBizProvider : IMoGoFuncBizProvider {
TrafficLightDispatcher.INSTANCE.initServer(context) //todo 红绿灯中心模块放入dataCenter
VipCarManager.INSTANCE.initServer(context)
SpeedLimitDataManager.getInstance().start()
SpeedLimitDispatcher.INSTANCE.initLimit(context)
// RedLightWarningManager.INSTANCE.listenTrafficLight()
}

View File

@@ -61,15 +61,16 @@ public class SpeedLimitDataManager implements IMoGoChassisLocationGCJ02Listener
@BizConfig(biz = V2I, dependentBizNode = "", bizNode = BIZ_SLW)
private void getSpeedLimit() {
if (!isShowObuLimitSpeedView) {
// if (!isShowObuLimitSpeedView) {
int speedLimit = CallerMapUIServiceManager.INSTANCE.getMapUIController().getLimitSpeed(mLocation.getLongitude(), mLocation.getLatitude(), (float) mLocation.getHeading());
UiThreadHandler.post(() -> {
if (speedLimit > 0) {
CallerHmiManager.INSTANCE.showLimitingVelocity(speedLimit);
// CallerHmiManager.INSTANCE.showLimitingVelocity(speedLimit, 1);
CallLimitingVelocityListenerManager.INSTANCE.invokeOnLimitingVelocityChange(speedLimit);
}
});
}
// }
}
}

View File

@@ -0,0 +1,70 @@
package com.mogo.eagle.function.biz.v2x.speedlimit
import android.content.Context
import com.mogo.eagle.core.function.api.v2x.LimitingVelocityListener
import com.mogo.eagle.core.function.api.v2x.ObuLimitingSpeedListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.trafficlight.CallerTrafficLightListenerManager
import com.mogo.eagle.core.function.call.v2x.CallLimitingVelocityListenerManager
import com.mogo.eagle.core.function.call.v2x.CallObuLimitingSpeedListenerManager
/**
* @author lixiaopeng
* @description 对多个限速进行调度maprsu ...
* @since: 2023/1/12
*/
class SpeedLimitDispatcher : LimitingVelocityListener, ObuLimitingSpeedListener {
companion object {
const val TAG = "SpeedLimitDispatcher"
val INSTANCE: SpeedLimitDispatcher by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
SpeedLimitDispatcher()
}
}
private var mContext: Context? = null
//是否有AI获取红绿灯灯态
private var hasObuStatus: Boolean = false
fun initLimit(context: Context) {
mContext = context
//注册监听MAP的限速
CallLimitingVelocityListenerManager.addListener(TAG, this)
//注册监听OBU的限速
CallObuLimitingSpeedListenerManager.addListener(TAG, this)
}
/**
* 地图限速数据
*/
override fun onLimitingVelocityChange(limitingVelocity: Int) {
// CallerHmiManager.disableLimitingVelocity()
if (!hasObuStatus) {
CallerHmiManager.showLimitingVelocity(limitingVelocity, 1)
}
}
/**
* obu限速
*/
override fun onObuLimitingSpeedChange(limitingSpeed: Int) {
// CallerHmiManager.disableLimitingVelocity()
if (limitingSpeed > 0) {
hasObuStatus = true
CallerHmiManager.showLimitingVelocity(limitingSpeed, 2)
} else {
hasObuStatus = false
CallerHmiManager.disableLimitingVelocity()
}
}
fun destroy() {
//取消注册监听AI云获取红绿灯状态
CallerTrafficLightListenerManager.removeListener(TAG)
//取消注册监听工控机感知红绿灯
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
}
}

View File

@@ -4,9 +4,11 @@ import android.content.Context
import android.os.Handler
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.obu.IMoGoObuTrafficLightListener
import com.mogo.eagle.core.function.api.trafficlight.IMoGoTrafficLightListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.obu.CallerObuTrafficLightListenerManager
import com.mogo.eagle.core.function.call.trafficlight.CallerTrafficLightListenerManager
import com.mogo.eagle.function.biz.v2x.trafficlight.TrafficLightHMIManager
import perception.TrafficLightOuterClass
@@ -17,26 +19,36 @@ import perception.TrafficLightOuterClass.TrafficLight
* @description 对多个红绿灯信号来源进行统一调度AI云、工控机
* @since: 2022/4/28
*/
class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener , IMoGoTrafficLightListener {
class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLightListener,
IMoGoObuTrafficLightListener {
companion object{
companion object {
const val TAG = "TrafficLightDispatcher"
val INSTANCE: TrafficLightDispatcher by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED){
val INSTANCE: TrafficLightDispatcher by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
TrafficLightDispatcher()
}
}
private var mContext: Context? = null
//是否有AI获取红绿灯灯态
private var hasAiLightStatus: Boolean = false
//obu数据
private var hasObuLightStatus: Boolean = false
fun initServer(context: Context){
fun initServer(context: Context) {
mContext = context
//注册监听AI云获取红绿灯状态,注册监听AI云进入路口,注册监听红绿灯请求失败
//注册监听AI云获取红绿灯状态
CallerTrafficLightListenerManager.addListener(TAG, this)
//注册监听AI云进入路口
CallerTrafficLightListenerManager.addListener(TAG, this)
//注册监听红绿灯请求失败
CallerTrafficLightListenerManager.addListener(TAG, this)
//注册监听工控机感知红绿灯
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
//obu红绿灯数据
CallerObuTrafficLightListenerManager.addListener(TAG, this)
}
/**
@@ -44,46 +56,48 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener , IMoGoTrafficLigh
* @param trafficLights 感知红绿灯
*/
override fun onAutopilotPerceptionTrafficLight(trafficLights: TrafficLightOuterClass.TrafficLights?) {
if(!hasAiLightStatus){
trafficLights?.let { it ->
var light :TrafficLight?= null
if(it.hasStraight()){
light = it.straight
}else if(it.hasLeft()){
light = it.left
}else if(it.hasRight()){
light = it.right
}else if(it.hasUTurn()){
light = it.uTurn
}
if(light == null){
//隐藏红绿灯显示
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
}else{
when (light.state) {
TrafficLightOuterClass.LightState.STATE_RED -> {
//红灯
CallerHmiManager.showWarningTrafficLight(1,2)
CallerHmiManager.changeCountdownGreen(0)
}
TrafficLightOuterClass.LightState.STATE_YELLOW -> {
//黄灯
CallerHmiManager.showWarningTrafficLight(2,2)
CallerHmiManager.changeCountdownGreen(0)
}
TrafficLightOuterClass.LightState.STATE_GREEN -> {
//绿灯
CallerHmiManager.showWarningTrafficLight(3,2)
CallerHmiManager.changeCountdownGreen(0)
}
TrafficLightOuterClass.LightState.STATE_OFF -> {
//黑灯,隐藏红绿灯显示
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
}
else -> {}
if (!hasObuLightStatus) {
if (!hasAiLightStatus) {
trafficLights?.let { it ->
var light: TrafficLight? = null
if (it.hasStraight()) {
light = it.straight
} else if (it.hasLeft()) {
light = it.left
} else if (it.hasRight()) {
light = it.right
} else if (it.hasUTurn()) {
light = it.uTurn
}
if (light == null) {
//隐藏红绿灯显示
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
} else {
when (light.state) {
TrafficLightOuterClass.LightState.STATE_RED -> {
//红灯
CallerHmiManager.showWarningTrafficLight(1, 2)
CallerHmiManager.changeCountdownGreen(0)
}
TrafficLightOuterClass.LightState.STATE_YELLOW -> {
//黄灯
CallerHmiManager.showWarningTrafficLight(2, 2)
CallerHmiManager.changeCountdownGreen(0)
}
TrafficLightOuterClass.LightState.STATE_GREEN -> {
//绿灯
CallerHmiManager.showWarningTrafficLight(3, 2)
CallerHmiManager.changeCountdownGreen(0)
}
TrafficLightOuterClass.LightState.STATE_OFF -> {
//黑灯,隐藏红绿灯显示
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
}
else -> {}
}
}
}
}
}
}
}
@@ -92,21 +106,28 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener , IMoGoTrafficLigh
* AI云获取红绿灯状态
*/
override fun onTrafficLightStatus(trafficLightResult: TrafficLightResult) {
TrafficLightHMIManager.INSTANCE.updateTrafficLight(trafficLightResult)
hasAiLightStatus = true
if (!hasObuLightStatus) {
TrafficLightHMIManager.INSTANCE.updateTrafficLight(trafficLightResult)
hasAiLightStatus = true
}
}
/**
* 车辆进入路口
* 车辆进入路口回调
* @param enter true:进入路口false:离开路口
*/
override fun onEnterCrossRoad(enter: Boolean) {
if(!enter){
if (!enter) {
Handler().postDelayed({
hasAiLightStatus = false
hasObuLightStatus = false
}, 5000)
CallerTrafficLightListenerManager.resetTrafficLightData()
//如果没有OBU灯态则进行隐藏如果有OBU灯态则交由OBU管理
if(!hasObuLightStatus){
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
}
}
}
/**
@@ -114,14 +135,32 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener , IMoGoTrafficLigh
*/
override fun onTrafficRequestError() {
hasAiLightStatus = false
CallerTrafficLightListenerManager.resetTrafficLightData()
if(!hasObuLightStatus){
if (TrafficLightHMIManager.INSTANCE.isWarningTrafficLightShow()) {
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
}
}
}
/**
* obu 红绿灯数据
*/
override fun onObuTrafficLight(light: Int) {
super.onObuTrafficLight(light)
hasObuLightStatus = true
CallerHmiManager.showWarningTrafficLight(light, 3)
}
fun destroy(){
//取消注册监听AI云获取红绿灯状态,取消注册监听红绿灯请求失败,取消注册监听AI云进入路口
fun destroy() {
//取消注册监听AI云获取红绿灯状态
CallerTrafficLightListenerManager.removeListener(TAG)
//取消注册监听工控机感知红绿灯
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
//取消注册监听红绿灯请求失败
CallerTrafficLightListenerManager.removeListener(TAG)
//取消注册监听AI云进入路口
CallerTrafficLightListenerManager.removeListener(TAG)
}
}

View File

@@ -52,6 +52,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListener
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningTrajectoryListenerManager.invokeAutopilotTrajectory
import com.mogo.eagle.core.function.call.autopilot.CallerStartAutopilotFailedListenerManager.invokeStartAutopilotFailed
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.obucombine.CallerObuDcCombineListenerManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.zhidao.support.adas.high.AdasManager
@@ -533,8 +534,9 @@ class MoGoAdasListenerImpl : OnAdasListener {
* @param obuWarningData 数据
*/
override fun onObuWarningData(header: MessagePad.Header?, obuWarningData: ObuWarningEvent.ObuWarningData?) {
CallerObuDcCombineListenerManager.invokeObuDcData(obuWarningData)
}
/**
* 重构后的功能状态
*

View File

@@ -3,7 +3,6 @@ package com.mogo.eagle.core.function.msgbox
import android.content.Context
import android.os.Looper
import com.mogo.eagle.core.data.msgbox.*
import com.mogo.eagle.core.data.notice.NoticeNormalData
import com.mogo.eagle.core.data.report.ReportEntity
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxListenerManager
import com.mogo.eagle.core.function.msgbox.db.MsgBoxDb

View File

@@ -11,10 +11,19 @@ import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.RecordBagMsg
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
import com.mogo.eagle.core.utilcode.util.*
import com.zhjt.mogo_core_function_devatools.badcase.biz.*
import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
@@ -27,7 +36,7 @@ import record_cache.RecordPanelOuterClass
import java.lang.ref.WeakReference
import java.util.concurrent.TimeUnit
internal object BadCaseManager : LifecycleEventObserver {
internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordListener {
const val TAG = "BadCase"
@@ -96,6 +105,8 @@ internal object BadCaseManager : LifecycleEventObserver {
* 主动采集BadCase
*/
fun initBadCase(view: View) {
CallerAutopilotRecordListenerManager.addListener(TAG, this)
val activity = view.context as? FragmentActivity
?: throw IllegalStateException("please ensure context is FragmentActivity.")
view.setOnClickListener {
@@ -193,24 +204,62 @@ internal object BadCaseManager : LifecycleEventObserver {
}
}
override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) {
super.onAutopilotRecordResult(recordPanel)
CallerLogger.d("$M_DEVA$TAG", "recordKey=${recordPanel.key},stat=${recordPanel.stat}")
if (BadCaseConfig.recordKeyList.contains(recordPanel.key)) {
if (recordPanel.stat == 100 || recordPanel.stat == 101) {
//成功结束录制
TipToast.shortTip(
"${
TimeUtils.millis2String(
System.currentTimeMillis(),
TimeUtils.getHourMinSecondFormat()
)
} bag录制成功"
)
}
if (recordPanel.stat == 200) {
//录制失败
TipToast.shortTip(
"${
TimeUtils.millis2String(
System.currentTimeMillis(),
TimeUtils.getHourMinSecondFormat()
)
} bag录制失败"
)
}
return
}
//在工控机taxi2.3.0版本和Bus2.4.0版本上不支持被动录包,不进行被动录包的弹窗
BadCaseConfig.dockerVersion?.let {
if (it.contains("taxi") && it.contains("2.3.0")) {
return
}
if (it.contains("bus") && it.contains("2.4.0")) {
return
}
}
//处于非美化模式下弹窗是地图数据采集任务时即type=2时不弹窗
if (!FunctionBuildConfig.isDemoMode && (recordPanel.stat == 100 || recordPanel.stat == 101) && recordPanel.type != 2) {
//只在司机屏生效,乘客屏不生效
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.RECORD, RecordBagMsg(
recordPanel.key, recordPanel.stat, recordPanel.id,
recordPanel.type, recordPanel.filename, recordPanel.note
)
)
)
}
}
}
override fun onStateChanged(source: LifecycleOwner, event: Event) {
}
}
internal fun RecordPanelOuterClass.RecordPanel.toRecord(): AutoPilotRecord =
AutoPilotRecord().also {
it.id = this.id
it.stat = this.stat
it.key = this.key.toString()
it.note = this.note
it.type = this.type
it.total = this.totalSize
it.fileName = this.filename
it.duration = this.duration.toDouble()
it.diskFree = this.diskFree
it.consumed = false
}

View File

@@ -373,6 +373,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) {
CallerLogger.d("${M_DEVA}${TAG}", "-- 收到工控机录制任务回调 -- $recordPanel")
ThreadUtils.runOnUiThread {
if (recordKey == null) {
recordKey = recordPanel.key.toString()

View File

@@ -57,7 +57,7 @@ class V2XLimitingVelocityBroadcastReceiver : BroadcastReceiver() {
* @param limitingVelocitySpeed 限速速度
*/
private fun dispatchShowWaring(limitingVelocitySpeed: Int) {
CallerHmiManager.showLimitingVelocity(limitingVelocitySpeed)
CallerHmiManager.showLimitingVelocity(limitingVelocitySpeed, 1)
}
/**

View File

@@ -76,7 +76,7 @@ class V2XWarningBroadcastReceiver : BroadcastReceiver() {
tag: String?
) {
if (EventTypeEnum.TYPE_USECASE_ID_IVP.poiType == v2xType.toString()) {
CallerHmiManager.showLimitingVelocity(1)
CallerHmiManager.showLimitingVelocity(1, 1)
}
if (alertContent.isNullOrEmpty() || ttsContent.isNullOrEmpty()) {
Log.d("MsgBox-V2XWarningBR", "alertContent或ttsContent为空!")

View File

@@ -3,12 +3,12 @@ package com.mogo.eagle.core.function.hmi.ui
import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import android.util.*
import android.view.View
import android.view.ViewGroup
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.widget.FrameLayout
import androidx.lifecycle.lifecycleScope
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
@@ -40,6 +40,7 @@ import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.PerspectiveSwitchView_TAG
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.SpeedPanelView_TAG
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.ToolsView_TAG
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.TrafficLightView_TAG
import com.mogo.eagle.core.function.api.hmi.view.IViewLimitingVelocity
import com.mogo.eagle.core.function.api.hmi.view.IViewTrafficLight
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoHmiProvider
@@ -86,12 +87,9 @@ import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
import com.zhjt.service_biz.BizConfig
import kotlinx.android.synthetic.main.fragment_hmi.*
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.*
import record_cache.RecordPanelOuterClass
import java.util.concurrent.atomic.AtomicReference
/**
* @author xiaoyuzhou
@@ -102,8 +100,7 @@ import record_cache.RecordPanelOuterClass
class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
IMoGoHmiProvider,
IMoGoHmiViewProxy,
MoGoHmiContract.View,
IMoGoAutopilotRecordListener {
MoGoHmiContract.View{
companion object {
private const val TAG = "MoGoHmiFragment"
@@ -116,36 +113,16 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
// todo 需要统一数据源 限速 View代理
private var mViewLimitingVelocity: IViewLimitingVelocity? = null
private var lastSpeakJob: Job? = null
private val lastSpeakJob by lazy { AtomicReference<Job>() }
private var lastShowV2XJob: Job? = null
private var showingV2XTip: IReminder? = null
override fun initViews() {
initViewShowWithConfig()
//设置StatusBar初始状态
CallerHmiViewControlListenerManager.updateStatusBarRightView(StatusBarView.TAG,FunctionBuildConfig.isDemoMode, "demoMode", DemoModeView(requireContext()))
ivCameraIcon?.setOnClickListener {
cameraLiveView.showCameraList(
context,
CallerFuncBizManager.bizProvider.getCameraList
) { liveStatus ->
if (liveStatus) {
ivCameraIcon.setBackgroundResource(R.drawable.icon_camera_selected)
} else {
ivCameraIcon.setBackgroundResource(R.drawable.icon_camera_nor)
}
}
}
viewShowDebugView.setOnLongClickListener {
toggleDebugView.toggle(requireContext())
true
}
//todo 新超,封装至消息盒子
cbMsgBoxDriver.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
@@ -208,14 +185,10 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
CallerAutopilotRecordListenerManager.addListener(TAG, this)
// 首次初始化使用默认视图
setProxyTrafficLightView(viewTrafficLightVr)
//todo 确认使用方 taxi bus 乘客/司机
setProxyLimitingSpeedView(viewLimitingVelocity)
}
/** todo ----------------------------------------------**/
/**
* 设置 红绿灯 代理View
@@ -231,109 +204,6 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
mViewLimitingVelocity = view
}
/**
* 根据配置文件初始化视图显示
*/
private fun initViewShowWithConfig() {
// 控制 自动驾驶状态 展示
if (HmiBuildConfig.isShowAutopilotStatusView) {
setAutopilotStatusViewVisibility(View.VISIBLE)
} else {
setAutopilotStatusViewVisibility(View.GONE)
}
// 控制 切换视角 展示
if (HmiBuildConfig.isShowPerspectiveSwitchView) {
setPerspectiveSwitchViewVisibility(View.VISIBLE)
} else {
setPerspectiveSwitchViewVisibility(View.GONE)
}
// 控制 红绿灯 展示
if (HmiBuildConfig.isShowTrafficLightView) {
setTrafficLightVrVisibility(View.VISIBLE)
} else {
setTrafficLightVrVisibility(View.GONE)
}
// 控制 远程摄像头图标 展示
if (HmiBuildConfig.isShowCameraView) {
setCameraViewVisibility(View.VISIBLE)
} else {
setCameraViewVisibility(View.GONE)
}
}
/** todo----------------------------------------------- **/
override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) {
CallerLogger.d("$M_HMI$TAG", "recordKey=${recordPanel.key},stat=${recordPanel.stat}")
if (BadCaseConfig.recordKeyList.contains(recordPanel.key)) { //todo InitiativeBadCaseWindow
if (recordPanel.stat == 100 || recordPanel.stat == 101) {
//成功结束录制
TipToast.shortTip(
"${
millis2String(
System.currentTimeMillis(),
TimeUtils.getHourMinSecondFormat()
)
} bag录制成功"
)
}
if (recordPanel.stat == 200) {
//录制失败
TipToast.shortTip(
"${
millis2String(
System.currentTimeMillis(),
TimeUtils.getHourMinSecondFormat()
)
} bag录制失败"
)
}
return
}
//在工控机taxi2.3.0版本和Bus2.4.0版本上不支持被动录包,不进行被动录包的弹窗
BadCaseConfig.dockerVersion?.let {
if (it.contains("taxi") && it.contains("2.3.0")) {
return
}
if (it.contains("bus") && it.contains("2.4.0")) {
return
}
}
//处于非美化模式下弹窗是地图数据采集任务时即type=2时不弹窗
if (!FunctionBuildConfig.isDemoMode && (recordPanel.stat == 100 || recordPanel.stat == 101) && recordPanel.type != 2) {
//只在司机屏生效,乘客屏不生效
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) { //todo 数据中心控制来源
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.RECORD, RecordBagMsg(
recordPanel.key, recordPanel.stat, recordPanel.id,
recordPanel.type, recordPanel.filename, recordPanel.note
)
)
)
}
}
if (!FunctionBuildConfig.isDemoMode && recordPanel.type == 2 && ( //todo CallerMapDataCollectorManager
recordPanel.stat == 101 || //工控机采集完成-被动完成
recordPanel.stat == 100 || //工控机采集完成-主动完成
recordPanel.stat == 102 || //工控机达到最大采集时长
recordPanel.stat == 103) //工控机磁盘满了
) {
CallerMapDataCollectorManager.finish(
recordPanel.id, recordPanel.stat, "", recordPanel.filename
?: "", recordPanel.note ?: ""
)
}
}
override fun onDestroyView() {
super.onDestroyView()
CallerAutopilotRecordListenerManager.removeListener(TAG)
}
/**
* ok
* 工控机重启返回结果
@@ -414,9 +284,8 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
DisplayEffectsHelper.getInstance().display()
}
/** todo----------------------------------------------- **/
override fun setTrafficLightVrVisibility(visibility: Int) {
mViewTrafficLight?.visibility = visibility
CallerHmiViewControlListenerManager.invokeVisible(TrafficLightView_TAG,visibility)
}
override fun setToolsViewVisibility(visibility: Int) {
@@ -482,10 +351,7 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
"$M_HMI$TAG",
"--- show v2x dialog 1 ---: info -> v2x-type: $v2xType : expireTime: $expireTime"
)
lastShowV2XJob?.safeCancel()
lastSpeakJob?.safeCancel()
lifecycleScope.launch {
delay(expireTime)
}.also { itx ->
@@ -496,10 +362,18 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
}
if (ttsContent != null && !TextUtils.isEmpty(ttsContent) && playTTS) {
lifecycleScope.launch {
val last = lastSpeakJob.get()
Log.d("CODE", "---- 0 ------: last: $last")
if (last != null && !last.isCompleted) {
Log.d("CODE", "---- 1 ------")
return
}
lifecycleScope.launch(Dispatchers.Default) {
Log.d("CODE", "---- 2 ------")
speak(it, ttsContent)
Log.d("CODE", "---- 3 ------")
}.also { itx ->
lastSpeakJob = itx
lastSpeakJob.set(itx)
}
}
}
@@ -594,18 +468,26 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
/**
* 控制展示限速标志及内容
*/
override fun showLimitingVelocity(limitingSpeed: Int) {
override fun showLimitingVelocity(limitingSpeed: Int, limitSpeedSource: Int) {
// 控制 限速UI 展示
if (HmiBuildConfig.isShowLimitingVelocityView) {
if (limitingSpeed > 0) {
mViewLimitingVelocity?.visibility = View.VISIBLE
mViewLimitingVelocity?.updateLimitingSpeed(limitingSpeed)
mViewLimitingVelocity?.updateLimitingSpeed(limitingSpeed, limitSpeedSource)
tvLimitingSource?.visibility = View.VISIBLE
if (limitSpeedSource == 1) {
tvLimitingSource.text = "MAP"
} else if (limitSpeedSource == 2) {
tvLimitingSource.text = "RSU"
}
} else {
mViewLimitingVelocity?.visibility = View.INVISIBLE
mViewLimitingVelocity?.updateLimitingSpeed(0)
mViewLimitingVelocity?.updateLimitingSpeed(0, limitSpeedSource)
tvLimitingSource?.visibility = View.INVISIBLE
}
} else {
disableLimitingVelocity()
tvLimitingSource?.visibility = View.GONE
}
}
@@ -614,7 +496,7 @@ class MoGoHmiFragment : MvpFragment<MoGoHmiContract.View?, HmiPresenter?>(),
*/
override fun disableLimitingVelocity() {
mViewLimitingVelocity?.visibility = View.GONE
mViewLimitingVelocity?.updateLimitingSpeed(0)
mViewLimitingVelocity?.updateLimitingSpeed(0, 1)
}
/**

View File

@@ -82,7 +82,9 @@ import mogo_msg.MogoReportMsg
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.abs
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner
/**
* @author xiaoyuzhou
@@ -215,7 +217,7 @@ internal class DebugSettingView @JvmOverloads constructor(
logInfoView!!.onEnterForeground()
}
// 开启定时查询速度
Timer().schedule(timerTaskRefresh, Date(), 100)
Timer().schedule(timerTaskRefresh, Date(), 300)
if (AppConfigInfo.isConnectAutopilot && (AppConfigInfo.plateNumber.isNullOrEmpty() || AppConfigInfo.iPCMacAddress.isNullOrEmpty())) {
//查询工控机基础配置信息
CallerAutoPilotManager.getCarConfig()
@@ -1686,10 +1688,10 @@ internal class DebugSettingView @JvmOverloads constructor(
}"
)
tvAutopilotInfo.text = GsonUtils.toJson(mAutoPilotStatusInfo)
tvIpcInfo.text = GsonUtils.toJson(mAutoPilotStatusInfo)
tvIpcInfoKey.text = GsonUtils.toJson(mAutoPilotStatusInfo)
val autopilotJson = GsonUtils.toJson(mAutoPilotStatusInfo)
tvAutopilotInfo.text = autopilotJson
tvIpcInfo.text = autopilotJson
tvIpcInfoKey.text = autopilotJson
tvCarInfo.text =
"GPS时间${(mGnssInfo?.satelliteTime?.times(1000))?.toLong()}\n" +
@@ -1734,18 +1736,20 @@ internal class DebugSettingView @JvmOverloads constructor(
* OBU状态回调
*/
override fun onObuStatusResponse(obuStatusInfo: ObuStatusInfo) {
tvObuInfo.text = GsonUtils.toJson(obuStatusInfo)
lifecycleOwner.lifecycleScope.launch {
tvObuInfo.text = GsonUtils.toJson(obuStatusInfo)
AppConfigInfo.obuSdkVersion = obuStatusInfo.obuSdkVersion
AppConfigInfo.isConnectObu = obuStatusInfo.obuStatus
AppConfigInfo.obuSdkVersion = obuStatusInfo.obuSdkVersion
AppConfigInfo.isConnectObu = obuStatusInfo.obuStatus
if (obuStatusInfo.obuStatus) {
obuConnectStatus = true
}
//OBU断开连接提示异常
if (obuConnectStatus && !obuStatusInfo.obuStatus) {
obuConnectStatus = false
toastMsg("OBU连接状态异常")
if (obuStatusInfo.obuStatus) {
obuConnectStatus = true
}
//OBU断开连接提示异常
if (obuConnectStatus && !obuStatusInfo.obuStatus) {
obuConnectStatus = false
toastMsg("OBU连接状态异常")
}
}
}

View File

@@ -78,6 +78,7 @@ internal class SOPSettingView @JvmOverloads constructor(
/**
* obu弱势交通控制
*/
tbObuWeaknessTrafficSop.isChecked = HmiBuildConfig.isShowObuWeaknessTrafficView
tbObuWeaknessTrafficSop.setOnCheckedChangeListener { _, isChecked ->
if (!isChecked) { //默认开启
CallerHmiManager.setObuWeaknessTraffic(true)
@@ -89,6 +90,7 @@ internal class SOPSettingView @JvmOverloads constructor(
/**
* 云端弱势交通控制
*/
tbCloudWeaknessTrafficSop.isChecked = HmiBuildConfig.isShowCloudWeaknessTrafficView
tbCloudWeaknessTrafficSop.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { //默认关闭
CallerHmiManager.setCloudWeaknessTraffic(true)

View File

@@ -6,6 +6,7 @@ import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.ToolsView_TAG
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.function.hmi.ui.setting.ToolsView.Companion.toolsView
class ToolsImageView(context: Context, attrs: AttributeSet?) :
androidx.appcompat.widget.AppCompatImageView(context, attrs), IViewControlListener {
@@ -15,6 +16,9 @@ class ToolsImageView(context: Context, attrs: AttributeSet?) :
setBackgroundResource(R.drawable.module_ext_check)
setImageResource(R.drawable.icon_tools_nor)
scaleType = ScaleType.CENTER
setOnClickListener{
toolsView.showToolsFloat(context)
}
CallerHmiViewControlListenerManager.addListener(ToolsView_TAG, this)
}

View File

@@ -4,8 +4,10 @@ import android.content.Context
import android.util.AttributeSet
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.CameraView_TAG
import com.mogo.eagle.core.function.call.biz.CallerFuncBizManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.function.hmi.ui.setting.CameraLiveView.Companion.cameraLiveView
class CameraView(context: Context, attrs: AttributeSet?) :
androidx.appcompat.widget.AppCompatImageView(context, attrs), IViewControlListener {
@@ -13,6 +15,19 @@ class CameraView(context: Context, attrs: AttributeSet?) :
override fun onAttachedToWindow() {
super.onAttachedToWindow()
setBackgroundResource(R.drawable.icon_camera_nor)
setOnClickListener {
cameraLiveView.showCameraList(
context,
CallerFuncBizManager.bizProvider.getCameraList
) { liveStatus ->
if (liveStatus) {
setBackgroundResource(R.drawable.icon_camera_selected)
} else {
setBackgroundResource(R.drawable.icon_camera_nor)
}
}
}
CallerHmiViewControlListenerManager.addListener(CameraView_TAG, this)
}

View File

@@ -20,8 +20,8 @@ class LimitingVelocityView @JvmOverloads constructor(
LayoutInflater.from(context).inflate(R.layout.view_limiting_speed_vr, this, true)
}
override fun updateLimitingSpeed(limitingSpeed: Int) {
super.updateLimitingSpeed(limitingSpeed)
override fun updateLimitingSpeed(limitingSpeed: Int, limitSource: Int) {
super.updateLimitingSpeed(limitingSpeed, limitSource)
tvLimitingVelocity.text = "$limitingSpeed"
}
}

View File

@@ -8,7 +8,10 @@ import android.widget.ImageView
import android.widget.TextView
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.config.HmiBuildConfig
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.TrafficLightView_TAG
import com.mogo.eagle.core.function.api.hmi.view.IViewTrafficLight
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
@@ -20,7 +23,7 @@ class SingleTrafficLightView @JvmOverloads constructor(
context: Context?,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : IViewTrafficLight(context, attrs, defStyleAttr) {
) : IViewTrafficLight(context, attrs, defStyleAttr), IViewControlListener {
private var mLightIconIV: ImageView? = null
private var mLightIconBG: ImageView? = null
private var mLightTimeTV: GradientTextView? = null
@@ -28,17 +31,26 @@ class SingleTrafficLightView @JvmOverloads constructor(
private var mLightSourceDivider: View? = null
private var mCurrentLightId = 0
init {
init(context)
}
private fun init(context: Context?) {
override fun onAttachedToWindow() {
super.onAttachedToWindow()
LayoutInflater.from(context).inflate(R.layout.hmi_view_traffic_light, this, true)
mLightIconIV = findViewById(R.id.hmi_traffic_light_iv)
mLightIconBG = findViewById(R.id.hmi_traffic_light_bg)
mLightTimeTV = findViewById(R.id.hmi_traffic_light_time_tv)
mLightSourceTV = findViewById(R.id.hmi_traffic_light_source)
mLightSourceDivider = findViewById(R.id.hmi_traffic_light_divider)
CallerHmiViewControlListenerManager.addListener(TrafficLightView_TAG, this)
}
override fun visible(v: Int) {
super.visible(v)
visibility = v
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
CallerHmiViewControlListenerManager.removeListener(TrafficLightView_TAG)
}
/**
@@ -47,11 +59,11 @@ class SingleTrafficLightView @JvmOverloads constructor(
* @param checkLightId 0-都是默认1-红2-黄3-绿
* @param lightSource 1:云端下发2:自车感知
*/
override fun showWarningTrafficLight(checkLightId: Int,lightSource: Int) {
super.showWarningTrafficLight(checkLightId,lightSource)
override fun showWarningTrafficLight(checkLightId: Int, lightSource: Int) {
super.showWarningTrafficLight(checkLightId, lightSource)
mCurrentLightId = checkLightId
if(!HmiBuildConfig.isShowTrafficLightView){
updateTrafficLightIcon(checkLightId,lightSource)
if (!HmiBuildConfig.isShowTrafficLightView) {
updateTrafficLightIcon(checkLightId, lightSource)
}
}
@@ -70,24 +82,28 @@ class SingleTrafficLightView @JvmOverloads constructor(
super.disableCountdown()
UiThreadHandler.post {
// 小巴车的司机端需要展示红绿灯信号来源
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
&& AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)){
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
&& AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
) {
val lp = this.layoutParams as MarginLayoutParams
lp.width = context.resources.getDimension(R.dimen.dp_325).toInt()
this.layoutParams = lp
mLightSourceTV!!.visibility = VISIBLE
mLightSourceDivider!!.visibility = VISIBLE
mLightTimeTV!!.visibility = GONE
mLightSourceTV!!.setPadding(0,0,75,0)
mLightIconBG!!.layoutParams.width = context.resources.getDimension(R.dimen.dp_310).toInt()
}else{
mLightSourceTV!!.setPadding(0, 0, 75, 0)
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.dp_310).toInt()
} else {
val lp = this.layoutParams as MarginLayoutParams
lp.width = context.resources.getDimension(R.dimen.hmi_traffic_light_icon_size).toInt()
lp.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_icon_size).toInt()
this.layoutParams = lp
mLightTimeTV!!.visibility = GONE
mLightSourceDivider!!.visibility = View.GONE
mLightSourceTV!!.visibility = View.GONE
mLightIconBG!!.layoutParams.width = context.resources.getDimension(R.dimen.dp_124).toInt()
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.dp_124).toInt()
}
}
}
@@ -176,7 +192,7 @@ class SingleTrafficLightView @JvmOverloads constructor(
* @param lightId 0-都是默认1-红2-黄3-绿
* @param lightSource 1:云端下发2:自车感知
*/
private fun updateTrafficLightIcon(lightId: Int,lightSource: Int) {
private fun updateTrafficLightIcon(lightId: Int, lightSource: Int) {
UiThreadHandler.post {
when (lightId) {
1 -> {
@@ -193,7 +209,7 @@ class SingleTrafficLightView @JvmOverloads constructor(
}
else -> this@SingleTrafficLightView.visibility = GONE
}
when(lightSource){
when (lightSource) {
1 -> {
mLightSourceTV!!.text = "云端下发"
}
@@ -207,26 +223,31 @@ class SingleTrafficLightView @JvmOverloads constructor(
}
}
private fun resetView(){
private fun resetView() {
// 小巴车的司机端需要展示红绿灯信号来源
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
&& AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)){
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
&& AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
) {
val lp = this.layoutParams as MarginLayoutParams
lp.width = context.resources.getDimension(R.dimen.hmi_traffic_light_bus_layout_width).toInt()
lp.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bus_layout_width).toInt()
this.layoutParams = lp
mLightTimeTV!!.visibility = View.VISIBLE
mLightSourceDivider!!.visibility = View.VISIBLE
mLightSourceTV!!.visibility = View.VISIBLE
mLightSourceTV!!.setPadding(0,0,0,0)
mLightIconBG!!.layoutParams.width = context.resources.getDimension(R.dimen.hmi_traffic_light_bus_bg_width).toInt()
}else{
mLightSourceTV!!.setPadding(0, 0, 0, 0)
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bus_bg_width).toInt()
} else {
val lp = this.layoutParams as MarginLayoutParams
lp.width = context.resources.getDimension(R.dimen.hmi_traffic_light_layout_width).toInt()
lp.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_layout_width).toInt()
this.layoutParams = lp
mLightTimeTV!!.visibility = View.VISIBLE
mLightSourceDivider!!.visibility = View.GONE
mLightSourceTV!!.visibility = View.GONE
mLightIconBG!!.layoutParams.width = context.resources.getDimension(R.dimen.hmi_traffic_light_bg_width).toInt()
mLightIconBG!!.layoutParams.width =
context.resources.getDimension(R.dimen.hmi_traffic_light_bg_width).toInt()
}
}

View File

@@ -178,7 +178,7 @@ public class SpeedChartView extends View {
setAnimation(lastAngle, currentAngle, 1000);
lastAngle = currentAngle;
//重新绘制
postInvalidate();
invalidate();
}
}

View File

@@ -80,7 +80,7 @@ class SpeedPanelView @JvmOverloads constructor(
}
}
this.timerTask = task
timer.schedule(task, Date(), 100)
timer.schedule(task, Date(), 200)
}
override fun onChassisLocationGCJ02(gnssInfo: MessagePad.GnssInfo?) {

View File

@@ -122,7 +122,6 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
}).start();
}
// TODO 李小鹏 这里需要将逻辑抽离出去,单独使用更新服务控制
private void upgradeProgressListener() {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setSmallIcon(R.mipmap.icon1001);//todo emArrow 更换图标,去除地图下载图标的依赖关系

View File

@@ -6,14 +6,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/viewShowDebugView"
android:layout_width="@dimen/dp_400"
android:layout_height="@dimen/dp_100"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<!--V2X预警红色边框-->
<com.mogo.eagle.core.function.hmi.ui.widget.V2XWarningView
android:id="@+id/flV2XWarningView"
@@ -47,27 +39,6 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--超视距-->
<com.mogo.eagle.core.function.hmi.ui.widget.CameraView
android:id="@+id/ivCameraIcon"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="45dp"
android:layout_marginEnd="40dp"
app:layout_constraintRight_toLeftOf="@id/viewTrafficLightVr"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<!--红绿灯-->
<com.mogo.eagle.core.function.hmi.ui.widget.SingleTrafficLightView
android:id="@+id/viewTrafficLightVr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/hmi_traffic_light_layout_margin_top"
android:layout_marginEnd="@dimen/hmi_traffic_light_layout_margin_right"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--地图视角切换-->
<com.mogo.eagle.core.function.hmi.ui.widget.PerspectiveSwitchView
android:id="@+id/viewPerspectiveSwitch"
@@ -104,10 +75,27 @@
android:textSize="60dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ivCameraIcon"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginEnd="40dp"
app:layout_goneMarginTop="40dp"
tools:visibility="gone" />
<!-- todo 需要放入使用方 -->
<!-- app:layout_constraintTop_toBottomOf="@+id/ivCameraIcon"-->
<!--限速来源-->
<TextView
android:id="@+id/tvLimitingSource"
android:layout_width="120dp"
android:layout_height="35dp"
android:gravity="center"
android:text=""
android:textColor="@color/color_FFFFFF"
android:textSize="@dimen/dp_30"
android:textStyle="bold"
android:layout_marginEnd="40dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewLimitingVelocity" />
<!--消息盒子司机端选择入口-->
<CheckBox
@@ -118,9 +106,11 @@
android:layout_marginEnd="25dp"
android:background="@drawable/selector_msg_box"
android:button="@null"
android:visibility="visible"
android:visibility="gone"
app:layout_constraintRight_toLeftOf="@id/viewLimitingVelocity"
app:layout_constraintTop_toBottomOf="@+id/ivCameraIcon" />
app:layout_constraintTop_toTopOf="parent"/>
<!-- todo 需要放入使用方 , view先gone掉方便重组 -->
<!-- app:layout_constraintTop_toBottomOf="@+id/ivCameraIcon" />-->
<!--司机端消息提示-->
<View

View File

@@ -6,22 +6,28 @@ import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.cloud.passport.IMoGoTokenCallback
import com.mogo.cloud.passport.MoGoAiCloudClient
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_MAP
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener
import com.mogo.eagle.core.function.api.map.collect.IMoGoMapDataCollectProvider
import com.mogo.eagle.core.function.api.map.listener.IMoGoMapLocationListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager
import com.zhidaoauto.map.operational.open.GatherApi
import com.zhidaoauto.map.operational.open.GatherParams
import com.zhidaoauto.map.operational.open.abs.OnTaskListener
import record_cache.RecordPanelOuterClass
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicReference
@Route(path = MogoServicePaths.PATH_MAP_DATA_COLLECT_PROVIDER)
class MoGoMapDataCollectProvider : IMoGoMapDataCollectProvider, OnTaskListener, IMoGoMapLocationListener, IMoGoTokenCallback {
class MoGoMapDataCollectProvider : IMoGoMapDataCollectProvider, OnTaskListener, IMoGoMapLocationListener, IMoGoTokenCallback,
IMoGoAutopilotRecordListener {
companion object {
const val TAG = "MoGoMapDataCollect"
@@ -39,13 +45,16 @@ class MoGoMapDataCollectProvider : IMoGoMapDataCollectProvider, OnTaskListener,
ConcurrentHashMap()
}
override val functionName: String = "$M_MAP$TAG"
override val functionName: String = TAG
@Volatile
private var hasInit = false
override fun init(context: Context?) {
CallerMapLocationListenerManager.addListener(functionName, this, false)
CallerMapLocationListenerManager.addListener(TAG, this, false)
CallerAutopilotRecordListenerManager.addListener(TAG, this)
executor.set(context?.let {
GatherApi.also { itx ->
itx.init(it,
@@ -64,13 +73,27 @@ class MoGoMapDataCollectProvider : IMoGoMapDataCollectProvider, OnTaskListener,
}
override fun onDestroy() {
CallerMapLocationListenerManager.removeListener("$M_MAP$TAG", false)
CallerLogger.d("$M_MAP$TAG", "--------- onDestroy --------")
CallerMapLocationListenerManager.removeListener(TAG, false)
CallerAutopilotRecordListenerManager.removeListener(TAG)
executor.get()?.setOnTaskListener(null)
listeners.clear()
map.clear()
}
override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) {
super.onAutopilotRecordResult(recordPanel)
CallerLogger.d("$M_MAP$TAG", "recordKey=${recordPanel.key},stat=${recordPanel.stat}")
if (!FunctionBuildConfig.isDemoMode && recordPanel.type == 2 && (
recordPanel.stat == 101 || //工控机采集完成-被动完成
recordPanel.stat == 100 || //工控机采集完成-主动完成
recordPanel.stat == 102 || //工控机达到最大采集时长
recordPanel.stat == 103) //工控机磁盘满了
) {
finish(recordPanel.id, recordPanel.stat, "", recordPanel.filename ?: "", recordPanel.note ?: "")
}
}
override fun registerOnMapCollectTaskListener(listener: IMoGoMapDataCollectProvider.OnMapCollectCmdListener?) {
CallerLogger.d("$M_MAP$TAG", "--------- registerOnMapCollectTaskListener --------")
listener ?: return

View File

@@ -38,8 +38,11 @@ data class V2XEvent(
@SerializedName("radius")
var radius: Double,
@SerializedName("type")
var type: Int
@SerializedName("poiType")
var poiType: String?,
@SerializedName("coordinateType")
var coordinateType:Int? = null
)
@Keep

View File

@@ -8,6 +8,8 @@ import com.mogo.eagle.core.function.overview.OverviewDao
import com.mogo.eagle.core.function.overview.remote.OverViewServiceApi
import com.mogo.eagle.core.function.overview.remote.V2XEvent
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -22,6 +24,10 @@ class OverViewModel(
private val _V2XEvents = MutableLiveData<List<V2XEvent>>()
private var disposable: Disposable? = null
companion object {
const val TAG = "OverViewModel"
}
val infStructures
get() = _infStructures
@@ -90,8 +96,10 @@ class OverViewModel(
.queryAllV2XEventsByLineId(lineId.toString(), sn)
.map {
if (it.code == 200 || it.code == 0) {
CallerLogger.d(SceneConstant.M_MAP + TAG, "请求成功size为${it.result?.v2XEventList?.size}")
return@map it.result?.v2XEventList
} else {
CallerLogger.d(SceneConstant.M_MAP + TAG, "请求失败code为${it.code}")
return@map ArrayList()
}
}
@@ -121,7 +129,12 @@ class OverViewModel(
if (parameter != null) {
if (parameter.autoPilotLine != null) {
lineId = parameter.autoPilotLine!!.lineId
CallerLogger.d(SceneConstant.M_MAP + TAG, "lineId为:$lineId")
} else {
CallerLogger.d(SceneConstant.M_MAP + TAG, "parameter.autoPilotLine为null")
}
} else {
CallerLogger.d(SceneConstant.M_MAP + TAG, "parameter为null")
}
return lineId
}

View File

@@ -260,10 +260,16 @@ public class AMapCustomView
if (center != null) {
center.getLon();
MarkerOptions markerOption = new MarkerOptions();
LatLng latLng = MarkerDrawerManager.INSTANCE.coordinateConverterWgsToGcj(mContext, center.getLat(), center.getLon());
LatLng latLng;
if (event.getCoordinateType() == null || event.getCoordinateType() == 0) {
latLng = new LatLng(center.getLat(), center.getLon());
} else {
// wgs84坐标系需转成高德坐标系
latLng = MarkerDrawerManager.INSTANCE.coordinateConverterWgsToGcj(mContext, center.getLat(), center.getLon());
}
markerOption.position(latLng);
markerOption.anchor(0.13f, 1f);
markerOption.icon(BitmapDescriptorFactory.fromBitmap(getV2XBitmap()));
markerOption.icon(BitmapDescriptorFactory.fromBitmap(getV2XBitmap(event.getPoiType())));
markerOptionsList.add(markerOption);
}
}
@@ -276,8 +282,8 @@ public class AMapCustomView
currMarkerList = mAMap.addMarkers(markerOptionsList, false);
}
private Bitmap getV2XBitmap() {
V2XMarkerView marker = new V2XMarkerView(getContext());
private Bitmap getV2XBitmap(String poiType) {
V2XMarkerView marker = new V2XMarkerView(getContext(), null, 0, poiType);
marker.measure(View.MeasureSpec.makeMeasureSpec(AutoSizeUtils.dp2px(mContext, 229), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(AutoSizeUtils.dp2px(mContext, 96), View.MeasureSpec.EXACTLY));
marker.layout(0, 0, marker.getMeasuredWidth(), marker.getMeasuredHeight());

View File

@@ -3,14 +3,16 @@ package com.mogo.eagle.core.function.smp
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.function.map.R
import kotlinx.android.synthetic.main.view_maker_with_count.view.*
class V2XMarkerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
private val poiType: String? = ""
) : ConstraintLayout (
context,
attrs,
@@ -19,5 +21,33 @@ class V2XMarkerView @JvmOverloads constructor(
init {
LayoutInflater.from(context).inflate(R.layout.layout_v2x_maker, this, true)
initView()
}
private fun initView() {
val iconView = findViewById<ImageView>(R.id.ivIcon)
val contentView = findViewById<TextView>(R.id.tvContent)
when (poiType) {
"10006" -> {
iconView.setBackgroundResource(R.drawable.icon_small_v2x_road_construction)
contentView.text = "道路施工"
}
"10007" -> {
iconView.setBackgroundResource(R.drawable.icon_v2x_road_congestion)
contentView.text = "道路拥堵"
}
"10032" -> {
iconView.setBackgroundResource(R.drawable.icon_v2x_road_accidents)
contentView.text = "道路事故"
}
"10025" -> {
iconView.setBackgroundResource(R.drawable.icon_v2x_obstacle)
contentView.text = "障碍车辆"
}
// "10031" -> {
// iconView.setBackgroundResource(R.drawable.icon_small_v2x_road_construction)
// contentView.text = "弱势预警"
// }
}
}
}

View File

@@ -19,7 +19,7 @@
/>
<TextView
android:id="@+id/tv"
android:id="@+id/tvContent"
android:layout_width="119dp"
android:layout_height="35dp"
android:text="道路施工"

View File

@@ -33,7 +33,7 @@ class MoGoObuProvider : IMoGoObuProvider {
override fun init(context: Context) {
//obu融合数据
// MogoObuDcCombineManager.INSTANCE.init(context)
MogoObuDcCombineManager.INSTANCE.init(context)
CallerLogger.d("$M_OBU$TAG", "初始化蘑菇自研OBU…… localIp = " + CommonUtils.getLocalIPAddress())
//bus乘客版本obu功能去掉
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode) && AppIdentityModeUtils.isPassenger(

View File

@@ -0,0 +1,663 @@
package com.mogo.eagle.core.function.obu.mogo
import android.content.Context
import com.mogo.eagle.core.data.config.HmiBuildConfig
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.enums.WarningDirectionEnum
import com.mogo.eagle.core.data.msgbox.DataSourceType
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.function.api.obucombine.IMoGoObuDcCombineListener
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.call.obucombine.CallerObuDcCombineListenerManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OBU
import com.mogo.support.obu.constants.MogoObuConstants
import mogo.v2x.ObuWarningEvent
import mogo.v2x.ObuWarningEvent.*
/**
*
* @author lixiaopeng
* @since 2021/11/30
* @description 工控机融合数据
*/
class MogoObuDcCombineManager private constructor() : IMoGoObuDcCombineListener {
companion object {
val INSTANCE: MogoObuDcCombineManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
MogoObuDcCombineManager()
}
}
private var mContext: Context? = null
private val TAG = "MogoObuDcCombineManager"
fun init(context: Context) {
mContext = context
CallerObuDcCombineListenerManager.addListener(TAG, this)
}
fun destoryListener() {
CallerObuDcCombineListenerManager.removeListener(TAG)
}
/**
* 通过工控机中转的obu数据,包括rsirsmspat
*
*/
override fun onMoGoObuDcCombineData(obuWarningData: ObuWarningEvent.ObuWarningData?) {
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager onMoGoObuDcCombineData obuWarningData = ${obuWarningData.toString()} ---obuWarningData.msgDataType = ${obuWarningData?.msgDataType}"
)
obuWarningData?.let {
when (obuWarningData.msgDataType) {
1 -> { //rsiEvent
onMogoObuDcRsiWarning(obuWarningData.rsiEvent)
}
2 -> { //RsmEvent
onMogoObuDcRsmWarning(obuWarningData.rsmEvent)
}
3 -> { //SpatEvent
onMogoObuDcSpatWarning(obuWarningData.spatEvent)
}
4 -> { //map
onMogoObuMapMath(obuWarningData.mapMatchData)
}
}
}
}
/**
* RSI预警信息 CvxRtiThreatIndInfo交通标志预警前方限速、前方学校等等交通事件预警前方拥堵、前方积水等等
*/
fun onMogoObuDcRsiWarning(rsiWarningData: RsiWarningData?) {
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager onMogoObuRsiWarning ------> ${rsiWarningData.toString()}"
)
if (rsiWarningData != null && rsiWarningData.warningMsgList != null && rsiWarningData.warningMsgList.size > 0) {
var alertContent = ""
var ttsContent = "" //列表只有一项
var appId = rsiWarningData.warningMsgList[0].sceneType.toString()
val status = rsiWarningData.status
val level = rsiWarningData.warningMsgList[0].warningLevel
val direction = getMessageDirection(rsiWarningData.warningMsgList[0].targetPosition)
CallerLogger.d("${M_OBU}${TAG}",
"MogoObuDcCombineManager onMogoObuDcRsiWarning appId = $appId --status = $status --level = $level -- eventSerialNum = ${rsiWarningData.warningMsgList[0].eventSerialNum} ---signSerialNum = ${rsiWarningData.warningMsgList[0].signSerialNum} --- direction = $direction -- targetPosition = ${rsiWarningData.warningMsgList[0].targetPosition}"
)
when (appId) {
// 道路危险情况预警
MogoObuConstants.RSI_SCENE_TYPE.HLW.toString() -> {
when (rsiWarningData.warningMsgList[0].eventSerialNum) {
MogoObuConstants.RTE.RTI_TYPE_BREAKDOWN -> {//车辆故障
appId = EventTypeEnumNew.TYPE_USECASE_ID_BREAKDOWN_WARNING.poiType
}
MogoObuConstants.RTE.RTI_TYPE_ROAD_WATER -> { //道路积水
appId = EventTypeEnumNew.FOURS_PONDING.poiType
}
MogoObuConstants.RTE.RTI_TYPE_PARKING_VIOLATION -> { //异常停车
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_PARKING.poiType
}
// MogoObuConstants.RTE.RTI_TYPE_CONSTRUCTION_RTE -> { //施工占道,和标牌重复
// appId = EventTypeEnumNew.FOURS_ROAD_WORK.poiType
// }
MogoObuConstants.RTE.RTI_TYPE_SPEEDING -> { //超速行驶
appId = EventTypeEnumNew.TYPE_USECASE_ID_SLW.poiType
}
MogoObuConstants.RTE.RTI_TYPE_RETRIGRADE -> { //车辆逆行
appId =
EventTypeEnumNew.TYPE_USECASE_ID_ROAD_VEHICLE_RETROGRADE.poiType
}
}
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = String.format( //事件才有影响范围
alertContent,
Math.round(rsiWarningData.warningMsgList[0].distance / 100.0).toString(),
Math.round(rsiWarningData.warningMsgList[0].eventRadius / 10.0).toString()
)
ttsContent = String.format(
ttsContent,
Math.round(rsiWarningData.warningMsgList[0].distance / 100.0).toString(),
Math.round(rsiWarningData.warningMsgList[0].eventRadius / 10.0).toString()
)
}
//车内标牌
MogoObuConstants.RSI_SCENE_TYPE.IVS.toString() -> {
when (rsiWarningData.warningMsgList[0].signSerialNum) {
// MogoObuConstants.RTS.RTI_TYPE_INTERSECTION -> { //十字路口
// appId = V2iEventTypeEnum.TYPE_ID_NTERSECTION.poiType
// }
MogoObuConstants.RTS.RTI_TYPE_SHAPR_TURNS -> { //急转弯
appId = EventTypeEnumNew.TYPE_ID_SHAPR_TURNS.poiType
}
MogoObuConstants.RTS.RTI_TYPE_BRIDGE -> { //桥梁
appId = EventTypeEnumNew.TYPE_ID_BRIDGE.poiType
}
MogoObuConstants.RTS.RTI_TYPE_PEDESTRIAN -> { //行人
appId = EventTypeEnumNew.TYPE_ID_PEDESTRIAN.poiType
}
MogoObuConstants.RTS.RTI_TYPE_SLIPPERY_ROAD -> { //路滑
appId = EventTypeEnumNew.TYPE_ID_SLIPPERY_ROAD.poiType
}
MogoObuConstants.RTS.RTI_TYPE_TUNNEL -> { //隧道
appId = EventTypeEnumNew.TYPE_ID_TUNNEL.poiType
}
MogoObuConstants.RTS.RTI_TYPE_FERRY -> { //渡轮
appId = EventTypeEnumNew.TYPE_ID_FERRY.poiType
}
MogoObuConstants.RTS.RTI_TYPE_UNEVEN_ROAD -> { //路面不平
appId = EventTypeEnumNew.TYPE_ID_UNEVEN_ROAD.poiType
}
MogoObuConstants.RTS.RTI_TYPE_NON_MOTOR_VEHICLE -> { //非机动车
appId = EventTypeEnumNew.TYPE_ID_NON_MOTOR_VEHICLE.poiType
}
MogoObuConstants.RTS.RTI_TYPE_OBSTACLE -> { //障碍
appId = EventTypeEnumNew.TYPE_ID_OBSTACLE.poiType
}
MogoObuConstants.RTS.RTI_TYPE_CONSTRUCTION -> { //施工
appId = EventTypeEnumNew.TYPE_FOURS_ROAD_WORK.poiType
}
MogoObuConstants.RTS.RTI_TYPE_VEHICLE_QUEUE -> { //车队
appId = EventTypeEnumNew.TYPE_VEHICLE_QUEUE.poiType
}
MogoObuConstants.RTS.RTI_TYPE_NO_PASSING -> { //不通
appId = EventTypeEnumNew.TYPE_NO_PASSING.poiType
}
MogoObuConstants.RTS.RTI_TYPE_NO_TURNING_AROUND -> { //禁止掉头
appId = EventTypeEnumNew.TYPE_NO_TURNING_AROUND.poiType
}
MogoObuConstants.RTS.RTI_TYPE_NO_STOPPING -> { //禁止停车
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_NO_PARKING.poiType
}
MogoObuConstants.RTS.RTI_TYPE_NO_TOOTING -> { //禁止鸣笛
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_NO_TOOTING.poiType
}
MogoObuConstants.RTS.RTI_TYPE_SPEED_LIMIT -> { //限速
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_SPEED_LIMIT.poiType
}
// MogoObuConstants.RTS.RTI_TYPE_GO_STRAIGHT_TURN_RIGHT -> { //直行或右转
// appId =
// EventTypeEnumNew.TYPE_USECASE_ID_GO_STRAIGHT_TURN_RIGHT.poiType
// }
MogoObuConstants.RTS.RTI_TYPE_BUS_WARNING -> { //公交提醒
appId = EventTypeEnumNew.TYPE_USECASE_ID_BUS_WARNING.poiType
}
MogoObuConstants.RTS.RTI_TYPE_NARROW_RIGHT -> { //右侧变窄/车道数减少
appId = EventTypeEnumNew.TYPE_USECASE_ID_NARROW_RIGHT.poiType
}
MogoObuConstants.RTS.RTI_TYPE_GAS_STATION -> { //加油站
appId = EventTypeEnumNew.TYPE_USECASE_ID_GAS_STATION.poiType
}
MogoObuConstants.RTS.RTI_TYPE_SCHOOL -> { //学校
appId =
EventTypeEnumNew.TYPE_USECASE_ID_ROAD_PEDESTRIAN_SCHOOL.poiType
}
MogoObuConstants.RTS.RTI_TYPE_ACCIDENT -> { //事故
appId = EventTypeEnumNew.TYPE_USECASE_ID_ACCIDENT.poiType
}
}
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = String.format( //标牌是没有影响范围的
alertContent,
Math.round(rsiWarningData.warningMsgList[0].distance / 100.0).toString()
)
ttsContent = String.format(
ttsContent,
Math.round(rsiWarningData.warningMsgList[0].distance / 100.0).toString()
)
}
// 拥堵
MogoObuConstants.RSI_SCENE_TYPE.TJW.toString() -> {
appId = EventTypeEnumNew.TYPE_USECASE_ID_TJW.poiType
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = String.format( //事件才有影响范围
alertContent,
Math.round(rsiWarningData.warningMsgList[0].distance / 100.0).toString(),
Math.round(rsiWarningData.warningMsgList[0].eventRadius / 10.0).toString()
)
ttsContent = String.format(
ttsContent,
Math.round(rsiWarningData.warningMsgList[0].distance / 100.0).toString(),
Math.round(rsiWarningData.warningMsgList[0].eventRadius / 10.0).toString()
)
}
//限速预警, ADD处理一次
MogoObuConstants.RSI_SCENE_TYPE.SLW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
}
}
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager ttsContent = $ttsContent --alertContent = $alertContent --appId = $appId ---direction = ${direction.direction} --distance = ${rsiWarningData.warningMsgList[0].distance} ---eventRadius = ${rsiWarningData.warningMsgList[0].eventRadius} --speedMaxLimit = ${rsiWarningData.warningMsgList[0].speedMaxLimit}"
)
when (status) {
// 添加
MogoObuConstants.STATUS.ADD -> {
//显示警告红边
CallerHmiManager.showWarning(direction)
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
appId,
alertContent,
ttsContent
)
).apply {
sourceType = DataSourceType.TELEMATIC
}
)
CallerHmiManager.warningV2X(
appId,
alertContent,
ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
(appId + direction.direction),//使用当前事件类型+方向记录tag当发生变化的时候关闭当前弹出新的
object : IMoGoWarningStatusListener {
override fun onDismiss() {
// 关闭警告红边
CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
}
},
true,
5000L
)
// 更新数据,是否需要
// TrafficDataConvertUtilsNew.cvxRtiThreatIndInfo2TrafficData(rsiWarningData)?.let {
// CallerMapUIServiceManager.getMarkerService()
// ?.updateITrafficThreatLevelInfo(it)
// }
}
MogoObuConstants.STATUS.UPDATE -> { // 更新
}
// 删除
MogoObuConstants.STATUS.DELETE -> {
// 关闭警告红边
// CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
// 移除顶部弹窗
CallerHmiManager.disableWarningV2X((appId + direction.direction))
// 更新数据,删除标牌?
// TrafficDataConvertUtilsNew.cvxRtiThreatIndInfo2TrafficData(rsiWarningData)
// ?.let {
// // 事件结束,还原车辆颜色
// it.threatLevel = 0x01
// CallerMapUIServiceManager.getMarkerService()
// ?.updateITrafficInfo(it)
// }
}
}
}
}
/**
* RSM预警信息 CvxPtcThreatIndInfo CvxPtcInfoIndInfo主车与弱势交通参与者之间的预警弱势交通参与者碰撞预警
*/
fun onMogoObuDcRsmWarning(rsmWarningData: RsmWarningData?) {
if (HmiBuildConfig.isShowObuWeaknessTrafficView) {
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager onMogoObuRsmWarning ------> ${rsmWarningData.toString()}"
)
// 交通参与者类型 0x0:未知 UNKNOWN | 1机动车 2:非机动车 NON_MOTOR | 3:行人 PEDESTRIAN 4:obu
if (rsmWarningData != null && rsmWarningData.participantOfOne != null) {
var v2xType = ""
if (rsmWarningData.participantOfOne.ptcType == 1) { //机动车
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_MOTOR_VEHICLES.poiType
} else if (rsmWarningData.participantOfOne.ptcType == 2) { //非机动车
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_NOT_MOTOR_VEHICLES.poiType
} else if (rsmWarningData.participantOfOne.ptcType == 3) { //行人
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_PERSON.poiType
} else { //未知
v2xType = EventTypeEnumNew.TYPE_ERROR.poiType
}
val ttsContent = EventTypeEnumNew.getWarningTts(v2xType)
val alertContent =
EventTypeEnumNew.getWarningContent(v2xType)
var level = -1
val direction =
getMessageDirection(rsmWarningData.participantOfOne.targetPosition) //TODO 只有一个
if (rsmWarningData.warningMsg != null && rsmWarningData.warningMsg.warningDataList != null && rsmWarningData.warningMsg.warningDataList.size > 0) {
level = rsmWarningData.warningMsg.warningDataList[0].warningLevel
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager onMogoObuRsmWarning ---status---> ${rsmWarningData.status} --list status----> ${rsmWarningData.warningMsg.warningDataList.get(0).status} --v2xType--- $v2xType ---alertContent = $alertContent ---ttsContent= $ttsContent"
)
when (rsmWarningData.warningMsg.warningDataList.get(0).status) {
MogoObuConstants.STATUS.ADD -> { // 添加
//显示警告红边
CallerHmiManager.showWarning(direction)
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
v2xType,
alertContent,
ttsContent
)
).apply {
sourceType = DataSourceType.TELEMATIC
}
)
CallerHmiManager.warningV2X(
v2xType,
alertContent,
ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
(v2xType + direction.direction),//使用当前事件类型+方向记录tag当发生变化的时候关闭当前弹出新的
object : IMoGoWarningStatusListener {
override fun onDismiss() {
// 关闭警告红边
CallerHmiManager.showWarning(
WarningDirectionEnum.ALERT_WARNING_NON
)
}
},
true,
5000L
)
// 更新数据 TODO
// TrafficDataConvertUtils.cvxPtcThreatIndInfo2TrafficData(rsmWarningData)?.let {
//// TrafficMarkerDrawer.updateITrafficThreatLevelInfo(it)
// CallerMapUIServiceManager.getMarkerService()
// ?.updateITrafficThreatLevelInfo(it)
// }
}
MogoObuConstants.STATUS.UPDATE -> {// 更新
}
// 删除
MogoObuConstants.STATUS.DELETE -> {
// 关闭警告红边
CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
// 更新数据 TODO 由于obu通过域控需要转换单位这里临时转换后面3.0不需要转换
// TrafficDataConvertUtils.cvxPtcThreatIndInfo2TrafficData(rsmWarningData)?.let {
// // 事件结束,还原交通参与者颜色
// it.threatLevel = 0x01
//// TrafficMarkerDrawer.updateITrafficThreatLevelInfo(it)
// CallerMapUIServiceManager.getMarkerService()
// ?.updateITrafficThreatLevelInfo(it)
// }
//删除弱势交通元素
CallerMapUIServiceManager.getMarkerService()
?.removeCvxRvInfoIndInfo(rsmWarningData.participantOfOne.ptcID.toString())
// TrafficMarkerDrawer.removeCvxRvInfoIndInfo(rsmWarningData.participantOfOne.ptcID.toString())
}
}
}
}
}
}
/**
* 红绿灯预警信息
*/
fun onMogoObuDcSpatWarning(spatWarningData: SpatWarningData?) {
CallerLogger.d("${M_OBU}${TAG}", "onMogoObuDcSpatWarning warningType = ${spatWarningData!!.warningType} --status = ${spatWarningData?.status} --lightsList = ${spatWarningData.lightsList}")
handlerTrafficLight(
spatWarningData!!.warningType,
spatWarningData?.status,
spatWarningData?.lightsList
)
}
/**
* 地图匹配 是OBU算法输出地图匹配结果主车匹配道路哪条路或者哪条车道
*/
fun onMogoObuMapMath(data: MapMatchData?) {
CallerLogger.d("${M_OBU}${TAG}", "MogoObuDcCombineManager onMogoObuMapMath HmiBuildConfig.isShowObuLimitSpeedView = " + HmiBuildConfig.isShowObuLimitSpeedView)
if(HmiBuildConfig.isShowObuLimitSpeedView) {
if (data != null) {
CallerLogger.d("${M_OBU}${TAG}",
"MogoObuDcCombineManager onMogoObuMapMath = ${data.status} --speedMaxLimit = ${Math.round((data.speedMaxLimit*0.02*3.6))} --- data.speedMaxLimit = ${data.speedMaxLimit}")
when (data.status) {
MogoObuConstants.STATUS.ADD -> { // 添加 TODO
CallerHmiManager.showLimitingVelocity(Math.round((data.speedMaxLimit*0.02*3.6)).toInt(), 2)
}
MogoObuConstants.STATUS.UPDATE -> { // 更新
}
MogoObuConstants.STATUS.DELETE -> { // 删除
CallerHmiManager.disableLimitingVelocity()
}
}
}
}
}
/**
* 获取消息的方位 车辆相关
*/
private fun getMessageDirection(targetClassification: Int): WarningDirectionEnum {
return when (targetClassification) {
MogoObuConstants.VEH_TARGET_POSITION.AHEAD_IN_LANE,
MogoObuConstants.VEH_TARGET_POSITION.ONCOMING_IN_LANE -> WarningDirectionEnum.ALERT_WARNING_TOP //正前方
MogoObuConstants.VEH_TARGET_POSITION.BEHEAD_IN_LANE -> WarningDirectionEnum.ALERT_WARNING_BOTTOM //正后方
MogoObuConstants.VEH_TARGET_POSITION.INTERSECTION_RIGHT -> WarningDirectionEnum.ALERT_WARNING_RIGHT //正右方
MogoObuConstants.VEH_TARGET_POSITION.INTERSECTION_LEFT -> WarningDirectionEnum.ALERT_WARNING_LEFT //正左方
MogoObuConstants.VEH_TARGET_POSITION.AHEAD_LEFT, MogoObuConstants.VEH_TARGET_POSITION.AHEAD_FAR_LEFT,
MogoObuConstants.VEH_TARGET_POSITION.ONCOMING_LEFT, MogoObuConstants.VEH_TARGET_POSITION.ONCOMING_FAR_LEFT
-> WarningDirectionEnum.ALERT_WARNING_TOP_LEFT //左前方
MogoObuConstants.VEH_TARGET_POSITION.AHEAD_RIGHT, MogoObuConstants.VEH_TARGET_POSITION.AHEAD_FAR_RIGHT,
MogoObuConstants.VEH_TARGET_POSITION.ONCOMING_RIGHT, MogoObuConstants.VEH_TARGET_POSITION.ONCOMING_FAT_RIGHT
-> WarningDirectionEnum.ALERT_WARNING_TOP_RIGHT //右前方
MogoObuConstants.VEH_TARGET_POSITION.BEHEAD_LEFT, MogoObuConstants.VEH_TARGET_POSITION.BEHEAD_FAR_LEFT,
-> WarningDirectionEnum.ALERT_WARNING_BOTTOM_LEFT //左后方
MogoObuConstants.VEH_TARGET_POSITION.BEHEAD_RIGHT, MogoObuConstants.VEH_TARGET_POSITION.BEHEAD_FAR_RIGHT,
-> WarningDirectionEnum.ALERT_WARNING_BOTTOM_RIGHT //右后方
MogoObuConstants.VEH_TARGET_POSITION.UNCLASSIFIED -> WarningDirectionEnum.ALERT_WARNING_NON //未知
else -> WarningDirectionEnum.ALERT_WARNING_ALL
}
}
/**
* 处理红绿灯
*/
private fun handlerTrafficLight(appId: Int, status: Int, lights: List<ObuWarningEvent.SpatLight>) {
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager handlerTrafficLight --- status = $status ---lights.size = ${lights.size} ---lights = $lights ---appId = $appId"
)
when (status) {
// 添加
MogoObuConstants.STATUS.ADD,
MogoObuConstants.STATUS.UPDATE
-> {
if (lights != null && lights.isNotEmpty()) {
changeTrafficLightStatus(appId, lights)
}
}
// 删除
MogoObuConstants.STATUS.DELETE -> {
// 移除顶部弹窗,当收不到信号的时候触发一次
CallerHmiManager.disableWarningTrafficLight()
CallerHmiManager.disableWarningV2X(appId.toString())
isShowGreenWave = false
isShowRunRedLight = false
}
}
}
private var isRedLight = false
private var isGreenLight = false
private var isShowGreenWave = false
private var isShowRunRedLight = false
/**
* 修改红绿灯
*/
@Synchronized
private fun changeTrafficLightStatus(
appId: Int,
lights: List<ObuWarningEvent.SpatLight>
) {
var ttsContent = ""
var alertContent = ""
//这里需要根据真实数据确定 index 取值方式
val currentLight = lights[0]
CallerLogger.e(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager currentLight = $currentLight ---currentLight.phaseID = ${currentLight.phaseID} ---appId = $appId ---isShowRunRedLight = $isShowRunRedLight ---isShowGreenWave = $isShowGreenWave"
)
// 闯红灯预警和绿波通行底层是互斥的
when (appId) {
0 -> {//不可用 V2I_RLVW_VIOLATION_TYPE_UNAVAILABLE 无效
}
1 -> { //闯红灯 V2I_RLVW_VIOLATION_TYPE_RUNNING_RED_LIGHT 一个红灯周期只显示一次
if (!isShowRunRedLight) {
isShowRunRedLight = true
CallerHmiManager.disableWarningV2X(1667.toString())
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType)
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType)
CallerLogger.d("${M_OBU}${TAG}","MogoObuDcCombineManager changeTrafficLightStatus 闯红灯 --------> ttsContent = $ttsContent ---alertContent = $alertContent ")
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType,
alertContent,
ttsContent
)
).apply {
sourceType = DataSourceType.TELEMATIC
}
)
CallerHmiManager.warningV2X(
EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType, alertContent, ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType, null, true, 5000L)
}
}
2 -> { //绿波通行引导 V2I_RLVW_VIOLATION_TYPE_NO_VIOLATION 一个绿灯周期只显示一次
if (!isShowGreenWave) {
isShowGreenWave = true
CallerHmiManager.disableWarningV2X(1666.toString())
CallerLogger.d(
"${M_OBU}${TAG}",
"MogoObuDcCombineManager 绿波通行引导 --------> speed_min = ${currentLight.suggestMinSpeed} --speed_max = ${currentLight.suggestMaxSpeed}")
val adviceSpeed =
"${Math.round(currentLight.suggestMinSpeed*3.6*0.02)} - ${Math.round(currentLight.suggestMaxSpeed*3.6*0.02)}"
val adviceSpeedTts =
"${Math.round(currentLight.suggestMinSpeed*3.6*0.02)} - ${Math.round(currentLight.suggestMaxSpeed*3.6*0.02)}"
ttsContent =
String.format(
EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType),
adviceSpeedTts
)
alertContent =
String.format(
EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType),
adviceSpeed
)
val maxSpeed = currentLight.suggestMaxSpeed*3.6
if (maxSpeed > 0) {
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType,
alertContent,
ttsContent
)
).apply {
sourceType = DataSourceType.TELEMATIC
}
)
CallerHmiManager.warningV2X(
EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType,
alertContent,
ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
appId.toString(),
null,
true,
5000L
)
}
}
}
}
when (currentLight.light) {
// 灯光不可用
0 -> {
CallerHmiManager.showWarningTrafficLight(0, 2)
}
// 红灯
2, 3 -> {
if (!isRedLight) {
CallerHmiManager.disableWarningV2X(appId.toString())
isRedLight = true
}
isGreenLight = false
CallerHmiManager.showWarningTrafficLight(1, 2)
val red = currentLight.countDown / 10
CallerHmiManager.changeCountdownRed(red)
}
// 绿灯
4, 5, 6 -> {
if (!isGreenLight) {
CallerHmiManager.disableWarningV2X(appId.toString())
isGreenLight = true
}
isRedLight = false
CallerHmiManager.showWarningTrafficLight(3, 2)
val green = currentLight.countDown / 10
CallerHmiManager.changeCountdownGreen(green)
}
// 黄灯
7, 8 -> {
CallerHmiManager.disableWarningV2X(appId.toString())
CallerHmiManager.showWarningTrafficLight(2, 2)
val yellow = currentLight.countDown / 10
CallerHmiManager.changeCountdownYellow(yellow)
}
}
}
}

View File

@@ -2,13 +2,15 @@ package com.mogo.eagle.core.function.obu.mogo
import android.content.Context
import android.util.Log
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.config.HmiBuildConfig
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.data.enums.EventTypeEnum
import com.mogo.eagle.core.data.enums.EventTypeHelper
import com.mogo.eagle.core.data.enums.WarningDirectionEnum
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
@@ -16,18 +18,12 @@ import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Default
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.TooClose
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.call.obu.CallerObuListenerManager
import com.mogo.eagle.core.function.obu.mogo.utils.TrafficDataConvertUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OBU
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.enums.EventTypeEnum
import com.mogo.eagle.core.data.enums.EventTypeHelper
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
//import com.mogo.service.IMogoServiceApis
import com.zhidao.support.obu.MogoObuManager
import com.zhidao.support.obu.OnMogoObuListener
import com.zhidao.support.obu.constants.ObuConstants
@@ -48,14 +44,11 @@ class MogoPrivateObuManager private constructor() {
}
}
// private var mMogoServiceApis: IMogoServiceApis? = null
private var mContext: Context? = null
private var mObuStatusInfo = CallerObuListenerManager.getObuStatusInfo()
fun init(context: Context, ipAddress: String) {
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_OBU}", "obuManager初始化--")
// mMogoServiceApis = ARouter.getInstance().build(MogoServicePaths.PATH_SERVICE_APIS)
// .navigation(context) as IMogoServiceApis
mContext = context
//连接obu设备
connectObu(context, ipAddress)

View File

@@ -1,11 +1,10 @@
package com.mogo.eagle.core.function.obu.mogo
import android.content.Context
import android.util.Log
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.config.HmiBuildConfig
import com.mogo.eagle.core.data.config.HmiBuildConfig.isShowObuLimitSpeedView
import com.mogo.eagle.core.data.enums.*
import com.mogo.eagle.core.data.msgbox.DataSourceType
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
@@ -18,6 +17,8 @@ import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Defa
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.TooClose
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.call.obu.CallerObuListenerManager
import com.mogo.eagle.core.function.call.obu.CallerObuTrafficLightListenerManager
import com.mogo.eagle.core.function.call.v2x.CallObuLimitingSpeedListenerManager
import com.mogo.eagle.core.function.obu.mogo.utils.TrafficDataConvertUtilsNew
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OBU
@@ -93,7 +94,6 @@ class MogoPrivateObuNewManager private constructor() {
*/
override fun onConnectStatus(connectStatus: Int) {
if (connectStatus == 0) { //断开连接
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}", "onConnectFail ------> ")
mObuStatusInfo.obuStatus = false
mObuStatusInfo.obuHvStatus = false
mObuStatusInfo.obuRvStatus = false
@@ -102,7 +102,6 @@ class MogoPrivateObuNewManager private constructor() {
mContext?.let { SharedPrefsMgr.getInstance(it).putBoolean("OBU_HV", false) }
mContext?.let { SharedPrefsMgr.getInstance(it).putBoolean("OBU_RV", false) }
} else if (connectStatus == 1) { //连接成功
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}", "onConnected ------> ")
mObuStatusInfo.obuStatus = true
CallerObuListenerManager.invokeListener(mObuStatusInfo)
mContext?.let { SharedPrefsMgr.getInstance(it).putBoolean("OBU", true) }
@@ -170,47 +169,47 @@ class MogoPrivateObuNewManager private constructor() {
*/
override fun onMogoObuRvWarning(data: MogoObuRvWarningData) {
super.onMogoObuRvWarning(data)
if (HmiBuildConfig.isShowObuV2vView) {
mObuStatusInfo.obuRvStatus = true
CallerObuListenerManager.invokeListener(mObuStatusInfo)
// if (HmiBuildConfig.isShowObuV2vView) { //TODO 临时需要关闭v2v开关
mObuStatusInfo.obuRvStatus = true
CallerObuListenerManager.invokeListener(mObuStatusInfo)
if (!data.warningMsg.warningData.isNullOrEmpty()) {
// 更新数据远车数据之前要匹配uuid
TrafficDataConvertUtilsNew.cvxRvInfoIndInfo2TrafficData(data)?.let {
CallerMapUIServiceManager.getMarkerService()?.updateITrafficLocationInfo(it)
}
if (!data.warningMsg.warningData.isNullOrEmpty()) {
// 更新数据远车数据之前要匹配uuid
TrafficDataConvertUtilsNew.cvxRvInfoIndInfo2TrafficData(data)?.let {
CallerMapUIServiceManager.getMarkerService()?.updateITrafficLocationInfo(it)
}
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}", data.toString())
data.let {
//预警信息,预警类型 threat_level 2、3
var status = data.status
data.vehBasicsMsg?.let {
//预警方位
val direction = getMessageDirection(data.vehBasicsMsg.targetPosition)
//处理预警类型
var appId = ""
var level = -1
data.warningMsg?.let {
if (data.warningMsg.warningData != null && data.warningMsg.warningData.size > 0) {
level = data.warningMsg.warningData[0].warningLevel
appId = data.warningMsg.warningData[0].warningType.toString()
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}", data.toString())
data.let {
//预警信息,预警类型 threat_level 2、3
data.vehBasicsMsg?.let {
//预警方位
val direction = getMessageDirection(data.vehBasicsMsg.targetPosition)
//处理预警类型
var appId = ""
var level = -1
var status = -1
data.warningMsg?.let {
if (data.warningMsg.warningData != null && data.warningMsg.warningData.size > 0) {
level = data.warningMsg.warningData[0].warningLevel
appId = data.warningMsg.warningData[0].warningType.toString()
status = data.warningMsg.warningData[0].status
//拼凑数据
if (appId != null) {
handleSdkObu(appId, direction, status, level, data)
}
}
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuRvWarning target_classification = ${
getMessageDirection(data.vehBasicsMsg.targetPosition)
} --- direction = $direction --- appId = $appId ---level = $level -- status = $status"
)
//拼凑数据
if (appId != null) {
handleSdkObu(appId, direction, status, level, data)
}
}
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuRvWarning target_classification = ${
getMessageDirection(data.vehBasicsMsg.targetPosition)
} --- direction = $direction --- appId = $appId ---level = $level -- status = $status"
)
}
}
}
// }
}
/**
@@ -218,46 +217,43 @@ class MogoPrivateObuNewManager private constructor() {
*/
override fun onMogoObuSpatWarning(data: MogoObuSpatWarningData) {
super.onMogoObuSpatWarning(data)
if (data?.lights != null && data.lights.isNotEmpty()
) {
if (HmiBuildConfig.isShowObuV2iView) {
handlerTrafficLight(
data.warningType,
data.status,
data.lights
)
}
if (data != null) {
// if (HmiBuildConfig.isShowObuV2iView) {
handlerTrafficLight(
data.warningType,
data.status,
data.lights
)
// }
}
}
/**
* RSI预警信息 CvxRtiThreatIndInfo(交通标志预警(前方限速、前方学校等等),交通事件预警(前方拥堵、前方积水等等))
* RSI预警信息 onMogoObuRsiWarning(交通标志预警(前方限速、前方学校等等),交通事件预警(前方拥堵、前方积水等等))
*/
override fun onMogoObuRsiWarning(data: MogoObuRsiWarningData) {
super.onMogoObuRsiWarning(data)
if (HmiBuildConfig.isShowObuV2iView) {
// if (HmiBuildConfig.isShowObuV2iView) {
if (data != null && data.warningMsg != null && data.warningMsg.size > 0) {
var alertContent = ""
var ttsContent = ""
var appId = data.warningMsg[0].sceneType.toString()
val status = data.status
val level = data.warningMsg[0].warningLevel
val direction = getMessageDirection(data.warningMsg[0].targetPosition)
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuRsiWarning ------> $data"
"onMogoObuRsiWarning appId = $appId --status = $status --level = $level -- eventSerialNum = ${data.warningMsg[0].eventSerialNum} ---signSerialNum = ${data.warningMsg[0].signSerialNum} --- direction = $direction -- targetPosition = ${data.warningMsg[0].targetPosition}"
)
if (data != null && data.warningMsg != null && data.warningMsg.size > 0) {
var alertContent = ""
var ttsContent = ""
var appId = data.warningMsg[0].sceneType.toString()
val status = data.status
val level = data.warningMsg[0].warningLevel
val direction = getMessageDirection(data.warningMsg[0].targetPosition)
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onCvxRtiThreatIndInfo appId = $appId --status = $status --level = $level -- eventSerialNum = ${data.warningMsg[0].eventSerialNum} ---signSerialNum = ${data.warningMsg[0].signSerialNum} --- direction = $direction -- targetPosition = ${data.warningMsg[0].targetPosition}"
)
if (appId != "0") {
when (appId) {
// 道路危险情况预警
MogoObuConstants.RSI_SCENE_TYPE.HLW.toString() -> {
when (data.warningMsg[0].eventSerialNum) {
MogoObuConstants.RTE.RTI_TYPE_BREAKDOWN -> {//车辆故障
appId = EventTypeEnumNew.TYPE_USECASE_ID_BREAKDOWN_WARNING.poiType
appId =
EventTypeEnumNew.TYPE_USECASE_ID_BREAKDOWN_WARNING.poiType
}
MogoObuConstants.RTE.RTI_TYPE_ROAD_WATER -> { //道路积水
appId = EventTypeEnumNew.FOURS_PONDING.poiType
@@ -341,9 +337,11 @@ class MogoPrivateObuNewManager private constructor() {
MogoObuConstants.RTS.RTI_TYPE_NO_TOOTING -> { //禁止鸣笛
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_NO_TOOTING.poiType
}
MogoObuConstants.RTS.RTI_TYPE_SPEED_LIMIT -> { //限速
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_SPEED_LIMIT.poiType
}
// MogoObuConstants.RTS.RTI_TYPE_SPEED_LIMIT -> { //限速
// appId =
// EventTypeEnumNew.TYPE_USECASE_ID_ROAD_SPEED_LIMIT.poiType
// }
// MogoObuConstants.RTS.RTI_TYPE_GO_STRAIGHT_TURN_RIGHT -> { //直行或右转
// appId =
// EventTypeEnumNew.TYPE_USECASE_ID_GO_STRAIGHT_TURN_RIGHT.poiType
@@ -381,7 +379,6 @@ class MogoPrivateObuNewManager private constructor() {
// 拥堵
MogoObuConstants.RSI_SCENE_TYPE.TJW.toString() -> {
appId = EventTypeEnumNew.TYPE_USECASE_ID_TJW.poiType
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = String.format( //事件才有影响范围
@@ -398,6 +395,7 @@ class MogoPrivateObuNewManager private constructor() {
//限速预警, ADD处理一次
MogoObuConstants.RSI_SCENE_TYPE.SLW.toString() -> {
appId = EventTypeEnumNew.TYPE_USECASE_ID_ROAD_SPEED_LIMIT.poiType
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
}
@@ -405,25 +403,30 @@ class MogoPrivateObuNewManager private constructor() {
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"new onMogoObuRsiWarning ttsContent = $ttsContent --alertContent = $alertContent --appId = $appId ---direction = ${direction.direction} --distance = ${Math.round(data.warningMsg[0].distance)} ---eventRadius = ${Math.round(data.warningMsg[0].eventRadius)} --speedMaxLimit = ${data.warningMsg[0].speedMaxLimit.toInt()}"
"new onMogoObuRsiWarning appId = $appId ---status = $status --- ttsContent = $ttsContent --alertContent = $alertContent -- eventSerialNum = ${data.warningMsg[0].eventSerialNum} ---signSerialNum = ${data.warningMsg[0].signSerialNum} ---direction = ${direction.direction} --distance = ${
Math.round(data.warningMsg[0].distance)
} ---eventRadius = ${Math.round(data.warningMsg[0].eventRadius)} --speedMaxLimit = ${data.warningMsg[0].speedMaxLimit.toInt()}"
)
when (status) {
MogoObuConstants.STATUS.ADD -> { // 添加
//显示警告红边
// CallerHmiManager.showWarning(direction)
//不显示弹框,语音提示,数据在消息盒子里面展示,此处不在处理弹框
if (alertContent.isNullOrEmpty() || ttsContent.isNullOrEmpty()) {
Log.d("MsgBox-PriObuNewMana1", "alertContent或ttsContent为空!")
return
}
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.OBU,
MsgBoxType.V2X,
V2XMsg(
appId,
alertContent,
ttsContent
)
)
).apply {
sourceType = DataSourceType.OBU
}
)
CallerHmiManager.warningV2X(
appId,
@@ -437,7 +440,7 @@ class MogoPrivateObuNewManager private constructor() {
}
},
true,
3000L
5000L
)
// 更新数据
@@ -451,10 +454,6 @@ class MogoPrivateObuNewManager private constructor() {
}
MogoObuConstants.STATUS.DELETE -> { // 删除
// 关闭警告红边
// CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
// 移除顶部弹窗
// CallerHmiManager.disableWarningV2X((appId + direction.direction))
// 更新数据
TrafficDataConvertUtilsNew.cvxRtiThreatIndInfo2TrafficData(data)
?.let {
@@ -467,7 +466,7 @@ class MogoPrivateObuNewManager private constructor() {
}
}
}
// }
}
/**
@@ -483,106 +482,146 @@ class MogoPrivateObuNewManager private constructor() {
data: MogoObuRsmWarningData?
) {
super.onMogoObuRsmWarning(data)
if (HmiBuildConfig.isShowObuV2iView) {
if (HmiBuildConfig.isShowObuWeaknessTrafficView) {
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuRsmWarning ------> ${data.toString()}"
)
// if (HmiBuildConfig.isShowObuV2iView) {
if (HmiBuildConfig.isShowObuWeaknessTrafficView) {
// 交通参与者类型 0x0:未知 UNKNOWN | 1机动车 2:非机动车 NON_MOTOR | 3:行人 PEDESTRIAN 4:obu
if (data != null && data.participant != null) {
var v2xType = ""
if (data.participant.ptcType == 1) { //机动车
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_MOTOR_VEHICLES.poiType
} else if (data.participant.ptcType == 2) { //非机动车
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_NOT_MOTOR_VEHICLES.poiType
} else if (data.participant.ptcType == 3) { //行人
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_PERSON.poiType
} else { //未知
v2xType = EventTypeEnumNew.TYPE_ERROR.poiType
}
val ttsContent = EventTypeEnumNew.getWarningTts(v2xType)
val alertContent =
EventTypeEnumNew.getWarningContent(v2xType)
var level = -1
val direction = getMessageDirection(data.participant.targetPosition)
//物体数据绘制
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuRsmWarning ------> ${data.toString()}"
)
// 交通参与者类型 0x0:未知 UNKNOWN | 1机动车 2:非机动车 NON_MOTOR | 3:行人 PEDESTRIAN 4:obu
if (data != null && data.participant != null) {
var v2xType = ""
if (data.participant.ptcType == 1) { //机动车
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_MOTOR_VEHICLES.poiType
} else if (data.participant.ptcType == 2) { //非机动车
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_NOT_MOTOR_VEHICLES.poiType
} else if (data.participant.ptcType == 3) { //行人
v2xType =
EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_PERSON.poiType
} else { //未知
v2xType = EventTypeEnumNew.TYPE_ERROR.poiType
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}", "onMogoObuRsmWarning ---- data.status = ${data.status} ---data.participant.ptcId = ${data.participant.ptcId} ---data.participant.ptcType = ${data.participant.ptcType} ---data.warningMsg = ${data.warningMsg} -----data = ${data.toString()}")
when (data.status) {
MogoObuConstants.STATUS.ADD -> { // 添加
// 更新数据模型变色的时候是不是update,如果不是更新可能导致模型不变色add的时候是否有level高的 TODO
TrafficDataConvertUtilsNew.cvxPtcThreatIndInfo2TrafficData(data)
?.let {
CallerMapUIServiceManager.getMarkerService()
?.updateITrafficThreatLevelInfo(it)
}
}
val ttsContent = EventTypeEnumNew.getWarningTts(v2xType)
val alertContent =
EventTypeEnumNew.getWarningContent(v2xType)
var level = -1
val direction = getMessageDirection(data.participant.targetPosition)
if (data.warningMsg != null && data.warningMsg.warningData != null && data.warningMsg.warningData.size > 0) {
level = data.warningMsg.warningData[0].warningLevel //默认是1个
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"new onMogoObuRsmWarning ---status---> ${data.status} ---data.warningMsg.warningData[0].status = ${data.warningMsg.warningData[0].status} ---v2xType = $v2xType ---alertContent = $alertContent ---ttsContent = $ttsContent "
)
when (data.warningMsg.warningData[0].status) {
MogoObuConstants.STATUS.ADD -> { // 添加
// if (level == 2 || level == 3) { //不考虑level
//显示警告红边
CallerHmiManager.showWarning(direction)
if (alertContent.isNullOrEmpty() || ttsContent.isNullOrEmpty()) {
Log.d("MsgBox-PriObuNewMana2", "alertContent或ttsContent为空!")
}
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.OBU,
V2XMsg(
v2xType,
alertContent,
ttsContent
)
)
)
CallerHmiManager.warningV2X(
v2xType,
alertContent,
ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
(v2xType + direction.direction),//使用当前事件类型+方向记录tag当发生变化的时候关闭当前弹出新的
object : IMoGoWarningStatusListener {
override fun onDismiss() {
// 关闭警告红边
CallerHmiManager.showWarning(
WarningDirectionEnum.ALERT_WARNING_NON
)
}
},
true,
5000L
)
// }
MogoObuConstants.STATUS.UPDATE -> { // 更新
//处理删除逻辑,
// if (rsmPtcIdMap.containsKey(data.participant.ptcId.toString())) {
// var oldTime = rsmPtcIdMap[data.participant.ptcId.toString()]
// var timeDiff = (System.currentTimeMillis() - oldTime!!) / 1000
// if (timeDiff > 3) { //超过3秒,删除对应弱势交通元素
// CallerMapUIServiceManager.getMarkerService()
// ?.removeCvxRvInfoIndInfo(data.participant.ptcId.toString())
// }
// rsmPtcIdMap.remove(data.participant.ptcId.toString())
// rsmPtcIdMap[data.participant.ptcId.toString()] = System.currentTimeMillis()
// } else {
// rsmPtcIdMap[data.participant.ptcId.toString()] = System.currentTimeMillis()
// }
}
// 更新数据
TrafficDataConvertUtilsNew.cvxPtcThreatIndInfo2TrafficData(data)?.let {
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}", "add cvxPtcThreatIndInfo2TrafficData ---it---> $it")
MogoObuConstants.STATUS.DELETE -> { // 删除
// 更新数据 TODO 删除原来的改变颜色删除marker。不影响别的模型添加
TrafficDataConvertUtilsNew.cvxPtcThreatIndInfo2TrafficData(data)
?.let {
// 事件结束,还原交通参与者颜色
it.threatLevel = 0x01
CallerMapUIServiceManager.getMarkerService()
?.updateITrafficThreatLevelInfo(it)
}
//删除弱势交通元素
CallerMapUIServiceManager.getMarkerService()
?.removeCvxRvInfoIndInfo(data.participant.ptcId.toString())
}
}
//预警status
if (data.warningMsg != null && data.warningMsg.warningData != null && data.warningMsg.warningData.size > 0) {
level = data.warningMsg.warningData[0].warningLevel //默认是1个
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuRsmWarning ---status---> ${data.status} ---data.warningMsg.warningData[0].status = ${data.warningMsg.warningData[0].status} ---v2xType = $v2xType ---alertContent = $alertContent ---ttsContent = $ttsContent ---level = $level"
)
when (data.warningMsg.warningData[0].status) {
MogoObuConstants.STATUS.ADD -> { // 添加
//更新模型的颜色
TrafficDataConvertUtilsNew.cvxPtcThreatIndInfo2TrafficData(data)
?.let {
CallerMapUIServiceManager.getMarkerService()
?.updateITrafficThreatLevelInfo(it)
}
}
MogoObuConstants.STATUS.UPDATE -> {// 更新
if (alertContent.isNullOrEmpty() || ttsContent.isNullOrEmpty()) {
return
}
//显示警告红边
CallerHmiManager.showWarning(direction)
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
v2xType,
alertContent,
ttsContent
)
).apply {
sourceType = DataSourceType.OBU
}
)
// 删除
MogoObuConstants.STATUS.DELETE -> {
// 关闭警告红边
CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
// 更新数据 TODO 删除原来的改变颜色删除marker。不影响别的模型添加
TrafficDataConvertUtilsNew.cvxPtcThreatIndInfo2TrafficData(data)
?.let {
// 事件结束,还原交通参与者颜色
it.threatLevel = 0x01
CallerMapUIServiceManager.getMarkerService()
?.updateITrafficThreatLevelInfo(it)
CallerHmiManager.warningV2X(
v2xType,
alertContent,
ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
(v2xType + direction.direction),//使用当前事件类型+方向记录tag当发生变化的时候关闭当前弹出新的
object : IMoGoWarningStatusListener {
override fun onDismiss() {
// 关闭警告红边
CallerHmiManager.showWarning(
WarningDirectionEnum.ALERT_WARNING_NON
)
}
},
true,
5000L
)
}
//删除弱势交通元素
CallerMapUIServiceManager.getMarkerService()?.removeCvxRvInfoIndInfo(data.participant.ptcId.toString())
}
MogoObuConstants.STATUS.UPDATE -> {// 更新
}
MogoObuConstants.STATUS.DELETE -> { // 删除
// 关闭警告红边
CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
//删除弱势交通元素
CallerMapUIServiceManager.getMarkerService()
?.removeCvxRvInfoIndInfo(data.participant.ptcId.toString())
}
}
}
}
}
// }
}
/**
@@ -590,16 +629,19 @@ class MogoPrivateObuNewManager private constructor() {
*/
override fun onMogoObuMapMath(data: MogoObuMapMathData?) {
super.onMogoObuMapMath(data)
if(isShowObuLimitSpeedView) {
// if (isShowObuLimitSpeedView) {
if (data != null) {
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"onMogoObuMapMathstatus = ${data.status} --speedMaxLimit = ${Math.round((data.speedMaxLimit*3.6))}")
"onMogoObuMapMath = ${data.status} --speedMaxLimit = ${Math.round((data.speedMaxLimit * 3.6))}"
)
when (data.status) {
MogoObuConstants.STATUS.ADD -> { // 添加
UiThreadHandler.post {
if(data.speedMaxLimit > 0) {
CallerHmiManager.showLimitingVelocity(Math.round((data.speedMaxLimit*3.6)).toInt())
if (data.speedMaxLimit > 0) {
// CallerHmiManager.showLimitingVelocity(
// Math.round((data.speedMaxLimit * 3.6)).toInt(), 2)
CallObuLimitingSpeedListenerManager.invokeOnObuLimitingSpeedChange(Math.round((data.speedMaxLimit * 3.6)).toInt())
}
}
}
@@ -609,22 +651,23 @@ class MogoPrivateObuNewManager private constructor() {
MogoObuConstants.STATUS.DELETE -> { // 删除
UiThreadHandler.post {
CallerHmiManager.disableLimitingVelocity()
// CallerHmiManager.disableLimitingVelocity()
CallObuLimitingSpeedListenerManager.invokeOnObuLimitingSpeedChange(-1)
}
}
}
}
}
// }
}
}
}
}
/**
* 获取消息的方位 车辆相关
*/
private fun getMessageDirection(targetClassification: Int): WarningDirectionEnum {
// CallerLogger.d("$M_OBU${TAG_MOGO_NEW_OBU}", "预警红边:预警方向->$targetClassification")
// CallerLogger.d("$M_OBU${TAG_MOGO_NEW_OBU}", "预警红边:预警方向->$targetClassification")
return when (targetClassification) {
MogoObuConstants.VEH_TARGET_POSITION.AHEAD_IN_LANE,
MogoObuConstants.VEH_TARGET_POSITION.ONCOMING_IN_LANE -> WarningDirectionEnum.ALERT_WARNING_TOP //正前方
@@ -657,7 +700,7 @@ class MogoPrivateObuNewManager private constructor() {
/**
* 构造对应展示数据和场景 根据obu的场景add change delete确定是否展示
*
* @param appId 使用WarningTypeEnum获取icon、提示内容、tts内容
* @param appId 使用WarningTypeEnum获取icon、提示内容、tts内容 TODO 添加事件频繁播报拦截
*
* @see com.mogo.module.common.enums.EventTypeEnum
*/
@@ -669,56 +712,32 @@ class MogoPrivateObuNewManager private constructor() {
info: MogoObuRvWarningData
) {
// 这里排除需要特殊定制的语音及文案外,其余的都可以使用 EventTypeEnumNew 提供的
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"handleSdkObu appId = $appId --- handleDirection = $direction ---level = $level ---status = $status"
)
var alertContent: String
var ttsContent: String
var alertContent: String = ""
var ttsContent: String = ""
var changeVisualAngle = false
when (appId) {
// 变道预警,注意左后车辆/注意右后车辆
EventTypeEnumNew.TYPE_USECASE_ID_LCW.poiType -> {
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
if (
direction == WarningDirectionEnum.ALERT_WARNING_LEFT ||
direction == WarningDirectionEnum.ALERT_WARNING_TOP_LEFT ||
direction == WarningDirectionEnum.ALERT_WARNING_BOTTOM_LEFT
) {
ttsContent = String.format(ttsContent, "")
alertContent = String.format(alertContent, "")
} else if (
direction == WarningDirectionEnum.ALERT_WARNING_RIGHT ||
direction == WarningDirectionEnum.ALERT_WARNING_TOP_RIGHT ||
direction == WarningDirectionEnum.ALERT_WARNING_BOTTOM_RIGHT
) {
ttsContent = String.format(ttsContent, "")
alertContent = String.format(alertContent, "")
}
//交叉路口碰撞预警
MogoObuConstants.V2X_WARNING_TYPE.FCW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_FCW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_FCW.poiType)
}
//车辆失控预警
EventTypeEnumNew.TYPE_USECASE_ID_CLW.poiType -> {
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = String.format(alertContent, direction.desc)
ttsContent = String.format(ttsContent, direction.desc)
//交叉路口碰撞预警
MogoObuConstants.V2X_WARNING_TYPE.ICW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_ICW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_ICW.poiType)
}
//异常车辆提醒
EventTypeEnumNew.TYPE_USECASE_ID_AVW.poiType -> {
alertContent = EventTypeEnumNew.getWarningContent(appId)
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = String.format(alertContent, direction.desc)
ttsContent = String.format(ttsContent, direction.desc)
//左转辅助预警
MogoObuConstants.V2X_WARNING_TYPE.LTA.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_LTA.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_LTA.poiType)
}
//盲区预警
EventTypeEnumNew.TYPE_USECASE_ID_BSW.poiType -> {
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = EventTypeEnumNew.getWarningContent(appId)
MogoObuConstants.V2X_WARNING_TYPE.BSW.toString() -> {
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_BSW.poiType)
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_BSW.poiType)
if (
direction == WarningDirectionEnum.ALERT_WARNING_LEFT ||
direction == WarningDirectionEnum.ALERT_WARNING_TOP_LEFT ||
@@ -737,10 +756,65 @@ class MogoPrivateObuNewManager private constructor() {
alertContent = String.format(alertContent, "")
}
}
// 变道预警,注意左后车辆/注意右后车辆
MogoObuConstants.V2X_WARNING_TYPE.LCW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_LCW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_LCW.poiType)
if (
direction == WarningDirectionEnum.ALERT_WARNING_LEFT ||
direction == WarningDirectionEnum.ALERT_WARNING_TOP_LEFT ||
direction == WarningDirectionEnum.ALERT_WARNING_BOTTOM_LEFT
) {
ttsContent = String.format(ttsContent, "")
alertContent = String.format(alertContent, "")
} else if (
direction == WarningDirectionEnum.ALERT_WARNING_RIGHT ||
direction == WarningDirectionEnum.ALERT_WARNING_TOP_RIGHT ||
direction == WarningDirectionEnum.ALERT_WARNING_BOTTOM_RIGHT
) {
ttsContent = String.format(ttsContent, "")
alertContent = String.format(alertContent, "")
}
}
//逆向超车预警
MogoObuConstants.V2X_WARNING_TYPE.DNPW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_DNPW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_DNPW.poiType)
}
//紧急制动预警
MogoObuConstants.V2X_WARNING_TYPE.EBW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_EBW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_EBW.poiType)
}
//异常车辆提醒
MogoObuConstants.V2X_WARNING_TYPE.AVW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_AVW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_AVW.poiType)
alertContent = String.format(alertContent, direction.desc)
ttsContent = String.format(ttsContent, direction.desc)
}
//车辆失控预警
MogoObuConstants.V2X_WARNING_TYPE.CLW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_CLW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_CLW.poiType)
alertContent = String.format(alertContent, direction.desc)
ttsContent = String.format(ttsContent, direction.desc)
}
//车辆失控预警
MogoObuConstants.V2X_WARNING_TYPE.EVW.toString() -> {
alertContent = EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_EVW.poiType)
ttsContent = EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_EVW.poiType)
}
// 这里处理固定的提示信息,包括了<紧急车辆提醒>
else -> {
ttsContent = EventTypeEnumNew.getWarningTts(appId)
alertContent = EventTypeEnumNew.getWarningContent(appId)
else -> { //TODO
// ttsContent = EventTypeEnumNew.getWarningTts(appId.toString())
// alertContent = EventTypeEnumNew.getWarningContent(appId.toString())
}
}
@@ -753,19 +827,18 @@ class MogoPrivateObuNewManager private constructor() {
"new handleSdkObu appId2 = $appId --- level = $level ---ttsContent = $ttsContent --- alertContent = $alertContent --- direction = $direction"
)
if (level == 2 || level == 3) {
if (alertContent.isNullOrEmpty() || ttsContent.isNullOrEmpty()) {
Log.d("MsgBox-PriObuNewManager2", "alertContent或ttsContent为空!")
}
//不显示弹框,其它保留
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.OBU,
MsgBoxType.V2X,
V2XMsg(
appId,
alertContent,
ttsContent
)
)
).apply {
sourceType = DataSourceType.OBU
}
)
CallerHmiManager.warningV2X(
appId,
@@ -789,7 +862,7 @@ class MogoPrivateObuNewManager private constructor() {
}
},
true,
3000L
5000L
)
//显示警告红边
CallerHmiManager.showWarning(direction)
@@ -805,7 +878,7 @@ class MogoPrivateObuNewManager private constructor() {
// 关闭警告红边
CallerHmiManager.showWarning(WarningDirectionEnum.ALERT_WARNING_NON)
// 移除顶部弹窗
// CallerHmiManager.disableWarningV2X((appId + direction.direction))
// CallerHmiManager.disableWarningV2X((appId + direction.direction))
//更新周边车辆进行预警颜色变换,车辆实时移动和变色
TrafficDataConvertUtilsNew.cvxV2vThreatIndInfo2TrafficData(info)?.let {
it.threatLevel = 0x01
@@ -829,7 +902,9 @@ class MogoPrivateObuNewManager private constructor() {
MogoObuConstants.STATUS.ADD,
MogoObuConstants.STATUS.UPDATE
-> {
changeTrafficLightStatus(appId, lights)
if (lights != null && lights.isNotEmpty()) {
changeTrafficLightStatus(appId, lights)
}
}
// 删除
MogoObuConstants.STATUS.DELETE -> {
@@ -838,15 +913,25 @@ class MogoPrivateObuNewManager private constructor() {
CallerHmiManager.disableWarningV2X(appId.toString())
isShowGreenWave = false
isShowRunRedLight = false
isYellowLight = false
// lightCountDownRed = 1
// lightCountDownGreen = 1
// lightCountDownYellow = 1
}
}
}
private var isRedLight = false
private var isGreenLight = false
private var isYellowLight = false
private var isShowGreenWave = false
private var isShowRunRedLight = false
// private var lightCountDownRed : Int = 1
// private var lightCountDownGreen : Int = 1
// private var lightCountDownYellow : Int = 1
/**
* 修改红绿灯
*/
@@ -861,63 +946,93 @@ class MogoPrivateObuNewManager private constructor() {
val currentLight = lights[0]
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"currentLight = $currentLight ---currentLight.phase = ${currentLight.phaseId} ---appId = $appId"
"changeTrafficLightStatus currentLight = $currentLight ----currentLight.light = ${currentLight.light} ---currentLight.phase = ${currentLight.phaseId} ---appId = $appId --countDown = ${currentLight.countDown.toInt()}"
)
// 闯红灯预警,绿波通行和闯红灯是互斥的
when (appId) {
0x0 -> {//不可用 V2I_RLVW_VIOLATION_TYPE_UNAVAILABLE 无效
0 -> {//不可用 V2I_RLVW_VIOLATION_TYPE_UNAVAILABLE 无效
}
0x1 -> {//闯红灯 V2I_RLVW_VIOLATION_TYPE_RUNNING_RED_LIGHT 一个红灯周期只显示一次
1 -> {//闯红灯 V2I_RLVW_VIOLATION_TYPE_RUNNING_RED_LIGHT 一个红灯周期只显示一次
if (!isShowRunRedLight) {
isShowRunRedLight = true
CallerHmiManager.disableWarningV2X(0x2.toString())
CallerLogger.d("$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}","changeTrafficLightStatus 闯红灯 --------> ")
ttsContent = EventTypeEnumNew.getWarningTts(appId.toString())
alertContent = EventTypeEnumNew.getWarningContent(appId.toString())
CallerHmiManager.disableWarningV2X(1667.toString())
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"changeTrafficLightStatus 闯红灯 --------> "
)
ttsContent =
EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType)
alertContent =
EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType)
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType,
alertContent,
ttsContent
)
).apply {
sourceType = DataSourceType.OBU
}
)
CallerHmiManager.warningV2X(
appId.toString(), alertContent, ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
appId.toString(), null, true, 5000L)
EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType,
alertContent,
ttsContent,// 只有第一次才tts防止更新的时候不断的提醒
EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType,
null,
true,
5000L
)
}
}
0x2 -> { //绿波通行引导 V2I_RLVW_VIOLATION_TYPE_NO_VIOLATION 一个绿灯周期只显示一次 100m的时候
2 -> { //绿波通行引导 V2I_RLVW_VIOLATION_TYPE_NO_VIOLATION 一个绿灯周期只显示一次 100m的时候
if (!isShowGreenWave) {
isShowGreenWave = true
CallerHmiManager.disableWarningV2X(0x1.toString())
CallerLogger.d(
"$M_OBU${MogoObuConst.TAG_MOGO_NEW_OBU}",
"new changeTrafficLightStatus speed_min = ${currentLight.suggestMinSpeed} --speed_max = ${currentLight.suggestMaxSpeed} --TYPE_USECASE_ID_IVP_GREEN ---alertContent = $alertContent ---ttsContent = $ttsContent"
)
val adviceSpeed =
"${currentLight.suggestMinSpeed} - ${currentLight.suggestMaxSpeed}"
val adviceSpeedTts =
"${currentLight.suggestMinSpeed}${currentLight.suggestMaxSpeed}"
CallerHmiManager.disableWarningV2X(1666.toString())
var minSpeedTemp = Math.round(currentLight.suggestMinSpeed*3.6)
var maxSpeedTemp = Math.round(currentLight.suggestMaxSpeed*3.6)
if (minSpeedTemp == maxSpeedTemp) {
minSpeedTemp -= 5
}
val adviceSpeed = "$minSpeedTemp - $maxSpeedTemp"
val adviceSpeedTts = "$minSpeedTemp$maxSpeedTemp"
// val adviceSpeed =
// "${Math.round(currentLight.suggestMinSpeed*3.6)} - ${Math.round(currentLight.suggestMaxSpeed*3.6)}"
// val adviceSpeedTts =
// "${Math.round(currentLight.suggestMinSpeed*3.6)} 到 ${Math.round(currentLight.suggestMaxSpeed*3.6)}"
ttsContent =
String.format(
EventTypeEnumNew.getWarningTts(appId.toString()),
EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType),
adviceSpeedTts
)
alertContent =
String.format(
EventTypeEnumNew.getWarningContent(appId.toString()),
EventTypeEnumNew.getWarningContent(EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType),
adviceSpeed
)
val maxSpeed = currentLight.suggestMaxSpeed
if (maxSpeed > 0) {
if (alertContent.isNullOrEmpty() || ttsContent.isNullOrEmpty()) {
Log.d("MsgBox-PriObuNewManager1", "alertContent或ttsContent为空!")
}
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.OBU,
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_USECASE_ID_IVP_GREEN.poiType,
alertContent,
ttsContent
)
)
).apply {
sourceType = DataSourceType.OBU
}
)
CallerHmiManager.warningV2X(
@@ -937,7 +1052,7 @@ class MogoPrivateObuNewManager private constructor() {
when (currentLight.light) {
// 灯光不可用
0 -> {
CallerHmiManager.showWarningTrafficLight(0, 2)
CallerObuTrafficLightListenerManager.invokeObuTrafficLight(0)
}
// 红灯
2, 3 -> {
@@ -946,8 +1061,8 @@ class MogoPrivateObuNewManager private constructor() {
isRedLight = true
}
isGreenLight = false
CallerHmiManager.showWarningTrafficLight(1, 2)
isYellowLight = false
CallerObuTrafficLightListenerManager.invokeObuTrafficLight(1)
val red = currentLight.countDown.toInt()
CallerHmiManager.changeCountdownRed(red)
}
@@ -959,17 +1074,23 @@ class MogoPrivateObuNewManager private constructor() {
isGreenLight = true
}
isRedLight = false
CallerHmiManager.showWarningTrafficLight(3, 2)
isYellowLight = false
CallerObuTrafficLightListenerManager.invokeObuTrafficLight(3)
val green = currentLight.countDown.toInt()
CallerHmiManager.changeCountdownGreen(green)
}
// 黄灯
7, 8 -> {
if (!isYellowLight) {
isYellowLight = true
}
isRedLight = false
isGreenLight = false
CallerHmiManager.disableWarningV2X(appId.toString())
CallerHmiManager.showWarningTrafficLight(2, 2)
CallerObuTrafficLightListenerManager.invokeObuTrafficLight(2)
val yellow = currentLight.countDown.toInt()
CallerHmiManager.changeCountdownYellow(yellow)
}
}
}
}

View File

@@ -4,6 +4,7 @@ plugins {
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'com.alibaba.arouter'
id 'com.google.protobuf'
}
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
@@ -35,6 +36,19 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
protobuf {
protoc {
artifact = rootProject.ext.dependencies.protoc
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {}
}
}
}
}
}
dependencies {
@@ -50,15 +64,18 @@ dependencies {
implementation rootProject.ext.dependencies.rxandroid
implementation rootProject.ext.dependencies.flexbox
kapt rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.mogo_v2x
implementation rootProject.ext.dependencies.protobuf_java
implementation rootProject.ext.dependencies.protobuf_java_util
implementation rootProject.ext.dependencies.mogoaicloudtrafficlive
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
implementation rootProject.ext.dependencies.mogocommons
implementation rootProject.ext.dependencies.mogo_core_data
implementation rootProject.ext.dependencies.mogo_core_utils
implementation rootProject.ext.dependencies.mogo_core_function_call
implementation rootProject.ext.dependencies.mogo_core_res
compileOnly rootProject.ext.dependencies.mogomap
} else {
implementation project(":foudations:mogo-commons")
implementation project(':core:mogo-core-data')
@@ -66,7 +83,7 @@ dependencies {
implementation project(':core:mogo-core-function-call')
implementation project(':core:mogo-core-res')
implementation project(':libraries:mogo-adas')
compileOnly project(':libraries:mogo-map')
}
}

View File

@@ -4,12 +4,12 @@ import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_V2X_MODULE
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
import com.mogo.eagle.core.function.api.v2x.IV2XEventProvider
import com.mogo.eagle.core.function.v2x.events.V2XEventManager
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
@Route(path = PATH_V2X_MODULE)
class V2XProvider : IMoGoFunctionServerProvider {
class V2XProvider : IV2XEventProvider {
override val functionName: String
get() = "V2XProvider"
@@ -22,6 +22,10 @@ class V2XProvider : IMoGoFunctionServerProvider {
}
}
override fun queryWholeRoadEvents() {
V2XEventManager.queryWholeRoadEvents()
}
override fun onDestroy() {
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode) && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
//不处理

View File

@@ -1,91 +1,83 @@
package com.mogo.eagle.core.function.v2x.events
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.core.util.Pair
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.mogo.cloud.commons.utils.CoordinateUtils
import com.mogo.cloud.passport.IMoGoTokenCallback
import com.mogo.cloud.passport.MoGoAiCloudClient
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import android.content.*
import android.os.*
import android.util.*
import androidx.localbroadcastmanager.content.*
import com.mogo.cloud.passport.*
import com.mogo.commons.constants.HostConst
import com.mogo.commons.module.ServiceConst.CARD_TYPE_ROAD_CONDITION
import com.mogo.commons.network.ParamsUtil
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.enums.EventTypeHelper
import com.mogo.commons.network.*
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_CLOUD_V2N
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_CLOUD
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CLOUD_V2N
import com.mogo.eagle.core.data.enums.EventTypeEnum
import com.mogo.eagle.core.data.enums.EventTypeHelper
import com.mogo.eagle.core.data.enums.TrafficTypeEnum
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.data.enums.*
import com.mogo.eagle.core.data.map.*
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay
import com.mogo.eagle.core.data.map.entity.MarkerShowEntity
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.data.msgbox.DataSourceType
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.data.traffic.TrafficData
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.function.api.map.listener.IMoGoMapLocationListener
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager
import com.mogo.eagle.core.data.traffic.*
import com.mogo.eagle.core.function.api.hmi.warning.*
import com.mogo.eagle.core.function.api.map.listener.*
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.hmi.*
import com.mogo.eagle.core.function.call.map.*
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Default
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.TooClose
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.v2x.events.alarm.V2XAlarmServer
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi
import com.mogo.eagle.core.function.v2x.events.alarm.*
import com.mogo.eagle.core.function.v2x.events.bridge.*
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi.context
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst.BROADCAST_SCENE_EXTRA_KEY
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst.BROADCAST_SCENE_HANDLER_ACTION
import com.mogo.eagle.core.function.v2x.events.manager.V2XStatusManager
import com.mogo.eagle.core.function.v2x.events.observer.V2XOptimalRouteObserver
import com.mogo.eagle.core.function.v2x.events.receiver.SceneBroadcastReceiver
import com.mogo.eagle.core.function.v2x.events.scenario.impl.V2XScenarioManager
import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker
import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker.Marker
import com.mogo.eagle.core.function.v2x.events.consts.*
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst.*
import com.mogo.eagle.core.function.v2x.events.manager.*
import com.mogo.eagle.core.function.v2x.events.observer.*
import com.mogo.eagle.core.function.v2x.events.receiver.*
import com.mogo.eagle.core.function.v2x.events.scenario.impl.*
import com.mogo.eagle.core.function.v2x.events.utils.*
import com.mogo.eagle.core.function.v2x.events.utils.MapUtils
import com.mogo.eagle.core.function.v2x.events.utils.TrackUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.config.V2XConfig
import com.mogo.eagle.core.function.v2x.internal.data.V2XAdvanceWarning
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerCardResult
import com.mogo.eagle.core.function.v2x.internal.data.V2XOptimalRoute
import com.mogo.eagle.core.function.v2x.internal.data.V2XWarningTarget
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.road.V2XEventServiceApi
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.network.utils.*
import com.mogo.eagle.core.utilcode.mogo.logger.*
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_V2X
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.*
import com.mogo.eagle.core.utilcode.util.Utils
import com.mogo.map.marker.IMogoMarker
import com.mogo.map.marker.IMogoMarkerClickListener
import com.mogo.map.marker.*
import com.mogo.map.marker.MogoMarkersHandler.Companion.mogoMarkersHandler
import com.mogo.v2x.V2XManager
import com.mogo.v2x.callback.IV2XCallback
import com.mogo.v2x.config.V2XConfig
import com.mogo.v2x.data.*
import com.mogo.v2x.event.V2XEvent
import com.shuyu.gsyvideoplayer.GSYVideoManager
import com.shuyu.gsyvideoplayer.cache.CacheFactory
import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager
import com.shuyu.gsyvideoplayer.model.VideoOptionModel
import com.shuyu.gsyvideoplayer.player.IjkPlayerManager
import com.shuyu.gsyvideoplayer.player.PlayerFactory
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
import com.zhjt.service.chain.ChainLog
import com.zhjt.service.chain.TracingConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import roadwork.Road.RW_PB
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import com.shuyu.gsyvideoplayer.*
import com.shuyu.gsyvideoplayer.cache.*
import com.shuyu.gsyvideoplayer.model.*
import com.shuyu.gsyvideoplayer.player.*
import com.shuyu.gsyvideoplayer.utils.*
import com.zhjt.service.chain.*
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.*
import kotlinx.coroutines.android.*
import tv.danmaku.ijk.media.player.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*
object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallback{
object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallback {
private const val TAG = "V2XEventManager"
@@ -95,15 +87,19 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
private val hasInit by lazy { AtomicBoolean(false) }
// 记录历史行驶轨迹,用于车行驶方向计算,只保留两个数据
private val historyPath = arrayOfNulls<MogoLocation>(2)
var v2xEventDisposable: Disposable? = null
fun init(context: Context) {
BridgeApi.init(context)
if (hasInit.compareAndSet(false, true)) {
if (!V2XManager.hasInit()) {
AiRoadMarker.init(context)
V2XManager.init(V2XConfig.Builder().also {
it.aiCloudConfig(MoGoAiCloudClientConfig.getInstance())
it.context(context)
it.loggable(false)
it.loggable(true)
it.distanceForTriggerRefresh(200f) //行驶超过200包含刷新道路周边信息短链请求
it.durationForTriggerRefresh(
60,
@@ -114,11 +110,9 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
}.build())
V2XManager.start()
}
registerListener()
V2XManager.forceRefresh()
MoGoAiCloudClient.getInstance().addTokenCallbacks(this)
// 注册广播接收场景弹窗使用的
SceneBroadcastReceiver.register(context)
}
@@ -139,6 +133,7 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
private fun unRegisterListener() {
V2XManager.removeCallback(this)
CallerMapLocationListenerManager.removeListener(TAG, false)
mogoMarkersHandler.unregisterMarkerClickListener(CARD_TYPE_ROAD_CONDITION)
}
@@ -199,6 +194,18 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
return null
}
/**
* 刷新自车求助状态
*
* @param isTrue
*/
private fun refreshMeSeekHelp(isTrue: Boolean) {
val entity = V2XMessageEntity<Boolean>()
entity.type = V2XMessageEntity.V2XTypeEnum.ALERT_CAR_FOR_HELP
entity.content = isTrue
V2XScenarioManager.getInstance().handlerMessage(entity)
}
override fun onLocationChanged(location: MogoLocation?, from: Int, isGps: Boolean) {
location ?: return
BridgeApi.location.set(location)
@@ -239,13 +246,16 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
)
if (v2XRoadEventEntity != null) {
val distance = v2XRoadEventEntity.distance
val min = if (EventTypeEnum.AI_ROAD_WORK.poiType == v2XRoadEventEntity.poiType) 0 else 5
Logger.d(
TAG,
val min = if (EventTypeEnumNew.isCloudSocketEvent(v2XRoadEventEntity.poiType)) 0 else 5
CallerLogger.d(
"$M_V2X$TAG",
"--- trigger show before ---:data=>[${location.longitude}, ${location.latitude}, ${location.speed}], distance: $distance, minDistance: $min, poiType: ${v2XRoadEventEntity.poiType}"
)
if (distance >= min) {
Logger.d(TAG, "--- trigger show ---:poiType:" + v2XRoadEventEntity.poiType)
CallerLogger.d(
"$M_V2X$TAG",
"--- trigger show ---:poiType:" + v2XRoadEventEntity.poiType
)
TrackUtils.trackV2xRoadProduceEvent(1)
val v2XMessageEntity = V2XMessageEntity<V2XRoadEventEntity>()
v2XMessageEntity.type = V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING
@@ -294,55 +304,19 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
handleWarningTargetEvent(event.data)
}
is V2XEvent.RoadAI -> {
handleRoadMarkerEvent(event.data.toRoadMarker)
/*
TODO zhongchao 先注掉,编译通过
if(FunctionBuildConfig.isV2NFromCar){
return
}*/
handleRoadMarkerEvent(event.data.toRoadMarker())
}
is V2XEvent.RoadEventX -> {
handleRoadMarkerEvent(event.data.toRoadMarker())
}
}
}
private val RW_PB.toRoadMarker: V2XMarkerCardResult
get() = V2XMarkerCardResult().also { l1 ->
this.roadwork?.polygonList?.takeIf { it.isNotEmpty() }?.also { old ->
l1.extras = HashMap<String, List<Pair<Double, Double>>>().also { extra ->
extra["polygon"] = old.map { d ->
Pair(d.lon, d.lat)
}
extra["gps_location"] = listOf(
Pair(
this.roadwork?.center?.point?.lon ?: 0.0,
this.roadwork?.center?.point?.lat ?: 0.0
)
)
}
}
l1.exploreWay = ArrayList<V2XMarkerExploreWay>().also { l2 ->
l2.add(V2XMarkerExploreWay().also { l3 ->
l3.poiType = this.roadwork?.poiType?.toString()
l3.generateTime = this.roadwork?.detectTime ?: 0L
l3.location = V2XMarkerLocation().also { l4 ->
val p = CoordinateUtils.transformWgsToGcj(
this.roadwork?.center?.point?.lat ?: 0.0,
this.roadwork?.center?.point?.lon ?: 0.0
)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.roadwork?.center?.road?.bearing?.toDouble() ?: 0.0
}
})
}
AiRoadMarker.receive(
Marker(
this.roadwork?.center?.point?.lat ?: 0.0,
this.roadwork?.center?.point?.lon ?: 0.0,
this.roadwork?.center?.road?.bearing?.toDouble() ?: 0.0,
null,
null,
null
)
)
}
private fun handleWarningTargetEvent(data: V2XWarningTarget) {
val v2xMessageEntity = V2XMessageEntity<V2XWarningTarget>()
v2xMessageEntity.type = V2XMessageEntity.V2XTypeEnum.ALERT_THE_FRONT_WEAKNESS
@@ -403,32 +377,34 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
}
1003 -> {
// 交叉路口碰撞预警
/*
TODO xiaopeng 先注掉,编译通过
changeVisualAngle = true
tempAppId = EventTypeEnum.TYPE_USECASE_ID_ICW.poiType.toInt()
tempTts = EventTypeEnum.TYPE_USECASE_ID_ICW.tts
tempContent = EventTypeEnum.TYPE_USECASE_ID_ICW.content
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_ICW.poiType.toInt()
tempTts = EventTypeEnumNew.TYPE_USECASE_ID_ICW.tts
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_ICW.content*/
}
1004 -> {
// 交叉路口碰撞预警
changeVisualAngle = true
tempAppId = EventTypeEnum.TYPE_USECASE_ID_BSW.poiType.toInt()
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_BSW.poiType.toInt()
tempTts = String.format(
EventTypeEnum.TYPE_USECASE_ID_BSW.tts,
EventTypeEnumNew.TYPE_USECASE_ID_BSW.tts,
getWarningDirection()
)
tempContent = EventTypeEnum.TYPE_USECASE_ID_BSW.content
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_BSW.content
}
1006 -> {
// 逆向超车预警
tempAppId = EventTypeEnum.TYPE_USECASE_ID_DNPW.poiType.toInt()
tempTts = EventTypeEnum.TYPE_USECASE_ID_DNPW.tts
tempContent = EventTypeEnum.TYPE_USECASE_ID_DNPW.content
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_DNPW.poiType.toInt()
tempTts = EventTypeEnumNew.TYPE_USECASE_ID_DNPW.tts
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_DNPW.content
}
1005 -> {
// 闯红灯预警
tempAppId = EventTypeEnum.TYPE_USECASE_ID_IVP.poiType.toInt()
tempTts = EventTypeEnum.TYPE_USECASE_ID_IVP.tts
tempContent = EventTypeEnum.TYPE_USECASE_ID_IVP.content
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType.toInt()
tempTts = EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.tts
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.content
}
2001 -> {
// 最优车道100061
@@ -521,6 +497,63 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
}
}
fun queryWholeRoadEvents() {
if (v2xEventDisposable != null && !v2xEventDisposable!!.isDisposed) {
v2xEventDisposable!!.dispose()
}
val sn = MoGoAiCloudClientConfig.getInstance().sn
val lineId = getLineId()
if (lineId > 0) {
realQueryV2xEvents(lineId.toString(), sn)
} else {
UiThreadHandler.postDelayed({
realQueryV2xEvents(getLineId().toString(), sn)
}, 500)
}
}
private fun realQueryV2xEvents(lineId: String, sn: String) {
v2xEventDisposable = MoGoRetrofitFactory.getInstance(HostConst.getHost())
.create(V2XEventServiceApi::class.java)
.queryAllV2XEventsByLineId(lineId, sn)
.map {
if (it.code == 200 || it.code == 0) {
CallerLogger.d(M_V2X + TAG, "请求成功size为${it.result?.v2XEventList?.size}")
return@map it.result?.v2XEventList
} else {
CallerLogger.d(M_V2X + TAG, "请求失败code为${it.code}")
return@map ArrayList()
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
val size = it?.size ?: 0
if (size > 0) {
val msgBoxBean = MsgBoxBean(MsgBoxType.V2X, V2XMsg("", "查询到当前全程共${size}个事件", ""))
msgBoxBean.sourceType = DataSourceType.SUMMARY
CallerMsgBoxManager.saveMsgBox(msgBoxBean)
}
}
}
private fun getLineId(): Long {
var lineId: Long = -1
val parameter = CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo()
.autopilotControlParameters
if (parameter != null) {
if (parameter.autoPilotLine != null) {
lineId = parameter.autoPilotLine!!.lineId
CallerLogger.d(M_V2X + TAG, "lineId为:$lineId")
} else {
CallerLogger.d(M_V2X + TAG, "parameter.autoPilotLine为null")
}
} else {
CallerLogger.d(M_V2X + TAG, "parameter为null")
}
return lineId
}
override fun onFail(msg: String) {
CallerLogger.e("$M_V2X$TAG", "Error: $msg")
}
@@ -538,4 +571,5 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
}
}
}
}

View File

@@ -9,6 +9,7 @@ import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
import io.netty.util.internal.ConcurrentSet;
import android.util.Log;
/**
* @author donghongyu
@@ -33,6 +34,7 @@ public class V2XAlarmServer {
CopyOnWriteArrayList<V2XRoadEventEntity> v2XRoadEventEntityList,
MogoLocation currentLocation) {
try {
Log.d("RWJ", "getDriveFrontAlarmEvent --- 1 ---" + currentLocation );
if (!showedEvents.isEmpty()) {
Iterator<V2XRoadEventEntity> iterator = showedEvents.iterator();
while (iterator.hasNext()) {
@@ -49,15 +51,18 @@ public class V2XAlarmServer {
}
}
}
Log.d("RWJ", "getDriveFrontAlarmEvent --- 2 ---" + currentLocation);
if (currentLocation != null && v2XRoadEventEntityList != null) {
// 因为集合是按照距离排序后的所以这里检索出来第一个就发出警告
for (V2XRoadEventEntity v2XRoadEventEntity : v2XRoadEventEntityList) {
// 0、道路事件必须有朝向角度>=0;
Log.d("RWJ", "entity:" + v2XRoadEventEntity.getLocation());
if (v2XRoadEventEntity.getLocation().getAngle() >= 0) {
// 计算车辆距离指定气泡的距离
MarkerLocation eventLocation = v2XRoadEventEntity.getLocation();
// 1、判断是否到达了触发距离,20 ~ 500,
double distance = v2XRoadEventEntity.getDistance();
Log.d("RWJ", "distance:" + distance);
if (distance <= 500) {
if (EventTypeEnum.GHOST_PROBE.getPoiType().equals(v2XRoadEventEntity.getPoiType())) {
if (distance > 25) {
@@ -68,7 +73,8 @@ public class V2XAlarmServer {
double carBearing = currentLocation.getBearing();
double eventBearing = eventLocation.getAngle();
double diffAngle = DrivingDirectionUtils.getAngleDiff(carBearing, eventBearing);
if (diffAngle < 20) {
Log.d("RWJ", "car_bearing:" + carBearing + ",eventBearing:" + eventBearing + ",diffAngle:" + diffAngle);
if (diffAngle <= 20) {
// 3、计算当前车辆行驶方向与事件位置之间夹角《20度保证道路事件在车辆前方
double eventAngle = DrivingDirectionUtils.getDegreeOfCar2Poi(
currentLocation.getLongitude(),
@@ -77,10 +83,13 @@ public class V2XAlarmServer {
eventLocation.getLat(),
(int) currentLocation.getBearing()
);
Log.d("RWJ", "eventAngle:" + eventAngle);
if (0 <= eventAngle && eventAngle <= 20) {
if (showedEvents.contains(v2XRoadEventEntity)) {
return null;
}
Log.d("RWJ", "showed---");
showedEvents.add(v2XRoadEventEntity);
return v2XRoadEventEntity;
}
@@ -91,6 +100,7 @@ public class V2XAlarmServer {
}
} catch (Exception e) {
e.printStackTrace();
Log.w("RWJ", "error: " + e.getMessage());
}
return null;
}

View File

@@ -4,8 +4,9 @@ import android.content.Context;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.v2x.data.V2XMarkerCardResult;
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerCardResult;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -37,11 +38,11 @@ public interface IMoGoV2XMarkerManager extends IProvider {
/**
* 绘制正在预警的道路事件的POI点
*
* @param context
* @param context
* @param roadEventEntity
* @return
*/
void drawableAlarmPOI(Context context, V2XRoadEventEntity roadEventEntity, IMogoMarkerClickListener clickListener);
IMogoMarker drawableAlarmPOI(Context context, V2XRoadEventEntity roadEventEntity, IMogoMarkerClickListener clickListener);
/**
* 清除 道路事件 POI

View File

@@ -32,10 +32,10 @@ import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.map.marker.IMogoMarkerManager;
import com.mogo.map.marker.MogoMarkerOptions;
import com.mogo.eagle.core.data.enums.EventTypeEnum;
import com.mogo.v2x.V2XManager;
import com.mogo.v2x.data.V2XMarkerCardResult;
import com.mogo.v2x.data.V2XMarkerExploreWay;
import com.mogo.v2x.data.V2XMarkerLocation;
import com.mogo.eagle.core.function.v2x.internal.V2XManager;
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerCardResult;
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerExploreWay;
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerLocation;
import java.util.List;
import java.util.Objects;
@@ -55,8 +55,7 @@ public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
// 记录所有的:新鲜事儿的道路事件点、探路事件
private static final CopyOnWriteArraySet<V2XRoadEventEntity> mV2XRoadEventEntityArrayList = new CopyOnWriteArraySet<>();
// 上次的道路事件的预警Marker
private static IMogoMarker mAlarmInfoMarker;
@Override
public void drawableLastAllPOI() {
@@ -132,7 +131,7 @@ public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
}
@Override
public void drawableAlarmPOI(Context context, V2XRoadEventEntity roadEventEntity, IMogoMarkerClickListener clickListener) {
public IMogoMarker drawableAlarmPOI(Context context, V2XRoadEventEntity roadEventEntity, IMogoMarkerClickListener clickListener) {
try {
IMoGoV2XStatusManager v2xStatus = BridgeApi.INSTANCE.v2xStatus();
if (v2xStatus != null) {
@@ -147,7 +146,6 @@ public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
.latitude(roadEventEntity.getLocation().getLat())
.longitude(roadEventEntity.getLocation().getLon());
optionsRipple.anchor(0.5f, 0.5f);
MarkerShowEntity markerShowEntity = new MarkerShowEntity();
MarkerExploreWay markerExploreWay = roadEventEntity.getNoveltyInfo();
markerShowEntity.setBindObj(markerExploreWay);
@@ -155,22 +153,21 @@ public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
markerShowEntity.setTextContent(markerExploreWay.getAddr());
markerShowEntity.setMarkerLocation(markerExploreWay.getLocation());
markerShowEntity.setMarkerType(CARD_TYPE_NOVELTY);
optionsRipple.icons(V2XMarkerAdapter.getV2XRoadEventViewGif(context, roadEventEntity));
optionsRipple.period(1);
IMogoMarker ret = null;
if (MogoStatusManager.getInstance().isVrMode()) {
mAlarmInfoMarker = Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).drawMarker(markerShowEntity);
ret = Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).drawMarker(markerShowEntity);
} else {
optionsRipple.icon(V2XMarkerAdapter.getV2XRoadEventViewPng(context, roadEventEntity));
IMogoMarkerManager marker = CallerMapUIServiceManager.INSTANCE.getMarkerManager(context);
if (marker != null) {
mAlarmInfoMarker = marker.addMarker(V2X_EVENT_ALARM_POI, optionsRipple);
ret = marker.addMarker(V2X_EVENT_ALARM_POI, optionsRipple);
}
}
// 当前Marker设置为最上面
if (mAlarmInfoMarker != null) {
mAlarmInfoMarker.setToTop();
if (ret != null) {
ret.setToTop();
}
// 绘制连接线
IMoGoV2XPolylineManager polylineManager = BridgeApi.INSTANCE.v2xPolyline();
@@ -182,28 +179,30 @@ public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
new MogoLatLng(roadEventEntity.getLocation().getLat(),
roadEventEntity.getLocation().getLon()
), context);
return ret;
} else {
CallerLogger.INSTANCE.e(M_V2X + TAG, "Location 必须进行初始化!!!!!");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void clearAlarmPOI() {
boolean isRoadEventPOIShow = false;
IMoGoV2XStatusManager v2xStatus = BridgeApi.INSTANCE.v2xStatus();
if (v2xStatus != null) {
isRoadEventPOIShow = v2xStatus.isRoadEventPOIShow();
}
if (isRoadEventPOIShow) {
v2xStatus.setRoadEventPOIShow(TAG, false);
if (mAlarmInfoMarker != null) {
mAlarmInfoMarker.remove();
}
}
// boolean isRoadEventPOIShow = false;
// IMoGoV2XStatusManager v2xStatus = BridgeApi.INSTANCE.v2xStatus();
// if (v2xStatus != null) {
// isRoadEventPOIShow = v2xStatus.isRoadEventPOIShow();
// }
// if (isRoadEventPOIShow) {
// v2xStatus.setRoadEventPOIShow(TAG, false);
// if (mAlarmInfoMarker != null) {
// mAlarmInfoMarker.remove();
// }
// }
}
@Override
@@ -220,9 +219,9 @@ public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
@Override
public void forceClearAlarmPOI() {
if (mAlarmInfoMarker != null) {
mAlarmInfoMarker.remove();
}
// if (mAlarmInfoMarker != null) {
// mAlarmInfoMarker.remove();
// }
}
@Override

View File

@@ -0,0 +1,193 @@
package com.mogo.eagle.core.function.v2x.events.marker
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import com.mogo.cloud.commons.utils.CoordinateUtils
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager
import com.mogo.eagle.core.utilcode.util.*
import com.mogo.map.marker.IMogoMarker
import com.mogo.map.overlay.IMogoPolyline
import kotlinx.coroutines.Runnable
import java.util.LinkedList
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
data class MarkerWrapper(val id: String, val lon: Double, val lat: Double, val coordinateType: Int, var markers: ArrayList<IMogoMarker>? = null, var lines: ArrayList<IMogoPolyline>? = null) {
fun addLine(line: IMogoPolyline) {
var ll = this.lines
if (ll == null) {
ll = ArrayList()
this.lines = ll
}
ll.add(line)
}
fun addMarker(marker: IMogoMarker) {
var mm = this.markers
if (mm == null) {
mm = ArrayList()
this.markers = mm
}
mm.add(marker)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MarkerWrapper
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id.hashCode()
}
}
object MarkerManager {
private const val TAG = "MarkerManager"
private val showedMarkers by lazy { LinkedList<MarkerWrapper>() }
private val toRemoveMakers by lazy { LinkedList<MarkerWrapper>() }
private val isFirstAdd by lazy { AtomicBoolean(false) }
private val elapsedDistances by lazy { ConcurrentHashMap<MarkerWrapper, Double>() }
private val lastCarLocation by lazy { AtomicReference<MogoLocation>() }
private val lastGpsLocation by lazy { AtomicReference<MogoLocation>() }
private val checkTask = object : Runnable {
override fun run() {
try {
Log.d(TAG, "--- checkTask --- 1 ---")
if (lastCarLocation.get() == null) {
return
}
Log.d(TAG, "--- checkTask --- 2 ---")
if (lastGpsLocation.get() == null) {
return
}
Log.d(TAG, "--- checkTask --- 3 ---")
val toRemove = toRemoveMakers.iterator()
val carLoc = AtomicReference<MogoLocation>()
while (toRemove.hasNext()) {
val marker = toRemove.next()
if (carLoc.get() == null) {
carLoc.set(if (marker.coordinateType == 0) {
//高德坐标
CallerMapLocationListenerManager.getCurrentLocation()
} else {
CallerMapLocationListenerManager.getCurrentGpsLocation()
})
}
val currentLocation = carLoc.get()
val lastLocation = if (marker.coordinateType == 0) lastCarLocation.get() else lastGpsLocation.get()
if (currentLocation != null && lastLocation != null) {
val delta = CoordinateUtils.calculateLineDistance(currentLocation.longitude, currentLocation.latitude, lastLocation.longitude, lastLocation.latitude)
Log.d(TAG, "--- checkTask --- 4 ---:delta:$delta, id:${marker.id}")
var elapsed = elapsedDistances[marker]
if (elapsed == null) {
elapsed = delta.toDouble()
} else {
elapsed += delta
}
Log.d(TAG, "--- checkTask --- 5 ---:delta:$delta, elapsed:${elapsed}, id: ${marker.id}")
if (elapsed >= 200) {
var removeMarkerError = false
marker.markers?.forEach {
try {
Log.e(TAG, "--- checkTask --- remove marker: $it, id: ${marker.id}")
it.setVisible(false)
it.destroy()
} catch (t: Throwable) {
t.printStackTrace()
removeMarkerError = true
Log.e(TAG, "--- checkTask --- remove marker error:${t.message}, id: ${marker.id}")
}
}
var removeLineError = false
marker.lines?.forEach {
try {
it.isVisible = false
Log.e(TAG, "--- checkTask --- remove line : $it, id:${marker.id}")
it.destroy()
} catch (t: Throwable) {
t.printStackTrace()
removeLineError = true
Log.e(TAG, "--- checkTask --- remove line error:${t.message}, id: ${marker.id}")
}
}
if (!removeLineError && !removeMarkerError) {
toRemove.remove()
synchronized(elapsedDistances) {
elapsedDistances.remove(marker)
}
}
} else {
elapsedDistances[marker] = elapsed
}
}
}
val iterator = showedMarkers.iterator()
while (iterator.hasNext()) {
val marker = iterator.next()
if (carLoc.get() == null) {
carLoc.set(if (marker.coordinateType == 0) {
//高德坐标
CallerMapLocationListenerManager.getCurrentLocation()
} else {
CallerMapLocationListenerManager.getCurrentGpsLocation()
})
}
val location = carLoc.get()
if (location != null) {
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(location.longitude, location.latitude, marker.lon, marker.lat, location.bearing.toDouble())
if (angle >= 90) {
iterator.remove()
synchronized(toRemoveMakers) {
toRemoveMakers.offer(marker)
}
}
}
}
} catch (t: Throwable) {
t.printStackTrace()
} finally {
lastCarLocation.set(CallerMapLocationListenerManager.getCurrentLocation())
lastGpsLocation.set(CallerMapLocationListenerManager.getCurrentGpsLocation())
handler.postDelayed(this, 1000)
}
}
}
private val handler by lazy {
val thread = HandlerThread("check_marker_expired")
thread.start()
Handler(thread.looper)
}
fun addMarker(marker: MarkerWrapper) {
Log.d(TAG, "=== addMarker ====: $marker")
synchronized(showedMarkers) {
showedMarkers.offer(marker)
}
if (isFirstAdd.compareAndSet(false,true)) {
handler.postDelayed(checkTask, 1000)
}
}
}

View File

@@ -7,6 +7,8 @@ import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.function.v2x.events.scenario.IV2XScenario;
import com.mogo.eagle.core.function.v2x.events.scenario.view.IV2XMarker;
import java.util.concurrent.atomic.AtomicReference;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
@@ -17,7 +19,7 @@ import com.mogo.eagle.core.function.v2x.events.scenario.view.IV2XMarker;
public abstract class AbsV2XScenario<T> implements IV2XScenario {
protected String TAG = "AbsV2XScenario";
private IV2XMarker mV2XMarker;
private V2XMessageEntity<T> mV2XMessageEntity;
private final AtomicReference<V2XMessageEntity> mV2XMessageEntity = new AtomicReference<>();
protected AbsV2XScenario() {
}
@@ -26,14 +28,14 @@ public abstract class AbsV2XScenario<T> implements IV2XScenario {
@Override
public void close() {
clearPOI();
// clearPOI();
}
/**
* 释放资源
*/
public void release() {
mV2XMessageEntity = null;
mV2XMessageEntity.set(null);
mV2XMarker = null;
}
@@ -46,19 +48,19 @@ public abstract class AbsV2XScenario<T> implements IV2XScenario {
}
public void setV2XMessageEntity(@Nullable V2XMessageEntity<T> mV2XMessageEntity) {
this.mV2XMessageEntity = mV2XMessageEntity;
this.mV2XMessageEntity.set(mV2XMessageEntity);
}
public V2XMessageEntity<T> getV2XMessageEntity() {
return mV2XMessageEntity;
return mV2XMessageEntity.get();
}
@Override
public boolean isSameScenario(@Nullable V2XMessageEntity v2XMessageEntity) {
if (mV2XMessageEntity == null) {
V2XMessageEntity old = mV2XMessageEntity.get();
if (old == null) {
return false;
}
return mV2XMessageEntity.equals(v2XMessageEntity);
return old.equals(v2XMessageEntity);
}
}

View File

@@ -21,6 +21,8 @@ import com.mogo.eagle.core.utilcode.util.Utils;
import com.mogo.map.uicontroller.IMogoMapUIController;
import com.mogo.map.uicontroller.VisualAngleMode;
import java.util.concurrent.atomic.AtomicReference;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com

View File

@@ -1,53 +1,42 @@
package com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad
import android.animation.ArgbEvaluator
import android.content.Context
import android.graphics.Color
import android.os.Handler
import android.os.Looper
import android.view.animation.DecelerateInterpolator
import androidx.core.util.Pair
import androidx.lifecycle.Lifecycle.Event
import androidx.lifecycle.Lifecycle.Event.ON_CREATE
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.mogo.cloud.commons.utils.*
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.data.map.MapRoadInfo.StopLine
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationWGS84Listener
import com.mogo.eagle.core.function.api.v2x.OnClearAllMarker
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager.OnRoadListener
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.v2x.CallMarkersClearManager
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst.V2X_EVENT_ALARM_POI
import com.mogo.eagle.core.function.call.map.*
import com.mogo.eagle.core.function.v2x.events.scenario.scene.road.V2XAiRoadEventMarker
import com.mogo.eagle.core.utilcode.kotlin.lifeCycleOwner
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils
import com.mogo.map.MogoMap
import com.mogo.map.overlay.IMogoPolyline
import com.mogo.map.overlay.MogoPolylineOptions
import io.netty.util.internal.ConcurrentSet
import mogo.telematics.pad.MessagePad
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.ConcurrentHashMap
import com.mogo.eagle.core.function.v2x.events.marker.MarkerManager
import com.mogo.eagle.core.function.v2x.events.marker.MarkerWrapper
/**
* Ai云道路施工事件道路颜色标记类
*/
object AiRoadMarker {
class AiRoadMarker {
private const val TAG = "AiRoadMarker"
companion object {
@JvmField
val aiMakers = ConcurrentHashMap<String, AiRoadMarker>()
}
private val queue by lazy { LinkedBlockingQueue<Marker>() }
private val pool by lazy { Executors.newFixedThreadPool(2) }
private val TAG = "AiRoadMarker"
private val marker by lazy { AtomicReference<Marker>() }
@@ -59,54 +48,28 @@ object AiRoadMarker {
)
}
private val line by lazy { AtomicReference<IMogoPolyline>() }
private val START_COLOR = Color.parseColor("#002ABAD9")
private val END_COLOR = Color.parseColor("#66FF7A30")
private val roadMarker by lazy { V2XAiRoadEventMarker() }
private val line = AtomicReference<IMogoPolyline>()
private val handler by lazy {
Handler(Looper.getMainLooper())
}
private val checkExpiredTask = Runnable {
val poi = this.marker.get()
val car = this.carLocation.get()
val car = CallerMapLocationListenerManager.getCurrentGpsLocation()
if (poi != null && car != null) {
val distance = DrivingDirectionUtils.distance(
car.first,
car.second,
poi.poi_lon,
poi.poi_lat
) * 10000
val distance = CoordinateUtils.calculateLineDistance(car.longitude, car.latitude, poi.poi_lon, poi.poi_lat)
if (distance < 500) {
unMarker(poi)
}
}
}
private val onClearAllMarker = object : OnClearAllMarker {
override fun onClearAllMarkers() {
Logger.d(TAG, "--- onClearAllMarkers ----")
val marker = this@AiRoadMarker.marker.get()
if (marker != null) {
Logger.d(TAG, "--- onClearAllMarkers ----2")
unMarker(marker)
}
}
override fun onClearAllMarkers(tag: String) {
Logger.d(TAG, "--- onClearAllMarkers ----: tag: $tag")
val marker = this@AiRoadMarker.marker.get()
if (marker != null && tag == V2X_EVENT_ALARM_POI) {
Logger.d(TAG, "--- onClearAllMarkers ----: tag: -- 1: $tag")
unMarker(marker)
}
}
}
private val markers = ConcurrentSet<Marker>()
private val options by lazy {
MogoPolylineOptions().apply {
zIndex(40000f)
@@ -116,257 +79,83 @@ object AiRoadMarker {
}
}
fun init(ctx: Context) {
ctx.lifeCycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Event) {
if (event == ON_CREATE) {
onCreate()
}
if (event == ON_DESTROY) {
onDestroy()
}
}
})
pool.execute {
var interrupted = false
Logger.d(TAG, "--- consumer --- 0 ---")
while (!interrupted) {
try {
Logger.d(TAG, "--- consumer --- 1 ---")
val top = queue.take() ?: continue
Logger.d(TAG, "--- consumer --- 2 ---")
val location = carLocation.get()
if (location == null) {
if (queue.isEmpty()) {
synchronized(markers) {
markers.clear()
}
}
continue
}
val isTrigger = isTriggerEvent(
top.poi_lon,
top.poi_lat,
location.first,
location.second,
location.third
)
Logger.d(TAG, "--- consumer --- 3 ---: isTrigger => $isTrigger")
if (isTrigger) {
marker.set(top)
marker(top, true)
} else {
synchronized(markers) {
markers.remove(top)
}
}
interrupted = Thread.currentThread().isInterrupted
} catch (e: InterruptedException) {
e.printStackTrace()
break
}
}
fun marker(marker: Marker, drawMarker: Boolean, drawRoadLine: Boolean = false) {
val location = CallerMapLocationListenerManager.getCurrentGpsLocation() ?: return
this.marker.set(marker)
val wrapper = MarkerWrapper(marker.id, marker.poi_lon, marker.poi_lat, 1, null, null)
if (drawMarker) {
marker.entity?.apply { roadMarker.drawMarkers(this, wrapper) }
}
}
private fun isTriggerEvent(
x1: Double,
y1: Double,
x2: Double,
y2: Double,
a2: Double
): Boolean {
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(x2, y2, x1, y1, a2)
if (angle <= 60 && DrivingDirectionUtils.distance(x1, y1, x2, y2) <= 300) {
return true
}
return false
}
private val onRoadListener = object : OnRoadListener {
private var roadId = ""
private var hasCrossRoad = false
override fun onRoadIdInfo(roadId: String) {
Logger.d(TAG, "--- onRoadInfo --- roadId: $roadId")
val oldRoadId = this.roadId
if (oldRoadId != roadId) {
if (hasCrossRoad) {
hasCrossRoad = false
}
}
this.roadId = roadId
}
override fun onStopLineInfo(info: StopLine) {
Logger.d(TAG, "--- onStopLineInfo --- info: $info")
if (!hasCrossRoad) {
hasCrossRoad = true
}
}
}
private val onLocationListener = object : IMoGoChassisLocationWGS84Listener {
override fun onChassisLocationWGS84(gnssInfo: MessagePad.GnssInfo?) {
if (gnssInfo == null) {
if (drawRoadLine) {
//施工中心点前方的自车行驶方向上300米距离
val l1 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(marker.poi_lon, marker.poi_lat, location.bearing, 300f)
//施工中心点后方的自车行驶方向上300米距离
Logger.d(TAG, "--- marker --- 3 --- l1: $l1")
val l2 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(marker.poi_lon, marker.poi_lat, location.bearing, -300f)
if (l1.points.isEmpty() || l2.points.isEmpty()) {
Logger.d(TAG, "--- marker --- 3 --- return ----")
return
}
try {
val loc = arrayOf(gnssInfo.longitude, gnssInfo.latitude)
carLocation.set(Triple(loc[0], loc[1], gnssInfo.heading.toDouble()))
} catch (t: Throwable) {
Logger.e(TAG, "error: ${t.message}")
Logger.d(TAG, "--- marker --- 4 --- l2: $l2")
val points = LinkedList<MogoLatLng>()
if (l2 != null && l2.points.isNotEmpty()) {
points.addAll(l2.points.reversed().map {
MogoLatLng(it.second, it.first)
})
}
}
}
private fun onCreate() {
CallerMapRoadListenerManager.registerRoadListener(TAG, onRoadListener)
CallMarkersClearManager.addAllMarkersClearListener(TAG, onClearAllMarker)
CallerChassisLocationWGS84ListenerManager.addListener(TAG, onLocationListener)
}
private fun onDestroy() {
CallerMapRoadListenerManager.unRegisterRoadListener(TAG)
CallMarkersClearManager.removeAllMarkersClearListener(TAG)
CallerChassisLocationWGS84ListenerManager.removeListener(TAG)
pool.shutdownNow()
removeLine()
}
fun enqueue(marker: Marker) {
Logger.d(TAG, "--- enqueue --- 1 ---")
if (markers.contains(marker)) {
Logger.d(TAG, "--- enqueue --- cache hit ---")
return
}
Logger.d(TAG, "--- enqueue --- 2 ---")
synchronized(markers) {
markers += marker
}
pool.execute {
Logger.d(
TAG,
"--- enqueue --- 3 ---${Thread.currentThread().name}::${Thread.currentThread().id}"
)
queue.put(marker)
}
}
fun marker(marker: Marker, drawMarker: Boolean) {
handler.removeCallbacks(checkExpiredTask)
val location = carLocation.get() ?: return
if (markers.contains(marker)) {
Logger.d(TAG, "--- enqueue --- cache hit ---")
return
}
synchronized(markers) {
markers += marker
}
this.marker.set(marker)
//施工中心点前方的自车行驶方向上300米距离
val l1 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(
marker.poi_lon,
marker.poi_lat,
location.third.toFloat(),
300f
)
//施工中心点后方的自车行驶方向上300米距离
Logger.d(TAG, "--- marker --- 3 --- l1: $l1")
val l2 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(
marker.poi_lon,
marker.poi_lat,
location.third.toFloat(),
-300f
)
if (l1.points.isEmpty() || l2.points.isEmpty()) {
Logger.d(TAG, "--- marker --- 3 --- return ----")
synchronized(markers) {
markers.remove(marker)
}
return
}
Logger.d(TAG, "--- marker --- 4 --- l2: $l2")
val points = LinkedList<MogoLatLng>()
if (l2 != null && l2.points.isNotEmpty()) {
points.addAll(l2.points.reversed().map {
MogoLatLng(it.second, it.first)
})
}
val centerX = marker.poi_lon
val centerY = marker.poi_lat
Logger.d(TAG, "--- marker --- 5 --- marker: $marker")
val farthestPoint = marker.polygon?.let {
var find: Pair<Double, Double> = Pair(centerX, centerY)
var min = Long.MAX_VALUE
for (p in it) {
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(
centerX,
centerY,
p.first,
p.second,
location.third
)
if (angle < min) {
min = angle
find = p
val centerX= marker.poi_lon
val centerY = marker.poi_lat
Logger.d(TAG, "--- marker --- 5 --- marker: $marker")
val farthestPoint = marker.polygon?.let {
var find: Pair<Double, Double> = Pair(centerX, centerY)
var min = Long.MAX_VALUE
for (p in it) {
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(centerX, centerY, p.first, p.second, location.bearing.toDouble())
if (angle < min) {
min = angle
find = p
}
}
MogoLatLng(find.second, find.first)
} ?: MogoLatLng(centerY, centerX)
marker.farthestPoint = Pair(farthestPoint.lon, farthestPoint.lat)
Logger.d(TAG, "--- marker --- 6 --- marker: $marker")
if (l1 != null && l1.points.isNotEmpty()) {
for (l in l1.points) {
if (DrivingDirectionUtils.getDegreeOfCar2Poi2(farthestPoint.lon, farthestPoint.lat, l.first, l.second, (location.bearing + 180).toDouble()) < 90L) {
points.add(l.let { MogoLatLng(it.second, it.first) })
}
}
}
MogoLatLng(find.second, find.first)
} ?: MogoLatLng(centerY, centerX)
marker.farthestPoint = Pair(farthestPoint.lon, farthestPoint.lat)
Logger.d(TAG, "--- marker --- 6 --- marker: $marker")
if (l1 != null && l1.points.isNotEmpty()) {
for (l in l1.points) {
if (DrivingDirectionUtils.getDegreeOfCar2Poi2(
farthestPoint.lon,
farthestPoint.lat,
l.first,
l.second,
location.third + 180
) < 90L
) {
points.add(l.let { MogoLatLng(it.second, it.first) })
}
if (points.size <= 1) {
return
}
val evaluator = ArgbEvaluator()
val interceptor = DecelerateInterpolator(1.5f)
val total = points.size
val colors = ArrayList<Int>()
(0..total).forEach { i ->
colors += evaluator.evaluate(interceptor.getInterpolation(i * 1f / total), START_COLOR, END_COLOR) as Int
}
var line = line.get()
options.points(points)
options.colorValues(colors)
Logger.d(TAG, "--- marker --- 7 --- points: ${points.size}")
if (line == null || line.isDestroyed) {
val l = overlayManager?.addPolyline(options)
this.line.set(l)
line = l
} else {
line.setOption(options)
}
if (!line.isVisible) {
line.isVisible = true
}
if (line != null) {
wrapper.addLine(line)
}
}
if (points.size <= 1) {
synchronized(markers) {
markers.remove(marker)
}
return
}
removeLine()
if (drawMarker) {
marker.entity?.apply { V2XAiRoadEventMarker.drawMarkers(this) }
}
val evaluator = ArgbEvaluator()
val interceptor = DecelerateInterpolator(1.5f)
val total = points.size
val colors = ArrayList<Int>()
(0..total).forEach { i ->
colors += evaluator.evaluate(
interceptor.getInterpolation(i * 1f / total),
START_COLOR,
END_COLOR
) as Int
}
var line = line.get()
options.points(points)
options.colorValues(colors)
Logger.d(TAG, "--- marker --- 7 --- points: ${points.size}")
if (line == null || line.isDestroyed) {
val l = overlayManager?.addPolyline(options)
this.line.set(l)
line = l
} else {
line.setOption(options)
}
if (!line.isVisible) {
line.isVisible = true
}
MarkerManager.addMarker(wrapper)
}
private fun removeLine() {
@@ -380,30 +169,21 @@ object AiRoadMarker {
}
}
fun unMarker(marker: Marker) {
private fun unMarker(marker: Marker) {
Logger.d(TAG, "--- unMarker ---")
markers -= marker
this.marker.set(null)
removeLine()
V2XAiRoadEventMarker.removeMarkers(null)
roadMarker.removeMarkers()
handler.removeCallbacks(checkExpiredTask)
}
fun receive(marker: Marker) {
fun receive() {
Logger.d(TAG, "receive --- 1 ---")
val poi = this.marker.get()
val car = this.carLocation.get()
val car = CallerMapLocationListenerManager.getCurrentGpsLocation()
if (poi != null && car != null) {
val distance = DrivingDirectionUtils.distance(
car.first,
car.second,
marker.poi_lon,
marker.poi_lat
) * 10000
Logger.d(
TAG,
"receive --- 2 ---:car:[${car.first}, ${car.second}] -> poi:[${marker.poi_lon}, ${marker.poi_lat}] --> distance:$distance"
)
val distance = CoordinateUtils.calculateLineDistance(car.longitude, car.latitude, poi.poi_lon, poi.poi_lat)
Logger.d(TAG, "receive --- 2 ---:car:[${car.longitude}, ${car.latitude}] -> poi:[${poi.poi_lon}, ${poi.poi_lat}] --> distance:$distance")
if (distance < 500) {
checkExpired()
} else {
@@ -422,10 +202,12 @@ object AiRoadMarker {
}
data class Marker(
val id: String,
val poiType: String,
val poi_lat: Double,
val poi_lon: Double,
val poi_angle: Double,
val polygon: List<Pair<Double, Double>>?,
val polygon: List<Pair<Double, Double>>? = null,
var farthestPoint: Pair<Double, Double>? = null,
var entity: V2XRoadEventEntity? = null
) {
@@ -434,15 +216,12 @@ object AiRoadMarker {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Marker
if (poi_lat != other.poi_lat) return false
if (poi_lon != other.poi_lon) return false
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
var result = poi_lat.hashCode()
result = 31 * result + poi_lon.hashCode()
return result
return id.hashCode()
}
}
}

View File

@@ -1,127 +1,88 @@
package com.mogo.eagle.core.function.v2x.events.scenario.scene.road
import android.graphics.*
import android.util.*
import com.mogo.cloud.commons.utils.*
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.map.*
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.v2x.R
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi.context
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi.v2xMarker
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils
import com.mogo.eagle.core.function.v2x.events.marker.MarkerWrapper
import com.mogo.map.*
import com.mogo.map.marker.*
import com.mogo.map.overlay.*
import java.util.*
import java.util.concurrent.atomic.*
import kotlin.Pair
import kotlin.collections.ArrayList
object V2XAiRoadEventMarker {
class V2XAiRoadEventMarker {
private val current = AtomicReference<Pair<IMogoPolyline?, List<IMogoMarker>?>>()
private val v2xLocation = AtomicReference<MogoLocation>()
private val carLocation = AtomicReference<MogoLocation>()
private val overlayManager by lazy { MogoOverlayManager.getInstance() }
private val timer = Timer()
private val timerTask by lazy { AtomicReference<TimerTask>() }
private val distance = AtomicInteger(0)
private val overlayManager by lazy { CallerMapUIServiceManager.getOverlayManager(AbsMogoApplication.getApp()) }
fun drawMarkers(entity: V2XRoadEventEntity): Pair<IMogoPolyline?, List<IMogoMarker>?>? {
removeMarkers(current.get())
timerTask.get()?.cancel()
val extra = entity.noveltyInfo.extras.get("polygon");
if (extra is List<*>) {
val l = extra
if (l.size > 0) {
fun drawMarkers(entity: V2XRoadEventEntity, wrapper: MarkerWrapper) {
val extra = entity.noveltyInfo.extras["polygon"]
v2xMarker()?.drawableAlarmPOI(context(), entity, null)?.also {
wrapper.addMarker(it)
}
if (extra is List<*> && entity.poiType != EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.poiType) {
if (extra.size > 0) {
val polygons: MutableList<androidx.core.util.Pair<Double, Double>> = ArrayList()
for (i in l.indices) {
val o = l[i]!! as? androidx.core.util.Pair<*, *> ?: continue
val p = o
val first = p.first
val second = p.second
for (i in extra.indices) {
val o = extra[i]!! as? androidx.core.util.Pair<*, *> ?: continue
val first = o.first
val second = o.second
if (first == null || second == null) {
continue
}
if (first !is Double || second !is Double) {
continue
}
val xx = CoordinateUtils.transformWgsToGcj(second, first)
polygons.add(androidx.core.util.Pair.create(xx[0], xx[1]))
polygons.add(androidx.core.util.Pair.create(second, first))
}
if (polygons.size > 0) {
val markers = ArrayList<IMogoMarker>(polygons.size)
for (i in polygons.indices) {
val p = polygons[i]
val options = MogoMarkerOptions().data(entity).latitude(p.second).longitude(p.first)
options.anchor(0.5f, 0.5f)
options.icon3DRes(R.raw.sanjiaozhui)
try {
val marker = CallerMapUIServiceManager.getMarkerManager(AbsMogoApplication.getApp())?.addMarker("road_pyramid_" + entity.poiType, options)
marker?.let {
markers += it
}
} catch (t: Throwable) {
t.printStackTrace()
}
val l2 = entity.noveltyInfo?.location ?: return
v2xLocation.set(MogoLocation().also {
it.longitude = l2.lon; it.latitude = l2.lat; it.bearing = l2.angle.toFloat()
})
val options = MogoPolylineOptions()
val colors = ArrayList<Int>()
colors.add(Color.argb(204, 237, 172, 21))
colors.add(Color.argb(0, 255, 255, 255))
options.colorValues(colors)
val points = ArrayList<MogoLatLng>()
for (p in polygons) {
points.add(MogoLatLng(p.first, p.second))
}
if (markers.size > 0) {
v2xMarker()?.drawableAlarmPOI(context(), entity, null)
val l2 = entity.noveltyInfo?.location ?: return null
v2xLocation.set(MogoLocation().also { it.longitude = l2.lon; it.latitude = l2.lat; it.bearing = l2.angle.toFloat() })
val options = MogoPolylineOptions()
val colors = ArrayList<Int>()
colors.add(Color.argb(204, 237, 172, 21))
colors.add(Color.argb(0, 255, 255, 255))
options.colorValues(colors)
val points = ArrayList<MogoLatLng>()
for (p in polygons) {
points.add(MogoLatLng(p.second, p.first))
}
if (points.size > 2) {
points.add(points[0])
}
options.points(points)
options.useGradient(true)
options.useFacade(true)
options.setGps(false)
options.width(5f)
options.zIndex(75000f)
options.maxIndex(800000f)
val line = overlayManager?.addPolyline(options)
current.set(Pair(line, markers))
if (line != null) {
line.isVisible = true
}
if (points.size > 2) {
points.add(points[0])
}
options.points(points)
options.useGradient(true)
options.useFacade(true)
options.setGps(true)
options.width(5f)
options.zIndex(75000f)
options.maxIndex(800000f)
val line = overlayManager.addPolyline(options)
current.set(Pair(line, wrapper.markers))
if (line != null) {
line.isVisible = true
wrapper.addLine(line)
}
}
}
}
return current.get()
}
fun removeMarkers(pair: Pair<IMogoPolyline?, List<IMogoMarker>?>?) {
if (pair != null) {
realRemove(pair)
} else {
val prev = current.get()
if (prev != null) {
realRemove(prev)
val v2xMarker = v2xMarker()
v2xMarker?.also {
it.forceClearAlarmPOI()
}
}
fun removeMarkers() {
val prev = current.get()
if (prev != null) {
realRemove(prev)
}
}
@@ -137,40 +98,4 @@ object V2XAiRoadEventMarker {
}
}
}
fun onLocationChanged(location: MogoLocation) {
val markerLocation = v2xLocation.get()
carLocation.set(location)
if (markerLocation != null) {
if (isOutOfRange(markerLocation.longitude, markerLocation.latitude, location.longitude, location.latitude, location.bearing.toDouble())) {
v2xLocation.set(null)
this.distance.set(0)
timer.schedule(object : TimerTask() {
override fun run() {
val carLocation = this@V2XAiRoadEventMarker.carLocation.get()
Log.d("XXXXX", "timer do action ---: marker_lon: ${markerLocation.longitude}, marker_lat: ${markerLocation.latitude}, car_lon:${carLocation.longitude}, car_lat: ${carLocation.latitude}")
checkDistanceIsValid(markerLocation.longitude, markerLocation.latitude, carLocation)
}
}.also { this.timerTask.set(it) }, 1000, 1000)
}
}
}
private fun checkDistanceIsValid(x1: Double, y1: Double, location: MogoLocation) {
val distance = DrivingDirectionUtils.distance(x1, y1, location.longitude, location.latitude)
Log.d("XXXXX", "distance: $distance")
if (this.distance.addAndGet(distance.toInt()) >= 100) {
Log.d("XXXXX", "remove marker")
removeMarkers(null)
this.timerTask.get()?.cancel()
}
}
private fun isOutOfRange(markerLon: Double, markerLat: Double, carLon: Double, carLat: Double, carAngle: Double): Boolean {
return !isFrontOfCar(markerLon, markerLat, carLon, carLat, carAngle)
}
private fun isFrontOfCar(markerLon: Double, markerLat: Double, carLon: Double, carLat: Double, carAngle: Double): Boolean {
val degree = DrivingDirectionUtils.getDegreeOfCar2Poi2(carLon, carLat, markerLon, markerLat, carAngle)
return degree < 90
}
}

View File

@@ -1,16 +1,20 @@
package com.mogo.eagle.core.function.v2x.events.scenario.scene.road;
import android.util.Log;
import androidx.core.util.Pair;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi;
import com.mogo.eagle.core.function.v2x.events.manager.IMoGoV2XMarkerManager;
import com.mogo.eagle.core.function.v2x.events.manager.IMoGoV2XPolylineManager;
import com.mogo.eagle.core.function.v2x.events.marker.MarkerWrapper;
import com.mogo.eagle.core.function.v2x.events.marker.MarkerManager;
import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker;
import com.mogo.eagle.core.function.v2x.events.scenario.view.IV2XMarker;
import com.mogo.eagle.core.data.enums.EventTypeEnum;
import com.mogo.map.marker.IMogoMarker;
import java.util.ArrayList;
import java.util.List;
@@ -22,30 +26,31 @@ import java.util.Objects;
public class V2XRoadEventMarker implements IV2XMarker<V2XRoadEventEntity> {
private static AiRoadMarker.Marker mMarker;
@Override
public void drawPOI(V2XRoadEventEntity entity) {
try {
// 清除道路事件
IMoGoV2XMarkerManager marker = BridgeApi.INSTANCE.v2xMarker();
if (marker != null) {
marker.clearAlarmPOI();
if (entity != null) {
if (!Objects.equals(entity.getPoiType(), EventTypeEnum.AI_ROAD_WORK.getPoiType())) {
AiRoadMarker.Marker prev = mMarker;
if (prev != null) {
AiRoadMarker.INSTANCE.unMarker(prev);
mMarker = null;
Log.d("RWJ", "V2XRoadEventMarker:" + entity.getPoiType());
if (!Objects.equals(entity.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType())
&& !Objects.equals(entity.getPoiType(), EventTypeEnumNew.FOURS_ACCIDENT_04.getPoiType())
&& !Objects.equals(entity.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.getPoiType())
&& !Objects.equals(entity.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGU.getPoiType())) {
IMogoMarker iMarker = marker.drawableAlarmPOI(BridgeApi.INSTANCE.context(), entity, null);
if (iMarker != null) {
Log.d("RWJ", "V2XRoadEventMarker:" + entity.getPoiType() + "--- add Marker");
ArrayList<IMogoMarker> markers = new ArrayList<>();
markers.add(iMarker);
String id = entity.getLocation().getLon() + "_" + entity.getLocation().getLat();
MarkerManager.INSTANCE.addMarker(new MarkerWrapper(id, entity.getLocation().getLon(), entity.getLocation().getLat(), 0, markers, null));
} else {
Log.d("RWJ", "V2XRoadEventMarker:" + entity.getPoiType() + "--- return empty marker");
}
marker.drawableAlarmPOI(BridgeApi.INSTANCE.context(), entity, null);
} else {
AiRoadMarker.Marker prev = mMarker;
if (prev != null) {
AiRoadMarker.INSTANCE.unMarker(prev);
mMarker = null;
}
MarkerExploreWay noveltyInfo = entity.getNoveltyInfo();
Log.d("RWJ", "V2XRoadEventMarker -> noveltyInfo:" + noveltyInfo);
if (noveltyInfo != null && noveltyInfo.extras != null) {
List<Pair<Double, Double>> polygons = new ArrayList<>();
Pair<Double, Double> gpsLocation = null;
@@ -77,14 +82,13 @@ public class V2XRoadEventMarker implements IV2XMarker<V2XRoadEventEntity> {
if (noveltyInfo.extras.containsKey("gps_location")) {
gpsLocation = (Pair<Double, Double>) ((List)(noveltyInfo.extras.get("gps_location"))).get(0);
}
if (!polygons.isEmpty() && gpsLocation != null) {
MarkerLocation location = noveltyInfo.getLocation();
AiRoadMarker.Marker m = new AiRoadMarker.Marker(gpsLocation.second, gpsLocation.first, location.getAngle(), polygons, null, entity);
mMarker = m;
AiRoadMarker.INSTANCE.marker(m, true);
AiRoadMarker.Marker m = new AiRoadMarker.Marker(noveltyInfo.getInfoId(), noveltyInfo.getPoiType(), gpsLocation.second, gpsLocation.first, location.getAngle(), polygons, null, entity);
AiRoadMarker aiMarker = new AiRoadMarker();
aiMarker.marker(m, true, isDrawRoadLine(m.getPoiType()));
AiRoadMarker.aiMakers.put(noveltyInfo.getInfoId(), aiMarker);
}
}
}
}
@@ -94,19 +98,23 @@ public class V2XRoadEventMarker implements IV2XMarker<V2XRoadEventEntity> {
}
}
private boolean isDrawRoadLine(String poiType) {
return EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType().equals(poiType);
}
@Override
public void clearPOI() {
// 移除线
IMoGoV2XPolylineManager polyLineManager = BridgeApi.INSTANCE.v2xPolyline();
if (polyLineManager != null) {
polyLineManager.clearLine();
}
IMoGoV2XMarkerManager v2xMarker = BridgeApi.INSTANCE.v2xMarker();
if (v2xMarker != null) {
// 移除事件POI
v2xMarker.clearAlarmPOI();
// 绘制上次的数据
v2xMarker.drawableLastAllPOI();
}
// IMoGoV2XPolylineManager polyLineManager = BridgeApi.INSTANCE.v2xPolyline();
// if (polyLineManager != null) {
// polyLineManager.clearLine();
// }
// IMoGoV2XMarkerManager v2xMarker = BridgeApi.INSTANCE.v2xMarker();
// if (v2xMarker != null) {
// // 移除事件POI
// v2xMarker.clearAlarmPOI();
// // 绘制上次的数据
// v2xMarker.drawableLastAllPOI();
// }
}
}

View File

@@ -1,12 +1,16 @@
package com.mogo.eagle.core.function.v2x.events.scenario.scene.road;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import android.util.Log;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.commons.analytics.AnalyticsUtils;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.enums.WarningDirectionEnum;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.data.msgbox.MsgBoxBean;
@@ -14,6 +18,7 @@ import com.mogo.eagle.core.data.msgbox.MsgBoxType;
import com.mogo.eagle.core.data.msgbox.V2XMsg;
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener;
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager;
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager;
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager;
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst;
@@ -21,13 +26,13 @@ import com.mogo.eagle.core.function.v2x.events.manager.V2XStatusManager;
import com.mogo.eagle.core.function.v2x.events.scenario.impl.AbsV2XScenario;
import com.mogo.eagle.core.function.v2x.events.scenario.view.IV2XMarker;
import com.mogo.eagle.core.network.utils.GsonUtil;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.data.enums.EventTypeEnum;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
@@ -45,7 +50,7 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
@Override
public void init(V2XMessageEntity<V2XRoadEventEntity> v2XMessageEntity) {
try {
CallerLogger.INSTANCE.d(M_V2X + TAG, "v2XMessageEntity:" + GsonUtil.jsonFromObject(v2XMessageEntity));
Log.d(TAG, "v2XMessageEntity:" + GsonUtil.jsonFromObject(v2XMessageEntity));
V2XRoadEventEntity v2XRoadEventEntity = v2XMessageEntity.getContent();
if (v2XRoadEventEntity != null) {
if (v2XMessageEntity.isShowState()) {
@@ -71,16 +76,23 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
try {
if (getV2XMessageEntity() != null && getV2XMessageEntity().getContent() != null) {
//只展示不播报 不广播
boolean onlyShow = getV2XMessageEntity().isOnlyShow();
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
boolean onlyShow = entity.isOnlyShow();
if (!onlyShow) {
// 设置TTS
getV2XMessageEntity().getContent().getTts(false);
V2XRoadEventEntity content = entity.getContent();
if (content != null && !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType())
&& !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.getPoiType())
&& !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGU.getPoiType())
&& !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_CONGESTION.getPoiType())) {
content.getTts(false);
}
}
showWindow();
String poiType = getV2XMessageEntity().getContent().getPoiType();
String lat = String.valueOf(getV2XMessageEntity().getContent().getLocation().getLat());
String lon = String.valueOf(getV2XMessageEntity().getContent().getLocation().getLon());
String infoId = getV2XMessageEntity().getContent().getNoveltyInfo().getInfoId();
String poiType = entity.getContent().getPoiType();
String lat = String.valueOf(entity.getContent().getLocation().getLat());
String lon = String.valueOf(entity.getContent().getLocation().getLon());
String infoId = entity.getContent().getNoveltyInfo().getInfoId();
String style = "1";
Map<String, Object> properties = new HashMap<>();
properties.put("dbid", infoId);
@@ -100,20 +112,39 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
V2XRoadEventEntity content = entity != null ? entity.getContent() : null;
if (content != null) {
// //显示警告红边
if (content.getAlarmContent() == null || content.getAlarmContent().isEmpty()
|| content.getTts() == null || content.getTts().isEmpty()) {
String alarmText = content.getAlarmContent();
String ttsText = content.getTts();
if (alarmText == null || alarmText.isEmpty()
|| ttsText == null || ttsText.isEmpty()) {
Log.d("MsgBox-V2XRoadScenario", "alertContent或ttsContent为空!");
}
String poiType = content.getPoiType();
if (EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType().equals(poiType) ||
EventTypeEnumNew. TYPE_SOCKET_ROAD_JINGZHI.getPoiType().equals(poiType) ||
EventTypeEnumNew.TYPE_SOCKET_ROAD_CONGESTION.getPoiType().equals(poiType) ||
EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGU.getPoiType().equals(poiType)) {
MogoLocation carLocation = CallerMapLocationListenerManager.INSTANCE.getCurrentLocation();
MarkerExploreWay noveltyInfo = content.getNoveltyInfo();
if (carLocation != null && noveltyInfo != null) {
MarkerLocation eventLocation = noveltyInfo.getLocation();
if (eventLocation != null) {
double distance = content.getDistance();
alarmText = String.format(alarmText, Math.round(distance) + "");
ttsText = String.format(ttsText, Math.round(distance) + "");
}
}
}
CallerMsgBoxManager.INSTANCE.saveMsgBox(
new MsgBoxBean(
MsgBoxType.V2X,
new V2XMsg(content.getPoiType(),
content.getAlarmContent(),
content.getTts())
new V2XMsg(poiType,
alarmText,
ttsText)
)
);
CallerHmiManager.INSTANCE.warningV2X(content.getPoiType(), content.getAlarmContent(),
content.getTts(), TAG, this, !entity.isOnlyShow(),
CallerHmiManager.INSTANCE.warningV2X(poiType, alarmText,
ttsText, TAG, this, !entity.isOnlyShow(),
TimeUnit.SECONDS.toMillis(5));
}
}
@@ -130,10 +161,10 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
@Override
public void clearPOI() {
IV2XMarker marker = getV2XMarker();
if (marker != null) {
marker.clearPOI();
}
// IV2XMarker marker = getV2XMarker();
// if (marker != null) {
// marker.clearPOI();
// }
}
@Override
@@ -144,13 +175,14 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
CallerHmiManager.INSTANCE.showWarning(WarningDirectionEnum.ALERT_WARNING_TOP, TimeUnit.HOURS.toMillis(1));
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
if (entity != null) {
if (entity.isNeedAddLine()) {
drawPOI();
}
V2XRoadEventEntity content = entity.getContent();
if (content != null) {
if (entity.isNeedAddLine() && !EventTypeEnumNew.TYPE_SOCKET_ROAD_CONGESTION.getPoiType().equals(content.getPoiType()) ) {
drawPOI();
}
MarkerExploreWay noveltyInfo = content.getNoveltyInfo();
if (noveltyInfo != null && EventTypeEnum.FOURS_FOG.getPoiType().equals(content.getNoveltyInfo().getPoiType())) {
if (noveltyInfo != null && EventTypeEnumNew.FOURS_FOG.getPoiType().equals(content.getNoveltyInfo().getPoiType())) {
CallerHmiManager.INSTANCE.displayEffects();
}
}
@@ -163,7 +195,7 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
if (content == null) {
return true;
}
return !EventTypeEnum.GHOST_PROBE.getPoiType().equals(content.getPoiType());
return !EventTypeEnumNew.GHOST_PROBE.getPoiType().equals(content.getPoiType());
}
@Override
@@ -172,7 +204,6 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
if (isNeedChangeAngle()) {
CallerVisualAngleManager.INSTANCE.changeVisualAngle(new CallerVisualAngleManager.Scene.Default(3, TimeUnit.SECONDS));
}
clearPOI();
release();
}
}

View File

@@ -39,13 +39,13 @@ public class V2XOptimalRouteVREventMarker implements IV2XMarker<V2XOptimalRouteD
@Override
public void clearPOI() {
// 移除线
clearLine();
// 绘制上次的数据
IMoGoV2XMarkerManager v2xMarker = BridgeApi.INSTANCE.v2xMarker();
if (v2xMarker != null) {
v2xMarker.drawableLastAllPOI();
}
// // 移除线
// clearLine();
// // 绘制上次的数据
// IMoGoV2XMarkerManager v2xMarker = BridgeApi.INSTANCE.v2xMarker();
// if (v2xMarker != null) {
// v2xMarker.drawableLastAllPOI();
// }
}
public void clearLine() {

View File

@@ -86,13 +86,13 @@ public class V2XOptimalRouteVREventScenario
@Override
public void clearPOI() {
if (getV2XMarker() != null) {
getV2XMarker().clearPOI();
}
IMoGoV2XStatusManager v2xStatus = BridgeApi.INSTANCE.v2xStatus();
if (v2xStatus != null) {
v2xStatus.setPushPOIShow(TAG, false);
}
// if (getV2XMarker() != null) {
// getV2XMarker().clearPOI();
// }
// IMoGoV2XStatusManager v2xStatus = BridgeApi.INSTANCE.v2xStatus();
// if (v2xStatus != null) {
// v2xStatus.setPushPOIShow(TAG, false);
// }
}
@Override
@@ -102,6 +102,5 @@ public class V2XOptimalRouteVREventScenario
@Override
public void onDismiss() {
clearPOI();
}
}

View File

@@ -22,8 +22,7 @@ import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager;
import com.mogo.eagle.core.function.v2x.events.scenario.impl.AbsV2XScenario;
import com.mogo.eagle.core.function.v2x.events.scenario.view.IV2XMarker;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.v2x.data.V2XWarningTarget;
import com.mogo.eagle.core.function.v2x.internal.data.V2XWarningTarget;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
@@ -43,7 +42,7 @@ public class V2XFrontWarningScenario extends AbsV2XScenario implements IMoGoChas
private WarningDirectionEnum mDirection;
public V2XFrontWarningScenario() {
setV2XMarker(sV2XWarningMarker);
//setV2XMarker(sV2XWarningMarker);
}
@Override
@@ -166,6 +165,6 @@ public class V2XFrontWarningScenario extends AbsV2XScenario implements IMoGoChas
if (mDirection != null) {
CallerHmiManager.INSTANCE.dismissWarning(mDirection);
}
clearPOI();
// clearPOI();
}
}

View File

@@ -24,8 +24,8 @@ import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.map.marker.IMogoMarkerManager;
import com.mogo.map.overlay.IMogoPolyline;
import com.mogo.commons.utils.Trigonometric;
import com.mogo.v2x.data.V2XLocation;
import com.mogo.v2x.data.V2XWarningTarget;
import com.mogo.eagle.core.function.v2x.internal.data.V2XLocation;
import com.mogo.eagle.core.function.v2x.internal.data.V2XWarningTarget;
import java.util.ArrayList;
import java.util.Arrays;

View File

@@ -1,55 +1,167 @@
package com.mogo.eagle.core.function.v2x.events.utils
import androidx.core.util.Pair
import com.mogo.eagle.core.data.enums.EventTypeEnumNew.Companion.isRoadEvent
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay
import com.mogo.eagle.core.data.map.entity.MarkerLocation
import com.mogo.eagle.core.data.map.entity.MarkerUserInfo
import com.mogo.v2x.data.MarkerExploreWayItem
import com.mogo.v2x.data.V2XMarkerExploreWay
import com.mogo.v2x.data.V2XMarkerLocation
import com.mogo.v2x.data.V2XMarkerUserInfo
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker
import com.mogo.eagle.core.function.v2x.internal.data.*
import com.mogo.eagle.core.utilcode.util.CoordinateTransform
import mogo.telematics.pad.MessagePad
import roadwork.Road
fun V2XMarkerLocation?.toMarkerLocation(): MarkerLocation? = if (this == null) null else MarkerLocation().also {
it.lon = this.lon
it.lat = this.lat
it.address = this.address
it.angle = this.angle
}
fun V2XMarkerLocation?.toMarkerLocation(): MarkerLocation? =
if (this == null) null else MarkerLocation().also {
it.lon = this.lon
it.lat = this.lat
it.address = this.address
it.angle = this.angle
}
fun MarkerExploreWayItem?.toMarkerExploreWayItem(): com.mogo.eagle.core.data.map.entity.MarkerExploreWayItem? = if (this == null) null else com.mogo.eagle.core.data.map.entity.MarkerExploreWayItem().also {
it.illegalCount = this.illegalCount
it.content = this.content
it.url = this.url
it.thumbnail = this.thumbnail
}
fun MarkerExploreWayItem?.toMarkerExploreWayItem(): com.mogo.eagle.core.data.map.entity.MarkerExploreWayItem? =
if (this == null) null else com.mogo.eagle.core.data.map.entity.MarkerExploreWayItem().also {
it.illegalCount = this.illegalCount
it.content = this.content
it.url = this.url
it.thumbnail = this.thumbnail
}
fun V2XMarkerUserInfo?.toMarkerUserInfo(): MarkerUserInfo? = if (this == null) null else MarkerUserInfo().also {
it.safeLabelType = this.safeLabelType
it.safeLabel = this.safeLabel
it.lastActiveweekAvgscore = this.lastActiveweekAvgscore
it.gender = this.gender
it.userHead = this.userHead
it.userName = this.userName
it.setAge(this.age)
}
fun V2XMarkerUserInfo?.toMarkerUserInfo(): MarkerUserInfo? =
if (this == null) null else MarkerUserInfo().also {
it.safeLabelType = this.safeLabelType
it.safeLabel = this.safeLabel
it.lastActiveweekAvgscore = this.lastActiveweekAvgscore
it.gender = this.gender
it.userHead = this.userHead
it.userName = this.userName
it.setAge(this.age)
}
fun V2XMarkerExploreWay.toMarkExploreWay(extras: Map<String, Any>? = null): MarkerExploreWay = MarkerExploreWay().also {
it.items = this.items?.map { itx -> itx.toMarkerExploreWayItem() }
it.userInfo = this.userInfo?.toMarkerUserInfo()
it.distance = this.distance
it.cityName = this.cityName
it.setGenerateTime(this.generateTime)
it.infoId = this.infoId
it.setFileType(this.fileType)
it.setDirection(this.direction)
it.location = this.location?.toMarkerLocation()
it.sn = this.sn
it.canLive = this.canLive != "0"
it.poiType = this.poiType
it.type = this.type
it.infoCheckNode = this.infoCheckNode
it.isFabulous = this.isFabulous
it.uploadType = this.uploadType
it.isCanLive = this.canLive != "0"
it.extras = extras
}
fun V2XMarkerExploreWay.toMarkExploreWay(extras: Map<String, Any>? = null): MarkerExploreWay =
MarkerExploreWay().also {
it.items = this.items?.map { itx -> itx.toMarkerExploreWayItem() }
it.userInfo = this.userInfo?.toMarkerUserInfo()
it.distance = this.distance
it.cityName = this.cityName
it.setGenerateTime(this.generateTime)
it.infoId = this.infoId
it.setFileType(this.fileType)
it.setDirection(this.direction)
it.location = this.location?.toMarkerLocation()
it.sn = this.sn
it.canLive = this.canLive != "0"
it.poiType = this.poiType
it.type = this.type
it.infoCheckNode = this.infoCheckNode
it.isFabulous = this.isFabulous
it.uploadType = this.uploadType
it.isCanLive = this.canLive != "0"
it.extras = extras
}
fun Road.RW_PB.toRoadMarker(): V2XMarkerCardResult =
V2XMarkerCardResult().also { l1 ->
this.roadwork?.polygonList?.takeIf { it.isNotEmpty() }?.also { old ->
l1.extras = HashMap<String, List<Pair<Double, Double>>>().also { extra ->
extra["polygon"] = old.map { d ->
Pair(d.lon, d.lat)
}
extra["gps_location"] = listOf(
Pair(
this.roadwork?.center?.point?.lon ?: 0.0,
this.roadwork?.center?.point?.lat ?: 0.0
)
)
}
}
val centerX = this.roadwork?.center?.point?.lon ?: 0.0
val centerY = this.roadwork?.center?.point?.lat ?: 0.0
val id = "${centerX}_${centerY}"
l1.exploreWay = ArrayList<V2XMarkerExploreWay>().also { l2 ->
l2.add(V2XMarkerExploreWay().also { l3 ->
l3.poiType = this.roadwork?.poiType?.toString()
l3.generateTime = this.roadwork?.detectTime ?: 0L
l3.location = V2XMarkerLocation().also { l4 ->
val p = CoordinateTransform.WGS84ToGCJ02(this.roadwork?.center?.point?.lon ?: 0.0, this.roadwork?.center?.point?.lat ?: 0.0)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.roadwork?.center?.road?.bearing?.toDouble() ?: 0.0
}
l3.infoId = id
})
}
AiRoadMarker.aiMakers[id]?.receive()
}
fun V2XRoadXData.toRoadMarker(): V2XMarkerCardResult =
V2XMarkerCardResult().also { l1 ->
this.polygon?.takeIf { it.isNotEmpty() }?.also { old ->
l1.extras = HashMap<String, List<Pair<Double, Double>>>().also { extra ->
extra["polygon"] = old.map { d ->
Pair(d.lon, d.lat)
}
extra["gps_location"] = listOf(Pair(this.center?.lon ?: 0.0, this.center?.lat ?: 0.0))
}
}
l1.exploreWay = ArrayList<V2XMarkerExploreWay>().also { l2 ->
l2.add(V2XMarkerExploreWay().also { l3 ->
l3.poiType = this.poiType
l3.generateTime = this.detectTime ?: 0L
l3.location = V2XMarkerLocation().also { l4 ->
val p = CoordinateTransform.WGS84ToGCJ02(this.center?.lon ?: 0.0, this.center?.lat ?: 0.0)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.centerRoad?.bearing ?: 0.0
}
l3.infoId = this.index
})
}
AiRoadMarker.aiMakers[this.index]?.receive()
}
fun MessagePad.TrackedObject.toRoadMarker(poiType: String): V2XMarkerCardResult =
V2XMarkerCardResult().also { l1 ->
this.polygonList?.takeIf { it.isNotEmpty() }?.also { old ->
l1.extras = HashMap<String, List<Pair<Double, Double>>>().also { extra ->
extra["polygon"] = old.map { d -> Pair(d.longitude, d.latitude) }
extra["gps_location"] = listOf(Pair(this.longitude, this.latitude))
}
}
val id = "${this.longitude}_${this.latitude}"
l1.exploreWay = ArrayList<V2XMarkerExploreWay>().also { l2 ->
l2.add(V2XMarkerExploreWay().also { l3 ->
l3.poiType = poiType
l3.generateTime = 0L
l3.location = V2XMarkerLocation().also { l4 ->
val p = CoordinateTransform.WGS84ToGCJ02(this.longitude, this.latitude)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.heading
}
l3.infoId = id
})
}
AiRoadMarker.aiMakers[id]?.receive()
}
fun V2XMarkerCardResult.toV2XRoadEventEntity(): V2XRoadEventEntity =
V2XRoadEventEntity().also { l1 ->
val exploreWayList: List<V2XMarkerExploreWay>? = this.exploreWay
if (!exploreWayList.isNullOrEmpty() && exploreWayList.isNotEmpty()) {
for (markerExploreWay in exploreWayList) {
if (isRoadEvent(markerExploreWay.poiType)) {
val markerLocation = markerExploreWay.location
l1.location = markerLocation.toMarkerLocation()
l1.poiType = markerExploreWay.poiType
l1.noveltyInfo = markerExploreWay.toMarkExploreWay(this.extras)
l1.expireTime = 20000
}
}
}
}

View File

@@ -0,0 +1,257 @@
package com.mogo.eagle.core.function.v2x.internal
import android.os.Handler
import android.os.Looper
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.cloud.socket.SocketManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.config.V2XConfig
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerResponse
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.internal.http.V2XRefreshModel
import com.mogo.eagle.core.function.v2x.internal.http.callback.IV2XRefreshCallback
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
import com.mogo.eagle.core.function.v2x.internal.socket.*
import com.mogo.eagle.core.function.v2x.internal.socket.V2XMessageListener_401012
import com.mogo.eagle.core.function.v2x.internal.socket.V2XMessageListener_401018
import com.mogo.eagle.core.function.v2x.internal.socket.V2XMessageListener_402000
import com.mogo.eagle.core.function.v2x.internal.socket.V2XMessageListener_404000
import com.mogo.eagle.core.function.v2x.internal.utils.DistanceUtils
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
object V2XManager {
internal const val TAG = "V2XManager"
private val config: AtomicReference<V2XConfig> by lazy {
AtomicReference<V2XConfig>(null)
}
private val cbs by lazy {
CopyOnWriteArrayList<IV2XCallback>()
}
private val lastLongitude by lazy {
AtomicReference(0.0)
}
private val lastLatitude by lazy {
AtomicReference(0.0)
}
private val realLongitude by lazy { AtomicReference(0.0) }
private val realLatitude by lazy { AtomicReference(0.0) }
/**
* 标识此参数是否启动
*/
private val started by lazy {
AtomicBoolean(false)
}
private val refreshCallback = object : IV2XRefreshCallback<V2XMarkerResponse> {
override fun onSuccess(result: V2XMarkerResponse) {
cbs.forEach {
it.onAck(V2XEvent.Marker(result))
}
}
override fun onFail(msg: String?) {
cbs.forEach {
it.onFail(msg ?: "")
}
}
}
private val refreshTask = object : Runnable {
override fun run() {
V2XRefreshModel.querySnapshot(longitude = realLongitude.get(), latitude = realLatitude.get(), refreshCallback)
handler.postDelayed(this, config.get().durationForTriggerRefresh)
}
}
private val handler by lazy {
Handler(Looper.getMainLooper())
}
/**
* 根据所配置的参数初始化V2X相关功能注: 此方法不要重复调用,非首次调用会抛异常)
* @param config 相关配置类
*/
fun init(config: V2XConfig) {
Logger.d(TAG, "-- init --")
if (V2XManager.config.get() != null) {
throw IllegalStateException("V2XManager has been initialized, don't initialize repeatably.")
}
V2XManager.config.set(config)
Logger.loggable = config.loggable
}
/**
* - 开启V2X功能, 此方法调用前,要确保满足以下两个条件:
* 1.初始化方法[init]已调用
* 2.确保[MoGoAiCloudClientConfig.sn]和[MoGoAiCloudClientConfig.token]两个值存在,如果其中有一个值不存在,不会启动相关功能
* - 此函数的功能如下:
* 1.建立长链接[SocketManager.init]
* 2.位置上报服务[LocationManager.init]和[LocationManager.start]
* 3.短链[V2XRefreshModel.querySnapshot]定时轮循,轮循时长取[V2XConfig.durationForTriggerRefresh]
*/
fun start() {
Logger.d(TAG, "-- start --")
val config = config.get() ?: throw IllegalStateException("V2XManager has not been initialized, please invoke V2XManager#init(config: X2XConfig) firstly.")
if (started.get()) {
Logger.d(TAG, "-- has been started --")
return
}
if (config.aiCloudConfig.sn?.isBlank() == true) {
Logger.e(TAG, "sn is null or blank, please ensure sn exists and then invoke V2XManager#start() again.")
cbs.forEach {
it.onFail("sn is null or blank, please ensure sn exists and then invoke V2XManager#start() again.")
}
return
}
if (config.aiCloudConfig.token?.isBlank() == true) {
Logger.e(TAG, "token is null or blank, please ensure token exists and then invoke V2Manager#start() again.")
cbs.forEach {
it.onFail("token is null or blank, please ensure token exists and then invoke V2Manager#start() again.")
}
return
}
if (started.compareAndSet(false, true)) {
Logger.d(TAG, "-- start real --")
SocketManager.getInstance().init(config.context,0.0,0.0)
SocketManager.getInstance().registerOnMessageListener(401012, V2XMessageListener_401012(cbs))
SocketManager.getInstance().registerOnMessageListener(401018, V2XMessageListener_401018(cbs))
SocketManager.getInstance().registerOnMessageListener(402000, V2XMessageListener_402000(cbs))
SocketManager.getInstance().registerOnMessageListener(404000, V2XMessageListener_404000(cbs))
//SocketManager.getInstance().registerOnMessageListener(503000, V2XMessageListener_503000(cbs))
SocketManager.getInstance().registerOnMessageListener(70001, V2XMessageListener_70001(cbs))
handler.post(refreshTask)
}
}
/**
* @param sn 更新后的sn
* @param token 更新后的token
*/
fun updateSnAndToken(sn: String?, token: String?) {
val config = config.get() ?: throw IllegalStateException("V2XManager has not been initialized, please invoke V2XManager#init(config: X2XConfig) firstly.")
sn ?: return
token ?: return
if (started.get()) {
return
}
config.aiCloudConfig.sn = sn
config.aiCloudConfig.token = token
start()
}
/**
* 停止V2X功能
* 1. 断开长链接[SocketManager.release]
* 2. 停止位置上报[LocationManager.stop]
* 3. 取消短链定时轮循任务
*/
fun stop() {
Logger.d(TAG, "-- stop --")
if (config.get() == null) {
throw IllegalStateException("V2XManager has not been initialized, please invoke V2XManager#init(config: X2XConfig) firstly.")
}
if (started.compareAndSet(true, false)) {
Logger.d(TAG, "-- stop real --")
SocketManager.getInstance().release()
handler.removeCallbacks(refreshTask)
lastLatitude.set(0.0)
lastLongitude.set(0.0)
}
}
/**
* 添加相关信息接口回调
* @param cb 要添加的回调接口
*/
fun addCallback(cb: IV2XCallback) {
Logger.d(TAG, "-- addCallback --")
if (cbs.contains(cb)) {
return
}
cbs += cb
}
/**
* 移除相关信息接口回调
* @param cb 要移除的回调接口
*/
fun removeCallback(cb: IV2XCallback) {
Logger.d(TAG, "-- removeCallback --")
if (!cbs.contains(cb)) {
return
}
cbs.remove(cb)
}
/**
* 当自车位置变量时调用
* @param longitude 自车所在精度
* @param latitude 自车所在纬度
*/
fun onLocationChanged(longitude: Double, latitude: Double) {
if (config.get() == null) {
throw IllegalStateException("V2XManager has not been initialized, please invoke V2XManager#init(config: X2XConfig) firstly.")
}
if (!started.get()) {
return
}
Logger.d(TAG, "--- onLocationChanged --[longitude: $longitude, latitude: $latitude]")
realLongitude.set(longitude)
realLatitude.set(latitude)
val oldLon = lastLongitude.get()
val oldLat = lastLatitude.get()
var update = false
try {
if (oldLon == 0.0 || oldLat == 0.0) {
Logger.d(TAG, "--- onLocationChanged -- first --[longitude: $longitude, latitude: $latitude]")
handler.removeCallbacks(refreshTask)
handler.post(refreshTask)
update = true
return
}
if (DistanceUtils.calculateLineDistance(oldLon, oldLat, longitude, latitude) >= config.get().distanceForTriggerRefresh) {
Logger.d(TAG, "--- onLocationChanged -- trigger --[longitude: $longitude, latitude: $latitude]")
handler.removeCallbacks(refreshTask)
handler.post(refreshTask)
update = true
}
} finally {
if (update) {
lastLatitude.set(latitude)
lastLongitude.set(longitude)
}
}
}
/**
* 是否已经初始化
* @return true: 已初始化过 false: 未初始化
*/
fun hasInit() = getConfig() != null
/**
* 强制刷新道路事件
*/
fun forceRefresh() {
if (hasInit()) {
handler.removeCallbacks(refreshTask)
handler.post(refreshTask)
}
}
internal fun getConfig() = config.get()
}

View File

@@ -0,0 +1,24 @@
package com.mogo.eagle.core.function.v2x.internal.callback
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
interface IV2XCallback {
/**
* 获取到V2X事件成功回调
* @param event
* - 参数说明:目前此参数支持以下类型
* - [V2XEvent.ForwardsWarning]: 路口碰撞预警、盲区预警等预警事件, 数据实体取自[V2XEvent.ForwardsWarning.data]
* - [V2XEvent.Road]: 道路事件, 数据实体取自[V2XEvent.Road.data]
* - [V2XEvent.Warning]: 预警目标物事件, 数据实体取自[V2XEvent.Warning.data]
* - [V2XEvent.Marker]: 道路标记事件, 数据实体取自[V2XEvent.Marker.data]
*/
fun onAck(event: V2XEvent)
/**
* V2X事件获取过程中出现的异常信息用于问题排查
* @param msg 异常信息
*/
fun onFail(msg: String)
}

View File

@@ -0,0 +1,174 @@
package com.mogo.eagle.core.function.v2x.internal.config
import android.content.Context
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.function.v2x.internal.executor.Executors
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import kotlin.IllegalStateException
/**
* V2X相关配置
*/
class V2XConfig private constructor(builder: Builder) {
/**
* - 应用上下文
* - 必选项
* - 通过[Builder.context]设置
*/
val context : Context by lazy {
builder.context?.applicationContext ?: throw IllegalStateException("context must not be null.")
}
/**
* - 云平台配置参数
* - 必选项
* - 通过[Builder.aiCloudConfig]设置
*/
val aiCloudConfig by lazy {
builder.aiCloudConfig ?: throw IllegalStateException("aiCloudConfig must not be null.")
}
/**
* - 网络请求使用的线程池IO类型
* - 可选项
* - 通过[Builder.executor]设置
*/
val executor: Executor by lazy {
builder.executor ?: Executors.IO
}
/**
* - 是否开启日志
* - 可选项
* - 通过[Builder.loggable]设置,开发阶段可以打开,应用发布后记得关闭
*/
val loggable: Boolean by lazy {
builder.loggable
}
/**
* - 公共参数, 默认为空
* - 可选项
* - 通过[Builder.staticParams]设置
*/
val staticParams by lazy {
builder.staticParams ?: HashMap<String, Any>()
}
/**
* - 基础Url, 默认值为`http://dzt-launcherSnapshot.zhidaozhixing.com`
* - 可选项
* - 通过[Builder.baseUrl]设置
*/
val baseUrl by lazy {
builder.baseUrl ?: "http://dzt-launcherSnapshot.zhidaozhixing.com"
}
/**
* - 多长时间请求一次自车周边信息,单位为毫秒,默认值为`6_000`毫秒
* - 可选项
* - 通过[Builder.durationForTriggerRefresh]设置
*/
val durationForTriggerRefresh by lazy {
val duration = builder.durationForTriggerRefresh
if (duration == null || duration <= 0) TimeUnit.SECONDS.toMillis(60) else duration
}
/**
* - 自车行驶超过此长度,会刷新自车周边信息,单位为`米`
* - 可选项
* - 通过[Builder.distanceForTriggerRefresh]设置
*/
val distanceForTriggerRefresh: Float by lazy {
val distance = builder.distanceForTriggerRefresh
if (distance == null || distance <= 0) 200f else distance
}
internal fun newBuilder() = Builder(this)
class Builder {
internal var context: Context? = null
internal var executor: Executor? = null
internal var loggable: Boolean = false
internal var staticParams: Map<String, Any?>? = null
internal var aiCloudConfig: MoGoAiCloudClientConfig? = null
internal var durationForTriggerRefresh: Long? = null
internal var baseUrl: String? = null
internal var distanceForTriggerRefresh: Float? = null
constructor()
internal constructor(config: V2XConfig) {
context = config.context
executor = config.executor
loggable = config.loggable
baseUrl = config.baseUrl
staticParams = config.staticParams
aiCloudConfig = config.aiCloudConfig
durationForTriggerRefresh = config.durationForTriggerRefresh
distanceForTriggerRefresh = config.distanceForTriggerRefresh
}
/**
* 应用上下文,此参数为必选项,不设置会抛异常
*/
fun context(context: Context) = apply { this.context = context }
/**
* 是否开启日志
*/
fun loggable(loggable: Boolean) = apply { this.loggable = loggable }
/**
* 公共参数列表
*/
fun staticParams(params: Map<String, Any?>) = apply { this.staticParams = params }
/**
* 网络请求线程池,如未设置,会使用内置的线程池[Executors.IO]
*/
fun executor(executor: Executor): Builder = apply {
if (this.executor != null) {
throw IllegalArgumentException("io executor has been initialized, don't set repeatedly.")
}
this.executor = executor
}
/**
* 刷新周边信息的时间间隔
* @param duration 时长
* @param unit 时间单位
*/
fun durationForTriggerRefresh(duration: Long, unit: TimeUnit = TimeUnit.SECONDS) = apply { this.durationForTriggerRefresh = unit.toMillis(duration) }
/**
* @param distance 超过此距离会触发刷新周边道路信息,单位为米
*/
fun distanceForTriggerRefresh(distance: Float) = apply { this.distanceForTriggerRefresh = distance }
/**
* 云平台配置信息,此参数为必选项,不设置会抛异常
* @param config 云平台配置
*/
fun aiCloudConfig(config: MoGoAiCloudClientConfig) = apply { this.aiCloudConfig = config }
/**
* 云平台baseUrl
* @param baseUrl 云平台baseUrl
*/
fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl }
fun build() : V2XConfig = V2XConfig(this)
}
}

View File

@@ -0,0 +1,120 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
import java.io.Serializable
/**
* 路口碰撞预警、盲区预警等数据实体
*/
@Keep
class V2XAdvanceWarning: Serializable {
companion object {
private const val serialVersionUID = -446395L
}
/**
* 物体唯一标识
*/
var objectId: String? = null
/**
* 物体类型:
* 1-人
* 2-自行车
* 3-小轿车
* 4-摩托车
* 5-红绿灯
* 6-公交车
* 8-卡车
* 9-路边摄像头
*/
var objectType: Int? = -1
/**
* 1-add
* 2-update
* 3-delete
*/
var status: Int? = -1
/**
* 大类标识
* 1-预警
* 2-规划
* 3-拥堵
* 4-事故
*/
var typeId: Int? = -1
/**
* 预警下发时间
*/
var time: Long? = 0
/**
* 预警等级
*/
var level: Int? = -1
/**
* 危险等级:
* 0-保留
* 1-模型原始颜色
* 2-通知--黄
* 3-警告--红
*/
var threatLevel: Int? = -1
/**
* 目标预警物所在位置
*/
var position: V2XLocation? = null
/**
* 目标预警物朝向
*/
var heading: Double? = 0.0
/**
* 目标预警物速度
*/
var speed: Double? = 0.0
/**
* 目标预警物到自车距离
*/
var distance: Double? = 0.0
/**
* 道路ID
*/
var roadId: String? = null
/**
* 车道ID
*/
var laneId: String? = null
/**
* 车道号:
* 中心线编号为0, 中心线右侧编号为负数。
* eg: 3车道通行Road的车道编号0,-1,-2,-3
*/
var laneNum: Int? = Integer.MIN_VALUE
/**
* 线性经纬度轨迹列表(高德)
*/
var gdLocusList: List<V2XLocation>? = null
/**
* 轨迹列表(Wgs84坐标系)
*/
var locusList: List<V2XLocation>? = null
override fun toString(): String {
return "V2XAdvanceWarning(objectId=$objectId, objectType=$objectType, status=$status, typeId=$typeId, time=$time, level=$level, threatLevel=$threatLevel, position=$position, heading=$heading, speed=$speed, distance=$distance, roadId=$roadId, laneId=$laneId, laneNum=$laneNum, gdLocusList=$gdLocusList, locusList=$locusList)"
}
}

View File

@@ -0,0 +1,9 @@
package com.mogo.eagle.core.function.v2x.internal.data
open class V2XBaseData {
@JvmField
var code = -1
@JvmField
var msg: String? = null
}

View File

@@ -0,0 +1,26 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
import java.io.Serializable
@Keep
class V2XLocation: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 经度
*/
var lon: Double = 0.0
/**
* 纬度
*/
var lat: Double = 0.0
override fun toString(): String {
return "V2XLocation(lon=$lon, lat=$lat)"
}
}

View File

@@ -0,0 +1,817 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
import java.io.Serializable
@Keep
class V2XMarkerCardResult: V2XBaseData(), Serializable {
companion object {
private const val serialVersionUID = -92L
}
/**
* 要查询的数据类型
* CARD_TYPE_USER_DATA用户相关数据
* CARD_TYPE_ROAD_CONDITION路况数据
* CARD_TYPE_LIVE正播相关数据
*/
var dataType: List<String>? = null
/**
* 车聊聊数据集合
*/
var carChat: List<V2XMarkerCarChat>? = null
/**
* 分享的音乐数据集合
*/
var shareMusic: List<V2XMarkerShareMusic>? = null
/**
* 新鲜事分享的数据集合
*/
var noveltyInfo: List<V2XMarkerNoveltyInfo>? = null
/**
* 在线车辆数据集合
*/
var onlineCar: List<V2XMarkerOnlineCar>? = null
/**
* 探路数据集合
*/
var exploreWay: List<V2XMarkerExploreWay>? = null
/**
* 服务端下发消息时间
*/
var messageTime: Long = 0
/**
* 额外信息
*/
var extras: Map<String, Any>? = null
override fun toString(): String {
return "MarkerCardResult(dataType=$dataType, carChat=$carChat, shareMusic=$shareMusic, noveltyInfo=$noveltyInfo, onlineCar=$onlineCar, exploreWay=$exploreWay, messageTime=$messageTime, extras=$extras)"
}
}
@Keep
class V2XMarkerCarChat: Serializable {
companion object {
private const val serialVersionUID = -92L
}
/**
* 卡片类型
*/
var type: String? = null
/**
* 地址信息
*/
var location: V2XMarkerLocation? = null
/**
* 用户信息
*/
var userInfo: V2XMarkerUserInfo? = null
override fun toString(): String {
return "V2XMarkerCarChat(type=$type, location=$location, userInfo=$userInfo)"
}
}
@Keep
class V2XMarkerShareMusic: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 事件类型
*/
var type: String? = null
/**
* 音乐专辑信息
*/
var bookInfo: String? = null
/**
* 歌曲ID
*/
var id = 0
/**
* 点赞数
*/
var likeNumber = 0
/**
* 位置信息
*/
var location: V2XMarkerLocation? = null
/**
* 已弃用
*/
var mediaId: String? = null
/**
* 歌曲封面-已弃用
*/
var mediaImg: String? = null
/**
* 歌曲名字
*/
var mediaName: String? = null
/**
* 歌手名字
*/
var mediaSinger: String? = null
/**
* 播放地址
*/
var mediaUrl: String? = null
/**
* 分享文案
*/
var shareContentText: String? = null
/**
* 分享类型
*/
var shareType = 0
/**
* 用户信息
*/
var userInfo: V2XMarkerUserInfo? = null
override fun toString(): String {
return "V2XMarkerShareMusic(bookInfo=$bookInfo, id=$id, likeNumber=$likeNumber, location=$location, mediaId=$mediaId, mediaImg=$mediaImg, mediaName=$mediaName, mediaSinger=$mediaSinger, mediaUrl=$mediaUrl, shareContentText=$shareContentText, shareType=$shareType, type=$type, userInfo=$userInfo)"
}
}
/**
* 新鲜事儿Marker数据
*/
@Keep
class V2XMarkerNoveltyInfo: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 事件类型
*/
var type: String? = null
/**
* 车机唯一标识
*/
var sn: String? = null
/**
* 标记坐标
*/
var location: V2XMarkerLocation? = null
/**
* POI类型
*/
var poiType: String? = null
/**
* 新鲜事分享内容
*/
var contentData: ContentData? = null
@Keep
class ContentData: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 信息ID
*/
var infoId: String? = null
/**
* 分享内容
*/
var content: String? = null
/**
* 分享内容左上角图标
*/
var iconUrl: String? = null
/**
* 分享内容图片
*/
var imgUrl: String? = null
/**
* 点赞数
*/
var likeNum: Long = 0
/**
* 标题
*/
var title: String? = null
/**
* 加油站油价
*/
var gasPrices: String? = null
/**
* 是否显示导航
*/
var isDisplayNavigation = false
/**
* 是否显示好友主页
*/
var isDesplayHost = false
/**
* 是否是新鲜的
*/
var isFabulous = false
/**
* 分享类型
*/
var styleType: String? = null
/**
* 上报类型:
* 1-用户上报
* 2-后台上报
* 3-三方上报
*/
var uploadType: String? = null
override fun toString(): String {
return "ContentData(content=$content, iconUrl=$iconUrl, imgUrl=$imgUrl, infoId=$infoId, likeNum=$likeNum, title=$title, gasPrices=$gasPrices, isDisplayNavigation=$isDisplayNavigation, isDesplayHost=$isDesplayHost, isFabulous=$isFabulous, styleType=$styleType, uploadType=$uploadType)"
}
}
override fun toString(): String {
return "V2XMarkerNoveltyInfo(type=$type, sn=$sn, location=$location, poiType=$poiType, contentData=$contentData)"
}
}
@Keep
class V2XMarkerOnlineCar: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 事件类型
*/
var type: String? = null
/**
* 车辆位置
*/
var location: V2XMarkerLocation? = null
/**
* focus:false-未关注true-关注
*/
var focus: Boolean? = null
/**
* 用户数据
*/
var userInfo: V2XMarkerUserInfo? = null
/**
* 车辆数据
*/
var carInfo: V2XMarkerCarInfo? = null
/**
* 车辆路线
*/
var pois: List<V2XMarkerCarPois>? = null
/**
* 动态数据
*/
var dynamicData: V2XMarkerDynamicData? = null
/**
* 爱好数据集合
*/
var hobbyData: V2XMarkerHobbyDatum? = null
/**
* 活动范围数据集合
*/
var activitiesScope: List<V2XMarkerActivitiesScope>? = null
/**
* 匹配度
*/
var compatibility = 0
override fun toString(): String {
return "V2XMarkerOnlineCar(type=$type, location=$location, focus=$focus, userInfo=$userInfo, carInfo=$carInfo, pois=$pois, dynamicData=$dynamicData, hobbyData=$hobbyData, activitiesScope=$activitiesScope, compatibility=$compatibility)"
}
}
@Keep
class V2XMarkerExploreWay: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 事件类型
*/
var type: String? = null
/**
* 信息ID
*/
var infoId: String? = null
/**
* POI类型
*/
var poiType: String? = null
/**
* 车辆唯一标识
*/
var sn: String? = null
/**
* 位置信息
*/
var location: V2XMarkerLocation? = null
/**
* 车辆方位
*/
var direction = 0
/**
* 是否可直播1为可直播0不可直播
*/
var canLive: String? = "0"
/**
* 是图片还是视频1视频0图片
*/
var fileType = 0
/**
* 车辆详细地址
*/
var addr: String? = null
/**
* 事件下发的时间
*/
var generateTime: Long = 0L
/**
* 城市名称
*/
var cityName: String? = null
/**
* 距离
*/
var distance = 0.0
/**
* 用户信息
*/
var userInfo: V2XMarkerUserInfo? = null
/**
* 视频地址和图片地址
*/
var items: List<MarkerExploreWayItem>? = null
/**
* 上报类型:
* 1-用户上报
* 2-后台上报
* 3-三方上报
*/
var uploadType: String? = null
/**
* 是否是新鲜的
*/
var isFabulous = false
/**
* 需要用户判断是否拥堵 进行UGC问答
*/
var infoCheckNode = 0
var coordinateType: Int? = null
override fun toString(): String {
return "V2XMarkerExploreWay(infoId=$infoId, type=$type, poiType=$poiType, sn=$sn, location=$location, direction=$direction, canLive=$canLive, fileType=$fileType, addr=$addr, generateTime=$generateTime, cityName=$cityName, distance=$distance, userInfo=$userInfo, items=$items, uploadType=$uploadType, isFabulous=$isFabulous, infoCheckNode=$infoCheckNode, coordinateType=$coordinateType)"
}
}
@Keep
class V2XMarkerUserInfo: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 自车车机唯一标识
*/
var sn: String? = null
/**
* 用户ID
*/
var userId: Long = 0
/**
* 用户昵称
*/
var userName: String? = null
/**
* 用户头像
*/
var userHead: String? = null
/**
* gender": "男也可以012根据实际库存返回即可
*/
var gender: String? = null
/**
* 年龄段,可以为空,与车聊聊一致
*/
var age: Int? = null
/**
* 末次活跃周驾驶行为平均得分
*/
var lastActiveweekAvgscore: String? = null
/**
* 车辆安全标签
*/
var safeLabel: String? = null
/**
* 1-老司机
* 2-安全驾驶
* 3-危险驾驶
*/
var safeLabelType = 0
override fun toString(): String {
return "V2XMarkerUserInfo(sn=$sn, userId=$userId, userName=$userName, userHead=$userHead, gender=$gender, age=$age, lastActiveweekAvgscore=$lastActiveweekAvgscore, safeLabel=$safeLabel, safeLabelType=$safeLabelType)"
}
}
@Keep
class V2XMarkerCarInfo: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 车品牌Logo资源链接
*/
var carBrandLogoUrl: String? = null
/**
* 车型名称
*/
var carTypeName: String? = null
/**
* 车类型:
* 0-普通车辆
* 1-警车
* 2-救护车
* 3-失控车
* 4-道路救援车
*/
var vehicleType: Int = 0
/**
* 车辆直播相关信息
*/
var carLiveInfo: CarLiveInfo? = null
@Keep
class CarLiveInfo: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* rtmp视频直播地址rtmp://
*/
var videoUrl: String? = null
/**
* 直播频道【直播心跳接口参数】C_1
*/
var videoChannel: String? = null
/**
* 直播源sn
*/
var videoSn: String? = null
override fun toString(): String {
return "CarLiveInfo(videoUrl=$videoUrl, videoChannel=$videoChannel, videoSn=$videoSn)"
}
}
override fun toString(): String {
return "V2XMarkerCarInfo(carBrandLogoUrl=$carBrandLogoUrl, carTypeName=$carTypeName, vehicleType=$vehicleType, carLiveInfo=$carLiveInfo)"
}
}
@Keep
class V2XMarkerCarPois: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 位置信息返回的值不为空并且长度为2的倍数
*/
var coordinates: List<*>? = null
/**
* 车的朝向角度
*/
var angle = 0.0
/**
* 地区code
*/
var adcode: String? = null
override fun toString(): String {
return "V2XMarkerCarPois(coordinates=$coordinates, angle=$angle, adcode=$adcode)"
}
}
@Keep
class V2XMarkerDynamicData: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* QQ音乐懒人听书乐听头条 2 为书籍听书3 为新闻,1 为qq音乐
*/
var type = 0
/**
* qq音乐id书的bookId
*/
var mediaId: String? = null
/**
* qq音乐url 懒人听书为“”
*/
var mediaUrl: String? = null
/**
* 歌曲名 ,当前播放书名,新闻标题内容
*/
var mediaName: String? = null
/**
* 演唱歌手,当前章节,新闻来源
*/
var mediaSinger: String? = null
/**
* 歌曲封面,书籍封面,新闻预览图
*/
var mediaImg: String? = null
/**
* 音乐类别,类似经典 流行只有qq特有
*/
var mediaType: String? = null
/**
* 音频总时长
*/
var maxTime = 0
/**
* 懒人听书json串
*/
var bookInfo: String? = null
/**
* 当前播放时长,可以不加,播放进度单独独立出来
*/
var curTime = 0
/**
* 是否是本地音频只有qq音乐
*/
var isLocalMedia = false
/**
* 播放模式,顺序,单曲循环,随机
*/
var mediaPlayMode = 0
/**
* 1 播放 2 缓冲 0 暂停/停止 -1 播放错误
*/
var playState = 0
override fun toString(): String {
return "V2XMarkerDynamicData(type=$type, mediaId=$mediaId, mediaUrl=$mediaUrl, mediaName=$mediaName, mediaSinger=$mediaSinger, mediaImg=$mediaImg, mediaType=$mediaType, maxTime=$maxTime, bookInfo=$bookInfo, curTime=$curTime, isLocalMedia=$isLocalMedia, mediaPlayMode=$mediaPlayMode, playState=$playState)"
}
}
@Keep
class V2XMarkerHobbyDatum: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 最喜欢的两位歌手
*/
var singerTop2: List<MarkerOnlineTag>? = null
/**
* 最喜欢的两种音乐类型
*/
var songTypeTop2: List<MarkerOnlineTag>? = null
/**
* 最喜欢的资讯类型
*/
var newsType: List<MarkerOnlineTag>? = null
/**
* 最喜欢听的两本书
*/
var listenBookTop2: List<MarkerOnlineTag>? = null
/**
* 是否喜爱社交
*/
var ifSociety: List<MarkerOnlineTag>? = null
@Keep
class MarkerOnlineTag: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 社交内容
*/
var content: String? = null
/**
* 是否选中
*/
var isCheck: Boolean = false
override fun toString(): String {
return "MarkerOnlineTag(content=$content, isCheck=$isCheck)"
}
}
override fun toString(): String {
return "V2XMarkerHobbyDatum(singerTop2=$singerTop2, songTypeTop2=$songTypeTop2, newsType=$newsType, listenBookTop2=$listenBookTop2, ifSociety=$ifSociety)"
}
}
@Keep
class V2XMarkerActivitiesScope: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 活动范围内容
*/
var content: String? = null
/**
* 是否选中
*/
var isCheck: Boolean = false
override fun toString(): String {
return "V2XMarkerActivitiesScope(content=$content, isCheck=$isCheck)"
}
}
/**
* 道路情报V2X预警地图道路事件POI违章停车POI等
*/
@Keep
class MarkerExploreWayItem: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 缩略图
*/
var thumbnail: String? = null
/**
* 正式图
*/
var url: String? = null
/**
* 描述字段
*/
var content: String? = null
/**
* 违章停车人数
*/
var illegalCount = 0.0
override fun toString(): String {
return "MarkerExploreWayItem(thumbnail=$thumbnail, url=$url, content=$content, illegalCount=$illegalCount)"
}
}
@Keep
class V2XMarkerLocation: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 纬度
*/
var lat: Double = 0.0
/**
* 纬度
*/
var lon: Double = 0.0
/**
* 车头角度,可以没有
*/
var angle: Double = 0.0
/**
* 具体的位置信息
*/
var address: String? = null
override fun toString(): String {
return "V2XMarkerLocation(lat=$lat, lon=$lon, angle=$angle, address=$address)"
}
}

View File

@@ -0,0 +1,28 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
import com.elegant.network.BaseResp
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerCardResult
import java.io.Serializable
@Keep
class V2XMarkerResponse: BaseResp(), Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 响应的数据集
*/
var result: V2XMarkerCardResult? = null
/**
* TODO 不知道啥含义,可以忽略
*/
var sign: String? = null
override fun toString(): String {
return "V2XMarkerResponse(result=$result, sign=$sign)"
}
}

View File

@@ -0,0 +1,56 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
import com.mogo.eagle.core.function.v2x.internal.data.V2XLocation
import java.io.Serializable
/**
* 最优路线推荐
*/
@Keep
class V2XOptimalRoute: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 自车SN
*/
var sn: String? = null
/**
* 道路ID
*/
var road_id: String? = null
/**
* 车道ID-2D路段
*/
var current_lane_id: String? = null
/**
* 车道号中心线编号为0 中心线右侧编号为负数3车道通行Road的车道编号0,-1,-2,-3
*/
var current_lane_num = 0
/**
* 最优车道平均速度
*/
var most_speed = 0.0
/**
* 车道号中心线编号为0 中心线右侧编号为负数3车道通行Road的车道编号0,-1,-2,-3
*/
var most_lane_num = 0
/**
* Wgs84坐标系线性经纬度轨迹列表
*/
var locus_list: List<V2XLocation>? = null
/**
* 高德坐标系Gcj线性经纬度轨迹列表
*/
var gd_locus_list: List<V2XLocation>? = null
}

View File

@@ -0,0 +1,59 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
@Keep
data class V2XRoadXData(
val poiType: String? = null,
val center: Point? = null,
val centerRoad: CenterRoad? = null,
val congestionLanes: List<Congestion>? = null,
val coordinateType: Int? = -1,
val id: String? = null,
val index: String? = null,
val obstacles: List<Obstacle>? = null,
val polygon: List<Point>? = null,
val type: Int? = 0,
val detectTime: Long? = 0L,
val crossId: String? = null
)
@Keep
data class CenterRoad(
val bearing: Double? = 0.0,
val laneNo: Int? = null,
val roadId: String? = null,
val roadName: String? = null,
val tileId: Int? = 0,
val heading: String? = null
)
@Keep
data class Congestion(
val laneId: Int? = null,
val level: Int? = null
)
@Keep
data class Obstacle(
val boundBox: List<PointX>? = null,
val center: Point? = null,
val id: Int? = null,
val polygon: List<Point>? = null,
val score: Double? = null,
val type: Int? = null
)
@Keep
data class Point(
val lon: Double? = null,
val lat: Double? = null
)
@Keep
data class PointX(
val x: Double? = null,
val y: Double? = null
)

View File

@@ -0,0 +1,176 @@
package com.mogo.eagle.core.function.v2x.internal.data
import androidx.annotation.Keep
import com.mogo.eagle.core.function.v2x.internal.data.V2XLocation
import java.io.Serializable
/**
* 预警目标物数据模型
*/
@Keep
class V2XWarningTarget: Serializable {
companion object {
private const val serialVersionUID = -93L
}
/**
* 事件类型
* 行人-1
* 自行车-2
* 摩托车-4
* 骑行车辆-11
*/
var type = 0
/**
* 目标物纬度
*/
var lat = 0.0
/**
* 目标物经度
*/
var lon = 0.0
/**
* 目标物颜色
*/
var targetColor: String? = null
/**
* 目标物距自车距离
*/
var distance = 0.0
/**
* 预测碰撞点位置-纬度
*/
var collisionLat = 0.0
/**
* 预测碰撞点位置-经度
*/
var collisionLon = 0.0
/**
* 目标物行驶朝向
*/
var angle = 0.0
/**
* 目标物方位
* 方位:前 后 左 右
*/
var direction = 0
/**
* 目标物速度
*/
var speed = 0f
/**
* 停止线经纬度
*/
var stopLines: List<V2XLocation>? = null
/**
* 自车到停止线距离
*/
var stopLineDistance = 0.0
/**
* 道路唯一标识
*/
var roadId: String? = null
/**
* 车道唯一标识
*/
var laneId: String? = null
/**
* 识别物体唯一标识
*/
var uuid: String? = null
/**
* 红绿灯颜色
*/
var color: String? = null
/**
* 车ID 暂不使用
*/
var carId: String? = null
/**
* 预警文案
*/
var warningContent: String? = null
/**
* 车头朝向
*/
var heading = 0.0
/**
* 系统时间 暂时没用
*/
var systemTime: Long = 0
/**
* 定位卫星时间 暂时没用
*/
var satelliteTime: Long = 0
/**
* 预警蒙层等展示时长
*/
var showTime: Long = 0
/**
* 设计划线宽度与道路同宽
*/
var roadwidth = 0f
/**
* 自组字段, tts播报
*/
var tts: String? = null
/**
* 自车位置
*/
var carLocation: V2XLocation? = null
override fun toString(): String {
return "V2XWarningEntity{" +
"type=" + type +
", lat=" + lat +
", lon=" + lon +
", targetColor='" + targetColor + '\'' +
", distance=" + distance +
", collisionLat=" + collisionLat +
", collisionLon=" + collisionLon +
", angle=" + angle +
", direction=" + direction +
", speed=" + speed +
", stopLines=" + stopLines +
", stopLineDistance=" + stopLineDistance +
", roadId='" + roadId + '\'' +
", laneId='" + laneId + '\'' +
", uuid='" + uuid + '\'' +
", color='" + color + '\'' +
", carId='" + carId + '\'' +
", warningContent='" + warningContent + '\'' +
", heading=" + heading +
", systemTime=" + systemTime +
", satelliteTime=" + satelliteTime +
", showTime=" + showTime +
", roadwidth=" + roadwidth +
", tts='" + tts + '\'' +
", carLocation=" + carLocation +
'}'
}
}

View File

@@ -0,0 +1,75 @@
package com.mogo.eagle.core.function.v2x.internal.event
import com.mogo.eagle.core.function.v2x.internal.data.*
import roadwork.Road.RW_PB
sealed class V2XEvent {
/**
* 长链-路口碰撞预警、盲区预警等通用Bean
*/
class ForwardsWarning(val type: Int = 404000, val data: V2XAdvanceWarning): V2XEvent() {
override fun toString(): String {
return "ForwardsWarning(type=$type, data=$data)"
}
}
/**
* 长链-最优推荐线种
*/
class OptimalRoute(val type: Int = 402000, val data: V2XOptimalRoute): V2XEvent() {
override fun toString(): String {
return "OptimalRoute(type=$type, data=$data)"
}
}
/**
* 长链-预警目标物
*/
class Warning(val type: Int = 401018, val data: V2XWarningTarget): V2XEvent() {
override fun toString(): String {
return "Warning(type=$type, data=$data)"
}
}
/**
* 长链-道路事件
*/
class Road(val type: Int = 401012, val data: V2XMarkerCardResult): V2XEvent() {
override fun toString(): String {
return "Road(type=$type, data=$data)"
}
}
/**
* 长链-道路事件云识别
*/
class RoadAI(val type: Int = 503000, val data: RW_PB): V2XEvent() {
override fun toString(): String {
return "RoadAI(type=$type, data=$data)"
}
}
/**
* 短链-道路标记事件
*/
class Marker(val data: V2XMarkerResponse): V2XEvent() {
override fun toString(): String {
return "Marker(data=$data)"
}
}
/**
* 长链-道路事件扩展数据结构
*/
class RoadEventX(val type: Int = 70001, val data: V2XRoadXData): V2XEvent() {
override fun toString(): String {
return "RoadEventX(type=$type, data=$data)"
}
}
}

View File

@@ -0,0 +1,35 @@
package com.mogo.eagle.core.function.v2x.internal.executor
import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicLong
import kotlin.math.max
import kotlin.math.min
internal object Executors {
private val group: ThreadGroup by lazy {
ThreadGroup("v2x-group")
}
private val CPU_CORE_COUNT by lazy {
Runtime.getRuntime().availableProcessors()
}
private val DEFAULT_CORE_COUNT by lazy {
(max(2, min(CPU_CORE_COUNT - 1, 6)) * 3) + 1
}
private const val DEFAULT_MAX_COUNT_4_IO = 128
val IO by lazy {
val idGenerator = AtomicLong(0)
ThreadPoolExecutor(
DEFAULT_CORE_COUNT, DEFAULT_MAX_COUNT_4_IO, 30, TimeUnit.SECONDS, LinkedBlockingDeque()
) { r ->
Thread(group, r).apply {
name = "io-thread-${idGenerator.getAndIncrement()}"
}
}
}
}

View File

@@ -0,0 +1,84 @@
package com.mogo.eagle.core.function.v2x.internal.http
import com.elegant.network.utils.GsonUtil
import com.elegant.network.utils.SignUtil
import com.elegant.utils.CommonUtils
import com.mogo.cloud.network.RetrofitFactory
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.config.V2XConfig
import com.mogo.eagle.core.function.v2x.internal.data.V2XLocation
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerResponse
import com.mogo.eagle.core.function.v2x.internal.http.api.V2XApiService
import com.mogo.eagle.core.function.v2x.internal.http.body.V2XRefreshEntity
import com.mogo.eagle.core.function.v2x.internal.http.callback.IV2XRefreshCallback
import com.mogo.eagle.core.function.v2x.internal.utils.DeviceUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
internal class V2XRefreshModel {
companion object {
fun querySnapshot(
longitude: Double,
latitude: Double,
callback: IV2XRefreshCallback<V2XMarkerResponse>?
): Disposable? {
val config = V2XManager.getConfig()
val retrofit = RetrofitFactory.getInstance(config.baseUrl) ?: return null
return retrofit
.create(V2XApiService::class.java)
.querySnapshotSync(buildParams(longitude, latitude, config))
.subscribeOn(Schedulers.from(config.executor))
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ data ->
if (data == null) {
callback?.onFail("returned data is null.")
return@subscribe
}
if (data.code != 0 && data.code != 200) {
callback?.onFail("code:${data.code}, msg: ${data.msg}")
} else {
callback?.onSuccess(data)
}
}, {
callback?.onFail(it.message)
})
}
private fun buildParams(
longitude: Double,
latitude: Double,
config: V2XConfig
): Map<String, Any> = mutableMapOf<String, Any>().apply {
putAll(config.staticParams.let {
val handled = mutableMapOf<String, Any>()
it.asIterable().forEach { itx ->
val value = itx.value
if (value != null) {
handled[itx.key] = value
}
}
handled
})
this["netType"] = CommonUtils.getNetworkType(config.context)
this["cellId"] = DeviceUtils.getCellId(config.context) ?: ""
this["sn"] = config.aiCloudConfig.sn
this["ticket"] = config.aiCloudConfig.token
this["sig"] = SignUtil.createSign(this, "JGjZx6")
this["data"] = GsonUtil.jsonFromObject(V2XRefreshEntity().apply {
limit = 999
location = V2XLocation().also {
it.lat = latitude
it.lon = longitude
}
radius = 1000
dataType.add("CARD_TYPE_ROAD_CONDITION")
viewPush = true
})
}
}
}

View File

@@ -0,0 +1,14 @@
package com.mogo.eagle.core.function.v2x.internal.http.api
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerResponse
import io.reactivex.Maybe
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
internal interface V2XApiService {
@FormUrlEncoded
@POST("/yycp-launcherSnapshot/launcherSnapshot/querySnapshotSync")
fun querySnapshotSync(@FieldMap parameters: Map<String, @JvmSuppressWildcards Any>): Maybe<V2XMarkerResponse?>
}

View File

@@ -0,0 +1,39 @@
package com.mogo.eagle.core.function.v2x.internal.http.body
import androidx.annotation.Keep
import com.mogo.eagle.core.function.v2x.internal.data.V2XLocation
/**
* 刷新地图信息接口
*/
@Keep
internal class V2XRefreshEntity {
@JvmField
var dataType: MutableList<String> = mutableListOf() // 要查询的类型
@JvmField
var limit = 50 // 请求数量
@JvmField
var radius = 2000 // 地理围栏半径(米)
@JvmField
var location // 坐标
: V2XLocation? = null
@JvmField
var sn: String? = null
@JvmField
var onlyFocus // 是否仅查询已关注的好友
= false
@JvmField
var onlySameCity // 是否仅查询注册城市相同的同城用户
= false
@JvmField
var viewPush // 是否走V2X通道 true-401011false -401001
= false
@JvmField
var onlyRealUser = false
}

View File

@@ -0,0 +1,11 @@
package com.mogo.eagle.core.function.v2x.internal.http.callback
/**
* 刷新回调
*/
internal interface IV2XRefreshCallback<T> {
fun onSuccess(result: T)
fun onFail(msg: String?)
}

View File

@@ -0,0 +1,24 @@
package com.mogo.eagle.core.function.v2x.internal.logger
import android.util.Log
internal object Logger {
var loggable: Boolean = false
fun v(tag: String, msg: String) = if (loggable) Log.v(tag, msg) else 0
fun d(tag: String, msg: String) = if (loggable) Log.d(tag, msg) else 0
fun i(tag: String, msg: String) = if (loggable) Log.i(tag, msg) else 0
fun w(tag: String, msg: String) = if (loggable) Log.w(tag, msg) else 0
fun e(tag: String, msg: String, t: Throwable? = null) = if (loggable) {
if (t == null) {
Log.e(tag, msg)
} else {
Log.e(tag, msg, t)
}
} else 0
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.internal.socket
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerCardResult
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
internal class V2XMessageListener_401012(val cbs: Iterable<IV2XCallback>?): IMogoCloudSocketOnMessageListener<V2XMarkerCardResult> {
override fun target(msgType: Int): Class<V2XMarkerCardResult> = V2XMarkerCardResult::class.java
override fun onMsgReceived(msgType: Int, data: V2XMarkerCardResult?) {
if (msgType != 401012) {
return
}
if (data == null) {
Logger.i(V2XManager.TAG, "V2XMessageListener_401012message is null!")
return
}
Logger.i(V2XManager.TAG, "V2XMessageListener_401012:$data")
cbs?.forEach {
it.onAck(V2XEvent.Road(data = data))
}
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.internal.socket
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.internal.data.V2XWarningTarget
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
internal class V2XMessageListener_401018(val cbs: Iterable<IV2XCallback>?): IMogoCloudSocketOnMessageListener<V2XWarningTarget> {
override fun target(msgType: Int): Class<V2XWarningTarget> = V2XWarningTarget::class.java
override fun onMsgReceived(msgType: Int, data: V2XWarningTarget?) {
if (msgType != 401018) {
return
}
if (data == null) {
Logger.i(V2XManager.TAG, "V2XMessageListener_401018message is null!")
return
}
Logger.i(V2XManager.TAG, "V2XMessageListener_401018:$data")
cbs?.forEach {
it.onAck(V2XEvent.Warning(data = data))
}
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.internal.socket
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.data.V2XOptimalRoute
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
internal class V2XMessageListener_402000(val cbs: Iterable<IV2XCallback>?): IMogoCloudSocketOnMessageListener<V2XOptimalRoute> {
override fun target(msgType: Int): Class<V2XOptimalRoute> = V2XOptimalRoute::class.java
override fun onMsgReceived(msgType: Int, data: V2XOptimalRoute?) {
if (msgType != 402000) {
return
}
if (data == null) {
Logger.i(V2XManager.TAG, "V2XMessageListener_402000message is null!")
return
}
Logger.i(V2XManager.TAG, "V2XMessageListener_402000:$data")
cbs?.forEach {
it.onAck(V2XEvent.OptimalRoute(data = data))
}
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.internal.socket
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.data.V2XAdvanceWarning
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
internal class V2XMessageListener_404000(val cbs: Iterable<IV2XCallback>?): IMogoCloudSocketOnMessageListener<V2XAdvanceWarning> {
override fun target(msgType: Int): Class<V2XAdvanceWarning> = V2XAdvanceWarning::class.java
override fun onMsgReceived(msgType: Int, data: V2XAdvanceWarning?) {
if (msgType != 404000) {
return
}
if (data == null) {
Logger.i(V2XManager.TAG, "V2XMessageListener_404000message is null!")
return
}
Logger.i(V2XManager.TAG, "V2XMessageListener_404000:$data")
cbs?.forEach {
it.onAck(V2XEvent.ForwardsWarning(data = data))
}
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.internal.socket
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent.RoadAI
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
import roadwork.Road.RW_PB
internal class V2XMessageListener_503000(val cbs: Iterable<IV2XCallback>?): IMogoCloudSocketOnMessageListener<RW_PB> {
override fun target(msgType: Int): Class<RW_PB> = RW_PB::class.java
override fun onMsgReceived(msgType: Int, data: RW_PB?) {
if (msgType != 503000) {
return
}
if (data == null) {
Logger.i(V2XManager.TAG, "V2XMessageListener_503000message is null!")
return
}
Logger.i(V2XManager.TAG, "V2XMessageListener_503000:$data")
cbs?.forEach {
it.onAck(RoadAI(data = data))
}
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.internal.socket
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.eagle.core.function.v2x.internal.V2XManager
import com.mogo.eagle.core.function.v2x.internal.callback.IV2XCallback
import com.mogo.eagle.core.function.v2x.internal.data.V2XRoadXData
import com.mogo.eagle.core.function.v2x.internal.event.V2XEvent
import com.mogo.eagle.core.function.v2x.internal.logger.Logger
internal class V2XMessageListener_70001(val cbs: Iterable<IV2XCallback>?): IMogoCloudSocketOnMessageListener<V2XRoadXData> {
override fun target(msgType: Int): Class<V2XRoadXData> = V2XRoadXData::class.java
override fun onMsgReceived(msgType: Int, data: V2XRoadXData?) {
if (msgType != 70001) {
return
}
if (data == null) {
Logger.i(V2XManager.TAG, "V2XMessageListener_70001message is null!")
return
}
Logger.i(V2XManager.TAG, "V2XMessageListener_70001:$data")
cbs?.forEach {
it.onAck(V2XEvent.RoadEventX(data = data))
}
}
}

View File

@@ -0,0 +1,46 @@
package com.mogo.eagle.core.function.v2x.internal.utils
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.telephony.CellLocation
import android.telephony.TelephonyManager
import android.telephony.cdma.CdmaCellLocation
import android.telephony.gsm.GsmCellLocation
import java.lang.Exception
internal class DeviceUtils {
companion object {
@SuppressLint("MissingPermission")
@JvmStatic
fun getCellId(context: Context): String? {
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val pm = context.packageManager
val accessCoarseLocationPermission = PackageManager.PERMISSION_GRANTED ==
pm.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, context.packageName)
val accessFineLocationPermission = PackageManager.PERMISSION_GRANTED ==
pm.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, context.packageName)
if (!accessCoarseLocationPermission || !accessFineLocationPermission) return "noPermission"
var location: CellLocation? = null
try {
location = tm.cellLocation
} catch (e: Exception) {
e.printStackTrace()
}
if (location != null) {
// Gsm网络 , 联通移动的网络属于这一套
if (location is GsmCellLocation) {
val cellid = location.cid
return cellid.toString()
// Cdma网络 , 电信网络属于这一种
} else if (location is CdmaCellLocation) {
return location.baseStationId.toString()
}
}
return null
}
}
}

View File

@@ -0,0 +1,52 @@
package com.mogo.eagle.core.function.v2x.internal.utils
import kotlin.math.asin
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
internal class DistanceUtils {
companion object {
/**
* @param lon1
* @param lat1
* @param lon2
* @param lat2
* @return 两坐标的距离 单位M
*/
fun calculateLineDistance(lon1: Double, lat1: Double, lon2: Double, lat2: Double): Float {
return try {
var var2 = lon1
var var4 = lat1
var var6 = lon2
var var8 = lat2
var2 *= 0.01745329251994329
var4 *= 0.01745329251994329
var6 *= 0.01745329251994329
var8 *= 0.01745329251994329
val var10 = sin(var2)
val var12 = sin(var4)
val var14 = cos(var2)
val var16 = cos(var4)
val var18 = sin(var6)
val var20 = sin(var8)
val var22 = cos(var6)
val var24 = cos(var8)
val var28 = DoubleArray(3)
val var29 = DoubleArray(3)
var28[0] = var16 * var14
var28[1] = var16 * var10
var28[2] = var12
var29[0] = var24 * var22
var29[1] = var24 * var18
var29[2] = var20
(asin(sqrt((var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2])) / 2.0) * 1.27420015798544E7).toFloat()
} catch (var26: Throwable) {
var26.printStackTrace()
0.0f
}
}
}
}

View File

@@ -0,0 +1,73 @@
package com.mogo.eagle.core.function.v2x.road
import androidx.annotation.Keep
import com.google.gson.annotations.SerializedName
import com.mogo.eagle.core.data.BaseData
@Keep
data class V2XEventResult (
@SerializedName("result")
var result: Result?
): BaseData()
@Keep
data class Result(
@SerializedName("eventList")
var v2XEventList: List<V2XEvent>?
)
@Keep
data class V2XEvent(
@SerializedName("receiveTime")
var receiveTime: Long,
@SerializedName("detectTime")
var detectTime: Long,
@SerializedName("id")
var id: String?,
@SerializedName("center")
var center: Center?,
@SerializedName("centerRoad")
var centerRoad: CenterRoad?,
@SerializedName("radius")
var radius: Double,
@SerializedName("poiType")
var poiType: String?,
@SerializedName("coordinateType")
var coordinateType:Int? = null
)
@Keep
data class Center(
@SerializedName("lat")
var lat: Double,
@SerializedName("lon")
var lon: Double
)
@Keep
data class CenterRoad(
@SerializedName("bearing")
var bearing: Double,
@SerializedName("laneNo")
var laneNo: Long,
@SerializedName("roadId")
var roadId: String?,
@SerializedName("roadName")
var roadName: String?,
@SerializedName("tileId")
var tileId: Long
)

View File

@@ -0,0 +1,11 @@
package com.mogo.eagle.core.function.v2x.road
import io.reactivex.Observable
import retrofit2.http.GET
import retrofit2.http.Query
interface V2XEventServiceApi {
@GET("/eagleEye-mis/config/queryV2NInformation")
fun queryAllV2XEventsByLineId(@Query("lineId") lineId: String, @Query("sn") sn: String): Observable<V2XEventResult>
}

View File

@@ -0,0 +1,59 @@
syntax = "proto2";
package roadwork;
message RW_PB {
required Roadwork_PB roadwork =1;
optional Header header = 2;
}
message Roadwork_PB{
optional string id = 1; // 对应id
required int32 score = 2; // 置信度
required int64 detect_time = 3; // 发送时间
required int32 poi_type = 4; // poi 类型
optional int32 type = 5; // 事件类型
required Center_PB center = 6; // 中心点坐标
repeated GPSPoint_PB polygon = 7; // 多边形范围
repeated Road_PB road = 8; // 车道集合信息
}
message GPSPoint_PB {
required double lat = 1; // 纬度
required double lon = 2; // 经度
optional double hgt = 3; // 高程
}
message Road_PB{
required string road_id = 1; // 路段id
required string lane_no = 2; // 车道号
required string tile_id = 3; // 瓦片id
required int32 bearing = 4; // 方向角正北是0度 顺时针
}
message Center_PB{
required Road_PB road = 1; // 道路信息
required GPSPoint_PB point = 2; // 坐标
}
// header
message Time {
optional uint32 sec = 1; // 秒
optional uint32 nsec = 2; // 纳秒
}
message Header {
// Sequence number for each message. Each module maintains its own counter for
// sequence_num, always starting from 1 on boot.
optional uint32 seq = 1;
// Message publishing time in seconds.
optional Time stamp = 2;
// frame id
optional string frame_id = 3;
// Module name.
optional string module_name = 4;
}