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 4e2cb2668b..d09694b0e1 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,6 +1,9 @@ package com.zhidao.mogo.module.obu.obu import android.os.Handler +import android.os.SystemClock +import android.util.ArrayMap +import com.google.gson.JsonObject import com.mogo.commons.debug.DebugConfig import com.mogo.utils.logger.Logger import com.zhidao.mogo.module.obu.ObuConstant @@ -8,6 +11,7 @@ import com.zhidao.mogo.module.obu.obu.bean.MogoObuEventInfo import com.zhidao.mogo.module.obu.socket.IUdpSocketCallback import com.zhidao.mogo.module.obu.socket.SimpleSocketManager import com.zhidao.mogo.module.obu.socket.UdpSocketManager +import org.json.JSONException import org.json.JSONObject import java.lang.StringBuilder import kotlin.concurrent.thread @@ -20,14 +24,40 @@ import kotlin.experimental.xor * @author tongchenfei */ class HualiObu : BaseObu(), IUdpSocketCallback { -// private val socketManager = UdpSocketManager(this) + // private val socketManager = UdpSocketManager(this) private val socketManager = SimpleSocketManager(this) + private val eventCacheMap = ArrayMap() + companion object { const val TAG = "HualiObu" - const val IP_ADDRESS = "192.168.8.10" -// const val IP_ADDRESS = "192.168.43.206" + const val IP_ADDRESS = "192.168.8.99" + + // const val IP_ADDRESS = "172.31.3.18" const val PORT = 10005 + + /** + * 红绿灯信息 key + * 绿波车速和闯红灯都是根据这个key来解析json,同时,这个key也用于[eventCacheMap],用来表示闯红灯预警和绿波车速 + */ + const val KEY_RUSH_RED_LIGHT = "rush_redlight" + + /** + * 交叉路口碰撞信息 key + */ + const val KEY_INTERSECTION_CRASH = "intersection_crash" + + /** + * 行人碰撞预警 key + */ + const val KEY_PEDESTRAIN_INFORMATION = "pedestrain_information" + + /** + * 事件上报事件间隔阈值 + */ + const val EVENT_WARN_TIME_THRESHOLD = 25_000 + + } private val handler = Handler() @@ -40,10 +70,15 @@ class HualiObu : BaseObu(), IUdpSocketCallback { override fun onMessageReceived(msg: ByteArray) { // 处理数据 - val m = String(msg) - Logger.d(TAG, "onMessageReceived: $m") - printByteArray(msg) - parseObuProtocol(msg) +// val m = String(msg) +// Logger.d(TAG, "onMessageReceived: $m") +// printByteArray(msg) + try { + parseObuProtocol(msg) + } catch (e: JSONException) { + e.printStackTrace() + Logger.e(TAG,e,"obu数据解析json异常") + } } /** @@ -51,7 +86,7 @@ class HualiObu : BaseObu(), IUdpSocketCallback { * * @param ori 原始数据 */ - private fun parseObuProtocol(ori: ByteArray) { + private fun parseObuProtocol(ori: ByteArray) { val effectiveData = if (DebugConfig.isUseMockObuData()) { ori } else { @@ -59,81 +94,124 @@ class HualiObu : BaseObu(), IUdpSocketCallback { } if (effectiveData != null) { val msg = String(effectiveData) - Logger.d(TAG, "收到obu数据: \n $msg") + Logger.d(TAG, "收到obu数据====${effectiveData.size}") val json = JSONObject(msg) - val rushRedLight = json.optJSONObject("rush_redlight") + val rushRedLight = json.optJSONObject(KEY_RUSH_RED_LIGHT) rushRedLight?.let { // 有闯红灯告警信息,绿波车速信息 Logger.d(TAG, "收到闯红灯告警信息: \n $it") + val currentLineDir = it.optInt("current_lane_man") + Logger.d(TAG, "当前车道方向: $currentLineDir") 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?.let { - handler.post { - it.onEventInfoCallback(eventInfo) + var lastInfo: JSONObject? = null + for (i in 0 until info.length()) { + val j = info.optJSONObject(i) + val lineDir = j.optInt("led_direction") + val enable = j.optInt("lane_en", 0) + if (lineDir == currentLineDir && enable == 1) { + // 使能,且车道方向一致 + lastInfo = j + } + } + lastInfo?.let { lightInfo -> + if (isWarnEnable(KEY_RUSH_RED_LIGHT)) { + val alert = lightInfo.optInt("rush_redlight_alarm", -1) + val eventInfo = MogoObuEventInfo() + when (alert) { + 0 -> { + // 有闯红灯风险 + + Logger.d(TAG, "准备预警--闯红灯") + eventInfo.mogoEventId = ObuConstant.TYPE_RUSH_RED_LIGHT + eventInfo.describe = "当前车速经过路口会闯红灯,请减速!" + callback?.let { + handler.post { + it.onEventInfoCallback(eventInfo) + } + } + + } + 1 -> { + // 没有风险,给出建议车速,绿波车速 + Logger.d(TAG, "准备预警--绿波车速") + eventInfo.mogoEventId = ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY + val optSpeedInterval = lastInfo.optJSONArray("advisory_speed") + val optSpeed = lastInfo.optInt("advisory_speed") + if (optSpeedInterval == null) { + // 不是速度区间,是具体速度值 + Logger.d(TAG, "建议速度值: $optSpeed") + eventInfo.describe = "前方路口,建议车速 $optSpeed km/h" + } else { + Logger.d(TAG, "建议速度区间: ${optSpeedInterval[0]} ~ ${optSpeedInterval[1]}") + val start = optSpeedInterval[0].toString().toInt() + val end = optSpeedInterval[1].toString().toInt() + val notice = if (start == end) { + "前方路口,建议车速 $start km/h" + } else { + "前方路口,建议车速 $start 到 $end km/h" + } + eventInfo.describe = notice + } + callback?.let { + handler.post { + it.onEventInfoCallback(eventInfo) + } + } + } + else -> { + Logger.e(TAG, "没有有效红绿灯预警信息") } } - } - 1 -> { - // 没有风险,给出建议车速,绿波车速 - Logger.d(TAG, "准备预警--绿波车速") - eventInfo.mogoEventId = ObuConstant.TYPE_OPTIMAL_SPEED_ADVISORY - val optSpeed = lastInfo.optInt("advisory_speed") - eventInfo.describe = "前方路口,建议车速 $optSpeed km/h" - callback?.let { - handler.post { - it.onEventInfoCallback(eventInfo) - } - } - } - else -> { - Logger.e(TAG, "没有有效红绿灯预警信息") + } else { + Logger.d(TAG, "已经报过闯红灯预警了,待会再报") } } } } - val intersectionCrash = json.optJSONObject("intersection_crash") + val intersectionCrash = json.optJSONObject(KEY_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?.let { - handler.post { - it.onEventInfoCallback(eventInfo) + if (isWarnEnable(KEY_INTERSECTION_CRASH)) { + 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?.let { + handler.post { + it.onEventInfoCallback(eventInfo) + } } } + } else { + Logger.d(TAG, "已经提醒过交叉口碰撞了,等会儿再提醒") } + } - val pedestrainInformation = json.optJSONObject("pedestrain_information") + val pedestrainInformation = json.optJSONObject(KEY_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 - callback?.let { - handler.post { - it.onEventInfoCallback(eventInfo) + if (isWarnEnable(KEY_PEDESTRAIN_INFORMATION)) { + val alert = it.optInt("pedestrian_stauts", 0) + if (alert == 1) { + // 有人车冲突 + Logger.d(TAG, "准备预警--行人碰撞") + val eventInfo = MogoObuEventInfo() + eventInfo.mogoEventId = ObuConstant.TYPE_ROAD_USER_COLLISION_WARNING + callback?.let { + handler.post { + it.onEventInfoCallback(eventInfo) + } } } + } else { + Logger.d(TAG, "已经上报过人车冲突,过会儿再上报") } } @@ -155,6 +233,23 @@ class HualiObu : BaseObu(), IUdpSocketCallback { } } + /** + * 是否可以进行事件提醒 + * 目前是根据时间间隔阈值进行判断,[EVENT_WARN_TIME_THRESHOLD]内,同一事件只播报一次 + * + * @return true 可上报 false 忽略此事件 + */ + private fun isWarnEnable(key: String): Boolean { + val time = eventCacheMap[key] ?: 0 + val current = SystemClock.elapsedRealtime() + return if (time == 0L || current - time > EVENT_WARN_TIME_THRESHOLD) { + eventCacheMap[key] = current + true + } else { + false + } + } + /** * 从原始数据中,根据数据长度字节,取出有效数据 * @@ -164,9 +259,13 @@ class HualiObu : BaseObu(), IUdpSocketCallback { private fun getEffectiveData(oriMsg: ByteArray): ByteArray? { val dataLengthInfo = ByteArray(4) System.arraycopy(oriMsg, 16, dataLengthInfo, 0, 4) - printByteArray(dataLengthInfo) +// printByteArray(dataLengthInfo) val dataLength = convertTwoUnSignInt(dataLengthInfo) Logger.d(TAG, "解析后的长度: $dataLength") + if (dataLength > oriMsg.size) { + Logger.e(TAG, "数据长度超限制") + return null + } val parseData = ByteArray(dataLength + 21) System.arraycopy(oriMsg, 0, parseData, 0, parseData.size) return if (isAvailable(parseData)) { diff --git a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/socket/SimpleSocketManager.kt b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/socket/SimpleSocketManager.kt index 432cefdbb7..2dc2236e6c 100644 --- a/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/socket/SimpleSocketManager.kt +++ b/modules/mogo-module-obu/src/main/java/com/zhidao/mogo/module/obu/socket/SimpleSocketManager.kt @@ -42,8 +42,10 @@ class SimpleSocketManager(private val callback: IUdpSocketCallback? = null) { socket = Socket(address, port) socket?.let { Logger.d(TAG, "socket连接基本成功,准备接受数据") - // 超时时间60秒 -// it.soTimeout = 60_000 + // 超时时间10秒 +// it.soTimeout = 10_000 + +// Logger.d(TAG,"设置了超时时间") val buffer = ByteArray(2048) var result: Int do { 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 c45b19decc..38ceae2d2c 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 @@ -10,6 +10,7 @@ import android.util.ArrayMap; import com.amap.api.maps.CoordinateConverter; import com.amap.api.maps.model.LatLng; import com.mogo.commons.debug.DebugConfig; +import com.mogo.commons.voice.AIAssist; import com.mogo.map.location.MogoLocation; import com.mogo.module.common.entity.V2XMessageEntity; import com.mogo.module.common.entity.V2XObuEventEntity; @@ -241,7 +242,6 @@ public class V2XObuManager implements IObuCallback, Handler.Callback { // 交叉口碰撞预警 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); diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/animation/V2XAnimationWindow.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/animation/V2XAnimationWindow.java index bef1acd8d1..3f56755e10 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/animation/V2XAnimationWindow.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/animation/V2XAnimationWindow.java @@ -8,6 +8,7 @@ import android.view.View; import androidx.constraintlayout.widget.ConstraintLayout; +import com.mogo.commons.voice.AIAssist; import com.mogo.module.common.entity.V2XPushMessageEntity; import com.mogo.module.v2x.R; import com.mogo.module.v2x.V2XServiceManager; @@ -59,6 +60,7 @@ public class V2XAnimationWindow extends ConstraintLayout implements IV2XWindow