Merge branch 'refs/heads/dev_robotaxi-d_241211_6.8.6' into dev_robobus-d_241226_6.8.6

This commit is contained in:
xinfengkun
2024-12-26 12:03:32 +08:00
19 changed files with 1032 additions and 38 deletions

View File

@@ -146,16 +146,16 @@
app:layout_constraintBottom_toTopOf="@+id/video_fragment"
app:layout_constraintEnd_toEndOf="parent" />
<!-- 事件弹框 -->
<com.mogo.eagle.core.function.hmi.ui.v2n.RoadV2NEventWindowView
android:id="@+id/roadV2NEventWindowView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="-70dp"
android:layout_marginRight="14dp"
app:layout_constraintBottom_toTopOf="@+id/zv_msg_pop_bottom"
app:layout_constraintRight_toRightOf="parent"
android:visibility="gone"/>
<!-- &lt;!&ndash; 事件弹框 &ndash;&gt;-->
<!-- <com.mogo.eagle.core.function.hmi.ui.v2n.RoadV2NEventWindowView-->
<!-- android:id="@+id/roadV2NEventWindowView"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginBottom="-70dp"-->
<!-- android:layout_marginRight="14dp"-->
<!-- app:layout_constraintBottom_toTopOf="@+id/zv_msg_pop_bottom"-->
<!-- app:layout_constraintRight_toRightOf="parent"-->
<!-- android:visibility="gone"/>-->
<!--红绿灯提醒-->
<com.mogo.eagle.core.function.hmi.ui.notice.traffic.TrafficLightPromptView

View File

@@ -134,7 +134,7 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
);
CallerHmiManager.INSTANCE.warningV2X(poiType, alarmText,
ttsText, this,WarningDirectionEnum.ALERT_WARNING_TOP,
TimeUnit.SECONDS.toMillis(5), AIAssist.LEVEL2, false);
TimeUnit.SECONDS.toMillis(5), AIAssist.NEW_LEVEL_2, false);
//消息埋点
V2XEventAnalyticsManager.INSTANCE.triggerV2XEvent(poiType,alarmText,ttsText, DataSourceType.AICLOUD, CommunicationType.V2N);
}

View File

@@ -88,7 +88,7 @@ public class V2XFrontWarningScenario extends AbsV2XScenario implements IMoGoChas
CallerHmiManager.INSTANCE.warningV2X(v2xType + "",
getAlertContentForFrontWarning(mMarkerEntity), mMarkerEntity.getTts(),
this,getDirection(),
TimeUnit.SECONDS.toMillis(5), AIAssist.LEVEL2, false);
TimeUnit.SECONDS.toMillis(5), AIAssist.NEW_LEVEL_2, false);
//消息埋点
V2XEventAnalyticsManager.INSTANCE.triggerV2XEvent(v2xType,getAlertContentForFrontWarning(mMarkerEntity).toString(),
mMarkerEntity.getTts(), DataSourceType.AICLOUD, CommunicationType.V2N);

View File

