Merge branch 'dev_robotaxi-d_250603_8.1.0' into 'master'

Dev robotaxi d 250603 8.1.0

See merge request SCA/L4HA/AndroidApp/MoGoEagleEye!875
This commit is contained in:
yangyakun
2025-06-30 03:01:37 +00:00
913 changed files with 57703 additions and 2654 deletions

View File

@@ -100,15 +100,17 @@
<!--红绿灯-->
<com.mogo.eagle.core.function.hmi.ui.widget.SingleTrafficLightView
<com.mogo.eagle.core.function.hmi.ui.widget.TrafficLightView
android:id="@+id/viewTrafficLightVr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_28"
android:layout_marginEnd="@dimen/dp_40"
android:visibility="gone"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="@dimen/dp_14"
android:layout_marginEnd="@dimen/dp_21"
android:visibility="gone"
app:lightUser="passenger"
/>
<!--接管提示-->
<com.mogo.eagle.core.function.hmi.ui.vehicle.TakeOverView

View File

@@ -52,6 +52,7 @@ import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.socket.lan.LedScreenManager
import com.mogo.och.bridge.utils.CoordinateCalculateRouteUtil
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.common.module.utils.PinYinUtil
import com.mogo.och.common.module.voice.VoiceNotice
@@ -697,7 +698,7 @@ object CharterPassengerModel {
}
val lastTime: Double =
lastSumLength / CharterPassengerConst.Charter_AVERAGE_SPEED * 3.6 //秒
lastSumLength / OchCommonConst.Charter_AVERAGE_SPEED * 3.6 //秒
d(
M_BUS_P + "calculateDistance",

View File

@@ -66,14 +66,14 @@ object LoginServiceManager : IOchLanPassengerStatusListener {
if (oldValue != newValue) {
OchChainLogManager.writeChainLog("登录状态变化", "${oldValue}-->${newValue}")
Log.d(tag, "登录状态变化:${oldValue}-->${newValue}")
// if (newValue == EnumLoginStatus.Login && AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
// BizLoopManager.setLoopFunction(
// TAGLoopStatus,
// LoopInfo(60 * 2, ::queryLoginStatusByNet, immediately = false, scheduler = Schedulers.io())
// )
// } else {
// BizLoopManager.removeLoopFunction(TAGLoopStatus)
// }
if (newValue == EnumLoginStatus.Login && AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
BizLoopManager.setLoopFunction(
TAGLoopStatus,
LoopInfo(60 * 10, ::queryLoginStatusByNet, immediately = false, scheduler = Schedulers.io())
)
} else {
BizLoopManager.removeLoopFunction(TAGLoopStatus)
}
LoginStatusManager.invokeLoginStatusChange(loginStatus)
}
}

View File

@@ -10,9 +10,12 @@ import com.mogo.eagle.core.utilcode.util.CoordinateUtils
import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.bridge.distance.TrajectoryAndDistanceManager
import com.mogo.och.bridge.bridge.OchBridgeManager
import com.mogo.och.bridge.bridge.OchVlmManager
import com.mogo.och.bridge.trajectory.TrajectoryManager
import com.mogo.och.common.module.biz.birdge.BridgeService
import com.mogo.och.common.module.biz.birdge.BridgeListener
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.common.module.biz.birdge.data.VlmData
import com.mogo.och.common.module.constant.OchCommonConst
@@ -29,7 +32,14 @@ class BridgeProvider : BridgeService, CallerBase<BridgeListener>() {
override fun init(context: Context?) {
this.context = context
// 车前引导线+预测数据
OchBridgeManager.load()
// if(EnvManager.isT1T2Passenger()){
OchVlmManager.load()
// }
TrajectoryManager.load()
}
@@ -92,5 +102,17 @@ class BridgeProvider : BridgeService, CallerBase<BridgeListener>() {
}
}
fun invokeVlmDataDispatch(vlmData:VlmData){
M_LISTENERS.forEach {
it.value.onVlmDataListener(vlmData)
}
}
fun inVokeNdeData(title: String, desc: String, sortedList: List<RoadMsg>) {
M_LISTENERS.forEach {
it.value.onNdeDataListener(title,desc,sortedList)
}
}
}

View File

@@ -3,13 +3,10 @@ package com.mogo.och.bridge
import android.annotation.SuppressLint
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.common.module.biz.birdge.data.VlmData
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.loop.LoopInfo
import io.reactivex.schedulers.Schedulers
import kotlin.properties.Delegates
object BridgeServiceManager {
@@ -19,52 +16,12 @@ object BridgeServiceManager {
private var bridgeService: BridgeProvider? =
ARouter.getInstance().build(OchCommonConst.BIZ_Bridge).navigation() as BridgeProvider
private var trajectoryTime = 0L
private var predictionTime = 0L
init {
BizLoopManager.setLoopFunction(TAG,
LoopInfo(2, ::checkTimeout, immediately = false, scheduler = Schedulers.io())
)
}
// 是否有车前引导线
private var haveTrajectoryInfo: Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
bridgeService?.invokeTrajectoryHaveDataListener(newValue)
CallerLogger.d(TAG,"haveTrajectoryInfo 发生变化:${newValue}")
}
trajectoryTime = System.currentTimeMillis()
}
// 是否有预测数据
private var havePredictionInfo: Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
bridgeService?.invokePredictionHavaData(newValue)
CallerLogger.d(TAG,"havePredictionInfo 发生变化:${newValue}")
}
predictionTime = System.currentTimeMillis()
}
fun checkTimeout(){
if(System.currentTimeMillis() - trajectoryTime>2_000){
haveTrajectoryInfo = false
CallerLogger.d(TAG,"超时设置为falsehaveTrajectoryInfo ${haveTrajectoryInfo}")
}
if(System.currentTimeMillis() - predictionTime>2_000){
havePredictionInfo = false
CallerLogger.d(TAG,"超时设置为falsehavePredictionInfo ${havePredictionInfo}")
}
}
fun invokePlanningListener(haveTrajectoryInfos:Boolean){
this.haveTrajectoryInfo = haveTrajectoryInfos
bridgeService?.invokeTrajectoryHaveDataListener(haveTrajectoryInfos)
}
fun invokePredictionHaveData(havePredictionInfos:Boolean){
this.havePredictionInfo = havePredictionInfos
bridgeService?.invokePredictionHavaData(havePredictionInfos)
}
fun invokeTrajectoryPoints(trajectoryList: MutableList<MogoLocation>){
@@ -78,4 +35,15 @@ object BridgeServiceManager {
this.bridgeService?.invokeTrajectoryPointAndDistance(trajectoryList, distance)
}
/**
* 分发vmData
*/
fun invokeVlmData(vlmData: VlmData){
this.bridgeService?.invokeVlmDataDispatch(vlmData)
}
fun invokeNdeData(title: String, desc: String, sortedList: List<RoadMsg>) {
this.bridgeService?.inVokeNdeData(title,desc,sortedList)
}
}

View File

@@ -73,6 +73,7 @@ object OchAutopilotAnalytics {
params[EVENT_PARAM_AUTOPILOTANALYTICS_GROUP] = EVENT_PARAM_AUTOPILOTANALYTICS_GROUP
OchChainLogManager.addCommonParams(params)
MogoAnalyticUtils.track(EVENT_KEY_START_AUTOPILOT_PARAMETERS, params)
OchChainLogManager.writeChainLogAutopilot("正式启动自驾把参数传给底层",params.toString(),false)
}
/**
@@ -86,6 +87,7 @@ object OchAutopilotAnalytics {
params[EVENT_PARAM_AUTOPILOTANALYTICS_GROUP] = EVENT_PARAM_AUTOPILOTANALYTICS_GROUP
OchChainLogManager.addCommonParams(params)
MogoAnalyticUtils.track(EVENT_KEY_START_AUTOPILOT_ACK, params)
OchChainLogManager.writeChainLogAutopilot("底盘收到启动自驾的ack",params.toString(),false)
}
/**
@@ -156,6 +158,7 @@ object OchAutopilotAnalytics {
mStartAutopilotParams[EVENT_PARAM_AUTOPILOTANALYTICS_GROUP] = EVENT_PARAM_AUTOPILOTANALYTICS_GROUP
OchChainLogManager.addCommonParams(mStartAutopilotParams)
MogoAnalyticUtils.track(mStartAutopilotKey, mStartAutopilotParams)
OchChainLogManager.writeChainLogAutopilot("启动自驾失败",mStartAutopilotParams.toString(),false)
clearStartAutopilotParams() //清空参数数据,防止误传
}
@@ -200,6 +203,7 @@ object OchAutopilotAnalytics {
mStartAutopilotParams[EVENT_PARAM_AUTOPILOTANALYTICS_GROUP] = EVENT_PARAM_AUTOPILOTANALYTICS_GROUP
OchChainLogManager.addCommonParams(mStartAutopilotParams)
MogoAnalyticUtils.track(mStartAutopilotKey, mStartAutopilotParams)
OchChainLogManager.writeChainLogAutopilot("启动自驾成功",mStartAutopilotParams.toString(),false)
clearStartAutopilotParams() //清空参数数据,防止误传
} else {
mStartAutopilotParams[EVENT_PARAM_ENV_ONLINE] = DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE
@@ -251,6 +255,7 @@ object OchAutopilotAnalytics {
params[EVENT_PARAM_AUTOPILOTANALYTICS_GROUP] = EVENT_PARAM_AUTOPILOTANALYTICS_GROUP
OchChainLogManager.addCommonParams(mStartAutopilotParams)
MogoAnalyticUtils.track(getEventKeyApUnableStartReason(), params)
OchChainLogManager.writeChainLogAutopilot("触发\"无法开启自驾已知异常\"埋点",params.toString(),false)
}
/**
@@ -263,6 +268,7 @@ object OchAutopilotAnalytics {
params[EVENT_PARAM_AUTOPILOTANALYTICS_GROUP] = EVENT_PARAM_AUTOPILOTANALYTICS_GROUP
OchChainLogManager.addCommonParams(mStartAutopilotParams)
MogoAnalyticUtils.track(getEventKeyClickStartAutopilot(), params)
OchChainLogManager.writeChainLogAutopilot("用户点击启动自驾的时间",params.toString(),false)
}
/**

View File

@@ -0,0 +1,42 @@
package com.mogo.och.bridge.bridge
data class VlmImageData(val imageSourceTimestamp: Double ,var image: ByteArray?) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as VlmImageData
return imageSourceTimestamp == other.imageSourceTimestamp
}
override fun hashCode(): Int {
return imageSourceTimestamp.hashCode()
}
override fun toString(): String {
return "VlmImageData(imageSourceTimestamp=$imageSourceTimestamp)"
}
}
data class VlmMessageData(val messageSourceTimestamp: Double ,val id:Int?,val message:String?){
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as VlmMessageData
// if (messageSourceTimestamp != other.messageSourceTimestamp) return false
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
var result = messageSourceTimestamp.hashCode()
result = 31 * result + (id ?: 0)
return result
}
}

View File

@@ -1,27 +1,96 @@
package com.mogo.och.bridge.bridge
import android.util.Log
import com.mogo.commons.env.ProjectUtils
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningActionsListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningTrajectoryListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager.getWgs84Lat
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager.getWgs84Lon
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningTrajectoryListenerManager
import com.mogo.eagle.core.function.call.base.CallerBase
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.LocationUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.map.MogoMap
import com.mogo.map.MogoMap.Companion.mapInstance
import com.mogo.map.overlay.core.Level
import com.mogo.map.overlay.point.Point
import com.mogo.och.bridge.BridgeServiceManager
import com.mogo.och.bridge.R
import prediction2025.Prediction2025
import mogo.telematics.pad.MessagePad
import kotlin.properties.Delegates
object OchBridgeManager: CallerBase<IMoGoPlanningTrajectoryListener>(),
IMoGoPlanningTrajectoryListener, IMoGoAutopilotIdentifyListener {
object OchBridgeManager: IMoGoPlanningTrajectoryListener, IMoGoAutopilotIdentifyListener,
IMoGoAutopilotPlanningActionsListener {
private val TAG = "${M_OCHCOMMON}OchPlanningListenerManager"
private var trajectoryTime = 0L
private var predictionTime = 0L
private val map by lazy {
mapInstance.getMogoMap(MogoMap.DEFAULT)
}
@Volatile
private var lastTime: Long = 0L
@Volatile
private var lastUpdateTime: Long = 0L
@Volatile
private var isHide = false
fun load(){
CallerPlanningTrajectoryListenerManager.addListener(TAG,this)
CallerAutopilotIdentifyListenerManager.addListener(TAG,this)
CallerPlanningActionsListenerManager.addListener(TAG, this)
UiThreadHandler.postDelayed(timeRunnable, 1000)
}
fun release(){
fun release() {
CallerPlanningTrajectoryListenerManager.removeListener(TAG)
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
CallerPlanningActionsListenerManager.removeListener(TAG)
}
// 是否有车前引导线
private var haveTrajectoryInfo: Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
BridgeServiceManager.invokePlanningListener(newValue)
CallerLogger.d(TAG,"haveTrajectoryInfo 发生变化:${newValue}")
}
trajectoryTime = System.currentTimeMillis()
}
// 是否有预测数据
private var havePredictionInfo: Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
BridgeServiceManager.invokePredictionHaveData(newValue)
CallerLogger.d(TAG,"havePredictionInfo 发生变化:${newValue}")
}
predictionTime = System.currentTimeMillis()
}
fun checkTimeout(){
if(System.currentTimeMillis() - trajectoryTime>2_000){
haveTrajectoryInfo = false
CallerLogger.d(TAG,"超时设置为falsehaveTrajectoryInfo $haveTrajectoryInfo")
}
if(System.currentTimeMillis() - predictionTime>2_000){
havePredictionInfo = false
CallerLogger.d(TAG,"超时设置为falsehavePredictionInfo $havePredictionInfo")
}
}
/**
@@ -29,19 +98,100 @@ object OchBridgeManager: CallerBase<IMoGoPlanningTrajectoryListener>(),
*/
override fun onAutopilotTrajectory(trajectoryInfos: MutableList<MessagePad.TrajectoryPoint>) {
if(trajectoryInfos.isEmpty()){
BridgeServiceManager.invokePlanningListener(false)
haveTrajectoryInfo = false
}else{
BridgeServiceManager.invokePlanningListener(true)
haveTrajectoryInfo = true
}
}
/**
* 预测信息
*/
override fun onPredictionObstacleTrajectory(predictionObjects: Prediction2025.mPredictionObjects) {
if (predictionObjects.objsAppList==null) {
BridgeServiceManager.invokePredictionHaveData(false)
havePredictionInfo = false
}else{
BridgeServiceManager.invokePredictionHaveData(true)
havePredictionInfo = true
}
}
private val timeRunnable = Runnable {
timeCheck()
}
private fun timeCheck() {
if (lastUpdateTime > 0 && System.currentTimeMillis() - lastUpdateTime > 1000) {
ThreadUtils.getIoPool().execute {
CallerMapUIServiceManager.getOverlayManager()?.hidePoint("RenderParkingModel")
}
isHide = true
}
UiThreadHandler.postDelayed(timeRunnable, 1000)
}
override fun pncActions(planningActionMsg: MessagePad.PlanningActionMsg) {
if (!FunctionBuildConfig.isParkingOpen) return
val timeStamp = System.currentTimeMillis()
lastUpdateTime = timeStamp
if (timeStamp - lastTime >= 1000) {
lastTime = System.currentTimeMillis()
// Saas乘客屏且是自驾中
if (ProjectUtils.isSaas() && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)
) {
Log.d(TAG, "pncActions-Sass乘客屏收到数据!")
if (CallerAutoPilotStatusListenerManager.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
Log.d(TAG, "pncActions-非自驾中!")
CallerMapUIServiceManager.getOverlayManager()?.hidePoint("RenderParkingModel")
isHide = true
} else {
Log.d(TAG, "pncActions-UTM度带号:${planningActionMsg.utmZone},坐标为:(${planningActionMsg.updatedTerminal.x},${planningActionMsg.updatedTerminal.y}),角度为:${planningActionMsg.parkingLotHeading}")
val lonLatArr = map?.switchData(
planningActionMsg.updatedTerminal.x,
planningActionMsg.updatedTerminal.y,
false
)
lonLatArr?.let {
if (it.size < 2) {
Log.d(TAG, "pncActions-UTM坐标转换失败!")
CallerMapUIServiceManager.getOverlayManager()?.hidePoint("RenderParkingModel")
isHide = true
return@let
}
val lon = getWgs84Lon()
val lat = getWgs84Lat()
val distance = LocationUtils.getDistance(it[0], it[1], lon, lat)
Log.d(TAG, "自车位置:(${lon},${lat}),进站点位置:(${it[0]},${it[1]}),pncActions-进站点距离自车${distance}米!")
// 只处理100m以内的
if (distance >= 100) {
Log.d(TAG, "pncActions-进站点距离自车过远,不展示!")
CallerMapUIServiceManager.getOverlayManager()?.hidePoint("RenderParkingModel")
isHide = true
return@let
}
val angle = map!!.convertAngle(planningActionMsg.parkingLotHeading, it[0], it[1]).toFloat()
// owner、level、id作为key去从缓存中取
val builder =
Point.Options.Builder("TYPE_MARKER_PNC", Level.MAP_MARKER)
.setId("RenderParkingModel")
.anchor(0.5f, 0.5f)
.set3DMode(true)
.isUseGps(true)
.controlAngle(true)
.rotate(angle)
.icon3DRes(R.raw.parking_model)
.longitude(it[0])
.latitude(it[1])
CallerMapUIServiceManager.getOverlayManager()
?.showOrUpdatePoint(builder.build())
Log.d(TAG, "pncActions-展示进站点(${it[0]},${it[1]}),角度为:${angle}!")
if (isHide) {
Log.d(TAG, "pncActions-显示被隐藏的进站点!")
CallerMapUIServiceManager.getOverlayManager()?.showPoint("RenderParkingModel")
isHide = false
}
}
}
}
}
}
}

View File

