This commit is contained in:
zhongchao
2021-11-05 23:02:54 +08:00
parent 6c094debd8
commit 88170bb515
93 changed files with 1439 additions and 325 deletions

View File

@@ -0,0 +1,24 @@
package com.mogo.eagle.core.function.v2x
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_V2X_MODULE
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
import com.mogo.eagle.core.function.call.trafficlight.CallTrafficLightManager
import com.mogo.eagle.core.function.v2x.vip.VipCarManager
@Route(path = PATH_V2X_MODULE)
class V2XProvider : IMoGoFunctionServerProvider {
override val functionName: String
get() = "V2XProvider"
override fun init(context: Context) {
CallTrafficLightManager.getTrafficLightProvider().initTrafficLightServer(context)
VipCarManager.INSTANCE.initServer(context)
}
override fun onDestroy() {
VipCarManager.INSTANCE.destroy()
}
}

View File

@@ -0,0 +1,26 @@
package com.mogo.eagle.core.function.v2x.trafficlight
import com.mogo.commons.debug.DebugConfig
class TrafficLightConst {
companion object {
const val MODULE_NAME = "MODULE_V2X_TRAFFIC_LIGHT"
private const val HOST_DEV = "http://dzt-test.zhidaozhixing.com"
private const val HOST_TEST = "http://dzt-test.zhidaozhixing.com"
private const val HOST_DEMO = "http://dzt-show.zhidaozhixing.com"
private const val HOST_PRODUCT = "http://dzt.zhidaozhixing.com"
fun getNetHost(): String {
return when (DebugConfig.getNetMode()) {
DebugConfig.NET_MODE_DEV -> HOST_DEV
DebugConfig.NET_MODE_QA -> HOST_TEST
DebugConfig.NET_MODE_DEMO -> HOST_DEMO
else -> HOST_PRODUCT
}
}
}
}

View File

@@ -0,0 +1,66 @@
package com.mogo.eagle.core.function.v2x.trafficlight
import android.content.Context
import com.mogo.eagle.core.data.trafficlight.*
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
class TrafficLightHMIManager {
companion object {
const val TAG = "TrafficLightHMIManager"
val INSTANCE: TrafficLightHMIManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
TrafficLightHMIManager()
}
}
private var mContext: Context? = null
private var initView: Boolean = false
fun init(context: Context) {
mContext = context
}
fun updateTrafficLight(trafficLightResult: TrafficLightResult) {
if (!initView) {
initView = true
CallerHmiManager.showWarningTrafficLight(0)
}
//todo 需要确认场景是否一致
// val leftTrafficLightStatus = trafficLightResult.laneList.left
// callerHMIToChangeLight(leftTrafficLightStatus)
//
// val midTrafficLightStatus = trafficLightResult.laneList.mid
// callerHMIToChangeLight(midTrafficLightStatus)
//
// val rightTrafficLightStatus = trafficLightResult.laneList.right
// callerHMIToChangeLight(rightTrafficLightStatus)
}
private fun callerHMIToChangeLight(trafficLightStatus: TrafficLightStatus) {
when {
trafficLightStatus.isGreen() -> {
CallerHmiManager.showWarningTrafficLight(3)
if (trafficLightStatus.remain != 99999) {
CallerHmiManager.changeCountdownGreen(trafficLightStatus.remain)
}
}
trafficLightStatus.isFlashGreen() -> {
CallerHmiManager.showWarningTrafficLight(3)
CallerHmiManager.changeCountdownGreen(trafficLightStatus.remain)
}
trafficLightStatus.isYellow() -> {
CallerHmiManager.showWarningTrafficLight(2)
CallerHmiManager.changeCountdownYellow(trafficLightStatus.remain)
}
trafficLightStatus.isRed() -> {
CallerHmiManager.showWarningTrafficLight(1)
CallerHmiManager.changeCountdownRed(trafficLightStatus.remain)
}
}
}
fun hideTrafficLight() {
CallerHmiManager.disableWarningTrafficLight()
}
}

View File