@@ -12,6 +12,7 @@ import com.mogo.eagle.core.function.datacenter.location.MoGoLocationDispatcher
import com.mogo.eagle.core.function.datacenter.v2x.SpeedLimitDispatcher
import com.mogo.eagle.core.function.datacenter.v2x.TrafficLightDispatcher
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.support.device.led.LedSourceManager
@Route(path = MogoServicePaths.PATH_DATA_CENTER_MODULE)
class DataCenterProvider : IDataCenterProvider {
@@ -25,14 +26,15 @@ class DataCenterProvider : IDataCenterProvider {
MoGoLocationDispatcher.initListener()
mContext = context
mContext?.let {
val isPassenger = AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)
LedSourceManager.init(!isPassenger)
CallerDataCenterBizManager.init()
CallerMsgBoxManager.queryAllMessages(it)
TrafficLightDispatcher.INSTANCE.initServer(it)
SpeedLimitDispatcher.INSTANCE.initLimit(it)
if (AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
if (isPassenger) {
IotManager.init()
}
}
}

View File

@@ -54,6 +54,7 @@ import com.mogo.eagle.core.utilcode.util.ParseVersionUtils
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.support.device.led.LedSourceManager
import com.mogo.telematic.MogoProtocolMsg
import com.mogo.telematic.MogoProtocolMsg.NORMAL_DATA
import com.mogo.telematic.MogoProtocolMsg.SYNC_FUSION_COLOR_STATUS
@@ -1024,6 +1025,13 @@ class MoGoAutopilotControlProvider :
*/
override fun sendTripInfo(type: Int, lineName: String, departureStopName: String,arrivalStopName: String, isLastStop: Boolean) {
AdasManager.getInstance().sendTripInfoReq(type, lineName, departureStopName,arrivalStopName, isLastStop)
LedSourceManager.updateTripInfoData(
type,
lineName,
departureStopName,
arrivalStopName,
isLastStop
)
}
/**

View File

@@ -91,16 +91,17 @@ import com.mogo.eagle.core.function.call.obu.CallerObuWarningSpatListenerManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_D_C
import com.mogo.eagle.core.utilcode.util.DeviceUtils
import com.mogo.support.device.led.LedSourceManager
import com.mogo.support.obu.ObuScene
import com.zhidao.support.adas.high.AdasManager
import com.zhidao.support.adas.high.OnAdasListener
import com.zhidao.support.adas.high.chain.AdasChain
import com.zhjt.mogo.adas.data.bean.AdasParam
import com.zhidao.support.adas.high.common.ProtocolStatus
import com.zhjt.mogo.adas.common.MessageType
import com.zhjt.mogo.adas.data.AdasConstants
import com.zhjt.mogo.adas.data.AdasConstants.NodeExistState
import com.zhjt.mogo.adas.data.AiCloudTask
import com.zhjt.mogo.adas.data.bean.AdasParam
import com.zhjt.mogo.adas.data.bean.AutopilotStatistics
import com.zhjt.mogo.adas.data.bean.LaunchConditionData
import com.zhjt.mogo.adas.data.bean.NodeStateInfo
@@ -133,6 +134,7 @@ import prediction.Prediction
import record_cache.RecordPanelOuterClass
import system_master.SsmInfo
import system_master.SystemStatusInfo
import kotlin.math.roundToInt
/**
* 适配ADAS 回调监听分发,这里不做业务,只做数据包装及分发处理
@@ -176,6 +178,7 @@ class MoGoAdasListenerImpl : OnAdasListener {
)
override fun onGnssInfo(header: MessagePad.Header, gnssInfo: MessagePad.GnssInfo) {
CallerChassisGnssListenerManager.invokeChassisGnssListener(gnssInfo)
LedSourceManager.updateAccelerationData(gnssInfo.acceleration)
if (gnssInfo != null) {
// 同步更新经纬度和系统时间至 AutoPilotStatusListener
CallerAutoPilotStatusListenerManager.updateAutoPilotLocAndTime(
@@ -278,6 +281,15 @@ class MoGoAdasListenerImpl : OnAdasListener {
override fun onLightSwitch(light: Chassis.LightSwitch) {
//转向灯数据
CallerChassisStatesListenerManager.invokeAutopilotLightSwitchData(light)
var type = 0
if (Chassis.LightSwitch.LIGHT_LEFT == light) {
type = 1
} else if (Chassis.LightSwitch.LIGHT_RIGHT == light) {
type = 2
} else if (Chassis.LightSwitch.LIGHT_FLASH == light) {
type = 3
}
LedSourceManager.updateTurnSignalData(type)
}
//自动驾驶状态
@@ -320,6 +332,8 @@ class MoGoAdasListenerImpl : OnAdasListener {
header: MessagePad.Header?,
trafficLights: FusionTrafficLightOuterClass.FusionTrafficLights?
) {
//此分发新开线程在invokeAutopilotPerceptionTrafficLight 前分发避免 invokeAutopilotPerceptionTrafficLight中存在耗时操作影响LED数据更新
transitionTurnToLedData(trafficLights)
if (trafficLights != null) {
CallerAutopilotIdentifyListenerManager.invokeAutopilotPerceptionTrafficLight(
trafficLights
@@ -327,6 +341,92 @@ class MoGoAdasListenerImpl : OnAdasListener {
}
}
/**
* LED屏幕数据转换
* 只能放在这 LedSourceManager LIB中并未依赖ADAS数据源
*/
private fun transitionTurnToLedData(trafficLights: FusionTrafficLightOuterClass.FusionTrafficLights?) {
var stateTurnRound = -1
var durationTurnRound = -1
var stateTurnLeft = -1
var durationTurnLeft = -1
var stateStraight = -1
var durationStraight = -1
var stateTurnRight = -1
var durationTurnRight = -1
if (trafficLights != null) {
if (trafficLights.uTurn != null) {
val uTurn = trafficLights.uTurn
stateTurnRound = transitionTurnType(uTurn.state)
if (uTurn.duration > 0) {
durationTurnRound = uTurn.duration.roundToInt()
}
}
if (trafficLights.left != null) {
val left = trafficLights.left
stateTurnLeft = transitionTurnType(left.state)
if (left.duration > 0) {
durationTurnLeft = left.duration.roundToInt()
}
}
if (trafficLights.straight != null) {
val straight = trafficLights.straight
stateStraight = transitionTurnType(straight.state)
if (straight.duration > 0) {
durationStraight = straight.duration.roundToInt()
}
}
if (trafficLights.right != null) {
val right = trafficLights.right
stateTurnRight = transitionTurnType(right.state)
if (right.duration > 0) {
durationTurnRight = right.duration.roundToInt()
}
}
//来源是自车没有倒计时 不管域控发的倒计时是什么值
if (trafficLights.source == 0) {
durationTurnRound = -1
durationTurnLeft = -1
durationStraight = -1
durationTurnRight = -1
}
}
LedSourceManager.updateTrafficLightData(
stateTurnRound,
durationTurnRound,
stateTurnLeft,
durationTurnLeft,
stateStraight,
durationStraight,
stateTurnRight,
durationTurnRight
)
}
private fun transitionTurnType(state: FusionTrafficLightOuterClass.FusionLightState?): Int {
var type = -1
state?.let {
type = when (it) {
FusionTrafficLightOuterClass.FusionLightState.STATE_RED_FUSION -> {
2
}
FusionTrafficLightOuterClass.FusionLightState.STATE_YELLOW_FUSION -> {
3
}
FusionTrafficLightOuterClass.FusionLightState.STATE_GREEN_FUSION -> {
4
}
else -> {
-1
}
}
}
return type
}
//他车轨迹预测
override fun onPredictionObstacleTrajectory(
header: MessagePad.Header?,

View File

@@ -143,6 +143,8 @@ class MoGoAdasMsgConnectStatusListenerImpl :
CallerAutoPilotControlManager.setRainMode(FunctionBuildConfig.isRainMode)
// 6.6.2 版本默认开启,与海江确认过,默认发盲区模式
CallerAutoPilotControlManager.sendFusionMode(2)
CallerAutoPilotControlManager.sendV2iToPncCmd(FunctionBuildConfig.v2iToPNC)
CallerAutoPilotControlManager.sendV2nToPncCmd(FunctionBuildConfig.v2nTotalSwitch)
}
AdasConstants.IpcConnectionStatus.CONNECTING -> {

View File

@@ -5,6 +5,7 @@ import android.os.CountDownTimer
import android.os.Handler
import android.util.Log
import com.mogo.commons.voice.AIAssist
import com.mogo.commons.voice.AIAssist.NEW_LEVEL_2
import com.mogo.eagle.core.data.biz.trafficlight.TrafficLightResult
import com.mogo.eagle.core.data.biz.trafficlight.TrafficLightStatus
import com.mogo.eagle.core.data.biz.trafficlight.currentRoadTrafficLight
@@ -232,7 +233,7 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
if((light.state == FusionTrafficLightOuterClass.FusionLightState.STATE_YELLOW_FUSION || light.state ==FusionTrafficLightOuterClass.FusionLightState.STATE_RED_FUSION)
&& light.duration < 5 && light.nextState == FusionTrafficLightOuterClass.FusionLightState.STATE_GREEN_FUSION){
//语音播放:红灯即将变绿
AIAssist.getInstance(mContext).speakTTSVoice("红灯即将变绿")
AIAssist.getInstance(mContext).speakTTSVoiceWithLevel("红灯即将变绿", NEW_LEVEL_2)
isTurnGreen = true
}
}

View File

@@ -5,7 +5,6 @@ import android.os.Bundle
import android.os.SystemClock
import android.util.AttributeSet
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -57,7 +56,6 @@ import com.mogo.eagle.core.function.hmi.ui.operate.preferences.PreferenceWithWel
import com.mogo.eagle.core.function.hmi.ui.tools.SweeperModeChangedConfirmDialog
import com.mogo.eagle.core.function.hmi.ui.utils.HmiActionLog.Companion.hmiAction
import com.mogo.eagle.core.function.hmi.ui.utils.SOPAnalyticsManager.clickEventAnalytics
import com.mogo.eagle.core.utilcode.floating.MoGoPopWindow
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
@@ -67,6 +65,7 @@ import com.mogo.eagle.core.utilcode.rv.divider.CommonDividerItemDecoration
import com.mogo.eagle.core.utilcode.util.AppStateManager
import com.mogo.eagle.core.utilcode.util.GsonUtils.*
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.support.device.led.LedSourceManager
import com.zhjt.mogo.adas.data.AdasConstants
import com.zhjt.mogo.adas.data.bean.AdasParam
import kotlinx.android.synthetic.main.layout_operate_panel.view.iv_operate_panel_close
@@ -1521,6 +1520,10 @@ class OperatePanelLayout : LinearLayout {
FunctionBuildConfig.welcomeWords = preference.extras.getString(PreferenceWithWelcomeWords.KEY_BUNDLE_CURRENT_EDIT_TEXT_VALUE)
hmiAction("外屏欢迎语", FunctionBuildConfig.welcomeWords ?: "")
clickEventAnalytics("外屏欢迎语", true)
LedSourceManager.foreverChangeWelcomeHint(
context?.applicationContext,
FunctionBuildConfig.welcomeWords
)
}
return super.onPreferenceClick(preference)
}