@@ -1,24 +1,28 @@
package com.mogo.och.unmanned.passenger.ui.aiview
package com.mogo.och.bridge.bridge
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.och.unmanned.passenger.ui.aiview.bean.AIMessage
import com.mogo.eagle.core.function.call.autopilot.CallerVlmManager
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.och.bridge.BridgeServiceManager
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import mogo.telematics.pad.MessagePad.TrackedObject
class NDEViewModel: ViewModel(), IMoGoAutopilotIdentifyListener {
object OchNdeManager : IMoGoAutopilotIdentifyListener {
private val TAG = "${M_OCHCOMMON}OchVlmManager"
companion object{
private const val TAG = "NDEViewModel"
fun load(){
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
}
fun release(){
CallerVlmManager.removeListener(TAG)
}
private var lastMap2 = HashMap<Int, String>()
private var lastTime = 0L
fun init(){
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
}
override fun onAutopilotIdentifyDataUpdate(trafficData: List<TrackedObject>?){
super.onAutopilotIdentifyDataUpdate(trafficData)
handleCheLong(trafficData)
@@ -27,7 +31,7 @@ class NDEViewModel: ViewModel(), IMoGoAutopilotIdentifyListener {
private fun handleCheLong(trafficData: List<TrackedObject>?) {
var hasCheLong = false
var isNewData = false
val roadMsgList = ArrayList<AIMessage.RoadMsg>()
val roadMsgList = ArrayList<RoadMsg>()
val curMap = HashMap<Int, String>()
if (lastTime > 0 && System.currentTimeMillis() - lastTime > 60000) {
lastMap2.clear()// 清除上次车龙事件的缓存
@@ -55,8 +59,7 @@ class NDEViewModel: ViewModel(), IMoGoAutopilotIdentifyListener {
curMap[obj.laneNum] = "0"
}
// 保存所有车道信息
roadMsgList.add(
AIMessage.RoadMsg(
roadMsgList.add(RoadMsg(
obj.arrowType,
laneNum = obj.laneNum,
isRecommend = obj.suggestedLanes,
@@ -74,10 +77,8 @@ class NDEViewModel: ViewModel(), IMoGoAutopilotIdentifyListener {
lastTime = System.currentTimeMillis()
val sortedList = roadMsgList.sortedWith(compareByDescending { it.laneNum })
val ndeEvent = AIMessage.NDEData(System.currentTimeMillis().toString(),"路口车龙","前方路口有车龙",sortedList)
AIMessageManager.post(ndeEvent)
BridgeServiceManager.invokeNdeData("路口车龙","前方路口有车龙",sortedList)
}
}
}
}

View File

@@ -0,0 +1,68 @@
package com.mogo.och.bridge.bridge
import com.mogo.eagle.core.function.api.autopilot.IVlmListener
import com.mogo.eagle.core.function.call.autopilot.CallerVlmManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.och.bridge.BridgeServiceManager
import com.mogo.och.common.module.biz.birdge.data.VlmData
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import vllm.Vlm
import kotlin.properties.Delegates
object OchVlmManager : IVlmListener {
private val TAG = "${M_OCHCOMMON}OchVlmManager"
fun load(){
CallerVlmManager.addListener(TAG,this)
}
fun release(){
CallerVlmManager.removeListener(TAG)
}
//
private var vllmImageData: VlmImageData by Delegates.observable(VlmImageData(0.0,null)) { _, oldValue, newValue ->
if (oldValue != newValue) {
if(newValue.imageSourceTimestamp == vllmData.messageSourceTimestamp){
CallerLogger.d(TAG," message先来 图片后来 发送message和图片 ${newValue.imageSourceTimestamp}---${vllmData.messageSourceTimestamp}")
val timemillis = System.currentTimeMillis()
BridgeServiceManager.invokeVlmData(VlmData(vllmData.id,vllmData.message,newValue.image, timemillis))
OchChainLogManager.writeChainLogEyeVlm("收到VlmData"," message先来 图片后来 发送message和图片 ${newValue.imageSourceTimestamp}---${vllmData.messageSourceTimestamp}--$timemillis")
}
}
}
private var vllmData: VlmMessageData by Delegates.observable(VlmMessageData(0.0,0,"")) { _, oldValue, newValue ->
if (oldValue != newValue) {
val currentTimeMillis = System.currentTimeMillis()
if(newValue.messageSourceTimestamp== vllmImageData.imageSourceTimestamp){
// 图片先来 发送message和图片
BridgeServiceManager.invokeVlmData(VlmData(newValue.id,newValue.message,
vllmImageData.image, currentTimeMillis
)
)
CallerLogger.d(TAG,"messsage后来 图片先来 发送message和图片 ${newValue.message}----${newValue.messageSourceTimestamp}---${newValue.id}")
OchChainLogManager.writeChainLogEyeVlm("收到VlmData","messsage后来 图片先来 发送message和图片 ${newValue.message}----${newValue.messageSourceTimestamp}---${newValue.id}--$currentTimeMillis")
}else{
// message 先来 单独发送message 图片来了后 再次发送出去
BridgeServiceManager.invokeVlmData(VlmData(newValue.id,newValue.message,null,
currentTimeMillis
))
CallerLogger.d(TAG,"message先来 图片后来 发送message ${newValue.message}---${newValue.messageSourceTimestamp}---${newValue.id}---$currentTimeMillis")
OchChainLogManager.writeChainLogEyeVlm("收到VlmData","message先来 图片后来 发送message ${newValue.message}---${newValue.messageSourceTimestamp}---${newValue.id}---$currentTimeMillis")
}
}
}
override fun onVllm(sourceTimestamp: Double, vllm: Vlm.VLLMObject) {
if(this.vllmData.id!=vllm.workZone.id){
this.vllmData = VlmMessageData(sourceTimestamp,vllm.workZone.id,vllm.workZone.sceneExplantion)
}
}
override fun onVllmImage(sourceTimestamp: Double, image: ByteArray) {
this.vllmImageData = VlmImageData(sourceTimestamp,image)
}
}

Binary file not shown.

View File

@@ -1,6 +1,8 @@
package com.mogo.och.common.module.debug
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Environment
import android.os.SystemClock
import chassis.Chassis
@@ -8,6 +10,7 @@ import chassis.Chassis.DoorNumber
import chassis.VehicleStateOuterClass
import com.amap.api.maps.model.LatLng
import com.google.gson.reflect.TypeToken
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.data.enums.DataSourceType
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.map.MogoLocation
@@ -24,6 +27,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02Lis
import com.mogo.eagle.core.function.call.autopilot.CallerChassisStatesListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerVlmManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.map.CallerMapRomaListener
@@ -34,24 +38,25 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.R
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.biz.order.OrderManager
import com.mogo.och.common.module.debug.location.MogoLocationExit
import com.mogo.och.common.module.manager.loop.BizLoopManager
//import com.mogo.och.bridge.distance.TrajectoryAndDistanceManager
//import com.mogo.och.bridge.utils.CoordinateCalculateRouteUtil
//import com.mogo.och.bridge.utils.CoordinateCalculateRouteUtil
import com.mogo.och.common.module.view.DebugFloatWindow
import com.mogo.och.common.module.wigets.media.MediaBeanManager
import com.zhjt.mogo.adas.data.bean.AutopilotStatistics
import mogo.telematics.pad.MessagePad
import mogo_msg.MogoReportMsg
import vllm.Vlm
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStreamReader
object DebugDataDispatch {
const val TAG = "DebugDataDispatch"
@@ -73,6 +78,8 @@ object DebugDataDispatch {
const val ota = "ota"
const val video = "video"
const val mediaMusic = "mediaAndMusic"
const val vlmMessage = "vlmMessage"
const val vlmImage = "vlmImage"
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "location" --es path "1111/11111"
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "globalPath" --es path "sy73.json"
@@ -89,7 +96,10 @@ object DebugDataDispatch {
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "showDebugView"
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "scanner" --es qrInfo ""
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "ota" --ei "ota" 1
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "video" --ei "video" 1 --es url "rtmp://video.zhidaozhixing.com/live/861130041693196C_2"
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "vlmMessage" --es message "前方100米有道路施工施工长度100米影响第1、2车道通行。" --ei id 128 --ef time 1880.0
// adb shell am broadcast -a com.mogo.launcher.debug -f 0x011000000 --es type "vlmImage" --ef time 1880.0
// adb shell am broadcast -a com.hmi.v2x.trafficlight -f 0x011000000 --ei trafficLightCheckType 1 --ei trafficLightCountDown 0 --ez trafficLightIsShow true // 红绿灯
val ROOT_PATH =
@@ -102,6 +112,25 @@ object DebugDataDispatch {
}
when (type) {
vlmMessage -> {
val time = intent.getFloatExtra("time",0f)
val id = intent.getIntExtra("id",0)
val message = intent.getStringExtra("message")
val newBuilder = Vlm.VLLMObject.newBuilder()
val build = newBuilder.workZoneBuilder.setId(id).setSceneExplantion(message).build()
newBuilder.workZone = build
CallerVlmManager.invokeVllm(time.toDouble(),newBuilder.build())
}
vlmImage -> {
val time = intent.getFloatExtra("time",0f)
BizLoopManager.runInIoThread{
val bitmap = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.common_debug)
val stream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
val byteArray = stream.toByteArray()
CallerVlmManager.invokeVllmImage(time.toDouble(),byteArray)
}
}
mediaMusic -> {
val musicList = MediaBeanManager.getMusicList()
val mediaList = MediaBeanManager.getMediaList()

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@@ -1,6 +1,8 @@
package com.mogo.och.common.module.biz.birdge
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.common.module.biz.birdge.data.VlmData
interface BridgeListener {
/**
@@ -15,4 +17,9 @@ interface BridgeListener {
fun onTrajectoryDistanceListener(distance: Double){}
fun onTrajectoryPointsAndDistanceListener(trajectoryList: MutableList<MogoLocation>,distance: Double){}
fun onVlmDataListener(vlmData: VlmData){}
fun onNdeDataListener(title: String, desc: String, sortedList: List<RoadMsg>) {}
}

View File

@@ -0,0 +1,8 @@
package com.mogo.och.common.module.biz.birdge.data
data class RoadMsg(
var arrowType: Int, // 车道类型如直行201(详情参考文件message_pad.proto)
var laneNum: Int,// 车道号
var isRecommend: Boolean,// 是否是推荐车道
var isCheLong: Boolean// 是否有车龙,代表拥堵、行驶缓慢
)

View File

@@ -0,0 +1,33 @@
package com.mogo.och.common.module.biz.birdge.data
data class VlmData(
val id: Int?,
val message: String?,
var image: ByteArray?,
var timestamp: Long = System.currentTimeMillis()
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as VlmData
if (id != other.id) return false
if (message != other.message) return false
if (image != null) {
if (other.image == null) return false
if (!image.contentEquals(other.image)) return false
} else if (other.image != null) return false
return true
}
override fun hashCode(): Int {
return id ?: 0
}
override fun toString(): String {
return "VlmData(id=$id, message=$message)"
}
}

View File

@@ -71,5 +71,14 @@ class OchCommonConst {
const val AUTOMATIC_PLANNING_MAX_DISTANCE = 15
const val ARRIVE_AT_END_STATION_DISTANCE = 10
//b1 b2 平均速度 bus的平均里程25km/h
const val BUS_AVERAGE_SPEED = 25
//M1的平均里程15km/h
const val Charter_AVERAGE_SPEED = 15
//T1T2的平均里程38km/h
const val TAXI_AVERAGE_SPEED = 38
}
}

View File

@@ -0,0 +1,45 @@
package com.mogo.och.common.module.manager
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
object EnvManager {
fun isB1(): Boolean {
return AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)
}
fun isB1Driver(): Boolean {
return isB1() && AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
}
fun isB1Passenger(): Boolean {
return isB1() && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)
}
fun isB2(): Boolean {
return AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)
}
fun isB2Driver(): Boolean {
return isB2() && AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
}
fun isB2Passenger(): Boolean {
return isB2() && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)
}
fun isT1T2(): Boolean {
return AppIdentityModeUtils.isT1T2(FunctionBuildConfig.appIdentityMode)
}
fun isT1T2Driver(): Boolean {
return isT1T2() && AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
}
fun isT1T2Passenger(): Boolean {
return isT1T2() && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)
}
}

View File

@@ -4,6 +4,7 @@ import android.content.Context
import android.media.AudioManager
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.manager.EnvManager
import com.mogo.och.common.module.manager.audition.AuditionManager
import com.mogo.och.common.module.manager.audition.MusicData
import com.mogo.och.common.module.manager.audition.PlayState
@@ -64,7 +65,11 @@ object AudioFocusManager : AuditionManager.MusicDataChangeListener {
if(isPlaying!= isPlayingVideo) {
isPlayingVideo = isPlaying
if(isPlaying){
AuditionManager.stop()
if(EnvManager.isT1T2Passenger()){
AuditionManager.pause()
}else {
AuditionManager.stop()
}
}
}
}

View File

@@ -64,6 +64,15 @@ object AuditionManager: AuditionCacheManager.DataChangeListener, Audition.OnAudi
return Audition.isPlaying
}
fun pause(){
val playing = isPlaying()
if(playing){
musicDataPlaying?.let {
toggle(it)
}
}
}
fun stop(){
val playing = isPlaying()
if(playing){

View File

@@ -64,12 +64,16 @@ object OchChainLogManager {
const val EVENT_KEY_INFO_ERROR = "analytics_event_och_error"
const val EVENT_KEY_INFO_VLM = "analytics_event_och_vlm"
fun writeChainLogEye(title: String, info: String) {
writeChainLog(title, info, true, EVENT_KEY_INFO_CALL_EYE)
}
fun writeChainLogEyeVlm(title: String, info: String) {
writeChainLog(title, info, false, EVENT_KEY_INFO_VLM)
}
// 时间方面的日志
fun writeChainLogTime(title: String, info: String) {
@@ -120,8 +124,8 @@ object OchChainLogManager {
fun writeChainLogScanner(title: String, changeInfo: String) {
writeChainLog(title, changeInfo, true, EVENT_KEY_INFO_SCANNER)
}
fun writeChainLogAutopilot(title: String, changeInfo: String) {
writeChainLog(title, changeInfo, true, EVENT_KEY_INFO_AUTOPILOT)
fun writeChainLogAutopilot(title: String, changeInfo: String,upload:Boolean = true) {
writeChainLog(title, changeInfo, upload, EVENT_KEY_INFO_AUTOPILOT)
}
fun writeChainLogInit(title: String, info: String) {

View File

@@ -1,6 +1,7 @@
package com.mogo.och.common.module.wigets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
@@ -10,6 +11,8 @@ import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;
import com.mogo.och.common.module.R;
/**
* 通用渐变文字
* @author: wangmingjun
@@ -30,6 +33,8 @@ public class OCHGradientTextView extends AppCompatTextView {
private float mdy;
private int mColor;
private int ochgravity = 1;
public OCHGradientTextView(Context context) {
this(context, null);
}
@@ -39,6 +44,11 @@ public class OCHGradientTextView extends AppCompatTextView {
super(context, attrs);
//设置默认的颜色
mColorList = new int[]{0xFFFFFFFF, 0xFFFFFFF};
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OCHGradientTextView);
ochgravity = array.getInt(R.styleable.OCHGradientTextView_ochgravity, 1);
array.recycle();
}
@@ -60,7 +70,11 @@ public class OCHGradientTextView extends AppCompatTextView {
mPaint.setShadowLayer(mRadius, mdx, mdy, mColor);
//画出文字
canvas.drawText(mTipText, getMeasuredWidth() / 2.0f - mTextBound.width() / 2.0f, getMeasuredHeight() / 2.0f + mTextBound.height() / 2.0f, mPaint);
if(ochgravity==1) {
canvas.drawText(mTipText, getMeasuredWidth() / 2.0f - mTextBound.width() / 2.0f, getMeasuredHeight() / 2.0f + mTextBound.height() / 2.0f, mPaint);
}else if(ochgravity==0){
canvas.drawText(mTipText, 0f, getMeasuredHeight() / 2.0f + mTextBound.height() / 2.0f-mTextBound.bottom, mPaint);
}
}
/**

View File

@@ -14,6 +14,10 @@
<attr name="assetsfolder" format="string" />
</declare-styleable>
<declare-styleable name="OCHGradientTextView">
<attr name="ochgravity" format="integer" />
</declare-styleable>
<declare-styleable name="EmptyView">
<attr name="empty_title" format="string" />
</declare-styleable>

View File

@@ -8,6 +8,7 @@
<color name="taxi_111533">#111533</color>
<color name="taxi_878890">#878890</color>
<color name="taxi_EF262C">#EF262C</color>
<color name="common_color_00000000">#00000000</color>
<color name="common_color_4D000000">#4D000000</color>
<color name="common_color_99000000">#99000000</color>
@@ -18,6 +19,7 @@
<color name="common_80000000">#80000000</color>
<color name="common_80FFFFFF">#80FFFFFF</color>
<color name="common_FFFFFF">#FFFFFF</color>
<color name="common_1466FB">#1466FB</color>
<color name="common_e0efff">#E0EFFF</color>
<color name="common_b8c2d7">#B8C2D7</color>
@@ -42,10 +44,15 @@
<color name="common_FF4E41">#FF4E41</color>
<color name="common_B3FFFFFF">#B3FFFFFF</color>
<color name="common_cccccc">#CCCCCC</color>
<color name="common_284F7E">#284F7E</color>
<color name="common_f7151d41">#F7151D41</color>
<color name="common_3B3D44">#3B3D44</color>
<color name="common_2E323A">#2E323A</color>
<color name="common_ffffffff">#ffffffff</color>
<color name="common_10ffffff">#1Affffff</color>
<color name="common_50ffffff">#80000000</color>
<color name="common_2eacff">#2EACFF</color>
<color name="common_d4d4d4">#D4D4D4</color>
<color name="common_ff852e">#FF852E</color>
</resources>

View File

@@ -39,6 +39,7 @@ class TaskRunningAdapter(
private var totalHeight = 0f
fun setDataList(dataList: List<BusStationBean>) {
CallerLogger.d(TAG,"设置view-----")
this.mData.clear()
this.mData.addAll(dataList)
if (LineModel.startStationIndex == 0) {
@@ -47,7 +48,7 @@ class TaskRunningAdapter(
totalHeight =
(halfHeight + (dataList.size - 1 - LineModel.startStationIndex) * heightItem).toFloat()
}
notifyItemRangeChanged(0, dataList.size, true)
notifyDataSetChanged()
}
override fun onCreateViewHolder(

View File

@@ -48,13 +48,13 @@ android {
main {
res.srcDirs = [
'src/main/res',
'src/main/res/m2',
'src/main/res/jinlv',
'src/main/res/b2',
'src/main/res/b1',
]
java.srcDirs = [
'src/main/java',
'src/main/java/m2',
'src/main/java/jinlv',
'src/main/java/b2',
'src/main/java/b1',
]
}
}

View File

@@ -37,11 +37,11 @@ class BaseBusPassengerPresenter(view: BusPassengerRouteFragment?) :
}
private fun initListeners() {
CommonModel.setRouteLineInfoCallback(this)
CommonModel.setRouteLineInfoCallback(TAG,this)
}
private fun releaseListeners() {
CommonModel.setRouteLineInfoCallback(null)
CommonModel.setRouteLineInfoCallback(TAG,null)
}
override fun updateSpeed(location: Int) {

View File

@@ -0,0 +1,242 @@
package com.mogo.och.shuttle.weaknet.passenger.presenter
import androidx.lifecycle.LifecycleOwner
import com.amap.api.maps.model.LatLng
import com.mogo.commons.mvp.Presenter
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.biz.birdge.BridgeListener
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.utils.RxUtils
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.callback.ADASCallback
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.constant.M2Const.Companion.M2_MAP_STATION_MAKER
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
import com.mogo.och.shuttle.weaknet.passenger.model.PM2ADASModel
import com.mogo.och.shuttle.weaknet.passenger.ui.map.PM2HPMapFragment
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import io.reactivex.disposables.Disposable
import kotlin.properties.Delegates
class PM2ADASPresenter(view: PM2HPMapFragment?) :
Presenter<PM2HPMapFragment?>(view), ADASCallback, ICommonCallback, BridgeListener,
AIMessageManager.AIMessageListener {
private val TAG = "PM2ADASPresenter"
private var haveTrajectoryInfos:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
checkScreenChange()
}
}
private var havePredictionInfos:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
checkScreenChange()
}
}
// 是否有订单
private var haveLine:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
checkScreenChange()
}
}
private var arrived:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
checkScreenChange()
}
}
private var aiMessageShowmagic:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
checkScreenChange()
}
}
private var lastAiMessageTime:Long by Delegates.observable(System.currentTimeMillis()) { _, oldValue, newValue ->
if (oldValue != newValue) {
aiMessageShowmagic = true
RxUtils.disposeSubscribe(lastAIMessageCountDown)
lastAIMessageCountDown = RxUtils.createSubscribe(5_000) {
aiMessageShowmagic = false
}
}
}
private var lastAIMessageCountDown: Disposable? = null
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
PM2ADASModel.INSTANCE.init(context)
initListener()
}
private fun initListener() {
PM2ADASModel.INSTANCE.setAdasCallback(this)
CommonModel.setRouteLineInfoCallback(TAG, this)
BridgeManager.addBridgeListener(TAG,this)
AIMessageManager.registerListener(this)
}
private fun removeListener() {
PM2ADASModel.INSTANCE.setAdasCallback(null)
CommonModel.setRouteLineInfoCallback(TAG,null)
CommonModel.releaseListeners()
BridgeManager.removeBridgeListener(TAG)
AIMessageManager.unregisterListener(this)
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
removeListener()
}
override fun updateHDMapStations(stations: MutableList<MutableList<Double>>) {
for (i in stations.indices) {
mView?.setMapMaker(M2_MAP_STATION_MAKER + i, stations[i])
}
}
override fun clearCustomPolyline() {
ThreadUtils.runOnUiThread {
mView?.clearCustomPolyline()
}
}
override fun updateLineStations(stations: MutableList<BusStationBean>) {
val stationsList = mutableListOf<LatLng>()
val stationsListPass = mutableListOf<LatLng>()
var startStation: LatLng? = null
var endStation: LatLng? = null
for (i in stations.indices) {
val station = stations[i]
val latLng = LatLng(station.gcjLat, station.gcjLon)
if (i == 0) {
startStation = latLng
continue
}
if (i == stations.size - 1) {
endStation = latLng
continue
}
if (station.drivingStatus == 1) {//行驶信息0初始值1已经过2当前站3未到站
stationsListPass.add(latLng)
} else if (station.drivingStatus == 2) {
if (station.isLeaving) {
arrived = false
stationsListPass.add(latLng)
} else {
arrived = true
stationsList.add(latLng)
}
} else {
stationsList.add(latLng)
}
}
ThreadUtils.runOnUiThread {
mView?.updateLineStations(stationsList, stationsListPass, startStation, endStation)
}
PM2ADASModel.INSTANCE.updateHDMapStations(stations)
}
override fun removeHDMapStations() {
mView?.removeMapMaker(M2_MAP_STATION_MAKER)
}
override fun showNoTaskView(noLine: Boolean) {
haveLine = !noLine
ThreadUtils.runOnUiThread {
mView?.showNoTaskView(!noLine)
}
}
override fun onTrajectoryHaveData(haveTrajectoryInfos: Boolean) {
this.haveTrajectoryInfos = haveTrajectoryInfos
// checkScreenChange()
}
override fun onPredictionHavaData(havePredictionInfos: Boolean) {
this.havePredictionInfos = havePredictionInfos
// checkScreenChange()
}
override fun onReceive(msg: AIMessage) {
lastAiMessageTime = System.currentTimeMillis()
}
override fun clear() {
}
fun checkScreenChange(){
CallerLogger.d(TAG,"haveLine:$haveLine arrived:$arrived havePredictionInfos:$havePredictionInfos haveTrajectoryInfos:$haveTrajectoryInfos aiMessageShowmagic:$aiMessageShowmagic")
BizLoopManager.runInMainThread{
// 是否有订单
if(haveLine){// 有订单
if(arrived){//展示高德地图
if(aiMessageShowmagic){
updateMapFlag(false)
// 展示高德地图+展示mogomind
mView?.showAmap_mind()
return@runInMainThread
}else{
updateMapFlag(false)
// 展示高德地图
mView?.showAmap()
return@runInMainThread
}
}else{// 展示高精地图
if(aiMessageShowmagic){
updateMapFlag(false)
// 展示高精地图
mView?.showHDMap_mind()
return@runInMainThread
}else{
// if(havePredictionInfos&&haveTrajectoryInfos){
// updateMapFlag(true)
// // 展示高精地图+展示预测和决策
// mView?.showHDMap_aip_prediction()
// return@runInMainThread
// }else{
updateMapFlag(false)
// 展示高精地图
mView?.showHDMap()
return@runInMainThread
// }
}
}
}else{// 没有订单
if(aiMessageShowmagic){// 有mogomind 消息
updateMapFlag(false)
// 展示高精地图+mogoMind
mView?.showHDMap_mind()
}else{
updateMapFlag(false)
// 展示高精地图
mView?.showHDMap()
}
}
}
}
private fun updateMapFlag(open: Boolean) {
// if (open) {
// FunctionBuildConfig.isDrawDecIdentifyData = true
// FunctionBuildConfig.isDrawPreIdentifyData = true
// } else {
// FunctionBuildConfig.isDrawDecIdentifyData = false
// FunctionBuildConfig.isDrawPreIdentifyData = false
// }
}
}

View File

@@ -0,0 +1,67 @@
package com.mogo.och.shuttle.weaknet.passenger.presenter
import androidx.lifecycle.LifecycleOwner
import com.mogo.commons.mvp.Presenter
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.shuttle.weaknet.passenger.model.PM2ADASModel
import com.mogo.och.shuttle.weaknet.passenger.ui.line.PM2DrivingInfoFragment
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
class PM2DrivingPresenter(view: PM2DrivingInfoFragment?) :
Presenter<PM2DrivingInfoFragment?>(view),
ICommonCallback {
private val TAG = "PM2DrivingPresenter"
init {
CommonModel.init(context)
PM2ADASModel.INSTANCE.init(context)
initListener()
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
destroyListener()
CommonModel.releaseListeners()
}
private fun initListener(){
CommonModel.setRouteLineInfoCallback(TAG,this)
}
private fun destroyListener(){
CommonModel.setRouteLineInfoCallback(TAG,null)
}
override fun updateSpeed(speed: Int) {
}
override fun updateRemainMT(meters: Long, timeInSecond: Long) {
ThreadUtils.runOnUiThread {
mView?.updateRemainMT(meters, timeInSecond) //米,秒
}
}
override fun showNoTaskView(empty: Boolean) {
ThreadUtils.runOnUiThread {
mView?.showNoTaskView(empty)
}
if (empty){
PM2ADASModel.INSTANCE.removeHDMapStations()
}
}
override fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean) {
ThreadUtils.runOnUiThread {
mView?.updateStationsInfo(stations,i,isArrived)
}
}
}

View File

@@ -0,0 +1,168 @@
package com.mogo.och.shuttle.weaknet.passenger.ui
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.mogo.commons.mvp.MvpFragment
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.util.AppUtils
import com.mogo.eagle.core.utilcode.util.UriUtils
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.transform.OchTransform
import com.mogo.och.common.module.manager.transform.OchTransformDispatch
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.presenter.PM2Presenter
import com.mogo.och.common.module.wigets.media.MediaPlayerFragment
import com.mogo.och.shuttle.weaknet.passenger.ui.line.PM2DrivingInfoFragment
import com.mogo.och.shuttle.weaknet.passenger.ui.map.PM2HPMapFragment
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.test1
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.test2
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.test3
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.tv_shuttle_b2_p_version
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.video_fragment
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class PM2BaseFragment :
MvpFragment<PM2BaseFragment?, PM2Presenter?>() {
val TAG = PM2BaseFragment::class.java.simpleName
private var drivingFragment: PM2DrivingInfoFragment? = null
private var hdMapFragment: PM2HPMapFragment? = null
private var mediaFragment: MediaPlayerFragment? = null
// 视频直播流
private val ochTransform = object : OchTransformDispatch {
override fun setVideoView(target: View?) {
super.setVideoView(target)
if (target != null) {
BizLoopManager.runInMainThread {
target.id = R.id.video_show
val params = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
video_fragment.addView(target, params)
MediaManager.setMediaPause()
}
} else {
BizLoopManager.runInMainThread {
findViewById<View>(R.id.video_show)?.let {
video_fragment.removeView(it)
MediaManager.setMediaResume()
}
}
}
}
}
override fun getLayoutId(): Int {
return R.layout.shuttle_p_m2_fragment
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
tv_shuttle_b2_p_version.text = "版本:${AppUtils.getAppVersionName()}"
initFragment()
OchTransform.addListener(TAG, ochTransform)
}
override fun onDestroy() {
OchTransform.removeListener(TAG)
super.onDestroy()
}
/**
* 初始化行程信息,高静地图,宣传 三个fragment
*/
private fun initFragment() {
if (drivingFragment == null) drivingFragment = PM2DrivingInfoFragment()
childFragmentManager.beginTransaction().add(R.id.driving_fragment, drivingFragment!!)
.show(drivingFragment!!).commitAllowingStateLoss()
if (hdMapFragment == null) hdMapFragment = PM2HPMapFragment()
childFragmentManager.beginTransaction().add(R.id.hd_map_fragment, hdMapFragment!!)
.show(hdMapFragment!!).commitAllowingStateLoss()
if (mediaFragment == null) mediaFragment = MediaPlayerFragment()
childFragmentManager.beginTransaction().add(R.id.video_fragment, mediaFragment!!)
.show(mediaFragment!!).commitAllowingStateLoss()
test1.onClick {
CallerRoadV2NEventWindowListenerManager.showImage(
System.currentTimeMillis().toString(),
System.currentTimeMillis(),
EventTypeEnumNew.getUpdateIconRes(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
String.format(
EventTypeEnumNew.getAlarmContent(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
100
),
false,
EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
UriUtils.res2Uri(
EventTypeEnumNew.getPoiTypeBg(
EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType,
false
).toString()
).toString()
)
}
test2.onClick {
CallerMapRoadListenerManager.invokeCrossDevice(true)
}
test3.onClick {
val one = RoadMsg(201,1,true,false)
val two = RoadMsg(202,2,false,false)
val three = RoadMsg(203,3,false,true)
val sortedList = ArrayList<RoadMsg>()
sortedList.add(one)
sortedList.add(two)
sortedList.add(three)
val ndeEvent = AIMessage.NDEData(System.currentTimeMillis().toString(),"路口车龙","前方路口有车龙",sortedList)
AIMessageManager.post(ndeEvent)
// CallerRoadV2NEventWindowListenerManager.showImage(
// System.currentTimeMillis().toString(),
// System.currentTimeMillis(),
// EventTypeEnumNew.getUpdateIconRes(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
// String.format(
// EventTypeEnumNew.getAlarmContent(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
// 100
// ),
// false,
// String.format(
// EventTypeEnumNew.getWarningTts(EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType),
// 100
// ),
// UriUtils.res2Uri(
// EventTypeEnumNew.getPoiTypeBg(
// EventTypeEnumNew.TYPE_USECASE_ROAD_BUS_STATION.poiType,
// false
// ).toString()
// ).toString()
// )
}
}
override fun createPresenter(): PM2Presenter {
return PM2Presenter(this)
}
}

View File

@@ -0,0 +1,119 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line
import android.os.Bundle
import android.view.View
import com.mogo.commons.mvp.MvpFragment
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.presenter.PM2DrivingPresenter
import com.mogo.och.common.module.utils.NumberFormatUtil
import com.mogo.och.data.bean.BusStationBean
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.arriveView
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.emptyView
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.lineView
import kotlin.math.ceil
import kotlin.math.roundToInt
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class PM2DrivingInfoFragment :
MvpFragment<PM2DrivingInfoFragment?, PM2DrivingPresenter?>() {
override fun getLayoutId(): Int {
return R.layout.shuttle_p_m2_driving_info_fragment
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
}
override fun initViews(savedInstanceState: Bundle?) {
super.initViews(savedInstanceState)
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onDestroyView() {
mPresenter?.onDestroy(this)
super.onDestroyView()
}
fun showNoTaskView(haveTask: Boolean) {
if(haveTask){
emptyView.visibility = View.VISIBLE
arriveView.visibility = View.GONE
lineView.visibility = View.GONE
}else{
emptyView.visibility = View.GONE
arriveView.visibility = View.GONE
lineView.visibility = View.VISIBLE
}
}
override fun createPresenter(): PM2DrivingPresenter {
return PM2DrivingPresenter(this)
}
fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean) {
if(stations.isEmpty()){
emptyView.visibility = View.VISIBLE
arriveView.visibility = View.GONE
lineView.visibility = View.GONE
}else{
if(isArrived&&i!=0){
emptyView.visibility = View.GONE
arriveView.visibility = View.VISIBLE
lineView.visibility = View.GONE
arriveView.setArrivedStation(stations.get(i))
}else{
emptyView.visibility = View.GONE
arriveView.visibility = View.GONE
lineView.visibility = View.VISIBLE
}
}
}
/**
* 剩余里程和时间
*/
fun updateRemainMT(meters: Long, timeInSecond: Long) { //米。秒
var disUnit = "公里"
var remainDis: String? = "0"
if (meters > 0) {
if (meters / 1000 < 1) {
disUnit = ""
remainDis = meters.toFloat().roundToInt().toString()
} else {
disUnit = "公里"
remainDis = NumberFormatUtil.formatLong(meters.toDouble() / 1000)
}
}
val time = ceil(timeInSecond / 60f).toInt()
// "$remainDis$disUnit".also { tv_distance.text = it }
// "${time}分钟".also { tv_left_time.text = it }
}
companion object {
private val TAG = PM2DrivingInfoFragment::class.java.simpleName
}
}

View File

@@ -0,0 +1,139 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.arrive
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.drawable.AnimationDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.m2_arrive_view.view.aciv_arrow_left
import kotlinx.android.synthetic.main.m2_arrive_view.view.aciv_arrow_right
import kotlinx.android.synthetic.main.m2_arrive_view.view.aciv_door_left
import kotlinx.android.synthetic.main.m2_arrive_view.view.aciv_door_right
import kotlinx.android.synthetic.main.m2_arrive_view.view.iv_animal_list
import kotlinx.android.synthetic.main.m2_arrive_view.view.ochtv_arrive_station_value
import me.jessyan.autosize.utils.AutoSizeUtils
class ArrivedView : ConstraintLayout {
private val TAG = "ArrivedView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
val marginMax = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),-137f)
val marginMin = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),-55f)
val animatorArrow = ValueAnimator.ofInt(0, 30).apply {
duration = 500
repeatMode = ValueAnimator.REVERSE
repeatCount = -1
addUpdateListener { animation ->
val index = animation.animatedValue as Int
val paramsLeft = aciv_arrow_left.layoutParams as LayoutParams
paramsLeft.marginEnd = index
aciv_arrow_left.layoutParams = paramsLeft
val paramsRight = aciv_arrow_right.layoutParams as LayoutParams
paramsRight.marginStart = index
aciv_arrow_right.layoutParams = paramsRight
}
}
val animator = ValueAnimator.ofInt(marginMax, marginMin).apply {
duration = 500
addUpdateListener { animation ->
val index = animation.animatedValue as Int
val paramsLeft = aciv_door_left.layoutParams as LayoutParams
paramsLeft.marginEnd = index
aciv_door_left.layoutParams = paramsLeft
val paramsRight = aciv_door_right.layoutParams as LayoutParams
paramsRight.marginStart = index
aciv_door_right.layoutParams = paramsRight
if(index==-100){
aciv_arrow_left.visibility = VISIBLE
aciv_arrow_right.visibility = VISIBLE
}
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
animatorArrow.start()
CallerLogger.d(TAG,"动画结束了")
}
})
}
private fun initView() {
LayoutInflater.from(context).inflate(R.layout.m2_arrive_view, this, true)
ochtv_arrive_station_value.setVertrial(true)
val intArrayOf = intArrayOf(
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_43cefe),
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_1466fb),
)
ochtv_arrive_station_value.setmColorList(intArrayOf)
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
CallerLogger.d(TAG,"isVisible:${isVisible}")
if(isVisible) {
if(!animator.isRunning){
animator.start()
}
iv_animal_list.visibility = View.VISIBLE
val animationDrawable = iv_animal_list.drawable as AnimationDrawable
animationDrawable.start()
}else{
animator.cancel()
val paramsLeft = aciv_door_left.layoutParams as LayoutParams
paramsLeft.marginEnd =marginMax
aciv_door_left.layoutParams = paramsLeft
val paramsRight = aciv_door_right.layoutParams as LayoutParams
paramsRight.marginStart = marginMax
aciv_door_right.layoutParams = paramsRight
aciv_arrow_left.visibility = GONE
aciv_arrow_right.visibility = GONE
animatorArrow.cancel()
iv_animal_list.visibility = View.VISIBLE
val animationDrawable = iv_animal_list.drawable as AnimationDrawable
animationDrawable.stop()
}
}
fun setArrivedStation(busStationBean: BusStationBean) {
BizLoopManager.runInMainThread{
ochtv_arrive_station_value.text = busStationBean.name
}
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,45 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.autopilot
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.m2_speed.view.tv_speed
import kotlin.math.abs
class AutopilotView : ConstraintLayout {
private val TAG = "ItineraryView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private fun initView() {
LayoutInflater.from(context).inflate(R.layout.m2_autopilot, this, true)
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -1,4 +1,4 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.widget
package com.mogo.och.shuttle.weaknet.passenger.ui.line.autopilot.light
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
@@ -16,11 +16,9 @@ import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.common.module.manager.light.TurnLightManager
import kotlinx.android.synthetic.main.shuttle_p_m2_turn_light_status.view.left_nor_image
import kotlinx.android.synthetic.main.shuttle_p_m2_turn_light_status.view.left_select_image
import kotlinx.android.synthetic.main.shuttle_p_m2_turn_light_status.view.right_nor_image
import kotlinx.android.synthetic.main.shuttle_p_m2_turn_light_status.view.right_select_image
import kotlinx.android.synthetic.main.shuttle_p_m2_turn_light_status.view.turn_light_layout
/**
* @author: wangmingjun
@@ -43,8 +41,7 @@ class M2TurnLightView @JvmOverloads constructor(
private var isDisappear: Boolean = false
init {
LayoutInflater.from(context)
.inflate(R.layout.shuttle_p_m2_turn_light_status, this, true)
LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_turn_light_status, this, true)
}
override fun onAttachedToWindow() {
@@ -126,12 +123,12 @@ class M2TurnLightView @JvmOverloads constructor(
appearAnimation.duration = 300
val appearAnimationImage = AlphaAnimation(0f, 1.0f)
appearAnimation.duration = 500
turn_light_layout.startAnimation(appearAnimation)
left_nor_image.startAnimation(appearAnimationImage)
// turn_light_layout.startAnimation(appearAnimation)
// left_nor_image.startAnimation(appearAnimationImage)
right_nor_image.startAnimation(appearAnimationImage)
turn_light_layout.visibility = View.VISIBLE
left_nor_image.visibility = View.VISIBLE
// turn_light_layout.visibility = View.VISIBLE
// left_nor_image.visibility = View.VISIBLE
right_nor_image.visibility = View.VISIBLE
}
@@ -142,19 +139,15 @@ class M2TurnLightView @JvmOverloads constructor(
left_select_image.clearAnimation()
right_select_image.clearAnimation()
left_nor_image.clearAnimation()
//left_nor_image.clearAnimation()
right_nor_image.clearAnimation()
turn_light_layout.clearAnimation()
val disappearAnimationLeft = AlphaAnimation(1.0f, 0f)
disappearAnimationLeft.duration = 300
val disappearAnimationBg = AlphaAnimation(1.0f, 0f)
disappearAnimationBg.duration = 500
left_nor_image.startAnimation(disappearAnimationLeft)
//left_nor_image.startAnimation(disappearAnimationLeft)
right_nor_image.startAnimation(disappearAnimationLeft)
turn_light_layout.startAnimation(disappearAnimationBg)
disappearAnimationLeft.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(p0: Animation?) {
@@ -164,20 +157,8 @@ class M2TurnLightView @JvmOverloads constructor(
}
override fun onAnimationEnd(p0: Animation?) {
left_nor_image.visibility = View.GONE
right_nor_image.visibility = View.GONE
}
})
disappearAnimationBg.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(p0: Animation?) {
}
override fun onAnimationStart(p0: Animation?) {
}
override fun onAnimationEnd(p0: Animation?) {
turn_light_layout.visibility = View.GONE
// left_nor_image.visibility = View.GONE
// right_nor_image.visibility = View.GONE
}
})
}

View File

@@ -0,0 +1,64 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.autopilot.speed
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.m2_speed.view.tv_speed
import kotlin.math.abs
class SpeedView : ConstraintLayout, IMoGoChassisLocationGCJ02Listener {
private val TAG = "ItineraryView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private fun initView() {
LayoutInflater.from(context).inflate(R.layout.m2_speed, this, true)
tv_speed.setOnLongClickListener {
context?.let { ToggleDebugView.toggleDebugView.toggle(it) }
true
}
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
if(isVisible){
OchLocationManager.addGCJ02Listener(TAG, 3, this)
}else{
OchLocationManager.removeGCJ02Listener(TAG)
}
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
mogoLocation?.let {
BizLoopManager.runInMainThread {
val speedKM = (abs(it.gnssSpeed) * 3.6f).toInt()
tv_speed.text = speedKM.toString()
}
}
}
}

View File

@@ -0,0 +1,58 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.autopilot.status
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.content.ContextCompat
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
class StatusView : AppCompatTextView, ICommonCallback {
private val TAG = "ItineraryView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
private fun initView() {
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
if(isVisible){
CommonModel.setRouteLineInfoCallback(TAG,this)
}else{
CommonModel.setRouteLineInfoCallback(TAG,null)
}
}
override fun updateAutoStatus(isAutoPilot: Boolean) {
BizLoopManager.runInMainThread {
context?.let {
if (isAutoPilot) {
setTextColor(ContextCompat.getColor(it, R.color.common_FFFFFF))
background = ContextCompat.getDrawable(it, R.drawable.m2_autopilot_status_in)
} else {
setTextColor(ContextCompat.getColor(it, R.color.common_284F7E))
background = ContextCompat.getDrawable(it, R.drawable.m2_autopilot_status_out)
}
}
}
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,47 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.empty
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.m2_empty_view.view.tv_title
class EmptyView : ConstraintLayout {
private val TAG = "EmptyView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private fun initView() {
LayoutInflater.from(context).inflate(R.layout.m2_empty_view, this, true)
tv_title.setVertrial(true)
val intArrayOf = intArrayOf(
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_43cefe),
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_1466fb),
)
tv_title.setmColorList(intArrayOf)
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,92 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.wigets.WrapContentLinearLayoutManager
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.item.ItemDecoration
import com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.item.StationAdapter
import kotlinx.android.synthetic.main.m2_line_view.view.autoplit_info
import kotlinx.android.synthetic.main.m2_line_view.view.ll_station_container
import me.jessyan.autosize.utils.AutoSizeUtils
class LineView : ConstraintLayout, LineViewModel.LineViewCallback {
private val TAG = "EmptyView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private lateinit var mAdapter: StationAdapter
private lateinit var linearLayoutManager: LinearLayoutManager
private var viewModel:LineViewModel?=null
private fun initView() {
LayoutInflater.from(context).inflate(R.layout.m2_line_view, this, true)
linearLayoutManager = LinearLayoutManager(context)
ll_station_container.setLayoutManager(linearLayoutManager)
mAdapter = StationAdapter()
ll_station_container.addItemDecoration(ItemDecoration())
ll_station_container.setAdapter(mAdapter)
ll_station_container.itemAnimator?.addDuration = 0;
ll_station_container.itemAnimator?.changeDuration = 0;
ll_station_container.itemAnimator?.moveDuration = 0;
ll_station_container.itemAnimator?.removeDuration = 0;
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(LineViewModel::class.java)
}
viewModel?.setLineCallback(this)
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun updateLineStations(stations: MutableList<BusStationBean>?) {
CallerLogger.d(TAG,"展示站点:${stations}")
mAdapter.submitList(stations)
}
override fun updateRemainMt(distance: String, time: String) {
BizLoopManager.runInMainThread{
mAdapter.notifyDistanceAndTime(distance,time)
}
}
}

View File

@@ -0,0 +1,74 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.utils.NumberFormatUtil
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
import io.reactivex.disposables.Disposable
import kotlin.math.ceil
import kotlin.math.roundToInt
/**
* @author XuXinChao
* @description BadCase录包管理页面
* @since: 2022/12/15
*/
class LineViewModel : ViewModel(), ICommonCallback {
private val TAG = M_BUS+LineViewModel::class.java.simpleName
private var viewCallback:LineViewCallback?=null
private var endTaskDisposable:Disposable?=null
override fun onCleared() {
d(TAG,"onCleared")
CommonModel.setRouteLineInfoCallback(TAG,null)
}
fun setLineCallback(viewCallback:LineViewCallback){
this.viewCallback = viewCallback
CommonModel.setRouteLineInfoCallback(TAG,this)
}
override fun updateLineStations(stations: MutableList<BusStationBean>?) {
BizLoopManager.runInMainThread{
this.viewCallback?.updateLineStations(stations)
}
}
override fun updateRemainMT(meters: Long, timeInSecond: Long) {
super.updateRemainMT(meters, timeInSecond)
var disUnit = "公里"
var remainDis: String? = "0"
if (meters > 0) {
if (meters / 1000 < 1) {
disUnit = ""
remainDis = meters.toFloat().roundToInt().toString()
} else {
disUnit = "公里"
remainDis = NumberFormatUtil.formatLong(meters.toDouble() / 1000)
}
}
val time = ceil(timeInSecond / 60f).toInt()
// "$remainDis$disUnit".also { tv_distance.text = it }
// "${time}分钟".also { tv_left_time.text = it }
this.viewCallback?.updateRemainMt("$remainDis$disUnit","${time}分钟")
}
interface LineViewCallback{
fun updateLineStations(stations: MutableList<BusStationBean>?)
fun updateRemainMt(distance: String, time: String)
}
}

View File

@@ -0,0 +1,40 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.item
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import me.jessyan.autosize.utils.AutoSizeUtils
/**
* 这是LinearLayoutManager设置Item间距的的一个辅助类
*
* @author donghongyu
*/
class ItemDecoration() : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect, view: View,
parent: RecyclerView, state: RecyclerView.State
) {
if((parent.adapter?.itemCount ?: 4) < 4) {
val height = AutoSizeUtils.dp2px(parent.context, 140f)
val layoutParams = view.layoutParams as RecyclerView.LayoutParams
layoutParams.height = height
view.layoutParams = layoutParams
}else if((parent.adapter?.itemCount ?: 4) == 4){
val height = AutoSizeUtils.dp2px(parent.context, 100f)
val layoutParams = view.layoutParams as RecyclerView.LayoutParams
layoutParams.height = height
view.layoutParams = layoutParams
}else{
val height = AutoSizeUtils.dp2px(parent.context,68f)
val layoutParams = view.layoutParams as RecyclerView.LayoutParams
layoutParams.height = height
view.layoutParams = layoutParams
}
super.getItemOffsets(outRect, view, parent, state)
}
}

View File

@@ -0,0 +1,178 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.item
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.R
class StationAdapter : ListAdapter<BusStationBean, StationViewHolder>(MessageDiffCallback()) {
var currentIndex = 0
var isLeaving = false
var showPassOmit = false
var showFuluterOmit = false
var distanceAndTime = ""
override fun submitList(list: MutableList<BusStationBean>?) {
val newDataList = mutableListOf<BusStationBean>()
list?.let {
it.forEachIndexed { index, busStationBean ->
if (busStationBean.drivingStatus == 2) {
currentIndex = index
isLeaving = busStationBean.isLeaving
return@forEachIndexed
}
}
if (isLeaving) {
currentIndex += 1
}
if ((it.size) <= 7) {
showPassOmit = false
showFuluterOmit = false
newDataList.addAll(it.toList())
} else {
if(currentIndex-1<3){
showPassOmit = false // 全展示
}else{
showPassOmit = true // 展示省略
}
if(it.size-(currentIndex+1)-1<3) {// 全展示
showFuluterOmit = false
}else{// 展示省略
showFuluterOmit = true
}
if(showPassOmit&&showFuluterOmit){// 都有
newDataList.add(it.first())
newDataList.add(StationBeanOmit(currentIndex-1-1))
newDataList.addAll(list.slice(currentIndex-1 .. currentIndex+1))
newDataList.add(StationBeanOmit(list.size-(currentIndex+3)))// 减去+1 省略 和最后一个
newDataList.add(list.last())
}else{
if(showFuluterOmit||showPassOmit){
if(showFuluterOmit){// 只展示下面的省略号
newDataList.addAll(list.subList(0,5))
newDataList.add(StationBeanOmit(list.size-5-1))
newDataList.add(list.last())
}
if(showPassOmit){// 只展示上面的手机号
newDataList.add(list.first())
newDataList.add(StationBeanOmit(list.size-5-1))
newDataList.addAll(list.slice(list.size-5 until list.size))
} else {
}
}else{
newDataList.addAll(it.toList())
}
}
}
}
newDataList.forEachIndexed { index, busStationBean ->
if (busStationBean.drivingStatus == 2) {
currentIndex = index
isLeaving = busStationBean.isLeaving
if(isLeaving){
currentIndex+=1
}
}
}
distanceAndTime = ""
super.submitList(newDataList)
}
override fun onBindViewHolder(holder: StationViewHolder, position: Int) {
getItem(position)?.let {
holder.bind(it,distanceAndTime)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StationViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
StationViewHolder.NormalStationStart -> NormalStationStartViewHolder(
inflater.inflate(R.layout.m2_station_normal_start_view, parent, false)
)
StationViewHolder.NormalStationEnd -> NormalStationEndViewHolder(
inflater.inflate(R.layout.m2_station_normal_end_view, parent, false)
)
StationViewHolder.NormalStationFuture -> NormalStationFutureViewHolder(
inflater.inflate(R.layout.m2_station_normal_future_view, parent, false)
)
StationViewHolder.NormalStationPass -> NormalStationPassViewHolder(
inflater.inflate(R.layout.m2_station_normal_pass_view, parent, false)
)
StationViewHolder.CurrentStationStart -> CurrentStationStartViewHolder(
inflater.inflate(R.layout.m2_station_current_start_view, parent, false)
)
StationViewHolder.CurrentStationEnd -> CurrentStationEndViewHolder(
inflater.inflate(R.layout.m2_station_current_end_view, parent, false)
)
StationViewHolder.CurrentStation -> CurrentStationViewHolder(
inflater.inflate(R.layout.m2_station_current_view, parent, false)
)
StationViewHolder.OmitStationPass -> OmitPassViewHolder(
inflater.inflate(R.layout.m2_station_omit_view_pass, parent,false)
)
StationViewHolder.OmitStationFuture -> OmitFutureViewHolder(
inflater.inflate(R.layout.m2_station_omit_view_future, parent,false)
)
else -> throw IllegalArgumentException("Invalid view type")
}
}
override fun getItemViewType(position: Int): Int {
if (getItem(position) is StationBeanOmit) {
return if (position < currentIndex) {
StationViewHolder.OmitStationPass
} else {
StationViewHolder.OmitStationFuture
}
}
when (position) {
0 -> {
return if (currentIndex == position) {
StationViewHolder.CurrentStationStart
} else {
StationViewHolder.NormalStationStart
}
}
itemCount - 1 -> {
return if (currentIndex == position) {
StationViewHolder.CurrentStationEnd
} else {
StationViewHolder.NormalStationEnd
}
}
else -> {
return if (currentIndex == position) {
StationViewHolder.CurrentStation
} else if (currentIndex < position) {
StationViewHolder.NormalStationFuture
} else {
StationViewHolder.NormalStationPass
}
}
}
}
override fun onViewRecycled(holder: StationViewHolder) {
super.onViewRecycled(holder)
holder.viewRecycled(holder)
}
fun notifyDistanceAndTime(distance: String, time: String) {
distanceAndTime = "${distance}·${time}"
notifyItemChanged(currentIndex)
}
}

View File

@@ -0,0 +1,17 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.item
import androidx.recyclerview.widget.DiffUtil
import com.mogo.och.data.bean.BusStationBean
class MessageDiffCallback: DiffUtil.ItemCallback<BusStationBean>() {
override fun areContentsTheSame(oldItem: BusStationBean, newItem: BusStationBean): Boolean {
return oldItem == newItem
}
override fun areItemsTheSame(oldItem: BusStationBean, newItem: BusStationBean): Boolean {
return oldItem.siteId == newItem.siteId
}
}
data class StationBeanOmit(var coutOmit:Int):BusStationBean()

View File

@@ -0,0 +1,123 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.item
import android.view.View
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.common.module.wigets.OCHGradientTextView
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.R
import java.text.SimpleDateFormat
import java.util.Locale
abstract class StationViewHolder(view: View) : RecyclerView.ViewHolder(view) {
abstract fun bind(item: BusStationBean,distanceAndView:String)
open fun viewRecycled(holder: StationViewHolder){}
private val sampleDateFormat = SimpleDateFormat("HH:mm", Locale.CHINA)
protected val TAG = javaClass.simpleName
companion object{
val CurrentStationStart = 0
val CurrentStationEnd = 1
val CurrentStation = 2
val NormalStationStart = 3
var NormalStationEnd = 4
val NormalStationPass = 5
val NormalStationFuture = 6
val OmitStationPass = 7
val OmitStationFuture = 8
}
}
class NormalStationStartViewHolder(binding: View) : StationViewHolder(binding) {
private var startStaionName: AppCompatTextView = binding.findViewById(R.id.actv_normal_station_start)
override fun bind(item: BusStationBean,distanceAndView:String) {
startStaionName.text = item.name
}
}
class NormalStationEndViewHolder(binding: View) : StationViewHolder(binding) {
private var endStaionName: AppCompatTextView = binding.findViewById(R.id.actv_normal_station_end)
override fun bind(item: BusStationBean,distanceAndView:String) {
endStaionName.text = item.name
}
}
class NormalStationPassViewHolder(binding: View) : StationViewHolder(binding) {
private var passStaionName: AppCompatTextView = binding.findViewById(R.id.actv_normal_station_pass)
override fun bind(item: BusStationBean,distanceAndView:String) {
passStaionName.text = item.name
}
}
class NormalStationFutureViewHolder(binding: View) : StationViewHolder(binding) {
private var futureStaionName: AppCompatTextView = binding.findViewById(R.id.actv_normal_station_future)
override fun bind(item: BusStationBean,distanceAndView:String) {
futureStaionName.text = item.name
}
}
class CurrentStationViewHolder(binding: View) : StationViewHolder(binding) {
private var currentStaionName: OCHGradientTextView = binding.findViewById(R.id.och_current_station_name)
private var actv_distance: AppCompatTextView = binding.findViewById(R.id.actv_distance)
override fun bind(item: BusStationBean,distanceAndView:String) {
var text = item.name
if(text.length>12){
text = text.slice(0..10)+""
}
currentStaionName.text = text
currentStaionName.setVertrial(true)
val intArrayOf = intArrayOf(
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_43cefe),
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_1466fb),
)
currentStaionName.setmColorList(intArrayOf)
actv_distance.text = distanceAndView
}
}
class CurrentStationStartViewHolder(binding: View) : StationViewHolder(binding) {
private var currentStaionStartName: OCHGradientTextView = binding.findViewById(R.id.och_current_station_start_name)
override fun bind(item: BusStationBean,distanceAndView:String) {
currentStaionStartName.text = item.name
val intArrayOf = intArrayOf(
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_43cefe),
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_1466fb),
)
currentStaionStartName.setmColorList(intArrayOf)
}
}
class CurrentStationEndViewHolder(binding: View) : StationViewHolder(binding) {
private var currentStaionEndName: OCHGradientTextView = binding.findViewById(R.id.och_current_station_end_name)
private var actv_distance_end: AppCompatTextView = binding.findViewById(R.id.actv_distance_end)
override fun bind(item: BusStationBean,distanceAndView:String) {
var text = item.name
if(text.length>12){
text = text.slice(0..10)+""
}
currentStaionEndName.text = text
val intArrayOf = intArrayOf(
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_43cefe),
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_1466fb),
)
currentStaionEndName.setmColorList(intArrayOf)
actv_distance_end.text = distanceAndView
}
}
class OmitPassViewHolder(binding: View) : StationViewHolder(binding) {
private var omitCout: AppCompatTextView = binding.findViewById(R.id.actv_pass_omit_cout)
override fun bind(item: BusStationBean,distanceAndView:String) {
if(item is StationBeanOmit){
omitCout.text = "${item.coutOmit}"
}
}
}
class OmitFutureViewHolder(binding: View) : StationViewHolder(binding) {
private var omitCout: AppCompatTextView = binding.findViewById(R.id.actv_future_omit_count)
override fun bind(item: BusStationBean,distanceAndView:String) {
if(item is StationBeanOmit){
omitCout.text = "${item.coutOmit}"
}
}
}

View File

@@ -0,0 +1,297 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.map
import android.graphics.BitmapFactory
import android.os.Bundle
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.marginEnd
import com.amap.api.maps.model.LatLng
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.mvp.MvpFragment
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.view.SiteMarkerBean
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import com.mogo.map.overlay.core.Level
import com.mogo.map.overlay.point.Point
import com.mogo.map.MapDataWrapper
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.constant.M2Const.Companion.TYPE_MARKER_M2_LINE
import com.mogo.och.shuttle.weaknet.passenger.presenter.PM2ADASPresenter
import com.mogo.och.common.module.utils.OCHThreadPoolManager
import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.aciv_top_shader
import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.mHomeView
import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.mindView
import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.overMapView
import me.jessyan.autosize.utils.AutoSizeUtils
import java.util.*
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class PM2HPMapFragment :
MvpFragment<PM2HPMapFragment?, PM2ADASPresenter?>() {
private val stationIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_staton_icon
)
private val stationPassIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_staton_arrived_icon
)
private val startStationIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_start_icon
)
private val endStationIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_end_icon
)
/**
* 改变自动驾驶状态
*
* @param status 2 - running 1 - enable 2 - disable
*/
override fun getLayoutId(): Int {
return R.layout.shuttle_p_m2_hpmap_fragment
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
}
override fun initViews(savedInstanceState: Bundle?) {
super.initViews(savedInstanceState)
mHomeView.onCreate(savedInstanceState)
overMapView?.let {
it.onCreateView(savedInstanceState)
val radius = AutoSizeUtils.dp2px(requireContext(), 16f)
it.outlineProvider = TextureVideoViewOutlineProvider(radius.toFloat())
it.clipToOutline = true
it.hideResetView()
}
// cl_prediction_contain.onCreate(savedInstanceState)
}
override fun onResume() {
super.onResume()
mHomeView.onResume()
overMapView?.onResume()
// cl_prediction_contain.onResume()
}
override fun onLowMemory() {
super.onLowMemory()
mHomeView.onLowMemory()
// cl_prediction_contain.onLowMemory()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mHomeView.onSaveInstanceState(outState)
// cl_prediction_contain.onSaveInstanceState(outState)
}
override fun onPause() {
super.onPause()
mHomeView.onPause()
overMapView?.onPause()
// cl_prediction_contain.onPause()
}
override fun onDestroyView() {
mHomeView.onDestroy()
overMapView?.onDestroy()
// cl_prediction_contain.onDestroy()
super.onDestroyView()
}
override fun createPresenter(): PM2ADASPresenter {
return PM2ADASPresenter(this)
}
companion object {
private val TAG = PM2HPMapFragment::class.java.simpleName
}
fun updateLineStations(
stations: MutableList<LatLng>,
stationsPass: MutableList<LatLng>,
startStation: LatLng?,
endStation: LatLng?
) {
overMapView?.let {
val stationsList: MutableList<SiteMarkerBean> = mutableListOf()
startStation?.let { start ->
stationsList.add(SiteMarkerBean(start, startStationIcon, 0.5f, 0.5f))
}
for (stationPass in stationsPass) {
stationsList.add(SiteMarkerBean(stationPass, stationPassIcon, 0.5f, 0.5f))
}
for (stationPass in stations) {
stationsList.add(SiteMarkerBean(stationPass, stationIcon, 0.5f, 0.5f))
}
endStation?.let { end ->
stationsList.add(SiteMarkerBean(end, endStationIcon, 0.5f, 0.5f))
}
it.drawSiteMarkers(stationsList)
}
}
fun setMapMaker(
uuid: String,
station: MutableList<Double>,
) {
//开启线程执行起终点marker设置
val setMapMarkerRunnable = Runnable {
d(
"setMapMaker= " + Thread.currentThread().name,
uuid + "=latitude=" + station[1] + ",longitude=" + station[0]
)
val builder = Point.Options.Builder(
TYPE_MARKER_M2_LINE,
Level.MAP_MARKER
)
.setId(uuid)
.anchor(0.5f, 0.5f)
.set3DMode(true)
.isUseGps(true)
.controlAngle(true)
.icon3DRes(R.raw.star_marker)
.longitude(station[0])
.latitude(station[1])
MapDataWrapper.getCenterLineInfo(
station[0], station[1], -1f
) {
// 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 地图未初始化会返回空
it?.let{
builder.rotate(it.angle.toFloat())
}
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
overlayManager?.showOrUpdatePoint(builder.build())
}
}
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable)
}
fun removeMapMaker(
uuid: String,
) {
//开启线程移除起终点marker设置
val removeMapMarkerRunnable = Runnable {
d("RemoveMapMaker=" + Thread.currentThread().name, uuid)
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
overlayManager?.removeAllPointsInOwner(TYPE_MARKER_M2_LINE)
}
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable)
}
fun showNoTaskView(b: Boolean) {
if(!b) {
overMapView?.clearSiteMarkers()
clearCustomPolyline()
}
}
fun clearCustomPolyline() {
overMapView?.clearCustomPolyline()
}
// 展示高精地图
// 展示高精地图+展示预测和决策
// 展示高精地图+mogoMind
// 展示高德地图
// 展示高德地图+展示mogomind
val hdMapMarginEnd = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),-170f)
// 展示高精地图
fun showHDMap(){
mHomeView.visibility = View.VISIBLE
val layoutParams = mHomeView.layoutParams as ConstraintLayout.LayoutParams
layoutParams.marginStart = 0
mHomeView.layoutParams = layoutParams
aciv_top_shader.visibility = View.GONE
// cl_aip_contain.visibility = View.GONE
// cl_prediction_contain.visibility = View.GONE
mindView.visibility = View.GONE
overMapView.visibility = View.GONE
}
// 展示高德地图
fun showAmap(){
mHomeView.visibility = View.GONE
aciv_top_shader.visibility = View.GONE
// cl_aip_contain.visibility = View.GONE
// cl_prediction_contain.visibility = View.GONE
mindView.visibility = View.GONE
overMapView.visibility = View.VISIBLE
val layoutParams = overMapView.layoutParams as ConstraintLayout.LayoutParams
layoutParams.marginStart = 0
overMapView.layoutParams = layoutParams
}
// 展示高精地图+mogoMind
fun showHDMap_mind(){
mHomeView.visibility = View.VISIBLE
val layoutParams = mHomeView.layoutParams as ConstraintLayout.LayoutParams
layoutParams.marginStart = hdMapMarginEnd
mHomeView.layoutParams = layoutParams
aciv_top_shader.visibility = View.VISIBLE
// cl_aip_contain.visibility = View.GONE
// cl_prediction_contain.visibility = View.GONE
mindView.visibility = View.VISIBLE
overMapView.visibility = View.GONE
}
// 展示高精地图+展示预测和决策
fun showHDMap_aip_prediction(){
mHomeView.visibility = View.VISIBLE
val layoutParams = mHomeView.layoutParams as ConstraintLayout.LayoutParams
layoutParams.marginStart = hdMapMarginEnd
mHomeView.layoutParams = layoutParams
aciv_top_shader.visibility = View.VISIBLE
// cl_aip_contain.visibility = View.VISIBLE
// cl_prediction_contain.visibility = View.VISIBLE
mindView.visibility = View.GONE
overMapView.visibility = View.GONE
}
fun showAmap_mind(){
mHomeView.visibility = View.GONE
aciv_top_shader.visibility = View.VISIBLE
// cl_aip_contain.visibility = View.GONE
// cl_prediction_contain.visibility = View.GONE
mindView.visibility = View.VISIBLE
overMapView.visibility = View.VISIBLE
val layoutParams = overMapView.layoutParams as ConstraintLayout.LayoutParams
layoutParams.marginStart = hdMapMarginEnd
overMapView.layoutParams = layoutParams
}
}