@@ -0,0 +1,45 @@
package com.mogo.eagle.core.function.v2x.trafficlight
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.data.trafficlight.TrafficLightDetail
import com.mogo.eagle.core.function.api.trafficlight.ITrafficLightProvider
import com.mogo.eagle.core.function.v2x.trafficlight.TrafficLightConst.Companion.MODULE_NAME
import com.mogo.eagle.core.function.v2x.trafficlight.core.MogoTrafficLightManager
import com.mogo.utils.logger.Logger
@Route(path = MogoServicePaths.PATH_TRAFFIC_LIGHT)
class TrafficLightProvider : ITrafficLightProvider {
override val functionName: String
get() = MODULE_NAME
override fun init(context: Context) {
}
override fun initTrafficLightServer(context: Context) {
MogoTrafficLightManager.INSTANCE.initServer(context)
TrafficLightHMIManager.INSTANCE.init(context)
}
override fun getTrafficLightCurrentState(): TrafficLightDetail? {
return MogoTrafficLightManager.INSTANCE.getTrafficLightCurrentState()
}
override fun turnLightToGreen(
lightId: Int,
crossingNo: String,
heading: Double,
onSuccess: (() -> Unit),
onError: ((String) -> Unit)
) {
return MogoTrafficLightManager.INSTANCE.turnLightToGreen(lightId, crossingNo,heading,onSuccess, onError)
}
override fun onDestroy() {
//todo MogoTrafficLightManager onDestroy
}
}

View File

@@ -0,0 +1,134 @@
package com.mogo.eagle.core.function.v2x.trafficlight.core
import android.content.Context
import android.location.Location
import android.os.Handler
import com.mogo.cloud.commons.utils.CoordinateUtils
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.trafficlight.TrafficLightDetail
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import com.mogo.eagle.core.function.call.trafficlight.CallTrafficLightListenerManager
import com.mogo.eagle.core.function.v2x.trafficlight.TrafficLightHMIManager
import com.mogo.eagle.core.function.v2x.trafficlight.core.TrafficLightThreadHandler.Companion.MSG_WHAT_LOOP_SEARCH_CROSS_ROAD
import com.mogo.eagle.core.function.v2x.trafficlight.core.TrafficLightThreadHandler.Companion.MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT
import com.mogo.eagle.core.function.v2x.trafficlight.core.TrafficLightThreadHandler.Companion.MSG_WHAT_STOP_SEARCH_CROSS_ROAD
import com.mogo.eagle.core.function.v2x.trafficlight.core.TrafficLightThreadHandler.Companion.MSG_WHAT_STOP_SEARCH_TRAFFIC_LIGHT
import com.mogo.eagle.core.function.v2x.trafficlight.network.TrafficLightNetWorkModel
import com.mogo.eagle.core.utilcode.mogo.thread.WorkThreadHandler
import com.mogo.map.navi.IMogoCarLocationChangedListener2
import com.mogo.module.common.MogoApisHandler
import com.mogo.utils.logger.Logger
class MogoTrafficLightManager : IMogoCarLocationChangedListener2 {
companion object {
const val TAG = "MogoTrafficLightManager"
val INSTANCE: MogoTrafficLightManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
MogoTrafficLightManager()
}
}
private var mContext: Context? = null
private val trafficLightNetWorkModel = TrafficLightNetWorkModel()
private var mLocation: Location? = null
private var roadId: String? = null
private var trafficLightResult: TrafficLightResult? = null
private var mThreadHandler: Handler? = null
fun initServer(context: Context) {
mContext = context
MogoApisHandler.getInstance().apis.registerCenterApi.registerCarLocationChangedListener(TAG, this)
Logger.d(TAG, "ready to start mThreadHandler")
mThreadHandler =
TrafficLightThreadHandler(WorkThreadHandler.newInstance("TrafficLight").looper,
{
Logger.d(TAG, "loop search roadID , mLocation : $mLocation")
mLocation?.let { it ->
val tileId =
MogoApisHandler.getInstance().apis.mapServiceApi.mapUIController.getTileId(
it.longitude,
it.latitude
)
trafficLightNetWorkModel.requestRoadID(tileId, it.latitude, it.longitude, {
mThreadHandler!!.sendEmptyMessage(MSG_WHAT_STOP_SEARCH_CROSS_ROAD)
roadId = it
}, {
Logger.d(TAG, "request road id error : $it")
})
}
}, {
//stop loop search road id
trafficLightNetWorkModel.cancelRequestRoadID()
//开始请求红绿灯
mThreadHandler!!.sendEmptyMessage(MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT)
}, {
//start loop traffic light
mLocation?.let {
trafficLightNetWorkModel.requestTrafficLight(
it.latitude, it.longitude, it.bearing.toDouble(), roadId!!, { result ->
trafficLightResult = result
TrafficLightHMIManager.INSTANCE.updateTrafficLight(result)
CallTrafficLightListenerManager.invokeTrafficLightStatus(result)
},
{ errorMsg ->
Logger.d(TAG, "request Traffic Light error : $errorMsg")
})
}
}, {
//stop loop traffic light
trafficLightNetWorkModel.cancelRequestTrafficLight()
//刚经过红绿灯加入3秒延时请求路口ID
mThreadHandler!!.sendEmptyMessageDelayed(
MSG_WHAT_LOOP_SEARCH_CROSS_ROAD,
3_000L
)
})
mThreadHandler!!.sendEmptyMessageDelayed(MSG_WHAT_LOOP_SEARCH_CROSS_ROAD, 5_000L)
}
fun getTrafficLightCurrentState(): TrafficLightDetail? {
trafficLightResult?.let {
return it.laneList
}
return null
}
fun turnLightToGreen(
lightId: Int,
crossingNo: String,
heading: Double,
onSuccess: (() -> Unit),
onError: ((String) -> Unit)
) {
trafficLightNetWorkModel.turnLightToGreen(lightId, crossingNo, heading, onSuccess, onError)
}
override fun onCarLocationChanged(latLng: MogoLatLng?) {
}
override fun onCarLocationChanged2(latLng: Location?) {
latLng?.let {
mLocation = latLng
// 检测是否开过路口,开过路口则停止读灯。并重置 trafficLightResult 值为 null
if (trafficLightResult != null
&& (CoordinateUtils.calculateLineDistance(
it.longitude,
it.latitude,
trafficLightResult!!.lon,
trafficLightResult!!.lat
) < 5)
) {
trafficLightResult = null
TrafficLightHMIManager.INSTANCE.hideTrafficLight()
CallTrafficLightListenerManager.resetTrafficLightData()
mThreadHandler!!.sendEmptyMessage(MSG_WHAT_STOP_SEARCH_TRAFFIC_LIGHT)
}
}
}
}