View File

@@ -484,7 +484,7 @@ class RoadV2NEventWindowView @JvmOverloads constructor(
"更新时间:${DateTimeUtils.getTimeText(dataBean.timestamp, DateTimeUtils.HH_mm_ss)}"
if (dataBean.isNeedTTS && !TextUtils.isEmpty(dataBean.ttsStr)) {
AIAssist.getInstance(context)
.speakTTSVoiceWithLevel(dataBean.ttsStr, AIAssist.LEVEL0)
.speakTTSVoiceWithLevel(dataBean.ttsStr, AIAssist.NEW_LEVEL_2)
}
when (dataBean.eventType) {
RoadV2NEventType.TEXT -> {

View File

@@ -31,10 +31,10 @@
android:key="mofang"
android:layout="@layout/layout_operate_panel_preference_header"
android:title="蘑方" />
<!-- <Preference-->
<!-- android:fragment="com.mogo.eagle.core.function.hmi.ui.operate.OperatePanelLayout$WelcomeWordsPreferenceCompat"-->
<!-- android:key="welcome_words"-->
<!-- android:layout="@layout/layout_operate_panel_preference_header"-->
<!-- android:title="欢迎语"/>-->
<Preference
android:fragment="com.mogo.eagle.core.function.hmi.ui.operate.OperatePanelLayout$WelcomeWordsPreferenceCompat"
android:key="welcome_words"
android:layout="@layout/layout_operate_panel_preference_header"
android:title="欢迎语"/>
</androidx.preference.PreferenceScreen>

View File

@@ -64,21 +64,21 @@ bytex.ASM_API=ASM7
LOGLIB_VERSION=1.10.18
######## MogoAiCloudSDK Version ########
# 网络请求LOGLIB_VERSION
MOGO_NETWORK_VERSION=1.4.7.58
MOGO_NETWORK_VERSION=1.4.7.59
# 鉴权
MOGO_PASSPORT_VERSION=1.4.7.58
MOGO_PASSPORT_VERSION=1.4.7.59
# 长链接
MOGO_SOCKET_VERSION=1.4.7.58
MOGO_SOCKET_VERSION=1.4.7.59
# 数据采集
MOGO_REALTIME_VERSION=1.4.7.58
MOGO_REALTIME_VERSION=1.4.7.59
# 直播推流
MOGO_LIVE_VERSION=1.4.7.58
MOGO_LIVE_VERSION=1.4.7.59
# 直播拉流
MOGO_TRAFFICLIVE_VERSION=1.4.7.58
MOGO_TRAFFICLIVE_VERSION=1.4.7.59
# 定位服务
MOGO_LOCATION_VERSION=1.4.7.58
MOGO_LOCATION_VERSION=1.4.7.59
# 远程通讯模块
MOGO_TELEMATIC_VERSION=1.4.7.58
MOGO_TELEMATIC_VERSION=1.4.7.59
# 动态换肤SDK
MOGO_SKIN_VERSION=1.4.7.49.19
######## MogoAiCloudSDK Version ########
@@ -92,8 +92,8 @@ WEBSOCKET_VERSION=1.1.7
applicationId=com.mogo.launcer
applicationName=IntelligentPilot
# RoboBus司机端2.5.1RoboTaxi司机端2.5.1RoboTaxi乘客端1.0.0
versionCode=6008002
versionName=6.8.2
versionCode=6008006
versionName=6.8.6
################# 新架构模块Maven版本管理 #################
MOGO_CORE_FUNCTION_HMI_VERSION=0.0.58.10
@@ -151,7 +151,7 @@ MATRIX_VERSION=2.0.8
# 公交模式司机端版本号
DRIVER_VERSION=6.8.2
DRIVER_VERSION=6.8.6
# 公交模式乘客端端版本号
PASSENGER_VERSION=5.8.2
PASSENGER_VERSION=5.8.6

View File

@@ -1,6 +1,7 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'org.jetbrains.kotlin.android'
}
android {
@@ -30,10 +31,14 @@ android {
lintOptions {
abortOnError false
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation rootProject.ext.dependencies.androidxappcompat
api rootProject.ext.dependencies.serialport
implementation "com.mogo.support.device.manager:led_screen_cpower5a:1.0.7"
implementation rootProject.ext.dependencies.view_model_scope
}

View File

@@ -0,0 +1,161 @@
package com.mogo.support.device.led
import android.util.Log
import com.mogo.support.device.manager.cpower5a.LedScreenCpower5aManager
import com.mogo.support.device.manager.cpower5a.common.LedScreen
import com.mogo.support.device.manager.cpower5a.common.Program
/**
* 后屏
*/
open class BackLedUIViewModel : BaseLedUIViewModel() {
companion object {
const val TAG = "BackLedUIViewModel"
val supportUIList = mutableSetOf<String?>().also {
it += WelcomeUI::class.simpleName
it += FinishUI::class.simpleName
it += RouteInfoUI::class.simpleName
it += StationReportUI::class.simpleName
it += ArriveStationUI::class.simpleName
it += LeaveStationUI::class.simpleName
it += EmergencyBrakeUI::class.simpleName
it += TrafficLightUI::class.simpleName
it += TurnSignalUI::class.simpleName
it += RoadWorkAheadWarningUI::class.simpleName
}
}
override suspend fun receive(msg: LedUI) {
if (supportUIList.contains(msg.javaClass.simpleName)) {
Log.i(
FrontLedUIViewModel.TAG,
"receive --> ${msg.javaClass.simpleName}[priority=${msg.priority}] "
)
super.receive(msg)
} else {
Log.i(
FrontLedUIViewModel.TAG,
"receive --> 不支持的类型,放弃 ${msg.javaClass.simpleName}[priority=${msg.priority}] "
)
}
}
override fun handleLedUIShow(ledUI: LedUI) {
super.handleLedUIShow(ledUI)
when (ledUI) {
is WelcomeUI -> {
LedScreenCpower5aManager.getInstance().playProgramWelcome(
null,
LedScreen.OUTWARD_BACK,
ledUI.hintMsg,
ledUI.isForever
)
Log.e(TAG, "后屏 播放欢迎语:${ledUI.hintMsg} 是否永久展示:${ledUI.isForever}")
}
is FinishUI -> {
LedScreenCpower5aManager.getInstance().playProgramFinish(
LedScreen.OUTWARD_BACK,
ledUI.hintMsg,
)
Log.e(TAG, "后屏 播放结束语:${ledUI.hintMsg}")
}
is RouteInfoUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineInformation(LedScreen.OUTWARD_BACK, ledUI.lineName)
Log.e(TAG, "后屏 播放线路信息:${ledUI.lineName}")
}
is StationReportUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineStationReport(
LedScreen.OUTWARD_BACK,
ledUI.stationName,
ledUI.state
)
Log.e(TAG, "后屏 播放报站 站点:${ledUI.stationName} 状态:${ledUI.state}")
}
is ArriveStationUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineStationReportHint(
LedScreen.OUTWARD_BACK,
"车辆进站"
)
Log.e(TAG, "后屏 播放车辆进站")
}
is LeaveStationUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineStationReportHint(
LedScreen.OUTWARD_BACK,
"车辆起步"
)
Log.e(TAG, "后屏 播放车辆起步")
}
is EmergencyBrakeUI -> {
LedScreenCpower5aManager.getInstance()
.playProgram(LedScreen.OUTWARD_BACK, Program.REMIND_FRONT_CAR_EMERGENCY_BRAKE)
Log.e(TAG, "后屏 车辆急刹")
}
is RoadWorkAheadWarningUI -> {
LedScreenCpower5aManager.getInstance()
.playProgram(LedScreen.OUTWARD_BACK, Program.REMIND_ROAD_WORK_AHEAD)
Log.e(TAG, "后屏 道路施工")
}
is TurnSignalUI -> {
var program: Program? = null
program = when (ledUI.type) {
1 -> {
Program.REMIND_TURN_LEFT
}
2 -> {
Program.REMIND_TURN_RIGHT
}
3 -> {
Program.REMIND_VEHICLE_ANOMALY
}
else -> {
null
}
}
program?.let {
LedScreenCpower5aManager.getInstance()
.playProgram(
LedScreen.OUTWARD_BACK,
it
)
}
Log.e(TAG, "后屏 播放节目${program}")
}
is TrafficLightUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramTrafficLights(
LedScreen.OUTWARD_BACK,
ledUI.stateTurnRound, ledUI.durationTurnRound,
ledUI.stateTurnLeft, ledUI.durationTurnLeft,
ledUI.stateStraight, ledUI.durationStraight,
ledUI.stateTurnRight, ledUI.durationTurnRight
)
Log.e(
TAG,
"后屏 播放信号灯节目 掉头:${ledUI.stateTurnRound} 掉头倒计时:${ledUI.durationTurnRound}\n" +
"左转:${ledUI.stateTurnLeft} 左转倒计时:${ledUI.durationTurnLeft}\n" +
"直行:${ledUI.stateStraight} 直行倒计时:${ledUI.stateStraight}\n" +
"右转:${ledUI.stateTurnRight} 右转倒计时:${ledUI.durationTurnRight}\n"
)
}
}
}
}

