diff --git a/.idea/misc.xml b/.idea/misc.xml index 21e99e2dc0..cd77a1f062 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a29dbc976b..b5a388511c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -250,9 +250,9 @@ dependencies { implementation rootProject.ext.dependencies.mogologlib - implementation rootProject.ext.dependencies.modulepushbase - launcherImplementation rootProject.ext.dependencies.modulepush - independentImplementation rootProject.ext.dependencies.modulepushnoop +// implementation rootProject.ext.dependencies.modulepushbase +// launcherImplementation rootProject.ext.dependencies.modulepush +// independentImplementation rootProject.ext.dependencies.modulepushnoop if (Boolean.valueOf(RELEASE)) { implementation rootProject.ext.dependencies.mogocommons diff --git a/app/src/main/java/com/mogo/launcher/MogoApplication.java b/app/src/main/java/com/mogo/launcher/MogoApplication.java index 2f96782f71..6aed57ee42 100644 --- a/app/src/main/java/com/mogo/launcher/MogoApplication.java +++ b/app/src/main/java/com/mogo/launcher/MogoApplication.java @@ -96,7 +96,7 @@ public class MogoApplication extends AbsMogoApplication { DebugConfig.setUseCustomNavi( BuildConfig.USE_CUSTOM_NAVI ); DebugConfig.setLauncher( BuildConfig.IS_LAUNCHER ); DebugConfig.setActiveAIAssistFlag( BuildConfig.AI_ASSIST_ACTIVE_STAUTS ); - DebugConfig.setUseMockObuData(false); + DebugConfig.setUseMockObuData(true); ObuConfig.useObuLocation = false; DebugConfig.setCarMachineType( BuildConfig.CAR_MACHINE_TYPE ); DebugConfig.setProductFlavor( BuildConfig.FLAVOR_product ); diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java index 6dcf23400f..3531741702 100644 --- a/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java @@ -102,6 +102,8 @@ public class V2XMessageEntity implements Serializable { int ALERT_ILLEGAL_PARK_WARNING = 1_008; // 自车求助 int ALERT_CAR_FOR_HELP = 8_000; + // obu事件 + int ALERT_OBU_EVENT = 9_000; } @IntDef(value = { @@ -115,6 +117,7 @@ public class V2XMessageEntity implements Serializable { V2XTypeEnum.ALERT_ROAD_LIVE_CAR_WARNING, V2XTypeEnum.ALERT_ILLEGAL_PARK_WARNING, V2XTypeEnum.ALERT_CAR_FOR_HELP, + V2XTypeEnum.ALERT_OBU_EVENT, }) @Target({ ElementType.PARAMETER, diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XObuEventEntity.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XObuEventEntity.java new file mode 100644 index 0000000000..802e035a42 --- /dev/null +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XObuEventEntity.java @@ -0,0 +1,35 @@ +package com.mogo.module.common.entity; + +/** + * obu事件封装 + * + * @author tongchenfei + */ +public class V2XObuEventEntity { + private int type; + private String desc; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @Override + public String toString() { + return "V2XObuEventEntity{" + + "type=" + type + + ", desc='" + desc + '\'' + + '}'; + } +} diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/MockUtil.kt b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/MockUtil.kt index aefaed0f48..67895e4ea2 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/MockUtil.kt +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/MockUtil.kt @@ -55,7 +55,7 @@ object MockUtil { carEventInfo.describe = "这个应该是随便写,反正也不用" dataCallback.showCarEventInfo(carEventInfo) } - api.windowManagerApi.addView(view, 960, 500, false) + api.windowManagerApi.addView(view, 500, 300, false) intervalMockData() } diff --git a/modules/mogo-module-v2x/build.gradle b/modules/mogo-module-v2x/build.gradle index 769d209c48..b80c5fc2de 100644 --- a/modules/mogo-module-v2x/build.gradle +++ b/modules/mogo-module-v2x/build.gradle @@ -83,10 +83,11 @@ dependencies { } annotationProcessor rootProject.ext.dependencies.aroutercompiler - testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + compileOnly project(':modules:mogo-module-obu') } apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString() diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XConst.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XConst.java index 986804044a..3dd0dc1cf6 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XConst.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XConst.java @@ -121,4 +121,8 @@ public class V2XConst { */ public static final String V2X_MARKER_GOVERNMENT = "V2X_MARKER_GOVERNMENT"; + /** + * 绿波车速marker + */ + public static final String V2X_OPTIMAL_SPEED_MARKER = "V2X_OPTIMAL_SPEED_MARKER"; } diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java index c966d01ef4..4f9fde268b 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java @@ -134,6 +134,8 @@ public class V2XModuleProvider implements intentFilter.addAction(V2XConst.BROADCAST_SCENE_HANDLER_ACTION); localBroadcastManager.registerReceiver(localReceiver, intentFilter); + // obu数据转发初始化 + V2XObuManager.getInstance().init(); } private void initData() { diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XObuManager.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XObuManager.java new file mode 100644 index 0000000000..f926bde319 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XObuManager.java @@ -0,0 +1,283 @@ +package com.mogo.module.v2x; + +import android.content.Intent; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.util.ArrayMap; + +import com.amap.api.maps.CoordinateConverter; +import com.amap.api.maps.model.LatLng; +import com.mogo.map.location.MogoLocation; +import com.mogo.module.common.entity.V2XMessageEntity; +import com.mogo.module.common.entity.V2XObuEventEntity; +import com.mogo.module.common.entity.V2XPushMessageEntity; +import com.mogo.module.v2x.listener.V2XLocationListener; +import com.mogo.module.v2x.scenario.scene.obu.V2XObuEventScenario; +import com.mogo.module.v2x.utils.ADASUtils; +import com.mogo.module.v2x.utils.DrivingDirectionUtils; +import com.mogo.module.v2x.utils.ObuConfig; +import com.mogo.service.obu.IMogoObuDataChangedListener; +import com.mogo.utils.logger.Logger; +import com.zhidao.mogo.module.obu.ObuConstant; +import com.zhidao.smartv2x.model.obu.CarEventInfo; +import com.zhidao.smartv2x.model.obu.CarLocationInfo; +import com.zhidao.smartv2x.model.obu.TrafficLightInfo; + +import org.json.JSONObject; + +import java.util.Map; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; +import static com.mogo.module.v2x.scenario.scene.obu.V2XObuEventScenario.ACTION_LAUNCHER_ADAS_APP_BIZ; + +/** + * obu数据管理类封装 + * + * @author tongchenfei + */ +public class V2XObuManager implements IMogoObuDataChangedListener, Handler.Callback { + private static final String TAG = V2XObuManager.class.getSimpleName(); + + private static final long DEFAULT_INTERVAL_TIME = 30_000L; + + private V2XObuManager() { + } + + private volatile static V2XObuManager instance = null; + + public static V2XObuManager getInstance() { + if (instance == null) { + synchronized (V2XObuManager.class) { + if (instance == null) { + instance = new V2XObuManager(); + } + } + } + return instance; + } + + private static final int MSG_HIDE_TRAFFIC_LIGHT = 1001; + private static final long DEFAULT_HIDE_TRAFFIC_LIGHT_DELAY = 1500L; + private Handler handler = new Handler(this); + + public void init() { + Logger.d(MODULE_NAME, "obuManager初始化--"); + V2XServiceManager.getMogoRegisterCenter().registerObuDataListener(MODULE_NAME, this); + } + + /** + * 用来处理30秒内不重复播报的情况 + */ + private Map intervalMap = new ArrayMap<>(); + + /** + * 车辆位置信息回调接口 + * + * @param info 位置信息 + */ + @Override + public void showCarLocationInfo(CarLocationInfo info) { + if (ObuConfig.useObuLocation) { + MogoLocation currentLocation = new MogoLocation(); + + CoordinateConverter converter = new CoordinateConverter(V2XServiceManager.getContext()); + converter.from(CoordinateConverter.CoordType.GPS); + LatLng latLng = new LatLng(info.lat, info.lng); + converter.coord(latLng); + LatLng convert = converter.convert(); + + currentLocation.setLatitude(convert.latitude); + currentLocation.setLongitude(convert.longitude); + currentLocation.setBearing(computeCarAngle(currentLocation)); + + V2XObuEventScenario.getInstance().updateLocation(currentLocation); + } + } + + /** + * UDP 收发消息回调接口 + * + * @param info 消息回调 + */ + @Override + public void showOtherInfo(String info) { + + } + + /** + * 交通信号灯信息回调接口 + * + * @param info 信号灯信息 + */ + @Override + public void showTrafficLightInfo(TrafficLightInfo info) { + handler.removeMessages(MSG_HIDE_TRAFFIC_LIGHT); + if (info == null) { + Logger.d("V2X_OBU_EVENT", "红绿灯数据为空==="); + sendTrafficLightStatusToAdas(CALL_ADAS_HIDE_TRAFFIC_LIGHT, null); + } else { + Logger.d("V2X_OBU_EVENT", "红绿灯数据==" + info); + handler.sendEmptyMessageDelayed(MSG_HIDE_TRAFFIC_LIGHT, DEFAULT_HIDE_TRAFFIC_LIGHT_DELAY); + sendTrafficLightStatusToAdas(CALL_ADAS_SHOW_TRAFFIC_LIGHT, info); + } + } + + /** + * 场景触发事件信息回调接口 + * + * @param info 场景触发事件信息 + */ + @Override + public void showCarEventInfo(CarEventInfo info) { + Logger.d("V2X_OBU_EVENT", "carEventInfo==" + info); + Long last = intervalMap.get(info.typeCode); + if (last == null) { + last = 0L; + } + int eventType = parseObuEvent(info.typeCode); + if (eventType == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { + // 加一个容错机制,如果已经驶过绿波车速路口,那么再收到绿波车速obu事件,就不再上报 + MogoLocation currentLocation = V2XLocationListener.getInstance().getLastCarLocation(); + double eventAngle = DrivingDirectionUtils.getDegreeOfCar2Poi( + currentLocation.getLongitude(), + currentLocation.getLatitude(), + V2XObuEventScenario.getInstance().getOptimalCrossing().getLon(), + V2XObuEventScenario.getInstance().getOptimalCrossing().getLat(), + (int) currentLocation.getBearing() + ); + if (0 > eventAngle || eventAngle > 20) { + Logger.e(MODULE_NAME, "超出绿波引导点范围,不处理此次事件===" + eventAngle); + return; + } + } + if (SystemClock.elapsedRealtime() - last > DEFAULT_INTERVAL_TIME) { + // 距离上次记录超过三十秒,继续相关逻辑,如果不超过三十秒,忽略此次事件 + intervalMap.put(info.typeCode, SystemClock.elapsedRealtime()); + V2XMessageEntity messageEntity = new V2XMessageEntity<>(); + messageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_OBU_EVENT); + switch (eventType) { + case ObuConstant + .TYPE_OPTIMAL_SPEED_ADVISORY: + // 绿波车速引导 + V2XObuEventEntity optimalEvent = new V2XObuEventEntity(); + optimalEvent.setType(ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY); + optimalEvent.setDesc(info.describe); + messageEntity.setContent(optimalEvent); + V2XObuEventScenario.getInstance().init(messageEntity); + break; + case ObuConstant.TYPE_URGENCY_COLLISION_WARNING: + // 前车紧急制动预警 + V2XObuEventEntity urgencyEvent = new V2XObuEventEntity(); + urgencyEvent.setType(ObuConstant.TYPE_URGENCY_COLLISION_WARNING); + urgencyEvent.setDesc(V2XObuEventScenario.URGENCY_COLLISION_WARN_TEXT); + messageEntity.setContent(urgencyEvent); + V2XObuEventScenario.getInstance().init(messageEntity); + break; + case ObuConstant.TYPE_ROAD_USER_COLLISION_WARNING: + // 行人预警,给adas发送广播即可 + V2XPushMessageEntity entity = new V2XPushMessageEntity(); + // 盲区行人预警的sceneId-100003 + entity.setSceneId("100003"); + entity.setTts("前方行人,注意减速"); + entity.setExpireTime(30_000); + entity.setAlarmContent("前方行人,注意减速"); + ADASUtils.broadcastToADAS(V2XServiceManager.getContext(), entity); + break; + case ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP: + // vip变灯提醒 + V2XObuEventEntity changeLightEvent = new V2XObuEventEntity(); + changeLightEvent.setType(ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP); + changeLightEvent.setDesc(info.describe); + messageEntity.setContent(changeLightEvent); + V2XObuEventScenario.getInstance().init(messageEntity); + break; + default: + break; + } + } + } + + private int parseObuEvent(String type) { + switch (type) { + case "06": + // 紧急制动预警 + return ObuConstant.TYPE_URGENCY_COLLISION_WARNING; + case "13": + // 绿波车速引导 + return ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY; + case "39": + // 行人碰撞预警 + return ObuConstant.TYPE_ROAD_USER_COLLISION_WARNING; + case "vip变灯提醒": + return ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP; + default: + return -1; + } + } + + private MogoLocation[] historyPath = new MogoLocation[2]; + + private float computeCarAngle(MogoLocation location) { + float angle = 0f; + if (historyPath[0] != null) { + historyPath[1] = historyPath[0]; + } + historyPath[0] = location; + + if (historyPath[1] != null && historyPath[0] != null) { + double carAngle = + DrivingDirectionUtils.getCarAngle( + historyPath[1].getLatitude(), historyPath[1].getLongitude(), + historyPath[0].getLatitude(), historyPath[0].getLongitude() + ); + // 这里是真实的车辆角度 + angle = (float) carAngle; + } + return angle; + } + + private static final String CALL_ADAS_SHOW_TRAFFIC_LIGHT = "2"; + private static final String CALL_ADAS_HIDE_TRAFFIC_LIGHT = "1"; + + private void sendTrafficLightStatusToAdas(String status, TrafficLightInfo trafficLightInfo) { + if (V2XObuEventScenario.getInstance().isInChangeLightForVip()) { + status = CALL_ADAS_HIDE_TRAFFIC_LIGHT; + } + try { + Intent intent = new Intent(ACTION_LAUNCHER_ADAS_APP_BIZ); + JSONObject json = new JSONObject(); + // String action "1" - 隐藏 "2" - 显示 + json.put("action", status); + if (trafficLightInfo != null) { + if (trafficLightInfo.lightStatus == null) { + json.put("lightStatus", "G"); + } else { + json.put("lightStatus", trafficLightInfo.lightStatus); + } + if (trafficLightInfo.surplusTime == null) { + json.put("surplusTime", "0"); + } else { + json.put("surplusTime", trafficLightInfo.surplusTime); + } + } + String data = json.toString(); + Logger.d(MODULE_NAME, "发送红绿灯广播: " + data); + intent.putExtra("data", data); + intent.putExtra("type", 2); + V2XServiceManager.getContext().sendBroadcast(intent); + } catch (Exception e) { + e.printStackTrace(); + Logger.e(MODULE_NAME, e, "发送红绿灯广播异常=="); + } + } + + @Override + public boolean handleMessage(Message msg) { + if (msg.what == MSG_HIDE_TRAFFIC_LIGHT) { + sendTrafficLightStatusToAdas(CALL_ADAS_HIDE_TRAFFIC_LIGHT, null); + return true; + } + return false; + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/marker/OptimalSpeedMarkerView.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/marker/OptimalSpeedMarkerView.java new file mode 100644 index 0000000000..2558d580e3 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/marker/OptimalSpeedMarkerView.java @@ -0,0 +1,43 @@ +package com.mogo.module.v2x.marker; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; + +import androidx.annotation.Nullable; + +import com.mogo.module.common.entity.MarkerShowEntity; +import com.mogo.module.service.marker.MapMarkerBaseView; +import com.mogo.module.v2x.R; + +/** + * 绿波速度引导在地图上打的marker + * + * @author tongchenfei + */ +public class OptimalSpeedMarkerView extends MapMarkerBaseView { + private String TAG = "OptimalSpeedMarkerView"; + + public OptimalSpeedMarkerView(Context context ) { + super( context ); + } + + public OptimalSpeedMarkerView(Context context, @Nullable AttributeSet attrs ) { + super( context, attrs ); + } + + public OptimalSpeedMarkerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr ) { + super( context, attrs, defStyleAttr ); + } + + @Override + protected void initView( Context context ) { + LayoutInflater.from( context ).inflate(R.layout.view_v2x_optimal_speed_marker, this ); + } + + @Override + public void updateView( MarkerShowEntity markerShowEntity ) { + } + + +} \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/OptimalSpeedMarker.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/OptimalSpeedMarker.java new file mode 100644 index 0000000000..f0b34492f8 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/OptimalSpeedMarker.java @@ -0,0 +1,41 @@ +package com.mogo.module.v2x.scenario.scene.obu; + +import com.mogo.map.MogoLatLng; +import com.mogo.map.marker.IMogoMarker; +import com.mogo.map.marker.MogoMarkerOptions; +import com.mogo.module.service.utils.ViewUtils; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.marker.OptimalSpeedMarkerView; +import com.mogo.module.v2x.scenario.view.IV2XMarker; +import com.mogo.utils.logger.Logger; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; +import static com.mogo.module.v2x.V2XConst.V2X_OPTIMAL_SPEED_MARKER; + +/** + * 绿波车速的marker + */ +class OptimalSpeedMarker implements IV2XMarker { + + private IMogoMarker optimalMarker = null; + + @Override + public void drawPOI(MogoLatLng entity) { + Logger.d(MODULE_NAME, "绘制绿波marker===" + entity); + MogoMarkerOptions optionsRipple = new MogoMarkerOptions() + .latitude(entity.getLat()) + .longitude(entity.getLon()).anchor(0.5f,0.9f).icon(ViewUtils.fromView(new OptimalSpeedMarkerView(V2XServiceManager.getContext()))); + optimalMarker = V2XServiceManager.getMarkerManager().addMarker(V2X_OPTIMAL_SPEED_MARKER, optionsRipple); + optimalMarker.setClickable(false); + } + + @Override + public void clearPOI() { + Logger.d(MODULE_NAME,"准备清除绿波marker"); + if (optimalMarker != null) { + Logger.d(MODULE_NAME, "清除绿波marker===" + optimalMarker); + optimalMarker.remove(); + optimalMarker = null; + } + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/V2XObuEventScenario.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/V2XObuEventScenario.java new file mode 100644 index 0000000000..9471a13343 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/obu/V2XObuEventScenario.java @@ -0,0 +1,382 @@ +package com.mogo.module.v2x.scenario.scene.obu; + +import android.content.Intent; +import android.graphics.Color; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + +import androidx.annotation.Nullable; + +import com.mogo.commons.voice.AIAssist; +import com.mogo.map.MogoLatLng; +import com.mogo.map.location.MogoLocation; +import com.mogo.map.overlay.IMogoPolyline; +import com.mogo.map.overlay.MogoPolylineOptions; +import com.mogo.module.common.entity.V2XMessageEntity; +import com.mogo.module.common.entity.V2XObuEventEntity; +import com.mogo.module.service.Utils; +import com.mogo.module.v2x.V2XObuManager; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.listener.V2XWindowStatusListener; +import com.mogo.module.v2x.scenario.impl.AbsV2XScenario; +import com.mogo.module.v2x.utils.DrivingDirectionUtils; +import com.mogo.utils.logger.Logger; +import com.zhidao.mogo.module.obu.ObuConstant; +import com.zhidao.smartv2x.model.obu.CarEventInfo; + +import org.json.JSONObject; + +import java.util.Arrays; +import java.util.List; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; + +/** + * obu场景界面管理 + * + * @author tongchenfei + */ +public class V2XObuEventScenario extends AbsV2XScenario implements Handler.Callback { + + public static final String URGENCY_COLLISION_WARN_TEXT = "前车急刹,注意保持安全距离!"; + private static final int MSG_CLOSE_OBU_WINDOW = 1001; + private static final int DEFAULT_EXPIRE_TIME = 20_000; + + private static final float DEFAULT_VIP_CROSSING_DISTANCE = 100F; + + /** + * 可以关闭绿波引导的距离路口的最大距离,单位是米 + */ + private static final float DEFAULT_DISTANCE_TO_CLOSE_OPTIMAL = 10F; + + private IMogoPolyline optimalLine = null; + private MogoLatLng defaultTarget = new MogoLatLng(39.969326, 116.407788); + + private MogoLatLng optimalCrossing = new MogoLatLng(40.196431,116.738011); +// private MogoLatLng vipCrossing = new MogoLatLng(40.200467,116.745498); + + + private MogoLatLng vipCrossing1 = new MogoLatLng(40.200467,116.745498); + private MogoLatLng vipCrossing2 = new MogoLatLng(40.200491,116.738535); + private List vipCrossingList = Arrays.asList(vipCrossing1, vipCrossing2); + + private V2XObuEventScenario() { + } + + private volatile static V2XObuEventScenario instance = null; + + public static V2XObuEventScenario getInstance() { + if (instance == null) { + synchronized (V2XObuEventScenario.class) { + if (instance == null) { + instance = new V2XObuEventScenario(); + instance.setV2XWindow(new V2XObuEventWindow(V2XServiceManager.getContext())); + } + } + } + return instance; + } + + private V2XMessageEntity lastMessage = null; + + private OptimalSpeedMarker optimalSpeedMarker = null; + + private Handler handler = new Handler(Looper.getMainLooper(), this); + + @Override + public void init(@Nullable V2XMessageEntity v2XMessageEntity) { + Logger.d(MODULE_NAME, "obu场景初始化: " + v2XMessageEntity); + setV2XMessageEntity(v2XMessageEntity); + if (v2XMessageEntity.getContent().getType() == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { + // 如果需要区分路口,就在这里做一下判断,给默认目标点赋值 + defaultTarget = optimalCrossing; + if (optimalSpeedMarker == null) { + optimalSpeedMarker = new OptimalSpeedMarker(); + } else { + optimalSpeedMarker.clearPOI(); + } + } else if (v2XMessageEntity.getContent().getType() == ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP) { + // vip变灯提醒 + isInChangeLightForVip = true; + V2XObuManager.getInstance().showTrafficLightInfo(null); + + if (optimalSpeedMarker == null) { + optimalSpeedMarker = new OptimalSpeedMarker(); + } else { + optimalSpeedMarker.clearPOI(); + } + } + show(); + } + + /** + * 展示场景 + *

+ * 此场景需要语音提示和弹窗 + */ + @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 { + public V2XObuEventWindow(@NonNull Context context) { + this(context,null); + } + + public V2XObuEventWindow(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs,0); + } + + public V2XObuEventWindow(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private ImageView ivTypeIcon; + private TextView tvType, tvDesc; + + private void initView(Context context){ + Logger.d(MODULE_NAME,"初始化obu场景view"); + LayoutInflater.from(context).inflate(R.layout.window_simple_obu_event_detail, this); + ivTypeIcon = findViewById(R.id.ivObuTypeIcon); + tvType = findViewById(R.id.tvObuType); + tvDesc = findViewById(R.id.tvObuDesc); + } + + /** + * 展示1/2窗口 + * + * 目前只处理如下obu事件 + * 绿波车速: {@link com.zhidao.mogo.module.obu.ObuConstant#TYPE_OPTIMAL_SPEED_ADVISORY} + * 前车急刹: {@link com.zhidao.mogo.module.obu.ObuConstant#TYPE_URGENCY_COLLISION_WARNING} + * vip车辆变灯提示(暂无回调,暂不处理) + * @param entity + */ + @Override + public void show(V2XObuEventEntity entity) { + Logger.d(MODULE_NAME, "ObuEventWindow show " + entity); + switch (entity.getType()) { + case ObuConstant + .TYPE_OPTIMAL_SPEED_ADVISORY: + // 绿波车速引导 + ivTypeIcon.setImageResource(R.drawable.v2x_icon_obu_optimal_speed); + tvDesc.setText(entity.getDesc()); + tvType.setText("车速引导"); + tvType.setBackgroundResource(R.drawable.bg_v2x_event_type_green); + break; + case ObuConstant.TYPE_URGENCY_COLLISION_WARNING: + // 前车急刹预警 + ivTypeIcon.setImageResource(R.drawable.v2x_icon_obu_urgency_collision); + tvDesc.setText(entity.getDesc()); + tvType.setText("前车急刹"); + tvType.setBackgroundResource(R.drawable.bg_v2x_event_type_read); + break; + case ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP: + // vip变灯提醒 + ivTypeIcon.setImageResource(R.drawable.v2x_icon_obu_traffic_light); + tvDesc.setText(entity.getDesc()); + tvType.setText("优先通行"); + tvType.setBackgroundResource(R.drawable.bg_v2x_event_type_green); + break; + default: + Logger.w(MODULE_NAME, "其他obu类型,暂不处理: " + entity.getType()); + break; + } + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 210); + V2XServiceManager.getMogoTopViewManager().addView(this, params,topViewStatusListener); + } + + /** + * 关闭1/2窗口 + */ + @Override + public void close() { + V2XServiceManager.getMogoTopViewManager().removeView(this); + } + + /** + * 返回窗体 + * + * @return 当前窗体 + */ + @Override + public View getView() { + return this; + } + + private V2XWindowStatusListener statusListener = null; + + /** + * 设置Window状态监听 + * + * @param listener 监听器 + */ + @Override + public void setWindowStatusListener(V2XWindowStatusListener listener) { + statusListener = listener; + } + + private IMogoTopViewStatusListener topViewStatusListener = new IMogoTopViewStatusListener() { + @Override + public void onViewAdded(View view) { + + } + + @Override + public void onViewRemoved(View view) { + if (statusListener != null) { + statusListener.onViewClose(); + } + } + + @Override + public void beforeViewAddAnim(View view) { + + } + + @Override + public void beforeViewRemoveAnim(View view) { + + } + }; + + +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/utils/ObuConfig.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/utils/ObuConfig.java new file mode 100644 index 0000000000..361af30cce --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/utils/ObuConfig.java @@ -0,0 +1,14 @@ +package com.mogo.module.v2x.utils; + +/** + * obu相关设置项 + * @author tongchenfei + */ +public class ObuConfig { + /** + * 设置是否使用obu定位信息 + * + * 此定位信息目前只用于obu计算绿波车速引导和vip变灯提醒 + */ + public static boolean useObuLocation = false; +} diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_bg_simple_obu.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_bg_simple_obu.png new file mode 100644 index 0000000000..cb30283530 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_bg_simple_obu.png differ diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_optimal_speed.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_optimal_speed.png new file mode 100644 index 0000000000..c7d9845123 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_optimal_speed.png differ diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_traffic_light.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_traffic_light.png new file mode 100644 index 0000000000..38dc68d539 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_traffic_light.png differ diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_urgency_collision.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_urgency_collision.png new file mode 100644 index 0000000000..383e8897b1 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_urgency_collision.png differ diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_obu_green_point.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_obu_green_point.png new file mode 100644 index 0000000000..6e48b03365 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_obu_green_point.png differ diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_obu_traffic_light_pop.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_obu_traffic_light_pop.png new file mode 100644 index 0000000000..5e70e5f300 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_obu_traffic_light_pop.png differ diff --git a/modules/mogo-module-v2x/src/main/res/drawable/bg_v2x_event_type_green.xml b/modules/mogo-module-v2x/src/main/res/drawable/bg_v2x_event_type_green.xml new file mode 100644 index 0000000000..1f055ae661 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/drawable/bg_v2x_event_type_green.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/layout/view_v2x_optimal_speed_marker.xml b/modules/mogo-module-v2x/src/main/res/layout/view_v2x_optimal_speed_marker.xml new file mode 100644 index 0000000000..61db0e4f33 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/view_v2x_optimal_speed_marker.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/layout/window_simple_obu_event_detail.xml b/modules/mogo-module-v2x/src/main/res/layout/window_simple_obu_event_detail.xml new file mode 100644 index 0000000000..fd50b53b9e --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/window_simple_obu_event_detail.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + \ No newline at end of file