Merge branch 'dev_arch_opt_3.0' into dev_robosweeper-d_app-module_221230_1.1.0

# Conflicts:
#	OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java
#	OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/SweeperFragment.java
#	OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperPresenter.java
#	OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperOperatePanelView.java
#	app_ipc_monitoring/src/main/java/com/zhidao/adas/client/DataDistribution.java
#	app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java
#	app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/MainActivity.java
#	core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoHandAdasMsgManager.java
#	core/function-impl/mogo-core-function-bindingcar/src/main/java/com/mogo/eagle/core/function/bindingcar/BindingcarProvider.java
#	core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/autopilot/adapter/MoGoAdasListenerImpl.kt
#	core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/status/flow/can/CanImpl.kt
#	core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt
#	core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/SteeringWheelView.java
#	core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/TrafficDataView.java
#	core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotVehicleStateListener.kt
#	core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotVehicleStateListenerManager.kt
#	libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/OnAdasListener.java
#	libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/msg/MyMessageFactory.java
#	libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/msg/VehicleStateMessage.java
This commit is contained in:
donghongyu
2023-01-17 18:09:06 +08:00
1903 changed files with 34839 additions and 33745 deletions

View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,79 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'com.alibaba.arouter'
}
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
//ARouter apt 参数
kapt {
useBuildCache = false
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.ext.dependencies.androidxccorektx
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.arouter
implementation rootProject.ext.dependencies.rxandroid
kapt rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.androidxroomruntime
kapt rootProject.ext.dependencies.androidxroomcompiler
implementation rootProject.ext.dependencies.androidxroomktx
implementation rootProject.ext.dependencies.mogoami
implementation rootProject.ext.dependencies.mogoaicloudtelematic
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
implementation rootProject.ext.dependencies.mogo_core_data
implementation rootProject.ext.dependencies.mogo_core_utils
implementation rootProject.ext.dependencies.mogo_core_function_call
implementation project(':libraries:mogo-adas')
} else {
implementation project(':core:mogo-core-data')
implementation project(':core:mogo-core-utils')
implementation project(':core:mogo-core-function-call')
implementation project(':libraries:mogo-adas')
implementation project(':foudations:mogo-commons')
}
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.eagle.core.function.impl
POM_ARTIFACT_ID=msgbox
VERSION_CODE=1

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.eagle.core.function.datacenter">
<application>
</application>
</manifest>

View File