View File

@@ -0,0 +1,256 @@
package com.mogo.support.device.led
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.PriorityQueue
import kotlin.math.ceil
open class BaseLedUIViewModel : ViewModel() {
companion object {
const val TAG = "LedUIViewModel"
val DEFAULT_UI = WelcomeUI()
}
private var baseUICountDownJob: Job? = null
private var currentLedUI: LedUI
private var currentCountDownJob: Job? = null
private val restoreLedUIQueue = PriorityQueue<LedUI>()
private val currentLedUILiveData = MutableLiveData<LedUI>()
private var currentRouteInfoUI: RouteInfoUI? = null//当前线路信息UI
private var currentStationReportUI: StationReportUI? = null//当前报站信息
init {
currentLedUI = DEFAULT_UI
}
fun start() {
viewModelScope.launch {
restoreLastUI()
}
}
/**
* 更新线路信息
*/
fun updateCurrentRouteInfo(lineName: String) {
Log.i(TAG, "线路信息更新 线路名称:$lineName")
currentRouteInfoUI = RouteInfoUI(lineName)
}
/**
* 更新报站信息
*/
fun updateCurrentStationReport(stationName: String, state: String) {
Log.i(TAG, "报站信息更新 ${state}$stationName 站点状态")
currentStationReportUI = StationReportUI(stationName, state)
}
open suspend fun receive(msg: LedUI) {
Log.e(
TAG,
"receive --> ${msg.javaClass.simpleName}[priority=${msg.priority}] current:${currentLedUI.javaClass.simpleName}[priority=${currentLedUI.priority}]"
)
if (msg.priority > currentLedUI.priority) {
//优先级低但是需要打断恢复,放入队列,否则直接舍弃
if (msg.interruptRestore) {
Log.i(
TAG,
"receive --> 优先级低,放入等待队列 ${msg.javaClass.simpleName}[priority=${msg.priority}]"
)
if (msg is LedUICountDown) {
val countdown = if (msg.countDownSeconds < 0) 0 else msg.countDownSeconds
// 如果是打断恢复的,不重新设置值
if (msg.absCountDownTimestamp == 0L) {
msg.absCountDownTimestamp =
System.currentTimeMillis() + countdown * 1000L
}
}
restoreLedUIQueue.offer(msg)
} else {
Log.i(
TAG,
"receive --> 优先级低,舍弃 ${msg.javaClass.simpleName}[priority=${msg.priority}]"
)
}
} else {
// 打断当前 UI
Log.i(
TAG,
"receive --> 优先级高或相等,打断当前 ${msg.javaClass.simpleName}[priority=${msg.priority}]"
)
if (msg is LedUIDataChange) {
if (msg.isShow) {
showUI(msg)
} else {
// 删除恢复队列中数据
removeRestoreLedUI(msg)
// 当前正在展示,取消展示
if (currentLedUI.javaClass.simpleName == msg.javaClass.simpleName) {
dismissUI(msg)
}
}
} else {
showUI(msg)
}
}
}
fun reset() {
Log.i(TAG, "reset()")
viewModelScope.launch {
currentLedUI = DEFAULT_UI
restoreLedUIQueue.clear()
currentCountDownJob?.cancel()
baseUICountDownJob?.cancel()
cancelBasicUISwitch()
currentRouteInfoUI = null
currentStationReportUI = null
}
}
private suspend fun showUI(msg: LedUI) {
Log.i(TAG, "showUI ledUI=${msg.javaClass.simpleName}[priority=${msg.priority}]")
// 如果当前类型是 需要打断恢复的,放入等待队列
if (currentLedUI.interruptRestore) {
restoreLedUIQueue.offer(msg)
}
currentCountDownJob?.also {
it.cancel()
}
cancelBasicUISwitch()
handleLedUIShow(msg)
currentLedUI = msg
// 倒计时类型的 处理倒计时逻辑
if (msg is LedUICountDown) {
val countdown = if (msg.countDownSeconds < 0) 0 else msg.countDownSeconds
Log.d(TAG, "LedUICountDown delay=${msg.countDownSeconds}")
// 如果是打断恢复的,不重新设置值
if (msg.absCountDownTimestamp == 0L) {
msg.absCountDownTimestamp =
System.currentTimeMillis() + countdown * 1000L
}
viewModelScope.launch {
val delaySeconds =
if (msg.absCountDownTimestamp > 0) {
ceil((msg.absCountDownTimestamp - System.currentTimeMillis()) / 1000.0).toInt()
} else
countdown
Log.d(TAG, "设置currentCountDownJob delay=${delaySeconds}")
delay(delaySeconds * 1000L)
restoreLastUI()
}.also { currentCountDownJob = it }
}
}
private suspend fun dismissUI(msg: LedUI) {
Log.i(TAG, "dismissUI ledUI=${msg.javaClass.simpleName}[priority=${msg.priority}]")
currentCountDownJob?.also {
it.cancel()
}
removeRestoreLedUI(msg)
restoreLastUI()
}
private suspend fun restoreLastUI() {
//恢复打断
val restoreUI = pollRestoreLedUI()
if (restoreUI != null) {
showUI(restoreUI)
} else {
// 启动 车辆基础状态 切换
startBasicUISwitchLoop()
}
}
private suspend fun startBasicUISwitchLoop() {
if (currentRouteInfoUI != null) {
showUI(currentRouteInfoUI!!)
} else if (currentStationReportUI != null) {
showUI(currentStationReportUI!!)
} else {
showUI(WelcomeUI())
}
basicUISwitchInternal()
}
private fun cancelBasicUISwitch() {
Log.i(TAG, "cancelBaseUISwitch()")
kotlin.runCatching { baseUICountDownJob?.cancel() }
}
private suspend fun basicUISwitchInternal() {
Log.i(TAG, "baseUISwitchInternal()")
cancelBasicUISwitch()
viewModelScope.launch {
delay(10 * 1000L)
if (currentLedUI.javaClass.simpleName == WelcomeUI::class.simpleName) {
if (currentRouteInfoUI != null) {
showUI(currentRouteInfoUI!!)
} else {
showUI(WelcomeUI())
}
} else if (currentLedUI.javaClass.simpleName == RouteInfoUI::class.simpleName) {
if (currentStationReportUI != null) {
showUI(currentStationReportUI!!)
} else {
showUI(WelcomeUI())
}
} else if (currentLedUI.javaClass.simpleName == StationReportUI::class.simpleName) {
showUI(WelcomeUI())
}
basicUISwitchInternal()
}.also { baseUICountDownJob = it }
}
/**
* 控制屏幕 UI 展示
*/
protected open fun handleLedUIShow(ledUI: LedUI) {
currentLedUILiveData.postValue(ledUI)
}
/**
* 过滤队列中时间戳小于指定时间的消息,取出优先级最高的消息
*/
private fun pollRestoreLedUI(): LedUI? {
while (restoreLedUIQueue.isNotEmpty()) {
val message = restoreLedUIQueue.poll()
if (message is LedUICountDown) {
if (message.countDownSeconds > 0 && message.absCountDownTimestamp > System.currentTimeMillis()) {
return message
}
} else {
return message
}
}
return null
}
/**
* 从等待队列中删除目标类型数据
*/
private fun removeRestoreLedUI(msg: LedUI) {
val toRemove = restoreLedUIQueue.filter {
it.javaClass == msg.javaClass ||
(it is LedUICountDown && it.countDownSeconds > 0
&& it.absCountDownTimestamp <= System.currentTimeMillis())
}
restoreLedUIQueue.removeAll(toRemove.toSet())
}
}