View File

@@ -0,0 +1,64 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import java.util.concurrent.CopyOnWriteArrayList
object AIMessageManager {
// 使用 CopyOnWriteArrayList 来存储消息回调列表,保证线程安全
private val messageListeners: MutableList<AIMessageListener> = CopyOnWriteArrayList()
/**
* 注册一个消息监听器。
*
* @param listener 要注册的 AiMessageListener 实例。
*/
fun registerListener(listener: AIMessageListener) {
messageListeners.add(listener)
}
/**
* 取消注册一个消息监听器。
*
* @param listener 要取消注册的 AiMessageListener 实例。
*/
fun unregisterListener(listener: AIMessageListener) {
messageListeners.remove(listener)
}
/**
* 发布一条消息。
*
* 这条消息会被发送给所有已注册的监听器。
*
* @param msg 要发布的消息。
*/
fun post(msg: AIMessage) {
// 遍历所有已注册的监听器,并调用它们的 onReceive 方法
messageListeners.forEach { callback ->
callback.onReceive(msg)
}
}
fun clearData(){
messageListeners.forEach { callback ->
callback.clear()
}
}
/**
* 消息监听器接口。
*/
interface AIMessageListener {
/**
* 当接收到消息时,会调用此方法。
*
* @param msg 接收到的消息。
*/
fun onReceive(msg: AIMessage)
fun clear()
}
}

