Commit 4d93012f authored by 耿迪迪's avatar 耿迪迪

jtt808 车辆定位项目初始化

parents
######################################################################
# Build Tools
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
/target/
*.class
*.jar
*.log
/logs/*
/target/*
.settings*
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>vehicle-actual-position</artifactId>
<groupId>com.zehong</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>commons</artifactId>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.15</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.zehong.commons.model;
/**
* 响应状态枚举类接口
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface APICode {
/** 状态码 */
int getCode();
/** 状态信息 */
String getMessage();
}
\ No newline at end of file
package com.zehong.commons.model;
/**
* 响应状态枚举类
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public enum APICodes implements APICode {
Success(200, ""),
UnregisteredUser(402, "未注册的用户"),
Unauthorized(403, "授权失败"),
NotPermission(404, "没有权限"),
MissingParameter(400, "缺少必要的参数"),
TypeMismatch(410, "参数格式不正确"),
InvalidParameter(411, "无效的参数"),
NotSupportedType(412, "不支持的请求类型"),
NotImplemented(413, "未实现的方法"),
OperationFailed(420, "操作失败"),
OfflineClient(4000, "离线的客户端"),
UnknownError(500, "未知错误");
private final int code;
private final String message;
APICodes(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
\ No newline at end of file
package com.zehong.commons.model;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class APIException extends RuntimeException {
private final int code;
private String message;
private String detailMessage;
public APIException(int code, String message) {
this.code = code;
this.message = message;
}
public APIException(APICode code) {
this.code = code.getCode();
this.message = code.getMessage();
}
public APIException(APICode code, String msg) {
this.code = code.getCode();
this.message = msg;
}
public APIException(APICode code, String message, String detailMessage) {
this.code = code.getCode();
this.message = message;
this.detailMessage = detailMessage;
}
public APIException(Throwable e) {
super(e);
this.code = APICodes.UnknownError.getCode();
}
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
public String getDetailMessage() {
return detailMessage;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('{');
sb.append("code:").append(code);
sb.append(",message:").append(super.getMessage());
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.commons.model;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import com.zehong.commons.util.StrUtils;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class APIResult<T> {
public static final APIResult SUCCESS = new ImmutableAPIResult<>(new APIResult<>());
public static final APIResult Unauthorized = new ImmutableAPIResult<>(new APIResult<>(APICodes.Unauthorized));
public static final APIResult NotPermission = new ImmutableAPIResult<>(new APIResult<>(APICodes.NotPermission));
public interface View {
}
@JsonView(View.class)
@Schema(description = "响应码(成功:200;客户端错误:400-499;服务端错误:500-599)")
protected int code;
@JsonView(View.class)
@Schema(description = "响应消息")
protected String msg;
@JsonView(View.class)
@Schema(description = "响应消息详情")
protected String detailMsg;
@JsonView(View.class)
@Schema(description = "响应数据")
protected T data;
public APIResult() {
this.code = APICodes.Success.getCode();
this.msg = APICodes.Success.getMessage();
}
public APIResult(Exception e) {
this.code = APICodes.UnknownError.getCode();
this.msg = e.getMessage();
this.detailMsg = StrUtils.getStackTrace(e);
}
public APIResult(APICode code, Exception e) {
this.code = code.getCode();
this.msg = code.getMessage();
this.detailMsg = e.getMessage();
}
public APIResult(APIException e) {
this.code = e.getCode();
this.msg = e.getMessage();
this.detailMsg = e.getDetailMessage();
}
public APIResult(APICode code) {
this.code = code.getCode();
this.msg = code.getMessage();
}
public APIResult(APICode code, String message) {
this.code = code.getCode();
this.msg = message;
}
public APIResult(APICode code, String message, String detailMsg) {
this.code = code.getCode();
this.msg = message;
this.detailMsg = detailMsg;
}
public APIResult(T t) {
this(APICodes.Success, t);
}
public APIResult(APICode code, T data) {
this(code);
this.data = data;
}
public APIResult(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static <T> APIResult<T> ok(T data) {
return new APIResult<>(data);
}
public boolean isSuccess() {
return APICodes.Success.getCode() == code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getDetailMsg() {
return detailMsg;
}
public void setDetailMsg(String detailMsg) {
this.detailMsg = detailMsg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static final class ImmutableAPIResult<T> extends APIResult<T> {
public ImmutableAPIResult(APIResult<T> that) {
this.code = that.code;
this.msg = that.msg;
this.detailMsg = that.detailMsg;
this.data = that.data;
}
@Override
public void setCode(int code) {
throw new UnsupportedOperationException();
}
@Override
public void setMsg(String msg) {
throw new UnsupportedOperationException();
}
@Override
public void setDetailMsg(String detailMsg) {
throw new UnsupportedOperationException();
}
@Override
public void setData(T data) {
throw new UnsupportedOperationException();
}
}
}
\ No newline at end of file
package com.zehong.commons.model;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class Result<T> {
private int state;
private T value;
private Result() {
}
public static <T> Result<T> of(int state) {
Result<T> result = new Result<>();
result.state = state;
return result;
}
public static <T> Result<T> of(T value) {
Result<T> result = new Result<>();
result.value = value;
return result;
}
public static <T> Result<T> of(T value, int state) {
Result<T> result = new Result<>();
result.value = value;
result.state = state;
return result;
}
public boolean isSuccess() {
return state == 0;
}
public int state() {
return state;
}
public T value() {
return value;
}
}
\ No newline at end of file
package com.zehong.commons.util;
/**
* 坐标系转换器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@FunctionalInterface
public interface Converter {
Converter DEFAULT = p -> p;
/** @return lngLat */
double[] convert(double... lngLat);
}
\ No newline at end of file
package com.zehong.commons.util;
/**
* WGS-84 GPS坐标(谷歌地图国外)
* GCJ-02 国测局坐标(谷歌地图国内、高德地图、腾讯地图)
* BD-09 百度坐标(百度地图)
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class CoordTransform {
/** 长半轴(赤道半径,单位米,克拉索夫斯基椭球) */
public static final double A = 6378245;
/** 第一偏心率平方 */
private static final double EE = 0.00669342162296594323;
private static final double PI = Math.PI;
private static final double X_PI = Math.PI * 3000.0 / 180.0;
public static double[] wgs84tobd09(double[] lngLat) {
return wgs84tobd09(lngLat[0], lngLat[1], new double[2]);
}
public static double[] wgs84tobd09(double lng, double lat) {
return wgs84tobd09(lng, lat, new double[2]);
}
/** WGS-84 转 BD-09 */
public static double[] wgs84tobd09(double lng, double lat, double[] result) {
wgs84togcj02(lng, lat, result);
gcj02tobd09(result[0], result[1], result);
return result;
}
public static double[] bd09towgs84(double[] lngLat) {
return bd09towgs84(lngLat[0], lngLat[1], new double[2]);
}
public static double[] bd09towgs84(double lng, double lat) {
return bd09towgs84(lng, lat, new double[2]);
}
/** BD-09 转 WGS-84 */
public static double[] bd09towgs84(double lng, double lat, double[] result) {
bd09togcj02(lng, lat, result);
gcj02towgs84(result[0], result[1], result);
return result;
}
public static double[] bd09togcj02(double[] lngLat) {
return bd09togcj02(lngLat[0], lngLat[1], new double[2]);
}
public static double[] bd09togcj02(double lng, double lat) {
return bd09togcj02(lng, lat, new double[2]);
}
/** BD-09 转 GCJ-02 */
public static double[] bd09togcj02(double lng, double lat, double[] result) {
double x = lng - 0.0065;
double y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
result[0] = z * Math.cos(theta);
result[1] = z * Math.sin(theta);
return result;
}
public static double[] gcj02tobd09(double[] lngLat) {
return gcj02tobd09(lngLat[0], lngLat[1], new double[2]);
}
public static double[] gcj02tobd09(double lng, double lat) {
return gcj02tobd09(lng, lat, new double[2]);
}
/** GCJ-02 转 BD-09 */
public static double[] gcj02tobd09(double lng, double lat, double[] result) {
double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
result[0] = z * Math.cos(theta) + 0.0065;
result[1] = z * Math.sin(theta) + 0.006;
return result;
}
public static double[] wgs84togcj02(double[] lngLat) {
return wgs84togcj02(lngLat[0], lngLat[1], new double[2]);
}
public static double[] wgs84togcj02(double lng, double lat) {
return wgs84togcj02(lng, lat, new double[2]);
}
/** WGS-84 转 GCJ-02 */
public static double[] wgs84togcj02(double lng, double lat, double[] result) {
if (inChina(lng, lat)) {
double dlat = transformlat(lng - 105.0, lat - 35.0);
double dlng = transformlng(lng - 105.0, lat - 35.0);
double radlat = lat * (PI / 180.0);
double magic = Math.sin(radlat);
magic = 1 - EE * magic * magic;
double sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((A * (1 - EE)) * PI / (magic * sqrtmagic));
dlng = (dlng * 180.0) / (A * PI / sqrtmagic * Math.cos(radlat));
result[0] = lng + dlng;
result[1] = lat + dlat;
return result;
} else {
result[0] = lng;
result[1] = lat;
return result;
}
}
public static double[] gcj02towgs84(double[] lngLat) {
return gcj02towgs84(lngLat[0], lngLat[1], new double[2]);
}
public static double[] gcj02towgs84(double lng, double lat) {
return gcj02towgs84(lng, lat, new double[2]);
}
/** GCJ-02 转 WGS-84 */
public static double[] gcj02towgs84(double lng, double lat, double[] result) {
if (inChina(lng, lat)) {
double dlat = transformlat(lng - 105.0, lat - 35.0);
double dlng = transformlng(lng - 105.0, lat - 35.0);
double radlat = lat * (PI / 180.0);
double magic = Math.sin(radlat);
magic = 1 - EE * magic * magic;
double sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((A * (1 - EE)) * PI / (magic * sqrtmagic));
dlng = (dlng * 180.0) / (A * PI / sqrtmagic * Math.cos(radlat));
result[0] = lng - dlng;
result[1] = lat - dlat;
return result;
} else {
result[0] = lng;
result[1] = lat;
return result;
}
}
private static double transformlat(double lng, double lat) {
double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(PI * 6.0 * lng) + 20.0 * Math.sin(PI * 2.0 * lng)) * (2.0 / 3.0);
ret += (20.0 * Math.sin(PI * lat) + 40.0 * Math.sin(PI / 3.0 * lat)) * (2.0 / 3.0);
ret += (160.0 * Math.sin(lat / (12.0 / PI)) + 320 * Math.sin(lat * (PI / 30.0))) * (2.0 / 3.0);
return ret;
}
private static double transformlng(double lng, double lat) {
double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(PI * 6.0 * lng) + 20.0 * Math.sin(PI * 2.0 * lng)) * (2.0 / 3.0);
ret += (20.0 * Math.sin(PI * lng) + 40.0 * Math.sin(PI / 3.0 * lng)) * (2.0 / 3.0);
ret += (150.0 * Math.sin(lng / (12.0 / PI)) + 300.0 * Math.sin(lng * (PI / 30.0))) * (2.0 / 3.0);
return ret;
}
/** 判断是否在国内,不在国内则不做偏移 */
public static boolean inChina(double lng, double lat) {
// 纬度3.86~53.55,经度73.66~135.05
return (lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
}
}
\ No newline at end of file
package com.zehong.commons.util;
/**
* 坐标系枚举
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public enum CoordType {
wgs84(
Converter.DEFAULT,
CoordTransform::wgs84togcj02,
CoordTransform::wgs84tobd09
),
gcj02(
CoordTransform::gcj02towgs84,
Converter.DEFAULT,
CoordTransform::gcj02tobd09
),
bd09(
CoordTransform::bd09towgs84,
CoordTransform::bd09togcj02,
Converter.DEFAULT
);
public final Converter WGS84;
public final Converter GCJ02;
public final Converter BD09;
public Converter to(CoordType type) {
switch (type) {
case wgs84:
return this.WGS84;
case gcj02:
return this.GCJ02;
case bd09:
return this.BD09;
default:
return Converter.DEFAULT;
}
}
CoordType(Converter WGS84, Converter GCJ02, Converter BD09) {
this.WGS84 = WGS84;
this.GCJ02 = GCJ02;
this.BD09 = BD09;
}
}
\ No newline at end of file
package com.zehong.commons.util;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
import java.time.temporal.TemporalQuery;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class DateUtils {
public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final DateTimeFormatter yyMMddHHmmss = DateTimeFormatter.ofPattern("yyMMddHHmmss");
public static final DateTimeFormatter yyyyMMdd = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR_OF_ERA, 4)
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.toFormatter();
public static final DateTimeFormatter yyMMdd = new DateTimeFormatterBuilder()
.appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, LocalDate.now().minusYears(80))
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.toFormatter();
public static final DateTimeFormatter yy = new DateTimeFormatterBuilder()
.appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, LocalDate.now().minusYears(80))
.toFormatter();
public static final ZoneOffset ZONE = ZoneOffset.systemDefault().getRules().getStandardOffset(Instant.now());
private static final TemporalQuery<LocalDate> dateQuery = TemporalQueries.localDate();
private static final TemporalQuery<LocalTime> timeQuery = TemporalQueries.localTime();
public static long currentTimeSecond() {
return System.currentTimeMillis() / 1000L;
}
public static long getMillis(LocalDateTime dateTime) {
return dateTime.toInstant(ZONE).toEpochMilli();
}
public static LocalDateTime getDateTime(Long millis) {
Instant instant = Instant.ofEpochMilli(millis);
return LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), ZONE);
}
public static LocalDateTime getDateTime(Instant instant) {
return LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), ZONE);
}
public static LocalDateTime parse(String str) {
return parse(str, yyMMddHHmmss);
}
public static LocalDateTime parse(String str, DateTimeFormatter df) {
try {
TemporalAccessor temporal = df.parse(str);
LocalDate date = temporal.query(dateQuery);
LocalTime time = temporal.query(timeQuery);
return LocalDateTime.of(date, time);
} catch (Exception e) {
return null;
}
}
}
\ No newline at end of file
package com.zehong.commons.util;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* 加密工具类
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class EncryptUtils {
private static volatile SecretKeySpec DefKey;
private static volatile IvParameterSpec DefInitVector;
private static final String MODE = "AES/CTR/NoPadding";
// private static final String MODE = "AES/CBC/PKCS5Padding";
static {
initial();
}
/**
* 初始化密钥
* @param privateKey 私钥 AES固定格式为128/192/256 bits.即:16/24/32bytes。DES固定格式为128bits,即8bytes。
* @param initVector 初始向量 AES 为16bytes. DES 为8bytes
*/
public static void initial(byte[] privateKey, byte[] initVector) {
DefKey = new SecretKeySpec(privateKey, "AES");
DefInitVector = new IvParameterSpec(initVector);
}
public static void initial() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom keyRandom = SecureRandom.getInstance("SHA1PRNG");
keyRandom.setSeed("test~!@_128".getBytes(StandardCharsets.UTF_8));
keyGenerator.init(128, keyRandom);
byte[] key = keyGenerator.generateKey().getEncoded();
SecureRandom ivRandom = SecureRandom.getInstance("SHA1PRNG");
ivRandom.setSeed("test~!@_128".getBytes(StandardCharsets.UTF_8));
keyGenerator.init(128, ivRandom);
byte[] initVector = keyGenerator.generateKey().getEncoded();
initial(key, initVector);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("初始化密钥失败", e);
}
}
public static byte[] encrypt(SecretKeySpec key, IvParameterSpec initVector, byte[] message) {
try {
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.ENCRYPT_MODE, key, initVector);
return cipher.doFinal(message);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] encrypt(String key, String initVector, byte[] message) {
return encrypt(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"), new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8)), message);
}
public static byte[] encrypt(byte[] message) {
return encrypt(DefKey, DefInitVector, message);
}
public static byte[] decrypt(SecretKeySpec key, IvParameterSpec initVector, byte[] message) {
try {
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.DECRYPT_MODE, key, initVector);
return cipher.doFinal(message);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] decrypt(String key, String initVector, byte[] message) {
return decrypt(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"), new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8)), message);
}
public static byte[] decrypt(byte[] message) {
return decrypt(DefKey, DefInitVector, message);
}
}
\ No newline at end of file
package com.zehong.commons.util;
/**
* 几何图形工具类
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class GeomUtils {
/** 长半轴(赤道半径,单位米,WGS-84) */
public static final double A = 6378137;
/** 弧度 */
public static final double RADIAN = Math.PI / 180.0;
/** 计算球面点到点距离(单位米) */
public static double distance(double lng1, double lat1, double lng2, double lat2) {
double radLat1 = lat1 * RADIAN;
double radLat2 = lat2 * RADIAN;
double a = radLat1 - radLat2;
double b = lng1 * RADIAN - lng2 * RADIAN;
double distance = A * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
distance = Math.round(distance * 10000) / 10000D;
return distance;
}
/** 计算平面点到点距离(单位米) */
public static double distance_(double x1, double y1, double x2, double y2) {
double a = x1 - x2;
double b = y1 - y2;
double distance = Math.sqrt(Math.abs((a * a) + (b * b)));
return distance * 100000;
}
/** 计算点到线距离(单位米) */
public static double distancePointToLine(double x1, double y1, double x2, double y2, double x0, double y0) {
double a = distance_(x1, y1, x2, y2);
double b = distance_(x1, y1, x0, y0);
double c = distance_(x2, y2, x0, y0);
if (c <= 0.001 || b <= 0.001) {
return 0.0;
}
if (a <= 0.001) {
return b;
}
double aa = a * a;
double bb = b * b;
double cc = c * c;
if (cc >= aa + bb) {
return b;
}
if (bb >= aa + cc) {
return c;
}
double p = (a + b + c) / 2D;
double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));
return 2D * s / a;
}
/** 判断坐标是否在矩形内 */
public static boolean inside(double x, double y, double minX, double minY, double maxX, double maxY) {
return (x >= minX && x <= maxX &&
y >= minY && y <= maxY);
}
/** 判断坐标是否在多边形内部 */
public static boolean inside(double x, double y, double[] points) {
boolean oddNodes = false;
double ret;
for (int i = 0, j = points.length - 2; i < points.length; i += 2) {
double x1 = points[i];
double y1 = points[i + 1];
double x2 = points[j];
double y2 = points[j + 1];
if ((y1 < y && y2 >= y) || (y2 < y && y1 >= y)) {
ret = x1 + (y - y1) / (y2 - y1) * (x2 - x1);
if (ret < x)
oddNodes = !oddNodes;
}
j = i;
}
return oddNodes;
}
/** 计算三个坐标角度 */
public static double getDegree(double lng1, double lat1, double lng2, double lat2, double lng3, double lat3) {
return getRadian(lng1, lat1, lng2, lat2, lng3, lat3) * (180 / Math.PI);
}
/** 计算三个坐标弧度 */
public static double getRadian(double lng1, double lat1, double lng2, double lat2, double lng3, double lat3) {
double[] p1 = ball2xyz(lng1, lat1);
double[] p2 = ball2xyz(lng2, lat2);
double[] p3 = ball2xyz(lng3, lat3);
double abx = p1[x] - p2[x];
double aby = p1[y] - p2[y];
double abz = p1[z] - p2[z];
double cbx = p3[x] - p2[x];
double cby = p3[y] - p2[y];
double cbz = p3[z] - p2[z];
double p1p2 = Math.sqrt(abx * abx + aby * aby + abz * abz);
double p2p3 = Math.sqrt(cbx * cbx + cby * cby + cbz * cbz);
double p = abx * cbx + aby * cby + abz * cbz;
double a = Math.acos(p / (p1p2 * p2p3));
double c = abx * cby - cbx * aby;
return (c > 0) ? a : -a;
}
private static final int x = 0;
private static final int y = 1;
private static final int z = 2;
private static double[] ball2xyz(double lng, double lat) {
lat = lat * RADIAN;
lng = lng * RADIAN;
double[] p = new double[3];
double t = Math.cos(lat) * 64;
p[x] = Math.cos(lng) * t;
p[y] = Math.sin(lng) * t;
p[z] = Math.sin(lat) * 64;
return p;
}
}
\ No newline at end of file
package com.zehong.commons.util;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class IOUtils {
public static final String Separator = System.lineSeparator();
public static String readIn(String classpath) {
return readIn(classpath, StandardCharsets.UTF_8);
}
public static String readIn(String classpath, Charset charset) {
return read(Thread.currentThread().getContextClassLoader().getResourceAsStream(classpath), charset);
}
public static String read(File file) {
return read(file, StandardCharsets.UTF_8);
}
public static String read(File file, Charset charset) {
try (FileInputStream is = new FileInputStream(file)) {
byte[] bytes = new byte[is.available()];
is.read(bytes);
return new String(bytes, charset);
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String read(InputStream is) {
return read(is, StandardCharsets.UTF_8);
}
public static String read(InputStream is, Charset charset) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, charset))) {
StringBuilder result = new StringBuilder(500);
String line;
while ((line = reader.readLine()) != null)
result.append(line).append(Separator);
int length = result.length();
if (length == 0)
return null;
return result.substring(0, length - Separator.length());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void write(String source, File target) {
write(source, StandardCharsets.UTF_8, target);
}
public static void write(String source, Charset charset, File target) {
byte[] bytes = source.getBytes(charset);
try (FileOutputStream os = new FileOutputStream(target)) {
os.write(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void write(InputStream source, File target) {
int buffer_size = 8192;
try (BufferedInputStream bis = new BufferedInputStream(source, buffer_size);
FileOutputStream fos = new FileOutputStream(target)) {
byte[] buffer = new byte[buffer_size];
int length;
while ((length = bis.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void copy(String sourcePath, String targetPath) {
copy(new File(sourcePath), new File(targetPath));
}
public static void copy(File source, File target) {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target);
FileChannel ifc = fis.getChannel();
FileChannel ofc = fos.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(8192);
while (ifc.read(buffer) != -1) {
buffer.flip();//切换为读模式 设置limit为position,并重置position为0
ofc.write(buffer);
buffer.clear();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void foreach(File file, Function<String, Boolean> function) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
if (Boolean.FALSE == function.apply(line))
break;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void delete(File file) {
if (file.isDirectory()) {
for (File child : file.listFiles()) {
if (child.isDirectory()) {
delete(child);
} else {
child.delete();
}
}
}
file.delete();
}
public static void close(AutoCloseable a) {
if (a != null)
try {
a.close();
} catch (Exception ignored) {
}
}
public static void close(AutoCloseable a1, AutoCloseable a2) {
close(a1);
close(a2);
}
public static void close(AutoCloseable a1, AutoCloseable a2, AutoCloseable a3) {
close(a1);
close(a2);
close(a3);
}
}
\ No newline at end of file
package com.zehong.commons.util;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class JsonUtils {
public static final ObjectMapper mapper = new ObjectMapper();
static {
SimpleModule longModule = new SimpleModule();
longModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
longModule.addSerializer(Long.class, ToStringSerializer.instance);
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateUtils.DATE_TIME_FORMATTER));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateUtils.DATE_TIME_FORMATTER));
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
timeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
timeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME));
mapper.registerModules(longModule, timeModule);
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);// 兼容高德地图api
}
public static String toJson_(Object value) throws JsonProcessingException {
return mapper.writeValueAsString(value);
}
public static String toJson(Object value) {
try {
return mapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
public static <T> T toObj_(Class<? extends T> clazz, String json) throws IOException {
return mapper.readValue(json, clazz);
}
public static <T> T toObj(Class<? extends T> clazz, String json) {
try {
return mapper.readValue(json, clazz);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static <T> T toObj_(TypeReference<T> type, String json) throws IOException {
return mapper.readValue(json, type);
}
public static <T> T toObj(TypeReference<T> type, String json) {
try {
return mapper.readValue(json, type);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
\ No newline at end of file
package com.zehong.commons.util;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
public class LogUtils {
private static final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
private static final Configuration config = ctx.getConfiguration();
private static final LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
public static void setLevel(Level level) {
loggerConfig.setLevel(level);
ctx.updateLoggers();
}
public enum Lv {
TRACE(Level.TRACE),
DEBUG(Level.DEBUG),
INFO(Level.INFO),
WARN(Level.WARN),
ERROR(Level.ERROR);
Lv(Level value) {
this.value = value;
}
public final Level value;
}
}
\ No newline at end of file
package com.zehong.commons.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class StrUtils {
public static final int[] EMPTY = new int[0];
public static final Integer[] EMPTY_ = new Integer[0];
public static int[] toInts(String str, String delimiter) {
String[] split = str.split(delimiter);
int[] result = new int[split.length];
for (int i = 0; i < split.length; i++)
result[i] = Integer.parseInt(split[i]);
return result;
}
public static double[] toDoubles(String str, String delimiter) {
String[] split = str.split(delimiter);
double[] result = new double[split.length];
for (int i = 0; i < split.length; i++)
result[i] = Double.parseDouble(split[i]);
return result;
}
public static byte[] toBytes(String str, String delimiter) {
String[] split = str.split(delimiter);
byte[] result = new byte[split.length];
for (int i = 0; i < split.length; i++)
result[i] = (byte) Integer.parseInt(split[i]);
return result;
}
public static String merge(String delimiter, Collection value) {
if (value == null || value.size() == 0)
return null;
StringBuilder result = new StringBuilder(value.size() * 5);
for (Object id : value)
result.append(id).append(delimiter);
return result.substring(0, result.length() - 1);
}
public static String merge(String delimiter, Object... value) {
if (value == null || value.length == 0)
return null;
StringBuilder result = new StringBuilder(value.length * 5);
for (Object id : value)
result.append(id).append(delimiter);
return result.substring(0, result.length() - 1);
}
public static String merge(String delimiter, int... value) {
if (value == null || value.length == 0)
return null;
StringBuilder result = new StringBuilder(value.length * 5);
for (int id : value)
result.append(id).append(delimiter);
return result.substring(0, result.length() - 1);
}
public static int[] toInts(Integer[] src) {
if (src == null || src.length == 0)
return EMPTY;
int[] dest = new int[src.length];
for (int i = 0; i < src.length; i++)
dest[i] = src[i];
return dest;
}
public static Integer[] toInts(int[] src) {
if (src == null || src.length == 0)
return EMPTY_;
Integer[] dest = new Integer[src.length];
for (int i = 0; i < src.length; i++)
dest[i] = src[i];
return dest;
}
public static Integer parseInt(String num) {
return parseInt(num, null);
}
public static Integer parseInt(String num, Integer defVal) {
if (isBlank(num))
return defVal;
try {
return Integer.parseInt(num);
} catch (NumberFormatException e) {
return defVal;
}
}
public static String toUnderline(String str) {
StringBuilder result = new StringBuilder(str.length() + 4);
char[] chars = str.toCharArray();
result.append(Character.toLowerCase(chars[0]));
for (int i = 1; i < chars.length; i++) {
char c = chars[i];
if (Character.isUpperCase(c))
result.append('_').append(Character.toLowerCase(c));
else
result.append(c);
}
return result.toString();
}
public static String subPrefix(String str, String prefix) {
if (str != null && str.startsWith(prefix))
str = str.substring(prefix.length());
return str;
}
public static Map newMap(Object... entrys) {
Map result = new HashMap((int) (entrys.length / 1.5) + 1);
for (int i = 0; i < entrys.length; )
result.put(entrys[i++], entrys[i++]);
return result;
}
public static boolean isNotBlank(String str) {
return !isBlank(str);
}
public static boolean isBlank(String str) {
return str == null || str.length() == 0 || str.trim().length() == 0;
}
public static <T> T getDefault(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
public static String leftPad(String str, int size, char ch) {
int length = str.length();
int pads = size - length;
if (pads > 0) {
char[] result = new char[size];
str.getChars(0, length, result, pads);
while (pads > 0)
result[--pads] = ch;
return new String(result);
}
return str;
}
public static int[] toArray(Collection<Integer> list) {
if (list == null || list.isEmpty())
return null;
int[] result = new int[list.size()];
int i = 0;
for (Integer e : list) {
if (e != null)
result[i++] = e;
}
return result;
}
public static Set<Integer> toSet(int... num) {
if (num == null || num.length == 0) {
return Collections.EMPTY_SET;
}
Set<Integer> result;
if (num.length <= 3) {
result = new TreeSet<>();
} else {
result = new HashSet<>(num.length << 1);
}
for (int i : num) {
result.add(i);
}
return result;
}
public static boolean isNum(String val) {
if (isBlank(val)) {
return false;
}
int sz = val.length();
for (int i = 0; i < sz; i++) {
if (!Character.isDigit(val.charAt(i))) {
return false;
}
}
return true;
}
public static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter(7680);
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
private static final char[] hexCode = "0123456789abcdef".toCharArray();
public static String bytes2Hex(byte[] bytes) {
char[] hex = new char[bytes.length << 1];
for (int j = 0, i = 0; i < bytes.length; i++) {
byte b = bytes[i];
hex[j++] = hexCode[(b >> 4) & 0xF];
hex[j++] = hexCode[(b & 0xF)];
}
return new String(hex);
}
public static byte[] hex2Bytes(String hex) {
final int len = hex.length();
if (len % 2 != 0) {
throw new IllegalArgumentException("hexBinary needs to be even-length: " + hex);
}
byte[] out = new byte[len >> 1];
for (int i = 0; i < len; i += 2) {
int h = hexToBin(hex.charAt(i));
int l = hexToBin(hex.charAt(i + 1));
if (h == -1 || l == -1) {
throw new IllegalArgumentException("contains illegal character for hexBinary: " + hex);
}
out[i >> 1] = (byte) (h * 16 + l);
}
return out;
}
public static int hexToBin(char ch) {
if ('0' <= ch && ch <= '9') {
return ch - '0';
}
if ('A' <= ch && ch <= 'F') {
return ch - ('A' - 10);
}
if ('a' <= ch && ch <= 'f') {
return ch - ('a' - 10);
}
return -1;
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>vehicle-actual-position</artifactId>
<groupId>com.zehong</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jtt808-protocol</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</dependency>
<dependency>
<groupId>io.github.yezhihao</groupId>
<artifactId>protostar</artifactId>
<version>3.0.8</version>
</dependency>
<dependency>
<groupId>io.github.yezhihao</groupId>
<artifactId>netmc</artifactId>
<version>3.0.8</version>
</dependency>
<dependency>
<groupId>com.zehong</groupId>
<artifactId>commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.zehong.protocol.basics;
import com.zehong.protocol.commons.MessageId;
import io.github.yezhihao.netmc.core.model.Message;
import io.github.yezhihao.netmc.session.Session;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.util.ToStringBuilder;
import io.netty.buffer.ByteBuf;
import java.beans.Transient;
public class JTMessage implements Message {
@Field(length = 2, desc = "消息ID")
protected int messageId;
@Field(length = 2, desc = "消息体属性")
protected int properties;
@Field(length = 1, desc = "协议版本号", version = 1)
protected int protocolVersion;
@Field(length = 6, charset = "BCD", desc = "终端手机号", version = {-1, 0})
@Field(length = 10, charset = "BCD", desc = "终端手机号", version = 1)
protected String clientId;
@Field(length = 2, desc = "流水号")
protected int serialNo;
@Field(length = 2, desc = "消息包总数")
protected Integer packageTotal;
@Field(length = 2, desc = "包序号")
protected Integer packageNo;
/** bcc校验 */
protected boolean verified = true;
protected transient Session session;
protected transient ByteBuf payload;
public JTMessage() {
}
public JTMessage(int messageId) {
this.messageId = messageId;
}
public JTMessage copyBy(JTMessage that) {
this.setClientId(that.getClientId());
this.setProtocolVersion(that.getProtocolVersion());
this.setVersion(that.isVersion());
return this;
}
public JTMessage messageId(int messageId) {
this.messageId = messageId;
return this;
}
public int getMessageId() {
return messageId;
}
public void setMessageId(int messageId) {
this.messageId = messageId;
}
public int getProperties() {
return properties;
}
public void setProperties(int properties) {
this.properties = properties;
}
public int getProtocolVersion() {
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public int getSerialNo() {
return serialNo;
}
public void setSerialNo(int serialNo) {
this.serialNo = serialNo;
}
public Integer getPackageTotal() {
if (isSubpackage())
return packageTotal;
return null;
}
public void setPackageTotal(Integer packageTotal) {
this.packageTotal = packageTotal;
}
public Integer getPackageNo() {
if (isSubpackage())
return packageNo;
return null;
}
public void setPackageNo(Integer packageNo) {
this.packageNo = packageNo;
}
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
@Transient
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
@Transient
public ByteBuf getPayload() {
return payload;
}
public void setPayload(ByteBuf payload) {
this.payload = payload;
}
public int reflectMessageId() {
if (messageId != 0)
return messageId;
return reflectMessageId(this.getClass());
}
public static int reflectMessageId(Class<?> clazz) {
io.github.yezhihao.protostar.annotation.Message messageType = clazz.getAnnotation(io.github.yezhihao.protostar.annotation.Message.class);
if (messageType != null && messageType.value().length > 0)
return messageType.value()[0];
return 0;
}
public boolean transform() {
return true;
}
public boolean noBuffer() {
return true;
}
private static final int BODY_LENGTH = 0b0000_0011_1111_1111;
private static final int ENCRYPTION = 0b00011_100_0000_0000;
private static final int SUBPACKAGE = 0b0010_0000_0000_0000;
private static final int VERSION = 0b0100_0000_0000_0000;
private static final int RESERVED = 0b1000_0000_0000_0000;
/** 消息体长度 */
public int getBodyLength() {
return this.properties & BODY_LENGTH;
}
public void setBodyLength(int bodyLength) {
this.properties ^= (properties & BODY_LENGTH);
this.properties |= bodyLength;
}
/** 加密方式 */
public int getEncryption() {
return (properties & ENCRYPTION) >> 10;
}
public void setEncryption(int encryption) {
this.properties ^= (properties & ENCRYPTION);
this.properties |= (encryption << 10);
}
/** 是否分包 */
public boolean isSubpackage() {
return (properties & SUBPACKAGE) == SUBPACKAGE;
}
public void setSubpackage(boolean subpackage) {
if (subpackage)
this.properties |= SUBPACKAGE;
else
this.properties ^= (properties & SUBPACKAGE);
}
/** 是否有版本 */
public boolean isVersion() {
return (properties & VERSION) == VERSION;
}
public void setVersion(boolean version) {
if (version)
this.properties |= VERSION;
else
this.properties ^= (properties & VERSION);
}
/** 保留位 */
public boolean isReserved() {
return (properties & RESERVED) == RESERVED;
}
public void setReserved(boolean reserved) {
if (reserved)
this.properties |= RESERVED;
else
this.properties ^= (properties & RESERVED);
}
protected StringBuilder toStringHead() {
final StringBuilder sb = new StringBuilder(768);
sb.append(MessageId.getName(messageId));
sb.append('[');
sb.append("cid=").append(clientId);
sb.append(",msgId=").append(messageId);
sb.append(",version=").append(protocolVersion);
sb.append(",serialNo=").append(serialNo);
sb.append(",props=").append(properties);
sb.append(",verified=").append(verified);
if (isSubpackage()) {
sb.append(",pt=").append(packageTotal);
sb.append(",pn=").append(packageNo);
}
sb.append(']');
sb.append(',');
return sb;
}
@Override
public String toString() {
String result = ToStringBuilder.toString(toStringHead(), this, false, "messageId", "clientId", "protocolVersion", "serialNo", "properties", "packageTotal", "packageNo");
return result;
}
}
\ No newline at end of file
package com.zehong.protocol.basics;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface JTMessageFilter<T extends JTMessage> {
boolean doFilter(T message);
}
\ No newline at end of file
package com.zehong.protocol.codec;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.jsatl12.DataPacket;
import io.github.yezhihao.netmc.util.ByteBufUtils;
import io.github.yezhihao.protostar.SchemaManager;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.netty.buffer.ByteBuf;
/**
* 数据帧解码器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class DataFrameMessageDecoder extends JTMessageDecoder {
private final RuntimeSchema<DataPacket> dataFrameSchema;
private final byte[] dataFramePrefix;
public DataFrameMessageDecoder(SchemaManager schemaManager, byte[] dataFramePrefix) {
super(schemaManager);
this.dataFramePrefix = dataFramePrefix;
this.dataFrameSchema = schemaManager.getRuntimeSchema(DataPacket.class, 0);
}
@Override
public JTMessage decode(ByteBuf input) {
if (ByteBufUtils.startsWith(input, dataFramePrefix)) {
DataPacket message = new DataPacket();
message.setPayload(input);
dataFrameSchema.mergeFrom(input, message);
return message;
}
return super.decode(input);
}
}
\ No newline at end of file
package com.zehong.protocol.codec;
import com.zehong.protocol.basics.JTMessage;
import io.github.yezhihao.netmc.codec.MessageDecoder;
import io.github.yezhihao.netmc.codec.MessageEncoder;
import io.github.yezhihao.netmc.session.Session;
import io.github.yezhihao.protostar.SchemaManager;
import io.github.yezhihao.protostar.util.Explain;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JT消息编解码适配器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class JTMessageAdapter implements MessageEncoder<JTMessage>, MessageDecoder<JTMessage> {
protected static final Logger log = LoggerFactory.getLogger(JTMessageAdapter.class);
private final JTMessageEncoder messageEncoder;
private final JTMessageDecoder messageDecoder;
public JTMessageAdapter(String... basePackages) {
this(new SchemaManager(basePackages));
}
public JTMessageAdapter(SchemaManager schemaManager) {
this(new JTMessageEncoder(schemaManager), new MultiPacketDecoder(schemaManager, new MultiPacketListener(20)));
}
public JTMessageAdapter(JTMessageEncoder messageEncoder, JTMessageDecoder messageDecoder) {
this.messageEncoder = messageEncoder;
this.messageDecoder = messageDecoder;
}
public ByteBuf encode(JTMessage message, Explain explain) {
return messageEncoder.encode(message, explain);
}
public JTMessage decode(ByteBuf input, Explain explain) {
return messageDecoder.decode(input, explain);
}
public ByteBuf encode(JTMessage message) {
return messageEncoder.encode(message);
}
public JTMessage decode(ByteBuf input) {
return messageDecoder.decode(input);
}
@Override
public ByteBuf encode(JTMessage message, Session session) {
ByteBuf output = messageEncoder.encode(message);
encodeLog(session, message, output);
return output;
}
@Override
public JTMessage decode(ByteBuf input, Session session) {
JTMessage message = messageDecoder.decode(input);
if (message != null)
message.setSession(session);
decodeLog(session, message, input);
return message;
}
public void encodeLog(Session session, JTMessage message, ByteBuf output) {
if (log.isInfoEnabled())
log.info("{}\n>>>>>-{},hex[{}]", session, message, ByteBufUtil.hexDump(output));
}
public void decodeLog(Session session, JTMessage message, ByteBuf input) {
if (log.isInfoEnabled())
log.info("{}\n<<<<<-{},hex[{}]", session, message, ByteBufUtil.hexDump(input, 0, input.writerIndex()));
}
}
\ No newline at end of file
package com.zehong.protocol.codec;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JTUtils;
import io.github.yezhihao.protostar.SchemaManager;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.github.yezhihao.protostar.util.ArrayMap;
import io.github.yezhihao.protostar.util.Explain;
import io.netty.buffer.*;
import java.util.ArrayList;
import java.util.List;
/**
* JT协议解码器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class JTMessageDecoder {
private static final ByteBufAllocator ALLOC = PooledByteBufAllocator.DEFAULT;
private final SchemaManager schemaManager;
private final ArrayMap<RuntimeSchema> headerSchemaMap;
public JTMessageDecoder(String... basePackages) {
this.schemaManager = new SchemaManager(basePackages);
this.headerSchemaMap = schemaManager.getRuntimeSchema(JTMessage.class);
}
public JTMessageDecoder(SchemaManager schemaManager) {
this.schemaManager = schemaManager;
this.headerSchemaMap = schemaManager.getRuntimeSchema(JTMessage.class);
}
public JTMessage decode(ByteBuf input) {
return decode(input, null);
}
public JTMessage decode(ByteBuf input, Explain explain) {
ByteBuf buf = unescape(input);
boolean verified = verify(buf);
int messageId = buf.getUnsignedShort(0);
int properties = buf.getUnsignedShort(2);
int version = 0;//缺省值为2013版本
if (Bit.isTrue(properties, 14))//识别2019及后续版本
version = buf.getUnsignedByte(4);
boolean isSubpackage = Bit.isTrue(properties, 13);
int headLen = JTUtils.headerLength(version, isSubpackage);
RuntimeSchema<JTMessage> headSchema = headerSchemaMap.get(version);
RuntimeSchema<JTMessage> bodySchema = schemaManager.getRuntimeSchema(messageId, version);
JTMessage message;
if (bodySchema == null)
message = new JTMessage();
else
message = bodySchema.newInstance();
message.setVerified(verified);
message.setPayload(input);
int writerIndex = buf.writerIndex();
buf.writerIndex(headLen);
headSchema.mergeFrom(buf, message, explain);
buf.writerIndex(writerIndex - 1);
int realVersion = message.getProtocolVersion();
if (realVersion != version)
bodySchema = schemaManager.getRuntimeSchema(messageId, realVersion);
if (bodySchema != null) {
int bodyLen = message.getBodyLength();
if (isSubpackage) {
ByteBuf bytes = ALLOC.buffer(bodyLen);
buf.getBytes(headLen, bytes);
ByteBuf[] packages = addAndGet(message, bytes);
if (packages == null)
return message;
ByteBuf bodyBuf = Unpooled.wrappedBuffer(packages);
bodySchema.mergeFrom(bodyBuf, message, explain);
if (message.noBuffer()) {
bodyBuf.release();
}
} else {
buf.readerIndex(headLen);
bodySchema.mergeFrom(buf, message, explain);
}
}
return message;
}
protected ByteBuf[] addAndGet(JTMessage message, ByteBuf bytes) {
return null;
}
/** 校验 */
public static boolean verify(ByteBuf buf) {
byte checkCode = JTUtils.bcc(buf, -1);
return checkCode == buf.getByte(buf.writerIndex() - 1);
}
/** 反转义 */
public static ByteBuf unescape(ByteBuf source) {
int low = source.readerIndex();
int high = source.writerIndex();
if (source.getByte(low) == 0x7e)
low++;
if (source.getByte(high - 1) == 0x7e)
high--;
int mark = source.indexOf(low, high - 1, (byte) 0x7d);
if (mark == -1) {
return source.slice(low, high - low);
}
List<ByteBuf> bufList = new ArrayList<>(3);
int len;
do {
len = mark + 2 - low;
bufList.add(slice(source, low, len));
low += len;
mark = source.indexOf(low, high, (byte) 0x7d);
} while (mark > 0);
bufList.add(source.slice(low, high - low));
return new CompositeByteBuf(ALLOC, false, bufList.size(), bufList);
}
/** 截取转义前报文,并还原转义位 */
protected static ByteBuf slice(ByteBuf byteBuf, int index, int length) {
byte second = byteBuf.getByte(index + length - 1);
if (second == 0x01) {
return byteBuf.slice(index, length - 1);
} else if (second == 0x02) {
byteBuf.setByte(index + length - 2, 0x7e);
return byteBuf.slice(index, length - 1);
} else {
return byteBuf.slice(index, length);
}
}
}
\ No newline at end of file
package com.zehong.protocol.codec;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JTUtils;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.SchemaManager;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.github.yezhihao.protostar.util.ArrayMap;
import io.github.yezhihao.protostar.util.Explain;
import io.netty.buffer.*;
import io.netty.util.ByteProcessor;
import java.util.LinkedList;
/**
* JT协议编码器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class JTMessageEncoder {
private static final ByteBufAllocator ALLOC = PooledByteBufAllocator.DEFAULT;
private final SchemaManager schemaManager;
private final ArrayMap<RuntimeSchema> headerSchemaMap;
public JTMessageEncoder(String... basePackages) {
this.schemaManager = new SchemaManager(basePackages);
this.headerSchemaMap = schemaManager.getRuntimeSchema(JTMessage.class);
}
public JTMessageEncoder(SchemaManager schemaManager) {
this.schemaManager = schemaManager;
this.headerSchemaMap = schemaManager.getRuntimeSchema(JTMessage.class);
}
public ByteBuf encode(JTMessage message) {
return encode(message, null);
}
public ByteBuf encode(JTMessage message, Explain explain) {
int version = message.getProtocolVersion();
int headLength = JTUtils.headerLength(version, false);
int bodyLength = 0;
Schema headSchema = headerSchemaMap.get(version);
Schema bodySchema = schemaManager.getRuntimeSchema(message.getMessageId(), version);
ByteBuf output;
if (bodySchema != null) {
output = ALLOC.buffer(headLength + bodySchema.length());
output.writerIndex(headLength);
bodySchema.writeTo(output, message, explain);
bodyLength = output.writerIndex() - headLength;
} else {
output = ALLOC.buffer(headLength, 21);
}
if (bodyLength <= 1023) {
message.setBodyLength(bodyLength);
int writerIndex = output.writerIndex();
if (writerIndex > 0) {
output.writerIndex(0);
headSchema.writeTo(output, message, explain);
output.writerIndex(writerIndex);
} else {
headSchema.writeTo(output, message, explain);
}
output = sign(output);
output = escape(output);
} else {
ByteBuf[] slices = slices(output, headLength, 1023);
int total = slices.length;
CompositeByteBuf _allBuf = new CompositeByteBuf(ALLOC, false, total);
output = _allBuf;
message.setSubpackage(true);
message.setPackageTotal(total);
headLength = JTUtils.headerLength(version, true);
for (int i = 0; i < total; i++) {
ByteBuf slice = slices[i];
message.setPackageNo(i + 1);
message.setBodyLength(slice.readableBytes());
ByteBuf headBuf = ALLOC.buffer(headLength, headLength);
headSchema.writeTo(headBuf, message, explain);
ByteBuf msgBuf = new CompositeByteBuf(ALLOC, false, 2)
.addComponent(true, 0, headBuf)
.addComponent(true, 1, slice);
msgBuf = sign(msgBuf);
msgBuf = escape(msgBuf);
_allBuf.addComponent(true, i, msgBuf);
}
}
return output;
}
public static ByteBuf[] slices(ByteBuf output, int start, int unitSize) {
int totalSize = output.writerIndex() - start;
int tailIndex = (totalSize - 1) / unitSize;
ByteBuf[] slices = new ByteBuf[tailIndex + 1];
output.skipBytes(start);
for (int i = 0; i < tailIndex; i++) {
slices[i] = output.readSlice(unitSize);
}
slices[tailIndex] = output.readSlice(output.readableBytes());
output.retain(tailIndex);
return slices;
}
/** 签名 */
public static ByteBuf sign(ByteBuf buf) {
byte checkCode = JTUtils.bcc(buf, 0);
buf.writeByte(checkCode);
return buf;
}
private static final ByteProcessor searcher = value -> !(value == 0x7d || value == 0x7e);
/** 转义处理 */
public static ByteBuf escape(ByteBuf source) {
int low = source.readerIndex();
int high = source.writerIndex();
LinkedList<ByteBuf> bufList = new LinkedList();
int mark, len;
while ((mark = source.forEachByte(low, high - low, searcher)) > 0) {
len = mark + 1 - low;
ByteBuf[] slice = slice(source, low, len);
bufList.add(slice[0]);
bufList.add(slice[1]);
low += len;
}
if (bufList.size() > 0) {
bufList.add(source.slice(low, high - low));
} else {
bufList.add(source);
}
ByteBuf delimiter = Unpooled.buffer(1, 1).writeByte(0x7e).retain();
bufList.addFirst(delimiter);
bufList.addLast(delimiter);
CompositeByteBuf byteBufs = new CompositeByteBuf(ALLOC, false, bufList.size());
byteBufs.addComponents(true, bufList);
return byteBufs;
}
/** 截断转义前报文,并转义 */
protected static ByteBuf[] slice(ByteBuf byteBuf, int index, int length) {
byte first = byteBuf.getByte(index + length - 1);
ByteBuf[] bufs = new ByteBuf[2];
bufs[0] = byteBuf.retainedSlice(index, length);
if (first == 0x7d) {
bufs[1] = Unpooled.buffer(1, 1).writeByte(0x01);
} else {
byteBuf.setByte(index + length - 1, 0x7d);
bufs[1] = Unpooled.buffer(1, 1).writeByte(0x02);
}
return bufs;
}
}
\ No newline at end of file
package com.zehong.protocol.codec;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.MessageId;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
/**
* 分包消息
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class MultiPacket {
private final JTMessage firstPacket;
private int serialNo = -1;
private int retryCount;
private final long creationTime;
private long lastAccessedTime;
private int count = 0;
private final ByteBuf[] packets;
public MultiPacket(JTMessage firstPacket) {
this.firstPacket = firstPacket;
this.creationTime = System.currentTimeMillis();
this.lastAccessedTime = creationTime;
this.packets = new ByteBuf[firstPacket.getPackageTotal()];
}
public ByteBuf[] addAndGet(int packetNo, ByteBuf packetData) {
lastAccessedTime = System.currentTimeMillis();
packetNo = packetNo - 1;
if (packets[packetNo] == null) {
packets[packetNo] = packetData;
count++;
} else {
packetData.release();
}
if (isComplete())
return packets;
return null;
}
public List<Integer> getNotArrived() {
if (isComplete())
return null;
int total = packets.length;
List<Integer> result = new ArrayList<>(total - count);
for (int i = 0; i < total; i++) {
if (packets[i] == null)
result.add(i + 1);
}
return result;
}
public void release() {
for (ByteBuf packet : packets) {
if (packet != null)
packet.release();
}
}
public void addRetryCount(int retryCount) {
this.retryCount += retryCount;
this.lastAccessedTime = System.currentTimeMillis();
}
public int getRetryCount() {
return retryCount;
}
public long getLastAccessedTime() {
return lastAccessedTime;
}
public long getCreationTime() {
return creationTime;
}
public boolean isComplete() {
return count == packets.length;
}
public JTMessage getFirstPacket() {
return firstPacket;
}
public int getSerialNo() {
return serialNo;
}
public void setSerialNo(int serialNo) {
if (serialNo == -1)
this.serialNo = serialNo;
}
@Override
public String toString() {
int total = packets.length;
final StringBuilder sb = new StringBuilder(82 + (total * 3));
sb.append(MessageId.getName(firstPacket.getMessageId()));
sb.append(", cid=").append(firstPacket.getClientId());
sb.append(", total=").append(total);
sb.append(", count=").append(count);
sb.append(", retryCount=").append(retryCount);
sb.append(", waitTime=").append((System.currentTimeMillis() - creationTime) / 1000);
sb.append(", packets=");
sb.append('{');
for (int i = 0; i < total; i++) {
if (packets[i] != null) sb.append(i + 1);
else sb.append(' ');
sb.append(',');
}
sb.setCharAt(sb.length() - 1, '}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.codec;
import com.zehong.protocol.basics.JTMessage;
import io.github.yezhihao.protostar.SchemaManager;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* 分包消息管理
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class MultiPacketDecoder extends JTMessageDecoder {
private static final Logger log = LoggerFactory.getLogger(MultiPacketDecoder.class);
private final Map<String, MultiPacket> multiPacketsMap;
private final MultiPacketListener multiPacketListener;
public MultiPacketDecoder(String... basePackages) {
this(new SchemaManager(basePackages));
}
public MultiPacketDecoder(SchemaManager schemaManager) {
this(schemaManager, null);
}
public MultiPacketDecoder(SchemaManager schemaManager, MultiPacketListener multiPacketListener) {
super(schemaManager);
if (multiPacketListener == null) {
this.multiPacketsMap = new WeakHashMap<>();
this.multiPacketListener = null;
} else {
this.multiPacketsMap = new ConcurrentHashMap<>();
this.multiPacketListener = multiPacketListener;
startListener();
}
}
@Override
protected ByteBuf[] addAndGet(JTMessage message, ByteBuf packetData) {
String clientId = message.getClientId();
int messageId = message.getMessageId();
int packageTotal = message.getPackageTotal();
int packetNo = message.getPackageNo();
String key = new StringBuilder(21).append(clientId).append('/').append(messageId).append('/').append(packageTotal).toString();
MultiPacket multiPacket = multiPacketsMap.get(key);
if (multiPacket == null)
multiPacketsMap.put(key, multiPacket = new MultiPacket(message));
if (packetNo == 1)
multiPacket.setSerialNo(message.getSerialNo());
ByteBuf[] packages = multiPacket.addAndGet(packetNo, packetData);
log.debug("<<<<<分包消息{}", multiPacket);
if (packages == null)
return null;
multiPacketsMap.remove(key);
return packages;
}
private void startListener() {
Thread thread = new Thread(() -> {
long timeout = multiPacketListener.timeout;
for (; ; ) {
long nextDelay = timeout;
long now = System.currentTimeMillis();
for (Map.Entry<String, MultiPacket> entry : multiPacketsMap.entrySet()) {
MultiPacket packet = entry.getValue();
long time = timeout - (now - packet.getLastAccessedTime());
if (time <= 0) {
if (!multiPacketListener.receiveTimeout(packet)) {
log.warn("<<<<<分包接收超时{}", packet);
multiPacketsMap.remove(entry.getKey());
packet.release();
}
} else {
nextDelay = Math.min(time, nextDelay);
}
}
try {
Thread.sleep(nextDelay);
} catch (InterruptedException e) {
log.error("MultiPacketListener", e);
}
}
});
thread.setName("MultiPacketListener");
thread.setPriority(Thread.MIN_PRIORITY);
thread.setDaemon(true);
thread.start();
}
}
\ No newline at end of file
package com.zehong.protocol.codec;
/**
* 分包消息监听器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class MultiPacketListener {
protected long timeout;
public MultiPacketListener() {
this(30);
}
/**
* 超时时间 (秒)
* @param timeout
*/
public MultiPacketListener(int timeout) {
this.timeout = timeout * 1000;
}
/**
* 超时分包消息处理
* @param multiPacket 分包信息
* @return 是否继续等待
*/
public boolean receiveTimeout(MultiPacket multiPacket) {
return false;
}
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface Action {
/** 清空 */
int Clear = 0;
/** 更新(先清空,后追加) */
int Update = 1;
/** 追加 */
int Append = 2;
/** 修改 */
int Modify = 3;
/** 指定删除 */
int Delete = 4;
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* 32位整型的二进制读写
* << 左移
* &与 同为1返回1
* |或 其中一个为1返回1
* ^异或 相同为0不同为1
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class Bit {
/**
* 判断n的第i位
* @param n int32
* @param i 取值范围0~31
*/
public static boolean isTrue(int n, int i) {
return get(n, i) > 0;
}
/**
* 读取n的第i位
* @param n int32
* @param i 取值范围0~31
*/
public static int get(int n, int i) {
return (1 << i) & n;
}
/**
* 设置n的第i位为1
* @param n int32
* @param i 取值范围0~31
*/
public static int set1(int n, int i) {
return (1 << i) | n;
}
/**
* 设置n的第i位为0
* @param n int32
* @param i 取值范围0~31
*/
public static int set0(int n, int i) {
return get(n, i) ^ n;
}
/**
* 写入bool到n的第i位
* @param n int32
* @param i 取值范围0~31
*/
public static int set(int n, int i, boolean bool) {
return bool ? set1(n, i) : set0(n, i);
}
/**
* 按位写入int
* 数组第一个int为首位
*/
public static int writeInt(int... bit) {
int n = 0;
for (int i = 0; i < bit.length; i++)
n = set(n, i, bit[i] > 0);
return n;
}
}
\ No newline at end of file
package com.zehong.protocol.commons;
import java.nio.charset.Charset;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class Charsets {
public static final Charset GBK = Charset.forName("GBK");
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* 江苏省团体标准
* 道路运输车辆主动安全智能防控系统(通讯协议规范)
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface JSATL12 {
int 报警附件上传指令 = 0x9208;
int 文件上传完成消息应答 = 0x9212;
int 报警附件信息消息 = 0x1210;
int 文件信息上传 = 0x1211;
int 文件上传完成消息 = 0x1212;
int 文件数据上传 = 0x30316364;
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* 中华人民共和国交通运输行业标准
* 道路运输车辆卫星定位系统视频通信协议
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface JT1078 {
int 终端上传音视频属性 = 0x1003;
int 终端上传乘客流量 = 0x1005;
int 终端上传音视频资源列表 = 0x1205;
int 文件上传完成通知 = 0x1206;
int 查询终端音视频属性 = 0x9003;
int 实时音视频传输请求 = 0x9101;
int 音视频实时传输控制 = 0x9102;
int 实时音视频传输状态通知 = 0x9105;
int 平台下发远程录像回放请求 = 0x9201;
int 平台下发远程录像回放控制 = 0x9202;
int 查询资源列表 = 0x9205;
int 文件上传指令 = 0x9206;
int 文件上传控制 = 0x9207;
int 云台旋转 = 0x9301;
int 云台调整焦距控制 = 0x9302;
int 云台调整光圈控制 = 0x9303;
int 云台雨刷控制 = 0x9304;
int 红外补光控制 = 0x9305;
int 云台变倍控制 = 0x9306;
int 实时音视频流及透传数据传输 = 0x30316364;
String 平台手工唤醒请求_短消息 = "WAKEUP";
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* 中华人民共和国交通运输行业标准
* 道路运输车辆卫星定位系统终端通信协议
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface JT808 {
int 终端通用应答 = 0x0001;
int 终端心跳 = 0x0002;
int 终端注销 = 0x0003;
int 查询服务器时间 = 0x0004;//2019 new
int 终端补传分包请求 = 0x0005;//2019 new
int 终端注册 = 0x0100;
int 终端鉴权 = 0x0102;//2019 modify
int 查询终端参数应答 = 0x0104;
int 查询终端属性应答 = 0x0107;
int 终端升级结果通知 = 0x0108;
int 位置信息汇报 = 0x0200;
int 位置信息查询应答 = 0x0201;
int 事件报告 = 0x0301;//2019 del
int 提问应答 = 0x0302;//2019 del
int 信息点播_取消 = 0x0303;//2019 del
int 车辆控制应答 = 0x0500;
int 查询区域或线路数据应答 = 0x0608;//2019 new
int 行驶记录数据上传 = 0x0700;
int 电子运单上报 = 0x0701;
int 驾驶员身份信息采集上报 = 0x0702;//2019 modify
int 定位数据批量上传 = 0x0704;
int CAN总线数据上传 = 0x0705;
int 多媒体事件信息上传 = 0x0800;
int 多媒体数据上传 = 0x0801;
int 存储多媒体数据检索应答 = 0x0802;
int 摄像头立即拍摄命令应答 = 0x0805;
int 数据上行透传 = 0x0900;
int 数据压缩上报 = 0x0901;
int 终端RSA公钥 = 0x0A00;
int 终端上行消息保留 = 0x0F00 - 0x0FFF;
int 平台通用应答 = 0x8001;
int 服务器补传分包请求 = 0x8003;
int 查询服务器时间应答 = 0x8004;//2019 new
int 终端注册应答 = 0x8100;
int 设置终端参数 = 0x8103;
int 查询终端参数 = 0x8104;
int 终端控制 = 0x8105;
int 查询指定终端参数 = 0x8106;
int 查询终端属性 = 0x8107;
int 下发终端升级包 = 0x8108;
int 位置信息查询 = 0x8201;
int 临时位置跟踪控制 = 0x8202;
int 人工确认报警消息 = 0x8203;
int 服务器向终端发起链路检测请求 = 0x8204;//2019 new
int 文本信息下发 = 0x8300;//2019 modify
int 事件设置 = 0x8301;//2019 del
int 提问下发 = 0x8302;//2019 del
int 信息点播菜单设置 = 0x8303;//2019 del
int 信息服务 = 0x8304;//2019 del
int 电话回拨 = 0x8400;
int 设置电话本 = 0x8401;
int 车辆控制 = 0x8500;//2019 modify
int 设置圆形区域 = 0x8600;//2019 modify
int 删除圆形区域 = 0x8601;
int 设置矩形区域 = 0x8602;//2019 modify
int 删除矩形区域 = 0x8603;
int 设置多边形区域 = 0x8604;//2019 modify
int 删除多边形区域 = 0x8605;
int 设置路线 = 0x8606;
int 删除路线 = 0x8607;
int 查询区域或线路数据 = 0x8608;//2019 new
int 行驶记录仪数据采集命令 = 0x8700;
int 行驶记录仪参数下传命令 = 0x8701;
int 上报驾驶员身份信息请求 = 0x8702;
int 多媒体数据上传应答 = 0x8800;
int 摄像头立即拍摄命令 = 0x8801;
int 存储多媒体数据检索 = 0x8802;
int 存储多媒体数据上传 = 0x8803;
int 录音开始命令 = 0x8804;
int 单条存储多媒体数据检索上传命令 = 0x8805;
int 数据下行透传 = 0x8900;
int 平台RSA公钥 = 0x8A00;
int 平台下行消息保留 = 0x8F00 - 0x8FFF;
int 厂商自定义上行消息 = 0xE000 - 0xEFFF;//2019 new
int 商自定义下行消息 = 0xF000 - 0xFFFF;//2019 new
}
\ No newline at end of file
package com.zehong.protocol.commons;
import io.netty.buffer.ByteBuf;
public class JTUtils {
/**
* BCC校验(异或校验)
*/
public static byte bcc(ByteBuf byteBuf, int tailOffset) {
byte cs = 0;
int readerIndex = byteBuf.readerIndex();
int writerIndex = byteBuf.writerIndex() + tailOffset;
while (readerIndex < writerIndex)
cs ^= byteBuf.getByte(readerIndex++);
return cs;
}
public static int headerLength(int version, boolean isSubpackage) {
if (version > 0)
return isSubpackage ? 21 : 17;
else
return isSubpackage ? 16 : 12;
}
}
\ No newline at end of file
package com.zehong.protocol.commons;
import io.github.yezhihao.protostar.annotation.Message;
import io.github.yezhihao.protostar.util.ClassUtils;
import com.zehong.protocol.basics.JTMessage;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class MessageId {
private static final Map<Integer, String> messageId = new HashMap<>(256);
private static final Map<Integer, Class> messageClass = new HashMap<>(256);
static {
for (Class clazz : new Class[]{JT808.class, JT1078.class, JSATL12.class}) {
Field[] fields = clazz.getFields();
for (Field field : fields) {
try {
if (!Integer.TYPE.isAssignableFrom(field.getType()))
continue;
int id = field.getInt(null);
String hexId = leftPad(Integer.toHexString(id), 4, '0');
String name = field.getName();
messageId.put(id, "[" + hexId + "]" + name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
List<Class> classList = ClassUtils.getClassList("org.yzh.protocol");
for (Class<?> clazz : classList) {
Message annotation = clazz.getAnnotation(Message.class);
if (annotation != null) {
int[] value = annotation.value();
for (int i : value) {
messageClass.put(i, clazz);
}
}
}
}
public static Class<JTMessage> getClass(Integer id) {
return messageClass.get(id);
}
public static String getName(int id) {
String name = messageId.get(id);
if (name != null) {
return name;
}
return leftPad(Integer.toHexString(id), 4, '0');
}
public static String leftPad(String str, int size, char ch) {
int length = str.length();
int pads = size - length;
if (pads > 0) {
char[] result = new char[size];
str.getChars(0, length, result, pads);
while (pads > 0)
result[--pads] = ch;
return new String(result);
}
return str;
}
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* 区域类型
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public final class Shape {
/** 圆形 */
public static final int Circle = 1;
/** 矩形 */
public static final int Rectangle = 2;
/** 多边形 */
public static final int Polygon = 3;
/** 路线 */
public static final int Route = 4;
/**
* @param type 区域类型:1.圆形 2.矩形 3.多边形 4.路线
*/
public static int toMessageId(int type) {
switch (type) {
case Shape.Circle:
return JT808.删除圆形区域;
case Shape.Rectangle:
return JT808.删除矩形区域;
case Shape.Polygon:
return JT808.删除多边形区域;
case Shape.Route:
return JT808.删除路线;
default:
throw new IllegalArgumentException(String.valueOf(type));
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface ShapeAction {
/** 更新(先清空,后追加) */
int Update = 0;
/** 追加 */
int Append = 1;
/** 修改 */
int Modify = 2;
}
\ No newline at end of file
package com.zehong.protocol.commons.transform;
import io.github.yezhihao.protostar.PrepareLoadStrategy;
import io.github.yezhihao.protostar.ProtostarUtil;
import io.github.yezhihao.protostar.schema.MapSchema;
import io.github.yezhihao.protostar.schema.NumberSchema;
import com.zehong.protocol.commons.transform.attribute.*;
/**
* 位置附加信息转换器(苏标)
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class AttributeConverter extends MapSchema<Number, Object> {
public AttributeConverter() {
super(NumberSchema.BYTE_INT, 1);
}
@Override
protected void addSchemas(PrepareLoadStrategy<Number> schemaRegistry) {
schemaRegistry
.addSchema(AttributeKey.Mileage, NumberSchema.DWORD_LONG)
.addSchema(AttributeKey.Fuel, NumberSchema.WORD_INT)
.addSchema(AttributeKey.Speed, NumberSchema.WORD_INT)
.addSchema(AttributeKey.AlarmEventId, NumberSchema.WORD_INT)
.addSchema(AttributeKey.TirePressure, TirePressure.SCHEMA)
.addSchema(AttributeKey.CarriageTemperature, NumberSchema.WORD_SHORT)
.addSchema(AttributeKey.OverSpeedAlarm, OverSpeedAlarm.SCHEMA)
.addSchema(AttributeKey.InOutAreaAlarm, InOutAreaAlarm.SCHEMA)
.addSchema(AttributeKey.RouteDriveTimeAlarm, RouteDriveTimeAlarm.SCHEMA)
.addSchema(AttributeKey.VideoRelatedAlarm, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.VideoMissingStatus, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.VideoObscuredStatus, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.StorageFailureStatus, NumberSchema.WORD_INT)
.addSchema(AttributeKey.DriverBehaviorAlarm, NumberSchema.WORD_INT)
.addSchema(AttributeKey.Signal, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.IoState, NumberSchema.WORD_INT)
.addSchema(AttributeKey.AnalogQuantity, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.SignalStrength, NumberSchema.BYTE_INT)
.addSchema(AttributeKey.GnssCount, NumberSchema.BYTE_INT)
.addSchema(AttributeKey.AlarmADAS, ProtostarUtil.getRuntimeSchema(AlarmADAS.class, 0))
.addSchema(AttributeKey.AlarmBSD, ProtostarUtil.getRuntimeSchema(AlarmBSD.class, 0))
.addSchema(AttributeKey.AlarmDSM, ProtostarUtil.getRuntimeSchema(AlarmDSM.class, 0))
.addSchema(AttributeKey.AlarmTPMS, ProtostarUtil.getRuntimeSchema(AlarmTPMS.class, 0))
.addSchema(AttributeKey.InstallErrorMsg, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.AlgorithmErrorMsg, NumberSchema.DWORD_INT)
;
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform;
import io.github.yezhihao.protostar.PrepareLoadStrategy;
import io.github.yezhihao.protostar.ProtostarUtil;
import io.github.yezhihao.protostar.schema.MapSchema;
import io.github.yezhihao.protostar.schema.NumberSchema;
import com.zehong.protocol.commons.transform.attribute.*;
/**
* 位置附加信息转换器(粤标)
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class AttributeConverterYue extends MapSchema<Number, Object> {
public AttributeConverterYue() {
super(NumberSchema.BYTE_INT, 1);
}
@Override
protected void addSchemas(PrepareLoadStrategy<Number> schemaRegistry) {
schemaRegistry
.addSchema(AttributeKey.Mileage, NumberSchema.DWORD_LONG)
.addSchema(AttributeKey.Fuel, NumberSchema.WORD_INT)
.addSchema(AttributeKey.Speed, NumberSchema.WORD_INT)
.addSchema(AttributeKey.AlarmEventId, NumberSchema.WORD_INT)
.addSchema(AttributeKey.TirePressure, TirePressure.SCHEMA)
.addSchema(AttributeKey.CarriageTemperature, NumberSchema.WORD_SHORT)
.addSchema(AttributeKey.OverSpeedAlarm, OverSpeedAlarm.SCHEMA)
.addSchema(AttributeKey.InOutAreaAlarm, InOutAreaAlarm.SCHEMA)
.addSchema(AttributeKey.RouteDriveTimeAlarm, RouteDriveTimeAlarm.SCHEMA)
.addSchema(AttributeKey.VideoRelatedAlarm, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.VideoMissingStatus, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.VideoObscuredStatus, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.StorageFailureStatus, NumberSchema.WORD_INT)
.addSchema(AttributeKey.DriverBehaviorAlarm, NumberSchema.WORD_INT)
.addSchema(AttributeKey.Signal, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.IoState, NumberSchema.WORD_INT)
.addSchema(AttributeKey.AnalogQuantity, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.SignalStrength, NumberSchema.BYTE_INT)
.addSchema(AttributeKey.GnssCount, NumberSchema.BYTE_INT)
.addSchema(AttributeKey.AlarmADAS, ProtostarUtil.getRuntimeSchema(AlarmADAS.class, 1))
.addSchema(AttributeKey.AlarmBSD, ProtostarUtil.getRuntimeSchema(AlarmBSD.class, 1))
.addSchema(AttributeKey.AlarmDSM, ProtostarUtil.getRuntimeSchema(AlarmDSM.class, 1))
.addSchema(AttributeKey.AlarmTPMS, ProtostarUtil.getRuntimeSchema(AlarmTPMS.class, 1))
.addSchema(AttributeKey.InstallErrorMsg, NumberSchema.DWORD_INT)
.addSchema(AttributeKey.AlgorithmErrorMsg, NumberSchema.DWORD_INT)
;
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform;
/**
* 位置附加信息
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public interface AttributeKey {
Integer Mileage = 1; // 0x01 里程,数据类型为DWORD,单位为1/10km,对应车上里程表读数
Integer Fuel = 2; // 0x02 油量,数据类型为WORD,单位为1/10L,对应车上油量表读数
Integer Speed = 3; // 0x03 行驶记录功能获取的速度,数据类型为WORD,单位为1/10km/h
Integer AlarmEventId = 4; // 0x04 需要人工确认报警事件的ID,数据类型为WORD,从1开始计数
Integer TirePressure = 5; // 0x05 胎压,单位为Pa,标定轮子的顺序为从车头开始从左到右顺序排列,多余的字节为0xFF,表示无效数据
Integer CarriageTemperature = 6; // 0x06 车厢温度,单位为摄氏度,取值范围为-32767~+32767,最高位为1表示负数
Integer OverSpeedAlarm = 17; // 0x11 超速报警附加信息见表28
Integer InOutAreaAlarm = 18; // 0x12 进出区域/路线报警附加信息见表29
Integer RouteDriveTimeAlarm = 19; // 0x13 路段行驶时间不足/过长报警附加信息见表30
Integer VideoRelatedAlarm = 20; // 0x14 视频相关报警,DWORD,按位设置,标志位定义见表14
Integer VideoMissingStatus = 21; // 0x15 视频信号丢失报警状态,DWORD,按位设置,bit0~bit31分别表示第1~32个逻辑通道,相应位为1则表示该逻辑通道发生视频信号丢失
Integer VideoObscuredStatus = 22; // 0x16 视频信号遮挡报警状态,DWORD,按位设置,bit0~bit31分别表示第1~32个逻辑通道,相应位为1则表示该逻辑通道发生视频信号遮挡
Integer StorageFailureStatus = 23; // 0x17 存储器故障报警状态,WORD,按位设置.bit0~bit11分别表示第1~12个主存储器.bit12~bit15分别表示第1~4个灾备存储装置,相应位为1则表示该存储器发生故障
Integer DriverBehaviorAlarm = 24; // 0x18 异常驾驶行为报警详细描述,WORD,定义见表15
Integer Signal = 37; // 0x25 扩展车辆信号状态位,参数项格式和定义见表31
Integer IoState = 42; // 0x2a I0状态位,参数项格式和定义见表32
Integer AnalogQuantity = 43; // 0x2b 模拟量,bit[0~15],AD0;bit[l6~31],ADl
Integer SignalStrength = 48; // 0x30 数据类型为BYTE,无线通信网络信号强度
Integer GnssCount = 49; // 0x31 数据类型为BYTE,GNSS定位卫星数
Integer AlarmADAS = 100; // 0x64 高级驾驶辅助系统报警
Integer AlarmDSM = 101; // 0x65 驾驶员状态监测
Integer AlarmTPMS = 102; // 0x66 轮胎气压监测系统
Integer AlarmBSD = 103; // 0x67 盲点监测
Integer InstallErrorMsg = 241; // 0xF1 安装异常信息,由厂家自定义(粤标)
Integer AlgorithmErrorMsg = 242; // 0xF2 算法异常信息,由厂家自定义(粤标)
}
\ No newline at end of file
package com.zehong.protocol.commons.transform;
import io.github.yezhihao.protostar.PrepareLoadStrategy;
import io.github.yezhihao.protostar.schema.ArraySchema;
import io.github.yezhihao.protostar.schema.MapSchema;
import io.github.yezhihao.protostar.schema.NumberSchema;
import com.zehong.protocol.commons.transform.passthrough.PeripheralStatus;
import com.zehong.protocol.commons.transform.passthrough.PeripheralSystem;
/**
* 透传消息转换器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class PassthroughConverter extends MapSchema<Number, Object> {
public PassthroughConverter() {
super(NumberSchema.BYTE_INT, 0);
}
@Override
protected void addSchemas(PrepareLoadStrategy<Number> schemaRegistry) {
schemaRegistry
.addSchema(0, ArraySchema.BYTES)
.addSchema(PeripheralStatus.key, PeripheralStatus.Schema.INSTANCE)
.addSchema(PeripheralSystem.key, PeripheralSystem.Schema.INSTANCE);
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import com.zehong.protocol.t808.T0200;
import java.time.LocalDateTime;
public abstract class Alarm {
private T0200 location;
private String platformAlarmId;
public T0200 getLocation() {
return location;
}
public void setLocation(T0200 location) {
this.location = location;
}
public String getPlatformAlarmId() {
return platformAlarmId;
}
public void setPlatformAlarmId(String platformAlarmId) {
this.platformAlarmId = platformAlarmId;
}
static int buildType(int key, int type) {
return (key * 100) + type;
}
//报警来源:0.设备报警 1.苏标报警 127.平台报警
public int getSource() {
return 0;
}
public int getAreaId() {
return 0;
}
public int getState() {
return 1;
}
//上报时间
public LocalDateTime getDateTime() {
if (location == null)
return null;
return location.getDeviceTime();
}
//报警时间
public LocalDateTime getAlarmTime() {
if (location == null)
return null;
return location.getDeviceTime();
}
//报警类别<=255
public int getCategory() {
return 0;
}
//报警类型
public abstract int getAlarmType();
//报警级别
public int getLevel() {
return 0;
}
//gps经度
public int getLongitude() {
if (location == null)
return 0;
return location.getLongitude();
}
//gps纬度
public int getLatitude() {
if (location == null)
return 0;
return location.getLatitude();
}
//海拔(米)
public int getAltitude() {
if (location == null)
return 0;
return location.getAltitude();
}
//速度(公里每小时)
public int getSpeed() {
if (location == null)
return 0;
return location.getSpeed() / 10;
}
//车辆状态
public int getStatusBit() {
if (location == null)
return 0;
return location.getStatusBit();
}
//序号(同一时间点报警的序号,从0循环累加)
public int getSequenceNo() {
return 0;
}
//附件总数
public int getFileTotal() {
return 0;
}
//扩展信息
public String getExtra() {
return null;
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.annotation.Field;
import java.time.LocalDateTime;
/**
* 高级驾驶辅助系统报警 0x64
*/
public class AlarmADAS extends Alarm {
public static final Integer key = 100;
@Field(length = 4, desc = "报警ID")
private long id;
@Field(length = 1, desc = "标志状态:0.不可用 1.开始标志 2.结束标志")
private int state;
@Field(length = 1, desc = "报警/事件类型:" +
" 1.前向碰撞报警" +
" 2.车道偏离报警" +
" 3.车距过近报警" +
" 4.行人碰撞报警" +
" 5.频繁变道报警" +
" 6.道路标识超限报警" +
" 7.障碍物报警" +
" 8~15.用户自定义" +
" 16.道路标志识别事件" +
" 17.主动抓拍事件" +
" 18.实线变道报警(粤标)" +
" 19.车厢过道行人检测报警(粤标)" +
" 18~31.用户自定义")
private int type;
@Field(length = 1, desc = "报警级别")
private int level;
@Field(length = 1, desc = "前车车速(Km/h)范围0~250,仅报警类型为1和2时有效")
private int frontSpeed;
@Field(length = 1, desc = "前车/行人距离(100ms),范围0~100,仅报警类型为1、2和4时有效")
private int frontDistance;
@Field(length = 1, desc = "偏离类型:1.左侧偏离 2.右侧偏离(报警类型为2时有效)")
private int deviateType;
@Field(length = 1, desc = "道路标志识别类型:1.限速标志 2.限高标志 3.限重标志 4.禁行标志(粤标) 5.禁停标志(粤标)(报警类型为6和10时有效)")
private int roadSign;
@Field(length = 1, desc = "道路标志识别数据")
private int roadSignValue;
@Field(length = 1, desc = "车速")
private int speed;
@Field(length = 2, desc = "高程")
private int altitude;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 6, charset = "BCD", desc = "日期时间")
private LocalDateTime alarmTime;
@Field(length = 2, desc = "车辆状态")
private int statusBit;
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID(粤标)", version = 1)
private String deviceId;
@Field(length = 6, charset = "BCD", desc = "时间(YYMMDDHHMMSS)")
private LocalDateTime dateTime;
@Field(length = 1, desc = "序号(同一时间点报警的序号,从0循环累加)")
private int sequenceNo;
@Field(length = 1, desc = "附件数量")
private int fileTotal;
@Field(length = 1, desc = "预留", version = {-1, 0})
@Field(length = 2, desc = "预留(粤标)", version = 1)
private int reserved;
@Override
public int getSource() {
return 1;
}
@Override
public int getCategory() {
return key;
}
@Override
public int getAlarmType() {
return Alarm.buildType(key, type);
}
@Override
public String getExtra() {
final StringBuilder sb = new StringBuilder(64);
if (type == 1 || type == 2) {
sb.append("frontSpeed:").append(frontSpeed).append(',');
}
if (type == 1 || type == 2 || type == 4) {
sb.append("frontDistance:").append(frontDistance).append(',');
}
if (type == 2) {
sb.append("deviateType:").append(deviateType).append(',');
}
if (type == 6 || type == 10) {
sb.append("roadSign:").append(roadSign).append(',');
sb.append("roadSignValue:").append(roadSignValue).append(',');
}
int length = sb.length();
if (length > 0)
return sb.substring(0, length - 1);
return null;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getFrontSpeed() {
return frontSpeed;
}
public void setFrontSpeed(int frontSpeed) {
this.frontSpeed = frontSpeed;
}
public int getFrontDistance() {
return frontDistance;
}
public void setFrontDistance(int frontDistance) {
this.frontDistance = frontDistance;
}
public int getDeviateType() {
return deviateType;
}
public void setDeviateType(int deviateType) {
this.deviateType = deviateType;
}
public int getRoadSign() {
return roadSign;
}
public void setRoadSign(int roadSign) {
this.roadSign = roadSign;
}
public int getRoadSignValue() {
return roadSignValue;
}
public void setRoadSignValue(int roadSignValue) {
this.roadSignValue = roadSignValue;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getLatitude() {
return latitude;
}
public void setLatitude(int latitude) {
this.latitude = latitude;
}
public int getLongitude() {
return longitude;
}
public void setLongitude(int longitude) {
this.longitude = longitude;
}
public LocalDateTime getAlarmTime() {
return alarmTime;
}
public void setAlarmTime(LocalDateTime alarmTime) {
this.alarmTime = alarmTime;
}
public int getStatusBit() {
return statusBit;
}
public void setStatusBit(int statusBit) {
this.statusBit = statusBit;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public LocalDateTime getDateTime() {
return dateTime;
}
public void setDateTime(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
public int getSequenceNo() {
return sequenceNo;
}
public void setSequenceNo(int sequenceNo) {
this.sequenceNo = sequenceNo;
}
public int getFileTotal() {
return fileTotal;
}
public void setFileTotal(int fileTotal) {
this.fileTotal = fileTotal;
}
public int getReserved() {
return reserved;
}
public void setReserved(int reserved) {
this.reserved = reserved;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(512);
sb.append("AlarmADAS{id=").append(id);
sb.append(", state=").append(state);
sb.append(", type=").append(type);
sb.append(", level=").append(level);
sb.append(", frontSpeed=").append(frontSpeed);
sb.append(", frontDistance=").append(frontDistance);
sb.append(", deviateType=").append(deviateType);
sb.append(", roadSign=").append(roadSign);
sb.append(", roadSignValue=").append(roadSignValue);
sb.append(", speed=").append(speed);
sb.append(", altitude=").append(altitude);
sb.append(", longitude=").append(longitude);
sb.append(", latitude=").append(latitude);
sb.append(", alarmTime=").append(alarmTime);
sb.append(", statusBit=").append(statusBit);
sb.append(", deviceId=").append(deviceId);
sb.append(", dateTime=").append(dateTime);
sb.append(", sequenceNo=").append(sequenceNo);
sb.append(", fileTotal=").append(fileTotal);
sb.append(", reserved=").append(reserved);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.annotation.Field;
import java.time.LocalDateTime;
/**
* 盲点监测 0x67
*/
public class AlarmBSD extends Alarm {
public static final Integer key = 103;
@Field(length = 4, desc = "报警ID")
private long id;
@Field(length = 1, desc = "标志状态:0.不可用 1.开始标志 2.结束标志")
private int state;
@Field(length = 1, desc = "报警/事件类型:1.后方接近报警 2.左侧后方接近报警 3.右侧后方接近报警")
private int type;
@Field(length = 1, desc = "车速")
private int speed;
@Field(length = 2, desc = "高程")
private int altitude;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 6, charset = "BCD", desc = "日期时间")
private LocalDateTime alarmTime;
@Field(length = 2, desc = "车辆状态")
private int statusBit;
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID(粤标)", version = 1)
private String deviceId;
@Field(length = 6, charset = "BCD", desc = "时间(YYMMDDHHMMSS)")
private LocalDateTime dateTime;
@Field(length = 1, desc = "序号(同一时间点报警的序号,从0循环累加)")
private int sequenceNo;
@Field(length = 1, desc = "附件数量")
private int fileTotal;
@Field(length = 1, desc = "预留", version = {-1, 0})
@Field(length = 2, desc = "预留(粤标)", version = 1)
private int reserved;
@Override
public int getSource() {
return 1;
}
@Override
public int getCategory() {
return key;
}
@Override
public int getAlarmType() {
return Alarm.buildType(key, type);
}
@Override
public int getLevel() {
return 0;
}
@Override
public String getExtra() {
return null;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getLatitude() {
return latitude;
}
public void setLatitude(int latitude) {
this.latitude = latitude;
}
public int getLongitude() {
return longitude;
}
public void setLongitude(int longitude) {
this.longitude = longitude;
}
public LocalDateTime getAlarmTime() {
return alarmTime;
}
public void setAlarmTime(LocalDateTime alarmTime) {
this.alarmTime = alarmTime;
}
public int getStatusBit() {
return statusBit;
}
public void setStatusBit(int statusBit) {
this.statusBit = statusBit;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public LocalDateTime getDateTime() {
return dateTime;
}
public void setDateTime(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
public int getSequenceNo() {
return sequenceNo;
}
public void setSequenceNo(int sequenceNo) {
this.sequenceNo = sequenceNo;
}
public int getFileTotal() {
return fileTotal;
}
public void setFileTotal(int fileTotal) {
this.fileTotal = fileTotal;
}
public int getReserved() {
return reserved;
}
public void setReserved(int reserved) {
this.reserved = reserved;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(300);
sb.append("AlarmBSD{id=").append(id);
sb.append(", state=").append(state);
sb.append(", type=").append(type);
sb.append(", speed=").append(speed);
sb.append(", altitude=").append(altitude);
sb.append(", longitude=").append(longitude);
sb.append(", latitude=").append(latitude);
sb.append(", alarmTime=").append(alarmTime);
sb.append(", statusBit=").append(statusBit);
sb.append(", deviceId=").append(deviceId);
sb.append(", dateTime=").append(dateTime);
sb.append(", sequenceNo=").append(sequenceNo);
sb.append(", fileTotal=").append(fileTotal);
sb.append(", reserved=").append(reserved);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.annotation.Field;
import java.time.LocalDateTime;
/**
* 驾驶员状态监测 0x65
*/
public class AlarmDSM extends Alarm {
public static final Integer key = 101;
@Field(length = 4, desc = "报警ID")
private long id;
@Field(length = 1, desc = "标志状态:0.不可用 1.开始标志 2.结束标志")
private int state;
@Field(length = 1, desc = "报警/事件类型:" +
" 1.疲劳驾驶报警" +
" 2.接打电话报警" +
" 3.抽烟报警" +
" 4.分神驾驶报警|不目视前方报警(粤标)" +
" 5.驾驶员异常报警" +
" 6.探头遮挡报警(粤标)" +
" 7.用户自定义" +
" 8.超时驾驶报警(粤标)" +
" 9.用户自定义" +
" 10.未系安全带报警(粤标)" +
" 11.红外阻断型墨镜失效报警(粤标)" +
" 12.双脱把报警(双手同时脱离方向盘)(粤标)" +
" 13.玩手机报警(粤标)" +
" 14.用户自定义" +
" 15.用户自定义" +
" 16.自动抓拍事件" +
" 17.驾驶员变更事件" +
" 18~31.用户自定义")
private int type;
@Field(length = 1, desc = "报警级别")
private int level;
@Field(length = 1, desc = "疲劳程度")
private int fatigueDegree;
@Field(length = 4, desc = "预留")
private int reserves;
@Field(length = 1, desc = "车速")
private int speed;
@Field(length = 2, desc = "高程")
private int altitude;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 6, charset = "BCD", desc = "日期时间")
private LocalDateTime alarmTime;
@Field(length = 2, desc = "车辆状态")
private int statusBit;
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID(粤标)", version = 1)
private String deviceId;
@Field(length = 6, charset = "BCD", desc = "时间(YYMMDDHHMMSS)")
private LocalDateTime dateTime;
@Field(length = 1, desc = "序号(同一时间点报警的序号,从0循环累加)")
private int sequenceNo;
@Field(length = 1, desc = "附件数量")
private int fileTotal;
@Field(length = 1, desc = "预留", version = {-1, 0})
@Field(length = 2, desc = "预留(粤标)", version = 1)
private int reserved;
@Override
public int getSource() {
return 1;
}
@Override
public int getCategory() {
return key;
}
@Override
public int getAlarmType() {
return Alarm.buildType(key, type);
}
@Override
public String getExtra() {
return "fatigueDegree:" + fatigueDegree;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getFatigueDegree() {
return fatigueDegree;
}
public void setFatigueDegree(int fatigueDegree) {
this.fatigueDegree = fatigueDegree;
}
public int getReserves() {
return reserves;
}
public void setReserves(int reserves) {
this.reserves = reserves;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getLatitude() {
return latitude;
}
public void setLatitude(int latitude) {
this.latitude = latitude;
}
public int getLongitude() {
return longitude;
}
public void setLongitude(int longitude) {
this.longitude = longitude;
}
public LocalDateTime getAlarmTime() {
return alarmTime;
}
public void setAlarmTime(LocalDateTime alarmTime) {
this.alarmTime = alarmTime;
}
public int getStatusBit() {
return statusBit;
}
public void setStatusBit(int statusBit) {
this.statusBit = statusBit;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public LocalDateTime getDateTime() {
return dateTime;
}
public void setDateTime(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
public int getSequenceNo() {
return sequenceNo;
}
public void setSequenceNo(int sequenceNo) {
this.sequenceNo = sequenceNo;
}
public int getFileTotal() {
return fileTotal;
}
public void setFileTotal(int fileTotal) {
this.fileTotal = fileTotal;
}
public int getReserved() {
return reserved;
}
public void setReserved(int reserved) {
this.reserved = reserved;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(400);
sb.append("AlarmDSM{id=").append(id);
sb.append(", state=").append(state);
sb.append(", type=").append(type);
sb.append(", level=").append(level);
sb.append(", fatigueDegree=").append(fatigueDegree);
sb.append(", reserves=").append(reserves);
sb.append(", speed=").append(speed);
sb.append(", altitude=").append(altitude);
sb.append(", longitude=").append(longitude);
sb.append(", latitude=").append(latitude);
sb.append(", alarmTime=").append(alarmTime);
sb.append(", statusBit=").append(statusBit);
sb.append(", deviceId=").append(deviceId);
sb.append(", dateTime=").append(dateTime);
sb.append(", sequenceNo=").append(sequenceNo);
sb.append(", fileTotal=").append(fileTotal);
sb.append(", reserved=").append(reserved);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.annotation.Field;
import java.time.LocalDateTime;
import java.util.List;
/**
* 轮胎气压监测系统 0x66
*/
public class AlarmTPMS extends Alarm {
public static final Integer key = 102;
@Field(length = 4, desc = "报警ID")
private long id;
@Field(length = 1, desc = "标志状态")
private int state;
@Field(length = 1, desc = "车速")
private int speed;
@Field(length = 2, desc = "高程")
private int altitude;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 6, charset = "BCD", desc = "日期时间")
private LocalDateTime alarmTime;
@Field(length = 2, desc = "车辆状态")
private int statusBit;
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID(粤标)", version = 1)
private String deviceId;
@Field(length = 6, charset = "BCD", desc = "时间(YYMMDDHHMMSS)")
private LocalDateTime dateTime;
@Field(length = 1, desc = "序号(同一时间点报警的序号,从0循环累加)")
private int sequenceNo;
@Field(length = 1, desc = "附件数量")
private int fileTotal;
@Field(length = 1, desc = "预留", version = {-1, 0})
@Field(length = 2, desc = "预留(粤标)", version = 1)
private int reserved;
@Field(totalUnit = 1, desc = "事件信息列表")
private List<Item> items;
@Override
public int getSource() {
return 1;
}
@Override
public int getCategory() {
return key;
}
@Override
public int getAlarmType() {
return Alarm.buildType(key, 0);
}
@Override
public int getLevel() {
return 0;
}
@Override
public String getExtra() {
return null;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getLatitude() {
return latitude;
}
public void setLatitude(int latitude) {
this.latitude = latitude;
}
public int getLongitude() {
return longitude;
}
public void setLongitude(int longitude) {
this.longitude = longitude;
}
public LocalDateTime getAlarmTime() {
return alarmTime;
}
public void setAlarmTime(LocalDateTime alarmTime) {
this.alarmTime = alarmTime;
}
public int getStatusBit() {
return statusBit;
}
public void setStatusBit(int statusBit) {
this.statusBit = statusBit;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public LocalDateTime getDateTime() {
return dateTime;
}
public void setDateTime(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
public int getSequenceNo() {
return sequenceNo;
}
public void setSequenceNo(int sequenceNo) {
this.sequenceNo = sequenceNo;
}
public int getFileTotal() {
return fileTotal;
}
public void setFileTotal(int fileTotal) {
this.fileTotal = fileTotal;
}
public int getReserved() {
return reserved;
}
public void setReserved(int reserved) {
this.reserved = reserved;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public static class Item {
@Field(length = 1, desc = "胎压报警位置(从左前轮开始以Z字形从00依次编号,编号与是否安装TPMS无关)")
private int position;
@Field(length = 2, desc = "报警类型:" +
" 0.胎压(定时上报)" +
" 1.胎压过高报警" +
" 2.胎压过低报警" +
" 3.胎温过高报警" +
" 4.传感器异常报警" +
" 5.胎压不平衡报警" +
" 6.慢漏气报警" +
" 7.电池电量低报警" +
" 8~31.预留")
private int type;
@Field(length = 2, desc = "胎压(Kpa)")
private int pressure;
@Field(length = 2, desc = "温度(℃)")
private int temperature;
@Field(length = 2, desc = "电池电量(%)")
private int batteryLevel;
public Item() {
}
public Item(int position, int type, int pressure, int temperature, int batteryLevel) {
this.position = position;
this.type = type;
this.pressure = pressure;
this.temperature = temperature;
this.batteryLevel = batteryLevel;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
public int getBatteryLevel() {
return batteryLevel;
}
public void setBatteryLevel(int batteryLevel) {
this.batteryLevel = batteryLevel;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Item{");
sb.append("position=").append(position);
sb.append(", type=").append(type);
sb.append(", pressure=").append(pressure);
sb.append(", temperature=").append(temperature);
sb.append(", batteryLevel=").append(batteryLevel);
sb.append('}');
return sb.toString();
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(400);
sb.append("AlarmTPMS{id=").append(id);
sb.append(", state=").append(state);
sb.append(", speed=").append(speed);
sb.append(", altitude=").append(altitude);
sb.append(", longitude=").append(longitude);
sb.append(", latitude=").append(latitude);
sb.append(", alarmTime=").append(alarmTime);
sb.append(", statusBit=").append(statusBit);
sb.append(", deviceId=").append(deviceId);
sb.append(", dateTime=").append(dateTime);
sb.append(", sequenceNo=").append(sequenceNo);
sb.append(", fileTotal=").append(fileTotal);
sb.append(", reserved=").append(reserved);
sb.append(", items=").append(items);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.Schema;
import io.netty.buffer.ByteBuf;
/**
* 进出区域/路线报警 0x12
* length 6
*/
public class InOutAreaAlarm extends Alarm {
public static final Integer key = 18;
public static final Schema<InOutAreaAlarm> SCHEMA = new InOutAreaAlarmSchema();
/** 位置类型:1.圆形区域 2.矩形区域 3.多边形区域 4.路线 */
private byte areaType;
/** 区域或路段ID */
private int areaId;
/** 方向:0.进 1.出 */
private byte direction;
public InOutAreaAlarm() {
}
public InOutAreaAlarm(byte areaType, int areaId, byte direction) {
this.areaType = areaType;
this.areaId = areaId;
this.direction = direction;
}
public byte getAreaType() {
return areaType;
}
public void setAreaType(byte areaType) {
this.areaType = areaType;
}
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
public byte getDirection() {
return direction;
}
public void setDirection(byte direction) {
this.direction = direction;
}
@Override
public int getAlarmType() {
return key;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(80);
sb.append("InOutAreaAlarm{areaType=").append(areaType);
sb.append(",areaId=").append(areaId);
sb.append(",direction=").append(direction);
sb.append('}');
return sb.toString();
}
private static class InOutAreaAlarmSchema implements Schema<InOutAreaAlarm> {
private InOutAreaAlarmSchema() {
}
@Override
public InOutAreaAlarm readFrom(ByteBuf input) {
InOutAreaAlarm message = new InOutAreaAlarm();
message.areaType = input.readByte();
message.areaId = input.readInt();
message.direction = input.readByte();
return message;
}
@Override
public void writeTo(ByteBuf output, InOutAreaAlarm message) {
output.writeByte(message.areaType);
output.writeInt(message.areaId);
output.writeByte(message.direction);
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.Schema;
import io.netty.buffer.ByteBuf;
/**
* 超速报警 0x11
* length 1 或 5
*/
public class OverSpeedAlarm extends Alarm {
public static final Integer key = 17;
public static final Schema<OverSpeedAlarm> SCHEMA = new OverSpeedAlarmSchema();
/** 位置类型:0.无特定位置 1.圆形区域 2.矩形区域 3.多边形区域 4.路段 */
private byte areaType;
/** 区域或路段ID */
private int areaId;
public OverSpeedAlarm() {
}
public OverSpeedAlarm(byte areaType, int areaId) {
this.areaType = areaType;
this.areaId = areaId;
}
public byte getAreaType() {
return areaType;
}
public void setAreaType(byte areaType) {
this.areaType = areaType;
}
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
@Override
public int getAlarmType() {
return key;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(80);
sb.append("OverSpeedAlarm{areaType=").append(areaType);
sb.append(",areaId=").append(areaId);
sb.append('}');
return sb.toString();
}
private static class OverSpeedAlarmSchema implements Schema<OverSpeedAlarm> {
private OverSpeedAlarmSchema() {
}
@Override
public OverSpeedAlarm readFrom(ByteBuf input) {
OverSpeedAlarm message = new OverSpeedAlarm();
message.areaType = input.readByte();
if (message.areaType > 0)
message.areaId = input.readInt();
return message;
}
@Override
public void writeTo(ByteBuf output, OverSpeedAlarm message) {
output.writeByte(message.areaType);
if (message.areaType > 0)
output.writeInt(message.areaId);
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.Schema;
import io.netty.buffer.ByteBuf;
/**
* 路段行驶时间不足/过长 0x13
* length 7
*/
public class RouteDriveTimeAlarm extends Alarm {
public static final Integer key = 19;
public static final Schema<RouteDriveTimeAlarm> SCHEMA = new RouteDriveTimeAlarmSchema();
/** 路段ID */
private int areaId;
/** 路段行驶时间(秒) */
private int driveTime;
/** 结果:0.不足 1.过长 */
private byte result;
public RouteDriveTimeAlarm() {
}
public RouteDriveTimeAlarm(int areaId, int driveTime, byte result) {
this.areaId = areaId;
this.driveTime = driveTime;
this.result = result;
}
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
public int getDriveTime() {
return driveTime;
}
public void setDriveTime(int driveTime) {
this.driveTime = driveTime;
}
public byte getResult() {
return result;
}
public void setResult(byte result) {
this.result = result;
}
@Override
public int getAlarmType() {
return key;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(80);
sb.append("RouteDriveTimeAlarm{areaId=").append(areaId);
sb.append(",driveTime=").append(driveTime);
sb.append(",result=").append(result);
sb.append('}');
return sb.toString();
}
private static class RouteDriveTimeAlarmSchema implements Schema<RouteDriveTimeAlarm> {
private RouteDriveTimeAlarmSchema() {
}
@Override
public RouteDriveTimeAlarm readFrom(ByteBuf input) {
RouteDriveTimeAlarm message = new RouteDriveTimeAlarm();
message.areaId = input.readInt();
message.driveTime = input.readUnsignedShort();
message.result = input.readByte();
return message;
}
@Override
public void writeTo(ByteBuf output, RouteDriveTimeAlarm message) {
output.writeInt(message.areaId);
output.writeShort(message.driveTime);
output.writeByte(message.result);
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.attribute;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import java.util.Arrays;
/**
* 胎压 0x05
* length 30
*/
public class TirePressure {
public static final Integer key = 5;
public static final Schema<TirePressure> SCHEMA = new TirePressureSchema();
private byte[] value;
public TirePressure() {
}
public TirePressure(byte[] value) {
this.value = value;
}
public byte[] getValue() {
return value;
}
public void setValue(byte[] value) {
this.value = value;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(32);
sb.append("TirePressure{value=").append(Arrays.toString(value));
sb.append('}');
return sb.toString();
}
private static class TirePressureSchema implements Schema<TirePressure> {
private TirePressureSchema() {
}
@Override
public TirePressure readFrom(ByteBuf input) {
int len = input.readableBytes();
if (len > 30)
len = 30;
byte[] value = new byte[len];
input.readBytes(value);
return new TirePressure(value);
}
@Override
public void writeTo(ByteBuf output, TirePressure message) {
ByteBufUtils.writeFixedLength(output, 30, message.value);
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.parameter;
import io.github.yezhihao.protostar.annotation.Field;
/**
* 盲区监测系统参数
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamBSD {
public static final Integer key = 0xF367;
@Field(length = 1, desc = "后方接近报警时间阈值")
private byte rearApproachAlarmTimeThreshold = -1;
@Field(length = 1, desc = "侧后方接近报警时间阈值")
private byte rearSideApproachAlarmTimeThreshold = -1;
public byte getRearApproachAlarmTimeThreshold() {
return rearApproachAlarmTimeThreshold;
}
public void setRearApproachAlarmTimeThreshold(byte rearApproachAlarmTimeThreshold) {
this.rearApproachAlarmTimeThreshold = rearApproachAlarmTimeThreshold;
}
public byte getRearSideApproachAlarmTimeThreshold() {
return rearSideApproachAlarmTimeThreshold;
}
public void setRearSideApproachAlarmTimeThreshold(byte rearSideApproachAlarmTimeThreshold) {
this.rearSideApproachAlarmTimeThreshold = rearSideApproachAlarmTimeThreshold;
}
@Override
public String toString() {
return "ParamBSD{" +
"rearApproachAlarmTimeThreshold=" + rearApproachAlarmTimeThreshold +
", rearSideApproachAlarmTimeThreshold=" + rearSideApproachAlarmTimeThreshold +
'}';
}
}
package com.zehong.protocol.commons.transform.parameter;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
/**
* 音视频通道列表设置
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamChannels {
public static final Integer key = 0x0076;
public static final Schema<ParamChannels> SCHEMA = new ParamChannelsSchema();
@Field(desc = "音视频通道总数")
private byte audioVideoChannels;
@Field(desc = "音频通道总数")
private byte audioChannels;
@Field(desc = "视频通道总数")
private byte videoChannels;
@Field(desc = "音视频通道对照表")
private List<ChannelInfo> channels;
public ParamChannels() {
}
public byte getAudioVideoChannels() {
return audioVideoChannels;
}
public void setAudioVideoChannels(byte audioVideoChannels) {
this.audioVideoChannels = audioVideoChannels;
}
public byte getAudioChannels() {
return audioChannels;
}
public void setAudioChannels(byte audioChannels) {
this.audioChannels = audioChannels;
}
public byte getVideoChannels() {
return videoChannels;
}
public void setVideoChannels(byte videoChannels) {
this.videoChannels = videoChannels;
}
public List<ChannelInfo> getChannels() {
return channels;
}
public void setChannels(List<ChannelInfo> channels) {
this.channels = channels;
}
private static class ChannelInfo {
@Field(desc = "物理通道号(从1开始)")
private byte channelId;
@Field(desc = "逻辑通道号(按照JT/T 1076-2016 中的表2)")
private byte channelNo;
@Field(desc = "通道类型:0.音视频 1.音频 2.视频")
private byte channelType;
@Field(desc = "是否连接云台(类型为0和2时,此字段有效):0.未连接 1.连接")
private boolean hasPanTilt;
public ChannelInfo() {
}
public ChannelInfo(byte channelId, byte channelNo, byte channelType, boolean hasPanTilt) {
this.channelId = channelId;
this.channelNo = channelNo;
this.channelType = channelType;
this.hasPanTilt = hasPanTilt;
}
public byte getChannelId() {
return channelId;
}
public void setChannelId(byte channelId) {
this.channelId = channelId;
}
public byte getChannelNo() {
return channelNo;
}
public void setChannelNo(byte channelNo) {
this.channelNo = channelNo;
}
public byte getChannelType() {
return channelType;
}
public void setChannelType(byte channelType) {
this.channelType = channelType;
}
public boolean isHasPanTilt() {
return hasPanTilt;
}
public void setHasPanTilt(boolean hasPanTilt) {
this.hasPanTilt = hasPanTilt;
}
}
private static class ParamChannelsSchema implements Schema<ParamChannels> {
private ParamChannelsSchema() {
}
@Override
public ParamChannels readFrom(ByteBuf input) {
ParamChannels message = new ParamChannels();
message.audioVideoChannels = input.readByte();
message.audioChannels = input.readByte();
message.videoChannels = input.readByte();
List<ChannelInfo> channels = new ArrayList<>(4);
while (input.isReadable()) {
byte channelId = input.readByte();
byte channelNo = input.readByte();
byte channelType = input.readByte();
boolean hasPanTilt = input.readBoolean();
channels.add(new ChannelInfo(channelId, channelNo, channelType, hasPanTilt));
}
message.setChannels(channels);
return message;
}
@Override
public void writeTo(ByteBuf output, ParamChannels message) {
output.writeByte(message.audioVideoChannels);
output.writeByte(message.audioChannels);
output.writeByte(message.videoChannels);
List<ChannelInfo> channelInfos = message.getChannels();
for (ChannelInfo channelInfo : channelInfos) {
output.writeByte(channelInfo.channelId);
output.writeByte(channelInfo.channelNo);
output.writeByte(channelInfo.channelType);
output.writeBoolean(channelInfo.hasPanTilt);
}
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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