View File

@@ -0,0 +1,93 @@
package com.mogo.support.device.led
import android.util.Log
import com.mogo.support.device.manager.cpower5a.LedScreenCpower5aManager
import com.mogo.support.device.manager.cpower5a.common.LedScreen
/**
* 前屏幕
*/
class FrontLedUIViewModel : BaseLedUIViewModel() {
companion object {
const val TAG = "FrontLedUIViewModel"
val supportUIList = mutableSetOf<String?>().also {
it += WelcomeUI::class.simpleName
it += FinishUI::class.simpleName
it += RouteInfoUI::class.simpleName
it += StationReportUI::class.simpleName
it += ArriveStationUI::class.simpleName
it += LeaveStationUI::class.simpleName
}
}
override suspend fun receive(msg: LedUI) {
if (supportUIList.contains(msg.javaClass.simpleName)) {
Log.i(TAG, "receive --> ${msg.javaClass.simpleName}[priority=${msg.priority}] ")
super.receive(msg)
} else {
Log.i(
TAG,
"receive --> 不支持的类型,放弃 ${msg.javaClass.simpleName}[priority=${msg.priority}] "
)
}
}
override fun handleLedUIShow(ledUI: LedUI) {
super.handleLedUIShow(ledUI)
when (ledUI) {
is WelcomeUI -> {
LedScreenCpower5aManager.getInstance().playProgramWelcome(
null,
LedScreen.OUTWARD_FRONT,
ledUI.hintMsg,
ledUI.isForever
)
Log.e(TAG, "前屏 播放欢迎语:${ledUI.hintMsg} 是否永久展示:${ledUI.isForever}")
}
is FinishUI -> {
LedScreenCpower5aManager.getInstance().playProgramFinish(
LedScreen.OUTWARD_FRONT,
ledUI.hintMsg,
)
Log.e(TAG, "前屏 播放结束语:${ledUI.hintMsg}")
}
is RouteInfoUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineInformation(LedScreen.OUTWARD_FRONT, ledUI.lineName)
Log.e(TAG, "前屏 播放线路信息:${ledUI.lineName}")
}
is StationReportUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineStationReport(
LedScreen.OUTWARD_FRONT,
ledUI.stationName,
ledUI.state
)
Log.e(TAG, "前屏 播放报站 站点:${ledUI.stationName} 状态:${ledUI.state}")
}
is ArriveStationUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineStationReportHint(
LedScreen.OUTWARD_FRONT,
"车辆进站"
)
Log.e(TAG, "前屏 播放车辆进站")
}
is LeaveStationUI -> {
LedScreenCpower5aManager.getInstance()
.playProgramLineStationReportHint(
LedScreen.OUTWARD_FRONT,
"车辆起步"
)
Log.e(TAG, "前屏 播放车辆起步")
}
}
}
}