View File

@@ -0,0 +1,152 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.util.UriUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.ui.line.lineinfo.LineViewModel
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter.AIMessageAdapter
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter.OnItemClickListener
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter.PaddingItemDecoration
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.AutomaticExplorationViewModel
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.NDEViewModel
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.RoadCrossRoamViewModel
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.data.RoadV2NEventViewModel
import kotlinx.android.synthetic.main.m2_mind_view.view.rv_mind_list
import kotlinx.coroutines.launch
class MindView : ConstraintLayout, MindViewModel.AiViewCallback {
private val TAG = "MindView"
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private var roadV2NEventModel: RoadV2NEventViewModel?= null
private var roadCrossRoamModel: RoadCrossRoamViewModel?= null
private var automaticExplorationModel: AutomaticExplorationViewModel?= null
private var ndeViewModel: NDEViewModel?= null
private var viewModel:MindViewModel?=null
private var isUserScrollingTime = 0L
private val SCROLL_THRESHOLD = 2000L
private val messageAdapter: AIMessageAdapter by lazy { AIMessageAdapter() }
private val messageLayoutManager: LinearLayoutManager by lazy {
LinearLayoutManager(context).apply {
stackFromEnd = true
}
}
private fun initView() {
LayoutInflater.from(context).inflate(R.layout.m2_mind_view, this, true)
rv_mind_list.layoutManager = messageLayoutManager
rv_mind_list.adapter = messageAdapter
rv_mind_list.addItemDecoration(PaddingItemDecoration(200, 300))
messageAdapter.onItemClickListener = OnItemClickListener { item, position ->
if (item is AIMessage.Event) {
}
}
rv_mind_list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState != RecyclerView.SCROLL_STATE_IDLE) {
isUserScrollingTime = System.currentTimeMillis()
}
}
})
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(MindViewModel::class.java)
}
viewModel?.setViewCallback(this)
roadV2NEventModel = findViewTreeViewModelStoreOwner()?.let{
ViewModelProvider(it)[RoadV2NEventViewModel::class.java]
}
roadV2NEventModel?.init()
roadCrossRoamModel = findViewTreeViewModelStoreOwner()?.let{
ViewModelProvider(it)[RoadCrossRoamViewModel::class.java]
}
roadCrossRoamModel?.init(context)
automaticExplorationModel = findViewTreeViewModelStoreOwner()?.let{
ViewModelProvider(it)[AutomaticExplorationViewModel::class.java]
}
automaticExplorationModel?.init()
ndeViewModel = findViewTreeViewModelStoreOwner()?.let{
ViewModelProvider(it)[NDEViewModel::class.java]
}
ndeViewModel?.init()
findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
viewModel?.messagesFlow?.collect {
Log.d(TAG, "${tName()} onMessages update: ${it}")
if(it.isNotEmpty()){
rv_mind_list.visibility = View.VISIBLE
}else{
rv_mind_list.visibility = View.VISIBLE
}
messageAdapter.submitList(it) {
Log.d(TAG, "${tName()} adapter submit: ")
scrollToBottom()
}
}
}
}
// 滚动到RecyclerView底部
private fun scrollToBottom() {
val delay = System.currentTimeMillis() - isUserScrollingTime
if (delay < SCROLL_THRESHOLD) {
return
}
val layoutManager = rv_mind_list.layoutManager as LinearLayoutManager
layoutManager.scrollToPositionWithOffset(messageAdapter.itemCount - 1, 0)
}
fun tName(): String {
return "${Thread.currentThread().name}"
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
}
init {
try {
initView()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,174 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.mogo.eagle.core.data.ai.V2XRepository
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.common.module.biz.birdge.BridgeListener
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class MindViewModel : ViewModel(), AIMessageManager.AIMessageListener,
BridgeListener {
private val msgList = mutableListOf<AIMessage>()
private var lastTimestamp = System.currentTimeMillis()
// 记录最后一次事件发生的时间,使用 private set 限制外部修改
// private val TIMESTAMP_THRESHOLD = 1000 * 60 * 5 // 5分钟
private val TIMESTAMP_THRESHOLD = 1000 * 30
private var llmResultJob: Job? = null
private var isChecking = false
private val _messagesFlow = MutableStateFlow<List<AIMessage>>(emptyList())
val messagesFlow: SharedFlow<List<AIMessage>> get() = _messagesFlow
private val commontCallback = object : ICommonCallback{
override fun showNoTaskView(isTrue: Boolean) {
if(isTrue){
clearMsg()
}
}
}
private val locationCallback = object : IMoGoChassisLocationGCJ02Listener {
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
mogoLocation?.let {
V2XRepository.provideLocation(it, 0)
}
}
}
init {
}
fun setViewCallback(aiView: AiViewCallback) {
CommonModel.setRouteLineInfoCallback(TAG,commontCallback)
OchLocationManager.addGCJ02Listener(TAG, 1, locationCallback)
AIMessageManager.registerListener(this)
BridgeManager.addBridgeListener(TAG,this)
}
override fun onCleared() {
AIMessageManager.unregisterListener(this)
llmResultJob?.cancel()
CommonModel.setRouteLineInfoCallback(TAG,null)
OchLocationManager.removeGCJ02Listener(TAG)
super.onCleared()
}
override fun onReceive(msg: AIMessage) {
Log.d(TAG, "onReceive: $msg")
if (isChecking) {
if (msg is AIMessage.Event) {
msg.showScanFlag = true
}
}
// 获更新消息
updateMsg(msg)
}
override fun clear() {
clearMsg()
}
private fun handleMsg(newMessage: AIMessage) {
val existingIndex = findMessageIndex(newMessage.id)
if (existingIndex != -1) {
handleExistingMessage(existingIndex, newMessage)
} else {
handleNewMessage(newMessage)
}
}
private fun findMessageIndex(messageId: String): Int {
return msgList.indexOfFirst { it.id == messageId }
}
private fun handleExistingMessage(index: Int, newMessage: AIMessage) {
val oldMessage = msgList[index]
newMessage.showTimestamp = oldMessage.showTimestamp
msgList[index] = newMessage
speakMessageIfNeeded(newMessage, isLastMessage = msgList.last() == newMessage)
}
private fun handleNewMessage(newMessage: AIMessage) {
updateTimestampIfNeeded(newMessage)
msgList.add(newMessage)
speakMessageIfNeeded(newMessage, isLastMessage = true)
}
private fun updateTimestampIfNeeded(newMessage: AIMessage) {
val time = newMessage.timestamp - lastTimestamp
if (time >= TIMESTAMP_THRESHOLD) {
newMessage.showTimestamp = true
lastTimestamp = newMessage.timestamp
}
}
private fun speakMessageIfNeeded(newMessage: AIMessage, isLastMessage: Boolean) {
if (isLastMessage && newMessage.tts.isNotEmpty()) {
VoiceNotice.showNotice(newMessage.tts)
}
}
companion object {
private const val TAG = "AiViewModel"
}
private fun updateMsg(msg: AIMessage) {
synchronized(msgList) {
handleMsg(msg)
_messagesFlow.value = msgList.toList()
}
}
private fun deleteMsg(msgId: String) {
synchronized(msgList) {
val iterator = msgList.iterator()
while (iterator.hasNext()) {
if (iterator.next().id == msgId) {
iterator.remove()
}
}
_messagesFlow.value = msgList.toList()
}
}
private fun clearMsg() {
synchronized(msgList) {
msgList.clear()
_messagesFlow.value = msgList.toList()
}
}
interface AiViewCallback {
}
}

View File

@@ -0,0 +1,51 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
class AIMessageAdapter : ListAdapter<AIMessage, MessageViewHolder>(MessageDiffCallback()) {
var onItemClickListener: OnItemClickListener? = null
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
getItem(position)?.let {
holder.bind(it, onItemClickListener)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
AIMessage.TYPE_PNC_ACTION -> PNCActionViewHolder(inflater.inflate(R.layout.b2_item_ai_pnc_action,parent,false))
AIMessage.TYPE_ROAD_V2N -> RoadV2NEventViewHolder(inflater.inflate(R.layout.b2_item_ai_road_v2n_event,parent,false))
AIMessage.TYPE_ROAD_CROSS -> RoadCrossRoamViewHolder(inflater.inflate(R.layout.b2_item_ai_road_cross_roam,parent,false))// 全息路口
AIMessage.TYPE_AUTOMATIC_EXPLORATION -> AutomaticExplorationViewHolder(inflater.inflate(R.layout.b2_item_ai_automatic_exploration,parent,false))// 探查
AIMessage.TYPE_NDE -> NDEViewHolder(inflater.inflate(R.layout.b2_item_ai_nde_event,parent,false))// 车龙
else -> throw IllegalArgumentException("Invalid view type")
}
}
override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is AIMessage.Event -> AIMessage.TYPE_EVENT
is AIMessage.Scan -> AIMessage.TYPE_SCAN
is AIMessage.Light -> AIMessage.TYPE_LIGHT
is AIMessage.Speed -> AIMessage.TYPE_SPEED
is AIMessage.Warning -> AIMessage.TYPE_WARNING
is AIMessage.PNCAction -> AIMessage.TYPE_PNC_ACTION
is AIMessage.RoadV2NEvent -> AIMessage.TYPE_ROAD_V2N
is AIMessage.RoadCrossRoam -> AIMessage.TYPE_ROAD_CROSS
is AIMessage.AutomaticExploration -> AIMessage.TYPE_AUTOMATIC_EXPLORATION
is AIMessage.NDEData -> AIMessage.TYPE_NDE
else -> AIMessage.TYPE_EVENT
}
}
override fun onViewRecycled(holder: MessageViewHolder) {
super.onViewRecycled(holder)
holder.viewRecycled(holder)
}
}

