协议解析基本完成

This commit is contained in:
tongchenfei
2020-09-21 17:39:48 +08:00
parent a60089b632
commit 156586d63e
10 changed files with 261 additions and 23 deletions

View File

@@ -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;
}

View File

@@ -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() {
}

View File

@@ -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)
}

View File

@@ -14,4 +14,5 @@ interface IObu {
* 注册数据回调
*/
fun registerObuCallback(callback: IObuCallback)
}

View File

@@ -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()
}
}
}

View File

@@ -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<V2XPushMessageEntity> 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);

View File

@@ -88,6 +88,12 @@ public class V2XObuEventWindow extends FrameLayout implements IV2XWindow<V2XObuE
tvType.setText("优先通行");
tvType.setBackgroundResource(R.drawable.bg_v2x_event_type_green);
break;
case ObuConstant.TYPE_RUSH_RED_LIGHT:
ivTypeIcon.setImageResource(R.drawable.v2x_icon_obu_rush_red_light);
tvDesc.setText(entity.getDesc());
tvType.setText("红灯警告");
tvType.setBackgroundResource(R.drawable.bg_v2x_event_type_read);
break;
default:
Logger.w(MODULE_NAME, "其他obu类型暂不处理: " + entity.getType());
break;

View File

@@ -189,6 +189,39 @@ public class TestOnLineCarUtils {
return null;
}
/**
* 模拟H5推送场景--十字路口碰撞
*/
public static V2XMessageEntity<V2XPushMessageEntity> 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<V2XPushMessageEntity> 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;
}
/**
* 模拟 疲劳驾驶
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -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"
}