View File

@@ -0,0 +1,261 @@
package com.mogo.support.device.led
import android.content.Context
import android.os.CountDownTimer
import com.mogo.support.device.manager.cpower5a.LedScreenCpower5aManager
import com.mogo.support.device.manager.cpower5a.common.LedScreen
import com.mogo.support.device.manager.cpower5a.common.TrafficLightState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlin.properties.Delegates
object LedSourceManager {
private val frontViewModel: FrontLedUIViewModel by lazy {
FrontLedUIViewModel() // 初始化
}
private val backViewModel: BackLedUIViewModel by lazy {
BackLedUIViewModel() // 初始化
}
private var typeTurnSignal = 0;//转向灯状态 0无灯1左转2右转3双闪
private var lastUpdateEmergencyBrakeTime = 0L//上次触发急刹展示的时间
private var isDriver by Delegates.notNull<Boolean>()
//红绿灯定时器,超时未更新隐藏红绿灯
@Volatile
private var lightCountDownTimer: CountDownTimer? = null
private var lastLightTime: Long = System.currentTimeMillis()
fun init(isDriver: Boolean) {
this.isDriver = isDriver
}
private fun receiveUI(ledUI: LedUI) {
GlobalScope.launch(Dispatchers.IO) {
frontViewModel.receive(ledUI)
backViewModel.receive(ledUI)
}
}
//更新线路信息
private fun updateLineNameUI(lineName: String) {
GlobalScope.launch(Dispatchers.IO) {
frontViewModel.updateCurrentRouteInfo(lineName)
backViewModel.updateCurrentRouteInfo(lineName)
}
}
//更新报站信息
private fun updateStationReportUI(stationName: String, state: String) {
GlobalScope.launch(Dispatchers.IO) {
frontViewModel.updateCurrentStationReport(stationName, state)
backViewModel.updateCurrentStationReport(stationName, state)
}
}
/**
* 更新转向灯
* type 0无灯1左转2右转3双闪
*/
fun updateTurnSignalData(type: Int) {
if (isDriver) {
if (typeTurnSignal != type) {
typeTurnSignal = type
receiveUI(TurnSignalUI(type != 0, type))
}
}
}
/**
* 车辆急刹
*/
fun updateAccelerationData(acceleration: Double) {
if (isDriver) {
if (acceleration <= -2) {
val now = System.currentTimeMillis()
if (now - lastUpdateEmergencyBrakeTime > 60 * 1000L) {//1m内不进行多次提示
lastUpdateEmergencyBrakeTime = now
receiveUI(EmergencyBrakeUI())
}
}
}
}
private fun updateLightCountDownTimer(){
lastLightTime = System.currentTimeMillis()
if (lightCountDownTimer == null) {
lightCountDownTimer = object : CountDownTimer(300000, 500) {
override fun onTick(millisUntilFinished: Long) {
if ((System.currentTimeMillis() - lastLightTime) > 1000) {
//隐藏红绿灯显示
receiveUI(
TrafficLightUI(
false,
null, -1,
null, -1,
null, -1,
null, -1
)
)
lightCountDownTimer?.cancel()
lightCountDownTimer = null
}
}
override fun onFinish() {
//隐藏红绿灯显示
receiveUI(
TrafficLightUI(
false,
null, -1,
null, -1,
null, -1,
null, -1
)
)
lightCountDownTimer?.cancel()
lightCountDownTimer = null
}
}
lightCountDownTimer?.start()
}
}
/**
* 更新红绿灯数据
* state -1表示 null; 0表示 CLEAR; 1表示 NONE; 2表示 RED; 3表示 YELLOW; 4表示 GREEN;
*/
fun updateTrafficLightData(
stateTurnRound: Int, durationTurnRound: Int,
stateTurnLeft: Int, durationTurnLeft: Int,
stateStraight: Int, durationStraight: Int,
stateTurnRight: Int, durationTurnRight: Int
) {
if (isDriver) {
var stateTurnRoundTemp: TrafficLightState? = null
var stateTurnLeftTemp: TrafficLightState? = null
var stateStraightTemp: TrafficLightState? = null
var stateTurnRightTemp: TrafficLightState? = null
var durationTurnRoundTemp = durationTurnRound
var durationTurnLeftTemp = durationTurnLeft
var durationStraightTemp = durationStraight
var durationTurnRightTemp = durationTurnRight
updateLightCountDownTimer()
var isShow = true
if (stateTurnRound == -1 && stateTurnLeft == -1 && stateStraight == -1 && stateTurnRight == -1) {
isShow = false
durationTurnRoundTemp = -1
durationTurnLeftTemp = -1
durationStraightTemp = -1
durationTurnRightTemp = -1
} else {
stateTurnRoundTemp = transitionTurnType(stateTurnRound)
stateTurnLeftTemp = transitionTurnType(stateTurnLeft)
stateStraightTemp = transitionTurnType(stateStraight)
stateTurnRightTemp = transitionTurnType(stateTurnRight)
}
receiveUI(
TrafficLightUI(
isShow,
stateTurnRoundTemp, durationTurnRoundTemp,
stateTurnLeftTemp, durationTurnLeftTemp,
stateStraightTemp, durationStraightTemp,
stateTurnRightTemp, durationTurnRightTemp
)
)
}
}
private fun transitionTurnType(type: Int): TrafficLightState {
return when (type) {
2 -> {
TrafficLightState.RED
}
3 -> {
TrafficLightState.YELLOW
}
4 -> {
TrafficLightState.GREEN
}
else -> {
TrafficLightState.NONE
}
}
}
/**
* 发生行程相关
* 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 是否最终站
*/
fun updateTripInfoData(
type: Int,
lineName: String,
departureStopName: String,
arrivalStopName: String,
isLastStop: Boolean
) {
if (isDriver) {
if (lineName.isNotEmpty()) {
updateLineNameUI(lineName)
}
if (type == 1) {
//开始
updateLineNameUI(lineName);
} else if (type == 2) {
//结束
receiveUI(FinishUI())
frontViewModel.reset()
backViewModel.reset()
} else if (type == 3) {
//出站
if (arrivalStopName.isNotEmpty()) {
updateStationReportUI(arrivalStopName, "下一站")
}
} else if (type == 4) {
//进站
if (departureStopName.isNotEmpty()) {
updateStationReportUI(
departureStopName, if (isLastStop) {
"终点站"
} else {
"下一站"
}
)
}
} else if (type == 5) {
//道路施工
receiveUI(RoadWorkAheadWarningUI())
}
}
}
/**
* 永久更改欢迎节目显示内容
* context如果是null会设置失败
*/
fun foreverChangeWelcomeHint(context: Context?, hintMsg: String?) {
LedScreenCpower5aManager.getInstance()
.playProgramWelcome(context, LedScreen.OUTWARD_FRONT, hintMsg, true)
LedScreenCpower5aManager.getInstance()
.playProgramWelcome(context, LedScreen.OUTWARD_BACK, hintMsg, true)
}
}