View File

@@ -0,0 +1,224 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Rect
import android.util.Log
import android.view.View
import android.view.animation.LinearInterpolator
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.mogo.eagle.core.data.notice.AutoExplorationEntity
import com.mogo.eagle.core.data.v2x.RoadV2NEventType
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
import com.mogo.eagle.core.function.hmi.ui.notice.exploration.AutomaticExplorationAdapter
import com.mogo.eagle.core.function.hmi.ui.v2n.RoadV2NEventLivePlayView
import com.mogo.eagle.core.function.view.MapRoamView
import com.mogo.eagle.core.function.view.RoadCrossRoamListAdapter
import com.mogo.eagle.core.utilcode.mogo.glide.GlideImageLoader
import com.mogo.eagle.core.utilcode.mogo.imageloader.MogoImageView
import com.mogo.eagle.core.utilcode.util.DateTimeUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
abstract class MessageViewHolder(view: View) : RecyclerView.ViewHolder(view) {
abstract fun bind(item: AIMessage, onItemClickListener: OnItemClickListener? = null)
open fun viewRecycled(holder: MessageViewHolder){}
private val sampleDateFormat = SimpleDateFormat("HH:mm", Locale.CHINA)
protected val TAG = javaClass.simpleName
fun handleTimestamp(item: AIMessage, tvTimestamp: TextView) {
if (item.showTimestamp) {
tvTimestamp.visibility = View.VISIBLE
tvTimestamp.text = sampleDateFormat.format(Date(item.timestamp))
} else {
tvTimestamp.visibility = View.GONE
}
}
fun View.setVisibilityBasedOn(condition: Boolean) {
visibility = if (condition) View.VISIBLE else View.GONE
}
fun TextView.setTextAndVisibility(text: String) {
if (text.isEmpty()) {
visibility = View.GONE
this.text = ""
} else {
visibility = View.VISIBLE
this.text = text
}
}
fun ImageView.showOrHideWithUrl(url: String) {
if (url.isEmpty()) {
visibility = View.GONE
} else {
visibility = View.VISIBLE
Glide.with(this)
.load(url)
.placeholder(R.drawable.icon_pic_holder)
.error(R.drawable.icon_pic_error)
// .error(R.drawable.icon_marker_window_place_holder)
// .placeholder(R.drawable.icon_marker_window_place_holder)
.into(this)
}
}
}
class PNCActionViewHolder(binding: View) : MessageViewHolder(binding){
private var tvPncActionDesc: TextView = binding.findViewById(R.id.tvPNCHintContent)
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
if(item is AIMessage.PNCAction){
tvPncActionDesc.text = item.actionDesc
}
}
}
class RoadV2NEventViewHolder(binding: View) : MessageViewHolder(binding){
private var tvV2XHintContent: TextView = binding.findViewById(R.id.tvV2XHintContent)
private var containerImageAndLiveVideo: FrameLayout = binding.findViewById(R.id.containerImageAndLiveVideo)
private var livePlayView: RoadV2NEventLivePlayView = binding.findViewById(R.id.livePlayView)
private var contentImageView: MogoImageView = binding.findViewById(R.id.contentImageView)
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
if(item is AIMessage.RoadV2NEvent){
tvV2XHintContent.text = item.title
when (item.eventType) {
RoadV2NEventType.TEXT -> {
containerImageAndLiveVideo.visibility = View.GONE
contentImageView.visibility = View.GONE
livePlayView.visibility = View.GONE
}
RoadV2NEventType.IMAGE -> {
containerImageAndLiveVideo.visibility = View.VISIBLE
contentImageView.visibility = View.VISIBLE
livePlayView.visibility = View.GONE
GlideImageLoader.getInstance()
.displayImage(item.contentImageUrl, contentImageView)
}
RoadV2NEventType.LIVE_VIDEO -> {
containerImageAndLiveVideo.visibility = View.VISIBLE
contentImageView.visibility = View.GONE
livePlayView.visibility = View.VISIBLE
val cityCode =
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84().cityCode
livePlayView.startRoadCameraLive(
item.id,
item.cameraIp, item.lon, item.lat, cityCode
)
}
}
}
}
}
class RoadCrossRoamViewHolder(binding: View) : MessageViewHolder(binding){
private var tvRoadRoamTitle: TextView = binding.findViewById(R.id.tvRoadRoamTitle)
private var lvRoadCrossRoamTip: RecyclerView = binding.findViewById(R.id.lvRoadCrossRoamTip)
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
if(item is AIMessage.RoadCrossRoam){
lvRoadCrossRoamTip.layoutManager = NoScrollLayoutManager(itemView.context)
lvRoadCrossRoamTip.adapter = RoadCrossRoamListB2Adapter(itemView.context)
tvRoadRoamTitle.setTextColor(itemView.context.getColor(R.color.color_131415))
}
}
}
class AutomaticExplorationViewHolder(binding: View) : MessageViewHolder(binding){
private var rvExplorationList: RecyclerView = binding.findViewById(R.id.rvExplorationList)
private lateinit var automaticExplorationAdapter: AutomaticExplorationB2Adapter
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
val linearLayoutManager = LinearLayoutManager(itemView.context)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
automaticExplorationAdapter = AutomaticExplorationB2Adapter(itemView.context)
rvExplorationList.adapter = automaticExplorationAdapter
rvExplorationList.layoutManager = linearLayoutManager
initData()
}
private fun initData() {
val dataList = ArrayList<AutoExplorationEntity>(7)
dataList.add(AutoExplorationEntity("当前道路事件分析",2000L,false))
dataList.add(AutoExplorationEntity("前方车辆",2000L,false))
dataList.add(AutoExplorationEntity("两侧车辆",2600L,false))
dataList.add(AutoExplorationEntity("后方车辆",3000L,false))
dataList.add(AutoExplorationEntity("前方路口车辆流速分析",4000L,false))
dataList.add(AutoExplorationEntity("前方路口行人/非机动车分析",4300L,false))
dataList.add(AutoExplorationEntity("路侧视频分析",5000L,false))
automaticExplorationAdapter.setListener(object: AutomaticExplorationB2Adapter.CompleteListener{
override fun onComplete(entity: AutoExplorationEntity) {
dataList.forEach {
if(it.explorationContent == entity.explorationContent){
it.explorationComplete = true
}
}
}
})
automaticExplorationAdapter.setData(dataList)
}
}
class NDEViewHolder(binding: View) : MessageViewHolder(binding){
private var tvNdeContent: TextView = binding.findViewById(R.id.tvNdeHintContent)
private var rvNdeList: RecyclerView = binding.findViewById(R.id.rvNdeList)
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
if(item is AIMessage.NDEData){
tvNdeContent.text = item.desc
val linearLayoutManager = LinearLayoutManager(itemView.context)
linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
val ndeRoadAdapter = AINDERoadAdapter(itemView.context)
rvNdeList.adapter = ndeRoadAdapter
rvNdeList.layoutManager = linearLayoutManager
ndeRoadAdapter.setData(item.roadList)
}
}
}
private class NoScrollLayoutManager(context: Context?) : LinearLayoutManager(context) {
override fun canScrollVertically(): Boolean {
return false
}
override fun canScrollHorizontally(): Boolean {
return false
}
}
fun interface OnItemClickListener {
fun onItemClick(item: AIMessage, position: Int)
}

View File

