Commit 2b7277a0 by xmh

通了

1 parent f0b6b57f
......@@ -25,17 +25,6 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.viontech.keliu</groupId>
<artifactId>keliu-util</artifactId>
<version>6.0.7-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>maven-scm-provider-integrity</artifactId>
<groupId>org.apache.maven.scm</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.32.Final</version>
......@@ -60,6 +49,16 @@
<artifactId>commons-pool2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
</dependencies>
<build>
......
......@@ -7,6 +7,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(exclude = org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class)
@Slf4j
public class Application {
private final static long REAL_TIME = 0x00000001L;
private final static long NOT_REAL_TIME = 0x00000002L;
public static void main(String[] args) {
try {
......@@ -15,4 +17,5 @@ public class Application {
log.error("error", e);
}
}
}
package com.viontech.controller;
import com.viontech.model.BaseModel;
import com.viontech.netty.ChannelGroup;
import com.viontech.process.Process;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.sound.sampled.Line;
/**
* .
*
......@@ -13,16 +17,18 @@ import org.springframework.web.bind.annotation.RestController;
* @date 2020/8/18
*/
@RestController
@Slf4j
public class DataController {
@Autowired
Process process;
@PostMapping("/data")
public Object receiveData(@RequestBody String dataStr) throws Exception{
process.process(dataStr);
return null;
public Object receiveData(@RequestBody String dataStr) throws Exception {
log.info("收到一条繁星发来的消息");
BaseModel data = Process.process(dataStr);
if (data != null) {
data.encodeData();
ChannelGroup.broadcast(data);
}
return "success";
}
......
......@@ -15,10 +15,10 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
public class BaseModel {
protected Long deviceId;
protected Long length;
protected Long firstInt;
protected Long secondInt;
protected long deviceId;
protected long length;
protected long protocol;
protected long flag;
protected byte[] data;
......@@ -51,8 +51,8 @@ public class BaseModel {
model.setDeviceId(deviceId);
model.setLength(length);
model.setFirstInt(firstInt);
model.setSecondInt(secondInt);
model.setProtocol(firstInt);
model.setFlag(secondInt);
if (length > 16) {
model.data = new byte[(int) (length - 16)];
byteBuf.readBytes(model.data);
......@@ -61,8 +61,17 @@ public class BaseModel {
return model;
}
public static int castLong2Int(long data) {
return (int) (data & 0xFF);
public static int toInt(long data) {
return (int) data;
}
public static byte[] toBytes(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
/**
......@@ -73,18 +82,24 @@ public class BaseModel {
public void to(ByteBuf byteBuf) {
encodeData();
byteBuf.writeInt(castLong2Int(deviceId));
byteBuf.writeInt(castLong2Int(length));
byteBuf.writeInt(castLong2Int(firstInt));
byteBuf.writeInt(castLong2Int(secondInt));
byteBuf.writeInt(toInt(deviceId));
byteBuf.writeInt(toInt(length));
byteBuf.writeInt(toInt(protocol));
byteBuf.writeInt(toInt(flag));
if (data != null && data.length > 0) {
byteBuf.writeBytes(data);
}
}
protected void encodeData() {
/**
* 重写此方法,将相关的字段组装成 byte[] 并赋值给 data
*/
public void encodeData() {
}
protected void decodeData() {
/**
* 重写此方法,将 byte[] 解析到子类的字段中
*/
public void decodeData() {
}
}
package com.viontech.model;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import lombok.Getter;
import lombok.Setter;
/**
* .
*
* @author 谢明辉
* @date 2020/8/24
*/
@Getter
@Setter
public class BehaviorModel extends BaseModel {
private final byte[] licensePlateText = new byte[16];
private final byte[] recordingPath = new byte[128];
private final byte[] eventLocation = new byte[32];
private final byte[] eventSnapshotPath = new byte[128];
private int serialNum;
private int recordingStartSecond;
private int recordingStartMillisecond;
private int recordingEndSecond;
private int recordingEndMillisecond;
private int eventStartSecond;
private int eventStartMillisecond;
private int eventEndSecond;
private int eventEndMillisecond;
private int eventCode;
private int laneNo;
private int pictureSize;
private int pictureWidth;
private int pictureHeight;
private int x;
private int y;
private int vehicleType;
private int color1;
private int speed;
private int direction;
private int color2;
private int color3;
private int color1Weights;
private int color2Weights;
private int color3Weights;
private int vehicleCategory;
private int reservedField;
private int recordingDuration;
private int faceWidth;
private int faceHeight;
private byte[] reservedField2 = new byte[24];
private byte[] picture;
@Override
public void encodeData() {
this.length = 16L + 448L + picture.length;
this.protocol = 0x00040006L;
ByteArrayBuilder builder = new ByteArrayBuilder(Math.toIntExact(this.length - 16));
builder.appendFourBytes(serialNum);
builder.appendFourBytes(recordingStartSecond);
builder.appendFourBytes(recordingStartMillisecond);
builder.appendFourBytes(recordingEndSecond);
builder.appendFourBytes(recordingEndMillisecond);
builder.appendFourBytes(eventStartSecond);
builder.appendFourBytes(eventStartMillisecond);
builder.appendFourBytes(eventEndSecond);
builder.appendFourBytes(eventEndMillisecond);
builder.appendFourBytes(laneNo);
builder.appendFourBytes(pictureSize);
builder.appendFourBytes(pictureWidth);
builder.appendFourBytes(pictureHeight);
builder.appendFourBytes(x);
builder.appendFourBytes(y);
builder.write(licensePlateText);
builder.write(recordingPath);
builder.appendFourBytes(vehicleType);
builder.appendFourBytes(color1);
builder.appendFourBytes(speed);
builder.appendFourBytes(direction);
builder.write(eventLocation);
builder.write(eventSnapshotPath);
builder.appendFourBytes(color2);
builder.appendFourBytes(color3);
builder.appendFourBytes(color1Weights);
builder.appendFourBytes(color2Weights);
builder.appendFourBytes(color3Weights);
builder.appendFourBytes(vehicleCategory);
builder.appendFourBytes(reservedField);
builder.appendFourBytes(recordingDuration);
builder.appendFourBytes(faceWidth);
builder.appendFourBytes(faceHeight);
builder.write(reservedField2);
builder.write(picture);
// todo 待crc校验
this.data = builder.resetAndGetFirstSegment();
}
}
package com.viontech.model;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import lombok.Getter;
import lombok.Setter;
/**
* .
*
* @author 谢明辉
* @date 2020/8/24
*/
@Getter
@Setter
public class FlowModel extends BaseModel {
private final int[] laneNoAndType = new int[16];
private final int[] traffic = new int[16];
private final int[] avgSpeed = new int[16];
private final int[] maxQueueLen = new int[16];
private final int[] avgDistanceBetweenVehicle = new int[16];
private final int[] trafficSupplement = new int[16];
private int serialNum;
private int time;
private int timeDuring;
private byte[] reservedField = new byte[64];
@Override
public void encodeData() {
this.length = 540L;
this.protocol = 0x00040005L;
ByteArrayBuilder builder = new ByteArrayBuilder(Math.toIntExact(this.length - 16));
builder.appendFourBytes(toInt(deviceId));
builder.appendFourBytes(toInt(length));
builder.appendFourBytes(toInt(protocol));
builder.appendFourBytes(toInt(flag));
builder.appendFourBytes(serialNum);
builder.appendFourBytes(time);
builder.appendFourBytes(timeDuring);
for (int value : laneNoAndType) {
builder.appendFourBytes(value);
}
for (int value : traffic) {
builder.appendFourBytes(value);
}
for (int value : avgSpeed) {
builder.appendFourBytes(value);
}
for (int value : maxQueueLen) {
builder.appendFourBytes(value);
}
for (int value : avgDistanceBetweenVehicle) {
builder.appendFourBytes(value);
}
for (int value : trafficSupplement) {
builder.appendFourBytes(value);
}
builder.write(reservedField);
this.data = builder.resetAndGetFirstSegment();
}
}
......@@ -11,12 +11,12 @@ public class KeepAlive extends BaseModel{
@Override
protected void encodeData() {
public void encodeData() {
}
@Override
protected void decodeData() {
public void decodeData() {
}
}
package com.viontech.model;
/**
* .
*
* @author 谢明辉
* @date 2020/8/21
*/
public class LicensePlateRecord extends BaseModel {
/** 序列号 */
private Long serialNum;
/** 识别车牌时间(秒) */
private Long discernSecondTime;
/** 识别车牌时间(毫秒) */
private Long discernMillisecondTime;
/** 车牌文字 */
private String LicensePlateText;
/** 车牌类型 */
private Long LicensePlateType;
/** 识别可靠度 */
private Long confidence;
/** 车道 */
private Long lane;
/** 车辆类型 */
private Long vehicleType;
/** 图片大小宽高 */
private Long secondPictureSize;
private Long secondPictureWidth;
private Long secondPictureHeight;
private Long firstPictureSize;
private Long firstPictureWidth;
private Long firstPictureHeight;
/** 车牌在第一张图片两种 左上右下 位置 */
private Long patternLeft;
private Long patternTop;
private Long patternRight;
private Long patternBottom;
@Override
protected void encodeData() {
this.firstInt = 0x00020004L;
}
}
......@@ -19,13 +19,13 @@ public class LoginData extends BaseModel {
private String password;
@Override
protected void decodeData() {
this.username = new String(data, 0, 32, StandardCharsets.UTF_8);
this.password = new String(data, 32, 32, StandardCharsets.UTF_8);
public void decodeData() {
this.username = new String(data, 0, 32, StandardCharsets.UTF_8).trim();
this.password = new String(data, 32, 32, StandardCharsets.UTF_8).trim();
}
@Override
protected void encodeData() {
public void encodeData() {
}
}
package com.viontech.model;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.zip.CRC32;
/**
* 发送车牌记录,包含电警记录
*
* @author 谢明辉
* @date 2020/8/21
*/
@Getter
@Setter
@Accessors(chain = true)
public class TrafficModel extends BaseModel {
/** 车牌文字 */
private final byte[] plateText = new byte[16];
/** 经过地点 */
private final byte[] routeLocation = new byte[32];
/** 录像路径 */
private final byte[] videoPath = new byte[128];
/** 第一张照片路径 */
private final byte[] picturePath = new byte[128];
/** 序列号 */
private int serialNum;
/** 识别车牌时间(秒) */
private int discernTime;
/** 识别车牌时间(毫秒) */
private int discernMillisecondTime;
/** 车牌类型 */
private int plateType;
/** 车牌识别可靠度 */
private int confidence;
/** 车道 */
private int lane;
/** 车辆类型 */
private int vehicleType;
/** 图片大小宽高 */
private int secondPictureSize;
private int secondPictureWidth;
private int secondPictureHeight;
private int firstPictureSize;
private int firstPictureWidth;
private int firstPictureHeight;
/** 车牌在第一张图片两种 左上右下 位置 */
private int patternLeft;
private int patternTop;
private int patternRight;
private int patternBottom;
/** 车身颜色 */
private int color;
/** 车速 */
private int speed;
/** 方向 */
private int direction;
/** 厂商标志 */
private int manufacturerLogo;
/** 三个预留位 */
private int reservedField;
private int reservedField2;
private int reservedField3;
/** 车型细分 */
private int vehicleCategory;
/** 车牌结构 1单行2双行3其他 */
private int plateStructure;
/** 违章类型 */
private int illegalType;
/** 预留位 */
private int reservedField4;
/** 第二张图片抓拍时间 */
private int secondPictureTime;
private int secondPictureMillisecondTime;
/** 红灯开始时间 */
private int redLightBeginTime;
private int redLightBeginMillisecondTime;
/** 红灯结束时间 */
private int redLightEndTime;
private int redLightEndMillisecondTime;
/** 限速值 */
private int speedLimit;
/** 超速抓拍值 */
private int overSpeedThreshold;
/** 预留字段 */
private byte[] reservedField5 = new byte[4];
/** picture1 */
private byte[] picture1 = new byte[0];
/** picture2 */
private byte[] picture2 = new byte[0];
@Override
public void encodeData() {
this.protocol = 0x00020004L;
this.length = 16L + 452L + picture1.length + picture2.length + 4;
ByteArrayBuilder builder = new ByteArrayBuilder(Math.toIntExact(this.length - 16 - 4));
builder.appendFourBytes(serialNum);
builder.appendFourBytes(discernTime);
builder.appendFourBytes(discernMillisecondTime);
builder.write(plateText);
builder.appendFourBytes(plateType);
builder.appendFourBytes(confidence);
builder.appendFourBytes(lane);
builder.appendFourBytes(vehicleType);
builder.appendFourBytes(secondPictureSize);
builder.appendFourBytes(secondPictureWidth);
builder.appendFourBytes(secondPictureHeight);
builder.appendFourBytes(firstPictureSize);
builder.appendFourBytes(firstPictureWidth);
builder.appendFourBytes(firstPictureHeight);
builder.appendFourBytes(patternLeft);
builder.appendFourBytes(patternTop);
builder.appendFourBytes(patternRight);
builder.appendFourBytes(patternBottom);
builder.appendFourBytes(color);
builder.appendFourBytes(speed);
builder.appendFourBytes(direction);
builder.appendFourBytes(manufacturerLogo);
builder.write(routeLocation);
builder.write(videoPath);
builder.write(picturePath);
builder.appendFourBytes(reservedField);
builder.appendFourBytes(reservedField2);
builder.appendFourBytes(reservedField3);
builder.appendFourBytes(vehicleCategory);
builder.appendFourBytes(plateStructure);
builder.appendFourBytes(illegalType);
builder.appendFourBytes(reservedField4);
builder.appendFourBytes(secondPictureTime);
builder.appendFourBytes(secondPictureMillisecondTime);
builder.appendFourBytes(redLightBeginTime);
builder.appendFourBytes(redLightBeginMillisecondTime);
builder.appendFourBytes(redLightEndTime);
builder.appendFourBytes(redLightEndMillisecondTime);
builder.appendFourBytes(speedLimit);
builder.appendFourBytes(overSpeedThreshold);
builder.write(reservedField5);
builder.write(picture1);
builder.write(picture2);
byte[] bytes = builder.resetAndGetFirstSegment();
int count = bytes.length;
// crc32
CRC32 crc32 = new CRC32();
crc32.update(bytes);
int value = (int) crc32.getValue();
for (int i = 0; i < count; i++) {
bytes[i] = (byte) (bytes[i] ^ 0x94);
}
this.data = new byte[count + 4];
System.arraycopy(bytes, 0, data, 0, count);
this.data[count++] = (byte) (value >> 24);
this.data[count++] = (byte) (value >> 16);
this.data[count++] = (byte) (value >> 8);
this.data[count] = (byte) value;
}
}
package com.viontech.netty;
import com.viontech.model.BaseModel;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
......@@ -56,7 +57,7 @@ public class ChannelGroup {
*
* @param msg 消息
*/
public static void broadcast(Object msg) {
public static void broadcast(BaseModel msg) {
for (Channel channel : DEVICE_CHANNEL_MAP.values()) {
try {
channel.writeAndFlush(msg).await();
......
......@@ -29,15 +29,19 @@ public class NettyReceiverHandler extends ChannelInboundHandlerAdapter {
//注册命令
if (message instanceof LoginData) {
BaseModel result = new BaseModel().setDeviceId(0L).setLength(16L).setFirstInt(0x00020100L);
BaseModel result = new BaseModel().setDeviceId(0L).setLength(16L).setProtocol(0x00020100L);
LoginData logindata = (LoginData) message;
Long deviceId = logindata.getDeviceId();
System.out.println(logindata.getUsername());
System.out.println(logindata.getPassword());
if ("admin".equals(logindata.getUsername()) && "admin".equals(logindata.getPassword())) {
ChannelGroup.registered(deviceId, ctx.channel());
result.setSecondInt(0L);
result.setFlag(0L);
} else {
result.setSecondInt(1L);
result.setFlag(1L);
}
ctx.writeAndFlush(result).await();
} else if (message instanceof KeepAlive) {
......@@ -51,6 +55,7 @@ public class NettyReceiverHandler extends ChannelInboundHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
cause.printStackTrace();
}
@Override
......
......@@ -41,7 +41,7 @@ public class NettyServer implements CommandLineRunner {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024 * 1024 * 1000, 4, 4, -16, 0));
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024 * 1024 * 1000, 4, 4, -8, 0));
ch.pipeline().addLast(new ByteToMessageCodecHandler());
ch.pipeline().addLast(new NettyReceiverHandler());
}
......
package com.viontech.process;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.viontech.model.BaseModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* .
......@@ -12,23 +11,31 @@ import java.util.Map;
* @author 谢明辉
* @date 2020/8/20
*/
public interface Process {
Logger log = LoggerFactory.getLogger(Process.class);
public abstract class Process {
public void process(String jsonStr) throws Exception{
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer();
ObjectMapper objectMapper=new ObjectMapper();
Map jsonMap=objectMapper.readValue(jsonStr,Map.class);
String vchan_refid= (String) jsonMap.get("vchan_refid");
//封装包头,暂未赋值
byteBuf.writeInt(0); //相机编号为String,他们要的是int,暂时保留
byteBuf.writeInt(0);
byteBuf.writeInt(0);
byteBuf.writeInt(0);
//封装包体
getData(jsonMap,byteBuf);
/**
* 分类处理繁星发来的数据
*
* @param jsonStr 繁星发来的数据
*
* @return 转换成对接方需要的
*/
static BaseModel process(String jsonStr) throws Exception {
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
String eventCate = jsonObject.getString("event_cate");
if (eventCate == null) {
return null;
}
switch (eventCate) {
case "traffic":
return new TrafficProcess().process(jsonObject);
case "behavior":
return new BehaviorProcess().process(jsonObject);
default:
return null;
}
}
public abstract void getData(Map jsonMap,ByteBuf byteBuf) throws Exception;
BaseModel process(JSONObject jsonObject) throws Exception;
}
......@@ -2,4 +2,3 @@
2=2
3=3
4=4
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!