Commit cdfc3702 authored by p x's avatar p x
Browse files

删除16jinzhi 几西裤

parent 99964718
...@@ -42,6 +42,4 @@ rootProject.name = "MapMultiEngine" ...@@ -42,6 +42,4 @@ rootProject.name = "MapMultiEngine"
include(":app") include(":app")
include(":mapapi") include(":mapapi")
include(":maplibs")//存放三方地图aar包 include(":maplibs")//存放三方地图aar包
//include(":sixteen_parse")//16进制解析库 include(":fusedlibrary")//融合库
//include(":mypubdep") //公共应用
include(":fusedlibrary")
/build
\ No newline at end of file
plugins {
alias(libs.plugins.android.library)
// alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.sixteen.parse"
compileSdk = 35
defaultConfig {
minSdk = 29
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
isShrinkResources = false
consumerProguardFiles("proguard-rules.pro")
// proguardFiles(
// getDefaultProguardFile("proguard-android-optimize.txt"),
// "proguard-rules.pro"
// )
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
//kotlin 注解库
implementation("org.jetbrains.kotlin:kotlin-reflect:2.0.0")
//Netty是一个异步事件驱动的网络应用框架
api("io.netty:netty-all:4.1.92.Final")
//事件分发
api("org.greenrobot:eventbus:3.3.1")
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-keep class com.sixteen.parse.normal.** { *; }
#-keep class com.sixteen.parse.assist_88.** { *; }
#-keep class com.sixteen.parse.vehcloud_state_82.** { *; }
#-keep class com.sixteen.parse.cloud2veh_advice_85.** { *; }
#-keep class com.sixteen.parse.selfdefine_810.** { *; }
# -- 解析Bean
#-keep class com.sixteen.parse.assist_88.** { *; }
#-keep class com.sixteen.parse.cloud2veh_advice_85.** { *; }
#-keep class com.sixteen.parse.vehcloud_state_82.** { *; }
#-keep class com.sixteen.parse.selfdefine_810.** { *; }
-keep class com.sixteen.parse.** { *; }
# 保留 Netty 核心类
-keep class io.netty.** { *; }
-keepclasseswithmembers class io.netty.** {
*;
}
-keepnames class io.netty.** { *; }
-dontwarn io.netty.**
\ No newline at end of file
package com.sixteen.parse
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.sixteen.parse.test", appContext.packageName)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
\ No newline at end of file
package com.sixteen.parse;
public class MessageHeadInfo {
}
package com.sixteen.parse;
import com.sixteen.parse.annotates.FieldDef;
import com.sixteen.parse.annotates.OffsetDef;
import com.sixteen.parse.annotates.Order;
import com.sixteen.parse.annotates.RefNumFlag;
import com.sixteen.parse.genHex.MsgHeadInfo;
import com.sixteen.parse.genHex.Position2DT;
import com.sixteen.parse.genHex.PositionT;
import com.sixteen.parse.genHex.VehInfo;
import com.sixteen.parse.genHex.VehMsg;
import com.sixteen.parse.genHex.VehMsgBody;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import io.netty.buffer.ByteBufUtil;
/**
* 完整的VehicleMessage转16进制字符串工具类
* 包含:MessageHeadInfo + VehicleMessageBody 完整序列化
*/
public class VehicleMessageHexSerializer {
// 全局字节序:统一使用大端(BIG_ENDIAN),可按需改为小端LITTLE_ENDIAN
private static final ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
/**
* @param speed 速度 km/h
* @param longitude
* @param latitude
* @param evel 高程(米)
* @param head 航向角
* @return 返回8.2字节数组
*/
public static byte[] take8_2Bytes(short speed, double longitude, double latitude, double evel, float head, String vehicleId) throws Exception {
// 1. 构建完整的VehicleMessage对象
VehMsg message = new VehMsg();
// 1.1 构建消息头(MessageHeadInfo)
MsgHeadInfo headInfo = new MsgHeadInfo();
headInfo.setFlag((byte) 0xF2); // 协议版本
headInfo.setBodyLenth((int) 74);
headInfo.setDataType((byte) 0x15); // 消息类型8.2
headInfo.setVersion((byte) 0x01); //版本号
headInfo.setTimestamp(System.currentTimeMillis());
headInfo.setControlContent((byte) 0x01);
message.setMsgHeadInfo(headInfo);
// 1.2 构建消息体
VehMsgBody body = new VehMsgBody();
// 1.2.1 车辆基础信息 VehInfo
VehInfo vehInfo = new VehInfo();
vehInfo.setVehicleId(vehicleId);
vehInfo.setTimestampGNSS(System.currentTimeMillis()); // 车辆ID(8字节)
vehInfo.setVelocityGNSS(speed); //传进来是千米/时)
PositionT position = new PositionT(); //位置
position.setLongitude(longitude + 180);
position.setLatitude(latitude + 90);
position.setElevation(evel + 500); //传进来是米
vehInfo.setPosition(position);
vehInfo.setHeading((int) (head * 10000));
vehInfo.setVelocity(speed);
Position2DT destLocation = new Position2DT();//目的地
destLocation.setLongitude(180);
destLocation.setLatitude(90);
vehInfo.setDestLocation(destLocation);
body.setVehInfo(vehInfo);
message.setVehMsgBody(body);
return serialize(message);
}
/**
* 对外核心方法:将完整的VehicleMessage转为16进制字符串
*
* @param message 待序列化的完整车辆消息对象
* @return 大写16进制字符串
* @throws Exception 反射/序列化异常
*/
private static byte[] serialize(VehMsg message) throws Exception {
if (message == null) {
throw new IllegalArgumentException("VehicleMessage 不能为空");
}
// 预分配足够的字节缓冲区(可根据实际业务调整大小)
ByteBuffer buffer = ByteBuffer.allocate(512);
buffer.order(BYTE_ORDER);
// 第一步:序列化消息头(MessageHeadInfo)- Order=0,优先级最高
serializeField(buffer, message.getMsgHeadInfo(), MsgHeadInfo.class);
// 第二步:序列化消息体(VehicleMessageBody)- Order=1
int bodyStartPos = buffer.position(); // 序列化前的位置(消息体起始位置)
serializeField(buffer, message.getVehMsgBody(), VehMsgBody.class);
int bodyEndPos = buffer.position(); // 序列化后的位置(消息体结束位置)
int msgBodyLength = bodyEndPos - bodyStartPos;
buffer.putInt(1, msgBodyLength);
// 切换为读模式,截取有效字节(避免空字节)
buffer.flip();
byte[] validBytes = new byte[buffer.remaining()];
buffer.get(validBytes);
String hexStr = ByteBufUtil.hexDump(validBytes);
System.out.println("完整VehicleMessage 16进制字符串:");
System.out.println(hexStr);
return validBytes;
// return bytesToHex(validBytes);
}
/**
* 通用递归序列化方法:支持基本类型、自定义对象、List集合
* 复用你原有的VehicleMessageBody序列化逻辑,统一处理所有字段
*/
private static void serializeField(ByteBuffer buffer, Object fieldValue, Class<?> fieldClass) throws Exception {
if (fieldValue == null) {
return;
}
// 1. 处理基本类型/包装类型(short/int/long/byte/float/double等)
if (isBasicType(fieldClass)) {
serializeBasicType(buffer, fieldValue);
return;
}
// 2. 处理List集合(适配@RefNumFlag注解,如多轮速、多传感器数据)
/* if (List.class.isAssignableFrom(fieldClass)) {
List<?> list = (List<?>) fieldValue;
for (Object item : list) {
if (item != null) {
serializeField(buffer, item, item.getClass());
}
}
return;
}*/
// 3. 处理自定义对象(按@Order注解升序排序字段)
Field[] fields = fieldClass.getDeclaredFields();
java.util.Arrays.sort(fields, (f1, f2) -> {
Order o1 = f1.getAnnotation(Order.class);
Order o2 = f2.getAnnotation(Order.class);
int order1 = o1 == null ? Integer.MAX_VALUE : o1.value();
int order2 = o2 == null ? Integer.MAX_VALUE : o2.value();
return Integer.compare(order1, order2);
});
// 遍历排序后的字段,递归序列化
for (Field field : fields) {
field.setAccessible(true);
Object value = field.get(fieldValue);
if (value == null) {
continue;
}
// 解析各类注解并处理字段
OffsetDef offsetDef = field.getAnnotation(OffsetDef.class);
FieldDef fieldDef = field.getAnnotation(FieldDef.class);
RefNumFlag refNumFlag = field.getAnnotation(RefNumFlag.class);
// 处理@OffsetDef:数值偏移(如0.1km、0.01m/s等单位转换)
Object actualValue = handleOffsetDef(value, offsetDef, fieldDef);
// 处理@FieldDef:固定长度/字节数组类型(如设备ID、时间戳)
if (fieldDef != null) {
serializeFieldDef(buffer, actualValue, fieldDef);
continue;
}
// 处理@RefNumFlag:基于其他字段的集合(已在List分支处理,此处跳过)
if (refNumFlag != null) {
continue;
}
// 递归序列化嵌套对象(如VehicleInfo/Position等)
serializeField(buffer, actualValue, field.getType());
}
}
/**
* 处理@OffsetDef注解:还原原始字节值(实际值 / 偏移量)
*/
private static Object handleOffsetDef(Object value, OffsetDef offsetDef, FieldDef fieldDef) {
if (offsetDef == null || value == null) {
return value;
}
double offset = offsetDef.value();
if (offset == 0) {
return value;
}
String type = "";
if (fieldDef != null) {
type = fieldDef.type();
}
// 按数据类型处理偏移转换
if (value instanceof Long) {
return (long) ((Long) value / offset);
} else if (value instanceof Integer) {
return (int) ((Integer) value / offset);
} else if (value instanceof Short) {
return (short) ((Short) value / offset);
} else if (value instanceof Double) {
if (type.equals("Position")) {
return (long) ((Double) value / offset);
}
return ((Double) value / offset);
} else if (value instanceof Float) {
return (float) ((Float) value / offset);
}
return value;
}
/**
* 处理@FieldDef注解:固定长度字节数组/特殊类型(TIMESTAMP/BYTE)
*/
private static void serializeFieldDef(ByteBuffer buffer, Object value, FieldDef fieldDef) throws Exception {
String type = fieldDef.type();
int length = fieldDef.length();
// 处理BYTE类型:固定长度字节数组(如vehicleId固定8字节)
if ("BYTE".equals(type)) {
byte[] bytes;
if (value instanceof String) {
// 1. 将字符串转为UTF-8字节数组
bytes = ((String) value).getBytes("UTF-8");
} else if (value instanceof Long) {
bytes = longToBytes((Long) value);
} else {
bytes = value.toString().getBytes("UTF-8");
}
// 固定长度填充/截断(不足补0,超出截断)
byte[] fixedBytes = new byte[length];
System.arraycopy(bytes, 0, fixedBytes, 0, Math.min(bytes.length, length));
// System.arraycopy(bytes, 0, fixedBytes, 0, length);
buffer.put(fixedBytes);
}
// 处理TIMESTAMP类型:8字节时间戳(long类型)
else if ("TIMESTAMP".equals(type)) {
buffer.putLong(((Long) value));
} else if ("Position".equals(type)) {
int intObjValue = ((Long) value).intValue();
buffer.putInt(intObjValue);
}
}
/**
* 序列化基本类型到字节缓冲区
*/
private static void serializeBasicType(ByteBuffer buffer, Object value) {
if (value instanceof Short) {
buffer.putShort((Short) value);
} else if (value instanceof Integer) {
buffer.putInt((Integer) value);
} else if (value instanceof Long) {
buffer.putLong((Long) value);
} else if (value instanceof Byte) {
buffer.put((Byte) value);
} else if (value instanceof Float) {
buffer.putFloat((Float) value);
} else if (value instanceof Double) {
buffer.putDouble((Double) value);
}
}
/**
* 判断是否为基本类型/包装类型
*/
private static boolean isBasicType(Class<?> clazz) {
return clazz.isPrimitive()
|| clazz == Short.class
|| clazz == Integer.class
|| clazz == Long.class
|| clazz == Byte.class
|| clazz == Float.class
|| clazz == Double.class
|| clazz == Boolean.class
|| clazz == Character.class;
}
/**
* 字节数组转大写16进制字符串(单个字节补前导0)
*/
private static String bytesToHex(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return "";
}
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* long转字节数组(适配BYTE类型的long字段)
*/
private static byte[] longToBytes(long value) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(BYTE_ORDER);
buffer.putLong(value);
return buffer.array();
}
// ------------------------------ 测试示例 ------------------------------
public static void main(String[] args) throws Exception {
}
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface DependencyDef {
String value() ;
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface DynamicsClassDef {
String classtype();
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface FieldDef {
int length() default 1;
String type();
boolean isArray()default false;
boolean isAutoLength() default false ;
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface NumFlag {
// 定义注解的属性
String value() default ""; // 默认值
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface OffsetDef {
double value() default 1;
int type() default 1; //1:除法 2:乘法;
int minValidLength() default 0;
int minusValue() default 0;//减多少多少
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface Order {
int value(); // 定义一个名为value的属性,用于存储序号
}
package com.sixteen.parse.annotates;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Target(ElementType.FIELD) // 注解只能用于字段(属性)
public @interface RefNumFlag {
String value();
}
package com.sixteen.parse.assist_88.dto;
public class AssistMessageBodyDto<T> {
//车辆编号
private String vehicleId;
//消息标识
private long seq;
//辅助功能类别
private short astFuncType;
//命令长度
private int dataLen;
//命令数据
private T infoData;
public short getAstFuncType() {
return astFuncType;
}
public T getInfoData() {
return infoData;
}
}
package com.sixteen.parse.assist_88.dto;
import com.sixteen.parse.annotates.OffsetDef;
import com.sixteen.parse.annotates.Order;
import com.sixteen.parse.assist_88.vo.FilterInfo;
import com.sixteen.parse.assist_88.vo.TrajectoryInfo;
import java.util.List;
/****感知目标物**/
public class PerceptualDto {
//唯一编号
@Order(1)
private String uuid;
//目标编号
@Order(2)
private int objId;
//目标类型
@Order(3)
private short type;
//目标状态
@Order(4)
private short status;
//目标长度 单位:cm
@Order(5)
@OffsetDef(value = 0.01)
private int len;
//目标宽度 单位:cm
@Order(6)
@OffsetDef(value = 0.01)
private int width;
//目标高度 单位:cm
@Order(7)
@OffsetDef(value = 0.01)
private int height;
//经度
@Order(8)
@OffsetDef(value=0.0000001,minValidLength=10)
private double longitude;
//纬度
@Order(9)
@OffsetDef(value=0.00000001,minValidLength=10)
private double latitude;
//东西向距离 单位:cm
@Order(10)
@OffsetDef(value = 0.01)
private long locEast;
//南北向距离 单位:cm
@Order(11)
@OffsetDef(value = 0.01)
private long locNorth;
//位置精度等级
@Order(12)
private short posConfidence;
//高程 单位:dm
@Order(13)
@OffsetDef(value = 0.1)
private long elevation;
//高程精度
@Order(14)
private short elevConfidence;
//速度 ,单位:0.01 m/s
@Order(15)
@OffsetDef(value = 0.036)
private float speed;
//速度精度等级
@Order(16)
private short speedConfidence;
//东西向速度 cm/s
@Order(17)
@OffsetDef(value = 0.0036)
private float speedEast;
//东西向速度精 度等级
@Order(18)
private short speedEastConfidence;
//南北向速度 cm/s,
@Order(19)
@OffsetDef(value = 0.0036)
private float speedNorth;
//南北向速度精 度等级
@Order(20)
private short speedNorthConfidence;
//航向角
@Order(21)
@OffsetDef(value=0.0001,minValidLength=7)
private double heading;
//航向精度等级
@Order(22)
private short headConfidence;
//目标纵向加速 度 单位:0.01m/
@Order(23)
@OffsetDef(value = 0.036)
private float accelVert;
//目标纵向加速 度置精度等级
@Order(24)
private short accelVertConfidence;
//目标跟踪时长 单位:毫秒
@Order(25)
private long trackedTimes;
//目标历史轨迹 数量
@Order(26)
private int histLocNum;
//目标历史轨迹 列表
@Order(27)
private List<TrajectoryInfo> histLocs;
//目标预测轨迹 数量
@Order(28)
private int predLocNum;
//目标预测轨迹 列表
@Order(29)
private List<TrajectoryInfo> predLocs;
//目标所在车道编号
@Order(30)
private short laneId;
//滤波信息的类型
@Order(31)
private short filterInfoType;
//卡尔曼滤波信息
@Order(32)
private List<FilterInfo> filterInfo;
//车牌号字节数
@Order(33)
private short plateNoLen;
//车牌号
@Order(34)
private byte[] plateNo;
//车牌类型
@Order(35)
private short plateType;
//车牌颜色
@Order(36)
private short plateColor;
//车身颜色
@Order(37)
private short vehicleColor;
}
package com.sixteen.parse.assist_88.dto;
import java.util.List;
/*** CLOUD2VEH_ASTFUNC_RSM 云端下发实时感知信息 11 **/
public class PerceptualInfoDto {
//数据源
private short source;
// 感知目标个数
private int objNum;
//感知目标数据
private List<PerceptualDto> detectionData;
public List<PerceptualDto> getDetectionData() {
return detectionData;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment