diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/ObuConstant.java b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/ObuConstant.java index 7ced90581f..d6b9513901 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/ObuConstant.java +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/ObuConstant.java @@ -35,4 +35,9 @@ public class ObuConstant { * 为vip车辆变灯提醒 */ public static final int TYPE_CHANGE_LIGHT_FOR_VIP = 116; + + /** + * 闯红灯预警 + */ + public static final int TYPE_RUSH_RED_LIGHT = 117; } diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/BaseObu.kt b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/BaseObu.kt index aea1585daf..206ff73683 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/BaseObu.kt +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/BaseObu.kt @@ -1,6 +1,6 @@ package com.zhidao.mogo.module.obu.obu -open class BaseObu : IObu { +abstract class BaseObu : IObu { protected var callback: IObuCallback? = null override fun init() { } diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/HualiObu.kt b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/HualiObu.kt index b6e108a7f4..28fd9e72e2 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/HualiObu.kt +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/HualiObu.kt @@ -1,47 +1,177 @@ package com.zhidao.mogo.module.obu.obu import com.mogo.utils.logger.Logger +import com.zhidao.mogo.module.obu.ObuConstant +import com.zhidao.mogo.module.obu.obu.bean.MogoObuEventInfo import com.zhidao.mogo.module.obu.socket.IUdpSocketCallback import com.zhidao.mogo.module.obu.socket.UdpSocketManager +import org.json.JSONObject +import java.lang.StringBuilder import kotlin.concurrent.thread +import kotlin.experimental.and +import kotlin.experimental.xor /** * 华砺智行obu 苏州演示项目用到的 * * @author tongchenfei */ -class HualiObu : BaseObu(),IUdpSocketCallback { +class HualiObu : BaseObu(), IUdpSocketCallback { private val socketManager = UdpSocketManager(this) - companion object{ + + companion object { const val TAG = "HualiObu" const val IP_ADDRESS = "172.30.31.44" const val PORT = 10005 } + override fun init() { super.init() socketManager.receiveMsgFrom(IP_ADDRESS, PORT) - socketManager.sendMsgTo("Hello ssokit", IP_ADDRESS, PORT) Logger.d(TAG, "init") - thread { - var count = 0 - while (true) { - Logger.d(TAG,"准备发送测试数据===") - socketManager.sendMsgTo("Hello ssokit===$count", IP_ADDRESS, PORT) - count++ - Thread.sleep(1000) - if (count == 1000) { - Logger.d(TAG, "测试数据结束") - break - } - } - } } override fun onMessageReceived(msg: ByteArray) { // todo 处理数据 val m = String(msg) - Logger.d(TAG, "onMessageReceived: $msg") - + Logger.d(TAG, "onMessageReceived: $m") + parseObuProtocol(msg) } + /** + * 解析obu数据 + * + * @param ori 原始数据 + */ + private fun parseObuProtocol(ori: ByteArray) { + val effectiveData = getEffectiveData(ori) + if (effectiveData != null) { + val msg = String(effectiveData) + Logger.d(TAG, "收到obu数据: \n $msg") + val json = JSONObject(msg) + val rushRedLight = json.optJSONObject("rush_redlight") + rushRedLight?.let { + // 有闯红灯告警信息,绿波车速信息 + Logger.d(TAG, "收到闯红灯告警信息: \n $it") + val glosaInfo = it.optJSONArray("glosa_info") + glosaInfo?.let { info -> + Logger.d(TAG, "收到红绿灯信息: $info") + val lastInfo = info.getJSONObject(0) + val alert = lastInfo.optInt("rush_redlight_alarm", -1) + val eventInfo = MogoObuEventInfo() + when (alert) { + 0 -> { + // 有闯红灯风险 + Logger.d(TAG,"准备预警--闯红灯") + eventInfo.mogoEventId = ObuConstant.TYPE_RUSH_RED_LIGHT + eventInfo.describe = "当前车速经过路口会闯红灯,请减速!" + callback?.onEventInfoCallback(eventInfo) + } + 1 -> { + // 没有风险,给出建议车速,绿波车速 + Logger.d(TAG,"准备预警--绿波车速") + eventInfo.mogoEventId = ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY + val optSpeed = lastInfo.optInt("advisory_speed") + eventInfo.describe = "前方路口,建议车速 $optSpeed km/h" + callback?.onEventInfoCallback(eventInfo) + } + else -> { + Logger.e(TAG,"没有有效红绿灯预警信息") + } + } + } + } + val intersectionCrash = json.optJSONObject("intersection_crash") + intersectionCrash?.let { + // 有交叉路口碰撞预警信息 + Logger.d(TAG, "收到交叉路口碰撞信息: \n $it") + val alert = it.optInt("intersection_crash_alarm", 0) + if (alert == 1) { + // 有碰撞预警 + Logger.d(TAG,"准备预警--交叉口碰撞") + val eventInfo = MogoObuEventInfo() + eventInfo.mogoEventId = ObuConstant.TYPE_CROSS_COLLISION_WARNING + callback?.onEventInfoCallback(eventInfo) + } + + } + val pedestrainInformation = json.optJSONObject("pedestrain_information") + pedestrainInformation?.let { + // 有人车冲突信息 + Logger.d(TAG, "收到人车冲突信息: \n $it") + val alert = it.optInt("pedestrian_crash_alarm", 0) + if (alert == 1) { + // 有人车冲突 + Logger.d(TAG,"准备预警--行人碰撞") + val eventInfo = MogoObuEventInfo() + eventInfo.mogoEventId = ObuConstant.TYPE_ROAD_USER_COLLISION_WARNING + } + + } + val position = json.optJSONObject("position_3d") + position?.let { + // 定位信息 + Logger.d(TAG, "收到定位信息: \n $it") + + } + + val motion = json.optJSONObject("motion") + motion?.let { + // 行驶信息 + Logger.d(TAG, "收到行驶信息: \n $it") + + } + } else { + Logger.e(TAG, "有效数据为空,无法解析") + } + } + + /** + * 从原始数据中,根据数据长度字节,取出有效数据 + * + * @param oriMsg 原始数据 + * @return 有效数据 + */ + private fun getEffectiveData(oriMsg: ByteArray): ByteArray? { + val dataLengthInfo = ByteArray(4) + System.arraycopy(oriMsg, 16, dataLengthInfo, 0, 4) + printByteArray(dataLengthInfo) + val dataLength = convertTwoUnSignInt(dataLengthInfo) + Logger.d(TAG, "解析后的长度: $dataLength") + val parseData = ByteArray(dataLength + 21) + System.arraycopy(oriMsg, 0, parseData, 0, parseData.size) + return if (isAvailable(parseData)) { + val msg = ByteArray(dataLength) + System.arraycopy(parseData, 20, msg, 0, dataLength) + msg + } else { + null + } + } + + private fun isAvailable(msg: ByteArray): Boolean { + val checkSum = msg.last() + var check = msg[0].xor(0xff.toByte()) + for (i in 1 until msg.size - 1) { + check = check.xor(msg[i]) + } + return checkSum == check + } + + private fun printByteArray(array: ByteArray) { + val arrayBuilder = StringBuilder() + array.forEach { + val res = it.toInt() and 0xff + arrayBuilder.append("0x") + if (res < 10) { + arrayBuilder.append("0") + } + arrayBuilder.append(it.toString(16)).append(", ") + } + Logger.d(TAG, arrayBuilder.toString()) + } + + private fun convertTwoUnSignInt(byteArray: ByteArray): Int = + (byteArray[0].toInt() shl 24) or (byteArray[1].toInt() and 0xFF) or (byteArray[2].toInt() shl 8) or (byteArray[3].toInt() and 0xFF) + } \ No newline at end of file diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/IObu.kt b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/IObu.kt index e0e350c9f0..7e99c1c6c5 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/IObu.kt +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/IObu.kt @@ -14,4 +14,5 @@ interface IObu { * 注册数据回调 */ fun registerObuCallback(callback: IObuCallback) + } \ No newline at end of file diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/bean/MogoObuEventInfo.kt b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/bean/MogoObuEventInfo.kt index 0ff33809eb..549ea38278 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/bean/MogoObuEventInfo.kt +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/obu/bean/MogoObuEventInfo.kt @@ -1,5 +1,6 @@ package com.zhidao.mogo.module.obu.obu.bean +import com.zhidao.mogo.module.obu.ObuConstant import com.zhidao.smartv2x.model.obu.CarEventInfo /** @@ -9,8 +10,13 @@ import com.zhidao.smartv2x.model.obu.CarEventInfo */ class MogoObuEventInfo(){ var typeCode:String? = null + set(value){ + mogoEventId = parseObuEvent(value) + field = value + } var type:String? = null var describe:String? = null + var mogoEventId:Int = 0 override fun toString(): String { return "MogoObuEventInfo(typeCode=$typeCode, type=$type, describe=$describe)" } @@ -21,4 +27,18 @@ class MogoObuEventInfo(){ this.describe = info.describe } + private fun parseObuEvent(type: String?): Int { + return when (type) { + "06" -> // 紧急制动预警 + ObuConstant.TYPE_URGENCY_COLLISION_WARNING + "13" -> // 绿波车速引导 + ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY + "39" -> // 行人碰撞预警 + ObuConstant.TYPE_ROAD_USER_COLLISION_WARNING + "vip变灯提醒" -> ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP + null -> -1 + else -> type.toInt() + } + } + } \ No newline at end of file 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 index 2929404f97..40163e0d60 100644 --- 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 @@ -18,6 +18,7 @@ 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.module.v2x.utils.TestOnLineCarUtils; import com.mogo.utils.logger.Logger; import com.zhidao.mogo.module.obu.ObuConstant; import com.zhidao.mogo.module.obu.ObuManager; @@ -31,7 +32,10 @@ import org.json.JSONObject; import java.util.Map; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + import static com.mogo.module.v2x.V2XConst.MODULE_NAME; +import static com.mogo.module.v2x.V2XServiceManager.getContext; import static com.mogo.module.v2x.scenario.scene.obu.V2XObuEventScenario.ACTION_LAUNCHER_ADAS_APP_BIZ; /** @@ -143,7 +147,7 @@ public class V2XObuManager implements IObuCallback, Handler.Callback { Logger.d(MODULE_NAME, "发送红绿灯广播: " + data); intent.putExtra("data", data); intent.putExtra("type", 2); - V2XServiceManager.getContext().sendBroadcast(intent); + getContext().sendBroadcast(intent); } catch (Exception e) { e.printStackTrace(); Logger.e(MODULE_NAME, e, "发送红绿灯广播异常=="); @@ -166,7 +170,8 @@ public class V2XObuManager implements IObuCallback, Handler.Callback { if (last == null) { last = 0L; } - int eventType = parseObuEvent(info.getTypeCode()); +// int eventType = parseObuEvent(info.getTypeCode()); + int eventType = info.getMogoEventId(); if (eventType == ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY) { // 加一个容错机制,如果已经驶过绿波车速路口,那么再收到绿波车速obu事件,就不再上报 MogoLocation currentLocation = V2XLocationListener.getInstance().getLastCarLocation(); @@ -213,7 +218,7 @@ public class V2XObuManager implements IObuCallback, Handler.Callback { entity.setTts("前方行人,注意减速"); entity.setExpireTime(30_000); entity.setAlarmContent("前方行人,注意减速"); - ADASUtils.broadcastToADAS(V2XServiceManager.getContext(), entity); + ADASUtils.broadcastToADAS(getContext(), entity); break; case ObuConstant.TYPE_CHANGE_LIGHT_FOR_VIP: // vip变灯提醒 @@ -223,6 +228,23 @@ public class V2XObuManager implements IObuCallback, Handler.Callback { messageEntity.setContent(changeLightEvent); V2XObuEventScenario.getInstance().init(messageEntity); break; + case ObuConstant.TYPE_RUSH_RED_LIGHT: + // 闯红灯预警 + V2XObuEventEntity rushRedLightEvent = new V2XObuEventEntity(); + rushRedLightEvent.setType(ObuConstant.TYPE_RUSH_RED_LIGHT); + rushRedLightEvent.setDesc(info.getDescribe()); + messageEntity.setContent(rushRedLightEvent); + V2XObuEventScenario.getInstance().init(messageEntity); + break; + case ObuConstant.TYPE_CROSS_COLLISION_WARNING: + // 交叉口碰撞预警 + V2XMessageEntity v2XMessageEntity = + TestOnLineCarUtils.getV2XScenarioCrossCrash(); + + Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION); + intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, v2XMessageEntity); + LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent); + break; default: break; } @@ -234,7 +256,7 @@ public class V2XObuManager implements IObuCallback, Handler.Callback { if (ObuConfig.useObuLocation) { MogoLocation currentLocation = new MogoLocation(); - CoordinateConverter converter = new CoordinateConverter(V2XServiceManager.getContext()); + CoordinateConverter converter = new CoordinateConverter(getContext()); converter.from(CoordinateConverter.CoordType.GPS); LatLng latLng = new LatLng(locationInfo.getLat(), locationInfo.getLon()); converter.coord(latLng); 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 index 07c48d8709..2bf04a71f1 100644 --- 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 @@ -88,6 +88,12 @@ public class V2XObuEventWindow extends FrameLayout implements IV2XWindow getV2XScenarioCrossCrash() { + try { + InputStream inputStream = V2XUtils.getApp() + .getResources() + .openRawResource(R.raw.scenario_push_cross_crash); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int len = -1; + byte[] buffer = new byte[1024]; + while ((len = inputStream.read(buffer)) != -1) { + baos.write(buffer, 0, len); + } + inputStream.close(); + + // 加载数据源 + V2XPushMessageEntity v2xRoadEventEntity = GsonUtil.objectFromJson(baos.toString(), V2XPushMessageEntity.class); + + V2XMessageEntity v2xMessageEntity = new V2XMessageEntity<>(); + // 控制类型 + v2xMessageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_ANIMATION_WARNING); + // 设置数据 + v2xMessageEntity.setContent(v2xRoadEventEntity); + // 控制展示状态 + v2xMessageEntity.setShowState(true); + return v2xMessageEntity; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + /** * 模拟 疲劳驾驶 */ diff --git a/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_rush_red_light.png b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_rush_red_light.png new file mode 100644 index 0000000000..885d5dfeb7 Binary files /dev/null and b/modules/mogo-module-v2x/src/main/res/drawable-xhdpi/v2x_icon_obu_rush_red_light.png differ diff --git a/modules/mogo-module-v2x/src/main/res/raw/scenario_push_cross_crash.json b/modules/mogo-module-v2x/src/main/res/raw/scenario_push_cross_crash.json new file mode 100644 index 0000000000..180b9688a1 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/raw/scenario_push_cross_crash.json @@ -0,0 +1,21 @@ +{ + "sceneId": "100006", + "alarmContent": "十字路口碰撞", + "expireTime": 30000, + "sceneCategory": 0, + "sceneDescription": "", + "sceneName": "", + "sceneLevel": 0, + "videoUrl": "", + "videoChannel": "C_1", + "videoSn": "ZD801B1932L00041", + "tts": "周围有路人发起顺风车", + "zoom": true, + "zoomScale": 15, + "location": { + "lat": 39.9754100000, + "lon": 116.4178276100 + }, + "userHead": "https://yycp-static-1255510688.cos.ap-beijing.myqcloud.com/defaultUserHeadImg/5.png", + "msgImgUrl": "https://upload.jianshu.io/users/upload_avatars/7663825/7c28763e-002b-4e89-8dea-5b8da210ef2c.jpg" +} \ No newline at end of file