diff --git a/.gitignore b/.gitignore
index c453264..b3f6ed4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +1,9 @@
*.iml
.gradle
/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
-/.idea/modules/
+.idea/
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 88ea3aa..0000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,122 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xmlns:android
-
- ^$
-
-
-
-
-
-
-
-
- xmlns:.*
-
- ^$
-
-
- BY_NAME
-
-
-
-
-
-
- .*:id
-
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- .*:name
-
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- name
-
- ^$
-
-
-
-
-
-
-
-
- style
-
- ^$
-
-
-
-
-
-
-
-
- .*
-
- ^$
-
-
- BY_NAME
-
-
-
-
-
-
- .*
-
- http://schemas.android.com/apk/res/android
-
-
- ANDROID_ATTRIBUTE_ORDER
-
-
-
-
-
-
- .*
-
- .*
-
-
- BY_NAME
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index 79ee123..0000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index fb7f4a8..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/dictionaries/zhongchao.xml b/.idea/dictionaries/zhongchao.xml
deleted file mode 100644
index 6d1b40d..0000000
--- a/.idea/dictionaries/zhongchao.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- amap
- coor
- designative
- mogo
- tongchenfei
-
-
-
\ No newline at end of file
diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
deleted file mode 100644
index b382006..0000000
--- a/.idea/git_toolbox_prj.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 5da1e76..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index bac8f7b..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
deleted file mode 100644
index bb43490..0000000
--- a/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index cd31019..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 3397f87..8744c96 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -62,11 +62,13 @@ dependencies {
implementation "com.mogo.cloud:tanlu:${MOGO_TANLU_VERSION}"
implementation "com.mogo.cloud:realtime:${MOGO_REALTIME_VERSION}"
implementation "com.mogo.cloud:trafficlive:${MOGO_TRAFFICLIVE_VERSION}"
+ implementation "com.mogo.v2x:v2x:${MOGO_V2X_VERSION}"
} else {
implementation project(":foudations:mogo-location")
implementation project(":modules:mogo-tanlu")
implementation project(":modules:mogo-realtime")
implementation project(":modules:mogo-trafficlive")
+ implementation project(":foudations:mogo-v2x")
}
annotationProcessor 'com.elegant.spi:compiler:1.0.3' //编译时库
diff --git a/app/src/main/java/com/mogo/cloud/MainActivity.java b/app/src/main/java/com/mogo/cloud/MainActivity.java
index cdca13b..d8be4fe 100644
--- a/app/src/main/java/com/mogo/cloud/MainActivity.java
+++ b/app/src/main/java/com/mogo/cloud/MainActivity.java
@@ -4,18 +4,27 @@ import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.SurfaceView;
+import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.elegant.log.simplelog.Logger;
import com.mogo.cloud.network.NetworkActivity;
import com.mogo.cloud.passport.IMoGoTokenCallback;
import com.mogo.cloud.passport.MoGoAiCloudClient;
+import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import com.mogo.cloud.trafficlive.api.ITrafficCarLiveCallBack;
import com.mogo.cloud.trafficlive.api.ITrafficIntersectionLiveCallBack;
import com.mogo.cloud.trafficlive.api.MoGoAiCloudTrafficLive;
+import com.mogo.v2x.V2XManager;
+import com.mogo.v2x.callback.IV2XCallback;
+import com.mogo.v2x.config.V2XConfig;
+import com.mogo.v2x.event.V2XEvent;
+
+import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
@@ -32,6 +41,9 @@ public class MainActivity extends AppCompatActivity {
private Button btnJumpLivePlay;
private Button btnRequestXINGLive;
private Button btnRequestCarLive;
+ private Button btnV2XFunctionTest;
+
+ private boolean v2xHasBeenInitialized = false;
private SurfaceView surfacePreviewView;
private TextView tvSn;
@@ -192,9 +204,62 @@ public class MainActivity extends AppCompatActivity {
});
});
+ //V2X功能测试
+ btnV2XFunctionTest = findViewById(R.id.btnV2XFunctionTest);
+ btnV2XFunctionTest.setOnClickListener(v -> {
+ if (v2xHasBeenInitialized) {
+ return;
+ }
+ v2xHasBeenInitialized = true;
+ V2XConfig.Builder builder = new V2XConfig.Builder();
+ builder.loggable(true)
+ .aiCloudConfig(MoGoAiCloudClientConfig.getInstance())
+ .appId("com.mogo.launcher")
+ .context(v.getContext())
+ .distanceForTriggerRefresh(300)
+ .durationForTriggerRefresh(1, TimeUnit.MINUTES);
+ V2XManager.INSTANCE.init(builder.build());
+ V2XManager.INSTANCE.addCallback(new IV2XCallback() {
+ @Override
+ public void onAck(@NonNull V2XEvent event) {
+ if (event instanceof V2XEvent.ForwardsWarning) {
+ V2XEvent.ForwardsWarning warning = (V2XEvent.ForwardsWarning) event;
+ Logger.d("V2XManager", "forward-warning<->onAck::" + warning.toString());
+ }
+ if (event instanceof V2XEvent.OptimalRoute) {
+ V2XEvent.OptimalRoute route = (V2XEvent.OptimalRoute) event;
+ Logger.d("V2XManager", "route<->onAck::" + route.toString());
+ }
+
+ if (event instanceof V2XEvent.Warning) {
+ V2XEvent.Warning warning = (V2XEvent.Warning) event;
+ Logger.d("V2XManager", "warning<->onAck::" + warning.toString());
+ }
+
+ if (event instanceof V2XEvent.Road) {
+ V2XEvent.Road road = (V2XEvent.Road) event;
+ Logger.d("V2XManager", "road<-->onAck::" + road.toString());
+ }
+
+ if (event instanceof V2XEvent.Marker) {
+ V2XEvent.Marker marker = (V2XEvent.Marker) event;
+ Logger.d("V2XManager", "marker<-->onAck::" + marker.toString());
+ }
+ }
+
+ @Override
+ public void onFail(@NonNull String s) {
+ Logger.d("V2XManager", "onFail::" + s);
+ }
+ });
+ });
+
MoGoAiCloudClient.getInstance().addTokenCallbacks(new IMoGoTokenCallback() {
@Override
public void onTokenGot(String token, String sn) {
+ if (btnV2XFunctionTest.getVisibility() != View.VISIBLE) {
+ btnV2XFunctionTest.setVisibility(View.VISIBLE);
+ }
initPassportInfo();
}
diff --git a/app/src/main/java/com/mogo/cloud/MoGoApplication.java b/app/src/main/java/com/mogo/cloud/MoGoApplication.java
index 5f93c51..aa80399 100644
--- a/app/src/main/java/com/mogo/cloud/MoGoApplication.java
+++ b/app/src/main/java/com/mogo/cloud/MoGoApplication.java
@@ -11,6 +11,7 @@ import com.mogo.cloud.httpdns.MogoHttpDnsClient;
import com.mogo.cloud.httpdns.MogoHttpDnsConfig;
import com.mogo.cloud.httpdns.bean.HttpDnsSimpleLocation;
import com.mogo.cloud.httpdns.listener.IHttpDnsCurrentLocation;
+import com.mogo.cloud.location.LocationManager;
import com.mogo.cloud.passport.IMoGoTokenCallback;
import com.mogo.cloud.passport.MoGoAiCloudClient;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 5ad8b0a..6148872 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -112,6 +112,12 @@
android:text="查看周边可直播车"
android:visibility="visible" />
+
+
+
+
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/V2XManager.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/V2XManager.kt
new file mode 100755
index 0000000..3dfaee2
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/V2XManager.kt
@@ -0,0 +1,157 @@
+package com.mogo.v2x
+
+import android.os.Handler
+import android.os.Looper
+import com.mogo.cloud.location.LocationManager
+import com.mogo.cloud.socket.SocketManager
+import com.mogo.v2x.callback.IV2XCallback
+import com.mogo.v2x.config.V2XConfig
+import com.mogo.v2x.data.V2XMarkerResponse
+import com.mogo.v2x.event.V2XEvent
+import com.mogo.v2x.http.V2XRefreshModel
+import com.mogo.v2x.http.callback.IV2XRefreshCallback
+import com.mogo.v2x.socket.V2XMessageListener_401012
+import com.mogo.v2x.socket.V2XMessageListener_401018
+import com.mogo.v2x.socket.V2XMessageListener_402000
+import com.mogo.v2x.socket.V2XMessageListener_404000
+import com.mogo.v2x.logger.Logger
+import com.mogo.v2x.utils.DistanceUtils
+import java.util.concurrent.CopyOnWriteArrayList
+import java.util.concurrent.atomic.AtomicReference
+
+object V2XManager {
+
+ internal const val TAG = "V2XManager"
+
+ private val config: AtomicReference by lazy {
+ AtomicReference(null)
+ }
+
+ private val cbs by lazy {
+ CopyOnWriteArrayList()
+ }
+
+ private val longitude by lazy {
+ AtomicReference(0.0)
+ }
+
+ private val latitude by lazy {
+ AtomicReference(0.0)
+ }
+
+ private val refreshCallback = object : IV2XRefreshCallback {
+
+ 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 = this@V2XManager.longitude.get(), latitude = this@V2XManager.latitude.get(), refreshCallback)
+ handler.postDelayed(this, config.get().durationForTriggerRefresh)
+ }
+ }
+
+ private val handler by lazy {
+ Handler(Looper.getMainLooper())
+ }
+
+ /**
+ * 根据所配置的参数,初始化V2X相关功能(注: 此方法不要重复调用,非首次调用会抛异常)
+ * @param config 相关配置类
+ */
+ fun init(config: V2XConfig) {
+ if (this.config.get() != null) {
+ throw IllegalStateException("V2XManager has been initialized, don't initialize repeatably.")
+ }
+ val aiCloudConfig = config.aiCloudConfig
+ if (aiCloudConfig.sn?.isBlank() == true) {
+ throw IllegalStateException("please ensure sn must not null.")
+ }
+ if (aiCloudConfig.token?.isBlank() == true) {
+ throw IllegalStateException("please ensure token must not null.")
+ }
+ this.config.set(config)
+ Logger.loggable = config.loggable
+ SocketManager.getInstance().init(config.context)
+ 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))
+ LocationManager.getInstance().init(config.context)
+ LocationManager.getInstance().start()
+ handler.post(refreshTask)
+ }
+
+ /**
+ * 添加相关信息接口回调
+ * @param cb 要添加的回调接口
+ */
+ fun addCallback(cb: IV2XCallback) {
+ if (cbs.contains(cb)) {
+ return
+ }
+ cbs += cb
+ }
+
+ /**
+ * 移除相关信息接口回调
+ * @param cb 要移除的回调接口
+ */
+ fun removeCallback(cb: IV2XCallback) {
+ if (!cbs.contains(cb)) {
+ return
+ }
+ cbs.remove(cb)
+ }
+
+ /**
+ * 当自车位置变量时回调
+ * @param longitude 自车所在精度
+ * @param latitude 自车所在纬度
+ */
+ fun onLocationChanged(longitude: Double, latitude: Double) {
+ if (this.config.get() == null) {
+ return
+ }
+ val oldLon = this.longitude.get()
+ val oldLat = this.latitude.get()
+ var update = false
+ try {
+ if (oldLon == 0.0 || oldLat == 0.0) {
+ handler.removeCallbacks(refreshTask)
+ handler.post(refreshTask)
+ update = true
+ return
+ }
+ if (DistanceUtils.calculateLineDistance(oldLon, oldLat, longitude, latitude) >= this.config.get().distanceForTriggerRefresh) {
+ handler.removeCallbacks(refreshTask)
+ handler.post(refreshTask)
+ update = true
+ }
+ } finally {
+ if (update) {
+ this.latitude.set(latitude)
+ this.longitude.set(longitude)
+ }
+ }
+ }
+
+ /**
+ * 是否已经初始化
+ * @return true: 已初始化过 false: 未初始化
+ */
+ fun hasInit() = this.getConfig() != null
+
+ internal fun getConfig() = this.config.get()
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/callback/IV2XCallback.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/callback/IV2XCallback.kt
new file mode 100644
index 0000000..e04abca
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/callback/IV2XCallback.kt
@@ -0,0 +1,15 @@
+package com.mogo.v2x.callback
+
+import com.mogo.v2x.event.V2XEvent
+
+interface IV2XCallback {
+ /**
+ * 成功-对应事件
+ */
+ fun onAck(event: V2XEvent)
+
+ /**
+ * 失败
+ */
+ fun onFail(msg: String)
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/config/V2XConfig.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/config/V2XConfig.kt
new file mode 100755
index 0000000..4356226
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/config/V2XConfig.kt
@@ -0,0 +1,173 @@
+package com.mogo.v2x.config
+
+import android.content.Context
+import com.mogo.cloud.passport.MoGoAiCloudClientConfig
+import com.mogo.v2x.executor.Executors
+import java.util.concurrent.Executor
+import java.util.concurrent.TimeUnit
+import kotlin.IllegalStateException
+
+/**
+ * V2X相关配置
+ */
+class V2XConfig private constructor(builder: Builder) {
+
+ init {
+ builder.aiCloudConfig ?: throw IllegalStateException("aiCloudConfig must not be null.")
+ }
+
+ /**
+ * 网络请求使用的线程池,IO类型
+ */
+ val executor: Executor by lazy {
+ builder.executor ?: Executors.IO
+ }
+
+ /**
+ * 是否开启日志
+ */
+ val loggable: Boolean by lazy {
+ builder.loggable
+ }
+
+ /**
+ * 应用上下文
+ */
+ val context : Context by lazy {
+ builder.context?.applicationContext ?: throw IllegalStateException("context must not be null.")
+ }
+
+ /**
+ * 公共参数
+ */
+ val staticParams by lazy {
+ builder.staticParams ?: HashMap()
+ }
+
+ /**
+ * 云平台设置
+ */
+ val aiCloudConfig by lazy {
+ builder.aiCloudConfig ?: throw IllegalStateException("aiCloudConfig must not be null.")
+ }
+
+ /**
+ * 应用ID(一般为应用包名)
+ */
+ val appId by lazy {
+ builder.appId ?: throw IllegalStateException("appId must not be null.")
+ }
+
+ /**
+ * 基础Url
+ */
+ val baseUrl by lazy {
+ builder.baseUrl ?: "http://dzt-launcherSnapshot.zhidaozhixing.com"
+ }
+
+ /**
+ * 多长时间请求一次自车周边信息
+ */
+ val durationForTriggerRefresh by lazy {
+ val duration = builder.durationForTriggerRefresh
+ if (duration == null || duration <= 0) TimeUnit.SECONDS.toMillis(60) else duration
+ }
+
+ /**
+ * 自车行驶超过此长度,会刷新自车周边信息
+ */
+ val distanceForTriggerRefresh: Float by lazy {
+ val distance = builder.distanceForTriggerRefresh
+ if (distance == null || distance <= 0) 200f else distance
+ }
+
+ fun newBuilder() = Builder(this)
+
+ class Builder {
+
+ constructor()
+
+ internal constructor(config: V2XConfig) {
+ context = config.context
+ executor = config.executor
+ loggable = config.loggable
+ appId = config.appId
+ baseUrl = config.baseUrl
+ staticParams = config.staticParams
+ aiCloudConfig = config.aiCloudConfig
+ durationForTriggerRefresh = config.durationForTriggerRefresh
+ distanceForTriggerRefresh = config.distanceForTriggerRefresh
+ }
+
+ internal var context: Context? = null
+
+ internal var executor: Executor? = null
+
+ internal var loggable: Boolean = false
+
+ internal var appId: String? = null
+
+ internal var staticParams: Map? = null
+
+ internal var aiCloudConfig: MoGoAiCloudClientConfig? = null
+
+ internal var durationForTriggerRefresh: Long? = null
+
+ internal var baseUrl: String? = null
+
+ internal var distanceForTriggerRefresh: Float? = null
+
+
+ /**
+ * 应用上下文,此参数为必选项,不设置会抛异常
+ */
+ fun context(context: Context) = apply { this.context = context }
+
+ /**
+ * 是否开启日志
+ */
+ fun loggable(loggable: Boolean) = apply { this.loggable = loggable }
+
+ /**
+ * 应用ID(一般取应用包名),此参数是必选项,不设置会抛异常
+ */
+ fun appId(appId: String) = apply { this.appId = appId }
+
+ /**
+ * 公共参数列表
+ */
+ fun staticParams(params: Map) = apply { this.staticParams = params }
+
+ /**
+ * 网络请求线程池,如未设置,会使用内置的
+ */
+ fun executor(executor: Executor): Builder = apply {
+ if (this.executor != null) {
+ throw IllegalArgumentException("io executor has been initialized, don't set repeatedly.")
+ }
+ this.executor = executor
+ }
+
+ /**
+ * 刷新周边信息的时间间隔
+ */
+ fun durationForTriggerRefresh(duration: Long, unit: TimeUnit = TimeUnit.SECONDS) = apply { this.durationForTriggerRefresh = unit.toMillis(duration) }
+
+ /**
+ * 自车走过的距离,超过此距离会刷新周边信息
+ */
+ fun distanceForTriggerRefresh(distance: Float) = apply { this.distanceForTriggerRefresh = distance }
+
+ /**
+ * 云平台配置信息,此参数为必选项,不设置会抛异常
+ */
+ fun aiCloudConfig(config: MoGoAiCloudClientConfig) = apply { this.aiCloudConfig = config }
+
+ /**
+ * 云平台baseUrl
+ */
+ fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl }
+
+ fun build() : V2XConfig = V2XConfig(this)
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XAdvanceWarning.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XAdvanceWarning.kt
new file mode 100644
index 0000000..bbcf8c3
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XAdvanceWarning.kt
@@ -0,0 +1,31 @@
+package com.mogo.v2x.data
+
+import androidx.annotation.Keep
+
+/**
+ * 路口碰撞预警、盲区预警等通用Bean
+ */
+@Keep
+data class V2XAdvanceWarning (
+ var objectId: String,// 物体唯一标识
+ var objectType: Int,// 物体类型 1-人 2-自行车 3-小轿车 4-摩托车 5-红绿灯 6-bus 8-truck 9-路边摄像头
+ var status: Int,// 1.add 2.update 3.delete
+ var typeId: Int,// 首位大类标识 1预警 2规划 3拥堵 4事故
+ var time: Long,
+ var level: Int,// 预警等级
+ var threatLevel: Int,// 危险等级:0保留,1模型原始颜色,2通知--黄,3警告--红
+ var position: V2XLocation,
+ var heading: Double,
+ var speed: Double,
+ var distance: Double,
+ var roadId: String,// 道路id
+ var laneId: String,// 车道id
+ var laneNum: Int,// 车道号:中心线编号为0, 中心线右侧编号为负数,3车道通行Road的车道编号,0,-1,-2,-3
+ var gdLocusList: List,// 线性经纬度轨迹列表(高德)
+ var locusList: List// 轨迹列表(Wgs84坐标系)
+) {
+ 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)"
+ }
+}
+
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XBaseData.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XBaseData.kt
new file mode 100644
index 0000000..920f271
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XBaseData.kt
@@ -0,0 +1,9 @@
+package com.mogo.v2x.data
+
+open class V2XBaseData {
+
+ @JvmField
+ var code = -1
+ @JvmField
+ var msg: String? = null
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XLocation.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XLocation.kt
new file mode 100644
index 0000000..7679fc1
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XLocation.kt
@@ -0,0 +1,10 @@
+package com.mogo.v2x.data
+
+import androidx.annotation.Keep
+
+@Keep
+data class V2XLocation(var lon: Double = 0.0, var lat: Double = 0.0) {
+ override fun toString(): String {
+ return "V2XLocation(lon=$lon, lat=$lat)"
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XMarkerCardResult.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XMarkerCardResult.kt
new file mode 100644
index 0000000..e171658
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XMarkerCardResult.kt
@@ -0,0 +1,355 @@
+package com.mogo.v2x.data
+
+import androidx.annotation.Keep
+import java.util.*
+
+@Keep
+class V2XMarkerCardResult: V2XBaseData() {
+ var dataType // 要查询的类型
+ : List? = null
+ var carChat: List? = null
+ var shareMusic: List? = null
+ var noveltyInfo: List? = null
+ var onlineCar: List? = null
+ var exploreWay: List? = null
+ var messageTime: Long = 0
+
+ override fun toString(): String {
+ return "MarkerCardResult(dataType=$dataType, carChat=$carChat, shareMusic=$shareMusic, noveltyInfo=$noveltyInfo, onlineCar=$onlineCar, exploreWay=$exploreWay, messageTime=$messageTime)"
+ }
+}
+
+@Keep
+class V2XMarkerCarChat {
+
+ 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 {
+ var bookInfo: String? = null
+ 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 type: String? = null
+ 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 {
+ var type: String? = null
+ var sn: String? = null
+ var location: V2XMarkerLocation? = null
+ var poiType: String? = null
+ var contentData: ContentData? = null
+
+ @Keep
+ class ContentData {
+ var content: String? = null
+ var iconUrl: String? = null
+ var imgUrl: String? = null
+ var infoId: 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 {
+ var type //卡片类型
+ : String? = null
+ var location //所在位置
+ : V2XMarkerLocation? = null
+ var focus //isFocus":"0-未关注,1-关注
+ : Boolean? = null
+ var userInfo //用户数据
+ : V2XMarkerUserInfo? = null
+ var carInfo //车辆数据
+ : V2XMarkerCarInfo? = null
+ var pois //车辆路线
+ : List? = null
+ var dynamicData //动态数据
+ : V2XMarkerDynamicData? = null
+ var hobbyData //爱好数据集合
+ : V2XMarkerHobbyDatum? = null
+ var activitiesScope //活动范围数据集合
+ : List? = 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 {
+ var infoId: String? = null
+ var type //卡片类型,
+ : String? = null
+
+ var poiType: String? = null
+
+ var sn: String? = null
+ var location //位置信息
+ : V2XMarkerLocation? = null
+ var direction //方位角度
+ = 0
+ var canLive //是否可直播(1为可直播,0不可直播)
+ = false
+ var fileType //是图片还是视频(1视频,0图片)
+ = 0
+ var addr //北京市朝阳区三里屯街道108号
+ : String? = null
+ var generateTime //时间戳
+ : Long = 0L
+ var cityName //:"城市名称",
+ : String? = null
+ var distance //距离
+ = 0.0
+ var userInfo //用户信息
+ : V2XMarkerUserInfo? = null
+ var items //视频地址和图片地址
+ : List? = null
+
+ //上报类型:1-用户上报,2-后台上报 3-三方上报
+ var uploadType: String? = null
+ var isFabulous = false
+
+ // http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=42321443
+ // 1 需要用户判断是否拥堵 进行UGC问答
+ var infoCheckNode = 0
+
+ override fun equals(o: Any?): Boolean {
+ if (this === o) return true
+ if (o == null || javaClass != o.javaClass) return false
+ val that = o as V2XMarkerExploreWay
+ return infoId == that.infoId &&
+ type == that.type &&
+ poiType == that.poiType
+ }
+
+ override fun hashCode(): Int {
+ return Objects.hash(infoId, type, poiType)
+ }
+
+ 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 {
+ private var sn: String? = null
+ var userId: Long = 0
+ private var userName //用户昵称
+ : String? = null
+ private var userHead //用户头像
+ : String? = null
+ private var gender //gender": "男|女|无(也可以0|1|2根据实际库存返回即可)
+ : String? = null
+ private var age // 年龄段,可以为空,与车聊聊一致
+ : Int? = null
+
+ var lastActiveweekAvgscore //末次活跃周驾驶行为平均得分
+ : String? = null
+ var safeLabel //车辆安全标签
+ : String? = null
+ var safeLabelType //1老司机 2安全驾驶 3危险驾驶
+ = 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 {
+ var carBrandLogoUrl: String? = null
+ var carTypeName: String? = null
+ var vehicleType = 0
+ var carLiveInfo: CarLiveInfo? = null
+
+ @Keep
+ class CarLiveInfo {
+ //rtmp视频直播地址rtmp://
+ var videoUrl: String? = null
+
+ //直播频道【直播心跳接口参数】C_1
+ var videoChannel: String? = null
+
+ //直播源sn【直播心跳接口参数】XTCBA90740400625
+ 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 {
+ var coordinates: List<*>? = null
+
+ var angle // 车头角度
+ = 0.0
+ var adcode: String? = null
+
+ override fun toString(): String {
+ return "V2XMarkerCarPois(coordinates=$coordinates, angle=$angle, adcode=$adcode)"
+ }
+}
+
+@Keep
+class V2XMarkerDynamicData {
+ //QQ音乐,懒人听书,乐听头条 2 为书籍听书,3 为新闻,1 为qq音乐
+ var type = 0
+ var mediaId //qq音乐id,书的bookId
+ : 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
+ var bookInfo //懒人听书json串
+ : 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 {
+ var singerTop2 // 最喜欢的两位歌手
+ : List? = null
+ var songTypeTop2 // 最喜欢的两种音乐类型
+ : List? = null
+ var newsType // 最喜欢的资讯类型
+ : List? = null
+ var listenBookTop2 // 最喜欢听的两本书
+ : List? = null
+ var ifSociety // 是否喜爱社交
+ : List? = null
+
+ @Keep
+ class MarkerOnlineTag {
+ var content: String? = null
+ var isCheck = 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 {
+ var content: String? = null
+ var isCheck = false
+
+ override fun toString(): String {
+ return "V2XMarkerActivitiesScope(content=$content, isCheck=$isCheck)"
+ }
+}
+
+/**
+ * 道路情报,V2X预警,地图道路事件POI,违章停车POI等
+ */
+@Keep
+class MarkerExploreWayItem {
+ 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 {
+ var lat //纬度
+ = 0.0
+ var lon //经度
+ = 0.0
+ var angle //车头角度,可以没有
+ = 0.0
+ var address //具体的位置信息
+ : String? = null
+
+ override fun toString(): String {
+ return "V2XMarkerLocation(lat=$lat, lon=$lon, angle=$angle, address=$address)"
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XMarkerResponse.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XMarkerResponse.kt
new file mode 100644
index 0000000..c8eeda2
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XMarkerResponse.kt
@@ -0,0 +1,15 @@
+package com.mogo.v2x.data
+
+import androidx.annotation.Keep
+import com.elegant.network.BaseResp
+
+@Keep
+class V2XMarkerResponse: BaseResp() {
+
+ var result: V2XMarkerCardResult? = null
+ var sign: String? = null
+
+ override fun toString(): String {
+ return "V2XMarkerResponse(result=$result, sign=$sign)"
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XOptimalRoute.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XOptimalRoute.kt
new file mode 100644
index 0000000..26ea2bc
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XOptimalRoute.kt
@@ -0,0 +1,47 @@
+package com.mogo.v2x.data
+
+import androidx.annotation.Keep
+
+/**
+ * 最优路线推荐
+ */
+@Keep
+class V2XOptimalRoute {
+
+ 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? = null
+
+ /**
+ * 高德坐标系Gcj,线性经纬度轨迹列表
+ */
+ var gd_locus_list: List? = null
+}
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XWarningTarget.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XWarningTarget.kt
new file mode 100644
index 0000000..c692291
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/data/V2XWarningTarget.kt
@@ -0,0 +1,112 @@
+package com.mogo.v2x.data
+
+import androidx.annotation.Keep
+
+/**
+ * 预警目标物数据模型
+ */
+@Keep
+class V2XWarningTarget {
+
+ //事件类型 行人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? = 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播报
+ private 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 +
+ '}'
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/event/V2XEvent.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/event/V2XEvent.kt
new file mode 100644
index 0000000..0978bdd
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/event/V2XEvent.kt
@@ -0,0 +1,32 @@
+package com.mogo.v2x.event
+
+import com.mogo.v2x.data.*
+
+sealed class V2XEvent {
+
+ /**
+ * 长链-路口碰撞预警、盲区预警等通用Bean
+ */
+ class ForwardsWarning(val type: Int = 404000, val data: V2XAdvanceWarning): V2XEvent()
+
+ /**
+ * 长链-最优推荐线种
+ */
+ class OptimalRoute(val type: Int = 402000, val data: V2XOptimalRoute): V2XEvent()
+
+ /**
+ * 长链-预警目标物
+ */
+ class Warning(val type: Int = 401018, val data: V2XWarningTarget): V2XEvent()
+
+ /**
+ * 长链-道路事件
+ */
+ class Road(val type: Int = 401012, val data: V2XMarkerCardResult): V2XEvent()
+
+
+ /**
+ * 短链-道路标记事件
+ */
+ class Marker(val data: V2XMarkerResponse): V2XEvent()
+}
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/executor/Executors.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/executor/Executors.kt
new file mode 100755
index 0000000..d676859
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/executor/Executors.kt
@@ -0,0 +1,35 @@
+package com.mogo.v2x.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()}"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/V2XRefreshModel.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/V2XRefreshModel.kt
new file mode 100644
index 0000000..d6434d0
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/V2XRefreshModel.kt
@@ -0,0 +1,72 @@
+package com.mogo.v2x.http
+import com.elegant.network.internal.RetrofitFactory
+import com.elegant.network.utils.GsonUtil
+import com.elegant.network.utils.SignUtil
+import com.elegant.utils.CommonUtils
+import com.mogo.v2x.V2XManager
+import com.mogo.v2x.config.V2XConfig
+import com.mogo.v2x.data.V2XLocation
+import com.mogo.v2x.data.V2XMarkerResponse
+import com.mogo.v2x.http.api.V2XApiService
+import com.mogo.v2x.http.body.V2XRefreshEntity
+import com.mogo.v2x.http.callback.IV2XRefreshCallback
+import com.mogo.v2x.utils.DeviceUtils
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+
+class V2XRefreshModel {
+
+ companion object {
+
+ fun querySnapshot(longitude: Double, latitude: Double, callback: IV2XRefreshCallback?): Disposable {
+ val config = V2XManager.getConfig()
+ return RetrofitFactory.getInstance(config.baseUrl)
+ .create(V2XApiService::class.java)
+ .querySnapshotAsync(buildParams(longitude, latitude, config))
+ .subscribeOn(Schedulers.from(config.executor))
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnError {
+ callback?.onFail(it.message)
+ }
+ .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)
+ }
+ }
+ }
+
+ private fun buildParams(longitude: Double, latitude: Double, config: V2XConfig): Map = mutableMapOf().apply {
+ putAll(config.staticParams.let {
+ val handled = mutableMapOf()
+ 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(longitude, latitude)
+ radius = 1000
+ dataType.add("CARD_TYPE_ROAD_CONDITION")
+ viewPush = true
+ })
+ }
+ }
+
+
+}
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/api/V2XApiService.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/api/V2XApiService.kt
new file mode 100644
index 0000000..a3303f8
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/api/V2XApiService.kt
@@ -0,0 +1,14 @@
+package com.mogo.v2x.http.api
+
+import com.mogo.v2x.data.V2XMarkerResponse
+import io.reactivex.Maybe
+import retrofit2.http.FieldMap
+import retrofit2.http.FormUrlEncoded
+import retrofit2.http.POST
+
+interface V2XApiService {
+
+ @FormUrlEncoded
+ @POST("/yycp-launcherSnapshot/launcherSnapshot/querySnapshotAsync")
+ fun querySnapshotAsync(@FieldMap parameters: Map): Maybe
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/body/V2XRefreshEntity.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/body/V2XRefreshEntity.kt
new file mode 100644
index 0000000..6c91326
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/body/V2XRefreshEntity.kt
@@ -0,0 +1,39 @@
+package com.mogo.v2x.http.body
+
+import androidx.annotation.Keep
+import com.mogo.v2x.data.V2XLocation
+
+/**
+ * 刷新地图信息接口
+ */
+@Keep
+class V2XRefreshEntity {
+
+ @JvmField
+ var dataType: MutableList = 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-401011,false -401001
+ = false
+ @JvmField
+ var onlyRealUser = false
+
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/callback/IV2XRefreshCallback.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/callback/IV2XRefreshCallback.kt
new file mode 100644
index 0000000..f28e3fb
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/http/callback/IV2XRefreshCallback.kt
@@ -0,0 +1,11 @@
+package com.mogo.v2x.http.callback
+
+/**
+ * 刷新回调
+ */
+interface IV2XRefreshCallback {
+
+ fun onSuccess(result: T)
+
+ fun onFail(msg: String?)
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/logger/Logger.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/logger/Logger.kt
new file mode 100644
index 0000000..8394aa2
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/logger/Logger.kt
@@ -0,0 +1,24 @@
+package com.mogo.v2x.logger
+
+import android.util.Log
+
+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
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_401012.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_401012.kt
new file mode 100644
index 0000000..890e4b0
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_401012.kt
@@ -0,0 +1,27 @@
+package com.mogo.v2x.socket
+
+import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
+import com.mogo.v2x.V2XManager
+import com.mogo.v2x.callback.IV2XCallback
+import com.mogo.v2x.data.V2XMarkerCardResult
+import com.mogo.v2x.event.V2XEvent
+import com.mogo.v2x.logger.Logger
+
+internal class V2XMessageListener_401012(val cbs: Iterable?): IMogoCloudSocketOnMessageListener {
+
+ override fun target(msgType: Int): Class = V2XMarkerCardResult::class.java
+
+ override fun onMsgReceived(msgType: Int, data: V2XMarkerCardResult?) {
+ if (msgType != 401012) {
+ return
+ }
+ if (data == null) {
+ Logger.i(V2XManager.TAG, "V2XMessageListener_401012:message is null!")
+ return
+ }
+ Logger.i(V2XManager.TAG, "V2XMessageListener_401012:$data")
+ cbs?.forEach {
+ it.onAck(V2XEvent.Road(data = data))
+ }
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_401018.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_401018.kt
new file mode 100644
index 0000000..5d502db
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_401018.kt
@@ -0,0 +1,27 @@
+package com.mogo.v2x.socket
+
+import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
+import com.mogo.v2x.V2XManager
+import com.mogo.v2x.callback.IV2XCallback
+import com.mogo.v2x.event.V2XEvent
+import com.mogo.v2x.data.V2XWarningTarget
+import com.mogo.v2x.logger.Logger
+
+internal class V2XMessageListener_401018(val cbs: Iterable?): IMogoCloudSocketOnMessageListener {
+
+ override fun target(msgType: Int): Class = V2XWarningTarget::class.java
+
+ override fun onMsgReceived(msgType: Int, data: V2XWarningTarget?) {
+ if (msgType != 401018) {
+ return
+ }
+ if (data == null) {
+ Logger.i(V2XManager.TAG, "V2XMessageListener_401018:message is null!")
+ return
+ }
+ Logger.i(V2XManager.TAG, "V2XMessageListener_401018:$data")
+ cbs?.forEach {
+ it.onAck(V2XEvent.Warning(data = data))
+ }
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_402000.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_402000.kt
new file mode 100644
index 0000000..5892a42
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_402000.kt
@@ -0,0 +1,27 @@
+package com.mogo.v2x.socket
+
+import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
+import com.mogo.v2x.V2XManager
+import com.mogo.v2x.callback.IV2XCallback
+import com.mogo.v2x.data.V2XAdvanceWarning
+import com.mogo.v2x.event.V2XEvent
+import com.mogo.v2x.logger.Logger
+
+internal class V2XMessageListener_402000(val cbs: Iterable?): IMogoCloudSocketOnMessageListener {
+
+ override fun target(msgType: Int): Class = V2XAdvanceWarning::class.java
+
+ override fun onMsgReceived(msgType: Int, data: V2XAdvanceWarning?) {
+ if (msgType != 402000) {
+ return
+ }
+ if (data == null) {
+ Logger.i(V2XManager.TAG, "V2XMessageListener_402000:message is null!")
+ return
+ }
+ Logger.i(V2XManager.TAG, "V2XMessageListener_402000:$data")
+ cbs?.forEach {
+ it.onAck(V2XEvent.ForwardsWarning(data = data))
+ }
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_404000.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_404000.kt
new file mode 100644
index 0000000..807b041
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/socket/V2XMessageListener_404000.kt
@@ -0,0 +1,27 @@
+package com.mogo.v2x.socket
+
+import com.mogo.cloud.socket.IMogoCloudSocketOnMessageListener
+import com.mogo.v2x.V2XManager
+import com.mogo.v2x.callback.IV2XCallback
+import com.mogo.v2x.data.V2XOptimalRoute
+import com.mogo.v2x.event.V2XEvent
+import com.mogo.v2x.logger.Logger
+
+internal class V2XMessageListener_404000(val cbs: Iterable?): IMogoCloudSocketOnMessageListener {
+
+ override fun target(msgType: Int): Class = V2XOptimalRoute::class.java
+
+ override fun onMsgReceived(msgType: Int, data: V2XOptimalRoute?) {
+ if (msgType != 404000) {
+ return
+ }
+ if (data == null) {
+ Logger.i(V2XManager.TAG, "V2XMessageListener_404000:message is null!")
+ return
+ }
+ Logger.i(V2XManager.TAG, "V2XMessageListener_404000:$data")
+ cbs?.forEach {
+ it.onAck(V2XEvent.OptimalRoute(data = data))
+ }
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/utils/DeviceUtils.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/utils/DeviceUtils.kt
new file mode 100644
index 0000000..17f551f
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/utils/DeviceUtils.kt
@@ -0,0 +1,46 @@
+package com.mogo.v2x.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
+
+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
+ }
+ }
+}
\ No newline at end of file
diff --git a/foudations/mogo-v2x/src/main/java/com/mogo/v2x/utils/DistanceUtils.kt b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/utils/DistanceUtils.kt
new file mode 100644
index 0000000..10bbb2f
--- /dev/null
+++ b/foudations/mogo-v2x/src/main/java/com/mogo/v2x/utils/DistanceUtils.kt
@@ -0,0 +1,52 @@
+package com.mogo.v2x.utils
+
+import kotlin.math.asin
+import kotlin.math.cos
+import kotlin.math.sin
+import kotlin.math.sqrt
+
+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
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 57f50f7..f73d79c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -55,3 +55,6 @@ MOGO_LIVE_VERSION=1.3.18
MOGO_TRAFFICLIVE_VERSION=1.3.18
# 定位服务
MOGO_LOCATION_VERSION=1.3.18
+
+# v2x
+MOGO_V2X_VERSION=1.0.1
diff --git a/settings.gradle b/settings.gradle
index 6925005..e010034 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -8,4 +8,5 @@ include ':foudations:mogo-network'
include ':foudations:mogo-httpdns'
include ':foudations:mogo-passport'
include ':app'
-rootProject.name = "MoGoAiCloudSdk"
\ No newline at end of file
+rootProject.name = "MoGoAiCloudSdk"
+include ':foudations:mogo-v2x'