[670][adas][data-center] 新增冷启动状态查询以及响应接口;新增环形路线功能:启动自驾新增字段、新增启动自驾新字段查询以及响应接口、新增到站查询和响应接口;新增电源盒协议接口相关接口:

This commit is contained in:
xinfengkun
2024-09-18 16:29:48 +08:00
parent f6f6d8b306
commit 9dd1f61583
33 changed files with 2279 additions and 31 deletions

View File

@@ -9,6 +9,7 @@ import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.commons.debug.DebugConfig
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters
import com.mogo.eagle.core.data.autopilot.toAutoPilotCmdInfo
import com.mogo.eagle.core.data.autopilot.toAutoPilotLine
import com.mogo.eagle.core.data.autopilot.toRouteInfo
import com.mogo.eagle.core.data.biz.trafficlight.TrafficLightResult
@@ -66,6 +67,7 @@ import com.zhidao.support.adas.high.chain.AdasChain
import com.zhidao.support.adas.high.common.Constants
import com.zhidao.support.adas.high.common.CupidLogUtils
import com.zhjt.mogo.adas.common.MessageType
import com.zhjt.mogo.adas.common.power.PowerUnitChannel
import com.zhjt.mogo.adas.data.Adas
import com.zhjt.mogo.adas.data.AdasConstants
import com.zhjt.mogo.adas.data.bean.MogoReport
@@ -391,12 +393,12 @@ class MoGoAutopilotControlProvider :
private fun startAutoPilotWithNoParameter(source: Int) {
if (AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
val invokeResult = AdasManager.getInstance()
.sendAutoPilotModeReq(1, source, null)
.sendAutoPilotModeReq(1, source, null, null)
invokeAutoPilotResult(if (invokeResult > -1) "无参自动驾驶调用成功:${invokeResult}" else "自动驾驶调用失败, socket 或者 rawPack 可能为空")
} else {
if (AdasManager.getInstance().ipcConnectionStatus == AdasConstants.IpcConnectionStatus.CONNECTED) {
val invokeResult = AdasManager.getInstance()
.sendAutoPilotModeReq(1, source, null)
.sendAutoPilotModeReq(1, source, null, null)
invokeAutoPilotResult(if (invokeResult > -1) "无参自动驾驶调用成功:${invokeResult}" else "自动驾驶调用失败, socket 或者 rawPack 可能为空")
} else {
invokeAutoPilotResult("车机与工控机链接失败,无法开启自动驾驶 无参")
@@ -407,13 +409,13 @@ class MoGoAutopilotControlProvider :
private fun startAutoPilot(controlParameters: AutopilotControlParameters, source: Int): Long {
if (AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
val invokeResult = AdasManager.getInstance()
.sendAutoPilotModeReq(1, source, controlParameters.toRouteInfo())
.sendAutoPilotModeReq(1, source, controlParameters.toRouteInfo(), controlParameters.toAutoPilotCmdInfo())
invokeAutoPilotResult(if (invokeResult > -1) "自动驾驶调用成功:${invokeResult}" else "自动驾驶调用失败, socket 或者 rawPack 可能为空")
return invokeResult
} else {
if (AdasManager.getInstance().ipcConnectionStatus == AdasConstants.IpcConnectionStatus.CONNECTED) {
val invokeResult = AdasManager.getInstance()
.sendAutoPilotModeReq(1, source, controlParameters.toRouteInfo())
.sendAutoPilotModeReq(1, source, controlParameters.toRouteInfo(), controlParameters.toAutoPilotCmdInfo())
invokeAutoPilotResult(if (invokeResult > -1) "自动驾驶调用成功:${invokeResult}" else "自动驾驶调用失败, socket 或者 rawPack 可能为空")
return invokeResult
} else {
@@ -463,7 +465,7 @@ class MoGoAutopilotControlProvider :
override fun cancelAutoPilot() {
if (AdasManager.getInstance().ipcConnectionStatus == AdasConstants.IpcConnectionStatus.CONNECTED) {
val invokeResult = AdasManager.getInstance().sendAutoPilotModeReq(0, 1, null)
val invokeResult = AdasManager.getInstance().sendAutoPilotModeReq(0, 1, null, null)
invokeAutoPilotResult(if (invokeResult > -1) "取消自动驾驶调用成功:${invokeResult}" else "取消自动驾驶调用失败, socket 或者 rawPack 可能为空")
} else {
invokeAutoPilotResult("车机与工控机链接失败,无法取消自动驾驶")
@@ -1032,11 +1034,11 @@ class MoGoAutopilotControlProvider :
*/
override fun setControlAutopilotCarAuto(isEnable: Boolean) {
if (isEnable) {
AdasManager.getInstance().sendAutoPilotModeReq(1, 0, null)
AdasManager.getInstance().sendAutoPilotModeReq(1, 0, null, null)
} else {
// 司机屏才可关闭自动驾驶
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
AdasManager.getInstance().sendAutoPilotModeReq(0, 0, null)
AdasManager.getInstance().sendAutoPilotModeReq(0, 0, null, null)
}
}
}
@@ -1269,6 +1271,82 @@ class MoGoAutopilotControlProvider :
return AdasManager.getInstance().sendSweeperCloudSuspendResumeTaskResp(reqNo, bigTaskActionResp) > -1
}
/**
* 发送电源状态查询请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
override fun sendPowerUnitSTSRequest(): Long {
return AdasManager.getInstance().sendPowerUnitSTSRequest()
}
/**
* 发送单通道电源控制请求
*
* @param channel 通道
* @param cmd 0关闭1打开
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
override fun sendPowerUnitSingleChannelControl(channel: PowerUnitChannel, cmd: Int): Long {
return AdasManager.getInstance().sendPowerUnitSingleChannelControl(channel,cmd)
}
/**
* 发送电源控制重置请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
override fun sendPowerUnitReset(): Long {
return AdasManager.getInstance().sendPowerUnitReset()
}
/**
* 查询冷启动状态
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
override fun sendSsmFuncQueryColdStartState(): Long {
return AdasManager.getInstance().sendSsmFuncQueryColdStartState()
}
/**
* 查询自驾命令状态
* 查询:是否首次进自驾、订单号、次数
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
override fun sendSsmFuncQueryAutoPilotInfo(): Long {
return AdasManager.getInstance().sendSsmFuncQueryAutoPilotInfo()
}
/**
* 查询到站信息
*
* @param orderId 订单号
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
override fun sendSsmFuncQueryAutoPilotStation(orderId: String): Long {
return AdasManager.getInstance().sendSsmFuncQueryAutoPilotStation(orderId)
}
override fun sendParallelDrivingReq(
reqNo: String,
parallelRequest: ParallelDrivingRequest.ParallelRequest

View File

@@ -8,8 +8,11 @@ import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.config.HdMapBuildConfig
import com.mogo.eagle.core.data.deva.chain.ChainConstant
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_ARRIVE
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_ARRIVE_QUERY
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_AUTOPILOT_INFO
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_CAR_CONFIG
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_CAR_LOC
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_COLD_START_STATE
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_FM_MSG
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_FSM_MSG
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_CODE_ADAS_GUARDIAN
@@ -35,6 +38,8 @@ import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.SSMMsg
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeArriveAtStation
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeAutoPilotInfo
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.invokeAutoPilotStation
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
@@ -58,6 +63,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerBackCameraVideoListener
import com.mogo.eagle.core.function.call.autopilot.CallerChassisDoorStateListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisGnssListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisStatesListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerColdStartStateListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerFaultManagementStateListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerFsm2024ListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerLocalizationStateListenerManager
@@ -98,6 +104,7 @@ import com.zhjt.mogo.adas.data.bean.LaunchConditionData
import com.zhjt.mogo.adas.data.bean.NodeStateInfo
import com.zhjt.mogo.adas.data.bean.ReceivedAck
import com.zhjt.mogo.adas.data.bean.UnableLaunchReason
import com.zhjt.mogo.adas.data.bean.power.PowerData
import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable
import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask
import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus
@@ -414,6 +421,160 @@ class MoGoAdasListenerImpl : OnAdasListener {
override fun onWarn(header: MessagePad.Header, warn: MessagePad.Warn?) {
}
/**
* 冷启动状态变更上报以及查询状态
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param isQuery 是否是查询 ture查询相应的结果 false表示状态变动域控主动推送
* @param coldStartState 数据 null表示 PadSsmMsg中的消息体为null
*/
override fun onColdStartState(
header: MessagePad.Header?,
token: Long,
timestamp: Long,
isQuery: Boolean,
coldStartState: SsmInfo.ColdStartState?
) {
CallerColdStartStateListenerManager.invokeColdStartState(
token,
timestamp,
isQuery,
coldStartState
)
if (coldStartState == null) {
coldStartStateError(
token,
timestamp,
isQuery,
"PadSsmMsg中的消息体为null"
)
} else {
coldStartState(
token,
timestamp,
isQuery,
coldStartState
)
}
}
@ChainLog(
linkChainLog = CHAIN_TYPE_SOCKET_AUTOPILOT,
linkCode = CHAIN_SOURCE_ADAS,
nodeAliasCode = CHAIN_CODE_ADAS_COLD_START_STATE,
paramIndexes = [0, 1, 2, 3]
)
private fun coldStartState(
token: Long,
timestamp: Long,
isQuery: Boolean,
coldStartState: SsmInfo.ColdStartState,
) {
}
@ChainLog(
linkChainLog = CHAIN_TYPE_SOCKET_AUTOPILOT,
linkCode = CHAIN_SOURCE_ADAS,
nodeAliasCode = CHAIN_CODE_ADAS_COLD_START_STATE,
paramIndexes = [0, 1, 2, 3]
)
private fun coldStartStateError(
token: Long,
timestamp: Long,
isQuery: Boolean,
autoPilotInfo: String,
) {
}
/**
* 自驾命令状态查询响应
* 返回 是否首次进自驾、订单号、次数
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotInfo 数据 null表示 PadSsmMsg中的消息体为null
*/
override fun onAutoPilotInfo(
header: MessagePad.Header?,
token: Long,
timestamp: Long,
autoPilotInfo: SsmInfo.AutoPilotInfo?
) {
invokeAutoPilotInfo(token, timestamp, autoPilotInfo)
val msg: String
if (autoPilotInfo == null) {
msg = "PadSsmMsg中的消息体为null"
} else {
val temB: String = autoPilotInfo.firstAutopilotFlag.toString()
val temS: String = autoPilotInfo.orderId ?: ""
msg = "firstAutopilotFlag:" + temB + "orderId:" + temS + "count:" + autoPilotInfo.count
}
autoPilotInfoResponse(
token,
timestamp,
msg
)
}
@ChainLog(
linkChainLog = CHAIN_TYPE_SOCKET_AUTOPILOT,
linkCode = CHAIN_SOURCE_ADAS,
nodeAliasCode = CHAIN_CODE_ADAS_AUTOPILOT_INFO,
paramIndexes = [0, 1, 2]
)
private fun autoPilotInfoResponse(
token: Long,
timestamp: Long,
autoPilotInfo: String,
) {
}
/**
* 到站信息查询响应
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotStation 数据 null表示 PadSsmMsg中的消息体为null
*/
override fun onAutoPilotStation(
header: MessagePad.Header?,
token: Long,
timestamp: Long,
autoPilotStation: SsmInfo.AutoPilotStation?
) {
invokeAutoPilotStation(token, timestamp, autoPilotStation)
val msg: String
if (autoPilotStation == null) {
msg = "PadSsmMsg中的消息体为null"
} else {
val temB: String = autoPilotStation.arrivedStationFlag.toString()
val temS: String = autoPilotStation.orderId ?: ""
msg = "arrivedStationFlag:" + temB + "orderId:" + temS
}
autoPilotStationResponse(
token,
timestamp,
msg
)
}
@ChainLog(
linkChainLog = CHAIN_TYPE_SOCKET_AUTOPILOT,
linkCode = CHAIN_SOURCE_ADAS,
nodeAliasCode = CHAIN_CODE_ADAS_ARRIVE_QUERY,
paramIndexes = [0, 1, 2]
)
private fun autoPilotStationResponse(
token: Long,
timestamp: Long,
autoPilotStation: String,
) {
}
//到站回调
@ChainLog(
linkChainLog = CHAIN_TYPE_SOCKET_AUTOPILOT,
@@ -1052,6 +1213,20 @@ class MoGoAdasListenerImpl : OnAdasListener {
}
/**
* 电源盒协议接口
* <p>
* {@link PowerData}使用方法
* 1.先判断数据中的{@link PowerData#protocolStatus} 是否是 {@link PowerProtocolStatus#SUCCEED} 如果是则表示数据解析正常可以正常使用,进行下一步
* 2.判断 {@link PowerData#frameType} 数据类型
*
* @param header 头
* @param data 数据
*/
override fun onPowerUnit(header: MessagePad.Header, data: PowerData) {
}
/**
* 所连接的域控的节点状态信息
* 目前包含状态 节点是否存在;节点是否超时;

View File

@@ -86,6 +86,12 @@ fun AutopilotControlParameters.toRouteInfo(): MessagePad.RouteInfo {
return routeInfo.build()
}
fun AutopilotControlParameters.toAutoPilotCmdInfo(): MessagePad.CmdInfo {
val cmdInfo = MessagePad.CmdInfo.newBuilder()
cmdInfo.setFirstAutopilotFlag(firstAutopilotFlag).setOrderId(orderId)
return cmdInfo.build()
}
fun AutopilotControlParameters.AutoPilotLine.toAutoPilotLine(): MessagePad.Line {
val line = MessagePad.Line.newBuilder()
line.lineId = this.lineId
@@ -145,6 +151,12 @@ class AutopilotControlParameters {
@JvmField
var autoPilotLine: AutoPilotLine? = null // 自动驾驶路线
@JvmField
var firstAutopilotFlag = true//是否首次进自驾
@JvmField
var orderId = ""//订单号
class AutoPilotLine {
var lineId = 0L

View File

@@ -56,6 +56,7 @@ class ChainConstant {
const val CHAIN_CODE_ADAS_FM_MSG = "CHAIN_CODE_ADAS_FM_MSG"
const val CHAIN_CODE_ADAS_FSM_MSG = "CHAIN_CODE_ADAS_FSM_MSG"
const val CHAIN_CODE_ADAS_ARRIVE = "CHAIN_CODE_ADAS_ARRIVE"
const val CHAIN_CODE_ADAS_ARRIVE_QUERY = "CHAIN_CODE_ADAS_ARRIVE_QUERY"
const val CHAIN_CODE_ADAS_ROUTE = "CHAIN_CODE_ADAS_ROUTE"
const val CHAIN_CODE_ADAS_ROUTE_REQ = "CHAIN_CODE_ADAS_ROUTE_REQ"
const val CHAIN_CODE_ADAS_TRAJECTORY = "CHAIN_CODE_ADAS_ROUTE_REQ"
@@ -73,6 +74,8 @@ class ChainConstant {
const val CHAIN_CODE_ADAS_V2N_EVENT = "CHAIN_CODE_ADAS_V2N_EVENT"
const val CHAIN_CODE_ADAS_POWER_OFF = "CHAIN_CODE_ADAS_POWER_OFF"
const val CHAIN_CODE_ADAS_IPC_REBOOT = "CHAIN_CODE_ADAS_IPC_REBOOT"
const val CHAIN_CODE_ADAS_AUTOPILOT_INFO = "CHAIN_CODE_ADAS_AUTOPILOT_INFO"
const val CHAIN_CODE_ADAS_COLD_START_STATE = "CHAIN_CODE_ADAS_COLD_START_STATE"
const val CHAIN_CODE_RECORD_NATIVE_LEAK = "CHAIN_CODE_RECORD_NATIVE_LEAK"
const val CHAIN_CODE_RECORD_ANR = "CHAIN_CODE_RECORD_ANR"

View File

@@ -5,7 +5,7 @@ import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters
import com.mogo.eagle.core.data.biz.trafficlight.TrafficLightResult
import com.mogo.eagle.core.data.deva.badcase.BagManagerEntity
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
import com.zhjt.mogo.adas.data.Adas
import com.zhjt.mogo.adas.common.power.PowerUnitChannel
import com.zhjt.mogo.adas.data.AdasConstants
import com.zhjt.mogo.adas.data.bean.NodeStateInfo
import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable.IsBootable
@@ -551,6 +551,70 @@ interface IMoGoAutopilotControlProvider : IMoGoFunctionServerProvider {
*/
fun sendSweeperCloudSuspendResumeTaskResp(reqNo: String, bigTaskActionResp: BigTaskActionResp): Boolean
/**
* 发送电源状态查询请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendPowerUnitSTSRequest(): Long
/**
* 发送单通道电源控制请求
*
* @param channel 通道
* @param cmd 0关闭1打开
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendPowerUnitSingleChannelControl(channel: PowerUnitChannel, cmd: Int): Long
/**
* 发送电源控制重置请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendPowerUnitReset(): Long
/**
* 查询冷启动状态
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendSsmFuncQueryColdStartState(): Long
/**
* 查询自驾命令状态
* 查询:是否首次进自驾、订单号、次数
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendSsmFuncQueryAutoPilotInfo(): Long
/**
* 查询到站信息
*
* @param orderId 订单号
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendSsmFuncQueryAutoPilotStation(orderId: String): Long
/**
* 打开点云绘制
*

View File

@@ -34,6 +34,32 @@ interface IMoGoAutopilotStatusListener {
*/
fun onAutopilotDockerInfo(dockerVersion:String){}
/**
* 自驾命令状态查询响应
* 返回 是否首次进自驾、订单号、次数
* 查询调用CallerAutoPilotControlManager.sendSsmFuncQueryAutoPilotInfo()
*
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotInfo 数据 null表示 PadSsmMsg中的消息体为null
*/
fun onAutoPilotInfo(token: Long, timestamp: Long, autoPilotInfo: SsmInfo.AutoPilotInfo?) {}
/**
* 到站信息查询响应
* 查询调用CallerAutoPilotControlManager.sendSsmFuncQueryAutoPilotStation(orderId: String)
*
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotStation 数据 null表示 PadSsmMsg中的消息体为null
*/
fun onAutoPilotStation(
token: Long,
timestamp: Long,
autoPilotStation: SsmInfo.AutoPilotStation?
) {
}
/**
* 自动驾驶到站
*

View File

@@ -0,0 +1,25 @@
package com.mogo.eagle.core.function.api.autopilot
import system_master.SsmInfo
/**
* 冷启动状态变更上报以及查询状态
*/
interface IMoGoColdStartStateListener {
/**
* 冷启动状态变更上报以及查询状态
*
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param isQuery 是否是查询 ture查询相应的结果 false表示状态变动域控主动推送
* @param coldStartState 数据 null表示 PadSsmMsg中的消息体为null
*/
fun onColdStartState(
token: Long,
timestamp: Long,
isQuery: Boolean,
coldStartState: SsmInfo.ColdStartState?
)
}

View File

@@ -22,6 +22,7 @@ import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.util.AppStateManager
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.zhjt.mogo.adas.common.power.PowerUnitChannel
import com.zhjt.mogo.adas.data.Adas
import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable.IsBootable
import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.GetTaskReq
@@ -845,6 +846,82 @@ object CallerAutoPilotControlManager {
return providerApi?.sendParallelDrivingReq(reqNo, parallelRequest) ?: false
}
/**
* 发送电源状态查询请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendPowerUnitSTSRequest(): Long {
return providerApi?.sendPowerUnitSTSRequest() ?: -1L
}
/**
* 发送单通道电源控制请求
*
* @param channel 通道
* @param cmd 0关闭1打开
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendPowerUnitSingleChannelControl(channel: PowerUnitChannel, cmd: Int): Long {
return providerApi?.sendPowerUnitSingleChannelControl(channel, cmd) ?: -1L
}
/**
* 发送电源控制重置请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendPowerUnitReset(): Long {
return providerApi?.sendPowerUnitReset() ?: -1L
}
/**
* 查询冷启动状态
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendSsmFuncQueryColdStartState(): Long {
return providerApi?.sendSsmFuncQueryColdStartState() ?: -1L
}
/**
* 查询自驾命令状态
* 查询:是否首次进自驾、订单号、次数
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendSsmFuncQueryAutoPilotInfo(): Long {
return providerApi?.sendSsmFuncQueryAutoPilotInfo() ?: -1L
}
/**
* 查询到站信息
*
* @param orderId 订单号
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
fun sendSsmFuncQueryAutoPilotStation(orderId: String): Long {
return providerApi?.sendSsmFuncQueryAutoPilotStation(orderId) ?: -1L
}
/**
* 打开点云绘制
*/

View File

@@ -190,6 +190,42 @@ object CallerAutoPilotStatusListenerManager : CallerBase<IMoGoAutopilotStatusLis
mAutopilotStatusInfo = autopilotStatusInfo
}
/**
* 自驾命令状态查询响应
* 返回 是否首次进自驾、订单号、次数
* 查询调用CallerAutoPilotControlManager.sendSsmFuncQueryAutoPilotInfo()
*
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotInfo 数据 null表示 PadSsmMsg中的消息体为null
*/
@Synchronized
fun invokeAutoPilotInfo(token: Long, timestamp: Long, autoPilotInfo: SsmInfo.AutoPilotInfo?) {
M_LISTENERS.forEach {
val listener = it.value
listener.onAutoPilotInfo(token, timestamp, autoPilotInfo)
}
}
/**
* 到站信息查询响应
* 查询调用CallerAutoPilotControlManager.sendSsmFuncQueryAutoPilotStation(orderId: String)
*
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotStation 数据 null表示 PadSsmMsg中的消息体为null
*/
@Synchronized
fun invokeAutoPilotStation(token: Long,
timestamp: Long,
autoPilotStation: SsmInfo.AutoPilotStation?) {
mAutopilotStatusInfo.isArriveAtStation = true
M_LISTENERS.forEach {
val listener = it.value
listener.onAutoPilotStation(token, timestamp, autoPilotStation)
}
}
/**
* 自动驾驶站点信息 回调
* @param arrivalNotification 自动驾驶网约车回调数据

View File

@@ -0,0 +1,34 @@
package com.mogo.eagle.core.function.call.autopilot
import com.mogo.eagle.core.function.api.autopilot.IMoGoColdStartStateListener
import com.mogo.eagle.core.function.call.base.CallerBase
import system_master.SsmInfo
/**
* 冷启动状态变更上报以及查询状态
* 查询调用 CallerAutoPilotControlManager.sendParallelDrivingReq()
*/
object CallerColdStartStateListenerManager : CallerBase<IMoGoColdStartStateListener>() {
/**
* 冷启动状态变更上报以及查询状态
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param isQuery 是否是查询 ture查询相应的结果 false表示状态变动域控主动推送
* @param coldStartState 数据 null表示 PadSsmMsg中的消息体为null
*/
@Synchronized
fun invokeColdStartState(
token: Long,
timestamp: Long,
isQuery: Boolean,
coldStartState: SsmInfo.ColdStartState?
) {
M_LISTENERS.forEach {
val listener = it.value
listener.onColdStartState(token, timestamp, isQuery, coldStartState)
}
}
}

View File

@@ -88,6 +88,13 @@ public enum MessageType {
TYPE_RECEIVE_V2N_NIO_OTHER_RETROGRADE_EVENT(MessagePad.MessageType.MsgTypeV2nNioOtherRetrogradeEvent, "V2N NIO他车逆行路侧"),
TYPE_RECEIVE_V2N_NIO_CONGESTION_EVENT(MessagePad.MessageType.MsgTypeV2nNioCongestionEvent, "V2N NIO拥堵事件"),
TYPE_RECEIVE_LANE_MARKS_TRAN(MessagePad.MessageType.MsgTypeLaneMarksTran, "车道线"),
TYPE_SEND_COLLISION_REPORT(MessagePad.MessageType.MsgTypeCollisionReport, "碰撞上报"),
TYPE_SEND_POWER_UNIT(MessagePad.MessageType.MsgTypePowerUnit, "电源模块请求"),
TYPE_RECEIVE_POWER_UNIT(MessagePad.MessageType.MsgTypePowerUnit, "电源模块响应"),
TYPE_SEND_SSM_FUNC_MSG(MessagePad.MessageType.MsgTypeSSMFuncMsg, "SSM功能控制"),
TYPE_RECEIVE_SSM_FUNC_MSG(MessagePad.MessageType.MsgTypeSSMFuncMsg, "SSM功能响应"),
TYPE_SEND_SSM_FUNC_STATUS_QUERY(MessagePad.MessageType.MsgTypeSSMFuncStatusQuery, "SSM功能状态查询"),
TYPE_RECEIVE_SSM_FUNC_STATUS_QUERY(MessagePad.MessageType.MsgTypeSSMFuncStatusQuery, "SSM功能状态响应"),
//TODO 透传原始pb文件中不存在以下type。由于Java中无法强转,所以在mogo-adas-data/message_pad.proto中放开注释
TYPE_RECEIVE_PLANNING_DECISION_STATE(MessagePad.MessageType.MsgTypePlanningDecisionState, "Planning决策状态"),
TYPE_RECEIVE_SWEEPER_TASK_INDEX_DATA(MessagePad.MessageType.MsgTypeSweeperTaskIndexData, "清扫车指标数据"),

View File

@@ -0,0 +1,34 @@
package com.zhjt.mogo.adas.common.power;
/**
* 电源控制类型
*/
public enum PowerControlType {
UNKNOWN(-1),//未知
SINGLE_CHANNEL_CONTROL(0x0011),//单通道控制
SINGLE_CHANNEL_CONTROL_RESPONSE(0x0811),//单通道控制响应
MULTI_CHANNEL_CONTROL(0x00FF),//多通道控制
MULTI_CHANNEL_CONTROL_RESPONSE(0x08FF),//多通道控制响应
RESET_CONTROL(0x0044),//复位控制
RESET_CONTROL_RESPONSE(0x0844),//复位控制响应
;
public final int value;
PowerControlType(int value) {
this.value = value;
}
public static PowerControlType getPowerControlType(int value) {
PowerControlType[] data = PowerControlType.values();
for (PowerControlType type : data) {
if (type.value == value) {
return type;
}
}
return UNKNOWN;
}
}

View File

@@ -0,0 +1,55 @@
package com.zhjt.mogo.adas.common.power;
public enum PowerError {
UNKNOWN(-1, "未知"),
ERR0(0x00, "其它未识别异常"),
ERR1(0x01, "帧校验值验证失败或帧类型不支持"),
ERR2(0x02, "STS帧长度“不是12”异常"),
ERR3(0x03, "帧长度“小于16”异常"),
ERR4(0x04, "帧类型不支持(合并处理)"),
ERR5(0x05, "底层控制“CAN”中断异常"),
ERR6(0x06, "底层控制“未就绪”异常"),
ERR7(0x07, "CMD帧的“控制方式”不支持或未定义"),
ERR8(0x08, "CMD帧、单通道控制、通道索引号未注册使用"),
ERR9(0x09, "CMD帧、单通道控制、通道索引号超出范围"),
;
public final int value;
/**
* 描述
*/
public final String desc;
PowerError(int value, String desc) {
this.value = value;
this.desc = desc;
}
public static PowerError getPowerError(int value) {
if (value == ERR0.value) {
return ERR0;
} else if (value == ERR1.value) {
return ERR1;
} else if (value == ERR2.value) {
return ERR2;
} else if (value == ERR3.value) {
return ERR3;
} else if (value == ERR4.value) {
return ERR4;
} else if (value == ERR5.value) {
return ERR5;
} else if (value == ERR6.value) {
return ERR6;
} else if (value == ERR7.value) {
return ERR7;
} else {
return UNKNOWN;
}
}
@Override
public String toString() {
return desc;
}
}

View File

@@ -0,0 +1,39 @@
package com.zhjt.mogo.adas.common.power;
public enum PowerFrameType {
UNKNOWN(-1, "未知"),
STS_REQUEST(0x0040, "STS请求"),
STS_RESPONSE(0x0840, "STS响应"),
CMD_REQUEST(0x0044, "CMD请求"),
CMD_RESPONSE(0x0844, "CMD响应"),
ERROR_RESPONSE(0x0800, "服务器异常响应"),//客户端发送的数据服务端检测到异常
;
public final int type;
/**
* 描述
*/
public final String desc;
PowerFrameType(int type, String desc) {
this.type = type;
this.desc = desc;
}
public static PowerFrameType getPowerFrameType(int type) {
if (type == STS_REQUEST.type) {
return STS_REQUEST;
} else if (type == STS_RESPONSE.type) {
return STS_RESPONSE;
} else if (type == CMD_REQUEST.type) {
return CMD_REQUEST;
} else if (type == CMD_RESPONSE.type) {
return CMD_RESPONSE;
} else if (type == ERROR_RESPONSE.type) {
return ERROR_RESPONSE;
} else {
return UNKNOWN;
}
}
}

View File

@@ -0,0 +1,35 @@
package com.zhjt.mogo.adas.common.power;
/**
* 数据协议解析状态
*/
public enum PowerProtocolStatus {
SUCCEED(0x00, "数据解析成功"),
CHECK_FAILED_PACKAGE_LENGTH(0x01, "数据包长度校验失败"),
DATA_LENGTH_NOT_NOTE_OF4(0x02, "数据长度非4的倍数"),
XOR_CHECK_FAILED(0x03, "异域校验失败"),
DATA_PARSE_FAILED(0x04, "数据解析失败"),
CHECK_FAILED_FRAME_HEADER(0x05, "数据头校验失败"),
POWER_FRAME_TYPE_UNKNOWN(0x06, "帧类型未知"),
PAYLOAD_DATA_PARSE_FAILED(0x07, "负载数据解析失败"),
;
public final int code;
/**
* 描述
*/
public final String desc;
PowerProtocolStatus(int code, String desc) {
this.code = code;
this.desc = desc;
}
@Override
public String toString() {
return desc;
}
}

View File

@@ -0,0 +1,96 @@
package com.zhjt.mogo.adas.common.power;
/**
* 单元通道
*/
public enum PowerUnitChannel {
UNKNOWN(-1, null, -1, null),
AIO_PASSENGER_SCREEN(1, "OUT1", 15, "乘客屏一体机(含主控)"),
EB5_DEVICE(2, "OUT2", 15, "EB5主机工程样车"),
VERIFICATION_DEVICE(3, "OUT3", 5, "核销设备"),
DASHCAM(4, "OUT4", 5, "行车记录仪"),
VOICE_MODULE(5, "OUT5", 10, "语音模块"),
CALL_KEY(6, "OUT6", 10, "呼叫按键"),
FRONT_LED_SCREEN(7, "OUT7", 10, "前LED屏"),
BACK_LED_SCREEN(8, "OUT8", 10, "后LED屏"),
POWER_AMPLIFIER(9, "OUT9", 10, "功放"),
AIO_DRIVER_SCREEN(10, "OUT10", 10, "司机屏一体机"),
RTK(27, "OUT27", 5, "RTK定位设备"),
VTBOX(28, "OUT28", 5, "VTBOX"),
FRONT_MILLIMETER_WAVE_RADAR(29, "OUT29", 10, "前毫米波雷达"),
BACK_MILLIMETER_WAVE_RADAR(30, "OUT30", 10, "后毫米波雷达"),
LEFT_FRONT_MILLIMETER_WAVE_RADAR(31, "OUT31", 10, "左前毫米波雷达"),
RIGHT_FRONT_MILLIMETER_WAVE_RADAR(32, "OUT32", 10, "右前毫米波雷达"),
LEFT_BACK_MILLIMETER_WAVE_RADAR(33, "OUT33", 10, "左后毫米波雷达"),
RIGHT_BACK_MILLIMETER_WAVE_RADAR(34, "OUT34", 10, "右后毫米波雷达"),
FRONT_BLIND_LASER_RADAR(35, "OUT35", 5, "前补盲激光雷达"),
LEFT_BLIND_LASER_RADAR(36, "OUT36", 5, "左补盲激光雷达"),
RIGHT_BLIND_LASER_RADAR(37, "OUT37", 5, "右补盲激光雷达"),
BACK_BLIND_LASER_RADAR(38, "OUT38", 5, "后补盲激光雷达"),
FRONT_LASER_RADAR(39, "OUT39", 5, "前激光雷达"),
LEFT_LASER_RADAR(40, "OUT40", 5, "左激光雷达"),
RIGHT_LASER_RADAR(41, "OUT41", 5, "右激光雷达"),
BACK_LASER_RADAR(42, "OUT42", 5, "后激光雷达"),
SWITCH(43, "OUT43", 5, "交换机"),
ROUTER_5G(44, "OUT44", 5, "5G路由器"),
OBU(45, "OUT45", 5, "OBU"),
FRONT_RIGHT_CAMERA_120(52, "M-Video1", 0.6F, "120°前右摄像头(2M)"),
FRONT_CENTRE_CAMERA_60(53, "M-Video2", 0.6F, "60°前中摄像头(8M)"),
LEFT_FRONT_CAMERA_120(54, "M-Video3", 0.6F, "120°左前摄像头(2M)"),
LEFT_BACK_CAMERA_120(55, "M-Video4", 0.6F, "120°左后摄像头(2M)"),
RIGHT_FRONT_CAMERA_120(56, "M-Video5", 0.6F, "120°右前摄像头(2M)"),
RIGHT_BACK_CAMERA_120(57, "M-Video6", 0.6F, "120°右后摄像头(2M)"),
BACK_CAMERA_60(58, "M-Video7", 0.6F, "120°后摄像头(2M)"),
FRONT_SURROUND_VIEW_CAMERA(63, "S-Video4", 0.6F, "前环视摄像头(2M)"),
LEFT_SURROUND_VIEW_CAMERA(64, "S-Video5", 0.6F, "左环视摄像头(2M)"),
RIGHT_SURROUND_VIEW_CAMERA(65, "S-Video6", 0.6F, "右环视摄像头(2M)"),
BACK_SURROUND_VIEW_CAMERA(66, "S-Video7", 0.6F, "后环视摄像头(2M)"),
;
/**
* 通道编号
*/
public final int index;
/**
* 物理连接通道
*/
public final String physicalChannel;
/**
* 电流保护阈值 单位A
*/
public final float currentProtectionThreshold;
/**
* 驱动单元
*/
public final String driverElement;
PowerUnitChannel(int index, String physicalChannel, float currentProtectionThreshold, String driverElement) {
this.index = index;
this.physicalChannel = physicalChannel;
this.currentProtectionThreshold = currentProtectionThreshold;
this.driverElement = driverElement;
}
public static PowerUnitChannel getPowerUnitChannel(int index) {
PowerUnitChannel[] data = PowerUnitChannel.values();
for (PowerUnitChannel channel : data) {
if (channel.index == index) {
return channel;
}
}
return UNKNOWN;
}
@Override
public String toString() {
return "PowerUnitChannel{" +
"index=" + index +
", driverElement='" + driverElement + '\'' +
'}';
}
}

View File

@@ -0,0 +1,68 @@
package com.zhjt.mogo.adas.data.bean.power;
import com.zhjt.mogo.adas.common.power.PowerControlType;
import com.zhjt.mogo.adas.common.power.PowerUnitChannel;
/**
* 命令执行状态 包括:单通道控制;多通道控制;复位控制;
*/
public class PowerCommandExecuteState {
/**
* 控制方式
*/
public final PowerControlType controlType;
/**
* 命令是否执行成功
*/
public final boolean isSucceed;
/**
* 单元索引
* 单通道控制存在此字段
*/
public final PowerUnitChannel channel;
/**
* 下发命令的开关状态
* 单通道控制存在此字段
* 索引1~46表示通电状态 0关闭1打开
*/
public final int sendPowerState;
/**
* 实际开关状态
* 单通道控制存在此字段
* 索引1~46表示通电状态 0关闭1打开
*/
public final int actualPowerState;
/**
* 故障状态
* 单通道控制存在此字段
* 索引1~46表示故障状态 0无故障1对地短路2过流3故障
* 索引51~66表示故障状态 0无故障8过温4过流2过压1欠压可能出现多故障
* <p>
* 整体判断是否有无故障使用{@link PowerUnitState#isNoneFault()}}
* <p>
* 索引为51~66时调用 以下方法判断存在哪些故障
* {@link PowerUnitState#isTS()}}
* {@link PowerUnitState#isOC()}}
* {@link PowerUnitState#isOV()}}
* {@link PowerUnitState#isUV()}}
* 详情参见{@link PowerUnitState#getFaultState()}}
*/
public final int faultState;
public PowerCommandExecuteState(PowerControlType controlType, boolean isSucceed) {
this(controlType, isSucceed, null, -1, -1, -1);
}
public PowerCommandExecuteState(PowerControlType controlType, boolean isSucceed, PowerUnitChannel channel, int sendPowerState, int actualPowerState, int faultState) {
this.controlType = controlType;
this.isSucceed = isSucceed;
this.channel = channel;
this.sendPowerState = sendPowerState;
this.actualPowerState = actualPowerState;
this.faultState = faultState;
}
}

View File

@@ -0,0 +1,101 @@
package com.zhjt.mogo.adas.data.bean.power;
import com.zhjt.mogo.adas.common.power.PowerFrameType;
import com.zhjt.mogo.adas.common.power.PowerProtocolStatus;
import java.util.List;
/**
* 电源原始数据协议
*/
public class PowerData {
/**
* 原始数据
*/
public final byte[] originalData;
/**
* 数据拆包状态
*/
public final PowerProtocolStatus protocolStatus;
/**
* 帧头 用于检查数据是否为正确数据
* mg=0xAA55
*/
public final int frameHead;
/**
* 帧总长度
*/
public final int totalLength;
/**
* 帧类型
*/
public final PowerFrameType frameType;
/**
* 保留字节
*/
public final int reserved;
/**
* 负载数据
*/
public final byte[] dataBlocks;
/**
* 帧校验值
*/
public final int checkValue;
private List<PowerUnitState> powerUnitStates;
private PowerErrorData powerErrorData;
private PowerCommandExecuteState executeState;
/**
* 拆包失败的构造
*/
public static PowerData createError(byte[] originalData, PowerProtocolStatus protocolStatus) {
return new PowerData(originalData, protocolStatus, 0, 0, null, 0, null, 0);
}
/**
* 拆包成功的构造
*/
public static PowerData create(byte[] originalData, int frameHead, int totalLength, PowerFrameType frameType, int reserved, byte[] dataBlocks, int checkValue) {
return new PowerData(originalData, PowerProtocolStatus.SUCCEED, frameHead, totalLength, frameType, reserved, dataBlocks, checkValue);
}
private PowerData(byte[] originalData, PowerProtocolStatus protocolStatus, int frameHead, int totalLength, PowerFrameType frameType, int reserved, byte[] dataBlocks, int checkValue) {
this.originalData = originalData;
this.protocolStatus = protocolStatus;
this.frameHead = frameHead;
this.totalLength = totalLength;
this.frameType = frameType;
this.reserved = reserved;
this.dataBlocks = dataBlocks;
this.checkValue = checkValue;
}
public List<PowerUnitState> getPowerUnitStates() {
return powerUnitStates;
}
public void setPowerUnitStates(List<PowerUnitState> powerUnitStates) {
this.powerUnitStates = powerUnitStates;
}
public PowerErrorData getPowerErrorData() {
return powerErrorData;
}
public void setPowerErrorData(PowerErrorData powerErrorData) {
this.powerErrorData = powerErrorData;
}
public PowerCommandExecuteState getExecuteState() {
return executeState;
}
public void setExecuteState(PowerCommandExecuteState executeState) {
this.executeState = executeState;
}
}

View File

@@ -0,0 +1,29 @@
package com.zhjt.mogo.adas.data.bean.power;
import com.zhjt.mogo.adas.common.power.PowerError;
import com.zhjt.mogo.adas.common.power.PowerFrameType;
/**
* 服务端输出的异常信息 对应帧类型{@link PowerFrameType#ERROR_RESPONSE}
*/
public class PowerErrorData {
/**
* 客户端请求类型
*/
public final PowerFrameType frameType;
/**
* 异常信息
*/
public final PowerError error;
public PowerErrorData(PowerFrameType frameType, PowerError error) {
this.frameType = frameType;
this.error = error;
}
@Override
public String toString() {
return "异常响应,帧类型:" + frameType + " 错误代码:" + error;
}
}

View File

@@ -0,0 +1,171 @@
package com.zhjt.mogo.adas.data.bean.power;
import com.zhjt.mogo.adas.common.power.PowerUnitChannel;
import java.util.Objects;
/**
* 个单元电源状态
*/
public class PowerUnitState {
/**
* 单元索引
*/
private final PowerUnitChannel channel;
/**
* 单元状态
* 索引1~46表示通电状态 0关闭1打开2底边打开
* 索引51~66表示连接状态 0未连接1已连接
*/
private int powerState;
/**
* 故障状态
* 索引1~46表示故障状态 0无故障1对地短路2过流3故障
* 索引51~66表示故障状态 0无故障8过温4过流2过压1欠压可能出现多故障
* <p>
* 整体判断是否有无故障使用{@link PowerUnitState#isNoneFault()}}
* <p>
* 索引为51~66时调用 以下方法判断存在哪些故障
* {@link PowerUnitState#isTS()}}
* {@link PowerUnitState#isOC()}}
* {@link PowerUnitState#isOV()}}
* {@link PowerUnitState#isUV()}}
*/
private int faultState;
/**
* 索引1~46电流保护状态 null表示没有此参数
* ture电流保护false为保护
*/
private Boolean currentProtectionState;
/**
* 索引1~46电流值 null表示没有此参数
* 单位A
*/
private Float currentValue;
public PowerUnitState(PowerUnitChannel channel) {
this.channel = channel;
}
public PowerUnitChannel getChannel() {
return channel;
}
public int getPowerState() {
return powerState;
}
public void setPowerState(int powerState) {
this.powerState = powerState;
}
public int getFaultState() {
return faultState;
}
public void setFaultState(int faultState) {
this.faultState = faultState;
}
public Boolean getCurrentProtectionState() {
return currentProtectionState;
}
public void setCurrentProtectionState(Boolean currentProtectionState) {
this.currentProtectionState = currentProtectionState;
}
public Float getCurrentValue() {
return currentValue;
}
public void setCurrentValue(Float currentValue) {
this.currentValue = currentValue;
}
/**
* 是否打开
* 索引1~46表示通电状态 false:关闭ture打开或底边打开
* 索引51~66表示连接状态 false未连接ture已连接
*
* @return 状态
*/
public boolean isPowerOpen() {
return powerState != 0;
}
/**
* 是否无故障
* 索引1~46表示通电状态 true无故障false对地短路或过流或故障
* 索引51~66表示连接状态 true无故障false过温或过流或过压或欠压
*
* @return 有无故障
*/
public boolean isNoneFault() {
return faultState == 0;
}
/**
* 索引51~66是否过温故障
*
* @return 是否过温故障
*/
public boolean isTS() {
return (faultState & 8) == 8;
}
/**
* 索引51~66是否过流故障
*
* @return 是否过流故障
*/
public boolean isOC() {
return (faultState & 4) == 4;
}
/**
* 索引51~66是否过压故障
*
* @return 是否过压故障
*/
public boolean isOV() {
return (faultState & 2) == 2;
}
/**
* 索引51~66是否欠压故障
*
* @return 是否欠压故障
*/
public boolean isUV() {
return (faultState & 1) == 1;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PowerUnitState that = (PowerUnitState) o;
return channel == that.channel;
}
@Override
public int hashCode() {
return Objects.hashCode(channel);
}
@Override
public String toString() {
return "PowerUnitState{" +
"channel=" + channel +
", powerState=" + powerState +
", faultState=" + faultState +
", currentProtectionState=" + currentProtectionState +
", currentValue=" + currentValue +
'}';
}
}

View File

@@ -18,6 +18,13 @@ public class ByteUtil {
return bytes;
}
public static byte[] set16bitUnsignedValueLittleEndian(int num) {
byte[] bytes = new byte[2];
bytes[1] = (byte) (num >> 8);
bytes[0] = (byte) num;
return bytes;
}
public static byte[] set32bitUnsignedValue(long num) {
byte[] bytes = new byte[4];
bytes[0] = (byte) (num >> 24);
@@ -27,6 +34,15 @@ public class ByteUtil {
return bytes;
}
public static byte[] set32bitUnsignedValueValueLittleEndian(long num) {
byte[] bytes = new byte[4];
bytes[0] = (byte) num;
bytes[1] = (byte) (num >> 8);
bytes[2] = (byte) (num >> 16);
bytes[3] = (byte) (num >> 24);
return bytes;
}
public static byte[] set64bitUnsignedValue(long num) {
byte[] bytes = new byte[8];
bytes[0] = (byte) (num >> 56);
@@ -81,6 +97,25 @@ public class ByteUtil {
return value;
}
/**
* 无符号
* 合并 2 byte
* 使用后将 Index中的index移动到下一个数据的开始位
*
* @param data
* @return
*/
public static int get16bitUnsignedValueLittleEndian(byte[] data) {
int value = 0;
if (data.length > 1) {
value = data[1] & 0xFF;
value = value << 8;
value = value | (data[0] & 0xFF);
}
return value;
}
/**
* 无符号
* 合并 4 byte
@@ -106,6 +141,30 @@ public class ByteUtil {
return value;
}
/**
* 无符号
* 合并 4 byte
* 使用后将 Index中的index移动到下一个数据的开始位
* *
*
* @param data
* @return
*/
public static int get32bitUnsignedValueLittleEndian(byte[] data) {
int value = 0;
if (data.length > 3) {
value = data[3] & 0xFF;
value = value << 8;
value = value | (data[2] & 0xFF);
value = value << 8;
value = value | (data[1] & 0xFF);
value = value << 8;
value = value | (data[0] & 0xFF);
}
return value;
}
/**
* 无符号
* 合并 8 byte
@@ -374,4 +433,11 @@ public class ByteUtil {
(byte) ((b >> 6) & 0x1) +
(byte) ((b >> 7) & 0x1);
}
//b为传入的字节i为第几位范围0-7如要获取bit0则i=0
public static int getBit(byte b, int i) {
return (b >> i) & 0x1;
}
}

View File

@@ -93,6 +93,10 @@ enum MessageType
MsgTypeV2nNioOtherRetrogradeEvent = 0x1012a; //他车逆行(路侧)事件推送, 透传
MsgTypeV2nNioCongestionEvent = 0x1012b; //拥堵事件推送, 透传
MsgTypeLaneMarksTran = 0x1012c;//车道线上传
MsgTypeCollisionReport = 0x1012d;//碰撞上报
MsgTypePowerUnit = 0x1012e;//电源模块通信
MsgTypeSSMFuncMsg = 0x1012f;//SSM功能(上下行)
MsgTypeSSMFuncStatusQuery = 0x10130;//SSM功能状态查询及返回(上下行)
}
message Header
@@ -292,7 +296,7 @@ message TrackedSource
message TrackedObject
{
uint32 type = 1; //物体类型, 0:Background, 1:Person, 2:Bicycle, 3:Car, 4:MotorCycle,
uint32 type = 1; //物体类型, 0:Background, 1:Person, 2:Bicycle, 3:Car, 4:MotorCycle,
//5:TrafficSign, 6:Bus, 7:CellPhone, 8:Truck, 9:Bottle, 10:TrafficLight,
//11:Rider, 12:TriangleRoadblock, 13:WarningTriangle, 100:Unknown,
//447:TAILBACK 501:RoadWork_occupy_0501, 502:RoadWork_break_0502,
@@ -351,7 +355,7 @@ message TrackedObjects
// message definition for MsgTypeGnssInfo
message GnssInfo
{
double longitude = 1; //经度
double longitude = 1; //经度
double latitude = 2; //纬度
double altitude = 3; //海拔
double heading = 4; //航向角
@@ -393,7 +397,7 @@ message AutopilotState
// message definition for MessageType: MsgTypePlanningObjects
message PlanningObject
{
uint32 uuid = 1;
uint32 uuid = 1;
uint32 type = 2; //影响自车决策的类型, 和感知的障碍物类型不是一回事 0是leading障碍物1是避障和择机的障碍物
}
@@ -434,7 +438,7 @@ message TrajectoryDownloadReq
}
// message definition for MessageType: MsgTypeBasicInfoReq
message BasicInfoReq
message BasicInfoReq
{
bytes certification = 1;//域控ssl证书
}
@@ -462,7 +466,7 @@ message Location
message RouteInfo
{
Location startLocation = 1;
Location startLocation = 1;
string startName = 2;
Location endLocation = 3;
string endName = 4;
@@ -478,12 +482,18 @@ message RouteInfo
bool isStation = 13; //20240523 用于表示判断是否是站点下单。默认false起点下单接管下单 true: 中间站点下单
}
message CmdInfo {
bool first_autopilot_flag = 1; // 是否首次进自驾
string order_id = 2; // 订单号
}
message SetAutopilotModeReq
{
uint32 mode = 1; //1: enter autopilot mode, 0: quit autopilot mode
uint32 source = 2; //命令来源: 0: pad模拟, 1: pad业务, 2:aicloud, 3:魔方(清扫车MAP Version==332以及MAP Version>=350其他车型目前未上线)
RouteInfo routeInfo = 3; //自动驾驶路径信息
uint64 sessionId = 4; //autopilot cmd session ID
CmdInfo cmd_info = 5; //自驾命令信息
}
// message definition for MsgTypeSetDemoModeReq
@@ -505,7 +515,7 @@ message CarConfigResp
string macAddress = 3;
ProtocolVersion protocolVersion = 4; //通信协议版本
double speedLimit = 5; //自动驾驶限速, 单位m/s
double maxSpeedLimit = 6; //最大自动驾驶限速, 单位m/s
double maxSpeedLimit = 6; //最大自动驾驶限速, 单位m/s
double minAcceleration = 7; //最小加速度, 单位m/s²
double maxAcceleration = 8; //最大加速度, 单位m/s²
string carType = 9; //车辆类型
@@ -582,7 +592,7 @@ message TrafficLightDetail
message TrafficLightData
{
string crossID = 1; //roadID
double latitude = 2;
double latitude = 2;
double longitude = 3;
string heading = 4; //红绿灯方向
string direction = 5; //路的航向角
@@ -794,7 +804,7 @@ message PlanningActionMsg
//message definition for MsgTypeSetParamReq
message SetOneParam
{
uint32 type = 1; // 0:default 1:绕障类功能开关(bool) 2:变道绕障的目标障碍物速度阈值(double, m/s),针对低速绕行功能的
uint32 type = 1; // 0:default 1:绕障类功能开关(bool) 2:变道绕障的目标障碍物速度阈值(double, m/s),针对低速绕行功能的
// 3:AEB开关(bool) 0:关闭自动紧急制动功能 1:启用自动紧急制动功能
// 4:限制绕障开关(bool) 0:正常绕障 1限制绕障 默认0
// 5:停车让行线前避让等待开关(bool) 0:停车让行线前无需等待 1:停车让行线前需要等待 默认0
@@ -810,7 +820,7 @@ message SetOneParam
// 15座椅状态(int) 0:表示仅主驾位有人,1:表示仅副驾位有人,2:表示主驾和副驾同时有人,3:表示仅后排有人,4:表示主驾有人+后排有人,5:表示副驾有人+后排有人,6:表示主驾和副驾同时有人+后排有人,7: 所有座位都无人, 255:缺省
// 16: 超车的最大速度阈值(double, m/s) T1/T2: 范围[3, 12.5], 默认值10
// 17: 故障模拟指令(int) default:0, 1:线控失效
// 18: 碰撞上报(null)
// 18: 碰撞上报(null) TODO 废弃使用message CollisionReport
// 19: 会车开关(bool) 0: off 1:on 默认0
// 20: 超车开关(bool) 0: off 1:on 默认0
string value = 2; // 转成字符串的值
@@ -923,3 +933,11 @@ message SessionInfo
//message definition for MsgTypeLocState
//refer to loc_state.proto
//message definition for MsgTypeCollisionReport
message CollisionReport
{
double longitude = 1;
double latitude = 2;
double timestamp = 3;//时间, 单位:秒
}

View File

@@ -52,3 +52,128 @@ message SsmStatusInf {
optional string slam_map_ver = 22; //slam地图版本
optional string grid_map_ver = 23; //栅格地图版本
}
enum MessageType {
NOTIFICATION = 0; // ssm发送通知 msg:Notification
OTA_DOWNLOAD_REQUEST = 1; // ssm发送OTA升级提示请求 todo
OTA_DOWNLOAD_RESPONSE = 2; // pad下发OTA升级提示响应 todo
OTA_LOADING_PROGRESS = 3; // ssm上报OTA下载进度, 开始升级后定频上报 todo
OTA_STATUS = 4; // ssm 上报OTA状态 todo
OTA_STATUS_QUERY = 5; // pad查询OTA状态 req:OtaToken resp:OtaStatus
COLD_START_STATUS_REPORT = 6; // 冷启动状态上报 msg:ColdStartState
COLD_START_STATE_QUERY = 7; // 冷启动状态查询 req:None resp:ColdStartState
AUTO_PILOT_INFO = 8; // 自驾命令状态查询 resp:AutoPilotInfo
STATION_STATUS_QUERY = 9; //到站信息查询 req: OrderInfo resp:AutoPilotStation
}
message PadSsmMsg {
required uint64 token = 1; //消息唯一id
required MessageType msg_type = 2; //消息类型
required double timestamp = 3; //消息发送时间, 单位:秒
optional bytes data = 6; // 消息体
}
enum Level {
INFO_MSG = 0;
WARNING_MSG = 1;
ERROR_MSG = 2;
}
message Notification {
required Level level = 1; // 消息等级 0:info, 1:warning, 2:error
required string msg = 2; // 通知
}
enum OtaType {
IMAGE = 1;
FIRMWARE = 2;
MAP = 3;
PROFILE = 4;
}
message OtaDownloadRequest {
required string ota_token = 1; // ota token 唯一标识
required OtaType ota_type = 2; // ota type 1:镜像, 2:固件, 3:地图, 4:配置文件
required bool need_restart = 3; // 是否需要重启 True:需要, False:不需要
required string product_name = 4; // 制品名称
optional double size = 5; // 文件大小 Mb
}
enum IfUpgrade {
IMMEDIATELY = 1;
DELAY = 2;
}
message OtaToken {
required string token = 1; // ota token
}
message OtaDownloadResponse {
required string token = 1; // ota token
required IfUpgrade if_upgrade = 2; // 是否立即升级 1:立即升级 2:暂不升级
}
message OtaLoadingProgess {
required string ota_token = 1; // ota token
required double currentSize = 2; // 当前下载大小
required double totalSize = 3; // 总大小
}
enum UpgradeStatus {
UPGRADE_DEFAULT = 0;
UPGRADE_DOWNLOADING = 1;
UPGRADE_DOWNLOAD_FINISH = 2;
UPGRADE_FINSH = 3;
UPGRADE_FAIL = 4;
}
message OtaStatus {
required OtaDownloadRequest ota_info = 1; // 升级信息
required UpgradeStatus status = 2; // 状态 0:默认(未开始), 1:下载中, 2:下载完成, 3:升级完成, 4:升级失败
optional string reason = 3; // 失败原因
}
enum CSState {
COLD_START_DEFAULT = 0; // 未开始
COLD_START_STARTING = 1; // 启动中
COLD_START_READY = 2; // 就绪
COLD_START_UNREADY = 3; // 有异常未就绪
COLD_START_TIMEOUT = 4; // 超时
}
enum NodeStatus {
NODE_STARTING = 0; // 启动中
NODE_FINISH = 1; // 启动成功
NODE_FAILED = 2; // 启动失败
NODE_TIMEOUT = 3; // 启动超时
}
message ColdStartNode {
required string node_name = 1; //节点名称
required string event_code = 2; //上报事件
required NodeStatus status = 3; //0:启动中, 1:启动成功, 2:启动失败, 3:启动超时
required string desc = 4; //事件描述
}
message ColdStartState {
required CSState process_status = 1; //旧冷启动状态
required CSState event_status = 2; //节点自上报冷启动状态
repeated ColdStartNode node = 3; //冷启动关键节点信息
optional string process_timeout_reason = 4; //旧冷启动超时原因
}
message AutoPilotInfo {
required bool first_autopilot_flag = 1; // 是否首次进自驾
required string order_id = 2; // 订单号
required uint32 count = 3; // 次数
}
message OrderInfo{
required string order_id = 1; //订单号
}
message AutoPilotStation {
required bool arrived_station_flag = 1; //是否到站
optional string order_id = 2; //订单号
}

View File

@@ -39,6 +39,7 @@ import com.zhidao.support.adas.high.protocol.PackData;
import com.zhidao.support.adas.high.protocol.RawData;
import com.zhidao.support.adas.high.protocol.RawPack;
import com.zhidao.support.adas.high.protocol.RawUnpack;
import com.zhidao.support.adas.high.protocol.power.PowerRawPack;
import com.zhidao.support.adas.high.queue.WSByteQueueManager;
import com.zhidao.support.adas.high.queue.WebSocketQueueManager;
import com.zhidao.support.adas.high.socket.FpgaSocket;
@@ -46,6 +47,9 @@ import com.zhidao.support.adas.high.subscribe.SubscribeInterface;
import com.zhidao.support.adas.high.subscribe.SubscribeInterfaceOption;
import com.zhidao.support.adas.high.thread.DispatchHandler;
import com.zhjt.mogo.adas.common.MessageType;
import com.zhjt.mogo.adas.common.power.PowerControlType;
import com.zhjt.mogo.adas.common.power.PowerFrameType;
import com.zhjt.mogo.adas.common.power.PowerUnitChannel;
import com.zhjt.mogo.adas.data.AdasConstants;
import com.zhjt.mogo.adas.data.AiCloudTask;
import com.zhjt.mogo.adas.data.bean.AdasParam;
@@ -70,7 +74,6 @@ import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import bag_manager.BagManagerOuterClass;
import chassis.Chassis;
import chassis.SpecialVehicleTaskCmdOuterClass;
import common.HeaderOuterClass;
import function_state_management.FSMStatusReasonQueryOuterClass;
@@ -78,6 +81,7 @@ import mogo.telematics.ParamSetCmdOuterClass;
import mogo.telematics.pad.MessagePad;
import mogo.yycp.paralleldriving.protocol.ParallelDrivingRequest;
import okio.ByteString;
import system_master.SsmInfo;
/**
* @ProjectName: lib-adas-fpga
@@ -150,6 +154,7 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec
private final ReceivedAckManager receivedAckManager = new ReceivedAckManager();//消息回执
private final AtomicBoolean isInitConfigure = new AtomicBoolean(false);//是否进行配置初始化
private PowerRawPack powerRawPack;
public void setOnMultiDeviceListener(OnMultiDeviceListener onMultiDeviceListener) {
this.onMultiDeviceListener = onMultiDeviceListener;
@@ -1177,13 +1182,14 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec
* @param mode 1: enter autopilot mode, 0: quit autopilot mode
* @param source 命令来源: 0: pad模拟, 1: pad业务, 2:aicloud, 3:魔方(清扫车MAP Version==332以及MAP Version>=350其他车型目前未上线)
* @param routeInfo 自动驾驶路径信息
* @param cmdInfo 自驾命令信息(订单号,是否首次进自驾等)
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID和SessionID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendAutoPilotModeReq(int mode, int source, MessagePad.RouteInfo routeInfo) {
public long sendAutoPilotModeReq(int mode, int source, @Nullable MessagePad.RouteInfo routeInfo, @Nullable MessagePad.CmdInfo cmdInfo) {
MessageId messageId = MessageId.build(MessageType.TYPE_SEND_SET_AUTOPILOT_MODE_REQ);
MessagePad.SetAutopilotModeReq.Builder builder = MessagePad.SetAutopilotModeReq.newBuilder();
builder.setMode(mode);
@@ -1191,6 +1197,9 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec
if (routeInfo != null)
builder.setRouteInfo(routeInfo);
builder.setSessionId(messageId.id);
if (cmdInfo != null) {
builder.setCmdInfo(cmdInfo);
}
MessagePad.SetAutopilotModeReq req = builder.build();
if (autopilotReview != null) autopilotReview.onAutopilotCommandTrigger(req);
return sendPBMessage(MessageType.TYPE_SEND_SET_AUTOPILOT_MODE_REQ, req.toByteArray(), messageId);
@@ -1642,9 +1651,9 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec
* 发送 轨迹下载请求
* 此方法存在域控回执,监听{@link OnAdasListener#onReceiveReceivedAck(ReceivedAck)}回调.使用方法:将此方法的返回值与{@link ReceivedAck#getMsgId()}进行比较,如果相同判断{@link ReceivedAck#getStatus()}是否等于{@link ReceivedAck.Status#NORMAL}详情参见CheckSystemView中的onReceiveReceivedAck
*
* @param line 线路相关参数详情见PB message_pad.proto -> Line
* @param downloadType 下载类型: 0:正常下载 1:预下载
* @param routeInfo 20240523 进行自动算路,务必下单时候携带自动驾驶路径信息,否则可不填!
* @param line 线路相关参数详情见PB message_pad.proto -> Line
* @param downloadType 下载类型: 0:正常下载 1:预下载
* @param routeInfo 20240523 进行自动算路,务必下单时候携带自动驾驶路径信息,否则可不填!
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
@@ -2874,5 +2883,117 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec
return sendAiCloudTaskCmd(MessageType.TYPE_SEND_PARALLEL_DRIVING_REQ, AiCloudTask.MessageType.ParallelDrivingCmd, reqNo, parallelRequest.toByteString());
}
private long sendPowerUnit(PowerFrameType frameType, byte[] data) {
if (powerRawPack == null) {
powerRawPack = new PowerRawPack();
}
byte[] temp = powerRawPack.pack(frameType, data);
return sendPBMessage(MessageType.TYPE_SEND_POWER_UNIT, temp);
}
/**
* 发送电源状态查询请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendPowerUnitSTSRequest() {
return sendPowerUnit(PowerFrameType.STS_REQUEST, null);
}
/**
* 发送单通道电源控制请求
*
* @param channel 通道
* @param cmd 0关闭1打开
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendPowerUnitSingleChannelControl(PowerUnitChannel channel, int cmd) {
byte[] type = ByteUtil.set16bitUnsignedValueLittleEndian(PowerControlType.SINGLE_CHANNEL_CONTROL.value);
byte[] channelB = ByteUtil.set8bitUnsignedValue(channel.index);
byte[] cmdB = ByteUtil.set8bitUnsignedValue(cmd);
byte[] temp = ByteUtil.concatBytes(type, channelB);
temp = ByteUtil.concatBytes(temp, cmdB);
return sendPowerUnit(PowerFrameType.CMD_REQUEST, temp);
}
@Override
public long sendPowerUnitReset() {
byte[] type = ByteUtil.set16bitUnsignedValueLittleEndian(PowerControlType.RESET_CONTROL.value);
byte[] reserved = ByteUtil.set16bitUnsignedValueLittleEndian(0);
byte[] temp = ByteUtil.concatBytes(type, reserved);
return sendPowerUnit(PowerFrameType.CMD_REQUEST, temp);
}
/**
* 发送SSM功能消息
*
* @param isQuery 是否是查询功能
* @param data 数据
* @return
*/
private long sendSsmFuncMsg(boolean isQuery, system_master.SsmInfo.MessageType type, @Nullable com.google.protobuf.ByteString data) {
MessageType messageType = isQuery ? MessageType.TYPE_SEND_SSM_FUNC_STATUS_QUERY : MessageType.TYPE_SEND_SSM_FUNC_MSG;
MessageId messageId = MessageId.build(messageType);
SsmInfo.PadSsmMsg.Builder builder = SsmInfo.PadSsmMsg.newBuilder();
builder.setToken(messageId.id);
builder.setMsgType(type);
builder.setTimestamp(System.currentTimeMillis() / 1000D);
if (data != null && !data.isEmpty()) {
builder.setData(data);
}
SsmInfo.PadSsmMsg req = builder.build();
return sendPBMessage(messageType, req.toByteArray(), messageId);
}
/**
* 查询冷启动状态
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendSsmFuncQueryColdStartState() {
return sendSsmFuncMsg(true, system_master.SsmInfo.MessageType.COLD_START_STATE_QUERY, null);
}
/**
* 查询自驾命令状态
* 查询:是否首次进自驾、订单号、次数
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendSsmFuncQueryAutoPilotInfo() {
return sendSsmFuncMsg(true, system_master.SsmInfo.MessageType.AUTO_PILOT_INFO, null);
}
/**
* 查询到站信息
*
* @param orderId 订单号
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendSsmFuncQueryAutoPilotStation(@NonNull String orderId) {
return sendSsmFuncMsg(true, system_master.SsmInfo.MessageType.STATION_STATUS_QUERY, SsmInfo.OrderInfo.newBuilder().setOrderId(orderId).build().toByteString());
}
}

View File

@@ -16,6 +16,7 @@ import com.zhidao.support.adas.high.common.MessageIdGenerator;
import com.zhidao.support.adas.high.common.ReceiveTimeoutManager;
import com.zhidao.support.adas.high.common.autopilot.ability.AutopilotAbilityManager;
import com.zhjt.mogo.adas.common.MessageType;
import com.zhjt.mogo.adas.common.power.PowerUnitChannel;
import com.zhjt.mogo.adas.data.Adas;
import com.zhjt.mogo.adas.data.AdasConstants;
import com.zhjt.mogo.adas.data.bean.AdasParam;
@@ -397,14 +398,15 @@ public class AdasManager implements IAdasNetCommApi {
* @param mode 1: enter autopilot mode, 0: quit autopilot mode
* @param source 命令来源: 0: pad模拟, 1: pad业务, 2:aicloud, 3:魔方(清扫车MAP Version==332以及MAP Version>=350其他车型目前未上线)
* @param routeInfo 自动驾驶路径信息
* @param cmdInfo 自驾命令信息(订单号,是否首次进自驾等)
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID和SessionID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendAutoPilotModeReq(int mode, int source, MessagePad.RouteInfo routeInfo) {
return mChannel == null ? -1L : mChannel.sendAutoPilotModeReq(mode, source, routeInfo);
public long sendAutoPilotModeReq(int mode, int source, @Nullable MessagePad.RouteInfo routeInfo, @Nullable MessagePad.CmdInfo cmdInfo) {
return mChannel == null ? -1L : mChannel.sendAutoPilotModeReq(mode, source, routeInfo, cmdInfo);
}
/**
@@ -1731,6 +1733,81 @@ public class AdasManager implements IAdasNetCommApi {
return mChannel == null ? -1L : mChannel.sendParallelDrivingReq(reqNo, parallelRequest);
}
/**
* 发送电源状态查询请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendPowerUnitSTSRequest() {
return mChannel == null ? -1L : mChannel.sendPowerUnitSTSRequest();
}
/**
* 发送单通道电源控制请求
*
* @param channel 通道
* @param cmd 0关闭1打开
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendPowerUnitSingleChannelControl(PowerUnitChannel channel, int cmd) {
return mChannel == null ? -1L : mChannel.sendPowerUnitSingleChannelControl(channel, cmd);
}
@Override
public long sendPowerUnitReset() {
return mChannel == null ? -1L : mChannel.sendPowerUnitReset();
}
/**
* 查询冷启动状态
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendSsmFuncQueryColdStartState() {
return mChannel == null ? -1L : mChannel.sendSsmFuncQueryColdStartState();
}
/**
* 查询自驾命令状态
* 查询:是否首次进自驾、订单号、次数
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendSsmFuncQueryAutoPilotInfo() {
return mChannel == null ? -1L : mChannel.sendSsmFuncQueryAutoPilotInfo();
}
/**
* 查询到站信息
*
* @param orderId 订单号
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
@Override
public long sendSsmFuncQueryAutoPilotStation(@NonNull String orderId) {
return mChannel == null ? -1L : mChannel.sendSsmFuncQueryAutoPilotStation(orderId);
}
/**
* 查询节点状态
*

View File

@@ -7,6 +7,7 @@ import com.zhidao.support.adas.high.bean.VersionCompatibility;
import com.zhidao.support.adas.high.common.Constants;
import com.zhidao.support.adas.high.common.Define;
import com.zhjt.mogo.adas.common.MessageType;
import com.zhjt.mogo.adas.common.power.PowerUnitChannel;
import com.zhjt.mogo.adas.data.AdasConstants;
import com.zhjt.mogo.adas.data.bean.AdasParam;
import com.zhjt.mogo.adas.data.bean.ReceivedAck;
@@ -22,7 +23,6 @@ import java.util.Map;
import java.util.Set;
import bag_manager.BagManagerOuterClass;
import chassis.Chassis;
import chassis.SpecialVehicleTaskCmdOuterClass;
import mogo.telematics.pad.MessagePad;
import mogo.yycp.paralleldriving.protocol.ParallelDrivingRequest;
@@ -169,12 +169,13 @@ public interface IAdasNetCommApi {
* @param mode 1: enter autopilot mode, 0: quit autopilot mode
* @param source 命令来源: 0: pad模拟, 1: pad业务, 2:aicloud, 3:魔方(清扫车MAP Version==332以及MAP Version>=350其他车型目前未上线)
* @param routeInfo 自动驾驶路径信息
* @param cmdInfo 自驾命令信息(订单号,是否首次进自驾等)
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID和SessionID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendAutoPilotModeReq(int mode, int source, MessagePad.RouteInfo routeInfo);
long sendAutoPilotModeReq(int mode, int source, @Nullable MessagePad.RouteInfo routeInfo, @Nullable MessagePad.CmdInfo cmdInfo);
/**
@@ -468,15 +469,15 @@ public interface IAdasNetCommApi {
* 发送 轨迹下载请求
* 此方法存在域控回执,监听{@link OnAdasListener#onReceiveReceivedAck(ReceivedAck)}回调.使用方法:将此方法的返回值与{@link ReceivedAck#getMsgId()}进行比较,如果相同判断{@link ReceivedAck#getStatus()}是否等于{@link ReceivedAck.Status#NORMAL}详情参见CheckSystemView中的onReceiveReceivedAck
*
* @param line 线路相关参数详情见PB message_pad.proto -> Line
* @param downloadType 下载类型: 0:正常下载 1:预下载
* @param routeInfo 20240523 进行自动算路,务必下单时候携带自动驾驶路径信息,否则可不填!
* @param line 线路相关参数详情见PB message_pad.proto -> Line
* @param downloadType 下载类型: 0:正常下载 1:预下载
* @param routeInfo 20240523 进行自动算路,务必下单时候携带自动驾驶路径信息,否则可不填!
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendTrajectoryDownloadReq(MessagePad.Line line, int downloadType, MessagePad.RouteInfo routeInfo);
long sendTrajectoryDownloadReq(MessagePad.Line line, int downloadType, MessagePad.RouteInfo routeInfo);
/**
* 发送 状态查询请求
@@ -1241,6 +1242,70 @@ public interface IAdasNetCommApi {
*/
long sendParallelDrivingReq(@NonNull String reqNo, @NonNull ParallelDrivingRequest.ParallelRequest parallelRequest);
/**
* 发送电源状态查询请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendPowerUnitSTSRequest();
/**
* 发送单通道电源控制请求
*
* @param channel 通道
* @param cmd 0关闭1打开
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendPowerUnitSingleChannelControl(PowerUnitChannel channel, int cmd);
/**
* 发送电源控制重置请求
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendPowerUnitReset();
/**
* 查询冷启动状态
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendSsmFuncQueryColdStartState();
/**
* 查询自驾命令状态
* 查询:是否首次进自驾、订单号、次数
*
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendSsmFuncQueryAutoPilotInfo();
/**
* 查询到站信息
*
* @param orderId 订单号
* @return 消息是否添加到WS消息发送队列返回值为非0的正整数时表示下发消息的消息ID
* * >=0表示添加到WS发送消息队列
* * =0表示乘客屏模式添加到WS发送消息队列
* * -1L添加到WS发送消息队列失败
*/
long sendSsmFuncQueryAutoPilotStation(@NonNull String orderId);
// TODO 需求暂停 待讨论
// boolean getRoutes();

View File

@@ -7,6 +7,7 @@ import com.google.protobuf.ByteString;
import com.mogo.support.obu.ObuScene;
import com.zhidao.support.adas.high.common.ProtocolStatus;
import com.zhjt.mogo.adas.common.MessageType;
import com.zhjt.mogo.adas.common.power.PowerProtocolStatus;
import com.zhjt.mogo.adas.data.AdasConstants;
import com.zhjt.mogo.adas.data.AiCloudTask;
import com.zhjt.mogo.adas.data.bean.AdasParam;
@@ -15,6 +16,7 @@ import com.zhjt.mogo.adas.data.bean.LaunchConditionData;
import com.zhjt.mogo.adas.data.bean.NodeStateInfo;
import com.zhjt.mogo.adas.data.bean.ReceivedAck;
import com.zhjt.mogo.adas.data.bean.UnableLaunchReason;
import com.zhjt.mogo.adas.data.bean.power.PowerData;
import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable;
import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask;
import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus;
@@ -205,6 +207,38 @@ public interface OnAdasListener {
@Deprecated
void onWarn(MessagePad.Header header, MessagePad.Warn warn);
/**
* 冷启动状态变更上报以及查询状态
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param isQuery 是否是查询 ture查询相应的结果 false表示状态变动域控主动推送
* @param coldStartState 数据 null表示 PadSsmMsg中的消息体为null
*/
void onColdStartState(MessagePad.Header header, long token, long timestamp, boolean isQuery, @Nullable SsmInfo.ColdStartState coldStartState);
/**
* 自驾命令状态查询响应
* 返回 是否首次进自驾、订单号、次数
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotInfo 数据 null表示 PadSsmMsg中的消息体为null
*/
void onAutoPilotInfo(MessagePad.Header header, long token, long timestamp, @Nullable SsmInfo.AutoPilotInfo autoPilotInfo);
/**
* 到站信息查询响应
*
* @param header 头
* @param token 唯一消息ID
* @param timestamp 消息发送时间 单位:毫秒
* @param autoPilotStation 数据 null表示 PadSsmMsg中的消息体为null
*/
void onAutoPilotStation(MessagePad.Header header, long token, long timestamp, @Nullable SsmInfo.AutoPilotStation autoPilotStation);
/**
* 到站提醒 自动驾驶站点
*
@@ -538,11 +572,23 @@ public interface OnAdasListener {
/**
* 车道线
*
* @param header
* @param header 头
* @param laneMarks 数据
*/
void onLaneMarksTran(@NonNull MessagePad.Header header, @NonNull LaneMarkOuterClass.LaneMarks laneMarks);
/**
* 电源盒协议接口
* <p>
* {@link PowerData}使用方法
* 1.先判断数据中的{@link PowerData#protocolStatus} 是否是 {@link PowerProtocolStatus#SUCCEED} 如果是则表示数据解析正常可以正常使用,进行下一步
* 2.判断 {@link PowerData#frameType} 数据类型
*
* @param header 头
* @param data 数据
*/
void onPowerUnit(@NonNull MessagePad.Header header, @NonNull PowerData data);
/**
* 所连接的域控的节点状态信息
* 目前包含状态 节点是否存在;节点是否超时;

View File

@@ -53,6 +53,8 @@ public class MyMessageFactory implements IMyMessageFactory {
private IMsg v2nNioOtherRetrogradeEventMessage;//V2N NIO他车逆行路侧
private IMsg v2nNioCongestionEventMessage;//V2N NIO拥堵事件
private IMsg laneMarksTranMessage;//车道线
private IMsg powerUnitMessage;//电源模块
private IMsg padSsmFuncMsgMessage;//SSM功能
private final AutopilotReview autopilotReview;
private final TurnLightState lightLeft = new TurnLightState();
@@ -303,6 +305,18 @@ public class MyMessageFactory implements IMyMessageFactory {
laneMarksTranMessage = new LaneMarksTranMessage();
}
return laneMarksTranMessage;
} else if (messageType == MessageType.TYPE_RECEIVE_POWER_UNIT.typeCode) {
//电源模块响应
if (powerUnitMessage == null) {
powerUnitMessage = new PowerUnitMessage();
}
return powerUnitMessage;
} else if (messageType == MessageType.TYPE_RECEIVE_SSM_FUNC_MSG.typeCode || messageType == MessageType.TYPE_RECEIVE_SSM_FUNC_STATUS_QUERY.typeCode) {
//SSM功能
if (padSsmFuncMsgMessage == null) {
padSsmFuncMsgMessage = new PadSsmFuncMsgMessage();
}
return padSsmFuncMsgMessage;
} else {
//MessageType.TYPE_DEFAULT.typeCode
return null;

View File

@@ -0,0 +1,59 @@
package com.zhidao.support.adas.high.msg;
import android.os.SystemClock;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.zhidao.support.adas.high.AdasChannel;
import com.zhidao.support.adas.high.OnAdasListener;
import com.zhidao.support.adas.high.common.CupidLogUtils;
import com.zhidao.support.adas.high.protocol.RawData;
import system_master.SsmInfo;
/**
* SSM功能相关
*/
public class PadSsmFuncMsgMessage extends MyAbstractMessageHandler {
@Override
public void handlerMsg(RawData raw, OnAdasListener adasListener) throws InvalidProtocolBufferException {
SsmInfo.PadSsmMsg padSsmMsg = SsmInfo.PadSsmMsg.parser().parseFrom(raw.originalData.toByteArray(), raw.getOffsetValue(), raw.getPackageLengthValue() - raw.getOffsetValue());
AdasChannel.calculateTimeConsumingOnDispatchRaw("SSM功能", raw.receiveTime);
long nowTime = 0;
if (CupidLogUtils.isEnableLog())
nowTime = SystemClock.elapsedRealtime();
SsmInfo.MessageType type = padSsmMsg.getMsgType();
ByteString data = padSsmMsg.getData();
long timestamp = (long) (padSsmMsg.getTimestamp() * 1000L);
if (type == SsmInfo.MessageType.COLD_START_STATUS_REPORT || type == SsmInfo.MessageType.COLD_START_STATE_QUERY) {
//冷启动状态上报
SsmInfo.ColdStartState coldStartState = null;
if (!data.isEmpty()) {
coldStartState = SsmInfo.ColdStartState.parseFrom(data);
}
if (adasListener != null) {
adasListener.onColdStartState(raw.getHeader(), padSsmMsg.getToken(), timestamp, type == SsmInfo.MessageType.COLD_START_STATE_QUERY, coldStartState);
}
} else if (type == SsmInfo.MessageType.AUTO_PILOT_INFO) {
//自驾命令状态查询响应
SsmInfo.AutoPilotInfo autoPilotInfo = null;
if (!data.isEmpty()) {
autoPilotInfo = SsmInfo.AutoPilotInfo.parseFrom(data);
}
if (adasListener != null) {
adasListener.onAutoPilotInfo(raw.getHeader(), padSsmMsg.getToken(), timestamp, autoPilotInfo);
}
} else if (type == SsmInfo.MessageType.STATION_STATUS_QUERY) {
//到站信息查询响应
SsmInfo.AutoPilotStation autoPilotStation = null;
if (!data.isEmpty()) {
autoPilotStation = SsmInfo.AutoPilotStation.parseFrom(data);
}
if (adasListener != null) {
adasListener.onAutoPilotStation(raw.getHeader(), padSsmMsg.getToken(), timestamp, autoPilotStation);
}
}
AdasChannel.calculateTimeConsumingBusiness("SSM功能", nowTime);
}
}

View File

@@ -0,0 +1,38 @@
package com.zhidao.support.adas.high.msg;
import android.os.SystemClock;
import com.google.protobuf.InvalidProtocolBufferException;
import com.zhidao.support.adas.high.AdasChannel;
import com.zhidao.support.adas.high.OnAdasListener;
import com.zhidao.support.adas.high.common.CupidLogUtils;
import com.zhidao.support.adas.high.protocol.RawData;
import com.zhidao.support.adas.high.protocol.power.PowerRawUnpack;
import com.zhjt.mogo.adas.data.bean.power.PowerData;
import okio.ByteString;
/**
* 电源管理
*/
public class PowerUnitMessage extends MyAbstractMessageHandler {
private static final String TAG = PowerUnitMessage.class.getSimpleName();
private final PowerRawUnpack unpack = new PowerRawUnpack();
public PowerUnitMessage() {
}
@Override
public void handlerMsg(RawData raw, OnAdasListener adasListener) throws InvalidProtocolBufferException {
ByteString data = ByteString.of(raw.originalData.toByteArray(), raw.getOffsetValue(), raw.getPackageLengthValue() - raw.getOffsetValue());
PowerData rawData = unpack.unpack(data);
AdasChannel.calculateTimeConsumingOnDispatchRaw("电源盒", raw.receiveTime);
long nowTime = 0;
if (CupidLogUtils.isEnableLog())
nowTime = SystemClock.elapsedRealtime();
if (adasListener != null) {
adasListener.onPowerUnit(raw.getHeader(), rawData);
}
AdasChannel.calculateTimeConsumingBusiness("电源盒", nowTime);
}
}

View File

@@ -0,0 +1,92 @@
package com.zhidao.support.adas.high.protocol.power;
/**
* 电源管理协议
*/
public class PowerMessageProtocol {
public static final int FRAME_HEAD = 0xAA55;
public static final int CHANNEL_NORMAL_END_INDEX = 46;//普通通道最大索引值包含46
public static final int CHANNEL_CAMERA_START_INDEX = 51;//相机通道最小索引值包含51
public static final byte KEY_SEND = 0x4D;
public static final byte KEY_RECEIVE = 0x47;
public static void xor(byte[] data,byte key) {
for (int i = 0; i < data.length; i++) {
data[i] ^= key;
}
}
/**
* 帧头长度
* 固定为0xAA55
*
* @return 字节个数
*/
public int getFrameHeaderLength() {
return 2;
}
/**
* 帧总长度长度
* 最小值12对应于数据区长度为0的帧
*
* @return 字节个数
*/
public int getTotalLengthLength() {
return 2;
}
/**
* 帧类型长度0x0000保留0xFFFF保留
* 客户端STS请求帧0x0040服务器响应正常帧0x0840
* 客户端CMD请求帧0x0044服务器响应正常帧0x0844
* 服务器检测到帧异常响应异常ERR帧0x0800
*
* @return 字节个数
*/
public int getFrameTypeLength() {
return 2;
}
/**
* 保留字节长度
* 定为0x0000
*
* @return 字节个数
*/
public int getReservedLength() {
return 2;
}
/**
* 数据区长度
* 数据区长度必须为4的整倍数可为0字节
*
* @param totalLength 数据包总长度
* @return 字节个数
*/
public int getDataBlocksLength(int totalLength) {
return totalLength - getFrameHeaderLength() - getTotalLengthLength() - getFrameTypeLength() - getReservedLength() - getCheckValueLength();
}
/**
* 帧校验值长度,对校验值之前的所有数据进行校验,
* 校验值计算初步定为:
* 1帧所有数据分割成32位长4字节的块
* 2对这些32位长的块进行二进制"异或"操作;
* 3取"异或"操作的结果作为校验值。
*
* @return 字节个数
*/
public int getCheckValueLength() {
return 4;
}
}

View File

@@ -0,0 +1,72 @@
package com.zhidao.support.adas.high.protocol.power;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.zhjt.mogo.adas.common.power.PowerFrameType;
import com.zhjt.mogo.adas.utils.ByteUtil;
/**
* 数据打包
*/
public class PowerRawPack {
private static final String TAG = PowerRawPack.class.getSimpleName();
private final PowerMessageProtocol messageProtocol;
private final byte[] reservedData;
public PowerRawPack() {
messageProtocol = new PowerMessageProtocol();
reservedData = new byte[messageProtocol.getReservedLength()];
}
public synchronized byte[] pack(@NonNull PowerFrameType frameType, @Nullable byte[] data) {
if (frameType == PowerFrameType.UNKNOWN) return null;
int dataBlocksLength = 0;
if (data != null && data.length != 0) {
dataBlocksLength = data.length;
}
//除校验位4个字节所有的长度
int packageLength = messageProtocol.getFrameHeaderLength() + messageProtocol.getTotalLengthLength() + messageProtocol.getFrameTypeLength() + messageProtocol.getReservedLength() + dataBlocksLength;
byte[] msg = new byte[packageLength];
byte[] frameHeadData = ByteUtil.set16bitUnsignedValueLittleEndian(PowerMessageProtocol.FRAME_HEAD);
//添加帧头
System.arraycopy(frameHeadData, 0, msg, 0, messageProtocol.getFrameHeaderLength());
byte[] packageLengthData = ByteUtil.set16bitUnsignedValueLittleEndian(packageLength + messageProtocol.getCheckValueLength());
//添加总长度
System.arraycopy(packageLengthData, 0, msg, messageProtocol.getFrameHeaderLength(), messageProtocol.getTotalLengthLength());
byte[] type = ByteUtil.set16bitUnsignedValueLittleEndian(frameType.type);
//添加帧类型
System.arraycopy(type, 0, msg, messageProtocol.getFrameHeaderLength() + messageProtocol.getTotalLengthLength(), messageProtocol.getFrameTypeLength());
//添加保留位
System.arraycopy(reservedData, 0, msg, messageProtocol.getFrameHeaderLength() + messageProtocol.getTotalLengthLength() + messageProtocol.getFrameTypeLength(), messageProtocol.getReservedLength());
if (data != null && data.length != 0) {
PowerMessageProtocol.xor(data, PowerMessageProtocol.KEY_SEND);
System.arraycopy(data, 0, msg, messageProtocol.getFrameHeaderLength() + messageProtocol.getTotalLengthLength() + messageProtocol.getFrameTypeLength() + messageProtocol.getReservedLength(), data.length);
}
int xor = xorCheck(msg);
return ByteUtil.concatBytes(msg, ByteUtil.set32bitUnsignedValueValueLittleEndian(xor));
}
//异或校验
private int xorCheck(byte[] bytes) {
int xorChecksum = 0;
//异或校验
for (int i = 0; i < bytes.length; i += 4) {
byte[] tInt = new byte[4];
tInt[0] = bytes[i];
tInt[1] = bytes[i + 1];
tInt[2] = bytes[i + 2];
tInt[3] = bytes[i + 3];
int datum = ByteUtil.get32bitUnsignedValueLittleEndian(tInt);
xorChecksum ^= datum; // 对每个字节进行异或操作
}
return xorChecksum;
}
}

View File

@@ -0,0 +1,290 @@
package com.zhidao.support.adas.high.protocol.power;
import androidx.annotation.NonNull;
import com.zhjt.mogo.adas.common.power.PowerControlType;
import com.zhjt.mogo.adas.common.power.PowerError;
import com.zhjt.mogo.adas.common.power.PowerFrameType;
import com.zhjt.mogo.adas.common.power.PowerProtocolStatus;
import com.zhjt.mogo.adas.common.power.PowerUnitChannel;
import com.zhjt.mogo.adas.data.bean.power.PowerCommandExecuteState;
import com.zhjt.mogo.adas.data.bean.power.PowerData;
import com.zhjt.mogo.adas.data.bean.power.PowerErrorData;
import com.zhjt.mogo.adas.data.bean.power.PowerUnitState;
import com.zhjt.mogo.adas.utils.ByteUtil;
import java.util.ArrayList;
import java.util.List;
import okio.ByteString;
/**
* 电源管理数据拆包
*/
public class PowerRawUnpack {
private static final String TAG = PowerRawUnpack.class.getSimpleName();
private final PowerMessageProtocol messageProtocol;
public PowerRawUnpack() {
messageProtocol = new PowerMessageProtocol();
}
public PowerData unpack(@NonNull ByteString bytes) {
byte[] data = bytes.toByteArray();
int size = bytes.size();
if (size == 0) {
return PowerData.createError(data, PowerProtocolStatus.CHECK_FAILED_PACKAGE_LENGTH);
}
if (size % 4 != 0) {
return PowerData.createError(data, PowerProtocolStatus.DATA_LENGTH_NOT_NOTE_OF4);
}
int frameHeaderLength = messageProtocol.getFrameHeaderLength();
int totalLengthLength = messageProtocol.getTotalLengthLength();
int frameTypeLength = messageProtocol.getFrameTypeLength();
int reservedLength = messageProtocol.getReservedLength();
int checkValueLength = messageProtocol.getCheckValueLength();
try {
int localXor = xorCheck(bytes, checkValueLength);
// Log.i(TAG, "计算得出的异域校验值=" + localXor);
ByteString xor = bytes.substring(size - checkValueLength, size);
int serverXor = ByteUtil.get32bitUnsignedValueLittleEndian(xor.toByteArray());
// Log.i(TAG, "数据中的异域校验值=" + serverXor);
if (localXor != serverXor) {
return PowerData.createError(data, PowerProtocolStatus.XOR_CHECK_FAILED);
}
//读取FrameHeader
ByteString frameHeaderByteString;
if (size < frameHeaderLength) {
frameHeaderByteString = bytes;
} else {
frameHeaderByteString = bytes.substring(0, frameHeaderLength);
}
int frameHeader = ByteUtil.get16bitUnsignedValueLittleEndian(frameHeaderByteString.toByteArray());
// Log.w(TAG, "WS frameHeader=" + frameHeaderByteString.hex());
// Log.w(TAG, "WS frameHeader=" + frameHeader);
if (frameHeader == PowerMessageProtocol.FRAME_HEAD) {
ByteString totalLengthByteString = bytes.substring(frameHeaderLength, frameHeaderLength + totalLengthLength);
int totalLength = ByteUtil.get16bitUnsignedValueLittleEndian(totalLengthByteString.toByteArray());
// Log.w(TAG, "WS TotalLength=" + totalLength);
if (size != totalLength) {
return PowerData.createError(data, PowerProtocolStatus.CHECK_FAILED_PACKAGE_LENGTH);
}
ByteString frameTypeByteString = bytes.substring(frameHeaderLength + totalLengthLength, frameHeaderLength + totalLengthLength + frameTypeLength);
int typeValue = ByteUtil.get16bitUnsignedValueLittleEndian(frameTypeByteString.toByteArray());
PowerFrameType frameType = PowerFrameType.getPowerFrameType(typeValue);
// Log.w(TAG, "WS FrameType=" + frameType);
if (frameType == PowerFrameType.UNKNOWN) {
return PowerData.createError(data, PowerProtocolStatus.POWER_FRAME_TYPE_UNKNOWN);
}
ByteString reservedByteString = bytes.substring(frameHeaderLength + totalLengthLength + frameTypeLength, frameHeaderLength + totalLengthLength + frameTypeLength + reservedLength);
int reserved = ByteUtil.get16bitUnsignedValueLittleEndian(reservedByteString.toByteArray());
int dataBlocksLength = messageProtocol.getDataBlocksLength(totalLength);
ByteString dataBlocksByteString = bytes.substring(frameHeaderLength + totalLengthLength + frameTypeLength + reservedLength, frameHeaderLength + totalLengthLength + frameTypeLength + reservedLength + dataBlocksLength);
byte[] dataBlocks = dataBlocksByteString.toByteArray();
PowerMessageProtocol.xor(dataBlocks, PowerMessageProtocol.KEY_RECEIVE);
dataBlocksByteString = ByteString.of(dataBlocks);
// Log.i(TAG, dataBlocks.length + " 负载数据=" + ByteUtil.byteArrToHex(dataBlocks));
PowerErrorData errorData = null;
List<PowerUnitState> states = null;
PowerCommandExecuteState executeState = null;
if (frameType == PowerFrameType.ERROR_RESPONSE) {
errorData = unpackErrorData(dataBlocksByteString);
if (errorData == null) {
return PowerData.createError(data, PowerProtocolStatus.PAYLOAD_DATA_PARSE_FAILED);
}
} else if (frameType == PowerFrameType.STS_RESPONSE) {
states = unpackSTSResponseData(dataBlocksByteString);
if (states == null) {
return PowerData.createError(data, PowerProtocolStatus.PAYLOAD_DATA_PARSE_FAILED);
}
} else if (frameType == PowerFrameType.CMD_RESPONSE) {
executeState = unpackCommandExecuteState(dataBlocksByteString);
if (executeState == null) {
return PowerData.createError(data, PowerProtocolStatus.PAYLOAD_DATA_PARSE_FAILED);
}
}
PowerData powerData = PowerData.create(data, frameHeader, totalLength, frameType, reserved, dataBlocks, serverXor);
if (errorData != null) {
powerData.setPowerErrorData(errorData);
}
if (states != null) {
powerData.setPowerUnitStates(states);
}
if (executeState != null) {
powerData.setExecuteState(executeState);
}
return powerData;
} else {
return PowerData.createError(data, PowerProtocolStatus.CHECK_FAILED_FRAME_HEADER);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
return PowerData.createError(data, PowerProtocolStatus.DATA_PARSE_FAILED);
}
}
private PowerCommandExecuteState unpackCommandExecuteState(ByteString bytes) {
try {
ByteString controlTypeByteString = bytes.substring(0, 2);
int controlTypeValue = ByteUtil.get16bitUnsignedValueLittleEndian(controlTypeByteString.toByteArray());
PowerControlType controlType = PowerControlType.getPowerControlType(controlTypeValue);
// Log.w(TAG, "controlType=" + controlType);
if (controlType == PowerControlType.SINGLE_CHANNEL_CONTROL_RESPONSE) {
int channelIndex = ByteUtil.get8bitUnsignedValue(2, bytes.toByteArray());
PowerUnitChannel channel = PowerUnitChannel.getPowerUnitChannel(channelIndex);
byte state = bytes.getByte(3);
int executeState = ByteUtil.getBit(state, 0);
int sendPowerState = ByteUtil.getBit(state, 1);
int actualPowerState = (state & 0x0c) >> 2;
int faultState = (state & 0xF0) >> 4;
return new PowerCommandExecuteState(controlType, executeState == 1, channel, sendPowerState, actualPowerState, faultState);
} else if (controlType == PowerControlType.MULTI_CHANNEL_CONTROL_RESPONSE || controlType == PowerControlType.RESET_CONTROL_RESPONSE) {
byte state = bytes.getByte(3);
int executeState = ByteUtil.getBit(state, 0);
return new PowerCommandExecuteState(controlType, executeState == 1);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private List<PowerUnitState> unpackSTSResponseData(ByteString bytes) {
try {
List<PowerUnitState> list = initPowerUnitStateList();
int channelBeginIndex = 0;//通道1~46索引开始
int channelEndIndex = channelBeginIndex + 8 * 3;//通道1~46索引结束
int currentProtectionStateBeginIndex = channelEndIndex;//1~46电流保护索引开始
int currentProtectionStateEndIndex = currentProtectionStateBeginIndex + 8;//1~46电流保护索引结束
int currentValueBeginIndex = currentProtectionStateEndIndex;//1~46电流值索引开始
int currentValueEndIndex = currentProtectionStateEndIndex + 8 * 16;//1~46电流值索引结束
int cameraChannelBeginIndex = currentValueEndIndex;//通道51~58索引开始
int cameraChannelEndIndex = cameraChannelBeginIndex + 8 * 2;//通道51~66索引结束
//获取索引1~46的开关状态以及故障状态
ByteString channelState = bytes.substring(channelBeginIndex, channelEndIndex);
// Log.i(TAG, channelState.size() + " 电源数据=" + ByteUtil.byteArrToHex(channelState.toByteArray()));
for (int i = 0; i < channelState.size(); i++) {
byte data = channelState.getByte(i);
int index = i * 2 + 1;
for (int j = 0; j < 2; j++) {
PowerUnitChannel channel = PowerUnitChannel.getPowerUnitChannel(index + j);
if (channel.index > PowerUnitChannel.UNKNOWN.index && channel.index <= PowerMessageProtocol.CHANNEL_NORMAL_END_INDEX) {
int faultState = (data >> j * 4) & 0x03;
int powerState = (data >> j * 4 + 2) & 0x03;
int pos = list.indexOf(new PowerUnitState(channel));
if (pos != -1) {
PowerUnitState powerUnitState = list.get(pos);
powerUnitState.setFaultState(faultState);
powerUnitState.setPowerState(powerState);
}
}
}
}
//获取索引1~46的电流保护状态
ByteString currentProtectionState = bytes.substring(currentProtectionStateBeginIndex, currentProtectionStateEndIndex);
// Log.i(TAG, currentProtectionState.size() + " 电源保护数据=" + ByteUtil.byteArrToHex(currentProtectionState.toByteArray()));
for (int i = 0; i < currentProtectionState.size(); i++) {
byte b = currentProtectionState.getByte(i);
int index = i * 8 + 1;
for (int j = 0; j < 8; j++) {
PowerUnitChannel channel = PowerUnitChannel.getPowerUnitChannel(index + j);
if (channel.index > PowerUnitChannel.UNKNOWN.index && channel.index <= PowerMessageProtocol.CHANNEL_NORMAL_END_INDEX) {
int pos = list.indexOf(new PowerUnitState(channel));
if (pos != -1) {
PowerUnitState powerUnitState = list.get(pos);
powerUnitState.setCurrentProtectionState(((b >> j) & 0x1) == 1);
}
}
}
}
//获取索引1~46的电流值
ByteString currentValue = bytes.substring(currentValueBeginIndex, currentValueEndIndex);
// Log.i(TAG, currentValue.size() + " 电流数据=" + ByteUtil.byteArrToHex(currentValue.toByteArray()));
for (int i = 0; i < currentValue.size(); i += 8) {
int idx = currentValue.getByte(i);
for (int j = 0; j < 3; j++) {
PowerUnitChannel channel = PowerUnitChannel.getPowerUnitChannel(idx * 3 + j + 1);
if (channel.index > PowerUnitChannel.UNKNOWN.index && channel.index <= PowerMessageProtocol.CHANNEL_NORMAL_END_INDEX) {
int pos = list.indexOf(new PowerUnitState(channel));
if (pos != -1) {
PowerUnitState powerUnitState = list.get(pos);
int beginIndex = i + 2 + j * 2;
int endIndex = beginIndex + 2;
powerUnitState.setCurrentValue(ByteUtil.get16bitUnsignedValueLittleEndian(currentValue.substring(beginIndex, endIndex).toByteArray()) * 0.1F);
}
}
}
}
//获取索引51~66的相机状态
ByteString cameraChannelState = bytes.substring(cameraChannelBeginIndex, cameraChannelEndIndex);
// Log.i(TAG, cameraChannelState.size() + " 相机通道数据=" + ByteUtil.byteArrToHex(cameraChannelState.toByteArray()));
for (int i = 0; i < cameraChannelState.size(); i++) {
PowerUnitChannel channel = PowerUnitChannel.getPowerUnitChannel(51 + i);
if (channel.index >= PowerMessageProtocol.CHANNEL_CAMERA_START_INDEX) {
byte b = cameraChannelState.getByte(i);
// Log.i(TAG, "相机" + channel + " 值=" + ByteUtil.byteToBit(b));
int pos = list.indexOf(new PowerUnitState(channel));
if (pos != -1) {
PowerUnitState powerUnitState = list.get(pos);
powerUnitState.setPowerState(b & 0x03);
int faultState = (b & 0x3C) >> 2;
powerUnitState.setFaultState(faultState);
}
}
}
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private PowerErrorData unpackErrorData(ByteString bytes) {
try {
ByteString frameTypeByteString = bytes.substring(0, 2);
int frameTypeValue = ByteUtil.get16bitUnsignedValueLittleEndian(frameTypeByteString.toByteArray());
PowerFrameType frameType = PowerFrameType.getPowerFrameType(frameTypeValue);
// Log.w(TAG, "Error FrameType=" + frameType);
int errorValue = ByteUtil.get8bitUnsignedValue(3, bytes.toByteArray());
PowerError error = PowerError.getPowerError(errorValue);
// Log.w(TAG, "Error errorType=" + error);
return new PowerErrorData(frameType, error);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//异或校验
private int xorCheck(ByteString bytes, int checkValueLength) {
int xorChecksum = 0;
//异或校验
for (int i = 0; i < bytes.size() - checkValueLength; i += 4) {
byte[] tInt = new byte[4];
tInt[0] = bytes.getByte(i);
tInt[1] = bytes.getByte(i + 1);
tInt[2] = bytes.getByte(i + 2);
tInt[3] = bytes.getByte(i + 3);
int datum = ByteUtil.get32bitUnsignedValueLittleEndian(tInt);
xorChecksum ^= datum; // 对每个字节进行异或操作
}
return xorChecksum;
}
private List<PowerUnitState> initPowerUnitStateList() {
List<PowerUnitState> list = new ArrayList<>();
PowerUnitChannel[] channels = PowerUnitChannel.values();
for (PowerUnitChannel channel : channels) {
if (channel != PowerUnitChannel.UNKNOWN) {
list.add(new PowerUnitState(channel));
}
}
return list;
}
}