View File

@@ -0,0 +1,96 @@
package com.mogo.support.device.led
import com.mogo.support.device.manager.cpower5a.common.TrafficLightState
open class LedUI(
var priority: Int = 0,
var interruptRestore: Boolean = false,
) : Comparable<LedUI> {
override fun compareTo(other: LedUI): Int = other.priority - this.priority
override fun toString(): String {
return "LedUI(priority=$priority, interruptRestore=$interruptRestore)"
}
}
open class LedUIBaseSwitch(
priority: Int = 0,
interruptRestore: Boolean = false,
) : LedUI(priority, interruptRestore) {
override fun toString(): String {
return "LedUIBaseSwitch() ${super.toString()}"
}
}
open class LedUIDataChange(
var isShow: Boolean = false,
priority: Int = 0,
interruptRestore: Boolean = false,
) : LedUI(priority, interruptRestore) {
override fun toString(): String {
return "LedUIDataChange(isShow=$isShow) ${super.toString()}"
}
}
open class LedUICountDown(
open var countDownSeconds: Int = 0,
open var absCountDownTimestamp: Long = 0L,
priority: Int = 0,
interruptRestore: Boolean = false,
) : LedUI(priority, interruptRestore) {
override fun toString(): String {
return "LedUICountDown(countDownSeconds=$countDownSeconds, absCountDownTimestamp=$absCountDownTimestamp) ${super.toString()}"
}
}
//欢迎提示
class WelcomeUI(val hintMsg: String? = null, val isForever: Boolean = false) :
LedUIBaseSwitch(priority = 5) {
}
//结束提示
class FinishUI(val hintMsg: String = "感谢一路相伴") :
LedUICountDown(priority = 5, countDownSeconds = 10)
//线路信息提示
class RouteInfoUI(val lineName: String) : LedUIBaseSwitch(priority = 5)
//报站提示
class StationReportUI(val stationName: String, val state: String) : LedUIBaseSwitch(priority = 5)
//进站提示 暂时没用
class ArriveStationUI() :
LedUICountDown(priority = 0, countDownSeconds = 10)
//出站提示 暂时没用
class LeaveStationUI() :
LedUICountDown(priority = 0, countDownSeconds = 10)
/**
* 转向灯提示
* type 0无灯1左转2右转3双闪
*/
class TurnSignalUI(isShow: Boolean, val type: Int) :
LedUIDataChange(isShow = isShow, priority = 3, interruptRestore = true)
//急刹提示
class EmergencyBrakeUI() :
LedUICountDown(priority = 1, countDownSeconds = 5)
//信号灯提示
class TrafficLightUI(
isShow: Boolean,
val stateTurnRound: TrafficLightState?, val durationTurnRound: Int,
val stateTurnLeft: TrafficLightState?, val durationTurnLeft: Int,
val stateStraight: TrafficLightState?, val durationStraight: Int,
val stateTurnRight: TrafficLightState?, val durationTurnRight: Int
) :
LedUIDataChange(isShow = isShow, priority = 4, interruptRestore = true)
//前方施工提示
class RoadWorkAheadWarningUI() : LedUICountDown(priority = 2, countDownSeconds = 10)

View File

@@ -401,7 +401,13 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack {
List<LangTtsEntity> ttsEntityList = new ArrayList<>();
ttsEntityList.add(new LangTtsEntity(tts, LanguageType.CHINESE));
MultiLangTtsEntity ttsEntity = new MultiLangTtsEntity(ttsEntityList);
speakMultiLangTTSWithLevel(ttsEntity, level);
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
UiThreadHandler.post(() -> {
speakMultiLangTTSWithLevel(ttsEntity, level);
}, QUEUE);
} else {
speakMultiLangTTSWithLevel(ttsEntity, level);
}
}
private void speakMultiLangTTSWithLevel(MultiLangTtsEntity ttsEntity,int ttsLevel) {