+ * 此场景需要语音提示和弹窗 + */ + @Override + public void show() { + AIAssist.getInstance(V2XServiceManager.getContext()).speakTTSVoice(getV2XMessageEntity().getContent().getDesc()); + showWindow(); + if (handler.hasMessages(MSG_CLOSE_OBU_WINDOW)) { + handler.removeMessages(MSG_CLOSE_OBU_WINDOW); + } + handler.sendEmptyMessageDelayed(MSG_CLOSE_OBU_WINDOW, DEFAULT_EXPIRE_TIME); + } + + /** + * 展示Window + */ + @Override + public void showWindow() { + if (lastMessage != null && lastMessage.getContent().getType() == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { + Logger.d(MODULE_NAME, "上一条消息是绿波,发送隐藏广播==="); + // 上一条信息是绿波,需要隐藏上一条信息 + sendBroadcastToAdas(CALL_ADAS_HIDE_OPTIMAL); + } + + if (lastMessage != null && lastMessage.getContent().getType() == ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP) { + Logger.d(MODULE_NAME,"上一条是vip变灯,需要先把线隐藏==="); + hideLine(); + } + lastMessage = getV2XMessageEntity(); + getV2XWindow().show(getV2XMessageEntity().getContent()); + getV2XWindow().setWindowStatusListener(new V2XWindowStatusListener() { + @Override + public void onViewShow() { + + } + + @Override + public void onViewClose() { + // 只在上滑关闭topview的时候回调 + if (getV2XMessageEntity().getContent().getType() == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { + Logger.d(MODULE_NAME, "关闭绿波浮窗,通知adas=="); + sendBroadcastToAdas(CALL_ADAS_HIDE_OPTIMAL); + } else if (getV2XMessageEntity().getContent().getType() == ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP) { + Logger.d(MODULE_NAME,"关闭vip变灯浮窗,隐藏line"); + isInChangeLightForVip = false; + hideLine(); + } + lastMessage = null; + } + }); + if (getV2XMessageEntity().getContent().getType() == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { + // 给adas发送显示绿波的广播 + Logger.d(MODULE_NAME, "收到绿波时间,发送广播给adas"); + sendBroadcastToAdas(CALL_ADAS_SHOW_OPTIMAL); + } else if (getV2XMessageEntity().getContent().getType() == ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP) { + Logger.d(MODULE_NAME,"收到vip变灯,画线"); + drawLine(); + } + + } + + /** + * 关闭Window + */ + @Override + public void closeWindow() { + Logger.d(MODULE_NAME, "obu场景关闭window"); + handler.removeMessages(MSG_CLOSE_OBU_WINDOW); + getV2XWindow().close(); + // 给adas发送隐藏绿波的广播 + if (getV2XMessageEntity().getContent().getType() == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { + Logger.d(MODULE_NAME, "关闭绿波浮窗,通知adas=="); + sendBroadcastToAdas(CALL_ADAS_HIDE_OPTIMAL); + } else if (getV2XMessageEntity().getContent().getType() == ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP) { + Logger.d(MODULE_NAME,"关闭vip变灯浮窗"); + isInChangeLightForVip = false; + hideLine(); + } + lastMessage = null; + } + + /** + * 展示按钮 + */ + @Override + public void showButton() { + + } + + /** + * 关闭按钮 + */ + @Override + public void closeButton() { + + } + + /** + * 绘制POI + */ + @Override + public void drawPOI() { + if (optimalSpeedMarker != null) { + Logger.d(MODULE_NAME, "绘制obu Poi点"); + optimalSpeedMarker.drawPOI(defaultTarget); + } + } + + /** + * 清除POI + */ + @Override + public void clearPOI() { + if (optimalSpeedMarker != null) { + Logger.d(MODULE_NAME, "清除obu Poi点"); + optimalSpeedMarker.clearPOI(); + optimalSpeedMarker = null; + } + } + + /** + * 当定位发生变化时,调用此方法,在此方法中,根据当前状态判断是否需要消费此定位事件 + *
+ * 主要目的是更新绿波速度引导的划线
+ *
+ * @param currentLocation 更新后的定位信息
+ */
+ public void updateLocation(MogoLocation currentLocation) {
+ MogoLatLng currentLatLng = new MogoLatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
+ if (optimalLine != null) {
+ float distance = Utils.calculateLineDistance(defaultTarget, currentLatLng);
+ if (distance <= DEFAULT_DISTANCE_TO_CLOSE_OPTIMAL) {
+ // 目标点和自身点小于DEFAULT_DISTANCE_TO_CLOSE_OPTIMAL的时候,隐藏绿波车速
+ closeWindow();
+ } else {
+ // 线不为空就更新位置,线为空了,也就隐藏了
+ optimalLine.setPoints(Arrays.asList(currentLatLng, defaultTarget));
+ }
+ }
+
+ // 判断当前位置与vip点的距离,来判断是否触发vip通行
+ for (MogoLatLng crossing : vipCrossingList) {
+ float distance = Utils.calculateLineDistance(currentLatLng, crossing);
+ double eventAngle = DrivingDirectionUtils.getDegreeOfCar2Poi(
+ currentLocation.getLongitude(),
+ currentLocation.getLatitude(),
+ crossing.getLon(),
+ crossing.getLat(),
+ (int) currentLocation.getBearing()
+ );
+ Logger.d("V2X_OBU_VIP", "监测是否需要进行vip弹框提醒\ndistance: " + distance + "\neventAngle: " + eventAngle + "\ntarget: " + crossing + "\ncurrent: " + currentLatLng);
+ if (distance <= DEFAULT_VIP_CROSSING_DISTANCE && 0 <= eventAngle && eventAngle <= 20) {
+ //距离小于DEFAULT_VIP_CROSSING_DISTANCE,且夹角在0~20(说明在前方),则触发vip通行
+ defaultTarget = crossing;
+ handler.post(() -> {
+ CarEventInfo eventInfo = new CarEventInfo();
+ eventInfo.type = "vip变灯提醒";
+ eventInfo.typeCode = "vip变灯提醒";
+ eventInfo.describe = "将为您变灯,vip车辆可优先通行";
+ V2XObuManager.getInstance().showCarEventInfo(eventInfo);
+ });
+ break;
+ }
+ }
+ }
+
+ /**
+ * @param msg A {@link Message Message} object
+ * @return True if no further handling is desired
+ */
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (msg.what == MSG_CLOSE_OBU_WINDOW) {
+ Logger.d(MODULE_NAME, "V2X Obu scenario expire===");
+ closeWindow();
+ return true;
+ }
+ return false;
+ }
+
+ public static final String ACTION_LAUNCHER_ADAS_APP_BIZ = "com.mogo.launcher.adas.app.biz";
+ private static final String CALL_ADAS_SHOW_OPTIMAL = "2";
+ private static final String CALL_ADAS_HIDE_OPTIMAL = "1";
+
+ private void sendBroadcastToAdas(String status) {
+ if (status.equals(CALL_ADAS_SHOW_OPTIMAL)) {
+ // 给adas发送显示绿波的广播,同时自己也要开始划线
+ drawLine();
+ } else {
+ // 给adas发送隐藏绿波的广播,同时自己也需要结束划线动画
+ hideLine();
+ }
+ try {
+ Intent intent = new Intent(ACTION_LAUNCHER_ADAS_APP_BIZ);
+ JSONObject json = new JSONObject();
+ json.put("action", status);
+ String data = json.toString();
+ Logger.d(MODULE_NAME, "发送绿波广播: " + data);
+ intent.putExtra("data", data);
+ intent.putExtra("type", 1);
+ V2XServiceManager.getContext().sendBroadcast(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Logger.e(MODULE_NAME, e, "发送绿波广播异常==");
+ }
+ }
+
+ public MogoLatLng getOptimalCrossing(){
+ return optimalCrossing;
+ }
+ public float cacheZoomLevel = 16f;
+ /**
+ * 开始划线,同时添加marker,调整地图比例尺
+ */
+ private void drawLine() {
+ Logger.d(MODULE_NAME, "绘制绿波车速的线=====");
+ if (optimalLine != null) {
+ optimalLine.remove();
+ }
+ // 绘制marker
+ drawPOI();
+ // 连接线参数
+ MogoPolylineOptions options = new MogoPolylineOptions();
+
+ // 线条粗细,渐变,渐变色值
+ options.width(16).useGradient(true).colorValues(Arrays.asList(Color.parseColor("#FF1DAAA5"), Color.parseColor("#3337DED9")));
+
+ // 当前车辆位置
+ MogoLatLng carLocation = V2XServiceManager.getNavi().getCarLocation();
+ if (carLocation != null) {
+ options.add(carLocation);
+ } else {
+ options.add(V2XServiceManager.getV2XStatusManager().getLocation());
+ }
+ // 目标车辆位置
+ options.add(defaultTarget);
+
+ // 绘制线的对象
+ optimalLine = V2XServiceManager.getMogoOverlayManager().addPolyline(options);
+ cacheZoomLevel = V2XServiceManager.getMapUIController().getZoomLevel();
+ Logger.d(MODULE_NAME, "V2xObuEventScenario cacheZoomLevel==" + cacheZoomLevel);
+ V2XServiceManager.getMapUIController().changeZoom(16);
+// V2XServiceManager.getMapUIController().changeZoom(17);
+ }
+
+ /**
+ * 结束划线,同时隐藏marker
+ */
+ private void hideLine() {
+ Logger.d(MODULE_NAME, "隐藏绿波车速的线====");
+ clearPOI();
+ if (optimalLine != null) {
+ optimalLine.remove();
+ optimalLine = null;
+ }
+ V2XServiceManager.getMapUIController().changeZoom(cacheZoomLevel);
+ }
+
+ private volatile boolean isInChangeLightForVip = false;
+
+ /**
+ * 是否在显示vip通行
+ * @return true - 在显示vip通行
+ */
+ public boolean isInChangeLightForVip(){
+ return isInChangeLightForVip;
+ }
+}
diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/V2XObuEventWindow.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/V2XObuEventWindow.java
new file mode 100644
index 0000000000..07c48d8709
--- /dev/null
+++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/V2XObuEventWindow.java
@@ -0,0 +1,154 @@
+package com.mogo.module.v2x.scenario.scene.obu;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.mogo.module.common.entity.V2XObuEventEntity;
+import com.mogo.module.v2x.R;
+import com.mogo.module.v2x.V2XServiceManager;
+import com.mogo.module.v2x.listener.V2XWindowStatusListener;
+import com.mogo.module.v2x.scenario.view.IV2XWindow;
+import com.mogo.service.windowview.IMogoTopViewStatusListener;
+import com.mogo.utils.logger.Logger;
+import com.zhidao.mogo.module.obu.ObuConstant;
+
+import static com.mogo.module.v2x.V2XConst.MODULE_NAME;
+
+/**
+ * obu事件window
+ *
+ * @author tongchenfei
+ */
+public class V2XObuEventWindow extends FrameLayout implements IV2XWindow