Merge branch 'dev_robotaxi-d-app-module_2132_221223_2.13.2' of gitlab.zhidaoauto.com:zhjt/AndroidApp/MoGoEagleEye into dev_robotaxi-d-app-module_2132_221223_2.13.2

This commit is contained in:
lixiaopeng
2023-01-10 18:25:07 +08:00
58 changed files with 2767 additions and 146 deletions

View File

@@ -56,8 +56,8 @@ class SceneManager {
sceneModuleTAG.map[DEVA] = SceneModule(false, M_DEVA)
sceneModuleTAG.map[HMI] = SceneModule(false, M_HMI)
sceneModuleTAG.map[OBU] = SceneModule(false, M_OBU)
sceneModuleTAG.map[V2X] = SceneModule(false, M_V2X)
sceneModuleTAG.map[MAP] = SceneModule(false, M_MAP)
sceneModuleTAG.map[V2X] = SceneModule(true, M_V2X)
sceneModuleTAG.map[MAP] = SceneModule(true, M_MAP)
sceneModuleTAG.map[ROUTE] = SceneModule(true, M_OLD_ROUTE)
sceneModuleTAG.map[NET] = SceneModule(true, M_NETWORK)
sceneModuleTAG.map[BUS] = SceneModule(true, M_BUS)

View File

@@ -3,16 +3,20 @@ package com.zhjt.dispatch;
import android.app.Dialog;
import android.content.Context;
import android.os.Build;
import android.view.Gravity;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.mogo.eagle.core.data.dispatch.DispatchAdasAutoPilotLocReceiverBean;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
public abstract class DispatchBaseDialog extends Dialog {
public DispatchBaseDialog(@NonNull Context context) {
super(context,R.style.Base_AlertDialog_AppCompat);
super(context,R.style.BaseFloatDialogStyle);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
} else {
@@ -27,4 +31,22 @@ public abstract class DispatchBaseDialog extends Dialog {
public abstract void showDialog(DispatchAdasAutoPilotLocReceiverBean dispatchContent);
@Override
public void show() {
super.show();
setWindowSize();
}
private void setWindowSize(){
WindowManager.LayoutParams attributes = getWindow().getAttributes();
attributes.width = ViewGroup.LayoutParams.MATCH_PARENT;
attributes.height = ViewGroup.LayoutParams.MATCH_PARENT;
FrameLayout content = (FrameLayout)findViewById(android.R.id.content);
if(content!=null){
ViewGroup rootView = (ViewGroup) content.getChildAt(0);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) rootView.getLayoutParams();
layoutParams.gravity = Gravity.CENTER;
rootView.setLayoutParams(layoutParams);
}
getWindow().setAttributes(attributes);
}
}

View File

@@ -2,4 +2,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.eagle.core.function.map">
<application>
<receiver android:name="com.mogo.eagle.core.function.business.ai.AiCloudRangeBroadcastReceiver">
<intent-filter>
<action android:name="com.map.aiCloud.notification" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -1,38 +0,0 @@
package com.mogo.eagle.core.function.business.ai
import android.content.Context
import com.mogo.cloud.socket.entity.SocketDownData
import com.mogo.commons.debug.DebugConfig
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.realtime.api.MoGoAiCloudRealTime
import com.mogo.realtime.socket.IMogoCloudOnMsgListener
class AiCloudIdentifyData{
companion object{
private const val TAG = "AiCloudIdentifyData"
@JvmStatic
val aiCloudIdentifyData by lazy(LazyThreadSafetyMode.SYNCHRONIZED){
AiCloudIdentifyData()
}
}
fun init(mContext:Context){
//todo emArrow
MoGoAiCloudRealTime.startRealTime(mContext, DebugConfig.getSocketAppId())
MoGoAiCloudRealTime.registerOnMsgListener(object :IMogoCloudOnMsgListener {
override fun onMsgSend(id: Long) {
}
override fun onMsgReceived(mogoSnapshotSetData: SocketDownData.LauncherSnapshotProto?) {
mogoSnapshotSetData?.let {
CallerLogger.d(TAG,"mogoSnapshotSetData : $mogoSnapshotSetData")
}
}
})
}
}

View File

@@ -0,0 +1,83 @@
package com.mogo.eagle.core.function.business.ai
import android.content.Context
import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
import com.mogo.cloud.socket.SocketManager
import com.mogo.cloud.socket.entity.SocketDownData.SocketDownDataProto
import com.mogo.eagle.core.function.business.ai.net.AiCloudIdentifyNetWorkModel
import com.mogo.eagle.core.function.business.identify.MapIdentifySubscriber
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_MAP
import com.mogo.map.listener.IMogoMapListener
import com.mogo.map.uicontroller.VisualAngleMode
import com.mogo.module.common.MogoApisHandler
import com.mogo.realtime.constant.RealTimeConstant
class AiCloudIdentifyDataManager : IMogoMapListener {
companion object {
private const val TAG = "AiCloudIdentifyData"
var START_METRE = 140
var END_METRE = 2000
@JvmStatic
val aiCloudIdentifyDataManager by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
AiCloudIdentifyDataManager()
}
}
private val aiCloudIdentifyNetWorkModel = AiCloudIdentifyNetWorkModel()
private var showAiCloud = false
fun init(mContext: Context) {
MogoApisHandler.getInstance().apis.registerCenterApi.registerMogoMapListener(TAG, this)
SocketManager.getInstance()
.registerOnMessageListener(
RealTimeConstant.LOW_FREQUENCY_CHANNEL_ID,
object : IMogoCloudSocketOnMessageListener<SocketDownDataProto> {
override fun target(msgType: Int): Class<SocketDownDataProto> {
return SocketDownDataProto::class.java
}
override fun onMsgReceived(msgType: Int, obj: SocketDownDataProto?) {
CallerLogger.d("$M_MAP$TAG", "SocketDownDataProto obj : $obj")
obj?.let {
obj.data?.let {
if (showAiCloud) {
if (it.allListList == null || it.allListList.size == 0) {
MapIdentifySubscriber.instance.clearAiCloudRoma()
return
}
MapIdentifySubscriber.instance.renderAiCloudResult(it.allListList)
}
}
}
}
})
requestRangeOfIdentify()
}
fun requestRangeOfIdentify() {
aiCloudIdentifyNetWorkModel.requestIdentifyRange({
CallerLogger.d(
M_MAP + TAG,
"requestIdentifyRange ok startRange:$START_METRE, endRange:$END_METRE"
)
}, {
CallerLogger.d(
M_MAP + TAG,
"requestIdentifyRange error : $it , startRange:$START_METRE, endRange:$END_METRE"
)
})
}
override fun onMapVisualAngleChanged(visualAngleMode: VisualAngleMode) {
super.onMapVisualAngleChanged(visualAngleMode)
showAiCloud = when {
visualAngleMode.isLongSight -> true
else -> false
}
}
}

View File

@@ -0,0 +1,30 @@
package com.mogo.eagle.core.function.business.ai
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager.Companion.END_METRE
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager.Companion.START_METRE
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager.Companion.aiCloudIdentifyDataManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_MAP
class AiCloudRangeBroadcastReceiver : BroadcastReceiver() {
companion object {
private const val TAG = "AiCloudRangeBroadcastReceiver"
private const val START_RANGE = "startRange"
private const val END_RANGE = "endRange"
// adb shell am broadcast -a com.map.aiCloud.notification --ei startRange 140 --ei endRange 2000
}
override fun onReceive(context: Context, intent: Intent) {
val startRange = intent.getIntExtra(START_RANGE, START_METRE)
val endRange = intent.getIntExtra(END_RANGE, END_METRE)
START_METRE = startRange
END_METRE = endRange
CallerLogger.d("$M_MAP$TAG", "startRange:$startRange, endRange:$endRange")
aiCloudIdentifyDataManager.requestRangeOfIdentify()
}
}

View File

@@ -0,0 +1,63 @@
package com.mogo.eagle.core.function.business.ai.net
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.debug.DebugConfig
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager.Companion.END_METRE
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager.Companion.START_METRE
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.network.apiCall
import com.mogo.eagle.core.network.request
import com.zhjt.service_biz.FuncConfig
class AiCloudIdentifyNetWorkModel {
companion object {
val aiCloudIdentifyNetWorkModel by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
AiCloudIdentifyNetWorkModel()
}
}
private fun getHost(): String {
var host = "https://dzt-city.zhidaozhixing.com"
when (DebugConfig.getNetMode()) {
DebugConfig.NET_MODE_DEV,
DebugConfig.NET_MODE_QA -> host = "https://dzt-qa-city.zhidaozhixing.com"
}
return host
}
private fun getNetWorkApi(baseUrl: String = getHost()): IAiCloudIdentifyApiService {
return MoGoRetrofitFactory.getInstanceNoCallAdapter(baseUrl)
.create(IAiCloudIdentifyApiService::class.java)
}
fun requestIdentifyRange(
onSuccess: (() -> Unit),
onError: ((String) -> Unit)
) {
request<BaseResponse<Any>> {
val map = mutableMapOf<String, Any>()
start {
map["sn"] = MoGoAiCloudClientConfig.getInstance().sn
map["status"] = true
map["startMetre"] = START_METRE
map["endMetre"] = END_METRE
map["type"] = 1
}
loader {
apiCall {
getNetWorkApi().identifyRange(map)
}
}
onSuccess {
onSuccess.invoke()
}
onError {
it.message?.let { errorMsg ->
onError.invoke(errorMsg)
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
package com.mogo.eagle.core.function.business.ai.net
import com.mogo.eagle.core.data.BaseResponse
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
interface IAiCloudIdentifyApiService {
@Headers("Content-type:application/json;charset=UTF-8")
@POST("yycp-c-v2x-service/dataFusion/remoteDrivingSet")
suspend fun identifyRange(@Body map: MutableMap<String, Any>): BaseResponse<Any>
}

View File

@@ -1,20 +1,37 @@
package com.mogo.eagle.core.function.business.identify
import com.mogo.cloud.socket.entity.SocketDownData
import com.mogo.eagle.core.data.traffic.TrafficData
import mogo.telematics.pad.MessagePad
import mogo.telematics.pad.MessagePad.TrackedObject
interface Identify {
fun renderAdasRecognizedResult(resultList: List<TrackedObject>?)
fun renderAdasRecognizedResult(resultList: List<TrackedObject>?){
fun renderPlanningWarningObj(planningObjects: List<MessagePad.PlanningObject>?)
}
fun renderAiCloudResult(resultList: List<SocketDownData.CloudRoadDataProto>){
}
fun renderPlanningWarningObj(planningObjects: List<MessagePad.PlanningObject>?){
}
fun renderOBUWarningObj(exist: Boolean, obuTrafficData: TrafficData) {
}
fun clearOldMarker()
fun clearOldMarker(){
fun getIdentifyObj(uuid: String):TrackedObject?
}
fun clearAiMarker(){
}
fun getIdentifyObj(uuid: String):TrackedObject?{
return null
}
}

View File

@@ -0,0 +1,102 @@
package com.mogo.eagle.core.function.business.identify
import android.annotation.SuppressLint
import androidx.collection.ArraySet
import com.mogo.cloud.socket.entity.SocketDownData
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.module.status.MogoStatusManager
import com.mogo.eagle.core.data.traffic.TrafficData
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.w
import com.mogo.map.MogoMarkerManager
import mogo.telematics.pad.MessagePad.PlanningObject
import mogo.telematics.pad.MessagePad.TrackedObject
import java.util.concurrent.ConcurrentHashMap
class IdentifyAiCloudDataDrawer : Identify {
companion object {
private const val TAG = "IdentifyDataDrawer"
}
/**
* 上一帧数据的缓存
*/
private val mMarkersCaches = ConcurrentHashMap<String, SocketDownData.CloudRoadDataProto>()
/**
* 记录每次实际绘制的交通元素UUID
*/
@SuppressLint("NewApi")
private val trafficDataUuidList = ArraySet<String>()
/**
* 过滤后的数据集合
*/
@SuppressLint("NewApi")
private val mFilterTrafficData = HashMap<String, SocketDownData.CloudRoadDataProto>()
@SuppressLint("NewApi")
override fun renderAiCloudResult(resultList: List<SocketDownData.CloudRoadDataProto>) {
if (resultList.isEmpty()) {
clearOldMarker()
w(TAG, "感知数据为空无需渲染……")
return
}
if (!MogoStatusManager.getInstance().isVrMode) {
clearOldMarker()
w(TAG, "渲染 adas 识别的数据 当前不是VR模式")
return
}
//清除缓存
for (data in resultList) {
if (trafficDataUuidList.size > 0 && trafficDataUuidList.contains("" + data.uuid)) {
trafficDataUuidList.remove("" + data.uuid)
}
}
//清除缓存,删除marker
val it: MutableIterator<*> = trafficDataUuidList.iterator()
while (it.hasNext()) {
val key = it.next() as String
it.remove()
mMarkersCaches.remove(key)
MogoMarkerManager.getInstance(AbsMogoApplication.getApp())
.removeMarker(key)
}
val filterList = filterTrafficData(resultList)
if (filterList.size > 0) {
// 绘制新数据
MogoMarkerManager.getInstance(AbsMogoApplication.getApp())
.updateBatchAiMarkerPosition(filterList)
}
}
/**
* 数据过滤器
*
* @return 过滤后的数据集合
*/
@SuppressLint("NewApi")
private fun filterTrafficData(trafficData: List<SocketDownData.CloudRoadDataProto>): HashMap<String, SocketDownData.CloudRoadDataProto> {
mFilterTrafficData.clear()
trafficDataUuidList.clear()
for (data in trafficData) {
val uuid = "" + data.uuid
mMarkersCaches[uuid] = data
trafficDataUuidList.add(uuid)
}
return mFilterTrafficData
}
@SuppressLint("NewApi")
override fun clearAiMarker() {
for (uuid in trafficDataUuidList) {
MogoMarkerManager.getInstance(AbsMogoApplication.getApp())
.removeMarker(uuid)
}
trafficDataUuidList.clear()
}
}

View File

@@ -2,6 +2,7 @@ package com.mogo.eagle.core.function.business.identify
import android.os.Handler
import android.os.Message
import com.mogo.cloud.socket.entity.SocketDownData
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.traffic.TrafficData
import com.mogo.eagle.core.function.api.obu.IMoGoObuStatusListener
@@ -22,7 +23,12 @@ object IdentifyFactory : Identify, IMoGoObuStatusListener {
internal val beautifyDataDrawer = IdentifyBeautifyDataDrawer()
}
object AiIdentify {
internal val aiCloudDataDrawer = IdentifyAiCloudDataDrawer()
}
private var identify: Identify? = null
private var aiCloudIdentify: Identify? = null
init {
identify = if (FunctionBuildConfig.isBeautyMode) {
@@ -30,14 +36,17 @@ object IdentifyFactory : Identify, IMoGoObuStatusListener {
} else {
DriverIdentify.originDataDrawer
}
aiCloudIdentify = AiIdentify.aiCloudDataDrawer
CallerObuListenerManager.addListener(TAG, this)
}
private const val MSG_DATA_TRACK = 0
private const val MSG_DATA_WARNING = 1
private const val MSG_DATA_OBU_WARNING_UPDATE = 2
private const val MSG_DATA_OBU_WARNING_REMOVE = 3
private const val MSG_DATA_CLEAR = 4
private const val MSG_DATA_AI_TRACK = 1
private const val MSG_DATA_WARNING = 2
private const val MSG_DATA_OBU_WARNING_UPDATE = 3
private const val MSG_DATA_OBU_WARNING_REMOVE = 4
private const val MSG_DATA_CLEAR = 5
private const val MSG_DATA_AI_CLEAR = 6
// 维护一个线程定时轮询数据进行地图绘制
private val mDrawerHandler: Handler =
@@ -63,6 +72,11 @@ object IdentifyFactory : Identify, IMoGoObuStatusListener {
identify!!.renderAdasRecognizedResult(msg.obj as List<TrackedObject>?)
}
}
MSG_DATA_AI_TRACK -> {
if (msg.obj is List<*>) {
aiCloudIdentify!!.renderAiCloudResult(msg.obj as List<SocketDownData.CloudRoadDataProto>)
}
}
MSG_DATA_WARNING -> {
if (msg.obj is List<*>) {
identify!!.renderPlanningWarningObj(msg.obj as List<MessagePad.PlanningObject>?)
@@ -81,6 +95,9 @@ object IdentifyFactory : Identify, IMoGoObuStatusListener {
MSG_DATA_CLEAR -> {
identify!!.clearOldMarker()
}
MSG_DATA_AI_CLEAR -> {
aiCloudIdentify!!.clearAiMarker()
}
}
}
}
@@ -92,6 +109,13 @@ object IdentifyFactory : Identify, IMoGoObuStatusListener {
mDrawerHandler.sendMessage(message)
}
override fun renderAiCloudResult(resultList: List<SocketDownData.CloudRoadDataProto>) {
val message = Message.obtain()
message.what = MSG_DATA_AI_TRACK
message.obj = resultList
mDrawerHandler.sendMessage(message)
}
override fun renderPlanningWarningObj(planningObjects: List<MessagePad.PlanningObject>?) {
val message = Message.obtain()
message.what = MSG_DATA_WARNING
@@ -105,6 +129,12 @@ object IdentifyFactory : Identify, IMoGoObuStatusListener {
mDrawerHandler.sendMessage(message)
}
override fun clearAiMarker() {
val message = Message.obtain()
message.what = MSG_DATA_AI_CLEAR
mDrawerHandler.sendMessage(message)
}
override fun getIdentifyObj(uuid: String): TrackedObject? {
return identify?.getIdentifyObj(uuid)
}

View File

@@ -2,11 +2,13 @@ package com.mogo.eagle.core.function.business.identify
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.cloud.socket.entity.SocketDownData
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_IDENTIFY
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.base.IMoGoSubscriber
import com.mogo.eagle.core.function.api.map.marker.IMoGoIdentifyListener
import com.mogo.eagle.core.function.business.identify.IdentifyFactory.AiIdentify.aiCloudDataDrawer
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import mogo.telematics.pad.MessagePad
@@ -19,7 +21,7 @@ import mogo.telematics.pad.MessagePad.TrackedObject
* @author donghongyu
*/
@Route(path = PATH_IDENTIFY)
class MapIdentifySubscriber private constructor() :IMoGoIdentifyListener, IMoGoSubscriber,
class MapIdentifySubscriber private constructor() : IMoGoIdentifyListener, IMoGoSubscriber,
IMoGoAutopilotIdentifyListener {
private val TAG = "MapIdentifySubscriber"
@@ -41,7 +43,6 @@ class MapIdentifySubscriber private constructor() :IMoGoIdentifyListener, IMoGoS
override fun onDestroy() {
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
}
override fun onAutopilotIdentifyDataUpdate(trafficData: List<TrackedObject>?) {
@@ -58,6 +59,26 @@ class MapIdentifySubscriber private constructor() :IMoGoIdentifyListener, IMoGoS
}
}
fun renderAiCloudResult(cloudData: List<SocketDownData.CloudRoadDataProto>) {
try {
if (FunctionBuildConfig.isDrawIdentifyData) {
ThreadUtils.getSinglePool().execute {
aiCloudDataDrawer.renderAiCloudResult(cloudData)
// IdentifyFactory.renderAiCloudResult(cloudData)
}
} else {
clearAiCloudRoma()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun clearAiCloudRoma() {
aiCloudDataDrawer.clearAiMarker()
// IdentifyFactory.clearAiMarker()
}
override fun onAutopilotIdentifyPlanningObj(planningObjects: List<MessagePad.PlanningObject>?) {
try {
if (FunctionBuildConfig.isDrawIdentifyData && FunctionBuildConfig.debugTrackerProvider == 0) {

View File

@@ -16,7 +16,7 @@ import com.mogo.eagle.core.data.map.CenterLine;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningListener;
import com.mogo.eagle.core.function.api.map.hd.IMoGoMapFragmentProvider;
import com.mogo.eagle.core.function.api.setting.IMoGoSkinModeChangeListener;
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyData;
import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager;
import com.mogo.eagle.core.function.business.identify.MapIdentifySubscriber;
import com.mogo.eagle.core.function.business.MapPointCloudSubscriber;
import com.mogo.eagle.core.function.business.routeoverlay.MogoRouteOverlayManager;
@@ -193,7 +193,7 @@ public class MapFragment extends MvpFragment<MapView, MapPresenter>
MapIdentifySubscriber.Companion.getInstance();
MogoRouteOverlayManager.getInstance().init();
MapPointCloudSubscriber.Companion.getInstance();
AiCloudIdentifyData.Companion.getAiCloudIdentifyData().init(AbsMogoApplication.getApp());
AiCloudIdentifyDataManager.Companion.getAiCloudIdentifyDataManager().init(AbsMogoApplication.getApp());
}
private void queryInfStructure() {

View File

@@ -141,12 +141,12 @@ public class SmallMapFragment extends BaseFragment
@Override
public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autoPilotStatusInfo) {
int tempStatus = autoPilotStatusInfo.getPilotmode();
CallerLogger.INSTANCE.i(M_MAP + TAG, "onAutopilotStatusResponse:"+tempStatus+" autoPilotStatus:"+autoPilotStatus);
// CallerLogger.INSTANCE.i(M_MAP + TAG, "onAutopilotStatusResponse:"+tempStatus+" autoPilotStatus:"+autoPilotStatus);
if (tempStatus != 1) {
CallerLogger.INSTANCE.i(M_MAP + TAG, "onAutopilotStatusResponse:"+tempStatus+" clearPolyline");
// CallerLogger.INSTANCE.i(M_MAP + TAG, "onAutopilotStatusResponse:"+tempStatus+" clearPolyline");
clearPolyline();
}else if (tempStatus == 1 && autoPilotStatus == 0){
CallerLogger.INSTANCE.i(M_MAP + TAG, "onAutopilotStatusResponse:getGlobalPath");
// CallerLogger.INSTANCE.i(M_MAP + TAG, "onAutopilotStatusResponse:getGlobalPath");
CallerAutoPilotManager.INSTANCE.getGlobalPath();
}
autoPilotStatus = tempStatus;

View File

@@ -4,6 +4,7 @@ plugins {
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'com.alibaba.arouter'
id 'com.google.protobuf'
}
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
@@ -35,6 +36,19 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
protobuf {
protoc {
artifact = rootProject.ext.dependencies.protoc
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {}
}
}
}
}
}
dependencies {
@@ -50,7 +64,8 @@ dependencies {
implementation rootProject.ext.dependencies.rxandroid
implementation rootProject.ext.dependencies.flexbox
kapt rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.mogo_v2x
implementation rootProject.ext.dependencies.protobuf_java
implementation rootProject.ext.dependencies.protobuf_java_util
implementation rootProject.ext.dependencies.mogoaicloudtrafficlive
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
implementation rootProject.ext.dependencies.mogocommons

View File

@@ -5,7 +5,6 @@ import android.content.*
import android.os.*
import android.provider.Settings.System
import android.util.*
import androidx.core.util.Pair
import androidx.localbroadcastmanager.content.*
import com.mogo.cloud.commons.utils.*
import com.mogo.cloud.passport.*
@@ -31,11 +30,9 @@ import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.data.traffic.*
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningActionsListener
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.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotPlanningActionsListenerManager
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
@@ -53,10 +50,17 @@ 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.scenario.scene.airoad.*
import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker.Marker
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.voice.*
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.network.utils.*
import com.mogo.eagle.core.utilcode.mogo.logger.*
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_V2X
@@ -66,11 +70,6 @@ import com.mogo.eagle.core.utilcode.util.TimeUtils
import com.mogo.eagle.core.utilcode.util.Utils
import com.mogo.map.listener.*
import com.mogo.map.marker.*
import com.mogo.v2x.*
import com.mogo.v2x.callback.*
import com.mogo.v2x.config.*
import com.mogo.v2x.data.*
import com.mogo.v2x.event.*
import com.shuyu.gsyvideoplayer.*
import com.shuyu.gsyvideoplayer.cache.*
import com.shuyu.gsyvideoplayer.model.*
@@ -80,7 +79,6 @@ import com.zhjt.service.chain.*
import kotlinx.coroutines.*
import kotlinx.coroutines.android.*
import mogo.telematics.pad.MessagePad
import roadwork.Road.RW_PB
import tv.danmaku.ijk.media.player.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*

View File

@@ -5,7 +5,7 @@ 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.IMogoMarkerClickListener;
import com.mogo.v2x.data.V2XMarkerCardResult;
import com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerCardResult;
import java.util.concurrent.CopyOnWriteArrayList;

View File

@@ -33,10 +33,10 @@ import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.map.marker.IMogoMarkerManager;
import com.mogo.map.marker.MogoMarkerOptions;
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;

View File

@@ -40,10 +40,6 @@ object AiRoadMarker {
private const val TAG = "AiRoadMarker"
private val queue by lazy { LinkedBlockingQueue<Marker>() }
private val pool by lazy { Executors.newFixedThreadPool(2) }
private val marker by lazy { AtomicReference<Marker>() }
private val carLocation by lazy { AtomicReference<Triple<Double, Double, Double>>() }
@@ -127,49 +123,6 @@ object AiRoadMarker {
}
}
})
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
}
}
}
}
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 {
@@ -219,26 +172,9 @@ object AiRoadMarker {
CallerMapRoadListenerManager.unRegisterRoadListener(TAG)
CallMarkersClearManager.removeAllMarkersClearListener(TAG)
CallerMapLocationListenerManager.removeListener(TAG, true)
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

View File

@@ -22,7 +22,7 @@ import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
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.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;

View File

@@ -25,8 +25,8 @@ import com.mogo.map.MogoMarkerManager;
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

@@ -7,8 +7,12 @@ import com.mogo.eagle.core.data.map.entity.MarkerLocation
import com.mogo.eagle.core.data.map.entity.MarkerUserInfo
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.MarkerExploreWayItem
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 com.mogo.eagle.core.function.v2x.internal.data.V2XMarkerUserInfo
import com.mogo.map.MogoMap
import com.mogo.v2x.data.*
import mogo.telematics.pad.MessagePad
import roadwork.Road

View File

@@ -0,0 +1,256 @@
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.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.socket.V2XMessageListener_503000
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))
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,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,68 @@
package com.mogo.eagle.core.function.v2x.internal.event
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.V2XMarkerResponse
import com.mogo.eagle.core.function.v2x.internal.data.V2XOptimalRoute
import com.mogo.eagle.core.function.v2x.internal.data.V2XWarningTarget
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)"
}
}
}

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,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;
}