Commit 360652c3 by xmh

第二阶段完成

1 parent 339f7375
......@@ -11,10 +11,9 @@
<groupId>com.viontech</groupId>
<artifactId>recv_data_longhua</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>recv_data_longhua</name>
<description>recv_data_longhua</description>
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
......
package com.viontech;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInit extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
\ No newline at end of file
package com.viontech.configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.InputStream;
import java.util.Properties;
/**
* .
*
* @author 谢明辉
* @date 2020/8/31
*/
@Configuration
@Slf4j
public class PropertiesConfiguration {
public static String username;
public static String password;
@Value("${login.username}")
public void setUsername(String username) {
PropertiesConfiguration.username = username;
}
@Value("${login.password}")
public void setPassword(String password) {
PropertiesConfiguration.password = password;
}
@Bean(name = "directionProp")
public Properties directionProp() {
Properties properties = new Properties();
try (InputStream inputStream = PropertiesConfiguration.class.getResourceAsStream("/fxlb.properties")) {
properties.load(inputStream);
} catch (Exception e) {
log.error("读取 fxlb.properties 失败", e);
}
return properties;
}
@Bean(name = "manufactureLogoProp")
public Properties manufactureLogoProp() {
Properties properties = new Properties();
try (InputStream inputStream = PropertiesConfiguration.class.getResourceAsStream("/clpp.properties")) {
properties.load(inputStream);
} catch (Exception e) {
log.error("读取 clpp.properties 失败", e);
}
return properties;
}
@Bean(name = "vehicleColorProp")
public Properties vehicleColorProp() {
Properties properties = new Properties();
try (InputStream inputStream = PropertiesConfiguration.class.getResourceAsStream("/csys.properties")) {
properties.load(inputStream);
} catch (Exception e) {
log.error("读取 csys.properties 失败", e);
}
return properties;
}
@Bean(name = "illegalTypeProp")
public Properties illegalTypeProp() {
Properties properties = new Properties();
try (InputStream inputStream = PropertiesConfiguration.class.getResourceAsStream("/wzlx.properties")) {
properties.load(inputStream);
} catch (Exception e) {
log.error("读取 wzlx.properties 失败", e);
}
return properties;
}
@Bean(name = "eventProp")
public Properties behaviorProp() {
Properties properties = new Properties();
try (InputStream inputStream = PropertiesConfiguration.class.getResourceAsStream("/sjlx.properties")) {
properties.load(inputStream);
} catch (Exception e) {
log.error("读取 sjlx.properties 失败", e);
}
return properties;
}
}
......@@ -2,13 +2,13 @@ package com.viontech.controller;
import com.viontech.model.BaseModel;
import com.viontech.netty.ChannelGroup;
import com.viontech.process.Process;
import com.viontech.process.ProcessService;
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;
import javax.annotation.Resource;
/**
* .
......@@ -20,10 +20,13 @@ import javax.sound.sampled.Line;
@Slf4j
public class DataController {
@Resource
private ProcessService processService;
@PostMapping("/data")
public Object receiveData(@RequestBody String dataStr) throws Exception {
log.info("收到一条繁星发来的消息");
BaseModel data = Process.process(dataStr);
BaseModel data = processService.process(dataStr);
if (data != null) {
ChannelGroup.broadcast(data);
}
......
......@@ -96,7 +96,6 @@ public class BehaviorModel extends BaseModel {
builder.appendFourBytes(faceHeight);
builder.write(reservedField2);
builder.write(picture);
// todo 待crc校验
this.data = builder.resetAndGetFirstSegment();
}
}
......@@ -19,6 +19,7 @@ public class FlowModel extends BaseModel {
private final int[] traffic = new int[16];
private final int[] avgSpeed = new int[16];
private final int[] maxQueueLen = new int[16];
private final int[] occupy = new int[16];
private final int[] avgDistanceBetweenVehicle = new int[16];
private final int[] trafficSupplement = new int[16];
private int serialNum;
......
package com.viontech.netty;
import com.viontech.configuration.PropertiesConfiguration;
import com.viontech.model.BaseModel;
import com.viontech.model.KeepAlive;
import com.viontech.model.LoginData;
......@@ -34,10 +35,9 @@ public class NettyReceiverHandler extends ChannelInboundHandlerAdapter {
LoginData logindata = (LoginData) message;
Long deviceId = logindata.getDeviceId();
System.out.println(logindata.getUsername());
System.out.println(logindata.getPassword());
if (PropertiesConfiguration.username.equals(logindata.getUsername()) &&
PropertiesConfiguration.password.equals(logindata.getPassword())) {
if ("admin".equals(logindata.getUsername()) && "admin".equals(logindata.getPassword())) {
ChannelGroup.registered(deviceId, ctx.channel());
result.setFlag(0L);
} else {
......
......@@ -40,7 +40,6 @@ public class NettyServer implements CommandLineRunner {
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
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.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.viontech.model.BaseModel;
import com.viontech.model.FlowModel;
import com.viontech.utils.DateUtil;
import com.viontech.utils.IntUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
* .
*
* @author 谢明辉
* @date 2020/9/1
*/
@Component
public class FlowProcess implements Process {
@Override
public BaseModel process(JSONObject jsonObject) throws Exception {
FlowModel model = new FlowModel();
model.setTimeDuring(120);
String eventDtStr = jsonObject.getString("event_dt");
if (eventDtStr != null) {
long time = DateUtil.parse(DateUtil.FORMAT_FULL, eventDtStr).getTime();
model.setTime((int) (time / 1000));
}
JSONObject eventData = jsonObject.getJSONObject("event_data");
// 序列号
model.setSerialNum(IntUtils.next());
// 机动车大车
JSONArray bigVehicle = eventData.getJSONArray("big_vehicle");
// 机动车小车
JSONArray smallVehicle = eventData.getJSONArray("small_vehicle");
// 非机动车
JSONArray xcycle = eventData.getJSONArray("xcycle");
// 行人
JSONArray pedestrian = eventData.getJSONArray("pedestrian");
HashMap<Integer, Integer> lane_index_map = new HashMap<>();
int count = cal(model, bigVehicle, lane_index_map, 0, 0);
count = cal(model, smallVehicle, lane_index_map, count, 1);
count = cal(model, xcycle, lane_index_map, count, 2);
cal(model, pedestrian, lane_index_map, count, 3);
return model;
}
/**
* @param data 数据
* @param lane_index_map 车道和index的map
* @param count maximum is 16
* @param type 0->机动车大车 1->机动车小车 2->非机动车 3->行人
*
* @return 下一个插入的index位置
*/
private int cal(FlowModel model, JSONArray data, HashMap<Integer, Integer> lane_index_map, int count, int type) {
if (data == null) {
return count;
}
for (int i = 0; i < data.size(); i++) {
if (count >= 16) {
break;
}
JSONObject item = data.getJSONObject(i);
Integer road = item.getInteger("road");
Integer index = lane_index_map.get(road);
if (index == null) {
int laneNoAndType = type == 0 || type == 1 ? (road << 16) | 0x00000001 : (road << 16) | 0x00000002;
model.getLaneNoAndType()[count] = laneNoAndType;
Integer traffic = item.getInteger("sample_num");
model.getTraffic()[count] = traffic & 0x0000FFFF;
if (type == 0) {
model.getTraffic()[count] = (traffic << 16) | model.getTraffic()[count];
} else if (type == 1 || type == 3) {
model.getTrafficSupplement()[count] = traffic & 0x0000FFFF;
} else if (type == 2) {
model.getTrafficSupplement()[count] = traffic << 16;
}
Float speed = item.getFloat("velocity");
model.getAvgSpeed()[count] = speed.intValue();
Integer queueLength = item.getInteger("queue_length");
model.getMaxQueueLen()[count] = queueLength;
Float occupy = item.getFloat("occupy");
model.getOccupy()[count] = (int) (occupy * 100);
Float distance = item.getFloat("distance");
model.getAvgDistanceBetweenVehicle()[count] = distance.intValue();
count++;
} else {
int laneType = model.getLaneNoAndType()[index] & 0x0000FFFF;
Integer traffic = item.getInteger("sample_num");
if (type == 1 || type == 3) {
model.getTrafficSupplement()[index] = model.getTrafficSupplement()[index] + (traffic & 0x0000FFFF);
model.getTraffic()[index] = model.getTraffic()[index] + (traffic & 0x0000FFFF);
} else if (laneType == 0x00000001 && type == 0) {
model.getTraffic()[index] = model.getTraffic()[index] + (traffic << 16) + (traffic & 0x0000FFFF);
} else if (laneType == 0x00000002 && type == 2) {
model.getTrafficSupplement()[index] = model.getTrafficSupplement()[index] + (traffic << 16);
model.getTraffic()[index] = model.getTraffic()[index] + (traffic & 0x0000FFFF);
}
}
}
return count;
}
}
......@@ -2,9 +2,13 @@ package com.viontech.process;
import com.alibaba.fastjson.JSONObject;
import com.viontech.model.BaseModel;
import com.viontech.utils.DateUtil;
import com.viontech.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
/**
* .
*
......@@ -12,30 +16,27 @@ import org.slf4j.LoggerFactory;
* @date 2020/8/20
*/
public interface Process {
Logger log = LoggerFactory.getLogger(Process.class);
Logger LOGGER = LoggerFactory.getLogger(Process.class);
/**
* 分类处理繁星发来的数据
*
* @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;
static String getFileFTPPath(Date date, String deviceId, String fileName) {
String yyyyMMdd = DateUtil.format("yyyyMMdd", date);
String ip;
try {
ip = Utils.INSTANCE.getIpAddress();
} catch (Exception e) {
ip = "null";
LOGGER.error("", e);
}
switch (eventCate) {
case "traffic":
return new TrafficProcess().process(jsonObject);
case "behavior":
return new BehaviorProcess().process(jsonObject);
default:
return null;
return "/video/" + yyyyMMdd + "/" + ip + "/" + deviceId + "/" + fileName;
}
static byte[] downloadFile(String url) {
return new byte[]{};
}
BaseModel process(JSONObject jsonObject) throws Exception;
}
package com.viontech.process;
import com.alibaba.fastjson.JSONObject;
import com.viontech.model.BaseModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* .
*
* @author 谢明辉
* @date 2020/8/31
*/
@Service
@Slf4j
public class ProcessService {
@Resource
private Process behaviorProcess;
@Resource
private Process trafficProcess;
@Resource
private Process flowProcess;
/**
* 分类处理繁星发来的数据
*
* @param jsonStr 繁星发来的数据
*
* @return 转换成对接方需要的
*/
public BaseModel process(String jsonStr) throws Exception {
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
String eventCate = jsonObject.getString("event_cate");
String eventType = jsonObject.getString("event_type");
if (eventCate == null) {
return null;
}
switch (eventCate) {
case "traffic":
if ("vehicle".equals(eventType)) {
return trafficProcess.process(jsonObject);
} else if ("tflow".equals(eventType)) {
return flowProcess.process(jsonObject);
}
return null;
case "behavior":
return behaviorProcess.process(jsonObject);
default:
return null;
}
}
}
......@@ -2,28 +2,49 @@ package com.viontech.process;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.viontech.ftp.FTPClientHelper;
import com.viontech.model.BaseModel;
import com.viontech.model.TrafficModel;
import com.viontech.utils.DateUtil;
import com.viontech.utils.IntUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.Base64;
import java.util.Date;
import java.util.Optional;
import java.util.Properties;
@Component
public class TrafficProcess implements Process {
@Resource
private Properties manufactureLogoProp;
@Resource
private Properties vehicleColorProp;
@Resource
private Properties illegalTypeProp;
@Resource
private Properties eventProp;
@Resource
private FTPClientHelper ftpClientHelper;
@Override
public BaseModel process(JSONObject jsonObject) throws Exception {
TrafficModel model = new TrafficModel();
JSONObject eventData = jsonObject.getJSONObject("event_data");
if (eventData != null) {
JSONArray video = jsonObject.getJSONArray("video");
JSONObject vehicle = eventData.getJSONObject("vehicle");
JSONObject lane = eventData.getJSONObject("lane");
JSONObject location = eventData.getJSONObject("location");
JSONObject illegal = eventData.getJSONObject("illegal");
JSONArray pics = eventData.getJSONArray("pics");
JSONArray pics = jsonObject.getJSONArray("pics");
model.setSerialNum(IntUtils.next());
String deviceSerialnum = jsonObject.getString("vchan_refid");
// ------------------- 车速 ------------------
Float speedF = eventData.getFloat("speed");
model.setSpeed(Optional.ofNullable(speedF).orElse(0F).intValue());
......@@ -34,23 +55,45 @@ public class TrafficProcess implements Process {
}
// ------------------------ 车辆信息 车牌信息 --------------
String eventTimeStr = jsonObject.getString("event_dt");
long eventTime = DateUtil.parse(DateUtil.FORMAT_FULL, eventTimeStr).getTime();
model.setDiscernTime(BaseModel.toInt(eventTime / 1000));
model.setDiscernMillisecondTime(BaseModel.toInt(eventTime % 1000));
Date eventTime = DateUtil.parse(DateUtil.FORMAT_FULL, eventTimeStr);
long eventTimeL = eventTime.getTime();
model.setDiscernTime(BaseModel.toInt(eventTimeL / 1000));
model.setDiscernMillisecondTime(BaseModel.toInt(eventTimeL % 1000));
vehicle(model, vehicle);
// ------------------------ 图片 --------------
pic(model, pics);
pic(model, pics, eventTime, deviceSerialnum);
// ---------------- 车速,方向,地点 --------------
location(model, location);
// ------------------ 违章 --------------------
illegal(model, illegal);
// ------------------ 录像 ---------------------
video(model, video, deviceSerialnum, eventTime);
return model;
} else {
return null;
}
}
private void pic(TrafficModel model, JSONArray pics) {
private void video(TrafficModel model, JSONArray video, String deviceSerialnum, Date eventTime) {
if (video != null && video.size() > 0) {
JSONObject item = video.getJSONObject(0);
String src_url = item.getString("src_url");
if (src_url == null || "".equals(src_url)) {
return;
}
// todo 下载录像
byte[] bytes = Process.downloadFile(src_url);
String filename = item.getString("ofilename");
String filePath = Process.getFileFTPPath(eventTime, deviceSerialnum, filename);
// ftpClientHelper.storeFile(filePath, bytes);
byte[] videoPathBytes = filePath.getBytes(StandardCharsets.UTF_8);
System.arraycopy(videoPathBytes, 0, model.getVideoPath(), 0, videoPathBytes.length);
}
}
private void pic(TrafficModel model, JSONArray pics, Date eventTime, String deviceSerialnum) {
if (pics != null && pics.size() > 0) {
// --------------- 图片2 ----------
if (pics.size() > 1) {
......@@ -76,7 +119,10 @@ public class TrafficProcess implements Process {
byte[] pic1Bytes = Base64.getDecoder().decode(picBase64);
model.setPicture1(pic1Bytes);
model.setFirstPictureSize(pic1Bytes.length);
byte[] pic1UrlBytes = pic1.getString("src_url").getBytes();
String filename = pic1.getString("ofilename");
String fileFTPPath = Process.getFileFTPPath(eventTime, deviceSerialnum, filename);
ftpClientHelper.storeFile(fileFTPPath, pic1Bytes);
byte[] pic1UrlBytes = fileFTPPath.getBytes();
System.arraycopy(pic1UrlBytes, 0, model.getPicturePath(), 0, Math.min(128, pic1UrlBytes.length));
}
}
......@@ -117,15 +163,19 @@ public class TrafficProcess implements Process {
}
JSONObject color = body.getJSONObject("color");
if (color != null) {
// todo 车身颜色待转换
// 车身颜色
String colorCode = color.getString("code");
model.setColor(0);
String property = vehicleColorProp.getProperty(colorCode, "0");
int integer = Integer.parseInt(property);
model.setColor(integer);
}
JSONObject logo = body.getJSONObject("logo");
if (logo != null) {
String code = logo.getString("code");
// todo 车辆品牌待转换
model.setManufacturerLogo(Integer.parseInt(code));
// 车辆品牌
String property = manufactureLogoProp.getProperty(code, "0");
int integer = Integer.parseInt(property);
model.setManufacturerLogo(integer);
}
}
......@@ -137,23 +187,22 @@ public class TrafficProcess implements Process {
JSONObject driveDirection = location.getJSONObject("drive_direction");
if (driveDirection != null) {
Integer directionCode = driveDirection.getInteger("code");
// todo 方向待转换
// 方向不用转换
model.setDirection(directionCode);
}
String locationName = location.getString("name");
byte[] locationNameBytes = locationName.getBytes(StandardCharsets.UTF_8);
System.arraycopy(locationNameBytes, 0, model.getRouteLocation(), 0, Math.min(locationNameBytes.length, 32));
// todo 录像路径
byte[] videoPathBytes = "testVideoPath".getBytes(StandardCharsets.UTF_8);
System.arraycopy(videoPathBytes, 0, model.getVideoPath(), 0, videoPathBytes.length);
}
}
private void illegal(TrafficModel model, JSONObject illegal) throws ParseException {
if (illegal != null && illegal.getInteger("state") == 1) {
String illegalCode = illegal.getString("code");
// todo 需要交通违法类型转换 illegalCode --> illegalType
model.setIllegalType(0);
//需要交通违法类型转换 illegalCode --> illegalType
String property = illegalTypeProp.getProperty(illegalCode, "0");
int integer = Integer.parseInt(property);
model.setIllegalType(integer);
JSONObject detail = illegal.getJSONObject("detail");
if (detail != null) {
Float limitSpeed = detail.getFloat("limit_speed");
......
package com.viontech.utils;
import java.util.concurrent.atomic.AtomicInteger;
/**
* .
*
* @author 谢明辉
* @date 2020/8/26
*/
public class IntUtils {
private static final AtomicInteger atomicInteger = new AtomicInteger();
public static synchronized Integer next() {
int num = atomicInteger.getAndIncrement();
if (num == Integer.MAX_VALUE) {
atomicInteger.set(0);
}
return num;
}
}
package com.viontech.utils;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
/**
* .
*
* @author 谢明辉
* @date 2020/9/7
*/
public enum Utils {
/***/
INSTANCE;
public String getIpAddress() throws SocketException {
Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
InetAddress ip;
while (allNetInterfaces.hasMoreElements()) {
NetworkInterface netInterface = allNetInterfaces.nextElement();
if (!netInterface.isLoopback() && !netInterface.isVirtual() && netInterface.isUp()) {
Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
ip = addresses.nextElement();
if (ip instanceof Inet4Address) {
return ip.getHostAddress();
}
}
}
}
return null;
}
}
netty.port=30001
ftp.host=127.0.0.1
ftp.port=10000
ftp.username=username
ftp.password=password
\ No newline at end of file
ftp.host=190.204.20.30
ftp.port=21
ftp.username=myusername
ftp.password=hc123456
login.username=admin
login.password=admin
\ 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!