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 io.github.yezhihao.protostar.schema.StringSchema;
import com.zehong.protocol.commons.transform.parameter.*;
/**
* 终端参数项转换器
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParameterConverter extends MapSchema<Number, Object> {
public ParameterConverter() {
super(NumberSchema.DWORD_INT, 1);
}
@Override
protected void addSchemas(PrepareLoadStrategy<Number> schemaRegistry) {
schemaRegistry
.addSchema(0x0001, NumberSchema.DWORD_LONG)//终端心跳发送间隔,单位为秒(s)
.addSchema(0x0002, NumberSchema.DWORD_LONG)//TCP消息应答超时时间,单位为秒(s)
.addSchema(0x0003, NumberSchema.DWORD_LONG)//TCP消息重传次数
.addSchema(0x0004, NumberSchema.DWORD_LONG)//UDP消息应答超时时间,单位为秒(s)
.addSchema(0x0005, NumberSchema.DWORD_LONG)//UDP消息重传次数
.addSchema(0x0006, NumberSchema.DWORD_LONG)//SMS消息应答超时时间,单位为秒(s)
.addSchema(0x0007, NumberSchema.DWORD_LONG)//SMS消息重传次数
.addSchema(0x0010, StringSchema.GBK)//主服务器APN,无线通信拨号访问点.若网络制式为CDMA,则该处为PPP拨号号码
.addSchema(0x0011, StringSchema.GBK)//主服务器无线通信拨号用户名
.addSchema(0x0012, StringSchema.GBK)//主服务器无线通信拨号密码
.addSchema(0x0013, StringSchema.GBK)//主服务器地址,IP或域名
.addSchema(0x0014, StringSchema.GBK)//备份服务器APN,无线通信拨号访问点
.addSchema(0x0015, StringSchema.GBK)//备份服务器无线通信拨号用户名
.addSchema(0x0016, StringSchema.GBK)//备份服务器无线通信拨号密码
.addSchema(0x0017, StringSchema.GBK)//备份服务器地址,IP或域名(2019版以冒号分割主机和端口,多个服务器使用分号分隔)
.addSchema(0x0018, NumberSchema.DWORD_LONG)//服务器TCP端口(2013版)
.addSchema(0x0019, NumberSchema.DWORD_LONG)//服务器UDP端口(2013版)
.addSchema(0x001A, StringSchema.GBK)//道路运输证IC卡认证主服务器IP地址或域名
.addSchema(0x001B, NumberSchema.DWORD_LONG)//道路运输证IC卡认证主服务器TCP端口
.addSchema(0x001C, NumberSchema.DWORD_LONG)//道路运输证IC卡认证主服务器UDP端口
.addSchema(0x001D, StringSchema.GBK)//道路运输证IC卡认证主服务器IP地址或域名,端口同主服务器
.addSchema(0x0020, NumberSchema.DWORD_LONG)//位置汇报策略:0.定时汇报 1.定距汇报 2.定时和定距汇报
.addSchema(0x0021, NumberSchema.DWORD_LONG)//位置汇报方案:0.根据ACC状态 1.根据登录状态和ACC状态,先判断登录状态,若登录再根据ACC状态
.addSchema(0x0022, NumberSchema.DWORD_LONG)//驾驶员未登录汇报时间间隔,单位为秒(s),>0
//JT808 2019
.addSchema(0x0023, StringSchema.GBK)//从服务器APN.该值为空时,终端应使用主服务器相同配置
.addSchema(0x0024, StringSchema.GBK)//从服务器无线通信拨号用户名.该值为空时,终端应使用主服务器相同配置
.addSchema(0x0025, StringSchema.GBK)//从服务器无线通信拨号密码.该值为空时,终端应使用主服务器相同配置
.addSchema(0x0026, StringSchema.GBK)//从服务器备份地址、IP或域名.主服务器IP地址或域名,端口同主服务器
//JT808 2019
.addSchema(0x0027, NumberSchema.DWORD_LONG)//休眠时汇报时间间隔,单位为秒(s),>0
.addSchema(0x0028, NumberSchema.DWORD_LONG)//紧急报警时汇报时间间隔,单位为秒(s),>0
.addSchema(0x0029, NumberSchema.DWORD_LONG)//缺省时间汇报间隔,单位为秒(s),>0
.addSchema(0x002C, NumberSchema.DWORD_LONG)//缺省距离汇报间隔,单位为米(m),>0
.addSchema(0x002D, NumberSchema.DWORD_LONG)//驾驶员未登录汇报距离间隔,单位为米(m),>0
.addSchema(0x002E, NumberSchema.DWORD_LONG)//休眠时汇报距离间隔,单位为米(m),>0
.addSchema(0x002F, NumberSchema.DWORD_LONG)//紧急报警时汇报距离间隔,单位为米(m),>0
.addSchema(0x0030, NumberSchema.DWORD_LONG)//拐点补传角度,<180°
.addSchema(0x0031, NumberSchema.WORD_INT)//电子围栏半径,单位为米
//JT808 2019
.addSchema(0x0032, TimeRange.SCHEMA)//违规行驶时段范围,精确到分
.addSchema(0x0040, StringSchema.GBK)//监控平台电话号码
.addSchema(0x0041, StringSchema.GBK)//复位电话号码,可采用此电话号码拨打终端电话让终端复位
.addSchema(0x0042, StringSchema.GBK)//恢复出厂设置电话号码,可采用此电话号码拨打终端电话让终端恢复出厂设置
.addSchema(0x0043, StringSchema.GBK)//监控平台SMS电话号码
.addSchema(0x0044, StringSchema.GBK)//接收终端SMS文本报警号码
.addSchema(0x0045, NumberSchema.DWORD_LONG)//终端电话接听策略,0.自动接听 1.ACC ON时自动接听,OFF时手动接听
.addSchema(0x0046, NumberSchema.DWORD_LONG)//每次最长通话时间,单位为秒(s),0为不允许通话,0xFFFFFFFF为不限制
.addSchema(0x0047, NumberSchema.DWORD_LONG)//当月最长通话时间,单位为秒(s),0为不允许通话,0xFFFFFFFF为不限制
.addSchema(0x0048, StringSchema.GBK)//监听电话号码
.addSchema(0x0049, StringSchema.GBK)//监管平台特权短信号码
.addSchema(0x0050, NumberSchema.DWORD_LONG)//报警屏蔽字.与位置信息汇报消息中的报警标志相对应,相应位为1则相应报警被屏蔽
.addSchema(0x0051, NumberSchema.DWORD_LONG)//报警发送文本SMS开关,与位置信息汇报消息中的报警标志相对应,相应位为1则相应报警时发送文本SMS
.addSchema(0x0052, NumberSchema.DWORD_LONG)//报警拍摄开关,与位置信息汇报消息中的报警标志相对应,相应位为1则相应报警时摄像头拍摄
.addSchema(0x0053, NumberSchema.DWORD_LONG)//报警拍摄存储标志,与位置信息汇报消息中的报警标志相对应,相应位为1则对相应报警时牌的照片进行存储,否则实时长传
.addSchema(0x0054, NumberSchema.DWORD_LONG)//关键标志,与位置信息汇报消息中的报警标志相对应,相应位为1则对相应报警为关键报警
.addSchema(0x0055, NumberSchema.DWORD_LONG)//最高速度,单位为公里每小时(km/h)
.addSchema(0x0056, NumberSchema.DWORD_LONG)//超速持续时间,单位为秒(s)
.addSchema(0x0057, NumberSchema.DWORD_LONG)//连续驾驶时间门限,单位为秒(s)
.addSchema(0x0058, NumberSchema.DWORD_LONG)//当天累计驾驶时间门限,单位为秒(s)
.addSchema(0x0059, NumberSchema.DWORD_LONG)//最小休息时间,单位为秒(s)
.addSchema(0x005A, NumberSchema.DWORD_LONG)//最长停车时间,单位为秒(s)
.addSchema(0x005B, NumberSchema.WORD_INT)//超速预警差值
.addSchema(0x005C, NumberSchema.WORD_INT)//疲劳驾驶预警插值
.addSchema(0x005D, NumberSchema.WORD_INT)//碰撞报警参数
.addSchema(0x005E, NumberSchema.WORD_INT)//侧翻报警参数
.addSchema(0x0064, NumberSchema.DWORD_LONG)//定时拍照参数
.addSchema(0x0065, NumberSchema.DWORD_LONG)//定距拍照参数
.addSchema(0x0070, NumberSchema.DWORD_LONG)//图像/视频质量,1~10,1最好
.addSchema(0x0071, NumberSchema.DWORD_LONG)//亮度,0~255
.addSchema(0x0072, NumberSchema.DWORD_LONG)//对比度,0~127
.addSchema(0x0073, NumberSchema.DWORD_LONG)//饱和度,0~127
.addSchema(0x0074, NumberSchema.DWORD_LONG)//色度,0~255
//JT1078 start
.addSchema(ParamVideo.key, ParamVideo.SCHEMA)//音视频参数设置,描述见表2
.addSchema(ParamChannels.key, ParamChannels.SCHEMA)//音视频通道列表设置,描述见表3
.addSchema(ParamVideoSingle.key, ParamVideoSingle.SCHEMA)//单独视频通道参数设置,描述见表5
.addSchema(ParamVideoSpecialAlarm.key, ParamVideoSpecialAlarm.class)//特殊报警录像参数设置,描述见表7
.addSchema(0x007A, NumberSchema.DWORD_LONG)//视频相关报警屏蔽字,和表13的视频报警标志位定义相对应,相应位为1则相应类型的报警被屏蔽
.addSchema(ParamImageIdentifyAlarm.key, ParamImageIdentifyAlarm.class)// 图像分析报警参数设置描述见表8
.addSchema(ParamSleepWake.key, ParamSleepWake.class)//终端休眠唤醒模式设置,描述见表9
//JT1078 end
.addSchema(0x0080, NumberSchema.DWORD_LONG)//车辆里程表读数,1/10km
.addSchema(0x0081, NumberSchema.WORD_INT)//车辆所在的省域ID
.addSchema(0x0082, NumberSchema.WORD_INT)//车辆所在的市域ID
.addSchema(0x0083, StringSchema.GBK)//公安交通管理部门颁发的机动车号牌
.addSchema(0x0084, NumberSchema.BYTE_INT)//车牌颜色,按照JT/T415-2006的5.4.12
.addSchema(0x0090, NumberSchema.BYTE_INT)//定位模式
.addSchema(0x0091, NumberSchema.BYTE_INT)//波特率
.addSchema(0x0092, NumberSchema.BYTE_INT)//模块详细定位数据输出频率
.addSchema(0x0093, NumberSchema.DWORD_LONG)//模块详细定位数据采集频率,单位为秒,默认为1
.addSchema(0x0094, NumberSchema.BYTE_INT)//模块详细定位数据上传方式
.addSchema(0x0095, NumberSchema.DWORD_LONG)//模块详细定位数据上传设置
.addSchema(0x0100, NumberSchema.DWORD_LONG)//总线通道1 采集时间间隔(ms),0 表示不采集
.addSchema(0x0101, NumberSchema.WORD_INT)//总线通道1 上传时间间隔(s),0 表示不上传
.addSchema(0x0102, NumberSchema.DWORD_LONG)//总线通道2 采集时间间隔(ms),0 表示不采集
.addSchema(0x0103, NumberSchema.WORD_INT)//总线通道2 上传时间间隔(s),0 表示不上传
.addSchema(0x0110, ArraySchema.BYTES)//总线ID 单独采集设置
//JSATL12 start
.addSchema(ParamADAS.key, ParamADAS.SCHEMA)//高级驾驶辅助系统参数,见表4-10
.addSchema(ParamDSM.key, ParamDSM.SCHEMA)//驾驶员状态监测系统参数,见表4-11
.addSchema(ParamTPMS.key, ParamTPMS.SCHEMA)//胎压监测系统参数,见表4-12
.addSchema(ParamBSD.key, ParamBSD.class)//盲区监测系统参数,见表4-13
//粤标
.addSchema(0xF370, NumberSchema.BYTE_INT)//智能视频协议版本信息,引入此智能视频协议版本信息方便平台进行版本控制初始版本是1,每次修订版本号都会递增(注:只支持获取,不支持设置)
;
}
}
\ 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.Schema;
import io.github.yezhihao.protostar.annotation.Field;
import io.netty.buffer.ByteBuf;
/**
* 高级驾驶辅助系统参数
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamADAS {
public static final Integer key = 0xF364;
public static final Schema<ParamADAS> SCHEMA = new ParamADASSchema();
@Field(desc = "报警判断速度阈值 BYTE")
private byte p00 = -1;
@Field(desc = "报警提示音量 BYTE")
private byte p01 = -1;
@Field(desc = "主动拍照策略 BYTE")
private byte p02 = -1;
@Field(desc = "主动定时拍照时间间隔 WORD")
private short p03 = -1;
@Field(desc = "主动定距拍照距离间隔 WORD")
private short p05 = -1;
@Field(desc = "单次主动拍照张数 BYTE")
private byte p07 = -1;
@Field(desc = "单次主动拍照时间间隔 BYTE")
private byte p08 = -1;
@Field(desc = "拍照分辨率 BYTE")
private byte p09 = -1;
@Field(desc = "视频录制分辨率 BYTE")
private byte p10 = -1;
@Field(desc = "报警使能 DWORD")
private int p11 = -1;
@Field(desc = "事件使能 DWORD")
private int p15 = -1;
@Field(desc = "预留字段 BYTE")
private byte p19 = -1;
@Field(desc = "障碍物报警距离阈值 BYTE")
private byte p20 = -1;
@Field(desc = "障碍物报警分级速度阈值 BYTE")
private byte p21 = -1;
@Field(desc = "障碍物报警前后视频录制时间 BYTE")
private byte p22 = -1;
@Field(desc = "障碍物报警拍照张数 BYTE")
private byte p23 = -1;
@Field(desc = "障碍物报警拍照间隔 BYTE")
private byte p24 = -1;
@Field(desc = "频繁变道报警判断时间段 BYTE")
private byte p25 = -1;
@Field(desc = "频繁变道报警判断次数 BYTE")
private byte p26 = -1;
@Field(desc = "频繁变道报警分级速度阈值 BYTE")
private byte p27 = -1;
@Field(desc = "频繁变道报警前后视频录制时间 BYTE")
private byte p28 = -1;
@Field(desc = "频繁变道报警拍照张数 BYTE")
private byte p29 = -1;
@Field(desc = "频繁变道报警拍照间隔 BYTE")
private byte p30 = -1;
@Field(desc = "车道偏离报警分级速度阈值 BYTE")
private byte p31 = -1;
@Field(desc = "车道偏离报警前后视频录制时间 BYTE")
private byte p32 = -1;
@Field(desc = "车道偏离报警拍照张数 BYTE")
private byte p33 = -1;
@Field(desc = "车道偏离报警拍照间隔 BYTE")
private byte p34 = -1;
@Field(desc = "前向碰撞报警时间阈值 BYTE")
private byte p35 = -1;
@Field(desc = "前向碰撞报警分级速度阈值 BYTE")
private byte p36 = -1;
@Field(desc = "前向碰撞报警前后视频录制时间 BYTE")
private byte p37 = -1;
@Field(desc = "前向碰撞报警拍照张数 BYTE")
private byte p38 = -1;
@Field(desc = "前向碰撞报警拍照间隔 BYTE")
private byte p39 = -1;
@Field(desc = "行人碰撞报警时间阈值 BYTE")
private byte p40 = -1;
@Field(desc = "行人碰撞报警使能速度阈值 BYTE")
private byte p41 = -1;
@Field(desc = "行人碰撞报警前后视频录制时间 BYTE")
private byte p42 = -1;
@Field(desc = "行人碰撞报警拍照张数 BYTE")
private byte p43 = -1;
@Field(desc = "行人碰撞报警拍照间隔 BYTE")
private byte p44 = -1;
@Field(desc = "车距监控报警距离阈值 BYTE")
private byte p45 = -1;
@Field(desc = "车距监控报警分级速度阈值 BYTE")
private byte p46 = -1;
@Field(desc = "车距过近报警前后视频录制时间 BYTE")
private byte p47 = -1;
@Field(desc = "车距过近报警拍照张数 BYTE")
private byte p48 = -1;
@Field(desc = "车距过近报警拍照间隔 BYTE")
private byte p49 = -1;
@Field(desc = "道路标志识别拍照张数 BYTE")
private byte p50 = -1;
@Field(desc = "道路标志识别拍照间隔 BYTE")
private byte p51 = -1;
@Field(desc = "实线变道报警分级速度阈值 BYTE(粤标)")
private byte p52 = -1;
@Field(desc = "实线变道报警前后视频录制时间 BYTE(粤标)")
private byte p53 = -1;
@Field(desc = "实线变道报警拍照张数 BYTE(粤标)")
private byte p54 = -1;
@Field(desc = "实线变道报警拍照间隔 BYTE(粤标)")
private byte p55 = -1;
@Field(desc = "车厢过道行人检测报警分级速度阈值 BYTE(粤标)")
private byte p56 = -1;
public ParamADAS() {
}
public byte getP00() {
return p00;
}
public void setP00(byte p00) {
this.p00 = p00;
}
public byte getP01() {
return p01;
}
public void setP01(byte p01) {
this.p01 = p01;
}
public byte getP02() {
return p02;
}
public void setP02(byte p02) {
this.p02 = p02;
}
public short getP03() {
return p03;
}
public void setP03(short p03) {
this.p03 = p03;
}
public short getP05() {
return p05;
}
public void setP05(short p05) {
this.p05 = p05;
}
public byte getP07() {
return p07;
}
public void setP07(byte p07) {
this.p07 = p07;
}
public byte getP08() {
return p08;
}
public void setP08(byte p08) {
this.p08 = p08;
}
public byte getP09() {
return p09;
}
public void setP09(byte p09) {
this.p09 = p09;
}
public byte getP10() {
return p10;
}
public void setP10(byte p10) {
this.p10 = p10;
}
public int getP11() {
return p11;
}
public void setP11(int p11) {
this.p11 = p11;
}
public int getP15() {
return p15;
}
public void setP15(int p15) {
this.p15 = p15;
}
public byte getP19() {
return p19;
}
public void setP19(byte p19) {
this.p19 = p19;
}
public byte getP20() {
return p20;
}
public void setP20(byte p20) {
this.p20 = p20;
}
public byte getP21() {
return p21;
}
public void setP21(byte p21) {
this.p21 = p21;
}
public byte getP22() {
return p22;
}
public void setP22(byte p22) {
this.p22 = p22;
}
public byte getP23() {
return p23;
}
public void setP23(byte p23) {
this.p23 = p23;
}
public byte getP24() {
return p24;
}
public void setP24(byte p24) {
this.p24 = p24;
}
public byte getP25() {
return p25;
}
public void setP25(byte p25) {
this.p25 = p25;
}
public byte getP26() {
return p26;
}
public void setP26(byte p26) {
this.p26 = p26;
}
public byte getP27() {
return p27;
}
public void setP27(byte p27) {
this.p27 = p27;
}
public byte getP28() {
return p28;
}
public void setP28(byte p28) {
this.p28 = p28;
}
public byte getP29() {
return p29;
}
public void setP29(byte p29) {
this.p29 = p29;
}
public byte getP30() {
return p30;
}
public void setP30(byte p30) {
this.p30 = p30;
}
public byte getP31() {
return p31;
}
public void setP31(byte p31) {
this.p31 = p31;
}
public byte getP32() {
return p32;
}
public void setP32(byte p32) {
this.p32 = p32;
}
public byte getP33() {
return p33;
}
public void setP33(byte p33) {
this.p33 = p33;
}
public byte getP34() {
return p34;
}
public void setP34(byte p34) {
this.p34 = p34;
}
public byte getP35() {
return p35;
}
public void setP35(byte p35) {
this.p35 = p35;
}
public byte getP36() {
return p36;
}
public void setP36(byte p36) {
this.p36 = p36;
}
public byte getP37() {
return p37;
}
public void setP37(byte p37) {
this.p37 = p37;
}
public byte getP38() {
return p38;
}
public void setP38(byte p38) {
this.p38 = p38;
}
public byte getP39() {
return p39;
}
public void setP39(byte p39) {
this.p39 = p39;
}
public byte getP40() {
return p40;
}
public void setP40(byte p40) {
this.p40 = p40;
}
public byte getP41() {
return p41;
}
public void setP41(byte p41) {
this.p41 = p41;
}
public byte getP42() {
return p42;
}
public void setP42(byte p42) {
this.p42 = p42;
}
public byte getP43() {
return p43;
}
public void setP43(byte p43) {
this.p43 = p43;
}
public byte getP44() {
return p44;
}
public void setP44(byte p44) {
this.p44 = p44;
}
public byte getP45() {
return p45;
}
public void setP45(byte p45) {
this.p45 = p45;
}
public byte getP46() {
return p46;
}
public void setP46(byte p46) {
this.p46 = p46;
}
public byte getP47() {
return p47;
}
public void setP47(byte p47) {
this.p47 = p47;
}
public byte getP48() {
return p48;
}
public void setP48(byte p48) {
this.p48 = p48;
}
public byte getP49() {
return p49;
}
public void setP49(byte p49) {
this.p49 = p49;
}
public byte getP50() {
return p50;
}
public void setP50(byte p50) {
this.p50 = p50;
}
public byte getP51() {
return p51;
}
public void setP51(byte p51) {
this.p51 = p51;
}
public byte getP52() {
return p52;
}
public void setP52(byte p52) {
this.p52 = p52;
}
public byte getP53() {
return p53;
}
public void setP53(byte p53) {
this.p53 = p53;
}
public byte getP54() {
return p54;
}
public void setP54(byte p54) {
this.p54 = p54;
}
public byte getP55() {
return p55;
}
public void setP55(byte p55) {
this.p55 = p55;
}
public byte getP56() {
return p56;
}
public void setP56(byte p56) {
this.p56 = p56;
}
private static class ParamADASSchema implements Schema<ParamADAS> {
private ParamADASSchema() {
}
@Override
public ParamADAS readFrom(ByteBuf input) {
ParamADAS message = new ParamADAS();
message.p00 = input.readByte();
message.p01 = input.readByte();
message.p02 = input.readByte();
message.p03 = input.readShort();
message.p05 = input.readShort();
message.p07 = input.readByte();
message.p08 = input.readByte();
message.p09 = input.readByte();
message.p10 = input.readByte();
message.p11 = input.readInt();
message.p15 = input.readInt();
message.p19 = input.readByte();
message.p20 = input.readByte();
message.p21 = input.readByte();
message.p22 = input.readByte();
message.p23 = input.readByte();
message.p24 = input.readByte();
message.p25 = input.readByte();
message.p26 = input.readByte();
message.p27 = input.readByte();
message.p28 = input.readByte();
message.p29 = input.readByte();
message.p30 = input.readByte();
message.p31 = input.readByte();
message.p32 = input.readByte();
message.p33 = input.readByte();
message.p34 = input.readByte();
message.p35 = input.readByte();
message.p36 = input.readByte();
message.p37 = input.readByte();
message.p38 = input.readByte();
message.p39 = input.readByte();
message.p40 = input.readByte();
message.p41 = input.readByte();
message.p42 = input.readByte();
message.p43 = input.readByte();
message.p44 = input.readByte();
message.p45 = input.readByte();
message.p46 = input.readByte();
message.p47 = input.readByte();
message.p48 = input.readByte();
message.p49 = input.readByte();
message.p50 = input.readByte();
message.p51 = input.readByte();
message.p52 = input.readByte();
message.p53 = input.readByte();
message.p54 = input.readByte();
message.p55 = input.readByte();
if (input.isReadable())
message.p56 = input.readByte();
return message;
}
@Override
public void writeTo(ByteBuf output, ParamADAS message) {
output.writeByte(message.p00);
output.writeByte(message.p01);
output.writeByte(message.p02);
output.writeShort(message.p03);
output.writeShort(message.p05);
output.writeByte(message.p07);
output.writeByte(message.p08);
output.writeByte(message.p09);
output.writeByte(message.p10);
output.writeInt(message.p11);
output.writeInt(message.p15);
output.writeByte(message.p19);
output.writeByte(message.p20);
output.writeByte(message.p21);
output.writeByte(message.p22);
output.writeByte(message.p23);
output.writeByte(message.p24);
output.writeByte(message.p25);
output.writeByte(message.p26);
output.writeByte(message.p27);
output.writeByte(message.p28);
output.writeByte(message.p29);
output.writeByte(message.p30);
output.writeByte(message.p31);
output.writeByte(message.p32);
output.writeByte(message.p33);
output.writeByte(message.p34);
output.writeByte(message.p35);
output.writeByte(message.p36);
output.writeByte(message.p37);
output.writeByte(message.p38);
output.writeByte(message.p39);
output.writeByte(message.p40);
output.writeByte(message.p41);
output.writeByte(message.p42);
output.writeByte(message.p43);
output.writeByte(message.p44);
output.writeByte(message.p45);
output.writeByte(message.p46);
output.writeByte(message.p47);
output.writeByte(message.p48);
output.writeByte(message.p49);
output.writeByte(message.p50);
output.writeByte(message.p51);
output.writeByte(message.p52);
output.writeByte(message.p53);
output.writeByte(message.p54);
output.writeByte(message.p55);
output.writeByte(message.p56);
}
}
}
\ 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
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;
/**
* 驾驶员状态监测系统参数
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamDSM {
public static final Integer key = 0xF365;
public static final Schema<ParamDSM> SCHEMA = new ParamDSMSchema();
@Field(desc = "报警判断速度阈值 BYTE")
private byte p00 = -1;
@Field(desc = "报警音量 BYTE")
private byte p01 = -1;
@Field(desc = "主动拍照策略 BYTE")
private byte p02 = -1;
@Field(desc = "主动定时拍照时间间隔 WORD")
private short p03 = -1;
@Field(desc = "主动定距拍照距离间隔 WORD")
private short p05 = -1;
@Field(desc = "单次主动拍照张数 BYTE")
private byte p07 = -1;
@Field(desc = "单次主动拍照时间间隔 BYTE")
private byte p08 = -1;
@Field(desc = "拍照分辨率 BYTE")
private byte p09 = -1;
@Field(desc = "视频录制分辨率 BYTE")
private byte p10 = -1;
@Field(desc = "报警使能 DWORD")
private int p11 = -1;
@Field(desc = "事件使能 DWORD")
private int p15 = -1;
@Field(desc = "吸烟报警判断时间间隔 WORD")
private short p19 = -1;
@Field(desc = "接打电话报警判断时间间隔 WORD")
private short p21 = -1;
@Field(desc = "预留字段 BYTE[3]")
private byte[] p23 = new byte[3];
@Field(desc = "疲劳驾驶报警分级速度阈值 BYTE")
private byte p26 = -1;
@Field(desc = "疲劳驾驶报警前后视频录制时间 BYTE")
private byte p27 = -1;
@Field(desc = "疲劳驾驶报警拍照张数 BYTE")
private byte p28 = -1;
@Field(desc = "疲劳驾驶报警拍照间隔时间 BYTE")
private byte p29 = -1;
@Field(desc = "接打电话报警分级速度阈值 BYTE")
private byte p30 = -1;
@Field(desc = "接打电话报警前后视频录制时间 BYTE")
private byte p31 = -1;
@Field(desc = "接打电话报警拍驾驶员面部特征照片张数 BYTE")
private byte p32 = -1;
@Field(desc = "接打电话报警拍驾驶员面部特征照片间隔时间 BYTE")
private byte p33 = -1;
@Field(desc = "抽烟报警分级车速阈值 BYTE")
private byte p34 = -1;
@Field(desc = "抽烟报警前后视频录制时间 BYTE")
private byte p35 = -1;
@Field(desc = "抽烟报警拍驾驶员面部特征照片张数 BYTE")
private byte p36 = -1;
@Field(desc = "抽烟报警拍驾驶员面部特征照片间隔时间 BYTE")
private byte p37 = -1;
@Field(desc = "分神驾驶报警分级车速阈值 BYTE")
private byte p38 = -1;
@Field(desc = "分神驾驶报警前后视频录制时间 BYTE")
private byte p39 = -1;
@Field(desc = "分神驾驶报警拍照张数 BYTE")
private byte p40 = -1;
@Field(desc = "分神驾驶报警拍照间隔时间 BYTE")
private byte p41 = -1;
@Field(desc = "驾驶行为异常分级速度阈值 BYTE")
private byte p42 = -1;
@Field(desc = "驾驶行为异常视频录制时间 BYTE")
private byte p43 = -1;
@Field(desc = "驾驶行为异常抓拍照片张数 BYTE")
private byte p44 = -1;
@Field(desc = "驾驶行为异常拍照间隔 BYTE")
private byte p45 = -1;
@Field(desc = "驾驶员身份识别触发 BYTE")
private byte p46 = -1;
@Field(desc = "摄像机遮挡报警分级速度阈值(粤标)")
private byte p47 = -1;
@Field(desc = "不系安全带报警分级速度阈值(粤标)")
private byte p48 = -1;
@Field(desc = "不系安全带报警前后视频录制时间(粤标)")
private byte p49 = -1;
@Field(desc = "不系安全带报警抓拍照片张数(粤标)")
private byte p50 = -1;
@Field(desc = "不系安全带报警抓拍照片间隔时间(粤标)")
private byte p51 = -1;
@Field(desc = "红外墨镜阻断失效报警分级速度阈值(粤标)")
private byte p52 = -1;
@Field(desc = "红外墨镜阻断失效报警前后视频录制时间(粤标)")
private byte p53 = -1;
@Field(desc = "红外墨镜阻断失效报警抓拍照片张数(粤标)")
private byte p54 = -1;
@Field(desc = "红外墨镜阻断失效报警抓拍照片间隔时间(粤标)")
private byte p55 = -1;
@Field(desc = "双脱把报警分级速度阈值(粤标)")
private byte p56 = -1;
@Field(desc = "双脱把报警前后视频录制时间(粤标)")
private byte p57 = -1;
@Field(desc = "双脱把报警抓拍照片张数(粤标)")
private byte p58 = -1;
@Field(desc = "双脱把报警抓拍照片间隔时间(粤标)")
private byte p59 = -1;
@Field(desc = "玩手机报警分级速度阈值(粤标)")
private byte p60 = -1;
@Field(desc = "玩手机报警前后视频录制时间(粤标)")
private byte p61 = -1;
@Field(desc = "玩手机报警抓拍照片张数(粤标)")
private byte p62 = -1;
@Field(desc = "玩手机报警拍抓拍,照片间隔时间(粤标)")
private byte p63 = -1;
@Field(desc = "保留字段(粤标)")
private byte p64 = -1;
public ParamDSM() {
}
public byte getP00() {
return p00;
}
public void setP00(byte p00) {
this.p00 = p00;
}
public byte getP01() {
return p01;
}
public void setP01(byte p01) {
this.p01 = p01;
}
public byte getP02() {
return p02;
}
public void setP02(byte p02) {
this.p02 = p02;
}
public short getP03() {
return p03;
}
public void setP03(short p03) {
this.p03 = p03;
}
public short getP05() {
return p05;
}
public void setP05(short p05) {
this.p05 = p05;
}
public byte getP07() {
return p07;
}
public void setP07(byte p07) {
this.p07 = p07;
}
public byte getP08() {
return p08;
}
public void setP08(byte p08) {
this.p08 = p08;
}
public byte getP09() {
return p09;
}
public void setP09(byte p09) {
this.p09 = p09;
}
public byte getP10() {
return p10;
}
public void setP10(byte p10) {
this.p10 = p10;
}
public int getP11() {
return p11;
}
public void setP11(int p11) {
this.p11 = p11;
}
public int getP15() {
return p15;
}
public void setP15(int p15) {
this.p15 = p15;
}
public short getP19() {
return p19;
}
public void setP19(short p19) {
this.p19 = p19;
}
public short getP21() {
return p21;
}
public void setP21(short p21) {
this.p21 = p21;
}
public byte[] getP23() {
return p23;
}
public void setP23(byte[] p23) {
this.p23 = p23;
}
public byte getP26() {
return p26;
}
public void setP26(byte p26) {
this.p26 = p26;
}
public byte getP27() {
return p27;
}
public void setP27(byte p27) {
this.p27 = p27;
}
public byte getP28() {
return p28;
}
public void setP28(byte p28) {
this.p28 = p28;
}
public byte getP29() {
return p29;
}
public void setP29(byte p29) {
this.p29 = p29;
}
public byte getP30() {
return p30;
}
public void setP30(byte p30) {
this.p30 = p30;
}
public byte getP31() {
return p31;
}
public void setP31(byte p31) {
this.p31 = p31;
}
public byte getP32() {
return p32;
}
public void setP32(byte p32) {
this.p32 = p32;
}
public byte getP33() {
return p33;
}
public void setP33(byte p33) {
this.p33 = p33;
}
public byte getP34() {
return p34;
}
public void setP34(byte p34) {
this.p34 = p34;
}
public byte getP35() {
return p35;
}
public void setP35(byte p35) {
this.p35 = p35;
}
public byte getP36() {
return p36;
}
public void setP36(byte p36) {
this.p36 = p36;
}
public byte getP37() {
return p37;
}
public void setP37(byte p37) {
this.p37 = p37;
}
public byte getP38() {
return p38;
}
public void setP38(byte p38) {
this.p38 = p38;
}
public byte getP39() {
return p39;
}
public void setP39(byte p39) {
this.p39 = p39;
}
public byte getP40() {
return p40;
}
public void setP40(byte p40) {
this.p40 = p40;
}
public byte getP41() {
return p41;
}
public void setP41(byte p41) {
this.p41 = p41;
}
public byte getP42() {
return p42;
}
public void setP42(byte p42) {
this.p42 = p42;
}
public byte getP43() {
return p43;
}
public void setP43(byte p43) {
this.p43 = p43;
}
public byte getP44() {
return p44;
}
public void setP44(byte p44) {
this.p44 = p44;
}
public byte getP45() {
return p45;
}
public void setP45(byte p45) {
this.p45 = p45;
}
public byte getP46() {
return p46;
}
public void setP46(byte p46) {
this.p46 = p46;
}
public byte getP47() {
return p47;
}
public void setP47(byte p47) {
this.p47 = p47;
}
public byte getP48() {
return p48;
}
public void setP48(byte p48) {
this.p48 = p48;
}
public byte getP49() {
return p49;
}
public void setP49(byte p49) {
this.p49 = p49;
}
public byte getP50() {
return p50;
}
public void setP50(byte p50) {
this.p50 = p50;
}
public byte getP51() {
return p51;
}
public void setP51(byte p51) {
this.p51 = p51;
}
public byte getP52() {
return p52;
}
public void setP52(byte p52) {
this.p52 = p52;
}
public byte getP53() {
return p53;
}
public void setP53(byte p53) {
this.p53 = p53;
}
public byte getP54() {
return p54;
}
public void setP54(byte p54) {
this.p54 = p54;
}
public byte getP55() {
return p55;
}
public void setP55(byte p55) {
this.p55 = p55;
}
public byte getP56() {
return p56;
}
public void setP56(byte p56) {
this.p56 = p56;
}
public byte getP57() {
return p57;
}
public void setP57(byte p57) {
this.p57 = p57;
}
public byte getP58() {
return p58;
}
public void setP58(byte p58) {
this.p58 = p58;
}
public byte getP59() {
return p59;
}
public void setP59(byte p59) {
this.p59 = p59;
}
public byte getP60() {
return p60;
}
public void setP60(byte p60) {
this.p60 = p60;
}
public byte getP61() {
return p61;
}
public void setP61(byte p61) {
this.p61 = p61;
}
public byte getP62() {
return p62;
}
public void setP62(byte p62) {
this.p62 = p62;
}
public byte getP63() {
return p63;
}
public void setP63(byte p63) {
this.p63 = p63;
}
public byte getP64() {
return p64;
}
public void setP64(byte p64) {
this.p64 = p64;
}
private static class ParamDSMSchema implements Schema<ParamDSM> {
private ParamDSMSchema() {
}
@Override
public ParamDSM readFrom(ByteBuf input) {
ParamDSM message = new ParamDSM();
message.p00 = input.readByte();
message.p01 = input.readByte();
message.p02 = input.readByte();
message.p03 = input.readShort();
message.p05 = input.readShort();
message.p07 = input.readByte();
message.p08 = input.readByte();
message.p09 = input.readByte();
message.p10 = input.readByte();
message.p11 = input.readInt();
message.p15 = input.readInt();
message.p19 = input.readShort();
message.p21 = input.readShort();
input.readBytes(message.p23);
message.p26 = input.readByte();
message.p27 = input.readByte();
message.p28 = input.readByte();
message.p29 = input.readByte();
message.p30 = input.readByte();
message.p31 = input.readByte();
message.p32 = input.readByte();
message.p33 = input.readByte();
message.p34 = input.readByte();
message.p35 = input.readByte();
message.p36 = input.readByte();
message.p37 = input.readByte();
message.p38 = input.readByte();
message.p39 = input.readByte();
message.p40 = input.readByte();
message.p41 = input.readByte();
message.p42 = input.readByte();
message.p43 = input.readByte();
message.p44 = input.readByte();
message.p45 = input.readByte();
message.p46 = input.readByte();
message.p47 = input.readByte();
message.p48 = input.readByte();
if (input.isReadable()) {
message.p49 = input.readByte();
message.p50 = input.readByte();
message.p51 = input.readByte();
message.p52 = input.readByte();
message.p53 = input.readByte();
message.p54 = input.readByte();
message.p55 = input.readByte();
message.p56 = input.readByte();
message.p57 = input.readByte();
message.p58 = input.readByte();
message.p59 = input.readByte();
message.p60 = input.readByte();
message.p61 = input.readByte();
message.p62 = input.readByte();
message.p63 = input.readByte();
message.p64 = input.readByte();
}
return message;
}
@Override
public void writeTo(ByteBuf output, ParamDSM message) {
output.writeByte(message.p00);
output.writeByte(message.p01);
output.writeByte(message.p02);
output.writeShort(message.p03);
output.writeShort(message.p05);
output.writeByte(message.p07);
output.writeByte(message.p08);
output.writeByte(message.p09);
output.writeByte(message.p10);
output.writeInt(message.p11);
output.writeInt(message.p15);
output.writeShort(message.p19);
output.writeShort(message.p21);
output.writeBytes(message.p23);
output.writeByte(message.p26);
output.writeByte(message.p27);
output.writeByte(message.p28);
output.writeByte(message.p29);
output.writeByte(message.p30);
output.writeByte(message.p31);
output.writeByte(message.p32);
output.writeByte(message.p33);
output.writeByte(message.p34);
output.writeByte(message.p35);
output.writeByte(message.p36);
output.writeByte(message.p37);
output.writeByte(message.p38);
output.writeByte(message.p39);
output.writeByte(message.p40);
output.writeByte(message.p41);
output.writeByte(message.p42);
output.writeByte(message.p43);
output.writeByte(message.p44);
output.writeByte(message.p45);
output.writeByte(message.p46);
output.writeByte(message.p47);
output.writeByte(message.p48);
output.writeByte(message.p49);
output.writeByte(message.p50);
output.writeByte(message.p51);
output.writeByte(message.p52);
output.writeByte(message.p53);
output.writeByte(message.p54);
output.writeByte(message.p55);
output.writeByte(message.p56);
output.writeByte(message.p57);
output.writeByte(message.p58);
output.writeByte(message.p59);
output.writeByte(message.p60);
output.writeByte(message.p61);
output.writeByte(message.p62);
output.writeByte(message.p63);
output.writeByte(message.p64);
}
}
}
\ 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 ParamImageIdentifyAlarm {
public static final Integer key = 0x007B;
@Field(length = 1, desc = "车辆核载人数,客运车辆核定载客人数,视频分析结果超过时产生报警")
private byte overloadThreshold;
@Field(length = 1, desc = "疲劳程度阈值,视频分析疲劳驾驶报警阈值,超过时产生报警")
private byte fatigueThreshold;
public ParamImageIdentifyAlarm() {
}
public byte getOverloadThreshold() {
return overloadThreshold;
}
public void setOverloadThreshold(byte overloadThreshold) {
this.overloadThreshold = overloadThreshold;
}
public byte getFatigueThreshold() {
return fatigueThreshold;
}
public void setFatigueThreshold(byte fatigueThreshold) {
this.fatigueThreshold = fatigueThreshold;
}
@Override
public String toString() {
return "ParamImageIdentifyAlarm{" +
"overloadThreshold=" + overloadThreshold +
", fatigueThreshold=" + fatigueThreshold +
'}';
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.parameter;
import io.github.yezhihao.protostar.annotation.Field;
import java.time.LocalTime;
/**
* 终端休眠唤醒模式设置数据格式
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamSleepWake {
public static final Integer key = 0x007C;
@Field(length = 1, desc = "休眠唤醒模式:[0]条件唤醒 [1]定时唤醒 [2]手动唤醒")
private int mode;
@Field(length = 1, desc = "唤醒条件类型:[0]紧急报警 [1]碰撞侧翻报警 [2]车辆开门,休眠唤醒模式中[0]为1时此字段有效,否则置0")
private int conditionType;
@Field(length = 1, desc = "周定时唤醒日设置:[0]周一 [1]周二 [2]周三 [3]周四 [4]周五 [5]周六 [6]周日")
private int dayOfWeek;
@Field(length = 1, desc = "日定时唤醒启用标志:[0]启用时间段1 [1]启用时间段2 [2]启用时间段3 [3]启用时间段4)")
private int timeFlag;
@Field(length = 2, charset = "BCD", desc = "时间段1唤醒时间")
private LocalTime wakeTime1 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段1关闭时间")
private LocalTime sleepTime1 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段2唤醒时间")
private LocalTime wakeTime2 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段2关闭时间")
private LocalTime sleepTime2 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段3唤醒时间")
private LocalTime wakeTime3 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段3关闭时间")
private LocalTime sleepTime3 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段4唤醒时间")
private LocalTime wakeTime4 = LocalTime.MIN;
@Field(length = 2, charset = "BCD", desc = "时间段4关闭时间")
private LocalTime sleepTime4 = LocalTime.MIN;
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
}
public int getConditionType() {
return conditionType;
}
public void setConditionType(int conditionType) {
this.conditionType = conditionType;
}
public int getDayOfWeek() {
return dayOfWeek;
}
public void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
public int getTimeFlag() {
return timeFlag;
}
public void setTimeFlag(int timeFlag) {
this.timeFlag = timeFlag;
}
public LocalTime getWakeTime1() {
return wakeTime1;
}
public void setWakeTime1(LocalTime wakeTime1) {
this.wakeTime1 = wakeTime1;
}
public LocalTime getSleepTime1() {
return sleepTime1;
}
public void setSleepTime1(LocalTime sleepTime1) {
this.sleepTime1 = sleepTime1;
}
public LocalTime getWakeTime2() {
return wakeTime2;
}
public void setWakeTime2(LocalTime wakeTime2) {
this.wakeTime2 = wakeTime2;
}
public LocalTime getSleepTime2() {
return sleepTime2;
}
public void setSleepTime2(LocalTime sleepTime2) {
this.sleepTime2 = sleepTime2;
}
public LocalTime getWakeTime3() {
return wakeTime3;
}
public void setWakeTime3(LocalTime wakeTime3) {
this.wakeTime3 = wakeTime3;
}
public LocalTime getSleepTime3() {
return sleepTime3;
}
public void setSleepTime3(LocalTime sleepTime3) {
this.sleepTime3 = sleepTime3;
}
public LocalTime getWakeTime4() {
return wakeTime4;
}
public void setWakeTime4(LocalTime wakeTime4) {
this.wakeTime4 = wakeTime4;
}
public LocalTime getSleepTime4() {
return sleepTime4;
}
public void setSleepTime4(LocalTime sleepTime4) {
this.sleepTime4 = sleepTime4;
}
@Override
public String toString() {
return "ParamSleepWake{" +
"mode=" + mode +
", conditionType=" + conditionType +
", dayOfWeek=" + dayOfWeek +
", timeFlag=" + timeFlag +
", wakeTime1=" + wakeTime1 +
", sleepTime1=" + sleepTime1 +
", wakeTime2=" + wakeTime2 +
", sleepTime2=" + sleepTime2 +
", wakeTime3=" + wakeTime3 +
", sleepTime3=" + sleepTime3 +
", wakeTime4=" + wakeTime4 +
", sleepTime4=" + sleepTime4 +
'}';
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.parameter;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import java.nio.charset.StandardCharsets;
/**
* 胎压监测系统参数
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamTPMS {
public static final Integer key = 0xF366;
public static final Schema<ParamTPMS> SCHEMA = new ParamTPMSSchema();
@Field(desc = "轮胎规格型号(例:195/65R1591V,12个字符,默认值'900R20')")
private String tireType;
@Field(desc = "胎压单位:0.kg/cm2 1.bar 2.Kpa 3.PSI(默认值3)")
private int pressureUnit = -1;
@Field(desc = "正常胎压值(同胎压单位,默认值140)")
private int normalValue = -1;
@Field(desc = "胎压不平衡报警阈值(百分比0~100,达到冷态气压值,默认值20)")
private int imbalanceThreshold = -1;
@Field(desc = "慢漏气报警阈值(百分比0~100,达到冷态气压值,默认值5)")
private int lowLeakThreshold = -1;
@Field(desc = "低压报警阈值(同胎压单位,默认值110)")
private int lowPressureThreshold = -1;
@Field(desc = "高压报警阈值(同胎压单位,默认值189)")
private int highPressureThreshold = -1;
@Field(desc = "高温报警阈值(摄氏度,默认值80)")
private int highTemperatureThreshold = -1;
@Field(desc = "电压报警阈值(百分比0~100,默认值10)")
private int voltageThreshold = -1;
@Field(desc = "定时上报时间间隔(秒,取值0~3600,默认值60,0表示不上报)")
private int reportInterval = -1;
@Field(desc = "保留项")
private byte[] reserved = new byte[6];
public String getTireType() {
return tireType;
}
public void setTireType(String tireType) {
this.tireType = tireType;
}
public int getPressureUnit() {
return pressureUnit;
}
public void setPressureUnit(int pressureUnit) {
this.pressureUnit = pressureUnit;
}
public int getNormalValue() {
return normalValue;
}
public void setNormalValue(int normalValue) {
this.normalValue = normalValue;
}
public int getImbalanceThreshold() {
return imbalanceThreshold;
}
public void setImbalanceThreshold(int imbalanceThreshold) {
this.imbalanceThreshold = imbalanceThreshold;
}
public int getLowLeakThreshold() {
return lowLeakThreshold;
}
public void setLowLeakThreshold(int lowLeakThreshold) {
this.lowLeakThreshold = lowLeakThreshold;
}
public int getLowPressureThreshold() {
return lowPressureThreshold;
}
public void setLowPressureThreshold(int lowPressureThreshold) {
this.lowPressureThreshold = lowPressureThreshold;
}
public int getHighPressureThreshold() {
return highPressureThreshold;
}
public void setHighPressureThreshold(int highPressureThreshold) {
this.highPressureThreshold = highPressureThreshold;
}
public int getHighTemperatureThreshold() {
return highTemperatureThreshold;
}
public void setHighTemperatureThreshold(int highTemperatureThreshold) {
this.highTemperatureThreshold = highTemperatureThreshold;
}
public int getVoltageThreshold() {
return voltageThreshold;
}
public void setVoltageThreshold(int voltageThreshold) {
this.voltageThreshold = voltageThreshold;
}
public int getReportInterval() {
return reportInterval;
}
public void setReportInterval(int reportInterval) {
this.reportInterval = reportInterval;
}
public byte[] getReserved() {
return reserved;
}
public void setReserved(byte[] reserved) {
this.reserved = reserved;
}
private static class ParamTPMSSchema implements Schema<ParamTPMS> {
private ParamTPMSSchema() {
}
@Override
public ParamTPMS readFrom(ByteBuf input) {
ParamTPMS message = new ParamTPMS();
message.tireType = input.readCharSequence(12, StandardCharsets.US_ASCII).toString();
message.pressureUnit = input.readShort();
message.normalValue = input.readShort();
message.imbalanceThreshold = input.readShort();
message.lowLeakThreshold = input.readShort();
message.lowPressureThreshold = input.readShort();
message.highPressureThreshold = input.readShort();
message.highTemperatureThreshold = input.readShort();
message.voltageThreshold = input.readShort();
message.reportInterval = input.readShort();
input.readBytes(message.reserved);
return message;
}
@Override
public void writeTo(ByteBuf output, ParamTPMS message) {
byte[] bytes = message.getTireType().getBytes(StandardCharsets.US_ASCII);
ByteBufUtils.writeFixedLength(output, 12, bytes);
output.writeShort(message.pressureUnit);
output.writeShort(message.normalValue);
output.writeShort(message.imbalanceThreshold);
output.writeShort(message.lowLeakThreshold);
output.writeShort(message.lowPressureThreshold);
output.writeShort(message.highPressureThreshold);
output.writeShort(message.highTemperatureThreshold);
output.writeShort(message.voltageThreshold);
output.writeShort(message.reportInterval);
ByteBufUtils.writeFixedLength(output, 6, message.getReserved());
}
}
}
\ No newline at end of file
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;
/**
* 音视频参数设置
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamVideo {
public static final Integer key = 0x0075;
public static final Schema<ParamVideo> SCHEMA = new ParamVideoSchema();
protected static final Schema<ParamVideo> SCHEMA_2 = new ParamVideoSchema2();
@Field(desc = "实时流编码模式:0.CBR(固定码率) 1.VBR(可变码率) 2.ABR(平均码率) 100~ 127.自定义")
private byte realtimeEncode;
@Field(desc = "实时流分辨率:0.QCIF 1.CIF 2.WCIF 3.D1 4.WD1 5.720P 6.1080P 100~127.自定义")
private byte realtimeResolution;
@Field(desc = "实时流关键帧间隔(1~1000帧)")
private short realtimeFrameInterval;
@Field(desc = "实时流目标帧率(1~120帧)")
private byte realtimeFrameRate;
@Field(desc = "实时流目标码率(kbps)")
private int realtimeBitRate;
@Field(desc = "存储流编码模式:0.CBR(固定码率) 1.VBR(可变码率) 2.ABR(平均码率) 100~ 127.自定义")
private byte storageEncode;
@Field(desc = "存储流分辨率:0.QCIF 1.CIF 2.WCIF 3.D1 4.WD1 5.720P 6.1080P 100~127.自定义")
private byte storageResolution;
@Field(desc = "存储流关键帧间隔(1~1000帧)")
private short storageFrameInterval;
@Field(desc = "存储流目标帧率(1~120帧)")
private byte storageFrameRate;
@Field(desc = "存储流目标码率(kbps)")
private int storageBitRate;
@Field(desc = "OSD字幕叠加设置(按位,0.表示不叠加 1.表示叠加):" +
" [0]日期和时间" +
" [1]车牌号码" +
" [2]逻辑通道号" +
" [3]经纬度" +
" [4]行驶记录速度" +
" [5]卫星定位速度" +
" [6]连续驾驶时间" +
" [7~l0]保留" +
" [11~l5]自定义")
private short odsConfig;
@Field(desc = "是否启用音频输出:0.不启用 1.启用")
private byte audioEnable;
public ParamVideo() {
}
public byte getRealtimeEncode() {
return realtimeEncode;
}
public void setRealtimeEncode(byte realtimeEncode) {
this.realtimeEncode = realtimeEncode;
}
public byte getRealtimeResolution() {
return realtimeResolution;
}
public void setRealtimeResolution(byte realtimeResolution) {
this.realtimeResolution = realtimeResolution;
}
public short getRealtimeFrameInterval() {
return realtimeFrameInterval;
}
public void setRealtimeFrameInterval(short realtimeFrameInterval) {
this.realtimeFrameInterval = realtimeFrameInterval;
}
public byte getRealtimeFrameRate() {
return realtimeFrameRate;
}
public void setRealtimeFrameRate(byte realtimeFrameRate) {
this.realtimeFrameRate = realtimeFrameRate;
}
public int getRealtimeBitRate() {
return realtimeBitRate;
}
public void setRealtimeBitRate(int realtimeBitRate) {
this.realtimeBitRate = realtimeBitRate;
}
public byte getStorageEncode() {
return storageEncode;
}
public void setStorageEncode(byte storageEncode) {
this.storageEncode = storageEncode;
}
public byte getStorageResolution() {
return storageResolution;
}
public void setStorageResolution(byte storageResolution) {
this.storageResolution = storageResolution;
}
public short getStorageFrameInterval() {
return storageFrameInterval;
}
public void setStorageFrameInterval(short storageFrameInterval) {
this.storageFrameInterval = storageFrameInterval;
}
public byte getStorageFrameRate() {
return storageFrameRate;
}
public void setStorageFrameRate(byte storageFrameRate) {
this.storageFrameRate = storageFrameRate;
}
public int getStorageBitRate() {
return storageBitRate;
}
public void setStorageBitRate(int storageBitRate) {
this.storageBitRate = storageBitRate;
}
public short getOdsConfig() {
return odsConfig;
}
public void setOdsConfig(short odsConfig) {
this.odsConfig = odsConfig;
}
public byte getAudioEnable() {
return audioEnable;
}
public void setAudioEnable(byte audioEnable) {
this.audioEnable = audioEnable;
}
private static class ParamVideoSchema implements Schema<ParamVideo> {
private ParamVideoSchema() {
}
@Override
public ParamVideo readFrom(ByteBuf input) {
ParamVideo message = new ParamVideo();
message.realtimeEncode = input.readByte();
message.realtimeResolution = input.readByte();
message.realtimeFrameInterval = input.readShort();
message.realtimeFrameRate = input.readByte();
message.realtimeBitRate = input.readInt();
message.storageEncode = input.readByte();
message.storageResolution = input.readByte();
message.storageFrameInterval = input.readShort();
message.storageFrameRate = input.readByte();
message.storageBitRate = input.readInt();
message.odsConfig = input.readShort();
message.audioEnable = input.readByte();
return message;
}
@Override
public void writeTo(ByteBuf output, ParamVideo message) {
output.writeByte(message.realtimeEncode);
output.writeByte(message.realtimeResolution);
output.writeShort(message.realtimeFrameInterval);
output.writeByte(message.realtimeFrameRate);
output.writeInt(message.realtimeBitRate);
output.writeByte(message.storageEncode);
output.writeByte(message.storageResolution);
output.writeShort(message.storageFrameInterval);
output.writeByte(message.storageFrameRate);
output.writeInt(message.storageBitRate);
output.writeShort(message.odsConfig);
output.writeByte(message.audioEnable);
}
}
public static class ParamVideoSchema2 implements Schema<ParamVideo> {
private ParamVideoSchema2() {
}
@Override
public ParamVideo readFrom(ByteBuf input) {
ParamVideo message = new ParamVideo();
message.realtimeEncode = input.readByte();
message.realtimeResolution = input.readByte();
message.realtimeFrameInterval = input.readShort();
message.realtimeFrameRate = input.readByte();
message.realtimeBitRate = input.readInt();
message.storageEncode = input.readByte();
message.storageResolution = input.readByte();
message.storageFrameInterval = input.readShort();
message.storageFrameRate = input.readByte();
message.storageBitRate = input.readInt();
message.odsConfig = input.readShort();
return message;
}
@Override
public void writeTo(ByteBuf output, ParamVideo message) {
output.writeByte(message.realtimeEncode);
output.writeByte(message.realtimeResolution);
output.writeShort(message.realtimeFrameInterval);
output.writeByte(message.realtimeFrameRate);
output.writeInt(message.realtimeBitRate);
output.writeByte(message.storageEncode);
output.writeByte(message.storageResolution);
output.writeShort(message.storageFrameInterval);
output.writeByte(message.storageFrameRate);
output.writeInt(message.storageBitRate);
output.writeShort(message.odsConfig);
}
}
}
\ No newline at end of file
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.Map;
import java.util.TreeMap;
/**
* 单独视频通道参数设置
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class ParamVideoSingle {
public static final Integer key = 0x0077;
public static final Schema<ParamVideoSingle> SCHEMA = new ParamVideoSingleSchema();
@Field(desc = "单独通道视频参数设置列表")
private Map<Integer, ParamVideo> paramVideos = new TreeMap<>();
public ParamVideoSingle() {
}
public ParamVideoSingle(Map<Integer, ParamVideo> paramVideos) {
this.paramVideos = paramVideos;
}
public Map<Integer, ParamVideo> getParamVideos() {
return paramVideos;
}
public void setParamVideos(Map<Integer, ParamVideo> paramVideos) {
this.paramVideos = paramVideos;
}
private static class ParamVideoSingleSchema implements Schema<ParamVideoSingle> {
private ParamVideoSingleSchema() {
}
@Override
public ParamVideoSingle readFrom(ByteBuf input) {
byte total = input.readByte();
Map<Integer, ParamVideo> paramVideos = new TreeMap<>();
for (int i = 0; i < total; i++) {
byte channelNo = input.readByte();
ParamVideo paramVideo = ParamVideo.SCHEMA_2.readFrom(input);
paramVideos.put((int) channelNo, paramVideo);
}
return new ParamVideoSingle(paramVideos);
}
@Override
public void writeTo(ByteBuf output, ParamVideoSingle message) {
Map<Integer, ParamVideo> paramVideos = message.paramVideos;
output.writeByte(message.paramVideos.size());
for (Map.Entry<Integer, ParamVideo> videoEntry : paramVideos.entrySet()) {
output.writeByte(videoEntry.getKey());
ParamVideo.SCHEMA_2.writeTo(output, videoEntry.getValue());
}
}
}
}
\ 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 ParamVideoSpecialAlarm {
public static final Integer key = 0x0079;
@Field(length = 1, desc = "特殊报警录像存储阈值(占用主存储器存储阈值百分比,取值1~99.默认值为20)")
private byte storageThreshold;
@Field(length = 1, desc = "特殊报警录像持续时间,特殊报警录像的最长持续时间(分钟),默认值为5")
private byte duration;
@Field(length = 1, desc = "特殊报警标识起始时间,特殊报警发生前进行标记的录像时间(分钟),默认值为1")
private byte startTime;
public byte getStorageThreshold() {
return storageThreshold;
}
public void setStorageThreshold(byte storageThreshold) {
this.storageThreshold = storageThreshold;
}
public byte getDuration() {
return duration;
}
public void setDuration(byte duration) {
this.duration = duration;
}
public byte getStartTime() {
return startTime;
}
public void setStartTime(byte startTime) {
this.startTime = startTime;
}
@Override
public String toString() {
return "ParamVideoSpecialAlarm{" +
"storageThreshold=" + storageThreshold +
", duration=" + duration +
", startTime=" + startTime +
'}';
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.parameter;
import io.github.yezhihao.protostar.Schema;
import io.netty.buffer.ByteBuf;
import java.time.LocalTime;
import static io.github.yezhihao.protostar.util.DateTool.BCD;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class TimeRange {
public static final Schema<TimeRange> SCHEMA = new TimeRangeSchema();
private LocalTime startTime;
private LocalTime endTime;
public TimeRange() {
}
public TimeRange(LocalTime startTime, LocalTime endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
public LocalTime getStartTime() {
return startTime;
}
public void setStartTime(LocalTime startTime) {
this.startTime = startTime;
}
public LocalTime getEndTime() {
return endTime;
}
public void setEndTime(LocalTime endTime) {
this.endTime = endTime;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(32);
sb.append('{');
sb.append("startTime=").append(startTime);
sb.append(", endTime=").append(endTime);
sb.append('}');
return sb.toString();
}
private static class TimeRangeSchema implements Schema<TimeRange> {
private TimeRangeSchema() {
}
@Override
public TimeRange readFrom(ByteBuf input) {
TimeRange message = new TimeRange();
message.startTime = BCD.readTime2(input);
message.endTime = BCD.readTime2(input);
return message;
}
@Override
public void writeTo(ByteBuf output, TimeRange message) {
BCD.writeTime2(output, message.startTime);
BCD.writeTime2(output, message.endTime);
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.passthrough;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
/**
* 状态查询
* 外设状态信息:外设工作状态、设备报警信息
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class PeripheralStatus {
public static final Integer key = 0xF7;
private List<Item> items;
public PeripheralStatus() {
}
public PeripheralStatus(List<Item> items) {
this.items = items;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(byte id, byte workState, int alarmStatus) {
if (items == null)
items = new ArrayList<>(4);
items.add(new Item(id, workState, alarmStatus));
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(150);
sb.append("PeripheralStatus{");
sb.append("items=").append(items);
sb.append('}');
return sb.toString();
}
public static class Item {
/**
* 外设ID:
* 100.高级驾驶辅助系统(ADAS)
* 101.驾驶员状态监控系统(DSM)
* 102.轮胎气压监测系统(TPMS)
* 103.盲点监测系统(BSD)
*/
private byte id;
/** 工作状态:1.正常工作 2.待机状态 3.升级维护 4.设备异常 16.断开连接 */
private byte workState;
/**
* 报警状态:
* 按位设置:0.表示无 1.表示有
* [0]摄像头异常
* [1]主存储器异常
* [2]辅存储器异常
* [3]红外补光异常
* [4]扬声器异常
* [5]电池异常
* [6~9]预留
* [10]通讯模块异常
* [ll]定位模块异常
* [12~31]预留
*/
private int alarmStatus;
public Item() {
}
public Item(byte id, byte workState, int alarmStatus) {
this.id = id;
this.workState = workState;
this.alarmStatus = alarmStatus;
}
public byte getId() {
return id;
}
public void setId(byte id) {
this.id = id;
}
public byte getWorkState() {
return workState;
}
public void setWorkState(byte workState) {
this.workState = workState;
}
public int getAlarmStatus() {
return alarmStatus;
}
public void setAlarmStatus(int alarmStatus) {
this.alarmStatus = alarmStatus;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(50);
sb.append("{id=").append(id);
sb.append(", workState=").append(workState);
sb.append(", alarmStatus=").append(Integer.toBinaryString(alarmStatus));
sb.append('}');
return sb.toString();
}
}
public static class Schema implements io.github.yezhihao.protostar.Schema<PeripheralStatus> {
public static final Schema INSTANCE = new Schema();
private Schema() {
}
@Override
public PeripheralStatus readFrom(ByteBuf input) {
byte total = input.readByte();
List<Item> list = new ArrayList<>(total);
for (int i = 0; i < total && input.isReadable(); i++) {
Item item = new Item();
item.id = input.readByte();
int len = input.readUnsignedByte();
item.workState = input.readByte();
item.alarmStatus = input.readInt();
input.skipBytes(len - 5);
list.add(item);
}
return new PeripheralStatus(list);
}
@Override
public void writeTo(ByteBuf output, PeripheralStatus message) {
List<Item> items = message.getItems();
output.writeByte(items.size());
for (Item item : items) {
output.writeByte(item.id);
output.writeByte(5);
output.writeByte(item.workState);
output.writeInt(item.alarmStatus);
}
}
}
}
\ No newline at end of file
package com.zehong.protocol.commons.transform.passthrough;
import com.zehong.protocol.commons.Charsets;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
/**
* 信息查询
* 外设传感器的基本信息:公司信息、产品代码、版本号、外设ID、客户代码
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class PeripheralSystem {
public static final Integer key = 0xF8;
private List<Item> items;
public PeripheralSystem() {
}
public PeripheralSystem(List<Item> items) {
this.items = items;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(byte id, String companyName, String productModel, String hardwareVersion, String firmwareVersion, String deviceId, String userCode) {
if (items == null)
items = new ArrayList<>(4);
items.add(new Item(id, companyName, productModel, hardwareVersion, firmwareVersion, deviceId, userCode));
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(360);
sb.append('{');
sb.append("items=").append(items);
sb.append('}');
return sb.toString();
}
public static class Item {
private byte id;
private String companyName;
private String productModel;
private String hardwareVersion;
private String firmwareVersion;
private String deviceId;
private String userCode;
public Item() {
}
public Item(byte id, String companyName, String productModel, String hardwareVersion, String firmwareVersion, String deviceId, String userCode) {
this.id = id;
this.companyName = companyName;
this.productModel = productModel;
this.hardwareVersion = hardwareVersion;
this.firmwareVersion = firmwareVersion;
this.deviceId = deviceId;
this.userCode = userCode;
}
public byte getId() {
return id;
}
public void setId(byte id) {
this.id = id;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getProductModel() {
return productModel;
}
public void setProductModel(String productModel) {
this.productModel = productModel;
}
public String getHardwareVersion() {
return hardwareVersion;
}
public void setHardwareVersion(String hardwareVersion) {
this.hardwareVersion = hardwareVersion;
}
public String getFirmwareVersion() {
return firmwareVersion;
}
public void setFirmwareVersion(String firmwareVersion) {
this.firmwareVersion = firmwareVersion;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(180);
sb.append('{');
sb.append("id=").append(id);
sb.append(",companyName=").append(companyName);
sb.append(",productModel=").append(productModel);
sb.append(",hardwareVersion=").append(hardwareVersion);
sb.append(",firmwareVersion=").append(firmwareVersion);
sb.append(",deviceId=").append(deviceId);
sb.append(",userCode=").append(userCode);
sb.append('}');
return sb.toString();
}
}
public static class Schema implements io.github.yezhihao.protostar.Schema<PeripheralSystem> {
public static final Schema INSTANCE = new Schema();
private Schema() {
}
@Override
public PeripheralSystem readFrom(ByteBuf input) {
byte total = input.readByte();
List<Item> list = new ArrayList<>(total);
while (input.isReadable()) {
Item item = new Item();
item.id = input.readByte();
input.readByte();
item.companyName = input.readCharSequence(input.readByte(), Charsets.GBK).toString();
item.productModel = input.readCharSequence(input.readByte(), Charsets.GBK).toString();
item.hardwareVersion = input.readCharSequence(input.readByte(), Charsets.GBK).toString();
item.firmwareVersion = input.readCharSequence(input.readByte(), Charsets.GBK).toString();
item.deviceId = input.readCharSequence(input.readByte(), Charsets.GBK).toString();
item.userCode = input.readCharSequence(input.readByte(), Charsets.GBK).toString();
list.add(item);
}
return new PeripheralSystem(list);
}
@Override
public void writeTo(ByteBuf output, PeripheralSystem message) {
List<Item> items = message.getItems();
output.writeByte(items.size());
byte[] bytes;
for (Item item : items) {
output.writeByte(item.id);
int begin = output.writerIndex();
output.writeByte(0);
bytes = item.companyName.getBytes(Charsets.GBK);
output.writeByte(bytes.length).writeBytes(bytes);
bytes = item.productModel.getBytes(Charsets.GBK);
output.writeByte(bytes.length).writeBytes(bytes);
bytes = item.hardwareVersion.getBytes(Charsets.GBK);
output.writeByte(bytes.length).writeBytes(bytes);
bytes = item.firmwareVersion.getBytes(Charsets.GBK);
output.writeByte(bytes.length).writeBytes(bytes);
bytes = item.deviceId.getBytes(Charsets.GBK);
output.writeByte(bytes.length).writeBytes(bytes);
bytes = item.userCode.getBytes(Charsets.GBK);
output.writeByte(bytes.length).writeBytes(bytes);
int len = output.writerIndex() - begin - 1;
output.setByte(begin, len);
}
}
}
}
\ No newline at end of file
package com.zehong.protocol.jsatl12;
import com.zehong.protocol.basics.JTMessage;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.netty.buffer.ByteBuf;
/**
* 文件数据上传
* 帧头标识 0x30 0x31 0x63 0x64
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message
public class DataPacket extends JTMessage {
@Field(length = 4, desc = "帧头标识")
private int flag;
@Field(length = 50, desc = "文件名称(文件类型_通道号_报警类型_序号_报警编号.后缀名)")
private String name;
@Field(length = 4, desc = "数据偏移量")
private int offset;
@Field(length = 4, desc = "数据长度")
private int length;
@Field(desc = "数据体")
private ByteBuf data;
@Override
public String getClientId() {
if (session != null)
return session.getClientId();
return null;
}
@Override
public int getMessageId() {
return flag;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public ByteBuf getData() {
return data;
}
public void setData(ByteBuf data) {
this.data = data;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(120);
sb.append("DataPacket{name=").append(name);
sb.append(",offset=").append(offset);
sb.append(",length=").append(length);
sb.append(",data=").append(data);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.jsatl12;
import com.zehong.commons.util.StrUtils;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JSATL12;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JSATL12.报警附件信息消息)
public class T1210 extends JTMessage {
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID(粤标)", version = 1)
private String deviceId;
@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(length = 32, desc = "报警编号")
private String platformAlarmId;
@Field(length = 1, desc = "信息类型:0.正常报警文件信息 1.补传报警文件信息")
private int type;
@Field(totalUnit = 1, desc = "附件信息列表")
private List<Item> items;
public String getDeviceId() {
if (StrUtils.isBlank(deviceId))
return deviceId_;
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = 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 String getPlatformAlarmId() {
return platformAlarmId;
}
public void setPlatformAlarmId(String platformAlarmId) {
this.platformAlarmId = platformAlarmId;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public static class Item {
@Field(lengthUnit = 1, desc = "文件名称")
private String name;
@Field(length = 4, desc = "文件大小")
private long size;
private transient T1210 parent;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public T1210 parent() {
return parent;
}
public Item parent(T1210 parent) {
this.parent = parent;
return this;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(80);
sb.append("{name=").append(name);
sb.append(",size=").append(size);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.jsatl12;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JSATL12;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JSATL12.文件信息上传, JSATL12.文件上传完成消息})
public class T1211 extends JTMessage {
@Field(lengthUnit = 1, desc = "文件名称")
private String name;
@Field(length = 1, desc = "文件类型 0.图片 1.音频 2.视频 3.文本 4.面部特征图片(粤标) 5.其它")
private int type;
@Field(length = 4, desc = "文件大小")
private long size;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
}
\ No newline at end of file
package com.zehong.protocol.jsatl12;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JSATL12;
import java.time.LocalDateTime;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JSATL12.报警附件上传指令)
public class T9208 extends JTMessage {
private static final byte[] RESERVES = new byte[16];
@Field(lengthUnit = 1, desc = "服务器IP地址")
private String ip;
@Field(length = 2, desc = "TCP端口")
private int tcpPort;
@Field(length = 2, desc = "UDP端口")
private int udpPort;
@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(length = 32, desc = "报警编号")
private String platformAlarmId;
@Field(length = 16, desc = "预留")
private byte[] reserves = RESERVES;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getTcpPort() {
return tcpPort;
}
public void setTcpPort(int tcpPort) {
this.tcpPort = tcpPort;
}
public int getUdpPort() {
return udpPort;
}
public void setUdpPort(int udpPort) {
this.udpPort = udpPort;
}
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 String getPlatformAlarmId() {
return platformAlarmId;
}
public void setPlatformAlarmId(String platformAlarmId) {
this.platformAlarmId = platformAlarmId;
}
public byte[] getReserves() {
return reserves;
}
public void setReserves(byte[] reserves) {
this.reserves = reserves;
}
}
\ No newline at end of file
package com.zehong.protocol.jsatl12;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JSATL12;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JSATL12.文件上传完成消息应答)
public class T9212 extends JTMessage {
@Field(lengthUnit = 1, desc = "文件名称(文件类型_通道号_报警类型_序号_报警编号.后缀名)")
private String name;
@Field(length = 1, desc = "文件类型:0.图片 1.音频 2.视频 3.文本 4.面部特征图片(粤标) 5.其它")
private int type;
@Field(length = 1, desc = "上传结果:0.完成 1.需要补传")
private int result;
@Field(length = 1, desc = "补传数据包数量")
private int total;
@Field(desc = "补传数据包列表[offset,length,offset,length...]")
private int[] items;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int[] getItems() {
return items;
}
public void setItems(int[] items) {
if (items != null && items.length > 1) {
this.items = items;
this.total = items.length / 2;
}
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.终端上传音视频属性)
public class T1003 extends JTMessage {
@Field(length = 1, desc = "输入音频编码方式")
private int audioFormat;
@Field(length = 1, desc = "输入音频声道数")
private int audioChannels;
@Field(length = 1, desc = "输入音频采样率:0.8kHz 1.22.05kHz 2.44.1kHz 3.48kHz")
private int audioSamplingRate;
@Field(length = 1, desc = "输入音频采样位数:0.8位 1.16位 2.32位")
private int audioBitDepth;
@Field(length = 2, desc = "音频帧长度")
private int audioFrameLength;
@Field(length = 1, desc = "是否支持音频输出")
private int audioSupport;
@Field(length = 1, desc = "视频编码方式")
private int videoFormat;
@Field(length = 1, desc = "终端支持的最大音频物理通道")
private int maxAudioChannels;
@Field(length = 1, desc = "终端支持的最大视频物理通道")
private int maxVideoChannels;
public int getAudioFormat() {
return audioFormat;
}
public void setAudioFormat(int audioFormat) {
this.audioFormat = audioFormat;
}
public int getAudioChannels() {
return audioChannels;
}
public void setAudioChannels(int audioChannels) {
this.audioChannels = audioChannels;
}
public int getAudioSamplingRate() {
return audioSamplingRate;
}
public void setAudioSamplingRate(int audioSamplingRate) {
this.audioSamplingRate = audioSamplingRate;
}
public int getAudioBitDepth() {
return audioBitDepth;
}
public void setAudioBitDepth(int audioBitDepth) {
this.audioBitDepth = audioBitDepth;
}
public int getAudioFrameLength() {
return audioFrameLength;
}
public void setAudioFrameLength(int audioFrameLength) {
this.audioFrameLength = audioFrameLength;
}
public int getAudioSupport() {
return audioSupport;
}
public void setAudioSupport(int audioSupport) {
this.audioSupport = audioSupport;
}
public int getVideoFormat() {
return videoFormat;
}
public void setVideoFormat(int videoFormat) {
this.videoFormat = videoFormat;
}
public int getMaxAudioChannels() {
return maxAudioChannels;
}
public void setMaxAudioChannels(int maxAudioChannels) {
this.maxAudioChannels = maxAudioChannels;
}
public int getMaxVideoChannels() {
return maxVideoChannels;
}
public void setMaxVideoChannels(int maxVideoChannels) {
this.maxVideoChannels = maxVideoChannels;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.终端上传乘客流量)
public class T1005 extends JTMessage {
@Field(length = 6, charset = "BCD", desc = "起始时间(YYMMDDHHMMSS)")
private String startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(YYMMDDHHMMSS)")
private String endTime;
@Field(length = 2, desc = "从起始时间到结束时间的上车人数")
private int getOnCount;
@Field(length = 2, desc = "从起始时间到结束时间的下车人数")
private int getOffCount;
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public int getGetOnCount() {
return getOnCount;
}
public void setGetOnCount(int getOnCount) {
this.getOnCount = getOnCount;
}
public int getGetOffCount() {
return getOffCount;
}
public void setGetOffCount(int getOffCount) {
this.getOffCount = getOffCount;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
import java.time.LocalDateTime;
import java.util.List;
@Message(JT1078.终端上传音视频资源列表)
public class T1205 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(totalUnit = 4, desc = "音视频资源列表")
private List<Item> items;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public static class Item {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 6, charset = "BCD", desc = "开始时间")
private LocalDateTime startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间")
private LocalDateTime endTime;
@Field(length = 4, desc = "报警标志0~31(参考808协议文档报警标志位定义)")
private int warnBit1;
@Field(length = 4, desc = "报警标志32~63")
private int warnBit2;
@Field(length = 1, desc = "音视频资源类型")
private int mediaType;
@Field(length = 1, desc = "码流类型")
private int streamType = 1;
@Field(length = 1, desc = "存储器类型")
private int storageType;
@Field(length = 4, desc = "文件大小")
private long size;
public Item() {
}
public Item(int channelNo, LocalDateTime startTime, LocalDateTime endTime, int warnBit1, int warnBit2, int mediaType, int streamType, int storageType, long size) {
this.channelNo = channelNo;
this.startTime = startTime;
this.endTime = endTime;
this.warnBit1 = warnBit1;
this.warnBit2 = warnBit2;
this.mediaType = mediaType;
this.streamType = streamType;
this.storageType = storageType;
this.size = size;
}
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public int getWarnBit1() {
return warnBit1;
}
public void setWarnBit1(int warnBit1) {
this.warnBit1 = warnBit1;
}
public int getWarnBit2() {
return warnBit2;
}
public void setWarnBit2(int warnBit2) {
this.warnBit2 = warnBit2;
}
public int getMediaType() {
return mediaType;
}
public void setMediaType(int mediaType) {
this.mediaType = mediaType;
}
public int getStreamType() {
return streamType;
}
public void setStreamType(int streamType) {
this.streamType = streamType;
}
public int getStorageType() {
return storageType;
}
public void setStorageType(int storageType) {
this.storageType = storageType;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(128);
sb.append('{');
sb.append("channelNo=").append(channelNo);
sb.append(",startTime=").append(startTime);
sb.append(",endTime=").append(endTime);
sb.append(",warnBit1=").append(Integer.toBinaryString(warnBit1));
sb.append(",warnBit2=").append(Integer.toBinaryString(warnBit2));
sb.append(",mediaType=").append(mediaType);
sb.append(",streamType=").append(streamType);
sb.append(",storageType=").append(storageType);
sb.append(",size=").append(size);
sb.append('}');
return sb.toString();
}
}
}
package com.zehong.protocol.t1078;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.文件上传完成通知)
public class T1206 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "结果:0.成功 1.失败")
private int result;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public boolean isSuccess() {
return result == 0;
}
}
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.实时音视频传输请求)
public class T9101 extends JTMessage {
@Field(lengthUnit = 1, desc = "服务器IP地址")
private String ip;
@Field(length = 2, desc = "实时视频服务器TCP端口号")
private int tcpPort;
@Field(length = 2, desc = "实时视频服务器UDP端口号")
private int udpPort;
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "数据类型:0.音视频 1.视频 2.双向对讲 3.监听 4.中心广播 5.透传")
private int mediaType;
@Field(length = 1, desc = "码流类型:0.主码流 1.子码流")
private int streamType;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getTcpPort() {
return tcpPort;
}
public void setTcpPort(int tcpPort) {
this.tcpPort = tcpPort;
}
public int getUdpPort() {
return udpPort;
}
public void setUdpPort(int udpPort) {
this.udpPort = udpPort;
}
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getMediaType() {
return mediaType;
}
public void setMediaType(int mediaType) {
this.mediaType = mediaType;
}
public int getStreamType() {
return streamType;
}
public void setStreamType(int streamType) {
this.streamType = streamType;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.音视频实时传输控制)
public class T9102 extends JTMessage {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "控制指令:" +
" 0.关闭音视频传输指令" +
" 1.切换码流(增加暂停和继续)" +
" 2.暂停该通道所有流的发送" +
" 3.恢复暂停前流的发送,与暂停前的流类型一致" +
" 4.关闭双向对讲")
private int command;
@Field(length = 1, desc = "关闭音视频类型:" +
" 0.关闭该通道有关的音视频数据" +
" 1.只关闭该通道有关的音频,保留该通道有关的视频" +
" 2.只关闭该通道有关的视频,保留该通道有关的音频")
private int closeType;
@Field(length = 1, desc = "切换码流类型:0.主码流 1.子码流")
private int streamType;
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getCommand() {
return command;
}
public void setCommand(int command) {
this.command = command;
}
public int getCloseType() {
return closeType;
}
public void setCloseType(int closeType) {
this.closeType = closeType;
}
public int getStreamType() {
return streamType;
}
public void setStreamType(int streamType) {
this.streamType = streamType;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.实时音视频传输状态通知)
public class T9105 extends JTMessage {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "丢包率")
private int packetLossRate;
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getPacketLossRate() {
return packetLossRate;
}
public void setPacketLossRate(int packetLossRate) {
this.packetLossRate = packetLossRate;
}
}
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.平台下发远程录像回放请求)
public class T9201 extends JTMessage {
@Field(lengthUnit = 1, desc = "服务器IP地址")
private String ip;
@Field(length = 2, desc = "实时视频服务器TCP端口号")
private int tcpPort;
@Field(length = 2, desc = "实时视频服务器UDP端口号")
private int udpPort;
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频")
private int mediaType;
@Field(length = 1, desc = "码流类型:0.所有码流 1.主码流 2.子码流(如果此通道只传输音频,此字段置0)")
private int streamType;
@Field(length = 1, desc = "存储器类型:0.所有存储器 1.主存储器 2.灾备存储器")
private int storageType;
@Field(length = 1, desc = "回放方式:0.正常回放 1.快进回放 2.关键帧快退回放 3.关键帧播放 4.单帧上传")
private int playbackMode;
@Field(length = 1, desc = "快进或快退倍数:0.无效 1.1倍 2.2倍 3.4倍 4.8倍 5.16倍 (回放控制为1和2时,此字段内容有效,否则置0)")
private int playbackSpeed;
@Field(length = 6, charset = "BCD", desc = "开始时间(YYMMDDHHMMSS,回放方式为4时,该字段表示单帧上传时间)")
private String startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(YYMMDDHHMMSS,回放方式为4时,该字段无效,为0表示一直回放)")
private String endTime;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getTcpPort() {
return tcpPort;
}
public void setTcpPort(int tcpPort) {
this.tcpPort = tcpPort;
}
public int getUdpPort() {
return udpPort;
}
public void setUdpPort(int udpPort) {
this.udpPort = udpPort;
}
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getMediaType() {
return mediaType;
}
public void setMediaType(int mediaType) {
this.mediaType = mediaType;
}
public int getStreamType() {
return streamType;
}
public void setStreamType(int streamType) {
this.streamType = streamType;
}
public int getStorageType() {
return storageType;
}
public void setStorageType(int storageType) {
this.storageType = storageType;
}
public int getPlaybackMode() {
return playbackMode;
}
public void setPlaybackMode(int playbackMode) {
this.playbackMode = playbackMode;
}
public int getPlaybackSpeed() {
return playbackSpeed;
}
public void setPlaybackSpeed(int playbackSpeed) {
this.playbackSpeed = playbackSpeed;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.平台下发远程录像回放控制)
public class T9202 extends JTMessage {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "回放控制:0.开始回放 1.暂停回放 2.结束回放 3.快进回放 4.关键帧快退回放 5.拖动回放 6.关键帧播放")
private int playbackMode;
@Field(length = 1, desc = "快进或快退倍数:0.无效 1.1倍 2.2倍 3.4倍 4.8倍 5.16倍 (回放控制为3和4时,此字段内容有效,否则置0)")
private int playbackSpeed;
@Field(length = 6, charset = "BCD", desc = "拖动回放位置(YYMMDDHHMMSS,回放控制为5时,此字段有效)")
private String playbackTime;
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getPlaybackMode() {
return playbackMode;
}
public void setPlaybackMode(int playbackMode) {
this.playbackMode = playbackMode;
}
public int getPlaybackSpeed() {
return playbackSpeed;
}
public void setPlaybackSpeed(int playbackSpeed) {
this.playbackSpeed = playbackSpeed;
}
public String getPlaybackTime() {
return playbackTime;
}
public void setPlaybackTime(String playbackTime) {
this.playbackTime = playbackTime;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.查询资源列表)
public class T9205 extends JTMessage {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 6, charset = "BCD", desc = "开始时间(YYMMDDHHMMSS,全0表示无起始时间)")
private String startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(YYMMDDHHMMSS,全0表示无终止时间)")
private String endTime;
@Field(length = 4, desc = "报警标志0~31(参考808协议文档报警标志位定义)")
private int warnBit1;
@Field(length = 4, desc = "报警标志32~63")
private int warnBit2;
@Field(length = 1, desc = "音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频")
private int mediaType;
@Field(length = 1, desc = "码流类型:0.所有码流 1.主码流 2.子码流")
private int streamType;
@Field(length = 1, desc = "存储器类型:0.所有存储器 1.主存储器 2.灾备存储器")
private int storageType;
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public int getWarnBit1() {
return warnBit1;
}
public void setWarnBit1(int warnBit1) {
this.warnBit1 = warnBit1;
}
public int getWarnBit2() {
return warnBit2;
}
public void setWarnBit2(int warnBit2) {
this.warnBit2 = warnBit2;
}
public int getMediaType() {
return mediaType;
}
public void setMediaType(int mediaType) {
this.mediaType = mediaType;
}
public int getStreamType() {
return streamType;
}
public void setStreamType(int streamType) {
this.streamType = streamType;
}
public int getStorageType() {
return storageType;
}
public void setStorageType(int storageType) {
this.storageType = storageType;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
import java.time.LocalDateTime;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.文件上传指令)
public class T9206 extends JTMessage {
@Field(lengthUnit = 1, desc = "服务器地址")
private String ip;
@Field(length = 2, desc = "端口")
private int port;
@Field(lengthUnit = 1, desc = "用户名")
private String username;
@Field(lengthUnit = 1, desc = "密码")
private String password;
@Field(lengthUnit = 1, desc = "文件上传路径")
private String path;
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 6, charset = "BCD", desc = "开始时间(YYMMDDHHMMSS)")
private LocalDateTime startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(YYMMDDHHMMSS)")
private LocalDateTime endTime;
@Field(length = 4, desc = "报警标志0~31(参考808协议文档报警标志位定义)")
private int warnBit1;
@Field(length = 4, desc = "报警标志32~63")
private int warnBit2;
@Field(length = 1, desc = "音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频")
private int mediaType;
@Field(length = 1, desc = "码流类型:0.所有码流 1.主码流 2.子码流")
private int streamType;
@Field(length = 1, desc = "存储位置:0.所有存储器 1.主存储器 2.灾备存储器")
private int storageType;
@Field(length = 1, desc = "任务执行条件(用bit位表示):[0]WIFI下可下载 [1]LAN连接时可下载 [2]3G/4G连接时可下载")
private int condition = -1;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public int getWarnBit1() {
return warnBit1;
}
public void setWarnBit1(int warnBit1) {
this.warnBit1 = warnBit1;
}
public int getWarnBit2() {
return warnBit2;
}
public void setWarnBit2(int warnBit2) {
this.warnBit2 = warnBit2;
}
public int getMediaType() {
return mediaType;
}
public void setMediaType(int mediaType) {
this.mediaType = mediaType;
}
public int getStreamType() {
return streamType;
}
public void setStreamType(int streamType) {
this.streamType = streamType;
}
public int getStorageType() {
return storageType;
}
public void setStorageType(int storageType) {
this.storageType = storageType;
}
public int getCondition() {
return condition;
}
public void setCondition(int condition) {
this.condition = condition;
}
public T9206 ip(String ip) {
this.ip = ip;
return this;
}
public T9206 port(int port) {
this.port = port;
return this;
}
public T9206 username(String username) {
this.username = username;
return this;
}
public T9206 password(String password) {
this.password = password;
return this;
}
public T9206 path(String path) {
this.path = path;
return this;
}
public T9206 channelNo(int channelNo) {
this.channelNo = channelNo;
return this;
}
public T9206 startTime(LocalDateTime startTime) {
this.startTime = startTime;
return this;
}
public T9206 endTime(LocalDateTime endTime) {
this.endTime = endTime;
return this;
}
public T9206 warnBit1(int warnBit1) {
this.warnBit1 = warnBit1;
return this;
}
public T9206 warnBit2(int warnBit2) {
this.warnBit2 = warnBit2;
return this;
}
public T9206 mediaType(int mediaType) {
this.mediaType = mediaType;
return this;
}
public T9206 streamType(int streamType) {
this.streamType = streamType;
return this;
}
public T9206 storageType(int storageType) {
this.storageType = storageType;
return this;
}
public T9206 condition(int condition) {
this.condition = condition;
return this;
}
}
\ No newline at end of file
package com.zehong.protocol.t1078;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.文件上传控制)
public class T9207 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "上传控制:0.暂停 1.继续 2.取消")
private int command;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getCommand() {
return command;
}
public void setCommand(int command) {
this.command = command;
}
}
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT1078.云台旋转)
public class T9301 extends JTMessage {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "方向:0.停止 1.上 2.下 3.左 4.右")
private int param1;
@Field(length = 1, desc = "速度(0~255)")
private int param2;
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getParam1() {
return param1;
}
public void setParam1(int param1) {
this.param1 = param1;
}
public int getParam2() {
return param2;
}
public void setParam2(int param2) {
this.param2 = param2;
}
}
package com.zehong.protocol.t1078;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JT1078.云台调整焦距控制, JT1078.云台调整光圈控制, JT1078.云台雨刷控制, JT1078.红外补光控制, JT1078.云台变倍控制})
public class T9302 extends JTMessage {
@Field(length = 1, desc = "逻辑通道号")
private int channelNo;
@Field(length = 1, desc = "参数(0.调大 1.调小)|(0.停止 1.启动)")
private int param;
public int getChannelNo() {
return channelNo;
}
public void setChannelNo(int channelNo) {
this.channelNo = channelNo;
}
public int getParam() {
return param;
}
public void setParam(int param) {
this.param = param;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JT808.平台通用应答, JT808.终端通用应答})
public class T0001 extends JTMessage implements Response {
public static final int Success = 0; //成功、确认
public static final int Failure = 1;//失败
public static final int MessageError = 2;//消息有误
public static final int NotSupport = 3;//不支持
public static final int AlarmAck = 4;//报警处理确认
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 2, desc = "应答ID")
private int responseMessageId;
@Field(length = 1, desc = "结果:0.成功 1.失败 2.消息有误 3.不支持 4.报警处理确认")
private int resultCode;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getResponseMessageId() {
return responseMessageId;
}
public void setResponseMessageId(int responseMessageId) {
this.responseMessageId = responseMessageId;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public boolean isSuccess() {
return this.resultCode == Success;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.终端注册)
public class T0100 extends JTMessage {
@Field(length = 2, desc = "省域ID")
private int provinceId;
@Field(length = 2, desc = "市县域ID")
private int cityId;
@Field(length = 5, desc = "制造商ID", version = {-1, 0})
@Field(length = 11, desc = "制造商ID", version = 1)
private String makerId;
@Field(length = 8, desc = "终端型号", version = -1)
@Field(length = 20, desc = "终端型号", version = 0)
@Field(length = 30, desc = "终端型号", version = 1)
private String deviceModel;
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID", version = 1)
private String deviceId;
@Field(length = 1, desc = "车牌颜色:0.未上车牌 1.蓝色 2.黄色 3.黑色 4.白色 9.其他")
private int plateColor;
@Field(desc = "车辆标识")
private String plateNo;
/** 设备安装车辆所在的省域,省域ID采用GB/T2260中规定的行政区划代码6位中前两位 */
public int getProvinceId() {
return provinceId;
}
public void setProvinceId(int provinceId) {
this.provinceId = provinceId;
}
/** 设备安装车辆所在的市域或县域,市县域ID采用GB/T2260中规定的行政区划代码6位中后四位 */
public int getCityId() {
return cityId;
}
public void setCityId(int cityId) {
this.cityId = cityId;
}
/** 终端制造商编码 */
public String getMakerId() {
return makerId;
}
public void setMakerId(String makerId) {
this.makerId = makerId;
}
/** 由制造商自行定义,位数不足时,后补"0x00" */
public String getDeviceModel() {
return deviceModel;
}
public void setDeviceModel(String deviceModel) {
this.deviceModel = deviceModel;
}
/** 由大写字母和数字组成,此终端ID由制造商自行定义 */
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
/** 按照JT/T415-2006的5.4.12 */
public int getPlateColor() {
return plateColor;
}
public void setPlateColor(int licensePlate) {
this.plateColor = licensePlate;
}
/** 车牌颜色为0时,表示车辆VIN 否则,表示公安交通管理部门颁发的机动车号牌 */
public String getPlateNo() {
return plateNo;
}
public void setPlateNo(String plateNo) {
this.plateNo = plateNo;
}
@Override
public int getProtocolVersion() {
int bodyLength = getBodyLength();
if (bodyLength > 0 && bodyLength < 37)
return -1;
return super.getProtocolVersion();
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.终端鉴权)
public class T0102 extends JTMessage {
/** 终端重连后上报鉴权码 */
@Field(desc = "鉴权码", version = {-1, 0})
@Field(lengthUnit = 1, desc = "鉴权码", version = 1)
private String token;
@Field(length = 15, desc = "终端IMEI", version = 1)
private String imei;
@Field(length = 20, desc = "软件版本号", version = 1)
private String softwareVersion;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
public String getSoftwareVersion() {
return softwareVersion;
}
public void setSoftwareVersion(String softwareVersion) {
this.softwareVersion = softwareVersion;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.ParameterConverter;
import java.util.Map;
import java.util.TreeMap;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.查询终端参数应答)
public class T0104 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "应答参数个数")
private int total;
@Field(desc = "参数项列表", converter = ParameterConverter.class)
private Map<Integer, Object> parameters;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public Map<Integer, Object> getParameters() {
return parameters;
}
public void setParameters(Map<Integer, Object> parameters) {
this.parameters = parameters;
this.total = parameters.size();
}
public void addParameter(Integer key, Object value) {
if (parameters == null)
parameters = new TreeMap();
parameters.put(key, value);
total = parameters.size();
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.查询终端属性应答)
public class T0107 extends JTMessage {
@Field(length = 2, desc = "终端类型")
private int deviceType;
@Field(length = 5, desc = "制造商ID,终端制造商编码")
private String makerId;
@Field(length = 20, desc = "终端型号", version = {-1, 0})
@Field(length = 30, desc = "终端型号", version = 1)
private String deviceModel;
@Field(length = 7, desc = "终端ID", version = {-1, 0})
@Field(length = 30, desc = "终端ID", version = 1)
private String deviceId;
@Field(length = 10, charset = "HEX", desc = "终端SIM卡ICCID")
private String iccid;
@Field(lengthUnit = 1, desc = "硬件版本号")
private String hardwareVersion;
@Field(lengthUnit = 1, desc = "固件版本号")
private String firmwareVersion;
@Field(length = 1, desc = "GNSS模块属性")
private int gnssAttribute;
@Field(length = 1, desc = "通信模块属性")
private int networkAttribute;
public int getDeviceType() {
return deviceType;
}
public void setDeviceType(int deviceType) {
this.deviceType = deviceType;
}
public String getMakerId() {
return makerId;
}
public void setMakerId(String makerId) {
this.makerId = makerId;
}
/** 由制造商自行定义,位数不足时,后补"0x00" */
public String getDeviceModel() {
return deviceModel;
}
public void setDeviceModel(String deviceModel) {
this.deviceModel = deviceModel;
}
/** 由大写字母和数字组成,此终端ID由制造商自行定义,位数不足时,后补"0x00" */
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getIccid() {
return iccid;
}
public void setIccid(String iccid) {
this.iccid = iccid;
}
public String getHardwareVersion() {
return hardwareVersion;
}
public void setHardwareVersion(String hardwareVersion) {
this.hardwareVersion = hardwareVersion;
}
public String getFirmwareVersion() {
return firmwareVersion;
}
public void setFirmwareVersion(String firmwareVersion) {
this.firmwareVersion = firmwareVersion;
}
public int getGnssAttribute() {
return gnssAttribute;
}
public void setGnssAttribute(int gnssAttribute) {
this.gnssAttribute = gnssAttribute;
}
public int getNetworkAttribute() {
return networkAttribute;
}
public void setNetworkAttribute(int networkAttribute) {
this.networkAttribute = networkAttribute;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.终端升级结果通知)
public class T0108 extends JTMessage {
/** 终端 */
public static final int Terminal = 0;
/** 道路运输证IC卡 读卡器 */
public static final int CardReader = 12;
/** 北斗卫星定位模块 */
public static final int Beidou = 52;
@Field(length = 1, desc = "升级类型:0.终端 12.道路运输证IC卡读卡器 52.北斗卫星定位模块")
private int type;
@Field(length = 1, desc = "升级结果:0.成功 1.失败 2.取消")
private int result;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.AttributeConverter;
import com.zehong.protocol.commons.transform.AttributeConverterYue;
import java.time.LocalDateTime;
import java.util.Map;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.位置信息汇报)
public class T0200 extends JTMessage {
/**
* 使用 Bit.isTrue判断报警和状态标志位
* @see com.zehong.protocol.commons.Bit
*/
@Field(length = 4, desc = "报警标志")
private int warnBit;
@Field(length = 4, desc = "状态")
private int statusBit;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 2, desc = "高程(米)")
private int altitude;
@Field(length = 2, desc = "速度(1/10公里每小时)")
private int speed;
@Field(length = 2, desc = "方向")
private int direction;
@Field(length = 6, charset = "BCD", desc = "时间(YYMMDDHHMMSS)")
private LocalDateTime deviceTime;
@Field(converter = AttributeConverter.class, desc = "位置附加信息", version = {-1, 0})
@Field(converter = AttributeConverterYue.class, desc = "位置附加信息(粤标)", version = 1)
private Map<Integer, Object> attributes;
public int getWarnBit() {
return warnBit;
}
public void setWarnBit(int warnBit) {
this.warnBit = warnBit;
}
public int getStatusBit() {
return statusBit;
}
public void setStatusBit(int statusBit) {
this.statusBit = statusBit;
}
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 int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public LocalDateTime getDeviceTime() {
return deviceTime;
}
public void setDeviceTime(LocalDateTime deviceTime) {
this.deviceTime = deviceTime;
}
public Map<Integer, Object> getAttributes() {
return attributes;
}
public void setAttributes(Map<Integer, Object> attributes) {
this.attributes = attributes;
}
@Override
public String toString() {
StringBuilder sb = toStringHead();
sb.append("T0200{deviceTime=").append(deviceTime);
sb.append(",longitude=").append(longitude);
sb.append(",latitude=").append(latitude);
sb.append(",altitude=").append(altitude);
sb.append(",speed=").append(speed);
sb.append(",direction=").append(direction);
sb.append(",warnBit=").append(Integer.toBinaryString(warnBit));
sb.append(",statusBit=").append(Integer.toBinaryString(statusBit));
sb.append(",attributes=").append(attributes);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.MergeSuperclass;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@MergeSuperclass
@Message({JT808.位置信息查询应答, JT808.车辆控制应答})
public class T0201_0500 extends T0200 implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Override
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.事件报告)
public class T0301 extends JTMessage {
@Field(length = 1, desc = "事件ID")
private int eventId;
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.提问应答)
public class T0302 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "答案ID")
private int answerId;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getAnswerId() {
return answerId;
}
public void setAnswerId(int answerId) {
this.answerId = answerId;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.信息点播_取消)
public class T0303 extends JTMessage {
@Field(length = 1, desc = "消息类型")
private int type;
@Field(length = 1, desc = "点播/取消标志:0.取消 1.点播")
private int action;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getAction() {
return action;
}
public void setAction(int action) {
this.action = action;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.查询区域或线路数据应答)
public class T0608 extends JTMessage {
/** @see com.zehong.protocol.commons.Shape */
@Field(length = 1, desc = "查询类型")
private int type;
@Field(totalUnit = 4, desc = "查询返回的数据")
private byte[] bytes;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public byte[] getBytes() {
return bytes;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.行驶记录数据上传)
public class T0700 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "命令字")
private int command;
@Field(desc = "数据块")
private byte[] data;
public T0700() {
}
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getCommand() {
return command;
}
public void setCommand(int command) {
this.command = command;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.驾驶员身份信息采集上报)
public class T0702 extends JTMessage {
@Field(length = 1, desc = "状态")
private int status;
@Field(length = 6, charset = "BCD", desc = "时间")
private String dateTime;
@Field(length = 1, desc = "IC卡读取结果")
private int cardStatus;
@Field(lengthUnit = 1, desc = "驾驶员姓名")
private String name;
@Field(length = 20, desc = "从业资格证编码")
private String licenseNo;
@Field(lengthUnit = 1, desc = "从业资格证发证机构名称")
private String institution;
@Field(length = 4, charset = "BCD", desc = "证件有效期")
private String licenseValidPeriod;
@Field(length = 20, desc = "驾驶员身份证号", version = 1)
private String idCard;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getDateTime() {
return dateTime;
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
public int getCardStatus() {
return cardStatus;
}
public void setCardStatus(int cardStatus) {
this.cardStatus = cardStatus;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLicenseNo() {
return licenseNo;
}
public void setLicenseNo(String licenseNo) {
this.licenseNo = licenseNo;
}
public String getInstitution() {
return institution;
}
public void setInstitution(String institution) {
this.institution = institution;
}
public String getLicenseValidPeriod() {
return licenseValidPeriod;
}
public void setLicenseValidPeriod(String licenseValidPeriod) {
this.licenseValidPeriod = licenseValidPeriod;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.定位数据批量上传)
public class T0704 extends JTMessage {
@Field(length = 2, desc = "数据项个数")
private int total;
@Field(length = 1, desc = "位置数据类型:0.正常位置批量汇报 1.盲区补报")
private int type;
@Field(lengthUnit = 2, desc = "位置汇报数据项")
private List<T0200> items;
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public List<T0200> getItems() {
return items;
}
public void setItems(List<T0200> items) {
this.items = items;
this.total = items.size();
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.netty.buffer.ByteBufUtil;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.CAN总线数据上传)
public class T0705 extends JTMessage {
@Field(length = 2, desc = "数据项个数(大于0)")
private int total;
@Field(length = 5, charset = "BCD", desc = "CAN总线数据接收时间(HHMMSSMSMS)")
private String dateTime;
@Field(desc = "CAN总线数据项")
private List<Item> items;
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public String getDateTime() {
return dateTime;
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
this.total = items.size();
}
public static class Item {
@Field(length = 4, desc = "CAN ID")
private int id;
@Field(length = 8, desc = "CAN DATA")
private byte[] data;
public Item() {
}
public Item(int id, byte[] data) {
this.id = id;
this.data = data;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(128);
sb.append("{id=").append(id);
sb.append(",data=").append(ByteBufUtil.hexDump(data));
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.多媒体事件信息上传)
public class T0800 extends JTMessage {
@Field(length = 4, desc = "多媒体数据ID")
private int id;
@Field(length = 1, desc = "多媒体类型:0.图像 1.音频 2.视频 ")
private int type;
@Field(length = 1, desc = "多媒体格式编码:0.JPEG 1.TIF 2.MP3 3.WAV 4.WMV ")
private int format;
@Field(length = 1, desc = "事件项编码")
private int event;
@Field(length = 1, desc = "通道ID")
private int channelId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getFormat() {
return format;
}
public void setFormat(int format) {
this.format = format;
}
public int getEvent() {
return event;
}
public void setEvent(int event) {
this.event = event;
}
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.netty.buffer.ByteBuf;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.多媒体数据上传)
public class T0801 extends JTMessage {
@Field(length = 4, desc = "多媒体数据ID")
private int id;
@Field(length = 1, desc = "多媒体类型:0.图像 1.音频 2.视频 ")
private int type;
@Field(length = 1, desc = "多媒体格式编码:0.JPEG 1.TIF 2.MP3 3.WAV 4.WMV ")
private int format;
@Field(length = 1, desc = "事件项编码")
private int event;
@Field(length = 1, desc = "通道ID")
private int channelId;
@Field(length = 28, desc = "位置信息")
private T0200 location;
@Field(desc = "多媒体数据包")
private ByteBuf packet;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getFormat() {
return format;
}
public void setFormat(int format) {
this.format = format;
}
public int getEvent() {
return event;
}
public void setEvent(int event) {
this.event = event;
}
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
public T0200 getLocation() {
return location;
}
public void setLocation(T0200 location) {
this.location = location;
}
public ByteBuf getPacket() {
return packet;
}
public void setPacket(ByteBuf packet) {
this.packet = packet;
}
@Override
public boolean noBuffer() {
return packet == null;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.存储多媒体数据检索应答)
public class T0802 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(totalUnit = 2, desc = "检索项")
private List<Item> items;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public static class Item {
@Field(length = 4, desc = "多媒体数据ID")
private int id;
@Field(length = 1, desc = "多媒体类型:0.图像 1.音频 2.视频")
private int type;
@Field(length = 1, desc = "通道ID")
private int channelId;
@Field(length = 1, desc = "事件项编码")
private int event;
@Field(length = 28, desc = "位置信息")
private T0200 location;
public Item() {
}
public Item(int id, int type, int channelId, int event, T0200 location) {
this.id = id;
this.type = type;
this.channelId = channelId;
this.event = event;
this.location = location;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
public int getEvent() {
return event;
}
public void setEvent(int event) {
this.event = event;
}
public T0200 getLocation() {
return location;
}
public void setLocation(T0200 location) {
this.location = location;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(768);
sb.append("{id=").append(id);
sb.append(",type=").append(type);
sb.append(",channelId=").append(channelId);
sb.append(",event=").append(event);
sb.append(",location=").append(location);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.摄像头立即拍摄命令应答)
public class T0805 extends JTMessage implements Response {
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "结果:0.成功 1.失败 2.通道不支持")
private int result;
@Field(totalUnit = 2, desc = "多媒体ID列表")
private int[] id;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int[] getId() {
return id;
}
public void setId(int[] id) {
this.id = id;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.github.yezhihao.protostar.util.KeyValuePair;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.PassthroughConverter;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.数据上行透传)
public class T0900 extends JTMessage {
/** GNSS模块详细定位数据 */
public static final int GNSSLocation = 0x00;
/** 道路运输证IC卡信息上传消息为64Byte,下传消息为24Byte,道路运输证IC卡认证透传超时时间为30s.超时后,不重发 */
public static final int ICCardInfo = 0x0B;
/** 串口1透传消息 */
public static final int SerialPortOne = 0x41;
/** 串口2透传消息 */
public static final int SerialPortTow = 0x42;
/** 用户自定义透传 0xF0~0xFF */
public static final int Custom = 0xF0;
@Field(desc = "透传消息", converter = PassthroughConverter.class)
private KeyValuePair<Integer, Object> message;
public T0900() {
}
public T0900(KeyValuePair<Integer, Object> message) {
this.message = message;
}
public KeyValuePair<Integer, Object> getMessage() {
return message;
}
public void setMessage(KeyValuePair<Integer, Object> message) {
this.message = message;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.数据压缩上报)
public class T0901 extends JTMessage {
@Field(length = 4, desc = "压缩消息长度")
private int length;
@Field(desc = "压缩消息体")
private byte[] body;
public T0901() {
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public byte[] getBody() {
return body;
}
public void setBody(byte[] body) {
this.body = body;
this.length = body.length;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JT808.平台RSA公钥, JT808.终端RSA公钥})
public class T0A00_8A00 extends JTMessage {
@Field(length = 4, desc = "RSA公钥{e,n}中的e")
private int e;
@Field(length = 128, desc = "RSA公钥{e,n}中的n")
private byte[] n;
public T0A00_8A00() {
}
public T0A00_8A00(int e, byte[] n) {
this.e = e;
this.n = n;
}
public int getE() {
return e;
}
public void setE(int e) {
this.e = e;
}
public byte[] getN() {
return n;
}
public void setN(byte[] n) {
this.n = n;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JT808.服务器补传分包请求, JT808.终端补传分包请求})
public class T8003 extends JTMessage implements Response {
@Field(length = 2, desc = "原始消息流水号")
private int responseSerialNo;
@Field(totalUnit = 1, desc = "重传包ID列表", version = {-1, 0})
@Field(totalUnit = 2, desc = "重传包ID列表", version = 1)
private short[] id;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public short[] getId() {
return id;
}
public void setId(short[] id) {
this.id = id;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.查询服务器时间应答)
public class T8004 extends JTMessage {
@Field(length = 6, charset = "BCD", desc = "UTC时间")
private LocalDateTime dateTime;
public T8004() {
}
public T8004(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
public LocalDateTime getDateTime() {
return dateTime;
}
public void setDateTime(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.终端注册应答)
public class T8100 extends JTMessage implements Response {
/** 0.成功 */
public static final int Success = 0;
/** 1.车辆已被注册 */
public static final int AlreadyRegisteredVehicle = 1;
/** 2.数据库中无该车辆 */
public static final int NotFoundVehicle = 2;
/** 3.终端已被注册 */
public static final int AlreadyRegisteredTerminal = 3;
/** 4.数据库中无该终端 */
public static final int NotFoundTerminal = 4;
@Field(length = 2, desc = "应答流水号")
private int responseSerialNo;
@Field(length = 1, desc = "结果:0.成功 1.车辆已被注册 2.数据库中无该车辆 3.终端已被注册 4.数据库中无该终端")
private int resultCode;
@Field(desc = "鉴权码(成功后才有该字段)")
private String token;
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.ParameterConverter;
import java.util.Map;
import java.util.TreeMap;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置终端参数)
public class T8103 extends JTMessage {
@Field(length = 1, desc = "参数总数")
private int total;
@Field(desc = "参数项列表", converter = ParameterConverter.class)
private Map<Integer, Object> parameters;
public T8103() {
}
public T8103(Map<Integer, Object> parameters) {
this.parameters = parameters;
this.total = parameters.size();
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public Map<Integer, Object> getParameters() {
return parameters;
}
public void setParameters(Map<Integer, Object> parameters) {
this.parameters = parameters;
this.total = parameters.size();
}
public T8103 addParameter(Integer key, Object value) {
if (parameters == null)
parameters = new TreeMap();
parameters.put(key, value);
total = parameters.size();
return this;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.终端控制)
public class T8105 extends JTMessage {
@Field(length = 1, desc = "命令字:" +
" 1.无线升级" +
" 2.控制终端连接指定服务器" +
" 3.终端关机" +
" 4.终端复位" +
" 5.终端恢复出厂设置" +
" 6.关闭数据通信" +
" 7.关闭所有无线通信")
private int command;
@Field(desc = "命令参数")
private String parameter;
public T8105() {
}
public T8105(int command, String parameter) {
this.command = command;
this.parameter = parameter;
}
public int getCommand() {
return command;
}
public void setCommand(int command) {
this.command = command;
}
public String getParameter() {
return parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.查询指定终端参数)
public class T8106 extends JTMessage {
@Field(totalUnit = 1, desc = "参数ID列表")
private int[] id;
public T8106() {
}
public T8106(int... id) {
this.id = id;
}
public int[] getId() {
return id;
}
public void setId(int[] id) {
this.id = id;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.下发终端升级包)
public class T8108 extends JTMessage {
public static final int Terminal = 0;
public static final int CardReader = 12;
public static final int Beidou = 52;
@Field(length = 1, desc = "升级类型")
private int type;
@Field(length = 5, desc = "制造商ID,终端制造商编码")
private String makerId;
@Field(lengthUnit = 1, desc = "版本号")
private String version;
@Field(lengthUnit = 4, desc = "数据包")
private byte[] packet;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getMakerId() {
return makerId;
}
public void setMakerId(String makerId) {
this.makerId = makerId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public byte[] getPacket() {
return packet;
}
public void setPacket(byte[] packet) {
this.packet = packet;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.临时位置跟踪控制)
public class T8202 extends JTMessage {
@Field(length = 2, desc = "时间间隔(秒)")
private int interval;
@Field(length = 4, desc = "有效期(秒)")
private int validityPeriod;
public T8202() {
}
public T8202(int interval, int validityPeriod) {
this.interval = interval;
this.validityPeriod = validityPeriod;
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public int getValidityPeriod() {
return validityPeriod;
}
public void setValidityPeriod(int validityPeriod) {
this.validityPeriod = validityPeriod;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.人工确认报警消息)
public class T8203 extends JTMessage implements Response {
@Field(length = 2, desc = "消息流水号")
private int responseSerialNo;
@Field(length = 4, desc = "报警类型:" +
" [0]确认紧急报警" +
" [1~2]保留" +
" [3]确认危险预警" +
" [4~19]保留" +
" [20]确认进出区域报警" +
" [21]确认进出路线报警" +
" [22]确认路段行驶时间不足/过长报警" +
" [23~26]保留" +
" [27]确认车辆非法点火报警" +
" [28]确认车辆非法位移报警" +
" [29~31]保留")
private int type;
public T8203() {
}
public T8203(int responseSerialNo, int type) {
this.responseSerialNo = responseSerialNo;
this.type = type;
}
public int getResponseSerialNo() {
return responseSerialNo;
}
public void setResponseSerialNo(int responseSerialNo) {
this.responseSerialNo = responseSerialNo;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.文本信息下发)
public class T8300 extends JTMessage {
@Field(length = 1, desc = "标志:" +
" [0]紧急" +
" [1]保留" +
" [2]终端显示器显示" +
" [3]终端 TTS 播读" +
" [4]广告屏显示" +
" [5]0.中心导航信息|1.CAN故障码信息" +
" [6~7]保留")
private int sign;
@Field(length = 1, desc = "类型:1.通知 2.服务", version = 1)
private int type;
@Field(desc = "文本信息", version = {0, 1})
private String content;
public T8300() {
}
public T8300(String content, int... sign) {
this.content = content;
this.sign = Bit.writeInt(sign);
}
public T8300(int type, String content, int... sign) {
this.type = type;
this.content = content;
this.sign = Bit.writeInt(sign);
}
public int getSign() {
return sign;
}
public void setSign(int sign) {
this.sign = sign;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.ArrayList;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.事件设置)
public class T8301 extends JTMessage {
/** @see com.zehong.protocol.commons.Action */
@Field(length = 1, desc = "设置类型:0.清空 1.更新(先清空,后追加) 2.追加 3.修改 4.指定删除")
private int type;
@Field(totalUnit = 1, desc = "事件项")
private List<Event> events;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public List<Event> getEvents() {
return events;
}
public void setEvents(List<Event> events) {
this.events = events;
}
public void addEvent(int id, String content) {
if (events == null)
events = new ArrayList<>(2);
events.add(new Event(id, content));
}
public static class Event {
@Field(length = 1, desc = "事件ID")
private int id;
@Field(lengthUnit = 1, desc = "内容")
private String content;
public Event() {
}
public Event(int id, String content) {
this.id = id;
this.content = content;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(40);
sb.append("{id=").append(id);
sb.append(",content=").append(content);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JT808;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.提问下发)
public class T8302 extends JTMessage {
@Field(length = 1, desc = "标志:" +
" [0]紧急" +
" [1]保留" +
" [2]终端显示器显示" +
" [3]终端 TTS 播读" +
" [4]广告屏显示" +
" [5]0.中心导航信息|1.CAN故障码信息" +
" [6~7]保留")
private int sign;
@Field(lengthUnit = 1, desc = "问题")
private String content;
@Field(desc = "候选答案列表")
private List<Option> options;
public T8302() {
}
public T8302(String content, int... sign) {
this.content = content;
this.sign = Bit.writeInt(sign);
}
public int getSign() {
return sign;
}
public void setSign(int sign) {
this.sign = sign;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public List<Option> getOptions() {
return options;
}
public void setOptions(List<Option> options) {
this.options = options;
}
public static class Option {
@Field(length = 1, desc = "答案ID")
private int id;
@Field(lengthUnit = 2, desc = "答案内容")
private String content;
public Option() {
}
public Option(int id, String content) {
this.id = id;
this.content = content;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(40);
sb.append("{id=").append(id);
sb.append(",content=").append(content);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.ArrayList;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.信息点播菜单设置)
public class T8303 extends JTMessage {
/** @see com.zehong.protocol.commons.Action */
@Field(length = 1, desc = "设置类型")
private int type;
@Field(totalUnit = 1, desc = "信息项")
private List<Info> infos;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public List<Info> getInfos() {
return infos;
}
public void setInfos(List<Info> infos) {
this.infos = infos;
}
public void addInfo(int type, String name) {
if (infos == null)
infos = new ArrayList<>(2);
infos.add(new Info(type, name));
}
public static class Info {
@Field(length = 1, desc = "信息类型")
private int type;
@Field(lengthUnit = 2, desc = "信息名称")
private String name;
public Info() {
}
public Info(int type, String name) {
this.type = type;
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(40);
sb.append("{type=").append(type);
sb.append(",name=").append(name);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
* 该消息2019版本已删除
*/
@Message(JT808.信息服务)
public class T8304 extends JTMessage {
@Field(length = 1, desc = "信息类型")
private int type;
@Field(lengthUnit = 2, desc = "文本信息")
private String content;
public T8304() {
}
public T8304(int type, String content) {
this.type = type;
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.电话回拨)
public class T8400 extends JTMessage {
/** 通话 */
public static final int Normal = 0;
/** 监听 */
public static final int Listen = 1;
@Field(length = 1, desc = "类型:0.通话 1.监听")
private int type;
@Field(length = 20, desc = "电话号码")
private String phoneNumber;
public T8400() {
}
public T8400(int type, String phoneNumber) {
this.type = type;
this.phoneNumber = phoneNumber;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.ArrayList;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置电话本)
public class T8401 extends JTMessage {
/** @see com.zehong.protocol.commons.Action */
@Field(length = 1, desc = "类型")
private int type;
@Field(totalUnit = 1, desc = "联系人项")
private List<Contact> contacts;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public List<Contact> getContacts() {
return contacts;
}
public void setContacts(List<Contact> contacts) {
this.contacts = contacts;
}
public void addContact(Contact contact) {
if (contacts == null)
contacts = new ArrayList<>(2);
contacts.add(contact);
}
public static class Contact {
@Field(length = 1, desc = "标志")
private int sign;
@Field(lengthUnit = 1, desc = "电话号码")
private String phone;
@Field(lengthUnit = 1, desc = "联系人")
private String name;
public Contact() {
}
public Contact(int sign, String phone, String name) {
this.sign = sign;
this.phone = phone;
this.name = name;
}
public int getSign() {
return sign;
}
public void setSign(int sign) {
this.sign = sign;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(50);
sb.append("{sign=").append(sign);
sb.append(",phone=").append(phone);
sb.append(",name=").append(name);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.车辆控制)
public class T8500 extends JTMessage {
@Field(length = 1, desc = "控制标志:[0]0.车门解锁 1.车门加锁 [1~7]保留")
@Field(length = 2, desc = "控制类型:1.车门加锁 2~8.为标准修订预留", version = 1)
private int type;
@Field(length = 1, desc = "控制标志:0.车门解锁 1.车门加锁", version = 1)
private int param;
public T8500() {
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getParam() {
return param;
}
public void setParam(int param) {
this.param = param;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置圆形区域)
public class T8600 extends JTMessage {
/** @see com.zehong.protocol.commons.ShapeAction */
@Field(length = 1, desc = "设置属性")
private int action;
@Field(totalUnit = 1, desc = "区域项")
private List<Circle> items;
public int getAction() {
return action;
}
public void setAction(int action) {
this.action = action;
}
public List<Circle> getItems() {
return items;
}
public void setItems(List<Circle> items) {
this.items = items;
}
public static class Circle {
@Field(length = 4, desc = "区域ID")
private int id;
@Field(length = 2, desc = "区域属性")
private int attribute;
@Field(length = 4, desc = "中心点纬度")
private int latitude;
@Field(length = 4, desc = "中心点经度")
private int longitude;
@Field(length = 4, desc = "半径(米)")
private int radius;
@Field(length = 6, lengthExpression = "attrBit(0) ? 6 : 0", charset = "BCD", desc = "起始时间(若区域属性0位为0则没有该字段)")
private LocalDateTime startTime;
@Field(length = 6, lengthExpression = "attrBit(0) ? 6 : 0", charset = "BCD", desc = "结束时间(若区域属性0位为0则没有该字段)")
private LocalDateTime endTime;
@Field(length = 2, lengthExpression = "attrBit(1) ? 2 : 0", desc = "最高速度(公里每小时,若区域属性1位为0则没有该字段)")
private Integer maxSpeed;
@Field(length = 1, lengthExpression = "attrBit(1) ? 1 : 0", desc = "超速持续时间(秒,若区域属性1位为0则没有该字段)")
private Integer duration;
@Field(length = 2, lengthExpression = "attrBit(1) ? 2 : 0", desc = "夜间最高速度(公里每小时,若区域属性1位为0则没有该字段)", version = 1)
private Integer nightMaxSpeed;
@Field(lengthUnit = 2, desc = "区域名称", version = 1)
private String name;
public Circle() {
}
public Circle(int id, int attribute, int latitude, int longitude, int radius, LocalDateTime startTime, LocalDateTime endTime, Integer maxSpeed, Integer duration) {
this.id = id;
this.attribute = attribute;
this.latitude = latitude;
this.longitude = longitude;
this.radius = radius;
this.setStartTime(startTime);
this.setEndTime(endTime);
this.setMaxSpeed(maxSpeed);
this.setDuration(duration);
}
public Circle(int id, int attribute, int latitude, int longitude, int radius, LocalDateTime startTime, LocalDateTime endTime, Integer maxSpeed, Integer duration, Integer nightMaxSpeed, String name) {
this(id, attribute, latitude, longitude, radius, startTime, endTime, maxSpeed, duration);
this.setNightMaxSpeed(nightMaxSpeed);
this.name = name;
}
public boolean attrBit(int i) {
return Bit.isTrue(attribute, i);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAttribute() {
return attribute;
}
public void setAttribute(int attribute) {
this.attribute = attribute;
}
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 int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.attribute = Bit.set(attribute, 0, startTime != null);
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.attribute = Bit.set(attribute, 0, endTime != null);
this.endTime = endTime;
}
public Integer getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(Integer maxSpeed) {
this.attribute = Bit.set(attribute, 1, maxSpeed != null);
this.maxSpeed = maxSpeed;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.attribute = Bit.set(attribute, 1, duration != null);
this.duration = duration;
}
public Integer getNightMaxSpeed() {
return nightMaxSpeed;
}
public void setNightMaxSpeed(Integer nightMaxSpeed) {
this.attribute = Bit.set(attribute, 1, nightMaxSpeed != null);
this.nightMaxSpeed = nightMaxSpeed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(240);
sb.append("{id=").append(id);
sb.append(",attribute=[").append(Integer.toBinaryString(attribute)).append(']');
sb.append(",longitude=").append(longitude);
sb.append(",latitude=").append(latitude);
sb.append(",radius=").append(radius);
sb.append(",startTime=").append(startTime);
sb.append(",endTime=").append(endTime);
sb.append(",maxSpeed=").append(maxSpeed);
sb.append(",duration=").append(duration);
sb.append(",nightMaxSpeed=").append(nightMaxSpeed);
sb.append(",name=").append(name);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JT808.删除圆形区域, JT808.删除矩形区域, JT808.删除多边形区域, JT808.删除路线})
public class T8601 extends JTMessage {
@Field(totalUnit = 1, desc = "区域列表")
private int[] id;
public T8601() {
}
public T8601(int... id) {
this.id = id;
}
public int[] getId() {
return id;
}
public void setId(int[] id) {
this.id = id;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置矩形区域)
public class T8602 extends JTMessage {
/** @see com.zehong.protocol.commons.ShapeAction */
@Field(length = 1, desc = "设置属性")
private int action;
@Field(totalUnit = 1, desc = "区域项")
private List<Rectangle> items;
public int getAction() {
return action;
}
public void setAction(int action) {
this.action = action;
}
public List<Rectangle> getItems() {
return items;
}
public void setItems(List<Rectangle> items) {
this.items = items;
}
public static class Rectangle {
@Field(length = 4, desc = "区域ID")
private int id;
@Field(length = 2, desc = "区域属性")
private int attribute;
@Field(length = 4, desc = "左上点纬度")
private int latitudeUL;
@Field(length = 4, desc = "左上点经度")
private int longitudeUL;
@Field(length = 4, desc = "右下点纬度")
private int latitudeLR;
@Field(length = 4, desc = "右下点经度")
private int longitudeLR;
@Field(length = 6, lengthExpression = "attrBit(0) ? 6 : 0", charset = "BCD", desc = "起始时间(若区域属性0位为0则没有该字段)")
private LocalDateTime startTime;
@Field(length = 6, lengthExpression = "attrBit(0) ? 6 : 0", charset = "BCD", desc = "结束时间(若区域属性0位为0则没有该字段)")
private LocalDateTime endTime;
@Field(length = 2, lengthExpression = "attrBit(1) ? 2 : 0", desc = "最高速度(公里每小时,若区域属性1位为0则没有该字段)")
private Integer maxSpeed;
@Field(length = 1, lengthExpression = "attrBit(1) ? 1 : 0", desc = "超速持续时间(秒,若区域属性1位为0则没有该字段)")
private Integer duration;
@Field(length = 2, lengthExpression = "attrBit(1) ? 2 : 0", desc = "夜间最高速度(公里每小时,若区域属性1位为0则没有该字段)", version = 1)
private Integer nightMaxSpeed;
@Field(lengthUnit = 2, desc = "区域名称", version = 1)
private String name;
public Rectangle() {
}
public Rectangle(int id, int attribute, int latitudeUL, int longitudeUL, int latitudeLR, int longitudeLR, LocalDateTime startTime, LocalDateTime endTime, Integer maxSpeed, Integer duration) {
this.id = id;
this.attribute = attribute;
this.latitudeUL = latitudeUL;
this.longitudeUL = longitudeUL;
this.latitudeLR = latitudeLR;
this.longitudeLR = longitudeLR;
this.setStartTime(startTime);
this.setEndTime(endTime);
this.setMaxSpeed(maxSpeed);
this.setDuration(duration);
}
public Rectangle(int id, int attribute, int latitudeUL, int longitudeUL, int latitudeLR, int longitudeLR, LocalDateTime startTime, LocalDateTime endTime, Integer maxSpeed, Integer duration, Integer nightMaxSpeed, String name) {
this(id, attribute, latitudeUL, longitudeUL, latitudeLR, longitudeLR, startTime, endTime, maxSpeed, duration);
this.setNightMaxSpeed(nightMaxSpeed);
this.name = name;
}
public boolean attrBit(int i) {
return Bit.isTrue(attribute, i);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAttribute() {
return attribute;
}
public void setAttribute(int attribute) {
this.attribute = attribute;
}
public int getLatitudeUL() {
return latitudeUL;
}
public void setLatitudeUL(int latitudeUL) {
this.latitudeUL = latitudeUL;
}
public int getLongitudeUL() {
return longitudeUL;
}
public void setLongitudeUL(int longitudeUL) {
this.longitudeUL = longitudeUL;
}
public int getLatitudeLR() {
return latitudeLR;
}
public void setLatitudeLR(int latitudeLR) {
this.latitudeLR = latitudeLR;
}
public int getLongitudeLR() {
return longitudeLR;
}
public void setLongitudeLR(int longitudeLR) {
this.longitudeLR = longitudeLR;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.attribute = Bit.set(attribute, 0, startTime != null);
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.attribute = Bit.set(attribute, 0, endTime != null);
this.endTime = endTime;
}
public Integer getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(Integer maxSpeed) {
this.attribute = Bit.set(attribute, 1, maxSpeed != null);
this.maxSpeed = maxSpeed;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.attribute = Bit.set(attribute, 1, duration != null);
this.duration = duration;
}
public Integer getNightMaxSpeed() {
return nightMaxSpeed;
}
public void setNightMaxSpeed(Integer nightMaxSpeed) {
this.attribute = Bit.set(attribute, 1, nightMaxSpeed != null);
this.nightMaxSpeed = nightMaxSpeed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(512);
sb.append("{id=").append(id);
sb.append(",attribute=[").append(Integer.toBinaryString(attribute)).append(']');
sb.append(",longitudeUL=").append(longitudeUL);
sb.append(",latitudeUL=").append(latitudeUL);
sb.append(",longitudeLR=").append(longitudeLR);
sb.append(",latitudeLR=").append(latitudeLR);
sb.append(",startTime=").append(startTime);
sb.append(",endTime=").append(endTime);
sb.append(",maxSpeed=").append(maxSpeed);
sb.append(",duration=").append(duration);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置多边形区域)
public class T8604 extends JTMessage {
@Field(length = 4, desc = "区域ID")
private int id;
@Field(length = 2, desc = "区域属性")
private int attribute;
@Field(length = 6, lengthExpression = "attrBit(0) ? 6 : 0", charset = "BCD", desc = "起始时间(若区域属性0位为0则没有该字段)")
private LocalDateTime startTime;
@Field(length = 6, lengthExpression = "attrBit(0) ? 6 : 0", charset = "BCD", desc = "结束时间(若区域属性0位为0则没有该字段)")
private LocalDateTime endTime;
@Field(length = 2, lengthExpression = "attrBit(1) ? 2 : 0", desc = "最高速度(公里每小时,若区域属性1位为0则没有该字段)")
private Integer maxSpeed;
@Field(length = 1, lengthExpression = "attrBit(1) ? 1 : 0", desc = "超速持续时间(秒,若区域属性1位为0则没有该字段)")
private Integer duration;
@Field(totalUnit = 2, desc = "顶点项")
private List<Point> points;
@Field(length = 2, desc = "夜间最高速度(公里每小时,若区域属性1位为0则没有该字段)", version = 1)
private Integer nightMaxSpeed;
@Field(lengthUnit = 2, desc = "区域名称", version = 1)
private String name;
public boolean attrBit(int i) {
return Bit.isTrue(attribute, i);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAttribute() {
return attribute;
}
public void setAttribute(int attribute) {
this.attribute = attribute;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.attribute = Bit.set(attribute, 0, startTime != null);
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.attribute = Bit.set(attribute, 0, endTime != null);
this.endTime = endTime;
}
public Integer getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(Integer maxSpeed) {
this.attribute = Bit.set(attribute, 1, maxSpeed != null);
this.maxSpeed = maxSpeed;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.attribute = Bit.set(attribute, 1, duration != null);
this.duration = duration;
}
public List<Point> getPoints() {
return points;
}
public void setPoints(List<Point> points) {
this.points = points;
}
public void addPoint(int longitude, int latitude) {
if (points == null)
points = new ArrayList<>(4);
points.add(new Point(latitude, longitude));
}
public Integer getNightMaxSpeed() {
return nightMaxSpeed;
}
public void setNightMaxSpeed(Integer nightMaxSpeed) {
this.attribute = Bit.set(attribute, 1, nightMaxSpeed != null);
this.nightMaxSpeed = nightMaxSpeed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static class Point {
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
public Point() {
}
public Point(int latitude, int longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
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;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(32);
sb.append('{');
sb.append("lng=").append(longitude);
sb.append(",lat=").append(latitude);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.Bit;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置路线)
public class T8606 extends JTMessage {
@Field(length = 4, desc = "路线ID")
private int id;
@Field(length = 2, desc = "路线属性")
private int attribute;
@Field(length = 6, charset = "BCD", desc = "起始时间(若区域属性0位为0则没有该字段)")
private LocalDateTime startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(若区域属性0位为0则没有该字段)")
private LocalDateTime endTime;
@Field(totalUnit = 2, desc = "拐点列表")
private List<Line> items;
@Field(lengthUnit = 2, desc = "区域名称", version = 1)
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAttribute() {
return attribute;
}
public void setAttribute(int attribute) {
this.attribute = attribute;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.attribute = Bit.set(attribute, 0, startTime != null);
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.attribute = Bit.set(attribute, 0, endTime != null);
this.endTime = endTime;
}
public List<Line> getItems() {
return items;
}
public void setItems(List<Line> items) {
this.items = items;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static class Line {
@Field(length = 4, desc = "拐点ID")
private int id;
@Field(length = 4, desc = "路段ID")
private int routeId;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 1, desc = "宽度(米)")
private int width;
@Field(length = 1, desc = "属性")
private int attribute;
@Field(length = 2, desc = "路段行驶过长阈值(秒,若区域属性0位为0则没有该字段)")
private Integer upperLimit;
@Field(length = 2, desc = "路段行驶不足阈值(秒,若区域属性0位为0则没有该字段)")
private Integer lowerLimit;
@Field(length = 2, desc = "路段最高速度(公里每小时,若区域属性1位为0则没有该字段)")
private Integer maxSpeed;
@Field(length = 1, desc = "路段超速持续时间(秒,若区域属性1位为0则没有该字段)")
private Integer duration;
@Field(length = 2, desc = "夜间最高速度(公里每小时,若区域属性1位为0则没有该字段)", version = 1)
private Integer nightMaxSpeed;
public Line() {
}
public Line(int id, int routeId, int latitude, int longitude, int width, int attribute, Integer upperLimit, Integer lowerLimit, Integer maxSpeed, Integer duration) {
this.id = id;
this.routeId = routeId;
this.latitude = latitude;
this.longitude = longitude;
this.width = width;
this.attribute = attribute;
this.setUpperLimit(upperLimit);
this.setLowerLimit(lowerLimit);
this.setMaxSpeed(maxSpeed);
this.setDuration(duration);
}
public Line(int id, int routeId, int latitude, int longitude, int width, int attribute, Integer upperLimit, Integer lowerLimit, Integer maxSpeed, Integer duration, Integer nightMaxSpeed) {
this(id, routeId, latitude, longitude, width, attribute, upperLimit, lowerLimit, maxSpeed, duration);
this.setNightMaxSpeed(nightMaxSpeed);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getRouteId() {
return routeId;
}
public void setRouteId(int routeId) {
this.routeId = routeId;
}
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 int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getAttribute() {
return attribute;
}
public void setAttribute(int attribute) {
this.attribute = attribute;
}
public Integer getUpperLimit() {
return upperLimit;
}
public void setUpperLimit(Integer upperLimit) {
this.attribute = Bit.set(attribute, 0, upperLimit != null);
this.upperLimit = upperLimit;
}
public Integer getLowerLimit() {
return lowerLimit;
}
public void setLowerLimit(Integer lowerLimit) {
this.attribute = Bit.set(attribute, 0, lowerLimit != null);
this.lowerLimit = lowerLimit;
}
public Integer getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(Integer maxSpeed) {
this.attribute = Bit.set(attribute, 1, maxSpeed != null);
this.maxSpeed = maxSpeed;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.attribute = Bit.set(attribute, 1, duration != null);
this.duration = duration;
}
public Integer getNightMaxSpeed() {
return nightMaxSpeed;
}
public void setNightMaxSpeed(Integer nightMaxSpeed) {
this.attribute = Bit.set(attribute, 1, nightMaxSpeed != null);
this.nightMaxSpeed = nightMaxSpeed;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(240);
sb.append("{id=").append(id);
sb.append(",routeId=").append(routeId);
sb.append(",longitude=").append(longitude);
sb.append(",latitude=").append(latitude);
sb.append(",width=").append(width);
sb.append(",attribute=[").append(Integer.toBinaryString(attribute)).append(']');
sb.append(",upperLimit=").append(upperLimit);
sb.append(",lowerLimit=").append(lowerLimit);
sb.append(",maxSpeed=").append(maxSpeed);
sb.append(",duration=").append(duration);
sb.append('}');
return sb.toString();
}
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.查询区域或线路数据)
public class T8608 extends JTMessage {
/** @see com.zehong.protocol.commons.Shape */
@Field(length = 1, desc = "查询类型:1.圆形 2.矩形 3.多边形 4.路线")
private int type;
@Field(totalUnit = 4, desc = "区域列表")
private int[] id;
public T8608() {
}
public T8608(int type, int... id) {
this.type = type;
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int[] getId() {
return id;
}
public void setId(int[] id) {
this.id = id;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.行驶记录仪参数下传命令)
public class T8701 extends JTMessage {
@Field(length = 1, desc = "命令字:" +
" 130.设置车辆信息" +
" 131.设置记录仪初次安装日期" +
" 132.设置状态童配置信息" +
" 194.设置记录仪时间" +
" 195.设置记录仪脉冲系数" +
" 196.设置初始里程" +
" 197~207.预留")
private int type;
@Field(desc = "数据块(参考GB/T 19056)")
private byte[] content;
public T8701() {
}
public T8701(int type, byte[] content) {
this.type = type;
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.多媒体数据上传应答)
public class T8800 extends JTMessage {
@Field(length = 4, desc = "多媒体ID(大于0) 如收到全部数据包则没有后续字段")
private int mediaId;
@Field(totalUnit = 1, desc = "重传包ID列表")
private short[] id;
public int getMediaId() {
return mediaId;
}
public void setMediaId(int mediaId) {
this.mediaId = mediaId;
}
public short[] getId() {
return id;
}
public void setId(short[] id) {
this.id = id;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.摄像头立即拍摄命令)
public class T8801 extends JTMessage {
@Field(length = 1, desc = "通道ID(大于0)")
private int channelId;
@Field(length = 2, desc = "拍摄命令:0表示停止拍摄;65535表示录像;其它表示拍照张数")
private int command;
@Field(length = 2, desc = "拍照间隔/录像时间(秒) 0表示按最小间隔拍照或一直录像")
private int time;
@Field(length = 1, desc = "保存标志:1.保存 0.实时上传")
private int save;
@Field(length = 1, desc = "分辨率:" +
" 1.320*240" +
" 2.640*480" +
" 3.800*600" +
" 4.1024*768" +
" 5.176*144 [QCIF]" +
" 6.352*288 [CIF]" +
" 7.704*288 [HALF D1]" +
" 8.704*576 [D1]")
private int resolution;
@Field(length = 1, desc = "图像/视频质量(1~10):1.代表质量损失最小 10.表示压缩比最大")
private int quality;
@Field(length = 1, desc = "亮度(0~255)")
private int brightness;
@Field(length = 1, desc = "对比度(0~127)")
private int contrast;
@Field(length = 1, desc = "饱和度(0~127)")
private int saturation;
@Field(length = 1, desc = "色度(0~255)")
private int chroma;
public T8801() {
}
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
public int getCommand() {
return command;
}
public void setCommand(int command) {
this.command = command;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
public int getSave() {
return save;
}
public void setSave(int save) {
this.save = save;
}
public int getResolution() {
return resolution;
}
public void setResolution(int resolution) {
this.resolution = resolution;
}
public int getQuality() {
return quality;
}
public void setQuality(int quality) {
this.quality = quality;
}
public int getBrightness() {
return brightness;
}
public void setBrightness(int brightness) {
this.brightness = brightness;
}
public int getContrast() {
return contrast;
}
public void setContrast(int contrast) {
this.contrast = contrast;
}
public int getSaturation() {
return saturation;
}
public void setSaturation(int saturation) {
this.saturation = saturation;
}
public int getChroma() {
return chroma;
}
public void setChroma(int chroma) {
this.chroma = chroma;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.存储多媒体数据检索)
public class T8802 extends JTMessage {
@Field(length = 1, desc = "多媒体类型:0.图像 1.音频 2.视频 ")
private int type;
@Field(length = 1, desc = "通道ID(0表示检索该媒体类型的所有通道)")
private int channelId;
@Field(length = 1, desc = "事件项编码:0.平台下发指令 1.定时动作 2.抢劫报警触发 3.碰撞侧翻报警触发 其他保留")
private int event;
@Field(length = 6, charset = "BCD", desc = "起始时间(YYMMDDHHMMSS)")
private LocalDateTime startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(YYMMDDHHMMSS)")
private LocalDateTime endTime;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
public int getEvent() {
return event;
}
public void setEvent(int event) {
this.event = event;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.time.LocalDateTime;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.存储多媒体数据上传)
public class T8803 extends JTMessage {
@Field(length = 1, desc = "多媒体类型:0.图像 1.音频 2.视频 ")
private int type;
@Field(length = 1, desc = "通道ID")
private int channelId;
@Field(length = 1, desc = "事件项编码:0.平台下发指令 1.定时动作 2.抢劫报警触发 3.碰撞侧翻报警触发 其他保留")
private int event;
@Field(length = 6, charset = "BCD", desc = "起始时间(YYMMDDHHMMSS)")
private LocalDateTime startTime;
@Field(length = 6, charset = "BCD", desc = "结束时间(YYMMDDHHMMSS)")
private LocalDateTime endTime;
@Field(length = 1, desc = "删除标志:0.保留 1.删除 ")
private int delete;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getChannelId() {
return channelId;
}
public void setChannelId(int channelId) {
this.channelId = channelId;
}
public int getEvent() {
return event;
}
public void setEvent(int event) {
this.event = event;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public int getDelete() {
return delete;
}
public void setDelete(int delete) {
this.delete = delete;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.录音开始命令)
public class T8804 extends JTMessage {
@Field(length = 1, desc = "录音命令:0.停止录音 1.开始录音")
private int command;
@Field(length = 2, desc = "录音时间(秒) 0.表示一直录音")
private int time;
@Field(length = 1, desc = "保存标志:0.实时上传 1.保存")
private int save;
@Field(length = 1, desc = "音频采样率:0.8K 1.11K 2.23K 3.32K 其他保留")
private int audioSamplingRate;
public int getCommand() {
return command;
}
public void setCommand(int command) {
this.command = command;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
public int getSave() {
return save;
}
public void setSave(int save) {
this.save = save;
}
public int getAudioSamplingRate() {
return audioSamplingRate;
}
public void setAudioSamplingRate(int audioSamplingRate) {
this.audioSamplingRate = audioSamplingRate;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.单条存储多媒体数据检索上传命令)
public class T8805 extends JTMessage {
@Field(length = 4, desc = "多媒体ID(大于0)")
private int id;
@Field(length = 1, desc = "删除标志:0.保留 1.删除 ")
private int delete;
public T8805() {
}
public T8805(int id, int delete) {
this.id = id;
this.delete = delete;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getDelete() {
return delete;
}
public void setDelete(int delete) {
this.delete = delete;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.github.yezhihao.protostar.util.KeyValuePair;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.PassthroughConverter;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.数据下行透传)
public class T8900 extends JTMessage {
/** GNSS模块详细定位数据 */
public static final int GNSSLocation = 0x00;
/** 道路运输证IC卡信息上传消息为64Byte,下传消息为24Byte,道路运输证IC卡认证透传超时时间为30s.超时后,不重发 */
public static final int ICCardInfo = 0x0B;
/** 串口1透传消息 */
public static final int SerialPortOne = 0x41;
/** 串口2透传消息 */
public static final int SerialPortTow = 0x42;
/** 用户自定义透传 0xF0~0xFF */
public static final int Custom = 0xF0;
@Field(desc = "透传消息", converter = PassthroughConverter.class)
private KeyValuePair<Integer, Object> message;
public T8900() {
}
public T8900(KeyValuePair<Integer, Object> message) {
this.message = message;
}
public KeyValuePair<Integer, Object> getMessage() {
return message;
}
public void setMessage(KeyValuePair<Integer, Object> message) {
this.message = message;
}
}
\ 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zehong</groupId>
<artifactId>vehicle-actual-position</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>vehicle-actual-position</name>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modules>
<module>commons</module>
<module>jtt808-protocol</module>
<module>position-server</module>
</modules>
<properties>
<java.version>8</java.version>
<resource.delimiter>@</resource.delimiter>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.test.skip>true</maven.test.skip>
<mariadb.version>3.1.4</mariadb.version>
</properties>
<dependencies>
</dependencies>
</project>
<?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>position-server</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.zehong</groupId>
<artifactId>jtt808-protocol</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.zehong</groupId>
<artifactId>commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.zehong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableCaching
@EnableScheduling
@SpringBootApplication
public class VehicleActualPositionApplication {
private static final Logger log = LoggerFactory.getLogger(VehicleActualPositionApplication.class);
public static void main(String[] args) {
SpringApplication.run(VehicleActualPositionApplication.class, args);
log.info("***Spring 启动成功***");
}
}
package com.zehong.protocol.t808;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.AttributeConverter;
import com.zehong.protocol.commons.transform.AttributeConverterYue;
import java.time.LocalDateTime;
import java.util.Map;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@JsonIgnoreProperties({"attributes", "alarmList", "dateTime", "messageId", "properties", "protocolVersion", "clientId", "serialNo", "packageTotal", "packageNo", "verified", "bodyLength", "encryption", "subpackage", "version", "reserved"})
@Message(JT808.位置信息汇报)
public class T0200 extends JTMessage {
@Field(length = 4, desc = "报警标志")
private int warnBit;
@Field(length = 4, desc = "状态")
private int statusBit;
@Field(length = 4, desc = "纬度")
private int latitude;
@Field(length = 4, desc = "经度")
private int longitude;
@Field(length = 2, desc = "高程(米)")
private int altitude;
@Field(length = 2, desc = "速度(1/10公里每小时)")
private int speed;
@Field(length = 2, desc = "方向")
private int direction;
@Field(length = 6, charset = "BCD", desc = "时间(YYMMDDHHMMSS)")
private LocalDateTime deviceTime;
@Field(converter = AttributeConverter.class, desc = "位置附加信息", version = {-1, 0})
@Field(converter = AttributeConverterYue.class, desc = "位置附加信息(粤标)", version = 1)
private Map<Integer, Object> attributes;
public int getWarnBit() {
return warnBit;
}
public void setWarnBit(int warnBit) {
this.warnBit = warnBit;
}
public int getStatusBit() {
return statusBit;
}
public void setStatusBit(int statusBit) {
this.statusBit = statusBit;
}
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 int getAltitude() {
return altitude;
}
public void setAltitude(int altitude) {
this.altitude = altitude;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public LocalDateTime getDeviceTime() {
return deviceTime;
}
public void setDeviceTime(LocalDateTime deviceTime) {
this.deviceTime = deviceTime;
}
public Map<Integer, Object> getAttributes() {
return attributes;
}
public void setAttributes(Map<Integer, Object> attributes) {
this.attributes = attributes;
}
public int getAttributeInt(int key) {
if (attributes != null) {
Integer value = (Integer) attributes.get(key);
if (value != null) {
return value;
}
}
return 0;
}
public long getAttributeLong(int key) {
if (attributes != null) {
Long value = (Long) attributes.get(key);
if (value != null) {
return value;
}
}
return 0L;
}
private boolean updated;
private double lng;
private double lat;
private float speedKph;
@Override
public boolean transform() {
if (deviceTime == null)
return false;
lng = longitude / 1000000d;
lat = latitude / 1000000d;
speedKph = speed / 10f;
return true;
}
public boolean updated() {
return updated || !(updated = true);
}
public double getLng() {
return lng;
}
public double getLat() {
return lat;
}
public float getSpeedKph() {
return speedKph;
}
@Override
public String toString() {
StringBuilder sb = toStringHead();
sb.append("T0200{deviceTime=").append(deviceTime);
sb.append(",longitude=").append(longitude);
sb.append(",latitude=").append(latitude);
sb.append(",altitude=").append(altitude);
sb.append(",speed=").append(speed);
sb.append(",direction=").append(direction);
sb.append(",warnBit=").append(Integer.toBinaryString(warnBit));
sb.append(",statusBit=").append(Integer.toBinaryString(statusBit));
sb.append(",attributes=").append(attributes);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.swagger.v3.oas.annotations.media.Schema;
import com.zehong.commons.model.APICodes;
import com.zehong.commons.model.APIException;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import java.util.Base64;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message({JT808.平台RSA公钥, JT808.终端RSA公钥})
public class T0A00_8A00 extends JTMessage {
@Field(length = 4, desc = "RSA公钥{e,n}中的e")
private int e;
@Field(length = 128, desc = "RSA公钥{e,n}中的n")
private byte[] n;
public T0A00_8A00() {
}
public T0A00_8A00(int e, byte[] n) {
this.e = e;
this.n = n;
}
public int getE() {
return e;
}
public void setE(int e) {
this.e = e;
}
public byte[] getN() {
return n;
}
public void setN(byte[] n) {
this.n = n;
}
@Schema(description = "n(BASE64编码)")
private String nBase64;
public String getnBase64() {
return nBase64;
}
public void setnBase64(String nBase64) {
this.nBase64 = nBase64;
}
public T0A00_8A00 build() {
byte[] src = Base64.getDecoder().decode(n);
if (src.length == 129) {
byte[] dest = new byte[128];
System.arraycopy(src, 1, dest, 0, 128);
src = dest;
}
if (src.length != 128)
throw new APIException(APICodes.InvalidParameter, "e length is not 128");
this.n = src;
return this;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.netmc.util.AdapterMap;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.swagger.v3.oas.annotations.media.Schema;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.ParameterConverter;
import com.zehong.protocol.commons.transform.parameter.*;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.设置终端参数)
public class T8103 extends JTMessage {
@Field(length = 1, desc = "参数总数")
private int total;
@Field(desc = "参数项列表", converter = ParameterConverter.class)
private Map<Integer, Object> parameters;
public T8103() {
}
public T8103(Map<Integer, Object> parameters) {
this.parameters = parameters;
this.total = parameters.size();
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public Map<Integer, Object> getParameters() {
return parameters;
}
public void setParameters(Map<Integer, Object> parameters) {
this.parameters = parameters;
this.total = parameters.size();
}
public T8103 addParameter(Integer key, Object value) {
if (parameters == null)
parameters = new TreeMap();
parameters.put(key, value);
total = parameters.size();
return this;
}
@Schema(description = "数值型参数列表(BYTE、WORD)")
private Map<Integer, Integer> parametersInt;
@Schema(description = "数值型参数列表(DWORD、QWORD)")
private Map<Integer, String> parametersLong;
@Schema(description = "字符型参数列表")
private Map<Integer, String> parametersStr;
@Schema(description = "图像分析报警参数设置(1078)")
private ParamImageIdentifyAlarm paramImageIdentifyAlarm;
@Schema(description = "特殊报警录像参数设置(1078)")
private ParamVideoSpecialAlarm paramVideoSpecialAlarm;
@Schema(description = "音视频通道列表设置(1078)")
private ParamChannels paramChannels;
@Schema(description = "终端休眠唤醒模式设置数据格式(1078)")
private ParamSleepWake paramSleepWake;
@Schema(description = "音视频参数设置(1078)")
private ParamVideo paramVideo;
@Schema(description = "单独视频通道参数设置(1078)")
private ParamVideoSingle paramVideoSingle;
@Schema(description = "盲区监测系统参数(苏标)")
private ParamBSD paramBSD;
@Schema(description = "胎压监测系统参数(苏标)")
private ParamTPMS paramTPMS;
@Schema(description = "驾驶员状态监测系统参数(苏标)")
private ParamDSM paramDSM;
@Schema(description = "高级驾驶辅助系统参数(苏标)")
private ParamADAS paramADAS;
public Map<Integer, Integer> getParametersInt() {
return parametersInt;
}
public void setParametersInt(Map<Integer, Integer> parametersInt) {
this.parametersInt = parametersInt;
}
public Map<Integer, String> getParametersLong() {
return parametersLong;
}
public void setParametersLong(Map<Integer, String> parametersLong) {
this.parametersLong = parametersLong;
}
public Map<Integer, String> getParametersStr() {
return parametersStr;
}
public void setParametersStr(Map<Integer, String> parametersStr) {
this.parametersStr = parametersStr;
}
public ParamADAS getParamADAS() {
return paramADAS;
}
public void setParamADAS(ParamADAS paramADAS) {
this.paramADAS = paramADAS;
}
public ParamBSD getParamBSD() {
return paramBSD;
}
public void setParamBSD(ParamBSD paramBSD) {
this.paramBSD = paramBSD;
}
public ParamChannels getParamChannels() {
return paramChannels;
}
public void setParamChannels(ParamChannels paramChannels) {
this.paramChannels = paramChannels;
}
public ParamDSM getParamDSM() {
return paramDSM;
}
public void setParamDSM(ParamDSM paramDSM) {
this.paramDSM = paramDSM;
}
public ParamImageIdentifyAlarm getParamImageIdentifyAlarm() {
return paramImageIdentifyAlarm;
}
public void setParamImageIdentifyAlarm(ParamImageIdentifyAlarm paramImageIdentifyAlarm) {
this.paramImageIdentifyAlarm = paramImageIdentifyAlarm;
}
public ParamSleepWake getParamSleepWake() {
return paramSleepWake;
}
public void setParamSleepWake(ParamSleepWake paramSleepWake) {
this.paramSleepWake = paramSleepWake;
}
public ParamTPMS getParamTPMS() {
return paramTPMS;
}
public void setParamTPMS(ParamTPMS paramTPMS) {
this.paramTPMS = paramTPMS;
}
public ParamVideo getParamVideo() {
return paramVideo;
}
public void setParamVideo(ParamVideo paramVideo) {
this.paramVideo = paramVideo;
}
public ParamVideoSingle getParamVideoSingle() {
return paramVideoSingle;
}
public void setParamVideoSingle(ParamVideoSingle paramVideoSingle) {
this.paramVideoSingle = paramVideoSingle;
}
public ParamVideoSpecialAlarm getParamVideoSpecialAlarm() {
return paramVideoSpecialAlarm;
}
public void setParamVideoSpecialAlarm(ParamVideoSpecialAlarm paramVideoSpecialAlarm) {
this.paramVideoSpecialAlarm = paramVideoSpecialAlarm;
}
public T8103 build() {
Map<Integer, Object> map = new TreeMap<>();
if (parametersInt != null && !parametersInt.isEmpty())
map.putAll(parametersInt);
if (parametersLong != null && !parametersLong.isEmpty())
map.putAll(new AdapterMap(parametersLong, (Function<String, Long>) Long::parseLong));
if (parametersStr != null && !parametersStr.isEmpty())
map.putAll(parametersStr);
if (paramADAS != null)
map.put(paramADAS.key, paramADAS);
if (paramBSD != null)
map.put(paramBSD.key, paramBSD);
if (paramChannels != null)
map.put(paramChannels.key, paramChannels);
if (paramDSM != null)
map.put(paramDSM.key, paramDSM);
if (paramImageIdentifyAlarm != null)
map.put(paramImageIdentifyAlarm.key, paramImageIdentifyAlarm);
if (paramSleepWake != null)
map.put(paramSleepWake.key, paramSleepWake);
if (paramTPMS != null)
map.put(paramTPMS.key, paramTPMS);
if (paramVideo != null)
map.put(paramVideo.key, paramVideo);
if (paramVideoSingle != null)
map.put(paramVideoSingle.key, paramVideoSingle);
if (paramVideoSpecialAlarm != null)
map.put(paramVideoSpecialAlarm.key, paramVideoSpecialAlarm);
this.total = map.size();
this.parameters = map;
return this;
}
}
\ No newline at end of file
package com.zehong.protocol.t808;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Message;
import io.github.yezhihao.protostar.util.KeyValuePair;
import io.swagger.v3.oas.annotations.media.Schema;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.commons.transform.PassthroughConverter;
import com.zehong.protocol.commons.transform.passthrough.PeripheralStatus;
import com.zehong.protocol.commons.transform.passthrough.PeripheralSystem;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Message(JT808.数据下行透传)
public class T8900 extends JTMessage {
/** GNSS模块详细定位数据 */
public static final int GNSSLocation = 0x00;
/** 道路运输证IC卡信息上传消息为64Byte,下传消息为24Byte,道路运输证IC卡认证透传超时时间为30s.超时后,不重发 */
public static final int ICCardInfo = 0x0B;
/** 串口1透传消息 */
public static final int SerialPortOne = 0x41;
/** 串口2透传消息 */
public static final int SerialPortTow = 0x42;
/** 用户自定义透传 0xF0~0xFF */
public static final int Custom = 0xF0;
@Field(desc = "透传消息", converter = PassthroughConverter.class)
private KeyValuePair<Integer, Object> message;
public T8900() {
}
public T8900(KeyValuePair<Integer, Object> message) {
this.message = message;
}
public KeyValuePair<Integer, Object> getMessage() {
return message;
}
public void setMessage(KeyValuePair<Integer, Object> message) {
this.message = message;
}
@Schema(description = "状态查询(外设状态信息:外设工作状态、设备报警信息)")
private PeripheralStatus peripheralStatus;
@Schema(description = "信息查询(外设传感器的基本信息:公司信息、产品代码、版本号、外设ID、客户代码)")
private PeripheralSystem peripheralSystem;
public PeripheralStatus getPeripheralStatus() {
return peripheralStatus;
}
public void setPeripheralStatus(PeripheralStatus peripheralStatus) {
this.peripheralStatus = peripheralStatus;
}
public PeripheralSystem getPeripheralSystem() {
return peripheralSystem;
}
public void setPeripheralSystem(PeripheralSystem peripheralSystem) {
this.peripheralSystem = peripheralSystem;
}
public T8900 build() {
KeyValuePair<Integer, Object> message = new KeyValuePair<>();
if (peripheralStatus != null) {
message.setKey(PeripheralStatus.key);
message.setValue(peripheralStatus);
} else if (peripheralSystem != null) {
message.setKey(PeripheralSystem.key);
message.setValue(peripheralSystem);
}
this.message = message;
return this;
}
}
\ No newline at end of file
package com.zehong.web.config;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationFeature;
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 com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.zehong.commons.util.DateUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
@Configuration
public class BeanConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager manager = new CaffeineCacheManager();
manager.setCaffeine(Caffeine.newBuilder()
.maximumSize(500L)
.expireAfterWrite(30, TimeUnit.MINUTES));
return manager;
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizeJackson2ObjectMapper() {
return builder -> {
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));
builder.modules(longModule, timeModule);
builder.postConfigurer(mapper -> {
mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, true);//忽略循环引用
mapper.configure(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL, true);//循环引用写入null
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
});
};
}
}
\ No newline at end of file
package com.zehong.web.config;
import io.github.yezhihao.netmc.core.HandlerMapping;
import io.github.yezhihao.netmc.core.SpringHandlerMapping;
import io.github.yezhihao.netmc.session.SessionListener;
import io.github.yezhihao.netmc.session.SessionManager;
import io.github.yezhihao.protostar.SchemaManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.zehong.protocol.codec.DataFrameMessageDecoder;
import com.zehong.protocol.codec.JTMessageAdapter;
import com.zehong.protocol.codec.JTMessageEncoder;
import com.zehong.protocol.codec.MultiPacketDecoder;
import com.zehong.web.endpoint.JTHandlerInterceptor;
import com.zehong.web.endpoint.JTMultiPacketListener;
import com.zehong.web.endpoint.JTSessionListener;
import com.zehong.web.model.enums.SessionKey;
@Configuration
public class JTBeanConfig {
@Bean
public HandlerMapping handlerMapping() {
return new SpringHandlerMapping();
}
@Bean
public JTHandlerInterceptor handlerInterceptor() {
return new JTHandlerInterceptor();
}
@Bean
public SessionListener sessionListener() {
return new JTSessionListener();
}
@Bean
public SessionManager sessionManager(SessionListener sessionListener) {
return new SessionManager(SessionKey.class, sessionListener);
}
@Bean
public SchemaManager schemaManager() {
return new SchemaManager("com.zehong.protocol");
}
@Bean
public JTMessageAdapter messageAdapter(SchemaManager schemaManager) {
JTMessageEncoder encoder = new JTMessageEncoder(schemaManager);
MultiPacketDecoder decoder = new MultiPacketDecoder(schemaManager, new JTMultiPacketListener(10));
return new WebLogAdapter(encoder, decoder);
}
@Bean
public JTMessageAdapter alarmFileMessageAdapter(SchemaManager schemaManager) {
JTMessageEncoder encoder = new JTMessageEncoder(schemaManager);
DataFrameMessageDecoder decoder = new DataFrameMessageDecoder(schemaManager, new byte[]{0x30, 0x31, 0x63, 0x64});
return new WebLogAdapter(encoder, decoder);
}
@Bean
public MultiPacketDecoder multiPacketDecoder(SchemaManager schemaManager) {
return new MultiPacketDecoder(schemaManager);
}
}
\ No newline at end of file
package com.zehong.web.config;
import io.github.yezhihao.netmc.NettyConfig;
import io.github.yezhihao.netmc.Server;
import io.github.yezhihao.netmc.codec.Delimiter;
import io.github.yezhihao.netmc.codec.LengthField;
import io.github.yezhihao.netmc.core.HandlerMapping;
import io.github.yezhihao.netmc.session.SessionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import com.zehong.protocol.codec.JTMessageAdapter;
import com.zehong.web.endpoint.JTHandlerInterceptor;
@Order(Integer.MIN_VALUE)
@Configuration
@ConditionalOnProperty(value = "jt-server.jt808.enable", havingValue = "true")
public class JTConfig {
private final JTMessageAdapter messageAdapter;
private final HandlerMapping handlerMapping;
private final JTHandlerInterceptor handlerInterceptor;
private final SessionManager sessionManager;
public JTConfig(JTMessageAdapter messageAdapter, HandlerMapping handlerMapping, JTHandlerInterceptor handlerInterceptor, SessionManager sessionManager) {
this.messageAdapter = messageAdapter;
this.handlerMapping = handlerMapping;
this.handlerInterceptor = handlerInterceptor;
this.sessionManager = sessionManager;
}
@ConditionalOnProperty(value = "jt-server.jt808.port.tcp")
@Bean(initMethod = "start", destroyMethod = "stop")
public Server jt808TCPServer(@Value("${jt-server.jt808.port.tcp}") int port) {
return NettyConfig.custom()
//心跳超时(秒)
.setIdleStateTime(180, 0, 0)
.setPort(port)
//标识位[2] + 消息头[21] + 消息体[1023 * 2(转义预留)] + 校验码[1] + 标识位[2]
.setMaxFrameLength(2 + 21 + 1023 * 2 + 1 + 2)
.setDelimiters(new Delimiter(new byte[]{0x7e}, false))
.setDecoder(messageAdapter)
.setEncoder(messageAdapter)
.setHandlerMapping(handlerMapping)
.setHandlerInterceptor(handlerInterceptor)
.setSessionManager(sessionManager)
.setName("808-TCP")
.build();
}
@ConditionalOnProperty(value = "jt-server.jt808.port.udp")
@Bean(initMethod = "start", destroyMethod = "stop")
public Server jt808UDPServer(@Value("${jt-server.jt808.port.udp}") int port) {
return NettyConfig.custom()
.setPort(port)
.setDelimiters(new Delimiter(new byte[]{0x7e}, false))
.setDecoder(messageAdapter)
.setEncoder(messageAdapter)
.setHandlerMapping(handlerMapping)
.setHandlerInterceptor(handlerInterceptor)
.setSessionManager(sessionManager)
.setName("808-UDP")
.setEnableUDP(true)
.build();
}
@ConditionalOnProperty(value = "jt-server.alarm-file.enable", havingValue = "true")
@Bean(initMethod = "start", destroyMethod = "stop")
public Server alarmFileServer(@Value("${jt-server.alarm-file.port}") int port, JTMessageAdapter alarmFileMessageAdapter) {
return NettyConfig.custom()
.setPort(port)
.setMaxFrameLength(2 + 21 + 1023 * 2 + 1 + 2)
.setLengthField(new LengthField(new byte[]{0x30, 0x31, 0x63, 0x64}, 1024 * 65, 58, 4))
.setDelimiters(new Delimiter(new byte[]{0x7e}, false))
.setDecoder(alarmFileMessageAdapter)
.setEncoder(alarmFileMessageAdapter)
.setHandlerMapping(handlerMapping)
.setHandlerInterceptor(handlerInterceptor)
.setName("AlarmFile")
.build();
}
}
\ No newline at end of file
package com.zehong.web.config;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.annotation.Fs;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.customizers.PropertyCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info()
.title("部标JT/T808协议接入平台")
.contact(new Contact().name("问题交流群:906230542").url("https://gitee.com/yezhihao"))
.license(new License().name("Apache-2.0").url("https://www.apache.org/licenses"))
.version("1.0.0"));
}
public static final Set<String> ignores = new HashSet<>();
static {
ignores.add("messageId");
ignores.add("properties");
ignores.add("protocolVersion");
ignores.add("serialNo");
ignores.add("packageTotal");
ignores.add("packageNo");
ignores.add("verified");
ignores.add("bodyLength");
ignores.add("encryption");
ignores.add("subpackage");
ignores.add("version");
ignores.add("reserved");
ignores.add("payload");
ignores.add("session");
ignores.add("messageName");
}
@Bean
public PropertyCustomizer propertyCustomizer() {
return (schema, type) -> {
String propertyName = type.getPropertyName();
boolean readOnly = ignores.contains(propertyName);
schema.readOnly(readOnly);
Field field = getField(type.getCtxAnnotations());
if (field != null) {
schema.description(field.desc());
if (!readOnly) {
schema.addRequiredItem("true");
}
}
return schema;
};
}
private Field getField(Annotation[] annotations) {
if (annotations != null) {
for (Annotation annotation : annotations) {
if (annotation instanceof Field) {
return (Field) annotation;
}
if (annotation instanceof Fs) {
return ((Fs) annotation).value()[0];
}
}
}
return null;
}
}
\ No newline at end of file
package com.zehong.web.config;
import io.github.yezhihao.netmc.session.Session;
import io.github.yezhihao.protostar.SchemaManager;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.codec.ServerSentEvent;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.codec.JTMessageAdapter;
import com.zehong.protocol.codec.JTMessageDecoder;
import com.zehong.protocol.codec.JTMessageEncoder;
import com.zehong.protocol.commons.JT808;
import reactor.core.publisher.FluxSink;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class WebLogAdapter extends JTMessageAdapter {
protected static final Logger log = LoggerFactory.getLogger(WebLogAdapter.class);
public static final HashMap<String, Set<FluxSink<Object>>> clientIds = new HashMap<>();
public static final HashSet<Integer> ignoreMsgs = new HashSet<>();
static {
ignoreMsgs.add(JT808.定位数据批量上传);
}
public WebLogAdapter(SchemaManager schemaManager) {
super(schemaManager);
}
public WebLogAdapter(JTMessageEncoder messageEncoder, JTMessageDecoder messageDecoder) {
super(messageEncoder, messageDecoder);
}
@Override
public void encodeLog(Session session, JTMessage message, ByteBuf output) {
Set<FluxSink<Object>> emitters = clientIds.get(message.getClientId());
if (emitters != null) {
ServerSentEvent<Object> event = ServerSentEvent.builder().event(message.getClientId())
.data(message + "hex:" + ByteBufUtil.hexDump(output, 0, output.writerIndex())).build();
for (FluxSink<Object> emitter : emitters) {
emitter.next(event);
}
}
if ((!ignoreMsgs.contains(message.getMessageId())) && (emitters != null || clientIds.isEmpty()))
super.encodeLog(session, message, output);
}
@Override
public void decodeLog(Session session, JTMessage message, ByteBuf input) {
if (message != null) {
Set<FluxSink<Object>> emitters = clientIds.get(message.getClientId());
if (emitters != null) {
ServerSentEvent<Object> event = ServerSentEvent.builder().event(message.getClientId())
.data(message + "hex:" + ByteBufUtil.hexDump(input, 0, input.writerIndex())).build();
for (FluxSink<Object> emitter : emitters) {
emitter.next(event);
}
}
if (!ignoreMsgs.contains(message.getMessageId()) && (emitters != null || clientIds.isEmpty()))
super.decodeLog(session, message, input);
if (!message.isVerified())
log.error("<<<<<校验码错误session={},payload={}", session, ByteBufUtil.hexDump(input, 0, input.writerIndex()));
}
}
public static void clearMessage() {
synchronized (ignoreMsgs) {
ignoreMsgs.clear();
}
}
public static void addMessage(int messageId) {
if (!ignoreMsgs.contains(messageId)) {
synchronized (ignoreMsgs) {
ignoreMsgs.add(messageId);
}
}
}
public static void removeMessage(int messageId) {
if (ignoreMsgs.contains(messageId)) {
synchronized (ignoreMsgs) {
ignoreMsgs.remove(messageId);
}
}
}
public static void clearClient() {
synchronized (clientIds) {
clientIds.clear();
}
}
public static void addClient(String clientId, FluxSink<Object> emitter) {
synchronized (clientIds) {
clientIds.computeIfAbsent(clientId, k -> new HashSet<>()).add(emitter);
}
}
public static void removeClient(String clientId, FluxSink<Object> emitter) {
synchronized (clientIds) {
Set<FluxSink<Object>> emitters = clientIds.get(clientId);
if (emitters != null) {
emitters.remove(emitter);
if (emitters.isEmpty()) {
clientIds.remove(clientId);
}
}
}
}
}
\ No newline at end of file
package com.zehong.web.config;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").combine(corsConfig());
}
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig());
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
@Bean
public CorsConfiguration corsConfig() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern(CorsConfiguration.ALL);
config.addAllowedMethod(CorsConfiguration.ALL);
config.addAllowedHeader(CorsConfiguration.ALL);
config.setAllowCredentials(true);
config.setMaxAge(3600L);
return config;
}
}
\ No newline at end of file
package com.zehong.web.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.zehong.commons.model.APICodes;
import com.zehong.commons.model.APIException;
import com.zehong.commons.model.APIResult;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@RestControllerAdvice
public class ExceptionController {
private static final Logger log = LoggerFactory.getLogger(ExceptionController.class);
private static final Pattern compile = Pattern.compile("'\\w*'");
@ExceptionHandler(Exception.class)
public APIResult<?> onException(Exception e) {
log.error("系统异常", e);
return new APIResult<>(e);
}
@ExceptionHandler(APIException.class)
public APIResult<?> onAPIException(APIException e) {
return new APIResult<>(e);
}
@ExceptionHandler(SQLException.class)
public APIResult<?> onSQLException(SQLException e) {
String message = e.getMessage();
if (message.endsWith("have a default value"))
return new APIResult<>(APICodes.MissingParameter, e);
log.warn("系统异常:", e);
return new APIResult<>(e);
}
@ExceptionHandler(DuplicateKeyException.class)
public APIResult<?> onDuplicateKeyException(DuplicateKeyException e) {
Matcher matcher = compile.matcher(e.getCause().getMessage());
List<String> values = new ArrayList<>(4);
while (matcher.find())
values.add(matcher.group());
int size = values.size();
int len = size < 2 ? size : (size / 2);
StringBuilder sb = new StringBuilder(20);
sb.append("已存在的号码:");
for (int i = 0; i < len; i++)
sb.append(values.get(i)).append(',');
return new APIResult<>(APICodes.InvalidParameter, sb.substring(0, sb.length() - 1));
}
@ExceptionHandler(IllegalArgumentException.class)
public APIResult<?> onIllegalArgumentException(IllegalArgumentException e) {
log.warn("系统异常:", e);
return new APIResult<>(APICodes.InvalidParameter, e.getMessage());
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public APIResult<?> onHttpMessageNotReadableException(HttpMessageNotReadableException e) {
log.warn("系统异常:", e);
return new APIResult<>(APICodes.TypeMismatch, e);
}
@ExceptionHandler(BindException.class)
public APIResult<?> onBindException(BindException e) {
List<FieldError> fieldErrors = e.getFieldErrors();
StringBuilder sb = new StringBuilder();
for (FieldError fieldError : fieldErrors)
sb.append(fieldError.getField()).append(fieldError.getDefaultMessage());
return new APIResult<>(APICodes.MissingParameter, sb.toString());
}
@ExceptionHandler(HttpMediaTypeException.class)
public APIResult<?> onHttpMediaTypeException(HttpMediaTypeException e) {
log.warn("系统异常:", e);
return new APIResult<>(APICodes.NotSupportedType, e.getMessage());
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public APIResult<?> onHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
return new APIResult<>(APICodes.NotImplemented);
}
@ExceptionHandler(MissingServletRequestParameterException.class)
public APIResult<?> onMissingServletRequestParameterException(MissingServletRequestParameterException e) {
return new APIResult<>(APICodes.MissingParameter, ":" + e.getParameterName());
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public APIResult<?> onMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
return new APIResult<>(APICodes.TypeMismatch, ":" + e.getName() + "=" + e.getValue(), e.getMessage());
}
}
\ No newline at end of file
package com.zehong.web.controller;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.zehong.commons.model.APIResult;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT1078;
import com.zehong.protocol.jsatl12.T9208;
import com.zehong.protocol.t1078.*;
import com.zehong.protocol.t808.T0001;
import com.zehong.web.endpoint.MessageManager;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("device")
public class JT1078Controller {
@Autowired
private MessageManager messageManager;
@Operation(summary = "9003 查询终端音视频属性")
@PostMapping("9003")
public Mono<APIResult<T1003>> T9003(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT1078.查询终端音视频属性), T1003.class);
}
@Operation(summary = "9101 实时音视频传输请求")
@PostMapping("9101")
public Mono<APIResult<T0001>> T9101(@RequestBody T9101 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9102 音视频实时传输控制")
@PostMapping("9102")
public Mono<APIResult<T0001>> T9102(@RequestBody T9102 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9201 平台下发远程录像回放请求")
@PostMapping("9201")
public Mono<APIResult<T1205>> T9201(@RequestBody T9201 request) {
return messageManager.requestR(request, T1205.class);
}
@Operation(summary = "9202 平台下发远程录像回放控制")
@PostMapping("9202")
public Mono<APIResult<T0001>> T9202(@RequestBody T9202 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9205 查询资源列表")
@PostMapping("9205")
public Mono<APIResult<T1205>> T9205(@RequestBody T9205 request) {
return messageManager.requestR(request, T1205.class);
}
@Operation(summary = "9206 文件上传指令")
@PostMapping("9206")
public Mono<APIResult<T0001>> T9206(@RequestBody T9206 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9207 文件上传控制")
@PostMapping("9207")
public Mono<APIResult<T0001>> T9207(@RequestBody T9207 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9208 报警附件上传指令(苏标)")
@PostMapping("9208")
public Mono<APIResult<T0001>> T9208(@RequestBody T9208 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9301 云台旋转")
@PostMapping("9301")
public Mono<APIResult<T0001>> T9301(@RequestBody T9301 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "9302 云台调整焦距控制")
@PostMapping("9302")
public Mono<APIResult<T0001>> T9302(@RequestBody T9302 request) {
return messageManager.requestR(request.messageId(JT1078.云台调整焦距控制), T0001.class);
}
@Operation(summary = "9303 云台调整光圈控制")
@PostMapping("9303")
public Mono<APIResult<T0001>> T9303(@RequestBody T9302 request) {
return messageManager.requestR(request.messageId(JT1078.云台调整光圈控制), T0001.class);
}
@Operation(summary = "9304 云台雨刷控制")
@PostMapping("9304")
public Mono<APIResult<T0001>> T9304(@RequestBody T9302 request) {
return messageManager.requestR(request.messageId(JT1078.云台雨刷控制), T0001.class);
}
@Operation(summary = "9305 红外补光控制")
@PostMapping("9305")
public Mono<APIResult<T0001>> T9305(@RequestBody T9302 request) {
return messageManager.requestR(request.messageId(JT1078.红外补光控制), T0001.class);
}
@Operation(summary = "9306 云台变倍控制")
@PostMapping("9306")
public Mono<APIResult<T0001>> T9306(@RequestBody T9302 request) {
return messageManager.requestR(request.messageId(JT1078.云台变倍控制), T0001.class);
}
}
\ No newline at end of file
package com.zehong.web.controller;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.zehong.commons.model.APIResult;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.t808.*;
import com.zehong.web.endpoint.MessageManager;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("device")
public class JT808Controller {
@Autowired
private MessageManager messageManager;
@Operation(summary = "8103 设置终端参数")
@PostMapping("8103")
public Mono<APIResult<T0001>> T8103(@RequestBody T8103 request) {
return messageManager.requestR(request.build(), T0001.class);
}
@Operation(summary = "8104 查询终端参数")
@PostMapping("8104")
public Mono<APIResult<T0104>> T8104(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT808.查询终端参数), T0104.class);
}
@Operation(summary = "8106 查询指定终端参数")
@PostMapping("8106")
public Mono<APIResult<T0104>> T8106(@RequestBody T8106 request) {
return messageManager.requestR(request, T0104.class);
}
@Operation(summary = "8105 终端控制")
@PostMapping("8105")
public Mono<APIResult<T0001>> T8105(@RequestBody T8105 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8107 查询终端属性")
@PostMapping("8107")
public Mono<APIResult<T0107>> T8107(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT808.查询终端属性), T0107.class);
}
@Operation(summary = "8201 位置信息查询")
@PostMapping("8201")
public Mono<APIResult<T0201_0500>> T8201(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT808.位置信息查询), T0201_0500.class);
}
@Operation(summary = "8202 临时位置跟踪控制")
@PostMapping("8202")
public Mono<APIResult<T0001>> T8202(@RequestBody T8202 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8203 人工确认报警消息")
@PostMapping("8203")
public Mono<APIResult<T0001>> T8203(@RequestBody T8203 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8204 服务器向终端发起链路检测请求")
@PostMapping("8204")
public Mono<APIResult<T0001>> T8204(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT808.服务器向终端发起链路检测请求), T0001.class);
}
@Operation(summary = "8300 文本信息下发")
@PostMapping("8300")
public Mono<APIResult<T0001>> T8300(@RequestBody T8300 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8301 事件设置")
@PostMapping("8301")
public Mono<APIResult<T0001>> T8301(@RequestBody T8301 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8302 提问下发")
@PostMapping("8302")
public Mono<APIResult<T0001>> T8302(@RequestBody T8302 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8303 信息点播菜单设置")
@PostMapping("8303")
public Mono<APIResult<T0001>> T8303(@RequestBody T8303 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8304 信息服务")
@PostMapping("8304")
public Mono<APIResult<T0001>> T8304(@RequestBody T8304 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8400 电话回拨")
@PostMapping("8400")
public Mono<APIResult<T0001>> T8400(@RequestBody T8400 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8401 设置电话本")
@PostMapping("8401")
public Mono<APIResult<T0001>> T8401(@RequestBody T8401 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8500 车辆控制")
@PostMapping("8500")
public Mono<APIResult<T0201_0500>> T8500(@RequestBody T8500 request) {
return messageManager.requestR(request, T0201_0500.class);
}
@Operation(summary = "8600 设置圆形区域")
@PostMapping("8600")
public Mono<APIResult<T0001>> T8600(@RequestBody T8600 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8601 删除圆形区域")
@PostMapping("8601")
public Mono<APIResult<T0001>> T8601(@RequestBody T8601 request) {
return messageManager.requestR(request.messageId(JT808.删除圆形区域), T0001.class);
}
@Operation(summary = "8602 设置矩形区域")
@PostMapping("8602")
public Mono<APIResult<T0001>> T8602(@RequestBody T8602 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8603 删除矩形区域")
@PostMapping("8603")
public Mono<APIResult<T0001>> T8603(@RequestBody T8601 request) {
return messageManager.requestR(request.messageId(JT808.删除矩形区域), T0001.class);
}
@Operation(summary = "8604 设置多边形区域")
@PostMapping("8604")
public Mono<APIResult<T0001>> T8604(@RequestBody T8604 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8605 删除多边形区域")
@PostMapping("8605")
public Mono<APIResult<T0001>> T8605(@RequestBody T8601 request) {
return messageManager.requestR(request.messageId(JT808.删除多边形区域), T0001.class);
}
@Operation(summary = "8606 设置路线")
@PostMapping("8606")
public Mono<APIResult<T0001>> T8606(@RequestBody T8606 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8607 删除路线")
@PostMapping("8607")
public Mono<APIResult<T0001>> T8607(@RequestBody T8601 request) {
return messageManager.requestR(request.messageId(JT808.删除路线), T0001.class);
}
@Operation(summary = "8608 查询区域或线路数据")
@PostMapping("8608")
public Mono<APIResult<T0608>> T8608(@RequestBody T8608 request) {
return messageManager.requestR(request, T0608.class);
}
@Operation(summary = "8700 行驶记录仪数据采集命令")
@PostMapping("8700")
public Mono<APIResult<T0001>> T8700(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT808.行驶记录仪数据采集命令), T0001.class);
}
@Operation(summary = "8701 行驶记录仪参数下传命令")
@PostMapping("8701")
public Mono<APIResult<T0001>> T8701(@RequestBody T8701 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8702 上报驾驶员身份信息请求")
@PostMapping("8702")
public Mono<APIResult<T0702>> T8702(@RequestBody JTMessage request) {
return messageManager.requestR(request.messageId(JT808.上报驾驶员身份信息请求), T0702.class);
}
@Operation(summary = "8801 摄像头立即拍摄命令")
@PostMapping("8801")
public Mono<APIResult<T0805>> T8801(@RequestBody T8801 request) {
return messageManager.requestR(request, T0805.class);
}
@Operation(summary = "8802 存储多媒体数据检索")
@PostMapping("8802")
public Mono<APIResult<T0802>> T8802(@RequestBody T8802 request) {
return messageManager.requestR(request, T0802.class);
}
@Operation(summary = "8803 存储多媒体数据上传")
@PostMapping("8803")
public Mono<APIResult<T0001>> T8803(@RequestBody T8803 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8804 录音开始命令")
@PostMapping("8804")
public Mono<APIResult<T0001>> T8804(@RequestBody T8804 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8805 单条存储多媒体数据检索上传命令")
@PostMapping("8805")
public Mono<APIResult<T0001>> T8805(@RequestBody T8805 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8108 下发终端升级包")
@PostMapping("8108")
public Mono<APIResult<T0001>> T8108(@RequestBody T8108 request) {
return messageManager.requestR(request, T0001.class);
}
@Operation(summary = "8900 数据下行透传")
@PostMapping("8900")
public Mono<APIResult<T0001>> T8900(@RequestBody T8900 request) {
return messageManager.requestR(request.build(), T0001.class);
}
@Operation(summary = "8A00 平台RSA公钥")
@PostMapping("8A00")
public Mono<APIResult<T0A00_8A00>> T8A00(@RequestBody T0A00_8A00 request) {
return messageManager.requestR(request.build(), T0A00_8A00.class);
}
}
\ No newline at end of file
package com.zehong.web.controller;
import io.github.yezhihao.netmc.session.Session;
import io.github.yezhihao.netmc.session.SessionManager;
import io.github.yezhihao.netmc.util.AdapterCollection;
import io.github.yezhihao.protostar.util.Explain;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import com.zehong.commons.model.APIResult;
import com.zehong.commons.util.LogUtils;
import com.zehong.protocol.codec.JTMessageDecoder;
import com.zehong.web.config.WebLogAdapter;
import com.zehong.web.model.entity.DeviceDO;
import com.zehong.web.model.enums.SessionKey;
import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink;
import reactor.core.publisher.Mono;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.time.Duration;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@RestController
@RequestMapping
public class OtherController {
@Autowired
private SessionManager sessionManager;
@Autowired
private JTMessageDecoder decoder;
@Hidden
@Operation(hidden = true)
@GetMapping
public void doc(HttpServletResponse response) throws IOException {
response.sendRedirect("doc.html");
}
@Operation(summary = "终端实时信息查询")
@GetMapping("device/all")
public APIResult<Collection<Session>> all() {
Collection<Session> all = sessionManager.all();
return APIResult.ok(all);
}
@Operation(summary = "获得当前所有在线设备信息")
@GetMapping("device/option")
public APIResult<Collection<DeviceDO>> getClientId(HttpSession httpSession) {
AdapterCollection<Session, DeviceDO> result = new AdapterCollection<>(sessionManager.all(), session -> {
DeviceDO device = SessionKey.getDevice(session);
if (device != null)
return device;
return new DeviceDO().mobileNo(session.getClientId());
});
return APIResult.ok(result);
}
@Operation(summary = "设备订阅")
@PostMapping(value = "device/sse", produces = MediaType.TEXT_PLAIN_VALUE)
public String sseSub(HttpSession httpSession, @RequestParam String clientId, @RequestParam boolean sub) {
FluxSink<Object> emitter = (FluxSink<Object>) httpSession.getAttribute("emitter");
if (emitter == null) {
return "0";
}
if (sub) {
WebLogAdapter.addClient(clientId, emitter);
((Set<String>) httpSession.getAttribute("clientIds")).add(clientId);
} else {
WebLogAdapter.removeClient(clientId, emitter);
((Set<String>) httpSession.getAttribute("clientIds")).remove(clientId);
}
return "1";
}
@Operation(summary = "设备监控")
@GetMapping(value = "device/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Object> sseConnect(HttpSession httpSession, String clientId) {
return Flux.create(emitter -> {
Set<String> clientIds = new HashSet<>();
if (clientId != null) {
WebLogAdapter.addClient(clientId, emitter);
clientIds.add(clientId);
}
httpSession.setAttribute("clientIds", clientIds);
httpSession.setAttribute("emitter", emitter);
emitter.onDispose(() -> clientIds.forEach(id -> WebLogAdapter.removeClient(id, emitter)));
});
}
@Operation(summary = "808协议分析工具")
@RequestMapping(value = "message/explain", method = {RequestMethod.POST, RequestMethod.GET})
public String decode(@Parameter(description = "16进制报文") @RequestParam String hex) {
Explain explain = new Explain();
hex = hex.replace(" ", "");
String[] lines = hex.split("\n");
for (String line : lines) {
String[] msgs = line.split("7e7e");
for (String msg : msgs) {
ByteBuf byteBuf = Unpooled.wrappedBuffer(ByteBufUtil.decodeHexDump(msg));
decoder.decode(byteBuf, explain);
}
}
return explain.toString();
}
@Operation(summary = "原始消息发送")
@PostMapping("device/raw")
public Mono<String> postRaw(@Parameter(description = "终端手机号") @RequestParam String clientId,
@Parameter(description = "16进制报文") @RequestParam String message) {
Session session = sessionManager.get(clientId);
if (session != null) {
ByteBuf byteBuf = Unpooled.wrappedBuffer(ByteBufUtil.decodeHexDump(message));
return session.notify(byteBuf).map(unused -> "success")
.timeout(Duration.ofSeconds(10), Mono.just("timeout"))
.onErrorResume(throwable -> Mono.just("fail"));
}
return Mono.just("offline");
}
@Operation(summary = "修改日志级别")
@GetMapping("logger")
public String logger(@RequestParam LogUtils.Lv level) {
LogUtils.setLevel(level.value);
return "success";
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.github.yezhihao.netmc.core.annotation.Endpoint;
import io.github.yezhihao.netmc.core.annotation.Mapping;
import io.github.yezhihao.netmc.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.zehong.protocol.commons.JSATL12;
import com.zehong.protocol.jsatl12.DataPacket;
import com.zehong.protocol.jsatl12.T1210;
import com.zehong.protocol.jsatl12.T1211;
import com.zehong.protocol.jsatl12.T9212;
import com.zehong.web.service.FileService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Endpoint
@Component
public class JSATL12Endpoint {
@Autowired
private FileService fileService;
private final Cache<String, Map<String, T1210.Item>> cache = Caffeine.newBuilder().expireAfterAccess(20, TimeUnit.MINUTES).build();
@Mapping(types = JSATL12.报警附件信息消息, desc = "报警附件信息消息")
public void alarmFileInfoList(T1210 message, Session session) {
session.register(message.getDeviceId(), message);
List<T1210.Item> items = message.getItems();
if (items == null) return;
Map<String, T1210.Item> fileInfos = cache.get(message.getClientId(), s -> new HashMap<>((int) (items.size() / 0.75) + 1));
for (T1210.Item item : items)
fileInfos.put(item.getName(), item.parent(message));
fileService.createDir(message);
}
@Mapping(types = JSATL12.文件信息上传, desc = "文件信息上传")
public void alarmFileInfo(T1211 message, Session session) {
if (!session.isRegistered()) session.register(message);
}
@Mapping(types = JSATL12.文件数据上传, desc = "文件数据上传")
public Object alarmFile(DataPacket dataPacket, Session session) {
Map<String, T1210.Item> fileInfos = cache.getIfPresent(session.getClientId());
if (fileInfos != null) {
T1210.Item fileInfo = fileInfos.get(dataPacket.getName().trim());
if (fileInfo != null) {
if (dataPacket.getOffset() == 0 && dataPacket.getLength() >= fileInfo.getSize()) {
fileService.writeFileSingle(fileInfo.parent(), dataPacket);
} else {
fileService.writeFile(fileInfo.parent(), dataPacket);
}
}
}
return null;
}
@Mapping(types = JSATL12.文件上传完成消息, desc = "文件上传完成消息")
public T9212 alarmFileComplete(T1211 message) {
Map<String, T1210.Item> fileInfos = cache.getIfPresent(message.getClientId());
T1210.Item fileInfo = fileInfos.get(message.getName());
T9212 result = new T9212();
result.setName(message.getName());
result.setType(message.getType());
int[] items = fileService.checkFile(fileInfo.parent(), message);
if (items == null) {
fileInfos.remove(message.getName());
if (fileInfos.isEmpty()) {
cache.invalidate(message.getClientId());
}
result.setResult(0);
} else {
result.setItems(items);
result.setResult(1);
}
return result;
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import io.github.yezhihao.netmc.core.annotation.Endpoint;
import io.github.yezhihao.netmc.core.annotation.Mapping;
import io.github.yezhihao.netmc.session.Session;
import org.springframework.stereotype.Component;
import com.zehong.protocol.t1078.T1003;
import com.zehong.protocol.t1078.T1005;
import com.zehong.protocol.t1078.T1205;
import com.zehong.protocol.t1078.T1206;
import static com.zehong.protocol.commons.JT1078.*;
@Endpoint
@Component
public class JT1078Endpoint {
@Mapping(types = 终端上传音视频资源列表, desc = "终端上传音视频资源列表")
public void T1205(T1205 message, Session session) {
session.response(message);
}
@Mapping(types = 终端上传音视频属性, desc = "终端上传音视频属性")
public void T1003(T1003 message, Session session) {
session.response(message);
}
@Mapping(types = 文件上传完成通知, desc = "文件上传完成通知")
public void T1206(T1206 message, Session session) {
session.response(message);
}
@Mapping(types = 终端上传乘客流量, desc = "终端上传乘客流量")
public void T1005(T1005 message, Session session) {
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import io.github.yezhihao.netmc.core.annotation.Async;
import io.github.yezhihao.netmc.core.annotation.AsyncBatch;
import io.github.yezhihao.netmc.core.annotation.Endpoint;
import io.github.yezhihao.netmc.core.annotation.Mapping;
import io.github.yezhihao.netmc.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.t808.*;
import com.zehong.web.model.entity.DeviceDO;
import com.zehong.web.model.enums.SessionKey;
import com.zehong.web.service.FileService;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import static com.zehong.protocol.commons.JT808.*;
@Endpoint
@Component
public class JT808Endpoint {
private static final Logger log = LoggerFactory.getLogger(JT808Endpoint.class);
@Autowired
private FileService fileService;
@Mapping(types = 终端通用应答, desc = "终端通用应答")
public Object T0001(T0001 message, Session session) {
session.response(message);
return null;
}
@Mapping(types = 终端心跳, desc = "终端心跳")
public void T0002(JTMessage message, Session session) {
}
@Mapping(types = 终端注销, desc = "终端注销")
public void T0003(JTMessage message, Session session) {
session.invalidate();
}
@Mapping(types = 查询服务器时间, desc = "查询服务器时间")
public T8004 T0004(JTMessage message, Session session) {
T8004 result = new T8004(LocalDateTime.now(ZoneOffset.UTC));
return result;
}
@Mapping(types = 终端补传分包请求, desc = "终端补传分包请求")
public void T8003(T8003 message, Session session) {
}
@Mapping(types = 终端注册, desc = "终端注册")
public T8100 T0100(T0100 message, Session session) {
session.register(message);
DeviceDO device = new DeviceDO();
device.setProtocolVersion(message.getProtocolVersion());
device.setMobileNo(message.getClientId());
device.setDeviceId(message.getDeviceId());
device.setPlateNo(message.getPlateNo());
session.setAttribute(SessionKey.Device, device);
T8100 result = new T8100();
result.setResponseSerialNo(message.getSerialNo());
result.setToken(message.getDeviceId() + "," + message.getPlateNo());
result.setResultCode(T8100.Success);
return result;
}
@Mapping(types = 终端鉴权, desc = "终端鉴权")
public T0001 T0102(T0102 message, Session session) {
session.register(message);
DeviceDO device = new DeviceDO();
String[] token = message.getToken().split(",");
device.setProtocolVersion(message.getProtocolVersion());
device.setMobileNo(message.getClientId());
device.setDeviceId(token[0]);
if (token.length > 1)
device.setPlateNo(token[1]);
session.setAttribute(SessionKey.Device, device);
T0001 result = new T0001();
result.setResponseSerialNo(message.getSerialNo());
result.setResponseMessageId(message.getMessageId());
result.setResultCode(T0001.Success);
return result;
}
@Mapping(types = 查询终端参数应答, desc = "查询终端参数应答")
public void T0104(T0104 message, Session session) {
session.response(message);
}
@Mapping(types = 查询终端属性应答, desc = "查询终端属性应答")
public void T0107(T0107 message, Session session) {
session.response(message);
}
@Mapping(types = 终端升级结果通知, desc = "终端升级结果通知")
public void T0108(T0108 message, Session session) {
}
/**
* 异步批量处理
* poolSize:参考数据库CPU核心数量
* maxElements:最大累积4000条记录处理一次
* maxWait:最大等待时间1秒
*/
@AsyncBatch(poolSize = 2, maxElements = 4000, maxWait = 1000)
@Mapping(types = 位置信息汇报, desc = "位置信息汇报")
public void T0200(List<T0200> list) {
log.info("=========locationInfo============" + list.toString());
}
@Mapping(types = 定位数据批量上传, desc = "定位数据批量上传")
public void T0704(T0704 message) {
}
@Mapping(types = {位置信息查询应答, 车辆控制应答}, desc = "位置信息查询应答/车辆控制应答")
public void T0201_0500(T0201_0500 message, Session session) {
session.response(message);
}
@Mapping(types = 事件报告, desc = "事件报告")
public void T0301(T0301 message, Session session) {
}
@Mapping(types = 提问应答, desc = "提问应答")
public void T0302(T0302 message, Session session) {
}
@Mapping(types = 信息点播_取消, desc = "信息点播/取消")
public void T0303(T0303 message, Session session) {
}
@Mapping(types = 查询区域或线路数据应答, desc = "查询区域或线路数据应答")
public void T0608(T0608 message, Session session) {
session.response(message);
}
@Mapping(types = 行驶记录数据上传, desc = "行驶记录仪数据上传")
public void T0700(T0700 message, Session session) {
session.response(message);
}
@Mapping(types = 电子运单上报, desc = "电子运单上报")
public void T0701(JTMessage message, Session session) {
}
@Mapping(types = 驾驶员身份信息采集上报, desc = "驾驶员身份信息采集上报")
public void T0702(T0702 message, Session session) {
session.response(message);
}
@Mapping(types = CAN总线数据上传, desc = "CAN总线数据上传")
public void T0705(T0705 message, Session session) {
}
@Mapping(types = 多媒体事件信息上传, desc = "多媒体事件信息上传")
public void T0800(T0800 message, Session session) {
}
@Async
@Mapping(types = 多媒体数据上传, desc = "多媒体数据上传")
public JTMessage T0801(T0801 message, Session session) {
if (message.getPacket() == null) {
T0001 result = new T0001();
result.copyBy(message);
result.setMessageId(JT808.平台通用应答);
result.setSerialNo(session.nextSerialNo());
result.setResponseSerialNo(message.getSerialNo());
result.setResponseMessageId(message.getMessageId());
result.setResultCode(T0001.Success);
return result;
}
fileService.saveMediaFile(message);
T8800 result = new T8800();
result.setMediaId(message.getId());
return result;
}
@Mapping(types = 存储多媒体数据检索应答, desc = "存储多媒体数据检索应答")
public void T0802(T0802 message, Session session) {
session.response(message);
}
@Mapping(types = 摄像头立即拍摄命令应答, desc = "摄像头立即拍摄命令应答")
public void T0805(T0805 message, Session session) {
session.response(message);
}
@Mapping(types = 数据上行透传, desc = "数据上行透传")
public void T0900(T0900 message, Session session) {
}
@Mapping(types = 数据压缩上报, desc = "数据压缩上报")
public void T0901(T0901 message, Session session) {
}
@Mapping(types = 终端RSA公钥, desc = "终端RSA公钥")
public void T0A00(T0A00_8A00 message, Session session) {
session.response(message);
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import io.github.yezhihao.netmc.core.HandlerInterceptor;
import io.github.yezhihao.netmc.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.t808.T0001;
import com.zehong.protocol.t808.T0200;
import com.zehong.web.model.entity.DeviceDO;
import com.zehong.web.model.enums.SessionKey;
public class JTHandlerInterceptor implements HandlerInterceptor<JTMessage> {
private static final Logger log = LoggerFactory.getLogger(JTHandlerInterceptor.class);
/** 未找到对应的Handle */
@Override
public JTMessage notSupported(JTMessage request, Session session) {
T0001 response = new T0001();
response.copyBy(request);
response.setMessageId(JT808.平台通用应答);
response.setSerialNo(session.nextSerialNo());
response.setResponseSerialNo(request.getSerialNo());
response.setResponseMessageId(request.getMessageId());
response.setResultCode(T0001.NotSupport);
log.info("{}\n<<<<-未识别的消息{}\n>>>>-{}", session, request, response);
return response;
}
/** 调用之后,返回值为void的 */
@Override
public JTMessage successful(JTMessage request, Session session) {
T0001 response = new T0001();
response.copyBy(request);
response.setMessageId(JT808.平台通用应答);
response.setSerialNo(session.nextSerialNo());
response.setResponseSerialNo(request.getSerialNo());
response.setResponseMessageId(request.getMessageId());
response.setResultCode(T0001.Success);
// log.info("{}\n<<<<-{}\n>>>>-{}", session, request, response);
return response;
}
/** 调用之后抛出异常的 */
@Override
public JTMessage exceptional(JTMessage request, Session session, Exception e) {
T0001 response = new T0001();
response.copyBy(request);
response.setMessageId(JT808.平台通用应答);
response.setSerialNo(session.nextSerialNo());
response.setResponseSerialNo(request.getSerialNo());
response.setResponseMessageId(request.getMessageId());
response.setResultCode(T0001.Failure);
log.warn(session + "\n<<<<-" + request + "\n>>>>-" + response + '\n', e);
return response;
}
/** 调用之前 */
@Override
public boolean beforeHandle(JTMessage request, Session session) {
int messageId = request.getMessageId();
if (messageId == JT808.终端注册 || messageId == JT808.终端鉴权)
return true;
boolean transform = request.transform();
if (messageId == JT808.位置信息汇报) {
DeviceDO device = SessionKey.getDevice(session);
if (device != null)
device.setLocation((T0200) request);
return transform;
}
if (!session.isRegistered()) {
log.info("{}未注册的设备<<<<-{}", session, request);
return true;
}
return true;
}
/** 调用之后 */
@Override
public void afterHandle(JTMessage request, JTMessage response, Session session) {
if (response != null) {
response.copyBy(request);
response.setSerialNo(session.nextSerialNo());
if (response.getMessageId() == 0) {
response.setMessageId(response.reflectMessageId());
}
}
// log.info("{}\n<<<<-{}\n>>>>-{}", session, request, response);
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import io.github.yezhihao.netmc.session.Session;
import com.zehong.protocol.codec.MultiPacket;
import com.zehong.protocol.codec.MultiPacketListener;
import com.zehong.protocol.commons.JT808;
import com.zehong.protocol.t808.T8003;
import java.util.List;
public class JTMultiPacketListener extends MultiPacketListener {
public JTMultiPacketListener(int timeout) {
super(timeout);
}
@Override
public boolean receiveTimeout(MultiPacket multiPacket) {
int retryCount = multiPacket.getRetryCount();
if (retryCount > 5)
return false;
T8003 request = new T8003();
request.setMessageId(JT808.服务器补传分包请求);
request.copyBy(multiPacket.getFirstPacket());
request.setResponseSerialNo(multiPacket.getSerialNo());
List<Integer> notArrived = multiPacket.getNotArrived();
short[] idList = new short[notArrived.size()];
for (int i = 0; i < idList.length; i++) {
idList[i] = notArrived.get(i).shortValue();
}
request.setId(idList);
Session session = multiPacket.getFirstPacket().getSession();
if (session != null) {
session.notify(request).block();
multiPacket.addRetryCount(1);
return true;
}
return false;
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import io.github.yezhihao.netmc.core.model.Message;
import io.github.yezhihao.netmc.session.Session;
import io.github.yezhihao.netmc.session.SessionListener;
import com.zehong.protocol.basics.JTMessage;
import com.zehong.web.model.entity.DeviceDO;
import com.zehong.web.model.enums.SessionKey;
import java.util.function.BiConsumer;
public class JTSessionListener implements SessionListener {
/**
* 下行消息拦截器
*/
private static final BiConsumer<Session, Message> requestInterceptor = (session, message) -> {
JTMessage request = (JTMessage) message;
request.setClientId(session.getClientId());
request.setSerialNo(session.nextSerialNo());
if (request.getMessageId() == 0) {
request.setMessageId(request.reflectMessageId());
}
DeviceDO device = SessionKey.getDevice(session);
if (device != null) {
int protocolVersion = device.getProtocolVersion();
if (protocolVersion > 0) {
request.setVersion(true);
request.setProtocolVersion(protocolVersion);
}
}
};
/**
* 设备连接
*/
@Override
public void sessionCreated(Session session) {
session.requestInterceptor(requestInterceptor);
}
/**
* 设备注册
*/
@Override
public void sessionRegistered(Session session) {
}
/**
* 设备离线
*/
@Override
public void sessionDestroyed(Session session) {
}
}
\ No newline at end of file
package com.zehong.web.endpoint;
import io.github.yezhihao.netmc.session.Session;
import io.github.yezhihao.netmc.session.SessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.zehong.commons.model.APIException;
import com.zehong.commons.model.APIResult;
import com.zehong.protocol.basics.JTMessage;
import reactor.core.publisher.Mono;
import java.time.Duration;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
@Component
public class MessageManager {
private static final Logger log = LoggerFactory.getLogger(MessageManager.class);
private static final Mono<Void> NEVER = Mono.never();
private static final Mono OFFLINE_EXCEPTION = Mono.error(new APIException(4000, "离线的客户端(请检查设备是否注册或者鉴权)"));
private static final Mono OFFLINE_RESULT = Mono.just(new APIResult<>(4000, "离线的客户端(请检查设备是否注册或者鉴权)"));
private static final Mono SENDFAIL_RESULT = Mono.just(new APIResult<>(4001, "消息发送失败"));
private static final Mono TIMEOUT_RESULT = Mono.just(new APIResult<>(4002, "消息发送成功,客户端响应超时(至于设备为什么不应答,请联系设备厂商)"));
private SessionManager sessionManager;
public MessageManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
public Mono<Void> notifyR(String sessionId, JTMessage request) {
Session session = sessionManager.get(sessionId);
if (session == null)
return OFFLINE_EXCEPTION;
return session.notify(request);
}
public Mono<Void> notify(String sessionId, JTMessage request) {
Session session = sessionManager.get(sessionId);
if (session == null)
return NEVER;
return session.notify(request);
}
public <T> Mono<APIResult<T>> requestR(String sessionId, JTMessage request, Class<T> responseClass) {
Session session = sessionManager.get(sessionId);
if (session == null)
return OFFLINE_RESULT;
return session.request(request, responseClass)
.map(message -> APIResult.ok(message))
.timeout(Duration.ofSeconds(10), TIMEOUT_RESULT)
.onErrorResume(e -> {
log.warn("消息发送失败", e);
return SENDFAIL_RESULT;
});
}
public <T> Mono<APIResult<T>> requestR(JTMessage request, Class<T> responseClass) {
Session session = sessionManager.get(request.getClientId());
if (session == null)
return OFFLINE_RESULT;
return session.request(request, responseClass)
.map(message -> APIResult.ok(message))
.timeout(Duration.ofSeconds(10), TIMEOUT_RESULT)
.onErrorResume(e -> {
log.warn("消息发送失败", e);
return SENDFAIL_RESULT;
});
}
public <T> Mono<T> request(String sessionId, JTMessage request, Class<T> responseClass, long timeout) {
return request(sessionId, request, responseClass).timeout(Duration.ofMillis(timeout));
}
public <T> Mono<T> request(String sessionId, JTMessage request, Class<T> responseClass) {
Session session = sessionManager.get(sessionId);
if (session == null)
return OFFLINE_EXCEPTION;
return session.request(request, responseClass);
}
}
\ No newline at end of file
package com.zehong.web.model.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import com.zehong.protocol.t808.T0200;
import java.util.Objects;
public class DeviceDO {
@Schema(description = "设备id")
private String deviceId;
@Schema(description = "设备手机号")
private String mobileNo;
@Schema(description = "车牌号")
private String plateNo;
@Schema(description = "机构id")
protected int agencyId;
@Schema(description = "司机id")
protected int driverId;
@Schema(description = "协议版本号")
private int protocolVersion;
@Schema(description = "实时状态")
private T0200 location;
public DeviceDO() {
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
public String getPlateNo() {
return plateNo;
}
public void setPlateNo(String plateNo) {
this.plateNo = plateNo;
}
public int getProtocolVersion() {
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
}
public T0200 getLocation() {
return location;
}
public void setLocation(T0200 location) {
this.location = location;
}
public DeviceDO mobileNo(String mobileNo) {
this.mobileNo = mobileNo;
return this;
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
DeviceDO other = (DeviceDO) that;
return Objects.equals(this.deviceId, other.deviceId);
}
@Override
public int hashCode() {
return ((deviceId == null) ? 0 : deviceId.hashCode());
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(256);
sb.append("DeviceDO{deviceId=").append(deviceId);
sb.append(", mobileNo=").append(mobileNo);
sb.append(", plateNo=").append(plateNo);
sb.append(", protocolVersion=").append(protocolVersion);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.web.model.enums;
import io.github.yezhihao.netmc.session.Session;
import com.zehong.web.model.entity.DeviceDO;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public enum SessionKey {
Device;
public static DeviceDO getDevice(Session session) {
return (DeviceDO) session.getAttribute(Device);
}
}
\ No newline at end of file
package com.zehong.web.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import com.zehong.protocol.commons.Charsets;
import java.io.*;
import java.time.LocalDate;
import static io.github.yezhihao.protostar.util.DateTool.BCD;
/**
* @author yezhihao
* https://gitee.com/yezhihao/jt808-server
*/
public class DeviceInfo {
@Schema(description = "签发日期")
protected LocalDate issuedAt;
@Schema(description = "预留字段")
protected byte reserved;
@Schema(description = "设备id")
protected String deviceId;
public DeviceInfo() {
}
public DeviceInfo(byte[] bytes) {
formBytes(bytes);
}
public DeviceInfo(String deviceId, LocalDate issuedAt) {
this.deviceId = deviceId;
this.issuedAt = issuedAt;
}
public LocalDate getIssuedAt() {
return issuedAt;
}
public void setIssuedAt(LocalDate issuedAt) {
this.issuedAt = issuedAt;
}
public byte getReserved() {
return reserved;
}
public void setReserved(byte reserved) {
this.reserved = reserved;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public DeviceInfo formBytes(byte[] bytes) {
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
DataInputStream dis = new DataInputStream(bis)) {
byte[] temp;
dis.read(temp = new byte[3]);
this.issuedAt = BCD.toDate(temp);
this.reserved = dis.readByte();
int len = dis.readUnsignedByte();
dis.read(temp = new byte[len]);
this.deviceId = new String(temp, Charsets.GBK);
return this;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public byte[] toBytes() {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(32);
DataOutputStream dos = new DataOutputStream(bos)) {
dos.write(BCD.from(issuedAt));
dos.writeByte(reserved);
byte[] bytes = deviceId.getBytes(Charsets.GBK);
dos.writeByte(bytes.length);
dos.write(bytes);
return bos.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("DeviceInfo{");
sb.append("issuedAt=").append(issuedAt);
sb.append(", reserved=").append(reserved);
sb.append(", deviceId=").append(deviceId);
sb.append('}');
return sb.toString();
}
}
\ No newline at end of file
package com.zehong.web.service;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.zehong.commons.util.DateUtils;
import com.zehong.commons.util.IOUtils;
import com.zehong.commons.util.StrUtils;
import com.zehong.protocol.jsatl12.DataPacket;
import com.zehong.protocol.jsatl12.T1210;
import com.zehong.protocol.jsatl12.T1211;
import com.zehong.protocol.t808.T0200;
import com.zehong.protocol.t808.T0801;
import com.zehong.web.model.entity.DeviceDO;
import com.zehong.web.model.enums.SessionKey;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@Service
public class FileService {
private static final Logger log = LoggerFactory.getLogger(FileService.class.getSimpleName());
private static final Comparator<long[]> comparator = Comparator.comparingLong((long[] a) -> a[0]).thenComparingLong(a -> a[1]);
@Value("${jt-server.alarm-file.path}")
private String workDirPath;
@Value("${jt-server.jt808.media-file.path}")
private String mediaFileRoot;
private String getDir(T1210 alarmId) {
StringBuilder sb = new StringBuilder(80);
sb.append(workDirPath).append('/');
sb.append(alarmId.getClientId()).append('_');
DateUtils.yyMMddHHmmss.formatTo(alarmId.getDateTime(), sb);
sb.append('_').append(alarmId.getSerialNo()).append('/');
return sb.toString();
}
/** 创建报警目录及 附件列表日志 */
public void createDir(T1210 alarmId) {
String dirPath = getDir(alarmId);
new File(dirPath).mkdirs();
List<T1210.Item> items = alarmId.getItems();
StringBuilder fileList = new StringBuilder(items.size() * 50);
fileList.append(dirPath).append(IOUtils.Separator);
for (T1210.Item item : items)
fileList.append(item.getName()).append('\t').append(item.getSize()).append(IOUtils.Separator);
IOUtils.write(fileList.toString(), new File(dirPath, "fs.txt"));
}
/** 将数据块写入到报警文件,并记录日志 */
public void writeFile(T1210 alarmId, DataPacket fileData) {
String dir = getDir(alarmId);
String name = dir + fileData.getName().trim();
int offset = fileData.getOffset();
int length = fileData.getLength();
byte[] buffer = ByteBuffer.allocate(8)
.putInt(offset).putInt(length).array();
RandomAccessFile file = null;
FileOutputStream filelog = null;
ByteBuf data = fileData.getData();
try {
file = new RandomAccessFile(name + ".tmp", "rw");
filelog = new FileOutputStream(name + ".log", true);
data.readBytes(file.getChannel(), offset, data.readableBytes());
filelog.write(buffer);
} catch (IOException e) {
log.error("写入报警文件", e);
} finally {
IOUtils.close(file, filelog);
}
}
public void writeFileSingle(T1210 alarmId, DataPacket fileData) {
String dir = getDir(alarmId);
String name = dir + fileData.getName().trim();
int offset = fileData.getOffset();
RandomAccessFile file = null;
ByteBuf data = fileData.getData();
try {
file = new RandomAccessFile(name, "rw");
data.readBytes(file.getChannel(), offset, data.readableBytes());
} catch (IOException e) {
log.error("写入报警文件", e);
} finally {
IOUtils.close(file);
}
}
/** 根据日志检查文件完整性,并返回缺少的数据块信息 */
public int[] checkFile(T1210 alarmId, T1211 fileInfo) {
String dir = getDir(alarmId);
File logFile = new File(dir + fileInfo.getName() + ".log");
byte[] bytes;
FileInputStream in = null;
try {
in = new FileInputStream(logFile);
bytes = new byte[in.available()];
in.read(bytes);
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
log.error("检查文件完整性", e);
return null;
} finally {
IOUtils.close(in);
}
int size = bytes.length / 8;
long[][] items = new long[size + 2][2];
items[size + 1][0] = fileInfo.getSize();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
for (int i = 1; i <= size; i++) {
items[i][0] = buffer.getInt();
items[i][1] = buffer.getInt();
}
List<Integer> result = new ArrayList<>(items.length);
int len = items.length - 1;
Arrays.sort(items, 1, len, comparator);
for (int i = 0; i < len; ) {
long a = items[i][0] + items[i][1];
long b = items[++i][0] - a;
if (b > 0) {
result.add((int) a);
result.add((int) b);
}
}
if (result.isEmpty()) {
File file = new File(dir + fileInfo.getName() + ".tmp");
File dest = new File(dir + fileInfo.getName());
if (file.renameTo(dest)) {
logFile.delete();
}
return null;
}
return StrUtils.toArray(result);
}
/** 多媒体数据上传 */
public boolean saveMediaFile(T0801 message) {
DeviceDO device = SessionKey.getDevice(message.getSession());
T0200 location = message.getLocation();
StringBuilder filename = new StringBuilder(32);
filename.append(type(message.getType())).append('_');
DateUtils.yyMMddHHmmss.formatTo(location.getDeviceTime(), filename);
filename.append('_');
filename.append(message.getChannelId()).append('_');
filename.append(message.getEvent()).append('_');
filename.append(message.getId()).append('.');
filename.append(suffix(message.getFormat()));
String deviceId;
if (device == null)
deviceId = message.getClientId();
else
deviceId = device.getDeviceId();
File dir = new File(mediaFileRoot + '/' + deviceId);
dir.mkdirs();
ByteBuf packet = message.getPacket();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(dir, filename.toString()));
packet.readBytes(fos.getChannel(), 0, packet.readableBytes());
return true;
} catch (IOException e) {
log.error("多媒体数据保存失败", e);
return false;
} finally {
IOUtils.close(fos);
packet.release();
}
}
private static String type(int type) {
switch (type) {
case 0:
return "image";
case 1:
return "audio";
case 2:
return "video";
default:
return "unknown";
}
}
private static String suffix(int format) {
switch (format) {
case 0:
return "jpg";
case 1:
return "tif";
case 2:
return "mp3";
case 3:
return "wav";
case 4:
return "wmv";
default:
return "bin";
}
}
}
\ No newline at end of file
jt-server:
jt808:
enable: true
port:
udp: 7611
tcp: 8904
media-file:
path: /data/vehicleActualPositionls\\\/jt_data/media_file
alarm-file:
host: 127.0.0.1
port: 7612
alarm-file:
enable: true
port: 7612
path: D:/jt_data/alarm_file
\ No newline at end of file
#测试环境配置
jt-server:
jt808:
enable: true
port:
udp: 7611
tcp: 7611
media-file:
path: D:/jt_data/media_file
alarm-file:
host: 127.0.0.1
port: 7612
alarm-file:
enable: true
port: 7612
path: D:/jt_data/alarm_file
\ No newline at end of file
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 8000
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# tomcat最大线程数,默认为200
max-threads: 800
# Tomcat启动初始化的线程数,默认值25
min-spare-threads: 30
spring:
profiles:
active: prd
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
mvc:
format:
date-time: yyyy-MM-dd HH:mm:ss
date: yyyy-MM-dd
time: HH:mm:ss
# 日志配置
logging:
level:
com.zehong: debug
org.springframework: warn
file:
path: ./logs
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="true">
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(%X{TRANCE_ID:-}) %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(-&#45;&#45;){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %X{TRANCE_ID:-} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } -&#45;&#45; [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="LOG_FILE" value="positionServer.log"/>
<!-- 控制台输出配置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 文件输出配置 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}/${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 分片格式以及压缩设置 -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<!-- 单个分片文件大小,默认是10M(压缩前) -->
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
<!-- 日志保存的最大时间,默认是永久保存 -->
<maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>设备消息监控</title>
<style>
html, body {
height: 100%;
margin: 0;
background-color: #3C3F41;
}
table {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
td {
height: inherit;
border: 1px solid #555;
}
select {
width: 210px;
height: 30px;
margin: 0 auto 5px auto;
color: #BABABA;
font-size: 16px;
padding: 2px;
border: 1px solid #646464;
background-color: #414141;
}
input {
width: 100px;
height: 23px;
color: #BABABA;
padding: 2px;
border: 1px solid #646464;
background-color: #414141;
}
button {
width: 90px;
color: #BABABA;
font-size: 18px;
border: 1px solid #4C708C;
background-color: #365880;
}
button:active {
color: #EEE;
border: 1px solid #6B96B4;
}
p {
color: #BABABA;
text-align: left;
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-all;
}
a {
color: #FFF;
}
.cell {
height: inherit;
text-align: center;
display: flex;
flex-direction: column;
}
.textarea {
height: inherit;
overflow: auto;
background-color: #2B2B2B;
}
.tool {
padding: 10px 0 10px 0;
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-thumb {
background-color: #666;
}
::-webkit-scrollbar-thumb:hover {
background-color: #777;
}
</style>
</head>
<body>
<table id="dev_box">
<tr>
<td>
<div class="cell">
<div class="textarea" id="dev_text_[idx]"></div>
<div class="tool">
<select id="dev_sel_[idx]">[option]</select>
<input type="text" onkeyup="onSearch(this)">
<button type="button" onclick="onSub([idx])">订阅</button>
<button type="button" onclick="onUnsub([idx])">取消</button>
<button type="button" onclick="$('dev_text_[idx]').innerHTML=''">清空</button>
<button type="button" onclick="onExport([idx])">导出</button>
</div>
</div>
</td>
</tr>
</table>
<a href="?s=1,2" target="_blank">1*2</a>
<a href="?s=1,4" target="_blank">1*4</a>
<a href="?s=2,6" target="_blank">2*6</a>
<script type="text/javascript">
const reg = new RegExp("\\[([^\\[\\]]*?)]", 'igm'); //igm是指分别用于指定区分大小写的匹配、全局匹配和多行匹配。
const host = window.location.host;
const domain = '//' + host;
let eventSource = null;
const subscriptions = {};
const $ = function (id) {
return document.getElementById(id);
};
function getQueryVariable(key) {
const query = window.location.search.substring(1);
const paramsArr = query.split("&");
for (let i = 0; i < paramsArr.length; i++) {
const pair = paramsArr[i].split("=");
if (pair[0] === key) {
return pair[1];
}
}
return null;
}
const renderForm = function (data) {
let options = '<option value="">没有可订阅的设备</option>\n';
if (data && data.length) {
options = '<option value="">---请选择订阅设备---</option>\n';
options += data.map(function (device) {
return `<option value="${device.mobileNo}">${device.mobileNo} - ${device.plateNo}</option>`
}).join('\n');
}
let size = [1, 1];
const s = getQueryVariable('s');
if (s)
size = s.split(',');
const row = size[0] > 3 ? 3 : size[0];
const column = size[1] > 6 ? 6 : size[1];
const height = Math.floor((document.documentElement.clientHeight) / row) - 1;
const table = $('dev_box');
const td = table.children[0].children[0].innerHTML;
let html = '';
let idx = 0;
for (let i = 0; i < row; i++) {
html += `<tr style="height: ${height}px">`;
for (let j = 0; j < column; j++) {
html += td.replace(reg, function (node, key) {
return ({idx: idx, option: options})[key]
});
++idx;
}
html += '</tr>';
}
table.innerHTML = html;
};
function onSearch(e) {
let value = e.value;
let select = e.previousElementSibling;
if (!select.disabled) {
const options = select.querySelectorAll('option');
options[0].selected = true;
if (value) {
options.forEach(option => {
if (option.innerHTML.search(value) >= 0) {
option.selected = true;
}
});
}
}
}
function onExport(idx) {
const data = $('dev_text_' + idx).innerText;
if (data) {
const a = document.createElement('a');
a.download = $('dev_sel_' + idx).value + '_' + new Date().toLocaleString().replaceAll(/[^0-9]/g, '_') + '.txt';
a.href = 'data:text/plain;base64,' + btoa(unescape(encodeURIComponent(data)));
a.click();
}
}
function onSub(idx) {
const select = $('dev_sel_' + idx);
if (select.disabled) {
return;
}
const clientId = select.value;
if (!clientId) {
return;
}
if (subscriptions[clientId]) {
alert(`同一设备[${clientId}]不能重复订阅`);
return;
}
select.disabled = true;
const text = $('dev_text_' + idx);
text.println = function (data) {
const c = this.scrollTop + this.offsetHeight + 4;
const h = this.scrollHeight;
const p = document.createElement('p');
p.append(new Date().toLocaleString().replaceAll('/', '-') + ' ');
p.append(data);
this.append(p);
if (c >= h)
this.scrollTop = this.scrollHeight;
}
eventSource.addEventListener(clientId, subscriptions[clientId] = function (event) {
text.println(event.data);
});
fetch(`${domain}/device/sse?sub=1&clientId=${clientId}`, {method: 'post'})
.then(res => res.json())
.then(function (res) {
if (res) {
text.println('开始订阅');
} else {
text.println('订阅失败,请刷新页面');
}
}).catch(err => text.println('连接服务器失败'));
}
function onUnsub(idx) {
const select = $('dev_sel_' + idx);
const clientId = select.value;
if (!clientId) {
return;
}
fetch(`${domain}/device/sse?sub=0&clientId=${clientId}`, {method: 'post'})
.then(res => res.json())
.then(function (res) {
if (res) {
console.log(`取消订阅设备[${clientId}]....`);
eventSource.removeEventListener(clientId, subscriptions[clientId]);
delete subscriptions[clientId];
select.disabled = false;
$('dev_text_' + idx).println('结束订阅');
}
}).catch(err => console.error(err));
}
window.onload = function () {
fetch(`${domain}/device/option`)
.then(res => res.json())
.then(function (res) {
renderForm(res.data);
eventSource = new EventSource(`${domain}/device/sse`);
eventSource.addEventListener('open', function (e) {
console.log(`建立连接`);
});
eventSource.addEventListener('error', function (e) {
console.log(`断开连接`);
});
}).catch(err => console.error(err));
}
</script>
</body>
</html>
\ No newline at end of file
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