View File

@@ -0,0 +1,64 @@
package com.mogo.eagle.core.function.v2x.trafficlight.core
import android.os.Handler
import android.os.Looper
import android.os.Message
import com.mogo.eagle.core.function.v2x.trafficlight.TrafficLightConst
import com.mogo.utils.logger.Logger
class TrafficLightThreadHandler : Handler {
private var loopSearchCrossRoad: (() -> Unit)? = null
private var stopSearchCrossRoad: (() -> Unit)? = null
private var loopSearchTrafficLight: (() -> Unit)? = null
private var stopSearchTrafficLight: (() -> Unit)? = null
constructor(
looper: Looper,
loopSearchCrossRoad: (() -> Unit),
stopSearchCrossRoad: (() -> Unit),
loopSearchTrafficLight: (() -> Unit),
stopSearchTrafficLight: (() -> Unit)
) : super(looper) {
this.loopSearchCrossRoad = loopSearchCrossRoad
this.stopSearchCrossRoad = stopSearchCrossRoad
this.loopSearchTrafficLight = loopSearchTrafficLight
this.stopSearchTrafficLight = stopSearchTrafficLight
}
companion object {
const val MSG_WHAT_LOOP_SEARCH_CROSS_ROAD = 1
const val MSG_WHAT_STOP_SEARCH_CROSS_ROAD = 2
const val MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT = 3
const val MSG_WHAT_STOP_SEARCH_TRAFFIC_LIGHT = 4
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg.what) {
MSG_WHAT_LOOP_SEARCH_CROSS_ROAD -> {
//handler轮询后续从地图处获取到车道线(前提获取车道线没有异步调用),来优化轮询时长
Logger.d(TrafficLightConst.MODULE_NAME,"MSG_WHAT_LOOP_SEARCH_CROSS_ROAD")
loopSearchCrossRoad?.invoke()
sendEmptyMessageDelayed(MSG_WHAT_LOOP_SEARCH_CROSS_ROAD,1_000L)
}
MSG_WHAT_STOP_SEARCH_CROSS_ROAD -> {
if(hasMessages(MSG_WHAT_LOOP_SEARCH_CROSS_ROAD)){
removeMessages(MSG_WHAT_LOOP_SEARCH_CROSS_ROAD)
}
stopSearchCrossRoad?.invoke()
}
MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT -> {
loopSearchTrafficLight?.invoke()
sendEmptyMessageDelayed(MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT,500L)
}
MSG_WHAT_STOP_SEARCH_TRAFFIC_LIGHT -> {
if(hasMessages(MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT)){
removeMessages(MSG_WHAT_LOOP_SEARCH_TRAFFIC_LIGHT)
}
stopSearchTrafficLight?.invoke()
}
}
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.v2x.trafficlight.network
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.data.trafficlight.RoadIDResult
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
interface TrafficLightApiService {
//获取前方路口RoadID
@FormUrlEncoded
@POST("ai-roadInfo-service/cross/near")
suspend fun getFrontRoadID(@FieldMap roadID: Map<String, String>): BaseResponse<RoadIDResult>
//获取前方红绿灯状态
@FormUrlEncoded
@POST("mec-etl-server/light//bgd/channel/realTime")
suspend fun getTrafficLight(@FieldMap status: Map<String, String>): BaseResponse<TrafficLightResult>
//变灯
@FormUrlEncoded
@POST("mec-etl-server/light/bdg/newTask")
suspend fun changeLight(@FieldMap turnLight: Map<String, String>): BaseResponse<Any>
}

View File

@@ -0,0 +1,123 @@
package com.mogo.eagle.core.function.v2x.trafficlight.network
import com.google.gson.Gson
import com.mogo.cloud.network.RetrofitFactory
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.data.trafficlight.*
import com.mogo.eagle.core.function.v2x.trafficlight.TrafficLightConst
import com.mogo.utils.network.apiCall
import com.mogo.utils.network.cancel
import com.mogo.utils.network.request
class TrafficLightNetWorkModel {
private fun getNetWorkApi(baseUrl: String = TrafficLightConst.getNetHost()): TrafficLightApiService {
return RetrofitFactory.getInstanceNoCallAdapter(baseUrl)!!
.create(TrafficLightApiService::class.java)
}
fun requestRoadID(
tileID: Long,
lat: Double,
lon: Double,
onSuccess: ((String) -> Unit),
onError: ((String) -> Unit),
) {
request<BaseResponse<RoadIDResult>>("requestRoadID") {
val map = hashMapOf<String, String>()
start {
val roadIDRequestData = RoadIDRequestData(tileID, lat, lon)
map["sn"] = MoGoAiCloudClientConfig.getInstance().sn
map["data"] = Gson().toJson(roadIDRequestData)
}
loader {
apiCall {
getNetWorkApi().getFrontRoadID(map)
}
}
onSuccess {
if(it.result!= null){
onSuccess.invoke(it.result.crossId)
}else{
onSuccess.invoke("11078")
}
}
onError {
if (it.message != null) {
onError.invoke(it.message!!)
}
}
}
}
fun cancelRequestRoadID() {
cancel("requestRoadID")
}
fun requestTrafficLight(
lat: Double,
lon: Double,
bearing: Double,
roadId: String,
onSuccess: ((TrafficLightResult) -> Unit),
onError: ((String) -> Unit),
) {
request<BaseResponse<TrafficLightResult>>("requestTrafficLight") {
val map = hashMapOf<String, String>()
start {
val trafficLightRequestData = TrafficLightRequestData(lat, lon, bearing, roadId)
map["sn"] = MoGoAiCloudClientConfig.getInstance().sn
map["data"] = Gson().toJson(trafficLightRequestData)
}
loader {
apiCall {
getNetWorkApi().getTrafficLight(map)
}
}
onSuccess {
onSuccess.invoke(it.result)
}
onError {
if (it.message != null) {
onError.invoke(it.message!!)
}
}
}
}
fun cancelRequestTrafficLight() {
cancel("requestTrafficLight")
}
fun turnLightToGreen(
lightId: Int,
crossingNo: String,
heading: Double,
onSuccess: (() -> Unit),
onError: ((String) -> Unit)
) {
request<BaseResponse<Any>> {
val map = hashMapOf<String, String>()
start {
val trafficLightRequestData = ChangeLightRequestData(lightId,crossingNo,heading)
map["sn"] = MoGoAiCloudClientConfig.getInstance().sn
map["data"] = Gson().toJson(trafficLightRequestData)
}
loader {
apiCall {
getNetWorkApi().changeLight(map)
}
}
onSuccess {
onSuccess.invoke()
}
onError {
if (it.message != null) {
onError.invoke(it.message!!)
}
}
}
}
}

View File

@@ -0,0 +1,141 @@
package com.mogo.eagle.core.function.v2x.vip
import android.content.Context
import android.location.Location
import com.mogo.cloud.commons.utils.CoordinateUtils
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import com.mogo.eagle.core.data.trafficlight.turnRedAtOnce
import com.mogo.eagle.core.data.v2x.VipMessage
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.function.api.trafficlight.IMoGoTrafficLightListener
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.trafficlight.CallTrafficLightListenerManager
import com.mogo.eagle.core.function.v2x.trafficlight.core.MogoTrafficLightManager
import com.mogo.map.location.MogoLocation
import com.mogo.map.navi.IMogoCarLocationChangedListener2
import com.mogo.module.common.MogoApisHandler
import com.mogo.module.common.enums.EventTypeEnum
import com.mogo.service.cloud.socket.IMogoOnMessageListener
import com.mogo.utils.logger.Logger
class VipCarManager : IMogoOnMessageListener<VipMessage>, IMoGoTrafficLightListener,
IMogoCarLocationChangedListener2 {
companion object {
const val TAG = "VipCarManager"
val INSTANCE: VipCarManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
VipCarManager()
}
}
private var mContext: Context? = null
private var mLocation: Location? = null
private var turnLightEnd = true
private var result: TrafficLightResult? = null
override fun init(context: Context?) {
Logger.d(TAG, "init provider")
}
fun initServer(context: Context) {
mContext = context
MogoApisHandler.getInstance().apis.registerCenterApi.registerCarLocationChangedListener(TAG, this)
MogoApisHandler.getInstance().apis.getSocketManagerApi(context)
.registerOnMessageListener(401025, this)
}
override fun target(): Class<VipMessage> {
return VipMessage::class.java
}
override fun onMsgReceived(vipMessage: VipMessage?) {
vipMessage?.let {
when (it.vipType) {
0 -> {
CallerHmiManager.vipIdentification(false)
CallTrafficLightListenerManager.unRegisterTrafficLightListener(TAG)
}
1 -> {
CallerHmiManager.vipIdentification(true)
CallTrafficLightListenerManager.registerTrafficLightListener(TAG, this)
}
}
}
}
override fun onTrafficLightStatus(trafficLightResult: TrafficLightResult) {
turnLight()
this.result = trafficLightResult
//如果上次结果和本次灯态结果变化比较大则已变灯控制HMI展示弹窗
if ((result!!.laneList.mid.remain - trafficLightResult.laneList.mid.remain) > 3) {
CallerHmiManager.showWarningV2X(EventTypeEnum.TYPE_VIP_IDENTIFICATION.poiType.toInt(),
"",
EventTypeEnum.TYPE_VIP_IDENTIFICATION.tts,
EventTypeEnum.TYPE_VIP_IDENTIFICATION.poiType,
object : IMoGoWarningStatusListener {
override fun onShow() {}
override fun onDismiss() {
}
})
}
//可作为补偿措施,暂不启用
// mLocation?.let {
// if (canGetThroughCross(it, trafficLightResult)) {
// turnLight()
// }
// }
}
private fun canGetThroughCross(
it: MogoLocation,
trafficLightResult: TrafficLightResult
): Boolean {
return if (CoordinateUtils.calculateLineDistance(
it.longitude,
it.latitude,
trafficLightResult.lon,
trafficLightResult.lat
) < 20
&& turnLightEnd
&& trafficLightResult.laneList.mid.turnRedAtOnce()
) {
turnLightEnd = false
false
} else {
true
}
}
private fun turnLight() {
result?.let {
MogoTrafficLightManager.INSTANCE.turnLightToGreen(
it.lightId,
it.crossId,
mLocation!!.bearing.toDouble(), {
Logger.d(TAG, "变灯请求成功")
}, { errorMsg ->
Logger.d(TAG, "变灯请求失败 msg : $errorMsg")
})
}
}
fun destroy() {
MogoApisHandler.getInstance().apis.getSocketManagerApi(mContext)
.unregisterLifecycleListener(401025)
mContext = null
}
override fun onCarLocationChanged(latLng: MogoLatLng?) {
}
override fun onCarLocationChanged2(latLng: Location?) {
latLng?.let {
mLocation = it
}
}
}