@@ -0,0 +1,722 @@
package com.mogo.eagle.core.function.datacenter.autopilot
import android.Manifest.permission
import android.content.Context
import android.util.Log
import androidx.annotation.RequiresPermission
import chassis.SpecialVehicleTaskCmdOuterClass
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters
import com.mogo.eagle.core.data.autopilot.toAutoPilotLine
import com.mogo.eagle.core.data.autopilot.toRouteInfo
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.constants.MoGoConfig
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.data.deva.chain.ChainConstant
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_MULTI_CONNECT
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_ADAS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CONNECT_STATUS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import com.mogo.eagle.core.data.trafficlight.toTrafficLightDetail
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotCarConfigListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotProvider
import com.mogo.eagle.core.function.api.map.collect.IMoGoMapDataCollectProvider
import com.mogo.eagle.core.function.datacenter.autopilot.adapter.MoGoAdasListenerImpl
import com.mogo.eagle.core.function.datacenter.autopilot.adapter.MoGoAdasMsgConnectStatusListenerImpl
import com.mogo.eagle.core.function.datacenter.autopilot.server.AsyncDataToAutopilotServer
import com.mogo.eagle.core.function.datacenter.autopilot.telematic.EventListener
import com.mogo.eagle.core.function.datacenter.autopilot.telematic.IMsgHandler
import com.mogo.eagle.core.function.datacenter.autopilot.telematic.TeleMsgHandler
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarConfigListenerManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_ADAS_IMPL
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.telematic.MogoProtocolMsg
import com.mogo.telematic.MogoProtocolMsg.NORMAL_DATA
import com.mogo.telematic.MogoProtocolMsg.SYNC_MODE_STATUS
import com.mogo.telematic.NSDNettyManager
import com.mogo.telematic.client.listener.NettyClientListener
import com.mogo.telematic.server.netty.NettyServerListener
import com.mogo.telematic.server.netty.NettyTcpServer
import com.zhidao.support.adas.high.AdasManager
import com.zhidao.support.adas.high.AdasOptions
import com.zhidao.support.adas.high.OnMultiDeviceListener
import com.zhidao.support.adas.high.common.Constants
import com.zhidao.support.adas.high.common.Constants.IPC_CONNECTION_STATUS
import com.zhidao.support.adas.high.common.CupidLogUtils
import com.zhidao.support.adas.high.common.MogoReport
import com.zhjt.service.chain.ChainLog
import com.zhjt.service.chain.TracingConstants
import io.netty.channel.Channel
import mogo.telematics.pad.MessagePad
import java.util.*
import java.util.concurrent.TimeUnit
/**
* @author xiaoyuzhou
* @date 2021/9/22 8:43 下午
* 域控制器
*/
@Route(path = MogoServicePaths.PATH_AUTO_PILOT)
class MoGoAutopilotProvider :
IMoGoAutopilotProvider, IMoGoMapDataCollectProvider.OnMapCollectCmdListener,
IMoGoAutopilotCarConfigListener {
private val TAG = "MoGoAutoPilotProvider"
private var mContext: Context? = null
private lateinit var msgHandler: IMsgHandler
private var timer: Timer? = null
@Volatile
private var isInit = false
override val functionName: String
get() = TAG
override fun init(context: Context) {
CallerLogger.i("$M_ADAS_IMPL$TAG", "初始化工控机连接……")
mContext = context
// 初始化ADAS 域控制器
CupidLogUtils.setEnableLog(false)
msgHandler = TeleMsgHandler()
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {// 司机
// 注册地图采集功能
CallerMapDataCollectorManager.registerOnMapCollectTaskListener(this)
// 配置默认关闭的连接topic
// val messageTypes: MutableSet<MessageType> = HashSet()
// messageTypes.add(MessageType.TYPE_RECEIVE_POINT_CLOUD)
// val subscribeInterfaceOptions = SubscribeInterfaceOptions.newBuilder()
// .setRole(Constants.TERMINAL_ROLE.DRIVER)
// .setType(Constants.SUBSCRIBE_TYPE.UNSUBSCRIBE)
// .setMessageTypes(messageTypes).build()
// "192.168.1.102"
val options = AdasOptions.Builder()
.setIpcConnectionMode(AdasOptions.IPC_CONNECTION_MODE.FIXATION)
.setIpcFixationIP(AdasManager.getInstance().getIPCFixationIPList(mContext))
.setClient(false)
// .setSubscribeInterfaceOptions(subscribeInterfaceOptions)//
.build()
AdasManager.getInstance().create(options, MoGoAdasMsgConnectStatusListenerImpl())
//////////////////////////////////注意先后顺序AdasManager.getInstance().create后才可以设置监听/////////////////////////////////////////////
// 监听ADAS-SDK获取到的工控机数据
AdasManager.getInstance().setOnAdasListener(MoGoAdasListenerImpl())
NSDNettyManager.getInstance().startNSDNettyServerWithSN(context, object :
NettyServerListener<MogoProtocolMsg> {
override fun onMessageResponseServer(msg: MogoProtocolMsg?, channel: Channel?) {
msgHandler.handleMsgFromClient(msg, channel)
}
override fun onStartServer() {
ToastUtils.showShort("司机端服务启动成功!")
if (timer == null) {
timer = Timer()
}
// 10s同步一次数据到乘客屏
timer!!.schedule(object : TimerTask() {
override fun run() {
// 同步是否开启美化模式
setDemoMode(FunctionBuildConfig.isDemoMode)
setIgnoreConditionDraw(FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData)
msgHandler.synMsgToAllClients()
}
}, 1000, 10000)
invokeNettyConnResult("司机端服务启动成功!")
}
override fun onStopServer() {
ToastUtils.showLong("司机端服务停止!")
timer?.cancel()
timer = null
invokeNettyConnResult("司机端服务停止!")
}
override fun onChannelConnect(channel: Channel?) {
msgHandler.handleClientConn2Server(channel)
}
override fun onChannelDisConnect(channel: Channel?) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "onChannelDisConnect")
}
override fun onReceiveClientSign(channel: Channel?, sn: String?) {
}
}, MoGoAiCloudClientConfig.getInstance().sn)
} else {
NSDNettyManager.getInstance()
.searchAndConnectServer(context, MoGoAiCloudClientConfig.getInstance().sn,
AppIdentityModeUtils.isTaxi(FunctionBuildConfig.appIdentityMode),
object : NettyClientListener<MogoProtocolMsg> {
override fun onMessageResponseClient(
msg: MogoProtocolMsg?,
sign: String?,
channel: Channel
) {
// 乘客端收到adas数据直接解析后续分发解析后的数据流程同司机端
msgHandler.handleMsgFromServer(msg, channel)
}
override fun onClientStatusConnectChanged(
statusCode: Int,
sign: String?,
channel: Channel
) {
msgHandler.handleClientConnStatus(statusCode, sign, channel)
}
})
}
msgHandler.setListener(object : EventListener {
override fun connectDevice(isSupportMulti: Boolean) {
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
if (!isInit) {
isInit = true
// 转发工控机数据给乘客屏
listenDeviceData()
}
} else {
if (!isInit) {
isInit = true
UiThreadHandler.post {
if (isSupportMulti) {
// 直连工控机
directConnect()
} else {
val options = AdasOptions
.Builder()
.setClient(true)
.build()
AdasManager.getInstance()
.create(options, MoGoAdasMsgConnectStatusListenerImpl())
// 监听ADAS-SDK获取到的工控机数据
AdasManager.getInstance().setOnAdasListener(MoGoAdasListenerImpl())
// 接收司机屏发过来的感知、定位等数据
listenDeviceData()
}
}
}
}
}
})
CallerAutopilotCarConfigListenerManager.addListener(TAG, this)
CallerLogger.i("$M_ADAS_IMPL$TAG", "initServer……")
// 同步数据给工控机的服务
AsyncDataToAutopilotServer.INSTANCE.initServer()
// 同步是否开启雨天模式
setRainMode(FunctionBuildConfig.isRainMode)
}
private fun directConnect() {
val options = AdasOptions
.Builder()
.setIpcConnectionMode(AdasOptions.IPC_CONNECTION_MODE.FIXATION)
.setIpcFixationIP(AdasManager.getInstance().getIPCFixationIPList(mContext))
.setClient(false)// 乘客端直连工控机改为false
.build()
AdasManager.getInstance().create(options, MoGoAdasMsgConnectStatusListenerImpl())
//////////////////////////////////注意先后顺序AdasManager.getInstance().create后才可以设置监听/////////////////////////////////////////////
// 监听ADAS-SDK获取到的工控机数据
AdasManager.getInstance().setOnAdasListener(MoGoAdasListenerImpl())
}
/**
* 司机屏转发工控机发过来的数据,乘客屏接收解析后的数据保持原流程不变
*/
private fun listenDeviceData() {
AdasManager.getInstance().setOnMultiDeviceListener(object : OnMultiDeviceListener {
override fun onForwardingDriverIPCMessage(bytes: ByteArray?) {
if (bytes == null)
return
// 发送数据给乘客端
if (NSDNettyManager.getInstance().isServerStart) {
msgHandler.synWriteTime()
NSDNettyManager.getInstance()
.sendMsgToAllClients(MogoProtocolMsg(NORMAL_DATA, bytes.size, bytes))
} else {
CallerLogger.d("$M_ADAS_IMPL$TAG", "司机端Server未启动")
}
}
override fun onForwardingPassengerIPCMessage(bytes: ByteArray?) {
if (bytes == null)
return
NSDNettyManager.getInstance()
.sendMogoProtocolMsgToServer(
MogoProtocolMsg(NORMAL_DATA, bytes.size, bytes),
null
)
}
})
}
/**
* 连接自动驾驶域控制器
*
* @param autoPilotIp 指定与控制器IP
*/
override fun resetIpAddress(autoPilotIp: String) {
// 关闭通信
AdasManager.getInstance().disconnect()
// 延时执行连接指定IP地址
ThreadUtils.executeBySingleWithDelay(object : ThreadUtils.SimpleTask<String>() {
@RequiresPermission(permission.INTERNET)
override fun doInBackground(): String {
// 保存本地 AutoPilot IP地址
mContext?.let {
SharedPrefsMgr.getInstance(it).putString(MoGoConfig.AUTOPILOT_IP, autoPilotIp)
}
// 设置IP地址
AdasManager.getInstance().adasOptions.ipcConnectionMode =
AdasOptions.IPC_CONNECTION_MODE.ASSIGN
AdasManager.getInstance().adasOptions.ipcAssignIP = autoPilotIp
// 打开通讯连接
AdasManager.getInstance().connect()
return ""
}
override fun onSuccess(result: String?) {
}
}, 1000, TimeUnit.MILLISECONDS)
}
/**
* 断开与工控机的连接
*/
override fun disconnectIpc() {
AdasManager.getInstance().disconnect()
}
override fun onMapCollectStart(cmdId: Int, cmdTime: Long) {
val result = recordPackage(2, cmdId)
CallerLogger.d("$M_ADAS_IMPL$TAG", "开始记录包: [$cmdId, $result]")
}
override fun onMapCollectEnd(cmdId: Int, cmdTime: Long) {
val result = stopRecord(2, cmdId)
CallerLogger.d("$M_ADAS_IMPL$TAG", "结束记录包: [$cmdId, $result]")
}
override fun startAutoPilot(controlParameters: AutopilotControlParameters) {
if (AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
val invokeResult = AdasManager.getInstance()
.sendAutoPilotModeReq(1, 1, controlParameters.toRouteInfo())
invokeAutoPilotResult(if (invokeResult) "自动驾驶调用成功" else "自动驾驶调用失败, socket 或者 rawPack 可能为空")
} else {
if (AdasManager.getInstance().ipcConnectionStatus == IPC_CONNECTION_STATUS.CONNECTED) {
val invokeResult = AdasManager.getInstance()
.sendAutoPilotModeReq(1, 1, controlParameters.toRouteInfo())
invokeAutoPilotResult(if (invokeResult) "自动驾驶调用成功" else "自动驾驶调用失败, socket 或者 rawPack 可能为空")
} else {
invokeAutoPilotResult("车机与工控机链接失败,无法开启自动驾驶")
CallerLogger.e("$M_ADAS_IMPL$TAG", "车机与工控机链接失败,无法开启自动驾驶")
}
}
}
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = TracingConstants.Endpoint.PAD,
nodeAliasCode = ChainConstant.CHAIN_ALIAS_CODE_EAGLE_START_AUTOPILOT_RESULT,
paramIndexes = [0],
clientPkFileName = "sn"
)
private fun invokeAutoPilotResult(status: String) {
CallerLogger.e("$M_ADAS_IMPL$TAG", status)
}
override fun sendTrafficLightData(trafficLightResult: TrafficLightResult) {
AdasManager.getInstance().sendTrafficLightData(
trafficLightResult.crossId,
trafficLightResult.lat,
trafficLightResult.lon,
trafficLightResult.heading,
trafficLightResult.direction,
trafficLightResult.lightId,
trafficLightResult.laneNo,
trafficLightResult.arrowNo,
trafficLightResult.flashYellow,
trafficLightResult.toTrafficLightDetail(),
trafficLightResult.timeStamp
)
}
override fun sendTrajectoryDownloadReq(autoPilotLine: AutopilotControlParameters.AutoPilotLine) {
AdasManager.getInstance().sendTrajectoryDownloadReq(autoPilotLine.toAutoPilotLine())
}
override fun cancelAutoPilot() {
if (AdasManager.getInstance().ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.CONNECTED) {
AdasManager.getInstance().sendAutoPilotModeReq(0, 1, null)
} else {
CallerLogger.e("$M_ADAS_IMPL$TAG", "车机与工控机链接失败,无法断开自动驾驶")
}
}
override fun recordPackage(): Boolean {
return AdasManager.getInstance()
.startRecordPackage((System.currentTimeMillis() / 1000).toInt(), 1)
}
override fun recordPackage(type: Int, id: Int): Boolean {
return AdasManager.getInstance().startRecordPackage(id, type)
}
override fun recordPackage(type: Int, id: Int, duration: Int): Boolean {
return AdasManager.getInstance().startRecordPackage(id, duration, type)
}
override fun recordPackage(type: Int, id: Int, duration: Int, bduration: Int): Boolean {
return AdasManager.getInstance().startRecordPackage(id, duration, type, bduration)
}
override fun recordPackage(
type: Int,
id: Int,
duration: Int,
bduration: Int,
topics: List<String>
): Boolean {
return AdasManager.getInstance().startRecordPackage(id, duration, type, bduration, topics)
}
override fun stopRecord(type: Int, id: Int): Boolean {
return AdasManager.getInstance().stopRecordPackage(id, type)
}
override fun setEnableLog(isEnableLog: Boolean) {
CupidLogUtils.setEnableLog(isEnableLog)
}
/**
* ADAS日志开启状态
*/
override fun isEnableLog(): Boolean {
return CupidLogUtils.isEnableLog()
}
override fun onDestroy() {
CallerMapDataCollectorManager.unRegisterOnMapCollectTaskListener(this)
}
override fun setAutoPilotSpeed(speed: Int): Boolean {
return AdasManager.getInstance().sendAutopilotSpeedReq(speed / 3.6)
}
override fun setIPCShutDown() {
// AdasManager.getInstance().shutdownIPC()
}
override fun setIPCReboot() {
// AdasManager.getInstance().rebootAPDocker()
}
override fun recordCause(key: String?, name: String?, id: String?, reason: String?) {
key?.let {
AdasManager.getInstance()
.sendRecordCause(it.toLong(), name ?: "", id ?: "", reason ?: "")
}
}
/**
* 演示模式(美化模式)设置只限定于鹰眼
* isEnable = true 开启
* isEnable = false 关闭
*/
override fun setDemoMode(isEnable: Boolean) {
// 同步给乘客端
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
val byteArray = if (isEnable) {
"1;${System.currentTimeMillis()}".toByteArray()
} else {
"0;${System.currentTimeMillis()}".toByteArray()
}
// val byteArray = if (isEnable) byteArrayOf(1) else byteArrayOf(0)
if (NSDNettyManager.getInstance().isServerStart) {
NSDNettyManager.getInstance()
.sendMsgToAllClients(
MogoProtocolMsg(
SYNC_MODE_STATUS,
byteArray.size,
byteArray
)
)
} else {
CallerLogger.d("$M_ADAS_IMPL$TAG", "同步美化模式状态时司机端Server未启动")
}
}
}
override fun setIgnoreConditionDraw(isIgnore: Boolean) {
// 同步给乘客端
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
val byteArray = if (isIgnore) {
"1;${System.currentTimeMillis()}".toByteArray()
} else {
"0;${System.currentTimeMillis()}".toByteArray()
}
if (NSDNettyManager.getInstance().isServerStart) {
NSDNettyManager.getInstance()
.sendMsgToAllClients(
MogoProtocolMsg(
11,
byteArray.size,
byteArray
)
)
} else {
CallerLogger.d("$M_ADAS_IMPL$TAG", "同步美化模式状态时司机端Server未启动")
}
}
}
/**
* 设置工控机演示模式(美化模式)开启、关闭
* isEnable = true 开启
* isEnable = false 关闭
*/
override fun setIPCDemoMode(isEnable: Boolean) {
if (isEnable) {
AdasManager.getInstance().sendDemoModeReq(1)
} else {
AdasManager.getInstance().sendDemoModeReq(0)
}
}
/**
* 雨天模式
* isEnable = true 开启
* isEnable = false 关闭
*/
override fun setRainMode(isEnable: Boolean) {
if (isEnable) {
AdasManager.getInstance().sendRainModeReq(1)
} else {
AdasManager.getInstance().sendRainModeReq(0)
}
}
/**
* 绕障类功能开关
* isEnable = true 开启
* isEnable = false 关闭
* @return boolean
*/
override fun sendDetouring(isEnable: Boolean): Boolean {
return if(isEnable){
AdasManager.getInstance().sendDetouring(1)
}else{
AdasManager.getInstance().sendDetouring(0)
}
}
/**
* 变道绕障的目标障碍物速度阈值
* @param speed 速度阈值 m/s
* @return boolean
*/
override fun sendDetouringSpeed(speed: Double): Boolean {
return AdasManager.getInstance().sendDetouringSpeed(speed)
}
/**
* 获取数据采集录制模式配置列表
* @param reqType 0: all, 1:获取当前所有topic列表, 2:配置需要预加载的topic组合
* @param recordType 0:不需要修改内置类型的topic组合, 1:需要修改内置类型的topic组合
* @param topicsNeedToCache
* @return boolean
*/
override fun getBadCaseConfig(reqType: Int,recordType: Int,topicsNeedToCache: List<String>): Boolean{
return AdasManager.getInstance().sendRecordDataConfigReq(reqType, recordType, topicsNeedToCache)
}
/**
* 向左变道
*/
override fun sendOperatorChangeLaneLeft() {
AdasManager.getInstance().sendOperatorCmdChangeLaneLeft()
}
/**
* 向右变道
*/
override fun sendOperatorChangeLaneRight() {
AdasManager.getInstance().sendOperatorCmdChangeLaneRight()
}
/**
* 发送设置加速度 acc>0加速 acc<0减速 acc=0复位
*/
override fun sendOperatorSetAcceleratedSpeed(cc: Double) {
AdasManager.getInstance().sendOperatorCmdSetAcceleratedSpeed(cc)
}
/**
* 鸣笛 value 1: honk 2: stop honking
*/
override fun sendOperatorSetHorn(value: Double) {
AdasManager.getInstance().sendOperatorCmdSetHorn(value)
}
/**
* 发生行程相关
* type=1或2的时 需要参数 lineName
* type=3或4的时 需要参数 lineName departureStopName arrivalStopName isLastStop
* type=5时 不需要任何参数
*
* @param type 事件类型, 1:行程开始, 2:行程结束, 3:出站, 4:进站, 5:城市占道施工预警
* @param lineName 路线名
* @param departureStopName 出站站点名
* @param arrivalStopName 下一站到达站点名
* @param isLastStop 是否最终站
* @return boolean
*/
override fun sendTripInfo(type: Int, lineName: String, departureStopName: String,arrivalStopName: String, isLastStop: Boolean) {
AdasManager.getInstance().sendTripInfoReq(type, lineName, departureStopName,arrivalStopName, isLastStop)
}
/**
* 发送工控机所有节点重启命令
*/
override fun sendIpcReboot() {
//重启所有节点
AdasManager.getInstance().sendSystemCmdReq(MessagePad.SystemCmdType.SYSTEMCMD_REBOOT)
}
/**
* 办公室调试使用,强制开启自动驾驶,将 statuspilotModecontrol_pilotMode强追设置为 1
* isEnable = true 开启
* isEnable = false 关闭
*/
override fun setControlAutopilotCarAuto(isEnable: Boolean) {
if (isEnable) {
AdasManager.getInstance().sendAutoPilotModeReq(1, 0, null)
} else {
// 司机屏才可关闭自动驾驶
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
AdasManager.getInstance().sendAutoPilotModeReq(0, 0, null)
}
}
}
/**
* 请求工控机基础配置信息
*/
override fun getCarConfig() {
AdasManager.getInstance().sendCarConfigReq()
}
/**
* 获取全局路径
*/
override fun getGlobalPath() {
AdasManager.getInstance().sendGlobalPathReq()
}
/**
* 车机与工控机是否连上了
*/
override fun isConnected(): Boolean {
return AdasManager.getInstance().ipcConnectionStatus == IPC_CONNECTION_STATUS.CONNECTED
}
/**
* 获取协议版本
*/
override fun getProtocolVersion(): Int {
return AdasManager.getInstance().protocolVersion
}
override fun connectSpecifiedServer(ip: String) {
NSDNettyManager.getInstance().connectSpecifiedServer(
ip,
NettyTcpServer.SERVER_PORT,
MoGoAiCloudClientConfig.getInstance().sn,
object : NettyClientListener<MogoProtocolMsg> {
override fun onMessageResponseClient(
msg: MogoProtocolMsg?,
sign: String?,
channel: Channel
) {
msgHandler.handleMsgFromServer(msg, channel)
}
override fun onClientStatusConnectChanged(
statusCode: Int,
sign: String?,
channel: Channel
) {
msgHandler.handleClientConnStatus(statusCode, sign, channel)
}
})
}
/**
* 获取工控机上报数据result code说明
* @param resultCode 上报字段code
*/
override fun getReportResultDesc(resultCode: String): String {
return MogoReport.Result.getDesc(resultCode)
}
/**
* 获取工控机上报数据action code说明
* @param actionCode 上报字段code
*/
override fun getReportActionDesc(actionCode: String): String {
return MogoReport.Action.getDesc(actionCode)
}
override fun onAutopilotCarConfig(carConfigResp: MessagePad.CarConfigResp) {
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
if (!isInit) {
isInit = true
if (carConfigResp.dockVersion.contains("2.3.0")) {// 不支持多连接
// 司机屏转发工控机发过来的数据
listenDeviceData()
}
}
msgHandler.synMsgToAllClients()
} else {// 乘客屏
CallerDevaToolsManager.getBindingCarInfo( carConfigResp.macAddress, MoGoAiCloudClientConfig.getInstance().sn)
invokeNettyConnResult("乘客屏车牌号:${carConfigResp.plateNumber},Mac地址为${carConfigResp.macAddress}")
}
}
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_CONNECT_STATUS,
linkCode = CHAIN_LINK_ADAS,
endpoint = TracingConstants.Endpoint.PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_MULTI_CONNECT,
paramIndexes = [0],
clientPkFileName = "sn"
)
private fun invokeNettyConnResult(status: String) {
CallerLogger.d("$M_ADAS_IMPL$TAG", status)
}
override fun getTeleTimeStamp(): Long {
return msgHandler.getTeleTimeStamp()
}
override fun sendStatusQueryReq() {
AdasManager.getInstance().sendStatusQueryReq()
}
override fun sendSweeperFuTianTaskCmd(fuTianTaskCmd: SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd) {
Log.d(TAG, "---- sendSweeperFuTianTaskCmd ----")
AdasManager.getInstance().sendRoboSweeperFuTianTaskCmd(fuTianTaskCmd)
}
}

