1、临时在RTCM微服务增加推送广西新发展的功能

This commit is contained in:
weidong 2023-12-09 07:26:52 +08:00
parent 1774ea61f6
commit f72dda0ac8
12 changed files with 456 additions and 29 deletions

View File

@ -31,7 +31,7 @@ public class GnssDevice {
private String parentid; private String parentid;
private Integer devicetype; private Integer devicetype;
private String tenantname; private String tenantname;
private Integer project_id = 0; private String project_id;
private Integer group_id = 1; //组参数缓存自动下发 private Integer group_id = 1; //组参数缓存自动下发
private Integer calc_group_id = 1; private Integer calc_group_id = 1;
private Integer fwd_group_id = 0; private Integer fwd_group_id = 0;

View File

@ -0,0 +1,114 @@
package com.imdroid.sideslope.fwd;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.GnssCalcData;
import com.imdroid.secapi.dto.GnssCalcDataMapper;
import com.imdroid.secapi.dto.GnssDevice;
import com.imdroid.secapi.dto.GnssDeviceMapper;
import com.imdroid.sideslope.util.GsonUtil;
import com.imdroid.sideslope.util.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Layton
* @date 2020/12/23 17:14
*/
@Component
@Configuration
@EnableScheduling
public class ForwardGnssTask {
private final Logger logger = LoggerFactory.getLogger(ForwardGnssTask.class);
@Autowired
private GnssDeviceMapper deviceMapper;
@Autowired
private GnssCalcDataMapper gnssDataMapper;
@Autowired
private XFZTcpClient xfzTcpClient;
/**
* 每半小时转发GNSS解算结果
*/
@Scheduled(cron = "0 0/30 * * * ?") // 每30分钟执行一次
private void forwardGnss() {
forwardGnssToXFZ(1);
}
private void forwardGnssToXFZ(int tenantId) {
LocalDateTime nowTime = LocalDateTime.now();
ConcurrentHashMap<String, List<GnssCalcData>> projects = new ConcurrentHashMap<>();
// 转发新发展数据
QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("tenantid", tenantId);
List<GnssDevice> gnssDeviceList = deviceMapper.selectList(queryWrapper);
List<GnssCalcData> records;
for(GnssDevice device:gnssDeviceList){
String projectId = device.getProject_id();
if(projectId == null) continue;
records = projects.get(projectId);
if(records == null){
records = new ArrayList<>();
projects.put(projectId,records);
}
QueryWrapper<GnssCalcData> gnssQueryWrapper = new QueryWrapper<>();
gnssQueryWrapper.eq("deviceid",device.getDeviceid());
gnssQueryWrapper.orderByDesc("createtime");
GnssCalcData record = gnssDataMapper.selectOne(gnssQueryWrapper);
if(record != null && record.getEnabled()){
if(nowTime.isBefore(record.getCreatetime().plusMinutes(40))) {
records.add(record);
}
}
}
// 按项目打包推送
String sendTime = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
for (Map.Entry<String, List<GnssCalcData>> entry: projects.entrySet()){
SendToXFZ(entry.getKey(), entry.getValue(), sendTime);
}
}
void SendToXFZ(String projectId, List<GnssCalcData> records, String sendTime){
if(records.size() == 0) return;
XFZTcpMessage xfzTcpMessage = new XFZTcpMessage();
xfzTcpMessage.setProjectID(projectId);
xfzTcpMessage.setWorkPointID(projectId);
List<XFZTcpMessage.Data> dataList = new ArrayList<>(records.size());
xfzTcpMessage.setData(dataList);
for(GnssCalcData locationRecord: records) {
XFZTcpMessage.Data data = new XFZTcpMessage.Data();
dataList.add(data);
data.setDataTime(sendTime);
data.setDevNum(locationRecord.getDeviceid());
data.setDevtype("GNSS");
// 单位由mm转化为m
data.setX(NumberUtils.scale(locationRecord.getRb562e() * 0.001, 5));
data.setY(NumberUtils.scale(locationRecord.getRb562n() * 0.001, 5));
data.setZ(NumberUtils.scale(locationRecord.getRb562d() * 0.001, 5));
}
String json = GsonUtil.toJson(xfzTcpMessage);
xfzTcpClient.writeAndFlush(json);
logger.info("project " + projectId + ": push calculation result to XFZ");
}
}

View File

@ -0,0 +1,116 @@
package com.imdroid.sideslope.fwd;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
/**
* @author Layton
* @date 2023/2/18 20:35
*/
@Component
public class XFZTcpClient implements ApplicationRunner {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${xfz.server.host}")
private String host;
@Value("${xfz.server.port}")
private int port;
@Value("${xfz.server.data.send}")
private boolean send;
private Bootstrap bootstrap;
private EventLoopGroup group;
private Channel channel;
public void start() {
new Thread(this::connect, "xfz-tcp-client").start();
}
private void init() {
//客户端需要一个事件循环组
group = new NioEventLoopGroup();
//创建客户端启动对象
// bootstrap 可重用, 只需在NettyClient实例化的时候初始化即可.
bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//加入处理器
ch.pipeline().addLast(new XFZTcpMessageHandler(XFZTcpClient.this));
}
});
}
public void connect() {
logger.info("netty client starting");
//启动客户端去连接服务器端
try {
ChannelFuture cf = bootstrap.connect(host, port);
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
//重连交给后端线程执行
future.channel().eventLoop().schedule(() -> {
logger.info("xfz tcp client reconnect");
try {
connect();
} catch (Exception e) {
e.printStackTrace();
}
}, 3000, TimeUnit.MILLISECONDS);
} else {
logger.info("xfz tcp client start success!");
}
}
});
//对通道关闭进行监听
this.channel = cf.channel();
this.channel.closeFuture().sync();
} catch (Exception e) {
logger.error("xfz netty client error:", e);
}
}
public void writeAndFlush(String json) {
if (!send) {
return;
}
String str = "#" + json + "!";
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(str.getBytes(StandardCharsets.UTF_8));
channel.writeAndFlush(buf).addListener(future -> {
if (future.isSuccess()) {
logger.info("send {} to xfz server succeed.", str);
} else {
logger.info("send {} to xfz server failed.", str);
}
});
}
@Override
public void run(ApplicationArguments args) throws Exception {
init();
start();
}
}

