[8.1.0]统一红绿灯

This commit is contained in:
xuxinchao
2025-06-16 10:11:35 +08:00
parent b33f5aff3b
commit a0a16a8f0a
24 changed files with 974 additions and 11 deletions

View File

@@ -24,8 +24,10 @@ import com.mogo.eagle.core.data.multidisplay.TelematicConstant
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener
import com.mogo.eagle.core.function.api.devatools.INDECloudListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager
import com.mogo.eagle.core.function.call.devatools.CallerNDECloudManager
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager
import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager
@@ -36,6 +38,9 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.skin.utils.SkinResources
import com.zhjt.mogo.adas.common.cloud.AstFuncTlmPhaseStateLightState
import com.zhjt.mogo.adas.data.bean.cloud.info.AstFuncTlmInfo
import com.zhjt.mogo.adas.data.bean.cloud.pojo.AstFuncPojo
import com.zhjt.service.chain.ChainLog
import perception.FusionTrafficLightOuterClass
import kotlin.math.abs
@@ -66,7 +71,7 @@ fun convert(state: FusionTrafficLightOuterClass.FusionLightState): TrafficLightE
* @since: 2022/4/28
*/
class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLightListener,
IMoGoChassisLocationGCJ02Listener {
IMoGoChassisLocationGCJ02Listener, INDECloudListener {
companion object {
const val TAG = "TrafficLightDispatcher"
@@ -93,6 +98,11 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
@Volatile
private var hasFusionLightStatus: Boolean = false
//是否有云控基础平台红绿灯数据
@Volatile
private var hasCloudControlLight: Boolean = false
//红绿灯定时器,超时未更新隐藏红绿灯
@Volatile
private var lightCountDownTimer: CountDownTimer? = null
@@ -110,6 +120,8 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
//注册获取当前车速
CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 1, this)
//注册监听云控基础平台数据
CallerNDECloudManager.addListener(TAG,this)
}
/**
@@ -362,7 +374,7 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
"${SceneConstant.M_D_C}${TAG}",
"resetTrafficLight ------> isReset = $isReset ---hasObuLightStatus = $hasObuLightStatus"
)
if (!hasObuLightStatus && !hasAutopilotPerception && !hasFusionLightStatus) {
if (!hasObuLightStatus && !hasAutopilotPerception && !hasFusionLightStatus && !hasCloudControlLight) {
if (isReset) {
hide("云端重置红绿灯数据", DataSourceType.AICLOUD)
}
@@ -425,6 +437,7 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
hasObuLightStatus = false
hasAutopilotPerception = false
hasAiLightStatus = false
hasCloudControlLight = false
hasFusionLightStatus = true
CallerTrafficLightListenerManager.showFusionTrafficLight(currentState, currentDuration, nextState, nextDuration,
nextTwoState, nextTwoDuration, lightSource)
@@ -542,6 +555,8 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
//取消注册获取当前车速
CallerChassisLocationGCJ02ListenerManager.removeListener(TAG)
//取消注册云控基础平台数据
CallerNDECloudManager.removeListener(TAG)
}
/**
@@ -551,4 +566,64 @@ class TrafficLightDispatcher : IMoGoAutopilotIdentifyListener, IMoGoTrafficLight
currentSpeed = abs(mogoLocation?.gnssSpeed ?: 0f)
}
/**
* NDE下发 信号灯信息
* @param astFuncPojo 云端辅助功能信息
* @param astFuncTlmInfo 云端下发信号灯信息
*/
override fun onNdeCloudAstFuncTlm(astFuncPojo: AstFuncPojo, astFuncTlmInfo: AstFuncTlmInfo) {
super.onNdeCloudAstFuncTlm(astFuncPojo, astFuncTlmInfo)
if(astFuncTlmInfo.phaseState.isNotEmpty()){
if(hasFusionLightStatus){
return
}else{
val currentState = getLightStatus(astFuncTlmInfo.phaseState[0].lightState)
val nextState = getLightStatus(astFuncTlmInfo.phaseState[0].nextLightState)
val currentDuration = astFuncTlmInfo.phaseState[0].timeLeft
val nextDuration = astFuncTlmInfo.phaseState[0].nextLightTime
if(currentState!=TrafficLightEnum.BLACK && nextState != TrafficLightEnum.BLACK
&& currentDuration != 0 && nextDuration != 0){
hasCloudControlLight = true
//展示云控基础平台信号灯信息
CallerTrafficLightListenerManager.showCloudTrafficLight(currentState, currentDuration, nextState, nextDuration)
}
}
}else{
hasCloudControlLight = false
}
}
/**
* 获取云控基础平台灯态
* @param lightState 当前灯态
*/
private fun getLightStatus(lightState: AstFuncTlmPhaseStateLightState): TrafficLightEnum {
return when (lightState) {
//红闪、红灯
AstFuncTlmPhaseStateLightState.RED_FLASH,
AstFuncTlmPhaseStateLightState.RED -> {
TrafficLightEnum.RED
}
//绿灯待行状态、绿灯状态、受保护相位绿灯(箭头灯)
AstFuncTlmPhaseStateLightState.GREEN_WAIT,
AstFuncTlmPhaseStateLightState.GREEN,
AstFuncTlmPhaseStateLightState.GREEN_PROTECTED -> {
TrafficLightEnum.GREEN
}
//黄灯状态、黄闪
AstFuncTlmPhaseStateLightState.YELLOW,
AstFuncTlmPhaseStateLightState.YELLOW_FLASH -> {
TrafficLightEnum.YELLOW
}
//异常、预留、未知状态、信号灯未工作、故障
AstFuncTlmPhaseStateLightState.ERROR,
AstFuncTlmPhaseStateLightState.RESERVED,
AstFuncTlmPhaseStateLightState.UNKNOWN,
AstFuncTlmPhaseStateLightState.OFF,
AstFuncTlmPhaseStateLightState.FAULT -> {
TrafficLightEnum.BLACK
}
}
}
}