View File

@@ -0,0 +1,29 @@
package com.mogo.eagle.core.function.datacenter.autopilot
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.function.api.telematic.IMogoTelematicProvider
import com.mogo.telematic.NSDNettyManager
@Route(path = MogoServicePaths.PATH_TELEMATIC_PROVIDER)
class MoGoTelematicProvider: IMogoTelematicProvider {
override fun init(context: Context?) {}
override fun getServerStarted(): Boolean {
return NSDNettyManager.getInstance().isServerStart
}
override fun getClientConnStatus(): Boolean {
return NSDNettyManager.getInstance().connectStatus
}
override fun getServerIp(): String {
return NSDNettyManager.getInstance().connServerIp
}
override fun getServerToken(): String {
return NSDNettyManager.getInstance().serverSn
}
}

View File

@@ -0,0 +1,612 @@
package com.mogo.eagle.core.function.datacenter.autopilot.adapter
import bag_manager.BagManagerOuterClass
import chassis.ChassisStatesOuterClass
import chassis.VehicleStateOuterClass
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.config.HdMapBuildConfig
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ARRIVE
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_GUARDIAN
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_RECORD
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ROUTE
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_STATUS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAFFIC_LIGHT
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAJECTORY
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_VEHICLE
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_CONFIG
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_STATE
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_PLANNING_ACTIONS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_PLANNING_OBJECTS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_MESSAGE_RECT_DATA
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_ADAS_STATUS_QUERY_RESP
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_ADAS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CONNECT_STATUS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_DATA_TRACKED
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_GNSSINFO
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_ACTIONS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_OBJECTS
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_TRAFFIC_LIGHT
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_TRAJECTORY
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_VEHICLE
import com.mogo.eagle.core.function.call.autopilot.*
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeArriveAtStation
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeAutoPilotStatus
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeAutopilotGuardian
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeAutopilotSNRequest
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeAutopilotStatusRespByQuery
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotActionsListenerManager.invokeAutopilotAbility
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarConfigListenerManager.invokeAutopilotCarConfigData
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager.invokeAutopilotIdentifyDataUpdate
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager.invokeAutopilotIdentifyPlanningObj
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager.invokeAutopilotWarnMessage
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager.invokeAutopilotRecordConfig
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager.invokeAutopilotRecordResult
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotStatisticsListenerManager.invokeAutopilotStatistics
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ20ListenerManager.invokeChassisLocationGCJ02
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager.invokeChassisLocationWGS84
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager.invokePNCActions
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager.invokeAutopilotRotting
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningTrajectoryListenerManager.invokeAutopilotTrajectory
import com.mogo.eagle.core.function.call.autopilot.CallerStartAutopilotFailedListenerManager.invokeStartAutopilotFailed
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.zhidao.support.adas.high.AdasManager
import com.zhidao.support.adas.high.OnAdasListener
import com.zhidao.support.adas.high.bean.AutopilotAbility
import com.zhidao.support.adas.high.bean.AutopilotStatistics
import com.zhidao.support.adas.high.common.ProtocolStatus
import com.zhjt.service.chain.ChainLog
import com.zhjt.service.chain.TracingConstants.Endpoint.Companion.PAD
import function_state_management.FunctionStates
import mogo.telematics.pad.MessagePad
import mogo.telematics.pad.MessagePad.TrackedObject
import mogo_msg.MogoReportMsg
import perception.TrafficLightOuterClass
import planning.RoboSweeperTaskIndexOuterClass
import prediction.Prediction
import record_cache.RecordPanelOuterClass
import system_master.SystemStatusInfo
/**
* @author emArrow
* @since 2022/3/11
*
*
* 适配ADAS 回调监听分发,这里不做业务,只做数据包装及分发处理
*/
class MoGoAdasListenerImpl : OnAdasListener {
companion object {
const val TAG = "MoGoAdasListenerImpl"
}
//车前引导线
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_TRAJECTORY,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAJECTORY,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onTrajectory(header: MessagePad.Header, trajectory: MessagePad.Trajectory?) {
if (HdMapBuildConfig.isMapLoaded) {
if (trajectory != null && trajectory.pointsList.size > 0) {
invokeAutopilotTrajectory(trajectory.pointsList)
}
}
}
//感知物体
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA_TRACKED,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_RECT_DATA,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onTrackedObjects(
header: MessagePad.Header,
trackedObjects: MessagePad.TrackedObjects
) {
if (HdMapBuildConfig.isMapLoaded) {
invokeAutopilotIdentifyDataUpdate(trackedObjects.objsList as List<TrackedObject>?)
}
}
//自车定位信息
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_GNSSINFO,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_STATE,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onGnssInfo(header: MessagePad.Header, gnssInfo: MessagePad.GnssInfo?) {
// WGS84坐标系高精度位置信息
invokeChassisLocationWGS84(gnssInfo)
// GCJ02高德坐标系位置信息
invokeChassisLocationGCJ02(gnssInfo)
if (gnssInfo != null) {
if (1 == FunctionBuildConfig.gpsProvider) {
// 同步给MAP地图
//CallerMapUIServiceManager.getMapUIController()?.syncLocation2Map(gnssInfo)
// 同步更新经纬度和系统时间至 AutoPilotStatusListener
CallerAutoPilotStatusListenerManager.updateAutoPilotLatLon(
gnssInfo.satelliteTime,
gnssInfo.longitude,
gnssInfo.latitude
)
}
}
}
/**
* 老底盘信息,透传底盘状态pb参考底盘
* TODO 目前由于M1车型不会在新底盘PB添加新的字段 所以临时保留
* TODO 后期会优化掉具体时间未知需要工控机端新老底盘PB字段对齐
*
* @param header 头
* @param vehicleState 数据
*/
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_VEHICLE,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_VEHICLE,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onVehicleState(header: MessagePad.Header, vehicleState: VehicleStateOuterClass.VehicleState?) {
if (vehicleState != null) {
//转向灯数据
CallerChassisLamplightListenerManager.invokeAutopilotLightSwitchData(vehicleState.light)
//刹车灯数据
CallerChassisLamplightListenerManager.invokeAutopilotBrakeLightData(vehicleState.brakeLightStatus)
//方向盘转向角数据
CallerChassisSteeringStateListenerManager.invokeAutopilotSteeringData(vehicleState.steering)
//挂挡档位数据
CallerChassisGearStateListenerManager.invokeAutopilotGearData(vehicleState.gear)
//加速度
CallerChassisAccStateListenerManager.invokeAutopilotAcc(vehicleState.accel)
//油门
CallerChassisThrottleStateListenerManager.invokeAutopilotThrottle(vehicleState.throttle)
//刹车
CallerChassisBrakeStateListenerManager.invokeAutopilotBrake(vehicleState.brake)
//电量
if (vehicleState.hasBmsSoc()) {
CallerBatteryManagementSystemListenerManager.invokeBatteryManagementSystemStates(
ChassisStatesOuterClass.BMSSystemStates.newBuilder()
.setBmsSoc(vehicleState.bmsSoc).build()
)
}
//清扫车(福田)清扫控制系统状态
vehicleState.sweeperFutianCleanSystemState?.also { sweeperState ->
val bytes: ByteArray = sweeperState.toByteArray()
val cleanSystemState: ChassisStatesOuterClass.SweeperFuTianTaskSystemStates? = ChassisStatesOuterClass.SweeperFuTianTaskSystemStates.parseFrom(bytes)
cleanSystemState?.let {
CallerSweeperFutianCleanSystemListenerManager.invokeSweeperFutianCleanSystemState(it)
}
}
//金旅M1
vehicleState.roboBusJinlvM1State?.also {
if (vehicleState.hasRoboBusJinlvM1State()) {
CallerRoboBusJinlvM1StatesListenerManager.invokeRoboBusJinlvM1States(it)
}
}
} else {
CallerAutopilotVehicleStateListenerManager.invokeAutopilotDataException(header.timestamp.toLong())
}
}
/**
* 底盘数据
*
* @param header 头
* @param vehicleState 数据
*/
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_VEHICLE,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_VEHICLE,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onChassisStates(header: MessagePad.Header, chassisStates: ChassisStatesOuterClass.ChassisStates?) {
if (chassisStates != null) {
chassisStates.bcmSystemStates?.let { bcmSystemStates ->
bcmSystemStates.turnLightState?.let {
//转向灯数据
CallerChassisLamplightListenerManager.invokeAutopilotLightSwitchData(it)
}
//刹车灯数据
CallerChassisLamplightListenerManager.invokeAutopilotBrakeLightData(bcmSystemStates.brakeLightState != 0)
}
chassisStates.steerSystemStates?.let {
//方向盘转向角数据
CallerChassisSteeringStateListenerManager.invokeAutopilotSteeringData(it.steeringWheelAngle)
}
chassisStates.gearSystemStates?.let { gearSystemStates ->
gearSystemStates.gearPosition?.let {
//挂挡档位数据
CallerChassisGearStateListenerManager.invokeAutopilotGearData(it)
}
}
chassisStates.vehicleMotionStates?.let {
//加速度
CallerChassisAccStateListenerManager.invokeAutopilotAcc(it.acceleration)
}
chassisStates.drivingSystemStates?.let {
//油门
CallerChassisThrottleStateListenerManager.invokeAutopilotThrottle(it.throttleResponsePosition)
}
chassisStates.brakeSystemStates?.let {
//刹车
CallerChassisBrakeStateListenerManager.invokeAutopilotBrake(it.brakePedalResponsePosition)
}
chassisStates.bmsSystemStates?.let {
//电量
CallerBatteryManagementSystemListenerManager.invokeBatteryManagementSystemStates(it)
}
chassisStates.bmsSystemStates?.let {
//电池管理系统
CallerAutopilotVehicleStateListenerManager.invokeBMSSystemStates(it)
}
chassisStates.taskSystemStates?.let { taskSystemStates ->
taskSystemStates.sweeperFutianTaskSystemStates?.let {
//清扫车(福田)清扫控制系统状态
CallerSweeperFutianCleanSystemListenerManager.invokeSweeperFutianCleanSystemState(it)
}
}
} else {
CallerAutopilotVehicleStateListenerManager.invokeAutopilotDataException(header.timestamp.toLong())
}
}
//自动驾驶状态
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_STATUS,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onAutopilotState(
header: MessagePad.Header,
autopilotState: MessagePad.AutopilotState?
) {
if (autopilotState != null) {
//工控机模拟时间
CallerAutopilotVehicleStateListenerManager.invokeAutopilotTime(header.timestamp.toLong())
if (HdMapBuildConfig.isMapLoaded) {
// 初始化自动驾驶状态信息
val autopilotStatusInfo = getAutoPilotStatusInfo()
autopilotStatusInfo.state = autopilotState.state
autopilotStatusInfo.pilotmode = autopilotState.autopilotMode
autopilotStatusInfo.reason = autopilotState.reason
autopilotStatusInfo.camera = autopilotState.camera
autopilotStatusInfo.rtk = autopilotState.rtk
autopilotStatusInfo.radar = autopilotState.radar
autopilotStatusInfo.version = AdasManager.getInstance().adasVersion
if (autopilotStatusInfo.connectIP == null) {
autopilotStatusInfo.connectIP = AdasManager.getInstance().ipcConnectedIp
}
if (autopilotStatusInfo.connectPort == null) {
autopilotStatusInfo.connectPort = AdasManager.getInstance().ipcConnectedPort
}
AdasManager.getInstance().carConfig?.let {
autopilotStatusInfo.dockVersion = it.dockVersion
}
CallerLogger.d("Upgrade", "origin = ${autopilotStatusInfo.connectStatus} -----now = ${AppConfigInfo.isConnectAutopilot} ")
AppConfigInfo.isConnectAutopilot = autopilotStatusInfo.connectStatus
AppConfigInfo.connectStatusDescribe = autopilotStatusInfo.connectStatusDescribe
invokeAutoPilotStatus()
}
}
}
//监控
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_GUARDIAN,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onReportMessage(
header: MessagePad.Header,
mogoReportMessage: MogoReportMsg.MogoReportMessage?
) {
if (HdMapBuildConfig.isMapLoaded) {
invokeAutopilotGuardian(mogoReportMessage)
}
}
//感知红绿灯
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_TRAFFIC_LIGHT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAFFIC_LIGHT,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onPerceptionTrafficLight(
header: MessagePad.Header?,
trafficLights: TrafficLightOuterClass.TrafficLights?
) {
if (trafficLights != null) {
CallerAutopilotIdentifyListenerManager.invokeAutopilotPerceptionTrafficLight(
trafficLights
)
}
}
//他车轨迹预测
override fun onPredictionObstacleTrajectory(
header: MessagePad.Header?,
predictionObjects: Prediction.mPredictionObjects?
) {
//他车轨迹预测
}
override fun onPointCloud(pointCloud: ByteArray?) {
//点云数据透传
CallerAutopilotPointCloudListenerManager.invokeAutopilotPointCloudDataUpdate(pointCloud)
}
//planning障碍物
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_OBJECTS,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_PLANNING_OBJECTS,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onPlanningObjects(
header: MessagePad.Header?,
planningObjects: MessagePad.PlanningObjects
) {
if (HdMapBuildConfig.isMapLoaded) {
invokeAutopilotIdentifyPlanningObj(planningObjects.objsList as List<MessagePad.PlanningObject>)
}
}
// 自动驾驶设备基础信息请求
override fun onBasicInfoReq(
header: MessagePad.Header,
basicInfoReq: MessagePad.BasicInfoReq?
) {
invokeAutopilotSNRequest()
}
//工控机基础配置信息
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_CONNECT_STATUS,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_CONFIG,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onCarConfigResp(
header: MessagePad.Header,
carConfigResp: MessagePad.CarConfigResp?
) {
if (carConfigResp != null) {
AppConfigInfo.dockerVersion = carConfigResp.dockVersion
AppConfigInfo.plateNumber = carConfigResp.plateNumber//车牌号
AppConfigInfo.iPCMacAddress = carConfigResp.macAddress//工控机MAC地址
AppConfigInfo.protocolVersionNumber = carConfigResp.protocolVersionValue//工控机协议版本
AppConfigInfo.isConnectAutopilot = true
invokeAutopilotCarConfigData(carConfigResp)
}
}
//全局路径规划
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ROUTE,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onGlobalPathResp(
header: MessagePad.Header,
globalPathResp: MessagePad.GlobalPathResp?
) {
if (HdMapBuildConfig.isMapLoaded) {
invokeAutopilotRotting(globalPathResp)
}
}
//数据采集badCase
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_RECORD,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onRecordResult(
header: MessagePad.Header,
recordPanel: RecordPanelOuterClass.RecordPanel?
) {
if (recordPanel != null) {
invokeAutopilotRecordResult(recordPanel)
}
}
//预警信息
// @ChainLog(
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
// linkCode = CHAIN_LINK_ADAS,
// endpoint = PAD,
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_WARN,
// paramIndexes = [0, 1],
// clientPkFileName = "sn"
// )
override fun onWarn(header: MessagePad.Header, warn: MessagePad.Warn?) {
invokeAutopilotWarnMessage(warn)
}
//到站回调
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ARRIVE,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onArrivalNotification(
header: MessagePad.Header,
arrivalNotification: MessagePad.ArrivalNotification?
) {
if (HdMapBuildConfig.isMapLoaded) {
invokeArriveAtStation(arrivalNotification)
}
}
//状态查询应答
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_STATUS_QUERY_RESP,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onStatusQueryResp(
header: MessagePad.Header?,
statusInfo: SystemStatusInfo.StatusInfo?
) {
invokeAutopilotStatusRespByQuery(statusInfo)
}
/**
* 数据采集配置应答
*/
override fun onRecordDataConfigResp(
header: MessagePad.Header?,
config: MessagePad.RecordDataConfig?
) {
if (config != null) {
invokeAutopilotRecordConfig(config)
}
}
/**
* planning决策状态, 透传
*/
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_ACTIONS,
linkCode = CHAIN_LINK_ADAS,
endpoint = PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_PLANNING_ACTIONS,
paramIndexes = [0, 1],
clientPkFileName = "sn"
)
override fun onPlanningActionMsg(
header: MessagePad.Header?,
planningActionMsg: MessagePad.PlanningActionMsg?
) {
planningActionMsg?.let {
invokePNCActions(it)
}
}
/**
* 重构后的功能状态
*
* @param header 头
* @param functionStates 头
*/
override fun onFunctionStates(header: MessagePad.Header?, functionStates: FunctionStates.FSMFunctionStates?) {
}
/**
* 清扫车指标数据
*
* @param header 头
* @param roboSweeperTaskIndex 数据
*/
override fun onSweeperTaskIndexData(header: MessagePad.Header?, roboSweeperTaskIndex: RoboSweeperTaskIndexOuterClass.RoboSweeperTaskIndex?) {
roboSweeperTaskIndex?.let {
//清扫车(福田)清扫控制系统状态
CallerAutopilotVehicleStateListenerManager.invokeSweeperFutianCleanTaskIndexData(it)
}
}
/**
* 清扫车指标数据
*
* @param header 头
* @param roboSweeperTaskIndex 数据
*/
override fun onSweeperTaskIndexData(header: MessagePad.Header?, roboSweeperTaskIndex: RoboSweeperTaskIndexOuterClass.RoboSweeperTaskIndex?) {
}
/**
* Bag管理应答
*
* @param header 头
* @param bagManager 数据
*/
override fun onBagManagerCmd(header: MessagePad.Header?, bagManager: BagManagerOuterClass.BagManager?) {
}
/**
* 是否可以启动自动驾驶
* 使用方法查看app_ipc_monitoring/uiMainActivity/onAutopilotAbility
*/
override fun onAutopilotAbility(ability: AutopilotAbility?) {
invokeAutopilotAbility(ability)
}
/**
* 启动自动驾驶失败回调
* 根据MAP 系统监控状态返回过滤
* message.getMsg() 获取详细错误说明
* message.getCode() 可用于判断属于什么类型
*
* @param message 数据
*/
override fun onStartAutopilotFailed(message: MogoReportMsg.MogoReportMessage?) {
invokeStartAutopilotFailed(message);
}
/**
* 启动自动驾驶状态统计
* 触发机制下发启动自动驾驶命令根据MAP返回状态判断成功或失败
* 统计四种状态:成功 失败 取消 超时
*
* @param statistics 统计数据
*/
override fun onAutopilotStatistics(statistics: AutopilotStatistics?) {
invokeAutopilotStatistics(statistics);
}
/**
* 数据解析失败、数据异常回调
* @param status 错误原因
* @param bytes 原始数据
*/
override fun onError(status: ProtocolStatus, bytes: ByteArray) {
Logger.e(TAG, "status===$status")
}
}