View File

@ -0,0 +1,158 @@
package com.imdroid.sideslope.fwd;
import java.util.List;
/**
* @author Layton
* @date 2023/2/19 9:16
*/
public class XFZTcpMessage {
private String ProjectID;
private String WorkPointID;
private String WorkPointLng = "0";
private String WorkPointLat = "0";
private List<Data> data;
public static class Data {
private String DevNum;
private String Devtype;
private String DevLng = "0";
private String DevLat = "0";
private double x;
private double y;
private double z;
private String DataTime;
public Data() {
}
public Data(String devNum, String devtype, String devLng, String devLat, double x, double y, double z, String dataTime) {
DevNum = devNum;
Devtype = devtype;
DevLng = devLng;
DevLat = devLat;
this.x = x;
this.y = y;
this.z = z;
DataTime = dataTime;
}
public String getDevNum() {
return DevNum;
}
public void setDevNum(String devNum) {
DevNum = devNum;
}
public String getDevtype() {
return Devtype;
}
public void setDevtype(String devtype) {
Devtype = devtype;
}
public String getDevLng() {
return DevLng;
}
public void setDevLng(String devLng) {
DevLng = devLng;
}
public String getDevLat() {
return DevLat;
}
public void setDevLat(String devLat) {
DevLat = devLat;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
public String getDataTime() {
return DataTime;
}
public void setDataTime(String dataTime) {
DataTime = dataTime;
}
}
public String getProjectID() {
return ProjectID;
}
public void setProjectID(String projectID) {
ProjectID = projectID;
}
public String getWorkPointID() {
return WorkPointID;
}
public void setWorkPointID(String workPointID) {
WorkPointID = workPointID;
}
public String getWorkPointLng() {
return WorkPointLng;
}
public void setWorkPointLng(String workPointLng) {
WorkPointLng = workPointLng;
}
public String getWorkPointLat() {
return WorkPointLat;
}
public void setWorkPointLat(String workPointLat) {
WorkPointLat = workPointLat;
}
public List<Data> getData() {
return data;
}
public void setData(List<Data> data) {
this.data = data;
}
}

View File

@ -0,0 +1,50 @@
package com.imdroid.sideslope.fwd;
import com.imdroid.sideslope.util.DataTypeUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Layton
* @date 2023/2/18 20:36
*/
public class XFZTcpMessageHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final XFZTcpClient tcpClient;
public XFZTcpMessageHandler(XFZTcpClient tcpClient) {
this.tcpClient = tcpClient;
}
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf buf) throws Exception {
if (logger.isDebugEnabled()) {
byte[] data = new byte[buf.readableBytes()];
buf.getBytes(0, data);
logger.debug("receive gxxfz server message:" + DataTypeUtil.getHexString(data));
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
logger.info("xfz tcp channel active");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
logger.info("xfz tcp channel inactive");
tcpClient.connect();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error("XFZTcpMessageHandler error: {}", cause.toString());
ctx.close();
}
}

View File

@ -29,3 +29,7 @@ app.format.time = HH:mm:ss
app.format.datetime = yyyy-MM-dd HH:mm:ss app.format.datetime = yyyy-MM-dd HH:mm:ss
mybatis-plus.configuration.map-underscore-to-camel-case=false mybatis-plus.configuration.map-underscore-to-camel-case=false
xfz.server.host = 171.106.48.63
xfz.server.port = 52000
xfz.server.data.send = false

View File