@@ -0,0 +1,237 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import android.content.Context
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.shuttle.weaknet.passenger.R
class AINDERoadAdapter(private val context: Context): RecyclerView.Adapter<AINDERoadAdapter.AIRoadHolder>() {
private var roadList: List<RoadMsg>?= null
fun setData(list: List<RoadMsg>){
roadList = list
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AIRoadHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.b2_item_ai_nde_road, parent, false)
return AIRoadHolder(view)
}
override fun onBindViewHolder(holder: AIRoadHolder, position: Int) {
roadList?.let{
val roadMsg = it[position]
if(it.size < 3){
//设置item宽度为最大宽度180dp
val params = ConstraintLayout.LayoutParams(
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90f,
context.resources.displayMetrics).toInt(),
ConstraintLayout.LayoutParams.WRAP_CONTENT)
holder.clRoadLayout.layoutParams = params
}else if(it.size == 3){
//设置item宽度为最大宽度180dp
val params = ConstraintLayout.LayoutParams(
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60f,
context.resources.displayMetrics).toInt(),
ConstraintLayout.LayoutParams.WRAP_CONTENT)
holder.clRoadLayout.layoutParams = params
}else if(it.size == 4){
//设置item宽度为最大宽度180dp
val params = ConstraintLayout.LayoutParams(
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50f,
context.resources.displayMetrics).toInt(),
ConstraintLayout.LayoutParams.WRAP_CONTENT)
holder.clRoadLayout.layoutParams = params
}else{
val params = ConstraintLayout.LayoutParams(
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45f,
context.resources.displayMetrics).toInt(),
ConstraintLayout.LayoutParams.WRAP_CONTENT)
holder.clRoadLayout.layoutParams = params
}
when(roadMsg.arrowType){
//直行
201->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_forward
))
}
//直行或左转
202->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_forward_or_turn_left
))
}
//直行或右转
203->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_forward_or_turn_right
))
}
//直行或掉头
204->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_forward_or_reverse
))
}
//左转
205->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_left
))
}
//左转或掉头
206->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_left_or_reverse
))
}
//左弯或向左合流
207->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_or_merge_left
))
}
//右转
208->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_right
))
}
//右转或向右合流
209->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_or_merge_right
))
}
//左右转弯
210->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_left_or_right
))
}
//掉头
211->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_reverse
))
}
//禁止左转
212->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_prohibit_turn_left
))
}
//禁止右转
213->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_prohibit_turn_right
))
}
//禁止掉头
214->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_prohibit_reverse
))
}
//直行或左转或右转
215->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_forward_turn_left_right
))
}
//直行或掉头或左转
216->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_forward_turn_left_reverse
))
}
//右转或掉头
217->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_turn_right_or_reverse
))
}
//禁止右转或向右合流
218->{
holder.ivRoadType.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_road_prohibit_turn_or_merge_right
))
}
}
//是否是推荐车道
if(roadMsg.isRecommend){
holder.tvRoadStatus.text = context.getString(R.string.nde_road_recommend)
holder.tvRoadStatus.setTextColor(context.getColor(R.color.msg_nde_road_recommend))
holder.clRoadLayout.background = ContextCompat.getDrawable(
context,
R.drawable.bg_nde_road_recommend
)
}
//是否有车龙,代表拥堵、行驶缓慢
if(roadMsg.isCheLong){
holder.tvRoadStatus.text = context.getString(R.string.nde_road_slow)
holder.tvRoadStatus.setTextColor(context.getColor(R.color.msg_nde_road_slow))
}
if(position == it.lastIndex){
holder.viewDivider.visibility = View.INVISIBLE
}
}
}
override fun getItemCount() = roadList?.size ?: 0
class AIRoadHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
var clRoadLayout: ConstraintLayout = itemView.findViewById(R.id.clRoadLayout)
var ivRoadType: ImageView = itemView.findViewById(R.id.ivRoadType)
var tvRoadStatus: TextView = itemView.findViewById(R.id.tvRoadStatus)
var viewDivider: View = itemView.findViewById(R.id.viewDivider)
}
}

View File

@@ -0,0 +1,83 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.mogo.eagle.core.data.notice.AutoExplorationEntity
import com.mogo.och.shuttle.weaknet.passenger.R
/**
* 自动探查适配器
* 鹰眼650需求
*/
class AutomaticExplorationB2Adapter(val context: Context): RecyclerView.Adapter<AutomaticExplorationB2Adapter.ExplorationHolder>() {
private var data: List<AutoExplorationEntity> ?= null
private var completeListener: CompleteListener ?= null
fun setData(data: List<AutoExplorationEntity>){
this.data = data
notifyDataSetChanged()
}
fun setListener(listener: CompleteListener){
completeListener = listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExplorationHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_auto_exploration_b2, parent, false)
return ExplorationHolder(view)
}
override fun getItemCount() = data?.size ?: 0
override fun onBindViewHolder(holder: ExplorationHolder, position: Int) {
data?.let {
val entity = it[position]
holder.tvExplorationContent.text = entity.explorationContent
holder.ivExplorationLoading.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_exploration_loading_p
))
val rotationAnim = ObjectAnimator.ofFloat(holder.ivExplorationLoading, "rotation", 0f, 360f)
rotationAnim.repeatCount = entity.explorationDuration.toInt()/1000
rotationAnim.repeatMode = ValueAnimator.RESTART
rotationAnim.duration = 1000
rotationAnim.interpolator = LinearInterpolator()
rotationAnim.addListener(object: AnimatorListenerAdapter(){
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
completeListener?.onComplete(entity)
holder.ivExplorationLoading.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_exploration_done_p
))
}
})
rotationAnim.start()
}
}
class ExplorationHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
var ivExplorationLoading: ImageView = itemView.findViewById(R.id.ivExplorationLoading)
var tvExplorationContent: TextView = itemView.findViewById(R.id.tvExplorationContent)
}
interface CompleteListener{
fun onComplete(entity: AutoExplorationEntity)
}
}

View File

@@ -0,0 +1,15 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import androidx.recyclerview.widget.DiffUtil
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
class MessageDiffCallback: DiffUtil.ItemCallback<AIMessage>() {
override fun areContentsTheSame(oldItem: AIMessage, newItem: AIMessage): Boolean {
return oldItem == newItem
}
override fun areItemsTheSame(oldItem: AIMessage, newItem: AIMessage): Boolean {
return oldItem.id == newItem.id
}
}

View File

@@ -0,0 +1,94 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.mogo.commons.AbsMogoApplication
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import me.jessyan.autosize.utils.AutoSizeUtils
class PaddingItemDecoration(private val topPadding: Int, private val bottomPadding: Int) : RecyclerView.ItemDecoration() {
private var divider: Drawable
private var padding = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),13f)
init {
val shapeDrawable = GradientDrawable()
shapeDrawable.setColor(ResourcesUtils.getColor(R.color.b2_BBC9D4))
shapeDrawable.shape = GradientDrawable.RECTANGLE
val width = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),343f)
val height = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),1f)
shapeDrawable.setSize(width, height)
divider = shapeDrawable
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
// 只有第一个 item 的顶部添加空白
if (parent.getChildAdapterPosition(view) == 0) {
outRect.top = topPadding
} else{
outRect.top = 0
}
// 最后一个 item 的底部添加空白
// if (parent.getChildAdapterPosition(view) == state.itemCount - 1) {
// outRect.bottom = bottomPadding
// } else{
// outRect.bottom = 0
// }
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
val childCount = parent.childCount //获取可见item的数量
val spanCount: Int = getSpanCount(parent)
for (i in 0 until childCount) {
val child = parent.getChildAt(i)
val params = child
.layoutParams as RecyclerView.LayoutParams
val left = child.left - params.leftMargin + padding
val right = child.right - padding //- params.rightMargin - divider.intrinsicWidth
val top = child.bottom + params.bottomMargin
val bottom = top + divider.intrinsicHeight
divider.setBounds(left, top, right, bottom)
divider.draw(c)
if (i < spanCount) { //画第一行顶部的分割线
drawHorizontalForFirstRow(c, child)
}
}
}
private fun drawHorizontalForFirstRow(c: Canvas, child: View) {
val params = child
.layoutParams as RecyclerView.LayoutParams
val left = child.left - params.leftMargin - divider.intrinsicWidth
val top = child.top - params.topMargin - divider.intrinsicHeight
val right = child.right + params.rightMargin + divider.intrinsicWidth
val bottom = top + divider.intrinsicHeight
divider.setBounds(left, top, right, bottom)
divider.draw(c)
}
private fun getSpanCount(parent: RecyclerView): Int {
// 列数
var spanCount = -1
val layoutManager = parent.layoutManager
if (layoutManager is GridLayoutManager) {
spanCount = layoutManager.spanCount
} else if (layoutManager is StaggeredGridLayoutManager) {
spanCount = layoutManager
.spanCount
}
return spanCount
}
}

View File