View File

@@ -0,0 +1,148 @@
package com.mogo.eagle.core.function.datacenter.autopilot.adapter
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.debug.DebugConfig.*
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.api.cloud.IMoGoCloudListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.cloud.CallerCloudListenerManager
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_ADAS_IMPL
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.zhidao.support.adas.high.AdasManager
import com.zhidao.support.adas.high.OnAdasConnectStatusListener
import com.zhidao.support.adas.high.bean.VersionCompatibility
import com.zhidao.support.adas.high.common.Constants
import com.zhidao.support.adas.high.common.Constants.ENVIRONMENT.*
import com.zhidao.support.adas.high.common.Constants.TERMINAL_ROLE.DRIVER
import com.zhidao.support.adas.high.common.Constants.TERMINAL_ROLE.PASSENGER
/**
* ADAS-SDK与工控机连接状态回调
*/
class MoGoAdasMsgConnectStatusListenerImpl :
OnAdasConnectStatusListener,
IMoGoAutopilotStatusListener,
IMoGoCloudListener {
private val TAG = "ConnectStatus"
private var connectStatus = false
init {
CallerCloudListenerManager.registerCloudListener(TAG, this)
}
override fun onConnectionIPCStatus(ipcConnectionStatus: Int, reason: String?) {
CallerAutoPilotStatusListenerManager.invokeAutoPilotIPCStatusChanged(
ipcConnectionStatus,
reason
)
if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.CONNECTED) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "webSocket 连接成功")
connectStatus = true
// 初始化自动驾驶状态信息
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectIP =
AdasManager.getInstance().ipcConnectedIp
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectPort =
AdasManager.getInstance().ipcConnectedPort
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectStatus = true
// 同步SN给工控机
syncBasicInfoToAutopilot()
//每次工控机连接成功后,需同步当前设置的美化模式状态
CallerAutoPilotManager.setDemoMode(FunctionBuildConfig.isDemoMode)
//当连接状态是关闭美化模式时,同步给工控机
if (!FunctionBuildConfig.isDemoMode) {
CallerAutoPilotManager.setIPCDemoMode(FunctionBuildConfig.isDemoMode)
}
//每次工控机连接成功后,需同步当前设置的雨天模式状态
CallerAutoPilotManager.setRainMode(FunctionBuildConfig.isRainMode)
} else if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.DISCONNECTED) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "webSocket 连接失败 reason:$reason")
if (connectStatus) {
reason?.let {
ToastUtils.showLong("工控机连接断开,原因:$it , 等待重连")
}
connectStatus = false
}
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectIP =
AdasManager.getInstance().ipcConnectedIp
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectPort =
AdasManager.getInstance().ipcConnectedPort
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectStatus = false
//与工控机断开连接,需要重置自动驾驶状态(包括上传至云平台缓存信息),等待连接成功后同步状态信息
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state = 0
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().pilotmode = 0
} else if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.CONNECTING) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "webSocket 正在连接")
} else if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.SEARCH_ADDRESS) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "webSocket 正在搜索工控机IP")
} else if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "webSocket 找不到可用IP 传入的IP不可用或固定IP列表中所有IP不可用")
}
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().ipcConnStatus =
ipcConnectionStatus
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().connectStatusDescribe = reason
CallerAutoPilotStatusListenerManager.invokeAutoPilotStatus()
}
override fun onCompatibility(versionCompatibility: VersionCompatibility?) {
// 与所连接工控机版本兼容性检查通知
}
/**
* 工控机获取SN
*/
override fun onAutopilotSNRequest() {
syncBasicInfoToAutopilot()
}
/**
* 同步SN信息给工控机
*/
private fun syncBasicInfoToAutopilot(sn: String? = null) {
CallerLogger.d("$M_ADAS_IMPL$TAG", "同步PAD的SN给工控机……")
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
// 设置PAD-SN给工控,网络环境
AdasManager.getInstance()
.sendBasicInfoResp(
MoGoAiCloudClientConfig.getInstance().sn,
getEnvironment(),
getTerminalRole()
)
} else {
// 乘客屏先不传sn
AdasManager.getInstance()
.sendBasicInfoResp(
"",
getEnvironment(),
getTerminalRole()
)
}
}
private fun getEnvironment(): Int {
return when (getNetMode()) {
NET_MODE_DEV -> DEVELOP
NET_MODE_QA -> TEST
NET_MODE_RELEASE -> PRODUCTION
NET_MODE_DEMO -> DEMO
else -> PRODUCTION
}
}
private fun getTerminalRole(): Int {
return when {
AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode) -> DRIVER
AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode) -> PASSENGER
else -> DRIVER
}
}
override fun tokenGot(token: String, sn: String) {
syncBasicInfoToAutopilot(sn)
}
}

