[dev_arch_opt_3.0][merge]合并2.13.2分支代码

This commit is contained in:
renwj
2023-01-29 17:58:41 +08:00
parent 2a9111c996
commit 7ae3e13fab
68 changed files with 3446 additions and 963 deletions

View File

@@ -1,26 +1,19 @@
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.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
@@ -28,64 +21,55 @@ import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
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.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.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.disposables.Disposable
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 +79,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 +102,9 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
}.build())
V2XManager.start()
}
registerListener()
V2XManager.forceRefresh()
MoGoAiCloudClient.getInstance().addTokenCallbacks(this)
// 注册广播接收场景弹窗使用的
SceneBroadcastReceiver.register(context)
}
@@ -139,6 +125,7 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
private fun unRegisterListener() {
V2XManager.removeCallback(this)
CallerMapLocationListenerManager.removeListener(TAG, false)
mogoMarkersHandler.unregisterMarkerClickListener(CARD_TYPE_ROAD_CONDITION)
}
@@ -199,6 +186,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 +238,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 +296,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 +369,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 +489,65 @@ 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) {
/*
TODO fufeng 先注掉,编译通过
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 +565,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,179 @@
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 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 ->
/*
TODO zhongchao 先注掉,编译通过
val p = MogoMap.getInstance().mogoMap.switchLonLat(
this.roadwork?.center?.point?.lon ?: 0.0,
this.roadwork?.center?.point?.lat ?: 0.0
)
l4.lon = p.lon
l4.lat = p.lat
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 ->
/*
TODO zhongchao 先注掉,编译通过
val p = MogoMap.getInstance().mogoMap.switchLonLat(
this.center?.lon ?: 0.0,
this.center?.lat ?: 0.0
)
l4.lon = p.lon
l4.lat = p.lat
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 ->
/*
TODO zhongchao 先注掉,编译通过
val p =
MogoMap.getInstance().mogoMap.switchLonLat(this.longitude, this.latitude)
l4.lon = p.lon
l4.lat = p.lat
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,815 @@
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
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)"
}
}
@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,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;
}