@ -4,11 +4,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@Controller @Controller
public class LayuiController extends BasicController{ public class IndexController extends BasicController{
@RequestMapping("/login")
public String login(){
return "/login";
}
@RequestMapping("/") @RequestMapping("/")
public String index0() { public String index0() {
@ -25,9 +21,4 @@ public class LayuiController extends BasicController{
return "/page/device_overview"; return "/page/device_overview";
} }
@RequestMapping("/page/gnss_data_tools")
public String gnssDataTools() {
return "/page/gnss_data_tools";
}
} }

View File

@ -13,6 +13,7 @@ import com.imdroid.beidou.entity.UserMapper;
import com.imdroid.beidou.utils.BCryptPasswordEncoderUtil; import com.imdroid.beidou.utils.BCryptPasswordEncoderUtil;
import com.imdroid.beidou.utils.WXUtils; import com.imdroid.beidou.utils.WXUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -25,8 +26,7 @@ import java.io.IOException;
* *
* @author LiGang * @author LiGang
*/ */
@RequestMapping @Controller
@RestController
public class LoginController { public class LoginController {
@Autowired @Autowired
@ -41,6 +41,11 @@ public class LoginController {
@Autowired @Autowired
private BCryptPasswordEncoderUtil bCryptPasswordEncoderUtil; private BCryptPasswordEncoderUtil bCryptPasswordEncoderUtil;
@RequestMapping("/login")
public String login(){
return "/login";
}
@PostMapping(value = "/do_login") @PostMapping(value = "/do_login")
@ResponseBody @ResponseBody
public HttpResult login(UserLoginVO userLoginVO, HttpServletRequest request, HttpServletResponse response) throws Exception { public HttpResult login(UserLoginVO userLoginVO, HttpServletRequest request, HttpServletResponse response) throws Exception {

View File

@ -45,7 +45,7 @@ CREATE TABLE IF NOT EXISTS `gnssdevices` (
`parentid` varchar(20) DEFAULT NULL, `parentid` varchar(20) DEFAULT NULL,
`devicetype` smallint DEFAULT 0, `devicetype` smallint DEFAULT 0,
`tenantname` varchar(100) NOT NULL, `tenantname` varchar(100) NOT NULL,
`project_id` int NOT NULL DEFAULT 0 COMMENT '项目id', `project_id` varchar(64) DEFAULT NULL COMMENT '项目id',
`group_id` int DEFAULT 1, `group_id` int DEFAULT 1,
`calc_group_id` int DEFAULT 1, `calc_group_id` int DEFAULT 1,
`fwd_group_id` int DEFAULT 0, `fwd_group_id` int DEFAULT 0,

View File

@ -258,12 +258,6 @@
"href": "page/gnss_data_raw", "href": "page/gnss_data_raw",
"icon": "fa fa-database", "icon": "fa fa-database",
"target": "_self" "target": "_self"
},
{
"title": "测试工具",
"href": "page/gnss_data_tools",
"icon": "fa fa-wrench",
"target": "_self"
} }
] ]
}, },

View File

@ -45,7 +45,7 @@
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table> <table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
<script type="text/html" id="currentTableBar"> <script type="text/html" id="currentTableBar">
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="cmd">命令行</a> <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="cmd">详细</a>
</script> </script>
</div> </div>
@ -84,17 +84,12 @@
{field: 'devicetime', title: '设备时间'}, {field: 'devicetime', title: '设备时间'},
{field: 'satelliteinview', title: '可见卫星'}, {field: 'satelliteinview', title: '可见卫星'},
{field: 'satelliteinuse', title: '使用卫星'}, {field: 'satelliteinuse', title: '使用卫星'},
{field: 'd3xxbytes', title: 'D3XX字节数'},
{field: 'b562bytes', title: 'B562字节数'},
{field: 'state', title: '状态',templet: '#stateTrans'}, {field: 'state', title: '状态',templet: '#stateTrans'},
{field: 'warning', title: '告警',templet: '#warningTrans'}, {field: 'warning', title: '告警',templet: '#warningTrans'},
{field: 'location', title: '位置'}, {field: 'location', title: '位置'},
{field: 'voltage', title: '电压'}, {field: 'voltage', title: '电压'},
{field: 'temperature', title: '温度'}, {field: 'temperature', title: '温度'},
{field: 'humidity', title: '湿度'}, {field: 'humidity', title: '湿度'},
{field: 'roll', title: 'roll'},
{field: 'pitch', title: 'pitch'},
{field: 'yaw', title: 'yaw'},
{field: 'rssi', title: '信号'}, {field: 'rssi', title: '信号'},
{title: '操作', toolbar: '#currentTableBar', align: "center"} {title: '操作', toolbar: '#currentTableBar', align: "center"}
]], ]],

View File

@ -38,9 +38,9 @@
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">项目</label> <label class="layui-form-label">项目号</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="number" name="project_id" id="project_id" placeholder="请输入项目编号" value="" class="layui-input"> <input type="text" name="project_id" id="project_id" placeholder="请输入项目编号" value="" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">