View File

@@ -0,0 +1,31 @@
package com.mogo.eagle.core.function.datacenter.autopilot.server
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import com.mogo.eagle.core.function.api.trafficlight.IMoGoTrafficLightListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
import com.mogo.eagle.core.function.call.trafficlight.CallerTrafficLightListenerManager
/**
* @author xiaoyuzhou
* @date 2021/11/08 8:43 下午
*
*
* 异步同步数据给 Autopilot 控制器
* 数据源不限于OBU、网络等
*/
class AsyncDataToAutopilotServer private constructor() : IMoGoTrafficLightListener {
companion object {
const val TAG = "AsyncDataToAutopilotServer"
val INSTANCE: AsyncDataToAutopilotServer by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
AsyncDataToAutopilotServer()
}
}
fun initServer() {
CallerTrafficLightListenerManager.addListener(TAG, this)
}
override fun onTrafficLightStatus(trafficLightResult: TrafficLightResult) {
CallerAutoPilotManager.sendTrafficLightData(trafficLightResult)
}
}

View File

@@ -0,0 +1,5 @@
package com.mogo.eagle.core.function.datacenter.autopilot.telematic
interface EventListener {
fun connectDevice(isSupportMulti: Boolean)
}

View File

@@ -0,0 +1,24 @@
package com.mogo.eagle.core.function.datacenter.autopilot.telematic
import com.mogo.telematic.MogoProtocolMsg
import io.netty.channel.Channel
interface IMsgHandler {
fun handleMsgFromServer(msg: MogoProtocolMsg?, channel: Channel?)
fun handleMsgFromClient(msg: MogoProtocolMsg?, channel: Channel?)
fun handleClientConn2Server(channel: Channel?)
fun handleClientConnStatus(statusCode: Int, content: String?, channel: Channel)
fun handleServerConnStatus(statusCode: Int, content: String?, channel: Channel)
fun synWriteTime()
fun getTeleTimeStamp(): Long
fun synMsgToAllClients()
fun setListener(eventListener: EventListener?)
}