@@ -0,0 +1,65 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlin.random.Random
class RoadCrossRoamListB2Adapter(private val mContext: Context) : RecyclerView.Adapter<RoadCrossRoamListB2Adapter.ViewHolder>() {
private val items: MutableList<String> = mutableListOf()
init {
items.add("前方路况拥堵分析")
items.add("路口危险车辆分析")
items.add("路口交通事故分析")
items.add("路口行人碰撞分析")
items.add("路口非机动车分析")
items.add("路口灯态分析")
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view: View =
LayoutInflater.from(mContext).inflate(R.layout.item_road_cross_ai_roam_tip_b2, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return 6
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
holder.textView.setTextColor(mContext.getColor(R.color.color_191A1C))
holder.textView.text = item
// 随机决定是否显示ProgressBar
// if (Random.nextBoolean()) { // 50%的几率显示ProgressBar
holder.progressBar.visibility = View.VISIBLE
holder.checkIcon.visibility = View.INVISIBLE
val r0 = Random.nextInt(0,3)
val r1 = Random.nextInt(1,9)
// 模拟加载完成
holder.itemView.postDelayed({
holder.progressBar.visibility = View.INVISIBLE
holder.checkIcon.visibility = View.VISIBLE
},r0 * 1000L + r1 * 100L)
// } else {
// holder.progressBar.visibility = View.GONE
// holder.checkIcon.visibility = View.VISIBLE
// }
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textView: TextView = itemView.findViewById(R.id.tvRoadItemTip)
var progressBar: ProgressBar = itemView.findViewById(R.id.pbRoadItemTip)
var checkIcon: ImageView = itemView.findViewById(R.id.ivRoadItemTip)
}
}

View File

@@ -0,0 +1,180 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean
import android.os.CountDownTimer
import android.util.Log
import com.mogo.eagle.core.data.v2x.RoadV2NEventType
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.common.module.biz.birdge.data.VlmData
import kotlin.math.floor
sealed class AIMessage(
open val id: String,
open val title: String,
open val tts: String = "",
val timestamp: Long = System.currentTimeMillis(),
var showTimestamp: Boolean = false
) {
companion object {
const val TYPE_SCAN = 0
const val TYPE_EVENT = 1
const val TYPE_LIGHT = 3
const val TYPE_SPEED = 4
const val TYPE_WARNING = 5
const val TYPE_PNC_ACTION = 6
const val TYPE_ROAD_V2N = 7
const val TYPE_ROAD_CROSS = 8
const val TYPE_AUTOMATIC_EXPLORATION = 9
const val TYPE_NDE = 11
}
data class Scan(
override val id: String,
override val title: String,
val pictureUrl: String = "",
var showScanFlag: Boolean = false
) : AIMessage(id, title)
data class Event(
override val id: String,
override val title: String,
override val tts: String = "",
val position: String = "",
val distance: String = "",
val range: String = "",
val time: String = "",
val pictureUrl: String = "",
val videoUrl: String = "",
var showScanFlag: Boolean = false
) : AIMessage(id, title, tts)
data class QA(
override val id: String,
override val title: String,
override val tts: String = "",
val question: String,
val answer: String,
var state: QuestionState = QuestionState.UNDERSTAND,
val pictureUrl: String = "",
var pictureUrlList: List<String> = listOf(),
val videoUrl: String = "",
) : AIMessage(id, title, tts) {
enum class QuestionState(val code: Int) {
UNDERSTAND(1),
ANALYZE(2),
ANSWER(3),
FINISH(4),
ERROR(-1),
}
}
data class Light(
override val id: String,
override val title: String,
override val tts: String = "",
var seconds: Int,
val status: Int
) : AIMessage(id, title, tts) {
private var countDownTimer: CountDownTimer? = null
private var listener: OnCountdownUpdateListener? = null
fun startCountdown(millisInFuture: Long, countDownInternal: Long) {
countDownTimer?.cancel()
countDownTimer = object : CountDownTimer(millisInFuture, countDownInternal) {
override fun onTick(millisUntilFinished: Long) {
//倒计时开始
Log.d(
"StartOrSlowDownTip",
"millisUntilFinished = $millisUntilFinished, countDownInternal = $countDownInternal"
)
val cd = millisUntilFinished / 1000.0
// val split = String.format("%.2f", cd).split(".")
seconds = floor(cd).toInt()
listener?.onCountdownUpdate()
}
override fun onFinish() {
//倒计时完成
seconds = 0
listener?.onCountdownFinish()
}
}
countDownTimer?.start()
}
fun stopCountdown() {
countDownTimer?.cancel()
}
fun setOnCountdownUpdateListener(listener: OnCountdownUpdateListener) {
this.listener = listener
}
interface OnCountdownUpdateListener {
fun onCountdownUpdate()
fun onCountdownFinish()
}
}
data class Speed(
override val id: String,
override val title: String,
override val tts: String = "",
val speedMax: Int,
val speedMin: Int,
) : AIMessage(id, title, tts)
data class Warning(
override val id: String,
override val title: String,
override val tts: String = "",
) : AIMessage(id, title, tts)
data class PNCAction(
override val id: String,
override val title: String,
var actionDesc: String,
var timeStamp: Long = 0, //事件发生事件戳
): AIMessage(id,title)
data class RoadV2NEvent(
override val id: String,
override val title: String,
override val tts: String = "", //TTS的文案
var eventType: RoadV2NEventType, //事件弹框类型
var timeStamp: Long = 0, //事件发生事件戳
var iconResId: Int, //事件icon res id
var isNeedTTS: Boolean = false, //事件文案是否需要同步tts
var contentImageUrl: String, // Image 类型时图片 url
var cameraIp: String, // 路侧camera ip,用于请求获取拉流地址
var lon: Double, //事件坐标-经度
var lat: Double, //事件坐标-纬度
): AIMessage(id,title,tts)
data class RoadCrossRoam(
override val id: String,
override val title: String
): AIMessage(id,title)
data class AutomaticExploration(
override val id: String,
override val title: String
): AIMessage(id,title)
data class EvaluateData(
override val id: String,
override val title: String,
var isFirst:Boolean = true
): AIMessage(id,title)
data class NDEData(
override val id: String,
override val title: String,
var desc: String,
var roadList: List<RoadMsg>
): AIMessage(id,title)
}

View File

@@ -0,0 +1,3 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean
data class ListenUIState(val show: Boolean, val text: String, val showTips: Boolean = false)

View File

@@ -0,0 +1,118 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
import android.os.CountDownTimer
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.MsgCategory
import com.mogo.eagle.core.function.api.datacenter.msgbox.IMsgBoxListener
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxListenerManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
/**
* 自动探查
*/
class AutomaticExplorationViewModel: ViewModel(), IMsgBoxListener, ICommonCallback {
companion object{
private const val TAG = "AutomaticExplorationViewModel"
private const val EXPLORATION_SHOW_TIME = 300000L //距离用户在触发上一次事件播报的时间5分钟后自动触发常规道路情况检测
}
private var showViewTimer: CountDownTimer?= null //展示自动探查倒计时
private var isCountingDown: Boolean = false //是否处于倒计时中
private var hasOrder: Boolean = false // 车当前是否有订单
fun init(){
CommonModel.setRouteLineInfoCallback(TAG,this)
CallerMsgBoxListenerManager.addListener(TAG,this)
}
override fun onCleared() {
super.onCleared()
CommonModel.setRouteLineInfoCallback(TAG,null)
CallerMsgBoxListenerManager.removeListener(TAG)
}
override fun showNoTaskView(isTrue: Boolean) {
super.showNoTaskView(isTrue)
if(isTrue){
cancelTimer()
currentOrderStatus(false)
}else{
startShowTimer()
currentOrderStatus(true)
}
}
override fun onDataChanged(category: MsgCategory, msgBoxList: MsgBoxBean) {
if(category == MsgCategory.NOTICE){
if(msgBoxList.type == MsgBoxType.V2X){
//重置倒计时时长
cancelTimer()
if(hasOrder){
startShowTimer()
}
}
}
}
/**
* 取消倒计时
*/
private fun cancelTimer(){
CallerLogger.d(TAG,"cancelTimer")
showViewTimer?.cancel()
showViewTimer = null
isCountingDown = false
}
/**
* 开始倒计时
*/
private fun startShowTimer(){
CallerLogger.d(TAG,"startShowTimer")
if(!isCountingDown){
ThreadUtils.runOnUiThread {
if(showViewTimer == null){
showViewTimer = object: CountDownTimer(EXPLORATION_SHOW_TIME,EXPLORATION_SHOW_TIME){
override fun onTick(millisUntilFinished: Long) {
CallerLogger.d(TAG,"倒计时+:${millisUntilFinished}")
}
override fun onFinish() {
if(hasOrder){
showAutoExploration()
}
isCountingDown = false
}
}
}
isCountingDown = true
showViewTimer?.start()
}
}
}
/**
* 设置当前订单状态
* @param orderStatus true有订单false没有订单
*/
private fun currentOrderStatus(orderStatus: Boolean){
hasOrder = orderStatus
}
private fun showAutoExploration(){
val automaticExploration = AIMessage.AutomaticExploration(System.currentTimeMillis().toString(),"")
AIMessageManager.post(automaticExploration)
}
}

View File

@@ -0,0 +1,35 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.och.common.module.biz.birdge.BridgeListener
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.biz.birdge.data.RoadMsg
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
/**
* 车龙信息
*/
class NDEViewModel: ViewModel(), BridgeListener {
companion object{
private const val TAG = "NDEViewModel"
}
fun init(){
BridgeManager.addBridgeListener(TAG,this)
}
override fun onCleared() {
super.onCleared()
BridgeManager.removeBridgeListener(TAG)
}
override fun onNdeDataListener(title: String, desc: String, sortedList: List<RoadMsg>) {
val ndeEvent = AIMessage.NDEData(System.currentTimeMillis().toString(),title,desc,sortedList)
AIMessageManager.post(ndeEvent)
}
}

View File

@@ -0,0 +1,259 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.data.autopilot.pnc.PncActionsHelper
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningActionsListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningActionsListenerManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import mogo.telematics.pad.MessagePad
class PNCActionsViewModel: ViewModel(), IMoGoAutopilotPlanningActionsListener, ICommonCallback {
companion object{
private const val TAG = "PNCActionsViewModel"
}
private var currentAction = ""
private var currentStation:BusStationBean?=null
fun init(){
CallerPlanningActionsListenerManager.addListener(TAG, this)
CommonModel.setRouteLineInfoCallback(TAG,this)
}
override fun onCleared() {
super.onCleared()
CallerPlanningActionsListenerManager.removeListener(TAG)
CommonModel.setRouteLineInfoCallback(TAG,null)
}
override fun updateStationsInfo(
stations: MutableList<BusStationBean>?,
currentStationIndex: Int,
isArrived: Boolean
) {
try {
currentStation = stations?.get(currentStationIndex)
}catch (e:Exception){
OchChainLogManager.writeChainLogError("PNCActionsViewModel 设置错误","${e.message}")
}
}
override fun showNoTaskView(isTrue: Boolean) {
super.showNoTaskView(isTrue)
if(isTrue){
currentStation = null
}
}
override fun pncActions(planningActionMsg: MessagePad.PlanningActionMsg) {
try {
BizLoopManager.runInMainThread {
if (CallerAutoPilotStatusListenerManager.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
var actions: String? = null
planningActionMsg.actionMsg?.let {
try {
actions = PncActionsHelper.getAction(
it.drivingState.number,
it.drivingAction.number
)
} catch (e: Exception) {
e.printStackTrace()
}
}
planningActionMsg.v2NActionMsgList?.forEach { v2nAction ->
actions = PncActionsHelper.getAction(
v2nAction.drivingState.number,
v2nAction.drivingAction.number
)
}
// update view
actions?.let {
if(it.isNotEmpty() && it != currentAction){
currentAction = it
val title = getActionTitle(it)
if(title.isNotEmpty()){
val desc = getActionDesc(title)
val action = AIMessage.PNCAction(it+System.currentTimeMillis(),title,desc,System.currentTimeMillis())
AIMessageManager.post(action)
}
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun getActionTitle(pncAction: String): String{
return when(pncAction){
"正在进站"->{
"车辆进站"
}
"等待进站"->{
"车辆等待进站"
}
"正在出站"->{
"车辆出站"
}
"等待出站"->{
"车辆等待出站"
}
"正在向左变道"->{
"车辆向左变道"
}
"正在向右变道"->{
"车辆向右变道"
}
"正在完成变道"->{
"车辆完成变道"
}
"正在绕过障碍物"->{
"车辆正在绕过前方障碍物"
}
"正在向左绕行避让前方静止障碍物"->{
"车辆正在绕过前方障碍物"
}
"正在向右绕行避让前方静止障碍物"->{
"车辆正在绕过前方障碍物"
}
"正在避让障碍物"->{
"车辆正在避让前方障碍物"
}
"正在向左变道避让前方静止障碍物"->{
"车辆正在避让前方障碍物"
}
"正在向右变道避让前方静止障碍物"->{
"车辆正在避让前方障碍物"
}
"正在等红灯"->{
"路口等红灯"
}
"正在向左变道避让前方道路施工"->{
"车辆正在变道避让前方道路施工"
}
"正在向右变道避让前方道路施工"->{
"车辆正在变道避让前方道路施工"
}
"正在向左绕行避让前方道路施工"->{
"车辆正在绕行避让前方道路施工"
}
"正在向右绕行避让前方道路施工"->{
"车辆正在绕行避让前方道路施工"
}
"正在向左变道避让前方道路事故"->{
"车辆正在变道避让前方道路事故"
}
"正在向右变道避让前方道路事故"->{
"车辆正在变道避让前方道路事故"
}
"正在向左绕行避让前方道路事故"->{
"车辆正在绕行避让前方道路事故"
}
"正在向右绕行避让前方道路事故"->{
"车辆正在绕行避让前方道路事故"
}
"正在跟随车辆行驶"->{
"车辆正在跟车通行"
}
"正在跟车行驶"->{
"车辆正在跟车通行"
}
"正在向左变道避让前方车龙"->{
"车辆正在绕行前方车龙"
}
"正在向右变道避让前方车龙"->{
"车辆正在绕行前方车龙"
}
"正在使用云端规划通过路口"->{
"车辆正在使用云端轨迹通行"
}
"正在避让后方来车"->{
"车辆正在避让后方来车"
}
else->{
""
}
}
}
private fun getActionDesc(action: String): String{
return when(action){
"车辆进站"->{
"前方即将到达${CommonModel.routesResult}" +
"车辆正在规划减速并进站停靠,请安心等待车辆停稳再下车哦~"
}
"车辆等待进站"->{
"车辆待环境安全后进站,耐心等几秒,安全比赶路更重要~"
}
"车辆出站"->{
"欢迎乘坐MOGO RoboTaxi车辆正在规划出站坐稳扶好哦我们出发啦小智持续守护您的行程。"
}
"车辆等待出站"->{
"车辆待环境安全后出站,耐心等几秒,安全比赶路更重要~"
}
"车辆向左变道"->{
"确认环境安全,车辆正在规划平稳向左变道,同时持续监测周边交通参与者动向,放心交给我们吧!"
}
"车辆向右变道"->{
"确认环境安全,车辆正在规划平稳向右变道,同时持续监测周边交通参与者动向,放心交给我们吧!"
}
"车辆完成变道"->{
"变道完成啦,继续前进!小智持续守护您的行程。"
}
"车辆正在绕过前方障碍物"->{
"发现前方障碍物,车辆正在规划平稳变道,即将画出一条完美弧线~"
}
"车辆正在避让前方障碍物"->{
"发现前方障碍物,车辆正在规划平稳避让,诠释优雅与丝滑~"
}
"车辆完成绕障"->{
"绕障完成啦,继续前进!小智持续守护您的行程。"
}
"路口等红灯"->{
"车辆正在路口等红灯,可以安心放空望望窗外~小智一直在您身边哦!"
}
"车辆正在变道避让前方道路施工"->{
"车辆正在提前规划变道避让前方道路施工,稳稳的很安心~您已体验到车路云一体化协同应用场景,是当之无愧的先锋体验官!"
}
"车辆正在绕行避让前方道路施工"->{
"车辆正在提前规划绕行避让前方道路施工,稳稳的很安心~您已体验到车路云一体化协同应用场景,是当之无愧的先锋体验官!"
}
"车辆正在变道避让前方道路事故"->{
"车辆正在提前规划变道避让前方道路事故,放心看我表现吧!您已体验到车路云一体化协同应用场景,小智为您欢呼!"
}
"车辆正在绕行避让前方道路事故"->{
"车辆正在提前规划绕行避让前方道路事故,放心看我表现吧!您已体验到车路云一体化协同应用场景,小智为您欢呼!"
}
"车辆正在跟车通行"->{
"车辆正在跟随前车通行舒适度MAX您已体验到车路云一体化协同应用场景超越全国99%的乘客!"
}
"车辆正在绕行前方车龙"->{
"车辆正在提前规划变道避让路口车龙舒适度MAX。您已体验到车路云一体化协同应用场景超越全国99%的乘客!"
}
"车辆正在使用云端轨迹通行"->{
"前方智慧路口内有障碍物车辆正在使用云端规划轨迹通行。您已体验到车路云一体化协同应用场景超越全国99%的乘客!"
}
"车辆正在避让后方来车"->{
"车辆正在避让后方来车,耐心等几秒,安全比赶路更重要~"
}
else->{
""
}
}
}
}

View File

@@ -0,0 +1,65 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
import android.content.Context
import androidx.lifecycle.ViewModel
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.function.api.map.road.IMoGoMapRoadListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerServicesEventManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapIdentifyManager
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
class RoadCrossRoamViewModel: ViewModel(), IMoGoMapRoadListener {
companion object{
const val TAG = "RoadCrossRoamViewModel"
}
private lateinit var mContext: Context
fun init(context: Context){
CallerMapRoadListenerManager.addListener(TAG, this)
mContext = context
}
override fun onCrossDevice(trigger: Boolean) {
super.onCrossDevice(trigger)
if(trigger){
show()
}
}
private fun show(){
// 没有路线不做提示
if (CallerAutoPilotStatusListenerManager.getLineId() == 0L) {
CallerLogger.d(TAG, "没有路线不做提示")
return
}
// 首页被遮挡不做提示
if (!CallerHmiViewControlListenerManager.getMainPageVisible()) {
CallerLogger.d(TAG, "attachView return , mainPageVisible is false")
return
}
// 没有路侧设备,不做处理
CallerLogger.d(TAG, "命中attachView")
val cross = CallerMapRoadListenerManager.getCrossEndInfo()
if (cross.isNullOrEmpty()) {
CallerLogger.d(TAG, "未触发路口ID:$cross")
return
}
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
val disStr = "为您提供路口全息影像,助力出行"
AIAssist.getInstance(mContext).speakTTSVoiceWithLevel(disStr, AIAssist.NEW_LEVEL_2)
}
CallerServicesEventManager.updateServicesNum(CallerServicesEventManager.ServiceType.ROAD)
AIMessageManager.post(AIMessage.RoadCrossRoam(System.currentTimeMillis().toString(),""))
}
}

View File

@@ -0,0 +1,74 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.mind.data
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import com.mogo.commons.utils.MogoAnalyticUtils
import com.mogo.eagle.core.data.v2x.RoadV2NEventWindowBean
import com.mogo.eagle.core.function.api.hmi.v2n.IRoadV2NEventWindowListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager
import com.mogo.eagle.core.function.hmi.ui.utils.HmiActionLog
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.AIMessageManager
import com.mogo.och.shuttle.weaknet.passenger.ui.mind.bean.AIMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class RoadV2NEventViewModel: ViewModel(), IRoadV2NEventWindowListener {
companion object{
const val TAG = "RoadV2NEventViewModel"
const val ANALYTICS_KEY = "hmi_road_event_window_view"
fun trackEvent(msg: String) {
ProcessLifecycleOwner.get().lifecycleScope.launch(Dispatchers.IO) {
val map: MutableMap<String, Any> = HashMap()
map["msg"] = msg
MogoAnalyticUtils.track(
ANALYTICS_KEY,
map
)
HmiActionLog.hmiAction(TAG, msg)
}
CallerLogger.i(TAG, msg)
}
}
fun init(){
CallerRoadV2NEventWindowListenerManager.addListener(TAG, this)
}
override fun show(dataBean: RoadV2NEventWindowBean) {
trackEvent("show --> $dataBean")
val canShowV2NEventWindowView = CallerHmiViewControlListenerManager.getMainPageVisible()
if (!canShowV2NEventWindowView) {
trackEvent("show --> 当前不在高精地图页面,跳过")
return
}
val lineId = CallerAutoPilotStatusListenerManager.getLineId()
if (lineId <= 0) {
trackEvent("show --> 当前无订单,跳过")
return
}
val event = AIMessage.RoadV2NEvent(
dataBean.eventId,
dataBean.hintStr,
"",
dataBean.eventType,
dataBean.timestamp,
dataBean.iconResId,
false,
dataBean.contentImageUrl,
dataBean.cameraIp,
dataBean.lon,
dataBean.lat
)
AIMessageManager.post(event)
}
override fun dismiss(eventId: String) {
}
}

View File

@@ -1,30 +1,29 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.widget
package com.mogo.och.shuttle.weaknet.passenger.ui.statusbar
import android.annotation.*
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import chassis.ChassisStatesOuterClass
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisStatesListener
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
import com.mogo.eagle.core.function.api.setting.IMoGoSkinModeChangeListener
import com.mogo.eagle.core.function.call.autopilot.CallerChassisStatesListenerManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.call.setting.CallerSkinModeListenerManager
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
import com.mogo.eagle.core.utilcode.kotlin.*
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ClickUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.common.module.manager.bluetooth.BleManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.aciv_wait_ele
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.iv_logon
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.progress
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.tv_power_cos
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.tv_status_line_name
import kotlinx.coroutines.*
import me.jessyan.autosize.utils.AutoSizeUtils
@@ -34,8 +33,8 @@ import me.jessyan.autosize.utils.AutoSizeUtils
*/
class M2StatusBarView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : ConstraintLayout(context, attrs), IViewControlListener, IMoGoSkinModeChangeListener,
IMoGoChassisStatesListener {
) : ConstraintLayout(context, attrs),
IMoGoChassisStatesListener, ICommonCallback {
companion object {
const val TAG = "M2StatusBarView"
@@ -46,59 +45,70 @@ class M2StatusBarView @JvmOverloads constructor(
init {
LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_view_status_bar, this, true)
setBackgroundColor(Color.parseColor("#80FFFFFF"))
setBackgroundColor(ResourcesUtils.getColor(R.color.white))
isClickable = true
isFocusable = true
iv_logon.setOnLongClickListener {
context?.let {
ToggleDebugView.toggleDebugView.toggle(it)
}
true
}
}
@SuppressLint("ClickableViewAccessibility")
override fun onAttachedToWindow() {
super.onAttachedToWindow()
CallerLogger.d(TAG,"onAttachedToWindow-------${this}")
post {
val params: ViewGroup.LayoutParams = getLayoutParams()
params.height = AutoSizeUtils.dp2px(context,60f)
params.height = AutoSizeUtils.dp2px(context,100f)
layoutParams = params
}
//添加view控制
CallerHmiViewControlListenerManager.addListener(TAG,this)
// 添加换肤监听
CallerSkinModeListenerManager.addListener(TAG, this)
//电量
CallerChassisStatesListenerManager.addListener(TAG,this)
CommonModel.setRouteLineInfoCallback(TAG,this)
progress?.also {
it.progress = 0
aciv_wait_ele.visibility = VISIBLE
}
tv_power_cos?.also {
it.text = "检测中"
}
iv_logon.onClick {
BizLoopManager.runInMainThread{
BleManager.scanLeDevice()
}
it.text = "?"
}
tv_power_cos.onClick {
BizLoopManager.runInIoThread {
BleManager.sendData2Wx("1889480", "00,${System.currentTimeMillis()}")
}
}
}
override fun onSkinModeChange(skinMode: Int) {
when (skinMode) {
0 -> setStatusBarDarkOrLight(false)
1 -> setStatusBarDarkOrLight(true)
override fun updateLineInfo(lineName: String?) {
post {
CallerLogger.d(TAG,"updateLineInfo2-------${lineName}----${this}")
if(lineName==null){
tv_status_line_name.setText(R.string.m2_line_name_detaile)
}else{
tv_status_line_name.text = lineName
}
}
}
override fun showNoTaskView(isTrue: Boolean) {
BizLoopManager.runInMainThread {
CallerLogger.d(TAG,"updateLineInfo1-------${isTrue}----${this}")
if(isTrue) {
tv_status_line_name.setText(R.string.m2_line_name_detaile)
}
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
CallerHmiViewControlListenerManager.removeListener(TAG)
CallerSkinModeListenerManager.removeListener(TAG)
CallerChassisStatesListenerManager.removeListener(TAG)
CallerDevaToolsManager.hideStatusBar()
CommonModel.setRouteLineInfoCallback(TAG,null)
}
@SuppressLint("SetTextI18n")
@@ -112,14 +122,11 @@ class M2StatusBarView @JvmOverloads constructor(
if (oldBmsSoc != bmsSoc ) {
scope.launch {
if(bmsSoc >1){
progress?.also { it.progress = bmsSoc.toInt() }
tv_power_cos?.also { it.text = "${bmsSoc.toInt()}%" }
}else{
val power = (bmsSoc * 100).toInt()
progress?.also { it.progress = power }
tv_power_cos?.also {it.text = "$power%" }
}
aciv_wait_ele.visibility = GONE
}
}
} finally {

View File

@@ -0,0 +1,19 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.widget
import android.content.Context
import android.util.AttributeSet
import com.mogo.eagle.core.function.view.MapBizView
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import me.jessyan.autosize.utils.AutoSizeUtils
class OchMapBizPView(context: Context?, attrs: AttributeSet?) : MapBizView(context, attrs) {
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
this.outlineProvider =
TextureVideoViewOutlineProvider(AutoSizeUtils.dp2px(context, 36f).toFloat())
this.clipToOutline = true
}
}

View File

@@ -9,17 +9,15 @@ import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.util.ActivityUtils
import com.mogo.eagle.core.utilcode.util.DeviceUtils
import com.mogo.eagle.core.utilcode.util.MultiDisplayUtils
import com.mogo.och.bridge.ui.autopilot.AutopilotState
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.biz.provider.CommonServiceImpl
import com.mogo.och.common.module.biz.scanner.ScannerManager
import com.mogo.och.common.module.voice.OutOffVoice
import com.mogo.och.common.module.wigets.media.MediaPlayerActivity
import com.mogo.och.shuttle.weaknet.passenger.model.TicketModel
import com.mogo.och.shuttle.weaknet.passenger.ui.widget.BusPStatusBarView
import com.mogo.och.shuttle.weaknet.passenger.ui.BusPassengerRouteFragment
import com.mogo.och.shuttle.weaknet.passenger.ui.PM2BaseFragment
import com.mogo.och.shuttle.weaknet.passenger.ui.widget.M2StatusBarView
import com.mogo.och.shuttle.weaknet.passenger.ui.statusbar.M2StatusBarView
/**
* 网约车-Bus-乘客端

View File

@@ -9,16 +9,16 @@ import java.util.List;
* @date: 2022/4/6
*/
public interface ICommonCallback {
void updateLineInfo(String lineName);
void updateStationsInfo(List<BusStationBean> stations, int currentStationIndex, boolean isArrived);
void updateSpeed(int location);
void updateRemainMT(long meters, long timeInSecond);
void showNoTaskView(boolean isTrue);
default void updateLineInfo(String lineName){}
default void updateStationsInfo(List<BusStationBean> stations, int currentStationIndex, boolean isArrived){}
default void updateSpeed(int location){}
default void updateRemainMT(long meters, long timeInSecond){}
default void showNoTaskView(boolean isTrue){}
/**
* false: 未开启自驾, true 开启自驾
*/
void updateAutoStatus(boolean isOpen);
default void updateAutoStatus(boolean isOpen){}
default void updateLineStations(List<BusStationBean> stations){}

View File

@@ -25,6 +25,7 @@ import com.mogo.och.bridge.autopilot.location.OchLocationManager
import com.mogo.och.bridge.distance.IDistanceListener
import com.mogo.och.bridge.distance.TrajectoryAndDistanceManager
import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.download.DownloadManager
import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager
import com.mogo.och.common.module.manager.socket.lan.ILanMessageListener
@@ -55,7 +56,7 @@ object CommonModel {
var mContext: Context? = null
private var mCommonCallback: ICommonCallback? = null // bus路线信息更新
private var mCommonCallbackList = mutableMapOf<String,ICommonCallback>()
var mStations = mutableListOf<BusStationBean>()
var mNextStationIndex = 0 // A-B要到达站的index
@@ -99,11 +100,16 @@ object CommonModel {
LanSocketManager.unRegisterSocketMessageListener(DPMsgType.TYPE_TASK_DETAILS.type, typeTaskDetails)
LoginLanPassengerSocket.removeListener(TAG)
cleanStation("release")
this.mCommonCallbackList.clear()
}
fun setRouteLineInfoCallback(callback: ICommonCallback?) {
this.mCommonCallback = callback
fun setRouteLineInfoCallback(tag:String,callback: ICommonCallback?) {
if(callback==null){
this.mCommonCallbackList.remove(tag)
return
}
this.mCommonCallbackList[tag] = callback
}
@@ -141,19 +147,25 @@ object CommonModel {
mNextStationIndex >= 0 && mNextStationIndex <= mStations.size - 1
&& isGoingToNextStation
){
mCommonCallback?.updateAutoStatus(true)
mCommonCallbackList.forEach {
it.value.updateAutoStatus(true)
}
}else{//非美化模式下
mCommonCallback?.updateAutoStatus(false)
mCommonCallbackList.forEach {
it.value.updateAutoStatus(false)
}
}
}else{//自驾状态 2
mCommonCallback?.updateAutoStatus(true)
mCommonCallbackList.forEach {
it.value.updateAutoStatus(true)
}
}
}
}
private val trajectoryListener: IDistanceListener = object : IDistanceListener {
override fun distanceCallback(distance: Float) {
val lastTime = distance / BusPassengerConst.BUS_AVERAGE_SPEED * 3.6 //秒
val lastTime = distance / OchCommonConst.BUS_AVERAGE_SPEED * 3.6 //秒
d(TAG, "轨迹排查==lastSumLength = $distance")
if (routesResult != null) {
for (site in routesResult!!.sites) {
@@ -172,10 +184,12 @@ object CommonModel {
}
}
}
mCommonCallback?.updateRemainMT(
distance.toLong(),
lastTime.toLong()
)
mCommonCallbackList.forEach {
it.value.updateRemainMT(
distance.toLong(),
lastTime.toLong()
)
}
}
}
@@ -226,7 +240,9 @@ object CommonModel {
mNextStationIndex = 0
cleanStation("queryDriverSiteByCoordinate")
isGoingToNextStation = false
mCommonCallback?.showNoTaskView(true)
mCommonCallbackList.forEach {
it.value.showNoTaskView(true)
}
}
@@ -238,20 +254,26 @@ object CommonModel {
if (routesResult != null && routesResult!!.lineId != result.lineId) {
d(TAG, "lineId change= clearCustomPolyline")
mCommonCallback?.clearCustomPolyline()
mCommonCallbackList.forEach {
it.value.clearCustomPolyline()
}
}
d(TAG, "queryDriverSiteByCoordinate = update")
d(TAG, "queryDriverSiteByCoordinate = update ${result}")
routesResult = result
if (result.sites != null) {
mCommonCallback?.updateLineInfo(result.name)
mCommonCallback?.showNoTaskView(false)
mCommonCallbackList.forEach {
it.value.updateLineInfo(result.name)
it.value.showNoTaskView(false)
}
if (result.sites != null) {
val stations = result.sites
mStations.clear()
mStations.addAll(stations)
mCommonCallback?.updateLineStations(mStations)
mCommonCallbackList.forEach {
it.value.updateLineStations(mStations)
}
for (i in stations.indices) {
val station = stations[i]
if(station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED){
@@ -259,7 +281,9 @@ object CommonModel {
if (station.isLeaving && i + 1 < stations.size
) {
isGoingToNextStation = true
mCommonCallback?.updateStationsInfo(stations, i + 1, false)
mCommonCallbackList.forEach {
it.value.updateStationsInfo(stations, i + 1, false)
}
mNextStationIndex = i + 1
val startStation = mStations[i]
val endStation = mStations[i + 1]
@@ -272,7 +296,9 @@ object CommonModel {
}
isGoingToNextStation = false
Logger.d(TAG, "order = station= arrive")
mCommonCallback?.updateStationsInfo(stations, i, true)
mCommonCallbackList.forEach {
it.value.updateStationsInfo(stations, i, true)
}
return
}
}
@@ -411,6 +437,8 @@ object CommonModel {
// km/h
val speedKM = (abs(mogoLocation.gnssSpeed) * 3.6f).toInt()
mCommonCallback?.updateSpeed(speedKM)
mCommonCallbackList.forEach {
it.value.updateSpeed(speedKM)
}
}
}

View File

@@ -1,41 +0,0 @@
package com.mogo.och.shuttle.weaknet.passenger.presenter
import androidx.lifecycle.LifecycleOwner
import com.mogo.commons.mvp.Presenter
import com.mogo.och.shuttle.weaknet.passenger.callback.ADASCallback
import com.mogo.och.shuttle.weaknet.passenger.constant.M2Const.Companion.M2_MAP_STATION_MAKER
import com.mogo.och.shuttle.weaknet.passenger.model.PM2ADASModel
import com.mogo.och.shuttle.weaknet.passenger.ui.PM2HPMapFragment
class PM2ADASPresenter(view: PM2HPMapFragment?) :
Presenter<PM2HPMapFragment?>(view), ADASCallback {
init {
PM2ADASModel.INSTANCE.init(context)
initListener()
}
private fun initListener() {
PM2ADASModel.INSTANCE.setAdasCallback(this)
}
private fun removeListener() {
PM2ADASModel.INSTANCE.setAdasCallback(null)
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
removeListener()
}
override fun updateHDMapStations(stations: MutableList<MutableList<Double>>) {
for (i in stations.indices){
mView?.setMapMaker(M2_MAP_STATION_MAKER+i,stations[i])
}
}
override fun removeHDMapStations() {
mView?.removeMapMaker(M2_MAP_STATION_MAKER)
}
}

View File

@@ -1,124 +0,0 @@
package com.mogo.och.shuttle.weaknet.passenger.presenter
import androidx.lifecycle.LifecycleOwner
import com.amap.api.maps.model.LatLng
import com.mogo.commons.mvp.Presenter
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.shuttle.weaknet.passenger.model.PM2ADASModel
import com.mogo.och.shuttle.weaknet.passenger.ui.PM2DrivingInfoFragment
import com.mogo.och.data.bean.BusStationBean
import com.mogo.och.shuttle.weaknet.passenger.callback.ICommonCallback
import com.mogo.och.shuttle.weaknet.passenger.model.CommonModel
class PM2DrivingPresenter(view: PM2DrivingInfoFragment?) :
Presenter<PM2DrivingInfoFragment?>(view),
ICommonCallback {
init {
CommonModel.init(context)
PM2ADASModel.INSTANCE.init(context)
initListener()
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
destroyListener()
CommonModel.releaseListeners()
}
private fun initListener(){
CommonModel.setRouteLineInfoCallback(this)
}
private fun destroyListener(){
CommonModel.setRouteLineInfoCallback(null)
}
override fun updateSpeed(speed: Int) {
// CallerLogger.d(
// SceneConstant.M_BUS_P + "speed = ",speed.toString()
// )
ThreadUtils.runOnUiThread {
mView?.updateSpeed(speed)
}
}
override fun updateLineInfo(lineName: String) {
ThreadUtils.runOnUiThread {
mView?.updateTaskName(lineName)
}
}
override fun updateRemainMT(meters: Long, timeInSecond: Long) {
ThreadUtils.runOnUiThread {
mView?.updateRemainMT(meters, timeInSecond) //米,秒
}
}
override fun showNoTaskView(isTrue: Boolean) {
ThreadUtils.runOnUiThread {
mView?.showNoTaskView(!isTrue)
}
if (isTrue){
PM2ADASModel.INSTANCE.removeHDMapStations()
}
}
override fun updateLineStations(stations: MutableList<BusStationBean>) {
val stationsList = mutableListOf<LatLng>()
val stationsListPass = mutableListOf<LatLng>()
var startStation: LatLng? = null
var endStation: LatLng? = null
for (i in stations.indices){
val station = stations[i]
val latLng = LatLng(station.gcjLat,station.gcjLon)
if(i==0){
startStation = latLng
continue
}
if(i==stations.size-1){
endStation = latLng
continue
}
if(station.drivingStatus==1){//行驶信息0初始值1已经过2当前站3未到站
stationsListPass.add(latLng)
}else if(station.drivingStatus==2){
if(station.isLeaving){
stationsListPass.add(latLng)
}else{
stationsList.add(latLng)
}
}else{
stationsList.add(latLng)
}
}
ThreadUtils.runOnUiThread {
mView?.updateLineStations(stationsList,stationsListPass,startStation,endStation)
}
PM2ADASModel.INSTANCE.updateHDMapStations(stations)
}
override fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean) {
ThreadUtils.runOnUiThread {
mView?.updateStationsInfo(stations,i,isArrived)
}
}
override fun clearCustomPolyline() {
ThreadUtils.runOnUiThread {
mView?.clearCustomPolyline()
}
}
override fun updateAutoStatus(isOpen: Boolean) {
ThreadUtils.runOnUiThread {
mView?.updateAutoStatus(isOpen)
}
}
}

View File

@@ -1,96 +0,0 @@
package com.mogo.och.shuttle.weaknet.passenger.ui
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.mogo.commons.mvp.MvpFragment
import com.mogo.eagle.core.utilcode.util.AppUtils
import com.mogo.och.common.module.biz.media.MediaManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.transform.OchTransform
import com.mogo.och.common.module.manager.transform.OchTransformDispatch
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.presenter.PM2Presenter
import com.mogo.och.common.module.wigets.media.MediaPlayerFragment
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.tv_shuttle_b2_p_version
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.video_fragment
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class PM2BaseFragment :
MvpFragment<PM2BaseFragment?, PM2Presenter?>() {
private var drivingFragment : PM2DrivingInfoFragment? = null
private var hdMapFragment : PM2HPMapFragment? = null
private var mediaFragment : MediaPlayerFragment? = null
private val ochTransform = object : OchTransformDispatch{
override fun setVideoView(target: View?) {
super.setVideoView(target)
if(target!=null){
BizLoopManager.runInMainThread{
target.id = R.id.video_show
val params = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
video_fragment.addView(target,params)
MediaManager.setMediaPause()
}
}else{
BizLoopManager.runInMainThread{
findViewById<View>(R.id.video_show)?.let {
video_fragment.removeView(it)
MediaManager.setMediaResume()
}
}
}
}
}
override fun getLayoutId(): Int {
return R.layout.shuttle_p_m2_fragment
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
tv_shuttle_b2_p_version.text = "版本:${AppUtils.getAppVersionName()}"
//隐藏小地图
initFragment()
OchTransform.addListener(TAG,ochTransform)
}
override fun onDestroy() {
OchTransform.removeListener(TAG)
super.onDestroy()
}
/**
* 初始化行程信息,高静地图,宣传 三个fragment
*/
private fun initFragment() {
if (drivingFragment == null) drivingFragment = PM2DrivingInfoFragment()
childFragmentManager.beginTransaction().add(R.id.driving_fragment, drivingFragment!!)
.show(drivingFragment!!).commitAllowingStateLoss()
if (hdMapFragment == null) hdMapFragment = PM2HPMapFragment()
childFragmentManager.beginTransaction().add(R.id.hd_map_fragment, hdMapFragment!!)
.show(hdMapFragment!!).commitAllowingStateLoss()
if (mediaFragment == null) mediaFragment = MediaPlayerFragment()
childFragmentManager.beginTransaction().add(R.id.video_fragment, mediaFragment!!)
.show(mediaFragment!!).commitAllowingStateLoss()
}
override fun createPresenter(): PM2Presenter {
return PM2Presenter(this)
}
companion object {
public val TAG = PM2BaseFragment::class.java.simpleName
}
}

View File

@@ -1,285 +0,0 @@
package com.mogo.och.shuttle.weaknet.passenger.ui
import android.graphics.BitmapFactory
import android.graphics.drawable.AnimationDrawable
import android.os.Bundle
import android.view.View
import androidx.core.content.ContextCompat
import com.amap.api.maps.model.LatLng
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.mvp.MvpFragment
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
import com.mogo.eagle.core.function.view.SiteMarkerBean
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.presenter.PM2DrivingPresenter
import com.mogo.och.common.module.utils.NumberFormatUtil
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.data.bean.BusStationBean
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.auto_tv
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.clg_distance_left_time
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.group_not_select_line
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.group_stationinfo
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.iv_animal_list
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.line_name_tv
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.overMapView
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.speed_tv
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.station_name_tv
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_arrived_notice
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_distance
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_left_time
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_next_station_title
import me.jessyan.autosize.utils.AutoSizeUtils
import kotlin.math.ceil
import kotlin.math.roundToInt
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class PM2DrivingInfoFragment :
MvpFragment<PM2DrivingInfoFragment?, PM2DrivingPresenter?>() {
private val stationIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_staton_icon
)
private val stationPassIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_staton_arrived_icon
)
private val startStationIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_start_icon
)
private val endStationIcon = BitmapFactory.decodeResource(
AbsMogoApplication.getApp().resources,
R.drawable.shuttle_p_m2_map_end_icon
)
override fun getLayoutId(): Int {
return R.layout.shuttle_p_m2_driving_info_fragment
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
speed_tv.setOnLongClickListener {
context?.let { ToggleDebugView.toggleDebugView.toggle(it) }
true
}
line_name_tv.setTextColor(ResourcesUtils.getColor(R.color.shuttle_p_m2_line_name_tv_color))
station_name_tv.setTextColor(ResourcesUtils.getColor(R.color.shuttle_p_m2_line_name_tv_color))
speed_tv.setVertrial(true)
val intArrayOf = intArrayOf(
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_43cefe),
ResourcesUtils.getColor(R.color.shuttle_p_m2_color_1466fb),
)
speed_tv.setmColorList(intArrayOf)
}
override fun initViews(savedInstanceState: Bundle?) {
super.initViews(savedInstanceState)
overMapView?.let {
it.onCreateView(savedInstanceState)
val radius = AutoSizeUtils.dp2px(requireContext(), 16f)
it.outlineProvider = TextureVideoViewOutlineProvider(radius.toFloat())
it.clipToOutline = true
}
}
override fun onResume() {
super.onResume()
overMapView?.onResume()
}
override fun onPause() {
super.onPause()
overMapView?.onPause()
}
override fun onDestroyView() {
overMapView?.onDestroy()
mPresenter?.onDestroy(this)
super.onDestroyView()
}
fun updateSpeed(speed: Int) {
speed_tv.text = speed.toString()
}
fun updateTaskName(name: String) {
line_name_tv.text = name
}
fun showNoTaskView(haveTask: Boolean) {
setLineInfoView(haveTask)
}
private fun setLineInfoView(isShow: Boolean) {
if (!isShow) {
updateNoOrderUI()
}
}
private fun updateNoOrderUI() {
line_name_tv.text = resources.getString(R.string.shuttle_p_m2_not_select_line_content)
updateNoStationView()
overMapView?.clearSiteMarkers()
clearCustomPolyline()
}
fun clearCustomPolyline() {
overMapView?.clearCustomPolyline()
}
private fun updateNoStationView() {
station_name_tv.setTextColor(ResourcesUtils.getColor(R.color.shuttle_p_m2_next_tv_color))
station_name_tv.text = resources.getString(R.string.shuttle_p_m2_empty_tv)
tv_distance.text = resources.getString(R.string.shuttle_p_m2_empty_remain_km)
tv_left_time.text = resources.getString(R.string.shuttle_p_m2_empty_remain_minute)
noLineShow()
}
override fun createPresenter(): PM2DrivingPresenter {
return PM2DrivingPresenter(this)
}
fun updateAutoStatus(isAutoPilot: Boolean) {
if (isAutoPilot) {
context?.let {
auto_tv.setTextColor(
ContextCompat.getColor(
it,
R.color.shuttle_p_m2_white_color
)
)
}
context?.let {
auto_tv.background =
ContextCompat.getDrawable(it, R.drawable.shuttle_p_m2_auto_button_bg)
}
} else {
context?.let {
auto_tv.setTextColor(
ContextCompat.getColor(
it,
R.color.shuttle_p_m2_color_7094ad
)
)
}
context?.let {
auto_tv.background =
ContextCompat.getDrawable(it, R.drawable.shuttle_p_m2_bg_p_m2_auto)
}
}
}
fun updateLineStations(
stations: MutableList<LatLng>,
stationsPass: MutableList<LatLng>,
startStation: LatLng?,
endStation: LatLng?
) {
overMapView?.let {
val stationsList: MutableList<SiteMarkerBean> = mutableListOf()
startStation?.let { start ->
stationsList.add(SiteMarkerBean(start, startStationIcon, 0.5f, 0.5f))
}
for (stationPass in stationsPass) {
stationsList.add(SiteMarkerBean(stationPass, stationPassIcon, 0.5f, 0.5f))
}
for (stationPass in stations) {
stationsList.add(SiteMarkerBean(stationPass, stationIcon, 0.5f, 0.5f))
}
endStation?.let { end ->
stationsList.add(SiteMarkerBean(end, endStationIcon, 0.5f, 0.5f))
}
it.drawSiteMarkers(stationsList)
}
}
fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean) {
if (stations.size == 0) return
if (0 <= i && i < stations.size) {
station_name_tv.setTextColor(ResourcesUtils.getColor(R.color.shuttle_p_m2_next_tv_color))
station_name_tv.text = stations[i].name
}
if (isArrived) {//到站
tv_distance.text = resources.getString(R.string.shuttle_p_m2_empty_remain_km)
tv_left_time.text = resources.getString(R.string.shuttle_p_m2_empty_remain_minute)
tv_next_station_title.text =
resources.getString(R.string.shuttle_p_m2_station_title_arrived_tv)
haveLineAndArrivedStation()
} else { //前往目的地中
tv_next_station_title.text =
resources.getString(R.string.shuttle_p_m2_next_station_title)
haveLineAndArriveingStation()
}
}
/**
* 剩余里程和时间
*/
fun updateRemainMT(meters: Long, timeInSecond: Long) { //米。秒
var disUnit = "公里"
var remainDis: String? = "0"
if (meters > 0) {
if (meters / 1000 < 1) {
disUnit = ""
remainDis = meters.toFloat().roundToInt().toString()
} else {
disUnit = "公里"
remainDis = NumberFormatUtil.formatLong(meters.toDouble() / 1000)
}
}
val time = ceil(timeInSecond / 60f).toInt()
"$remainDis$disUnit".also { tv_distance.text = it }
"${time}分钟".also { tv_left_time.text = it }
}
fun noLineShow() {
// 没有线路展示
group_not_select_line.visibility = View.VISIBLE
// 下一个站点
group_stationinfo.visibility = View.GONE
// 距离和剩余大概时间
clg_distance_left_time.visibility = View.GONE
// 到达站点
tv_arrived_notice.visibility = View.GONE
iv_animal_list.visibility = View.GONE
}
// 有线路正在到站点
fun haveLineAndArriveingStation() {
group_not_select_line.visibility = View.GONE
group_stationinfo.visibility = View.VISIBLE
clg_distance_left_time.visibility = View.VISIBLE
tv_arrived_notice.visibility = View.GONE
iv_animal_list.visibility = View.GONE
}
// 有线路到达站点
private fun haveLineAndArrivedStation() {
group_not_select_line.visibility = View.GONE
group_stationinfo.visibility = View.VISIBLE
clg_distance_left_time.visibility = View.GONE
tv_arrived_notice.visibility = View.VISIBLE
iv_animal_list.visibility = View.VISIBLE
val animationDrawable = iv_animal_list.drawable as AnimationDrawable
animationDrawable.start()
}
companion object {
private val TAG = PM2DrivingInfoFragment::class.java.simpleName
}
}

View File

@@ -1,128 +0,0 @@
package com.mogo.och.shuttle.weaknet.passenger.ui
import android.os.Bundle
import com.mogo.commons.mvp.MvpFragment
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.map.overlay.core.Level
import com.mogo.map.overlay.point.Point
import com.mogo.map.MapDataWrapper
import com.mogo.och.shuttle.weaknet.passenger.R
import com.mogo.och.shuttle.weaknet.passenger.constant.M2Const.Companion.TYPE_MARKER_M2_LINE
import com.mogo.och.shuttle.weaknet.passenger.presenter.PM2ADASPresenter
import com.mogo.och.common.module.utils.OCHThreadPoolManager
import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.mHomeView
import java.util.*
/**
* @author: wangmingjun
* @date: 2022/4/12
*/
class PM2HPMapFragment :
MvpFragment<PM2HPMapFragment?, PM2ADASPresenter?>() {
/**
* 改变自动驾驶状态
*
* @param status 2 - running 1 - enable 2 - disable
*/
override fun getLayoutId(): Int {
return R.layout.shuttle_p_m2_hpmap_fragment
}
override fun getTagName(): String {
return TAG
}
override fun initViews() {
}
override fun initViews(savedInstanceState: Bundle?) {
super.initViews(savedInstanceState)
mHomeView.onCreate(savedInstanceState)
}
override fun onResume() {
super.onResume()
mHomeView.onResume()
}
override fun onLowMemory() {
super.onLowMemory()
mHomeView.onLowMemory()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mHomeView.onSaveInstanceState(outState)
}
override fun onPause() {
super.onPause()
mHomeView.onPause()
}
override fun onDestroyView() {
mHomeView.onDestroy()
super.onDestroyView()
}
override fun createPresenter(): PM2ADASPresenter {
return PM2ADASPresenter(this)
}
companion object {
private val TAG = PM2HPMapFragment::class.java.simpleName
}
fun setMapMaker(
uuid: String,
station: MutableList<Double>,
) {
//开启线程执行起终点marker设置
val setMapMarkerRunnable = Runnable {
d(
"setMapMaker= " + Thread.currentThread().name,
uuid + "=latitude=" + station[1] + ",longitude=" + station[0]
)
val builder = Point.Options.Builder(
TYPE_MARKER_M2_LINE,
Level.MAP_MARKER
)
.setId(uuid)
.anchor(0.5f, 0.5f)
.set3DMode(true)
.isUseGps(true)
.controlAngle(true)
.icon3DRes(R.raw.star_marker)
.longitude(station[0])
.latitude(station[1])
MapDataWrapper.getCenterLineInfo(
station[0], station[1], -1f
) {
// 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 地图未初始化会返回空
it?.let{
builder.rotate(it.angle.toFloat())
}
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
overlayManager?.showOrUpdatePoint(builder.build())
}
}
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable)
}
fun removeMapMaker(
uuid: String,
) {
//开启线程移除起终点marker设置
val removeMapMarkerRunnable = Runnable {
d("RemoveMapMaker=" + Thread.currentThread().name, uuid)
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
overlayManager?.removeAllPointsInOwner(TYPE_MARKER_M2_LINE)
}
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable)
}
}

View File

@@ -1,36 +0,0 @@
package com.mogo.och.shuttle.weaknet.passenger.ui.widget
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import com.mogo.eagle.core.function.api.devatools.IMoGoDevaToolsListener
import com.mogo.eagle.core.function.hmi.ui.widget.BlueToothView
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.shuttle_p_m2_view_blue_tooth.view.blueView
/**
* 魔戒蓝牙控件
* 放置于StatusBar右侧位置
*/
class M2BlueToothView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : BlueToothView(context, attrs, defStyleAttr),IMoGoDevaToolsListener {
init {
LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_view_blue_tooth, this, true)
}
override fun mofangStatus(status: Boolean) {
ThreadUtils.runOnUiThread {
if (status) {
blueView.setImageResource(R.drawable.shuttle_p_m2_blue_tooth_close)
} else {
blueView.setImageResource(R.drawable.shuttle_p_m2_blue_tooth_open)
}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 765 B

After

Width:  |  Height:  |  Size: 765 B

View File

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 797 B

Some files were not shown because too many files have changed in this diff Show More