View File

@@ -0,0 +1,205 @@
package com.mogo.eagle.core.function.hmi.ui.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.mogo.eagle.core.data.enums.TrafficLightEnum;
import com.mogo.eagle.core.function.hmi.R;
import java.util.ArrayList;
import java.util.List;
import me.jessyan.autosize.utils.AutoSizeUtils;
/**
* 融合红绿灯红、黄、绿时间占比示意View
* 鹰眼6.5.0需求
*/
public class ProportionChartTwoView extends View {
private static final int DEFAULT_RING_WIDTH = 5;
private float mRingWidth = 0;
private Paint mRingPaint;
private RectF mRectF;
//红绿灯绿灯、黄灯、红灯灯色时间
private List<Integer> proportionList = new ArrayList<>();
//红绿灯灯态
private List<TrafficLightEnum> lightStatusList = new ArrayList<>();
//一轮灯态的总时长
private int totalDuration = 0;
int[] greenColorArray = new int[]{Color.parseColor("#45E041"),Color.parseColor("#45E041")};
int[] yellowColorArray = new int[]{Color.parseColor("#FFF000"),Color.parseColor("#FFF000")};
int[] redColorArray = new int[]{Color.parseColor("#FF4E41"),Color.parseColor("#FF4E41")};
public ProportionChartTwoView(Context context) {
super(context);
initSize(context);
init();
}
public ProportionChartTwoView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttr(context, attrs);
initSize(context);
init();
}
/**
* 更新红绿灯时间
* @param durationList 时间列表
* @param colorList 灯态列表
*/
public void updateProportion(List<Integer> durationList, List<TrafficLightEnum> colorList){
if(durationList != null && colorList != null){
this.proportionList = durationList;
totalDuration = 0;
for(int element: proportionList){
totalDuration += element;
}
this.lightStatusList = colorList;
postInvalidate();
}
}
public ProportionChartTwoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs);
initSize(context);
init();
}
private void initAttr(Context context, AttributeSet attrs){
if (attrs == null) {
return;
}
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProportionChartTwoView);
int n = array.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = array.getIndex(i);
if (attr == R.styleable.ProportionChartTwoView_chartRingWidth) {
mRingWidth = array.getDimension(attr, AutoSizeUtils.dp2px(context, DEFAULT_RING_WIDTH));
}
}
array.recycle();
}
/**
* 初始化Size
* @param context 上下文
*/
private void initSize(Context context){
if (mRingWidth == 0) {
mRingWidth = AutoSizeUtils.dp2px(context, AutoSizeUtils.dp2px(context, DEFAULT_RING_WIDTH));
}
}
/**
* 初始化画笔
*/
private void init(){
mRectF = new RectF();
mRingPaint = new Paint();
//抗锯齿
mRingPaint.setAntiAlias(true);
//防抖动
mRingPaint.setDither(true);
//仅描边(圆环)
mRingPaint.setStyle(Paint.Style.STROKE);
//圆环宽度
mRingPaint.setStrokeWidth(mRingWidth);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = Math.max(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(widthMeasureSpec));
setMeasuredDimension(size, size);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//宽和高分别去掉padding值取min的一半即圆的半径(这里demo没有用到可自行做一些其他计算使用)
// mRadius = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2f;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawRingView(canvas);
}
/**
* 画Ring
*/
private void drawRingView(Canvas canvas){
float sweepAngle = 0f;
float startAngle = -90f;
//矩形坐标
mRectF.set(getPaddingLeft() + mRingWidth / 2 , getPaddingTop() + mRingWidth / 2 ,
getWidth() - getPaddingRight() - mRingWidth / 2, getHeight() - getPaddingBottom() - mRingWidth / 2 );
for(int i=0;i<proportionList.size();i++){
startAngle += sweepAngle;
sweepAngle = 360f*proportionList.get(i)/totalDuration;
SweepGradient sweepGradient;
//设置渐变颜色
if(lightStatusList.get(i) == TrafficLightEnum.GREEN){
//设置绿灯渐变色
sweepGradient = new SweepGradient(getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f,
greenColorArray,null);
Matrix rotateMatrix = new Matrix();
if(i == 0){
rotateMatrix.setRotate(270,getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}else if(i == 1){
rotateMatrix.setRotate(270+(360*proportionList.get(0)),getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}else{
rotateMatrix.setRotate(270+(360*proportionList.get(0)+proportionList.get(1)),getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}
sweepGradient.setLocalMatrix(rotateMatrix);
}else if(lightStatusList.get(i) == TrafficLightEnum.YELLOW){
//设置黄灯渐变色
sweepGradient = new SweepGradient(getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f,
yellowColorArray,null);
Matrix rotateMatrix = new Matrix();
if(i == 0){
rotateMatrix.setRotate(270,getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}else if(i == 1){
rotateMatrix.setRotate(270+(360*proportionList.get(0)),getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}else{
rotateMatrix.setRotate(270+(360*proportionList.get(0)+proportionList.get(1)),getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}
sweepGradient.setLocalMatrix(rotateMatrix);
}else{
//设置红灯渐变色
sweepGradient = new SweepGradient(getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f,
redColorArray,null);
Matrix rotateMatrix = new Matrix();
if(i == 0){
rotateMatrix.setRotate(270,getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}else if(i == 1){
rotateMatrix.setRotate(270+(360*proportionList.get(0)),getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}else{
rotateMatrix.setRotate(270+(360*proportionList.get(0)+proportionList.get(1)),getWidth()/2f,(getPaddingTop() + getHeight() - getPaddingBottom())/2f);
}
sweepGradient.setLocalMatrix(rotateMatrix);
}
mRingPaint.setShader(sweepGradient);
//画圆环
canvas.drawArc(mRectF, startAngle, sweepAngle, false, mRingPaint);
}
}
}

View File

@@ -0,0 +1,530 @@
package com.mogo.eagle.core.function.hmi.ui.widget
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.mogo.eagle.core.data.enums.DataSourceType
import com.mogo.eagle.core.data.enums.TrafficLightEnum
import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener
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.v2x.CallerTrafficLightListenerManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
/**
* 8.1.0 信号灯统一方案
*/
class TrafficLightView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoTrafficLightListener {
companion object {
private const val TAG = "TrafficLightView"
}
private var user = 0 //使用方driver:0 passenger 1
private lateinit var ivLightStatus: ImageView //灯态
private lateinit var pcvLightProportion: ProportionChartTwoView //时长占比示意
private lateinit var tvLightRemain: TypefaceTextView //倒计时
private lateinit var tvLightSource: TextView //数据来源
private var totalDuration = 0 //一轮灯态的总时长
private var currentAngle = 0f //指针指向角度
private var currentLightState = TrafficLightEnum.BLACK //当前灯态
private var currentLightDuration = 0 //当前灯态倒计时
private var previousLightStatus = TrafficLightEnum.BLACK //上一帧灯态
private var previousLightDuration = 0 //上一帧灯态倒计时
private var redLightRoundNum = 0 //当前路口红灯出现的轮数
private var greenLightRoundNum = 0 //当前路口绿灯出现的轮数
private var yellowLightRoundNum = 0 //当前路口黄灯出现的轮数
private var isShowLight: Boolean = false
private var currentSource: Int = -1 //0:融合 1:云控基础平台 2:自车感知
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.TrafficLightView)
user = typedArray.getInt(R.styleable.TrafficLightView_lightUser,0)
typedArray.recycle()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
when(user){
//司机端
0 -> {
LayoutInflater.from(context).inflate(R.layout.hmi_view_traffic_light_driver, this, true)
}
//乘客端
1 -> {
LayoutInflater.from(context).inflate(R.layout.hmi_view_traffic_light_passenger, this, true)
}
}
CallerTrafficLightListenerManager.addListener(TAG, this)
initView()
}
private fun initView(){
ivLightStatus = findViewById(R.id.ivLightStatus)
pcvLightProportion = findViewById(R.id.pcvLightProportion)
tvLightRemain = findViewById(R.id.tvLightRemain)
tvLightSource = findViewById(R.id.tvLightSource)
}
/**
* 关闭红绿灯预警展示,并重制灯态
*/
override fun disableTrafficLight() {
super.disableTrafficLight()
UiThreadHandler.post{
this@TrafficLightView.visibility = GONE
CallerHmiViewControlListenerManager.invokeV2XEvent(View.GONE, TAG)
//将灯态轮归零
returnToZero()
resetLight()
}
}
/**
* 将灯态轮归零
*/
private fun returnToZero(){
redLightRoundNum = 0 //当前路口红灯出现的轮数
greenLightRoundNum = 0 //当前路口绿灯出现的轮数
yellowLightRoundNum = 0 //当前路口黄灯出现的轮数
}
/**
* 重置灯态
*/
private fun resetLight(){
currentLightState = TrafficLightEnum.BLACK
currentLightDuration = 0
previousLightStatus = TrafficLightEnum.BLACK
previousLightDuration = 0
currentSource = -1
}
/**
* 判断是否进入新的一轮灯态
* @param currentState 当前灯态
*/
private fun judgeRoundNum(currentState: TrafficLightEnum): Boolean{
if(currentLightState == currentState){
return false
}else{
currentLightState = currentState
when(currentState){
TrafficLightEnum.RED->{
redLightRoundNum++
return redLightRoundNum > greenLightRoundNum && redLightRoundNum > yellowLightRoundNum
}
TrafficLightEnum.GREEN->{
greenLightRoundNum++
return greenLightRoundNum > redLightRoundNum && greenLightRoundNum > yellowLightRoundNum
}
TrafficLightEnum.YELLOW->{
yellowLightRoundNum++
return yellowLightRoundNum > redLightRoundNum && yellowLightRoundNum > greenLightRoundNum
}
TrafficLightEnum.BLACK->{
return false
}
}
}
}
/**
* 展示红绿灯预警
* @param checkLightId 0-都是默认1-红2-黄3-绿
* @param lightSource 1:云端下发2:自车感知 3:OBU
*/
override fun showTrafficLight(checkLightId: TrafficLightEnum, lightSource: DataSourceType) {
super.showTrafficLight(checkLightId, lightSource)
UiThreadHandler.post {
CallerLogger.d("$M_HMI$TAG","update checkLightId:$checkLightId, lightSource: $lightSource")
isShowLight = true
currentLightState = checkLightId
updateTrafficLightIcon(checkLightId, lightSource)
}
}
/**
* @param redNum 红灯倒计时
* @param yellowNum 黄灯倒计时
* @param greenNum 绿灯倒计时
*/
override fun changeCountdownTrafficLightNum(redNum: Int, yellowNum: Int, greenNum: Int) {
super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum)
UiThreadHandler.post {
when (currentLightState) {
TrafficLightEnum.RED -> changeCountdownRed(redNum)
TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum)
TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum)
else ->{}
}
}
}
override fun changeCountdownRed(redNum: Int) {
super.changeCountdownRed(redNum)
UiThreadHandler.post {
if (redNum > 0) {
tvLightRemain.text = redNum.toString()
} else {
disableTrafficLightCountDown()
}
}
}
override fun changeCountdownGreen(greenNum: Int) {
super.changeCountdownGreen(greenNum)
UiThreadHandler.post {
if (greenNum > 0) {
tvLightRemain.text = greenNum.toString()
} else {
disableTrafficLightCountDown()
}
}
}
override fun changeCountdownYellow(yellowNum: Int) {
super.changeCountdownYellow(yellowNum)
UiThreadHandler.post {
if (yellowNum > 0) {
tvLightRemain.text = yellowNum.toString()
} else {
disableTrafficLightCountDown()
}
}
}
/**
* 更新红绿灯icon
*
* @param lightId 0-都是默认1-红2-黄3-绿
* @param lightSource 1:云端下发2:自车感知; 3:OBU
*/
private fun updateTrafficLightIcon(lightId: TrafficLightEnum, lightSource: DataSourceType) {
if(currentSource == 0 || currentSource == 1){
return
}
if(currentSource == -1){
this@TrafficLightView.visibility = View.VISIBLE
currentSource = 2
}
when (lightId) {
TrafficLightEnum.RED -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_red_light_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_red_light_passenger))
}
}
TrafficLightEnum.YELLOW -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_yellow_light_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_yellow_light_passenger))
}
}
TrafficLightEnum.GREEN -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_green_light_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_green_light_passenger))
}
}
else -> this@TrafficLightView.visibility = GONE
}
when (lightSource) {
DataSourceType.AICLOUD -> {
tvLightSource.text = context.getString(R.string.light_source_ai_cloud)
}
DataSourceType.TELEMATIC_UNION_V2I,
DataSourceType.TELEMATIC_UNION_V2N,
DataSourceType.TELEMATIC -> {
tvLightSource.text = context.getString(R.string.light_source_perception)
}
DataSourceType.OBU -> {
tvLightSource.text = context.getString(R.string.light_source_obu)
}
else -> {
tvLightSource.visibility = GONE
}
}
}
/**
* 展示融合带有下一下二灯态的红绿灯
* @param currentState 当前灯态
* @param currentDuration 当前灯态倒计时
* @param nextState 下一灯态
* @param nextDuration 下一灯态倒计时
* @param nextTwoState 下二灯态
* @param nextTwoDuration 下二灯态倒计时
* @param lightSource 数据来源
*/
override fun showFusionTrafficLight(currentState: TrafficLightEnum, currentDuration: Int, nextState: TrafficLightEnum,
nextDuration: Int, nextTwoState: TrafficLightEnum, nextTwoDuration: Int, lightSource: DataSourceType
) {
super.showFusionTrafficLight(currentState, currentDuration, nextState, nextDuration, nextTwoState, nextTwoDuration, lightSource)
if(currentLightState == currentState && currentLightDuration == currentDuration){
return
}
currentLightDuration = currentDuration
ThreadUtils.runOnUiThread {
//如果初次获取的路口灯态倒计时时长小于1秒则返回不处理灯态进入下一轮灯态开始进行显示
if(this@TrafficLightView.visibility == View.GONE && currentDuration < 1){
return@runOnUiThread
}
//兼容融合异常数据当下一下二灯态时长均大于0时展示
if(this@TrafficLightView.visibility == View.GONE && (nextDuration == 0) || nextTwoDuration == 0){
return@runOnUiThread
}
/**
* 如果红绿灯显示过程中遇到突然灯态发生改变即当前灯态未倒计时完成灯态发生变化
* (正常情况下不会出现此情况,兼容异常状态)
* 重置灯态占比和指针指向
*/
if(previousLightStatus == TrafficLightEnum.BLACK && previousLightDuration == 0
&& currentState != TrafficLightEnum.BLACK && currentDuration != 0){
previousLightStatus = currentState
previousLightDuration = currentDuration
}else{
if((currentState != previousLightStatus && previousLightDuration >1)
|| (currentState == previousLightStatus && previousLightDuration < currentDuration)){
//灯态未倒计时到1灯态发生变化正常情况是倒计时到0考虑到可能存在的异常情况倒计时到1也算正常
returnToZero()
resetLight()
}else{
previousLightStatus = currentState
previousLightDuration = currentDuration
}
}
//如果当前红绿灯视图为隐藏状态则设置为显示状态
if(judgeRoundNum(currentState) || currentSource == 1){
//从云控基础平台信号源切换到融合感知信号源
currentSource = 0
if(this@TrafficLightView.visibility == View.GONE){
this@TrafficLightView.visibility = View.VISIBLE
CallerHmiViewControlListenerManager.invokeV2XEvent(View.VISIBLE, TAG)
CallerServicesEventManager.updateServicesNum(CallerServicesEventManager.ServiceType.LIGHT)
}
val colorList = ArrayList<TrafficLightEnum>()
val durationList = ArrayList<Int>()
colorList.add(currentState)
colorList.add(nextState)
colorList.add(nextTwoState)
if(currentDuration < 3){
durationList.add(3)
totalDuration = 3 + nextDuration + nextTwoDuration
currentAngle = 360f/totalDuration*(3-currentDuration) - 90f
}else{
durationList.add(currentDuration)
totalDuration = currentDuration + nextDuration + nextTwoDuration
currentAngle = -90f
}
durationList.add(nextDuration)
durationList.add(nextTwoDuration)
//没轮灯态绘制一次灯态时长比例
pcvLightProportion.updateProportion(durationList,colorList)
}else{
if(currentAngle < 360f){
currentAngle += 360f/totalDuration
}
}
//根据当前灯态设置转盘、刻度、指针背景
when(currentState){
TrafficLightEnum.GREEN -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_green_light_pointer_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_green_light_pointer_passenger))
}
}
TrafficLightEnum.YELLOW -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_yellow_light_pointer_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_yellow_light_pointer_passenger))
}
}
else -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_red_light_pointer_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_red_light_pointer_passenger))
}
}
}
if(ivLightStatus.visibility != View.VISIBLE){
ivLightStatus.visibility = View.VISIBLE
}
if(pcvLightProportion.visibility != View.VISIBLE){
pcvLightProportion.visibility = View.VISIBLE
}
if(tvLightSource.visibility == View.VISIBLE){
tvLightSource.visibility = View.INVISIBLE
}
if(tvLightRemain.visibility != View.VISIBLE){
tvLightRemain.visibility = View.VISIBLE
}
//更新当前灯态倒计时时间
if(currentDuration>0){
tvLightRemain.text = currentDuration.toString()
}else{
tvLightRemain.text = "0"
}
//更新指针指向
val pointerLayoutParams = ivLightStatus.layoutParams as LayoutParams
pointerLayoutParams.circleAngle = currentAngle
ivLightStatus.rotation = currentAngle
ivLightStatus.layoutParams = pointerLayoutParams
}
}
/**
* 展示云控基础平台数据红绿灯
* @param currentState 当前灯态
* @param currentDuration 当前灯态倒计时
* @param nextState 下一灯态
* @param nextDuration 下一灯态倒计时
*/
override fun showCloudTrafficLight(currentState: TrafficLightEnum, currentDuration: Int,
nextState: TrafficLightEnum, nextDuration: Int) {
super.showCloudTrafficLight(currentState, currentDuration, nextState, nextDuration)
currentSource = 1
if(currentLightState == currentState && currentLightDuration == currentDuration){
return
}
currentLightDuration = currentDuration
ThreadUtils.runOnUiThread{
//如果初次获取的路口灯态倒计时时长小于1秒则返回不处理灯态进入下一轮灯态开始进行显示
if(this@TrafficLightView.visibility == View.GONE && currentDuration < 1){
return@runOnUiThread
}
//如果当前红绿灯视图为隐藏状态则设置为显示状态
if(judgeRoundNum(currentState)){
if(this@TrafficLightView.visibility == View.GONE){
this@TrafficLightView.visibility = View.VISIBLE
CallerHmiViewControlListenerManager.invokeV2XEvent(View.VISIBLE, TAG)
CallerServicesEventManager.updateServicesNum(CallerServicesEventManager.ServiceType.LIGHT)
}
val colorList = ArrayList<TrafficLightEnum>()
val durationList = ArrayList<Int>()
colorList.add(currentState)
colorList.add(nextState)
if(currentDuration < 3){
durationList.add(3)
totalDuration = 3 + nextDuration
currentAngle = 360f/totalDuration*(3-currentDuration) - 90f
}else{
durationList.add(currentDuration)
totalDuration = currentDuration + nextDuration
currentAngle = -90f
}
durationList.add(nextDuration)
//没轮灯态绘制一次灯态时长比例
pcvLightProportion.updateProportion(durationList,colorList)
}else{
if(currentAngle < 360f){
currentAngle += 360f/totalDuration
}
}
//根据当前灯态设置转盘、刻度、指针背景
when(currentState){
TrafficLightEnum.GREEN -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_green_light_pointer_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_green_light_pointer_passenger))
}
}
TrafficLightEnum.YELLOW -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_yellow_light_pointer_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_yellow_light_pointer_passenger))
}
}
else -> {
if(user == 0){
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_red_light_pointer_driver))
}else{
ivLightStatus.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.icon_red_light_pointer_passenger))
}
}
}
if(ivLightStatus.visibility != View.VISIBLE){
ivLightStatus.visibility = View.VISIBLE
}
if(pcvLightProportion.visibility != View.VISIBLE){
pcvLightProportion.visibility = View.VISIBLE
}
if(tvLightSource.visibility == View.VISIBLE){
tvLightSource.visibility = View.INVISIBLE
}
if(tvLightRemain.visibility != View.VISIBLE){
tvLightRemain.visibility = View.VISIBLE
}
//更新当前灯态倒计时时间
if(currentDuration>0){
tvLightRemain.text = currentDuration.toString()
}else{
tvLightRemain.text = "0"
}
//更新指针指向
val pointerLayoutParams = ivLightStatus.layoutParams as LayoutParams
pointerLayoutParams.circleAngle = currentAngle
ivLightStatus.rotation = currentAngle
ivLightStatus.layoutParams = pointerLayoutParams
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
CallerTrafficLightListenerManager.removeListener(TAG)
}
override fun onVisibilityChanged(changedView: View, visibility: Int) {
super.onVisibilityChanged(changedView, visibility)
if(visibility == View.VISIBLE && isShowLight){
CallerServicesEventManager.updateServicesNum(CallerServicesEventManager.ServiceType.LIGHT)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/dp_295"
android:layout_height="@dimen/dp_178"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/bg_traffic_light_driver">
<ImageView
android:id="@+id/ivLightStatus"
android:layout_width="@dimen/dp_140"
android:layout_height="@dimen/dp_140"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginStart="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_15"
android:contentDescription="@string/common_traffic_light_status"
/>
<com.mogo.eagle.core.function.hmi.ui.widget.ProportionChartTwoView
android:id="@+id/pcvLightProportion"
android:layout_width="@dimen/dp_125"
android:layout_height="@dimen/dp_125"
app:layout_constraintTop_toTopOf="@id/ivLightStatus"
app:layout_constraintBottom_toBottomOf="@id/ivLightStatus"
app:layout_constraintLeft_toLeftOf="@id/ivLightStatus"
app:layout_constraintRight_toRightOf="@id/ivLightStatus"
/>
<com.mogo.eagle.core.function.hmi.ui.widget.TypefaceTextView
android:id="@+id/tvLightRemain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/ivLightStatus"
app:layout_constraintBottom_toBottomOf="@id/ivLightStatus"
app:layout_constraintLeft_toRightOf="@id/ivLightStatus"
app:layout_constraintRight_toRightOf="parent"
android:textColor="@color/white"
android:textSize="@dimen/sp_80"
app:textType="DS_DIGIB_2"
android:layout_marginEnd="@dimen/dp_40"
/>
<TextView
android:id="@+id/tvLightSource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/tvLightRemain"
app:layout_constraintBottom_toBottomOf="@id/tvLightRemain"
app:layout_constraintLeft_toLeftOf="@id/tvLightRemain"
app:layout_constraintRight_toRightOf="@id/tvLightRemain"
android:textColor="@color/white"
android:textSize="@dimen/sp_40"
android:textStyle="bold"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/dp_192"
android:layout_height="@dimen/dp_122"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/bg_traffic_light_passenger">
<ImageView
android:id="@+id/ivLightStatus"
android:layout_width="@dimen/dp_90"
android:layout_height="@dimen/dp_90"
android:src="@drawable/icon_green_light_passenger"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginStart="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_10"
android:contentDescription="@string/common_traffic_light_status"
/>
<com.mogo.eagle.core.function.hmi.ui.widget.ProportionChartTwoView
android:id="@+id/pcvLightProportion"
android:layout_width="@dimen/dp_76"
android:layout_height="@dimen/dp_76"
app:layout_constraintTop_toTopOf="@id/ivLightStatus"
app:layout_constraintBottom_toBottomOf="@id/ivLightStatus"
app:layout_constraintLeft_toLeftOf="@id/ivLightStatus"
app:layout_constraintRight_toRightOf="@id/ivLightStatus"
app:chartRingWidth="@dimen/dp_3"
/>
<com.mogo.eagle.core.function.hmi.ui.widget.TypefaceTextView
android:id="@+id/tvLightRemain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/ivLightStatus"
app:layout_constraintBottom_toBottomOf="@id/ivLightStatus"
app:layout_constraintLeft_toRightOf="@id/ivLightStatus"
app:layout_constraintRight_toRightOf="parent"
android:textColor="@color/white"
android:textSize="@dimen/sp_50"
app:textType="DS_DIGIB_2"
android:layout_marginEnd="@dimen/dp_40"
/>
<TextView
android:id="@+id/tvLightSource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/tvLightRemain"
app:layout_constraintBottom_toBottomOf="@id/tvLightRemain"
app:layout_constraintLeft_toLeftOf="@id/tvLightRemain"
app:layout_constraintRight_toRightOf="@id/tvLightRemain"
android:textColor="@color/white"
android:textSize="@dimen/sp_26"
android:textStyle="bold"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -123,6 +123,10 @@
<attr name="ringWidth" format="reference|dimension"/>
</declare-styleable>
<declare-styleable name="ProportionChartTwoView">
<attr name="chartRingWidth" format="reference|dimension"/>
</declare-styleable>
<declare-styleable name="FusionTrafficLightView">
<attr name="fusionLightUser">
<enum name="driver" value="0"/>
@@ -131,6 +135,13 @@
</attr>
</declare-styleable>
<declare-styleable name="TrafficLightView">
<attr name="lightUser">
<enum name="driver" value="0"/>
<enum name="passenger" value="1"/>
</attr>
</declare-styleable>
<declare-styleable name="TrafficLightPromptView">
<attr name="promptUser">
<enum name="driver" value="0"/>

View File

@@ -107,13 +107,13 @@
<string name="traffic_light_status">红绿灯灯态</string>
<!--红绿灯数据来源-->
<string name="light_source_ai_cloud">云端下发</string>
<string name="light_source_ai_cloud">云端</string>
<string name="light_source_driver_ai_cloud">云\n端</string>
<string name="light_source_perception">自车感知</string>
<string name="light_source_perception">自车</string>
<string name="light_source_driver_perception">自\n车</string>
<string name="light_source_perception_v2i">融合V2I</string>
<string name="light_source_perception_v2n">融合V2N</string>
<string name="light_source_obu">\u2000OBU\u2000</string>
<string name="light_source_obu">OBU</string>
<string name="light_source_driver_obu">O\nB\nU</string>
<string name="parallel_drive">远程代驾</string>
<string name="parallel_drive_requesting">请求中...</string>
@@ -296,4 +296,6 @@
<string name="disk_not_enough_space">剩余空间不足</string>
<string name="date_cannot_copy">所选日期无法拷贝</string>
<string name="common_traffic_light_status">红绿灯灯态背景</string>
</resources>