View File

@@ -0,0 +1,297 @@
package com.mogo.eagle.core.function.datacenter.autopilot.telematic
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.google.protobuf.TextFormat
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.deva.chain.ChainConstant
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CONNECT_STATUS
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager.setDemoMode
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager.setIgnoreConditionDraw
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.utilcode.mogo.logger.*
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.telematic.MogoProtocolMsg
import com.mogo.telematic.NSDNettyManager
import com.mogo.telematic.client.NettyTcpClient
import com.mogo.telematic.client.status.ConnectState
import com.zhidao.support.adas.high.AdasManager
import com.zhjt.service.chain.ChainLog
import com.zhjt.service.chain.TracingConstants
import io.netty.channel.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import mogo.telematics.pad.MessagePad
class TeleMsgHandler : IMsgHandler {
private val TAG = "TeleMsgHandler"
@Volatile
private var isFirstDisc = true
@Volatile
private var wrTimeStamp = 0L
@Volatile
private var isReceiveSN = false
@Volatile
private var demoModeTime = 0L
@Volatile
private var timestamp = 0L
private var listener: EventListener? = null
override fun handleMsgFromServer(msg: MogoProtocolMsg?, channel: Channel?) {
msg?.let {
when (it.protocolType) {
MogoProtocolMsg.NORMAL_DATA -> {
try {
synWriteTime()
AdasManager.getInstance().decoderRaw(it.body)
} catch (e: Exception) {
e.printStackTrace()
CallerLogger.e(
"${SceneConstant.M_ADAS_IMPL}$TAG",
"乘客屏解析数据过程中出现异常:${e.message}"
)
}
}
MogoProtocolMsg.SYNC_MODE_STATUS -> {
val content = String(it.body)
if (content.contains(";")) {
val strArr = content.split(";")
if (strArr.size == 2) {
val currTime = strArr[1].toLong()
if (currTime > demoModeTime) {
FunctionBuildConfig.isDemoMode = when (strArr[0]) {
"1" -> true
else -> false
}
demoModeTime = currTime
invokeNettyConnResult("乘客屏收到的美化模式DemoMode为${FunctionBuildConfig.isDemoMode}")
} else {
invokeNettyConnResult("乘客屏收到过时的美化模式DemoMode为${FunctionBuildConfig.isDemoMode}")
}
}
}
}
MogoProtocolMsg.REQ_MAC_ADDRESS -> {
val carConfig = MessagePad.CarConfigResp.parseFrom(msg.body)
AppConfigInfo.plateNumber = carConfig.plateNumber
AppConfigInfo.iPCMacAddress = carConfig.macAddress
AppConfigInfo.dockerVersion = carConfig.dockVersion
listener?.connectDevice(!carConfig.dockVersion.contains("2.3.0"))
invokeNettyConnResult(
"司机屏发送给乘客屏配置信息为:${
TextFormat.printer().escapingNonAscii(false).printToString(carConfig)
}"
)
CallerDevaToolsManager.getBindingCarInfo(carConfig.macAddress, MoGoAiCloudClientConfig.getInstance().sn)
}
// SN
10 -> {
val sn = String(it.body)
isReceiveSN = true
NettyTcpClient.sSERVER_SN = sn
}
// 美化模式是否忽略条件直接绘制
11 -> {
val content = String(it.body)
if (content.contains(";")) {
val strArr = content.split(";")
if (strArr.size == 2) {
val currTime = strArr[1].toLong()
if (currTime > timestamp) {
FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData =
when (strArr[0]) {
"1" -> true
else -> false
}
timestamp = currTime
invokeNettyConnResult("乘客屏收到的美化模式isIgnore为${FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData}")
} else {
invokeNettyConnResult("乘客屏收到过时的美化模式isIgnore为${FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData}")
}
}
}
}
else -> {
}
}
}
}
override fun handleMsgFromClient(msg: MogoProtocolMsg?, channel: Channel?) {
msg?.let {
when (it.protocolType) {
MogoProtocolMsg.REQ_MAC_ADDRESS -> {
val carConfig = AdasManager.getInstance().carConfig
if (carConfig != null) {
listener?.connectDevice(!carConfig.dockVersion.contains("2.3.0"))
val configArray = carConfig.toByteArray()
NSDNettyManager.getInstance().sendMsgToSpecifiedClient(
MogoProtocolMsg(
MogoProtocolMsg.REQ_MAC_ADDRESS,
configArray.size, configArray
), channel
) {
invokeNettyConnResult("司机屏发送配置信息到乘客屏是否成功:${it.isSuccess}")
}
} else {
queryCarConfig()
}
}
//乘客端发送过来的工控机数据交给司机端adas转发到工控机
MogoProtocolMsg.NORMAL_DATA -> {
AdasManager.getInstance().sendWsMessage(it.body)
}
10 -> {
val sn = MoGoAiCloudClientConfig.getInstance().sn
if (!sn.isNullOrEmpty()) {
val snArray = sn.toByteArray()
NSDNettyManager.getInstance().sendMsgToSpecifiedClient(
MogoProtocolMsg(10, snArray.size, snArray), channel
) {
invokeNettyConnResult("司机屏发送SN(${sn})到乘客屏是否成功:${it.isSuccess}")
}
} else {
invokeNettyConnResult("司机屏SN未获取到不发送给乘客屏")
}
}
else -> {
}
}
}
}
private fun queryCarConfig() {
invokeNettyConnResult("乘客屏请求司机屏向工控机查询配置信息")
CallerAutoPilotManager.getCarConfig()
}
override fun handleClientConn2Server(channel: Channel?) {
val socketAddress = channel?.remoteAddress().toString()
CallerLogger.d("${SceneConstant.M_ADAS_IMPL}$TAG", "Client ip is:${socketAddress}")
setDemoMode(FunctionBuildConfig.isDemoMode)
setIgnoreConditionDraw(FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData)
}
override fun handleClientConnStatus(statusCode: Int, content: String?, channel: Channel) {
when (statusCode) {
ConnectState.STATUS_CONNECT_SUCCESS -> {
if (!isFirstDisc) {
isFirstDisc = true
}
// 重置状态
if (isReceiveSN) {
isReceiveSN = false
}
// AdasManager.getInstance().startDispatchHandler()
ToastUtils.showShort("连接司机屏成功!")
invokeNettyConnResult("乘客屏连接司机屏成功")
val byteArray = byteArrayOf(0)
NSDNettyManager.getInstance().sendMogoProtocolMsgToServer(
MogoProtocolMsg(MogoProtocolMsg.REQ_MAC_ADDRESS, byteArray.size, byteArray)
) {
invokeNettyConnResult("乘客屏请求配置信息的数据发送是否成功:${it}")
}
// 请求司机屏SN
reqServerSN()
}
ConnectState.STATUS_CONNECT_CLOSED -> {// 由于重连机制会回调多次
if (isFirstDisc) {
isFirstDisc = false
AppConfigInfo.plateNumber = ""
AppConfigInfo.iPCMacAddress = ""
ToastUtils.showLong("断开和司机屏的连接!")
invokeNettyConnResult("断开和司机屏的连接!")
AdasManager.getInstance().stopDispatchHandler()
}
}
ConnectState.STATUS_CONNECT_ERROR -> {
AppConfigInfo.plateNumber = ""
ToastUtils.showLong("和司机端连接异常!")
invokeNettyConnResult("乘客屏和司机屏连接异常,错误为:$content")
AdasManager.getInstance().stopDispatchHandler()
}
else -> {
AdasManager.getInstance().stopDispatchHandler()
}
}
}
override fun handleServerConnStatus(statusCode: Int, content: String?, channel: Channel) {}
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_CONNECT_STATUS,
linkCode = ChainConstant.CHAIN_LINK_ADAS,
endpoint = TracingConstants.Endpoint.PAD,
nodeAliasCode = ChainConstant.CHAIN_ALIAS_CODE_MULTI_CONNECT,
paramIndexes = [0],
clientPkFileName = "sn"
)
private fun invokeNettyConnResult(status: String) {
CallerLogger.d("${SceneConstant.M_ADAS_IMPL}$TAG", status)
}
/**
* 记录最新的司机屏发送数据的时间戳
* 或乘客屏解析数据的时间戳
*/
@Synchronized
override fun synWriteTime() {
wrTimeStamp = System.currentTimeMillis()
}
override fun getTeleTimeStamp(): Long {
return wrTimeStamp
}
override fun setListener(eventListener: EventListener?) {
listener = eventListener
}
private fun reqServerSN() {
if (NettyTcpClient.sSERVER_SN.isNullOrEmpty()) {
ProcessLifecycleOwner.get().lifecycleScope.launch {
for (i in 1..10) {
if (isReceiveSN) {
break
} else {
val byteArray = "SN".toByteArray()
NSDNettyManager.getInstance().sendMogoProtocolMsgToServer(
MogoProtocolMsg(10, byteArray.size, byteArray)
) {
invokeNettyConnResult("乘客屏请求司机屏SN的数据发送是否成功${it}")
}
delay(700)
}
}
}
}
}
override fun synMsgToAllClients() {
if (NSDNettyManager.getInstance().isServerStart) {
val carConfig = AdasManager.getInstance().carConfig
if (carConfig != null) {
val configArray = carConfig.toByteArray()
NSDNettyManager.getInstance().sendMsgToAllClients(
MogoProtocolMsg(
MogoProtocolMsg.REQ_MAC_ADDRESS,
configArray.size, configArray
)
)
}
}
}
}

View File

@@ -0,0 +1,299 @@
package com.mogo.eagle.core.function.msgbox
import android.content.Context
import android.os.Looper
import com.mogo.eagle.core.data.msgbox.*
import com.mogo.eagle.core.data.notice.NoticeNormalData
import com.mogo.eagle.core.data.report.ReportEntity
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxListenerManager
import com.mogo.eagle.core.function.msgbox.db.MsgBoxDb
import com.mogo.eagle.core.function.msgbox.db.MsgBoxInfo
import com.mogo.eagle.core.utilcode.kotlin.lifeCycleScope
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
object DataManager {
// private val msgBoxMap: EnumMap<MsgBoxType, MutableList<MsgBoxBean>> = EnumMap(MsgBoxType::class.java)
// 消失时间5000ms
const val DISMISS_TIME = 5000L
private val notifyList by lazy {
mutableListOf<MsgBoxBean>()
}
/**
* 当天缓存的通知消息
*/
private val cacheNotifyList by lazy {
mutableListOf<MsgBoxBean>()
}
private val sysInfoList by lazy {
mutableListOf<MsgBoxBean>()
}
/**
* 当天缓存的系统消息
*/
private val cacheSysInfoList by lazy {
mutableListOf<MsgBoxBean>()
}
private val recordBagList by lazy {
mutableListOf<MsgBoxBean>()
}
/**
* 当天缓存的录包消息
*/
private val cacheRecordList by lazy {
mutableListOf<MsgBoxBean>()
}
private val scope by lazy {
Utils.getApp().lifeCycleScope
}
/**
* 用户取消给录制的Bag包打标签
*/
private val removedRecordMap by lazy {
HashMap<String, Any>()
}
/**
* 存储时保证按时序排列
*/
fun saveMsg(bean: MsgBoxBean) {
if (Thread.currentThread() == Looper.getMainLooper().thread) {
scope.launch {
withContext(Dispatchers.Default) {
realSaveMsg(bean)
}
}
} else {
realSaveMsg(bean)
}
}
private fun realSaveMsg(msg: MsgBoxBean) {
val type = msg.type
msg.timestamp = System.currentTimeMillis()
msg.bean2Json = GsonUtils.toJson(msg.bean)
when (type) {
MsgBoxType.V2X, MsgBoxType.OBU, MsgBoxType.NOTICE, MsgBoxType.OPERATION -> {
synchronized(this) {
notifyList.add(msg)
}
CallerMsgBoxListenerManager.invokeListener(MsgCategory.NOTICE, msg)
}
MsgBoxType.REPORT -> {
synchronized(this) {
sysInfoList.add(msg)
}
CallerMsgBoxListenerManager.invokeListener(MsgCategory.SYS_INFO, msg)
}
MsgBoxType.RECORD -> {
synchronized(this) {
recordBagList.add(msg)
}
CallerMsgBoxListenerManager.invokeListener(MsgCategory.RECORD_BAG, msg)
}
else -> {}
}
}
/**
* 通知消息V2X、云公告、运营信息
*/
fun getNotifyData(): List<MsgBoxBean> {
return cacheNotifyList
}
/**
* 工控机Report信息
*/
fun getSysInfoData(): List<MsgBoxBean> {
return cacheSysInfoList
}
/**
* 录包信息
*/
fun getRecordBagData(): List<MsgBoxBean> {
return cacheRecordList
}
fun removeRecordInfo(key: String, value: Any) {
removedRecordMap[key] = value
}
/**
* 从本地数据库中查询数据
*/
fun queryAllMessages(context: Context) {
scope.launch {
initCache()
try {
getCacheMessages(context)
} catch (e: Exception) {
CallerLogger.e("DataManager", e.message)
}
}
}
private fun initCache() {
if (cacheNotifyList.isNotEmpty()) {
cacheNotifyList.clear()
}
if (cacheRecordList.isNotEmpty()) {
cacheRecordList.clear()
}
if (cacheSysInfoList.isNotEmpty()) {
cacheSysInfoList.clear()
}
}
private suspend fun getCacheMessages(context: Context): List<MsgBoxBean> = withContext(Dispatchers.IO) {
delay(2000)
return@withContext MsgBoxDb.getDb(context)
.monitorDao()
.getAllCachedMessages()
.map { msgInfo ->
val json = msgInfo.bean2Json
when (msgInfo.obj2JsonType) {
MsgBoxType.V2X.ordinal -> {
return@map MsgBoxBean(
MsgBoxType.V2X,
GsonUtils.fromJson(json, V2XMsg::class.java)
).apply {
this.timestamp = msgInfo.timeStamp
withContext(Dispatchers.Main) {
cacheNotifyList.add(this@apply)
}
}
}
MsgBoxType.OBU.ordinal -> {
return@map MsgBoxBean(
MsgBoxType.OBU,
GsonUtils.fromJson(json, V2XMsg::class.java)
).apply {
this.timestamp = msgInfo.timeStamp
withContext(Dispatchers.Main) {
cacheNotifyList.add(this@apply)
}
}
}
MsgBoxType.OPERATION.ordinal -> {
return@map MsgBoxBean(
MsgBoxType.OPERATION,
GsonUtils.fromJson(json, OperationMsg::class.java)
).apply {
this.timestamp = msgInfo.timeStamp
withContext(Dispatchers.Main) {
cacheNotifyList.add(this@apply)
}
}
}
MsgBoxType.REPORT.ordinal -> {
return@map MsgBoxBean(
MsgBoxType.REPORT,
GsonUtils.fromJson(json, ReportEntity::class.java)
).apply {
this.timestamp = msgInfo.timeStamp
withContext(Dispatchers.Main) {
cacheSysInfoList.add(this@apply)
}
}
}
MsgBoxType.RECORD.ordinal -> {
return@map MsgBoxBean(
MsgBoxType.RECORD,
GsonUtils.fromJson(json, RecordBagMsg::class.java)
).apply {
this.timestamp = msgInfo.timeStamp
withContext(Dispatchers.Main) {
cacheRecordList.add(this@apply)
}
}
}
MsgBoxType.NOTICE.ordinal -> {
return@map MsgBoxBean(
MsgBoxType.NOTICE,
GsonUtils.fromJson(json, NoticeFrCloudMsg::class.java)
).apply {
this.timestamp = msgInfo.timeStamp
withContext(Dispatchers.Main) {
cacheNotifyList.add(this@apply)
}
}
}
else -> {
return@map MsgBoxBean(MsgBoxType.V2X, V2XMsg())
}
}
}
}
/**
* 存储到本地数据库
*/
fun saveAllMessages2Disk(context: Context) {
synchronized(this) {
val msgInfoList = ArrayList<MsgBoxInfo>()
if (notifyList.isNotEmpty()) {
notifyList.forEach {
msgInfoList.add(MsgBoxInfo(it.bean2Json, it.type.ordinal, it.timestamp))
}
notifyList.clear()
}
if (sysInfoList.isNotEmpty()) {
sysInfoList.forEach {
msgInfoList.add(MsgBoxInfo(it.bean2Json, it.type.ordinal, it.timestamp))
}
sysInfoList.clear()
}
if (recordBagList.isNotEmpty()) {
recordBagList.forEach {
var recordKey = ""
if (it.bean is RecordBagMsg) {
recordKey = (it.bean as RecordBagMsg).key.toString()
}
// 用户未处理的Bag包才存本地
if (!removedRecordMap.contains(recordKey)) {
msgInfoList.add(MsgBoxInfo(it.bean2Json, it.type.ordinal, it.timestamp))
} else {// 用户已处理的Bag包
removedRecordMap.remove(recordKey)
}
}
recordBagList.clear()
}
if (msgInfoList.isNotEmpty()) {
MsgBoxDb.getDb(context)
.monitorDao()
.insertMessages(*msgInfoList.toTypedArray())
}
}
}
fun delMsgBoxBean(context: Context, msgBoxBean: MsgBoxBean) {
scope.launch {
withContext(Dispatchers.Default) {
val msgBoxInfo = MsgBoxInfo(msgBoxBean.bean2Json, msgBoxBean.type.ordinal, msgBoxBean.timestamp)
MsgBoxDb.getDb(context)
.monitorDao()
.deleteMsg(msgBoxInfo)
}
}
}
}

View File

@@ -0,0 +1,42 @@
package com.mogo.eagle.core.function.msgbox
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.utilcode.util.SPUtils
/**
* @author XuXinChao
* @description 消息盒子配置
* @since: 2022/12/1
*/
class MsgBoxConfig {
companion object{
//当前用户的Tab选择记录
private const val userRecord = "USER_RECORD"
/**
* 获取当前用户Tab选择记录
*/
fun getUserRecord(): Int{
return SPUtils.getInstance().getInt(userRecord,0)
}
/**
* 设置当前用户Tab选择记录
*/
fun setUserRecord(record: Int){
SPUtils.getInstance().put(userRecord,record)
}
//通知消息缓存列表
@JvmField
var noticeList: ArrayList<MsgBoxBean> = ArrayList()
//车辆系统信息缓存列表
@JvmField
var systemInfoList: ArrayList<MsgBoxBean> = ArrayList()
//录包信息缓存列表
@JvmField
var recordBagList: ArrayList<MsgBoxBean> = ArrayList()
}
}

View File

@@ -0,0 +1,61 @@
package com.mogo.eagle.core.function.msgbox
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_MSG_BOX_MODULE
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.function.api.msgbox.IMsgBoxProvider
import com.mogo.eagle.core.function.msgbox.DataManager.saveAllMessages2Disk
@Route(path = PATH_MSG_BOX_MODULE)
class MsgBoxProvider : IMsgBoxProvider {
override val functionName: String
get() = "MsgBoxProvider"
override fun init(context: Context) {
Thread {
while (true) {
try {
saveAllMessages2Disk(context)
Thread.sleep(3000)
} catch (e: Exception) {
e.printStackTrace()
}
}
}.start()
}
override fun queryAllMessages(context: Context) {
DataManager.queryAllMessages(context)
}
override fun saveMsg(bean: MsgBoxBean) {
DataManager.saveMsg(bean)
}
override fun getCachedNotifyData(): List<MsgBoxBean> {
return DataManager.getNotifyData()
}
override fun getCachedSysInfoData(): List<MsgBoxBean> {
return DataManager.getSysInfoData()
}
override fun getCachedRecordBagData(): List<MsgBoxBean> {
return DataManager.getRecordBagData()
}
override fun removeRecordInfo(context: Context, msgBoxBean: MsgBoxBean, key: String) {
DataManager.removeRecordInfo(key, key)
DataManager.delMsgBoxBean(context, msgBoxBean)
}
override fun getDismissTime(): Long {
return DataManager.DISMISS_TIME
}
override fun onDestroy() {
}
}

View File

@@ -0,0 +1,18 @@
package com.mogo.eagle.core.function.msgbox.db
import androidx.room.*
@Dao
interface MsgBoxDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMessage(info: MsgBoxInfo)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMessages(vararg info: MsgBoxInfo)
@Delete
suspend fun deleteMsg(info: MsgBoxInfo)
@Query("SELECT * FROM t_msg_box")
fun getAllCachedMessages(): List<MsgBoxInfo>
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.core.function.msgbox.db
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [MsgBoxInfo::class], version = 1, exportSchema = false)
abstract class MsgBoxDb: RoomDatabase() {
abstract fun monitorDao(): MsgBoxDao
companion object {
const val INTERNAL_DB_NAME = "msg_box.db"
private var db: MsgBoxDb? = null
@JvmStatic
fun getDb(context: Context): MsgBoxDb {
if (db == null) {
db = Room.databaseBuilder(context.applicationContext, MsgBoxDb::class.java, INTERNAL_DB_NAME)
.fallbackToDestructiveMigration()
.build()
}
return db!!
}
}
}

View File

@@ -0,0 +1,18 @@
package com.mogo.eagle.core.function.msgbox.db
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "t_msg_box")
data class MsgBoxInfo(
@PrimaryKey
@ColumnInfo(name = "obj_json")
val bean2Json: String,
@ColumnInfo(name = "json_obj_type")
val obj2JsonType: Int = 0,
@ColumnInfo(name = "time_stamp")
val timeStamp: Long = 0
)