1、推送功能单独一个微服务

2、增加数据推送相关界面,包括推送代理信息、推送记录
3、取消推送参数组设置,设备的推送参数选择推送代理
This commit is contained in:
weidong 2024-01-07 10:30:13 +08:00
parent 7c2ab42755
commit cbf58af460
28 changed files with 400 additions and 770 deletions

View File

@ -28,4 +28,6 @@ public class FwdRecord {
LocalDateTime starttime;
LocalDateTime endtime;
Short state;
private String fwd_group_id;
}

View File

@ -38,7 +38,7 @@ public class GnssDevice {
private String project_id;
private Integer group_id = 1; //组参数缓存自动下发
private Integer calc_group_id = 1;
private Integer fwd_group_id = 0;
private String fwd_group_id;
private Boolean syn; //组参数是否同步
private String pictures;

View File

@ -1,24 +1,22 @@
package com.imdroid.secapi.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName(value = "gnssgroupfwd")
public class GnssGroupFwd {
public static final short FWD_TYPE_NONE = 0; //不转发
public static final short FWD_TYPE_CALC = 1; //按模板转发解算结果
public static final short FWD_TYPE_RAW = 2; //转发原始数据D331/D341
public static final short FWD_TYPE_NTRIP = 3; //按ntrip协议转发
public static final String FWD_TYPE_NONE = "不推送"; //不转发
@TableId(value = "id", type = IdType.AUTO)
Integer id;
String name;
String description;
Short type1;
String addr1;
Integer port1;
String template1;
Short type2;
String addr2;
Integer port2;
String template2;
LocalDateTime updatetime;
Integer device_num;
Integer fwd_device_num;
Boolean result;
}

View File

@ -0,0 +1,23 @@
package com.imdroid.beidou_fwd;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
/**
* @author Layton
* @date 2023/1/31 20:33
*/
@SpringBootApplication(scanBasePackages = {"com.imdroid"})
@MapperScan({"com.imdroid.secapi","com.imdroid.beidou.entity"})
@ComponentScan({"com.imdroid.*"})
@EntityScan({"com.imdroid.*"})
public class BeidouFwdApp {
public static void main(String[] args) {
SpringApplication.run(BeidouFwdApp.class, args);
}
}

View File

@ -17,13 +17,11 @@ public class TCPClient {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//@Value("${xfz.server.host}")
private String host="171.106.48.63";
private String host;
//@Value("${xfz.server.port}")
private int port=52000;
private int port;
//@Value("${xfz.server.data.send}")
private boolean send=true;
private Bootstrap bootstrap;
private EventLoopGroup group;
@ -33,7 +31,9 @@ public class TCPClient {
new Thread(this::connect, "xfz-tcp-client").start();
}
private void init() {
public void init(String dest_addr, int dest_port) {
host = dest_addr;
port = dest_port;
//客户端需要一个事件循环组
group = new NioEventLoopGroup();
//创建客户端启动对象
@ -83,9 +83,6 @@ public class TCPClient {
public void writeAndFlush(String json) {
if (!send) {
return;
}
String str = "#" + json + "!";
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(str.getBytes(StandardCharsets.UTF_8));

View File

@ -0,0 +1,44 @@
package com.imdroid.beidou_fwd.task;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.GnssGroupFwd;
import com.imdroid.secapi.dto.GnssGroupFwdMapper;
import java.time.LocalDateTime;
public class Forwarder {
String name;
String description;
GnssGroupFwdMapper fwdMapper;
void init(String name, String desc, GnssGroupFwdMapper fwdMapper){
this.name = name;
this.description = desc;
this.fwdMapper = fwdMapper;
QueryWrapper<GnssGroupFwd> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name",name);
GnssGroupFwd gnssGroupFwd = fwdMapper.selectOne(queryWrapper);
if(gnssGroupFwd == null){
gnssGroupFwd = new GnssGroupFwd();
gnssGroupFwd.setName(name);
gnssGroupFwd.setDescription(description);
gnssGroupFwd.setDevice_num(0);
fwdMapper.insert(gnssGroupFwd);
}
else{
gnssGroupFwd.setDescription(description);
fwdMapper.updateById(gnssGroupFwd);
}
}
void updateFwd(int fwd_num, boolean isFwdOK){
QueryWrapper<GnssGroupFwd> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name",name);
GnssGroupFwd gnssGroupFwd = fwdMapper.selectOne(queryWrapper);
if(gnssGroupFwd != null){
gnssGroupFwd.setFwd_device_num(fwd_num);
gnssGroupFwd.setResult(isFwdOK);
gnssGroupFwd.setUpdatetime(LocalDateTime.now());
fwdMapper.updateById(gnssGroupFwd);
}
}
}

View File

@ -1,17 +1,21 @@
package com.imdroid.sideslope.fwd;
package com.imdroid.beidou_fwd.task;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.*;
import com.imdroid.beidou_fwd.entity.XFZData;
import com.imdroid.beidou_fwd.service.TCPClient;
import com.imdroid.common.util.GsonUtil;
import com.imdroid.common.util.NumberUtils;
import com.imdroid.secapi.dto.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@ -19,29 +23,37 @@ 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 {
public class GXXfzForwarder extends Forwarder{
private final Logger logger = LoggerFactory.getLogger(GXXfzForwarder.class);
private final Logger logger = LoggerFactory.getLogger(ForwardGnssTask.class);
static final String forwarderName = "广西新发展";
@Value("${xfz.server.host}")
private String host;
@Value("${xfz.server.port}")
private int port;
@Autowired
private GnssDeviceMapper deviceMapper;
@Autowired
private GnssCalcDataMapper gnssDataMapper;
@Autowired
private XFZTcpClient xfzTcpClient;
private TCPClient xfzTcpClient;
@Autowired
private FwdRecordMapper fwdRecordsMapper;
final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
private GnssGroupFwdMapper fwdMapper;
@PostConstruct
void registerMe(){
init(forwarderName, "TCP "+host+":"+port, fwdMapper);
}
/**
* 每半小时转发GNSS解算结果
*/
@ -49,15 +61,20 @@ public class ForwardGnssTask {
private void forwardGnss() {
// 1.按项目检索最近半小时的解算结果记录推送Enable为true的记录
// 2.如果某终端最近半小时没有数据则记录本次时间为待补传时间
forwardGnssToXFZ(1);
if(xfzTcpClient == null){
xfzTcpClient = new TCPClient();
xfzTcpClient.init(host, port);
xfzTcpClient.start();
}
forwardGnssToXFZ(forwarderName);
}
//@Scheduled(cron = "0 40 * * * ?") // 每小时的40分钟执行一次
@Scheduled(cron = "0 0/20 * * * ?") // 每20分钟执行一次
@Scheduled(cron = "0 40 * * * ?") // 每小时的40分钟执行一次
//@Scheduled(cron = "0 0/20 * * * ?") // 每20分钟执行一次
private void forwardHistoryGnss() {
// 1.从转发记录表里检索待补传记录时间表含设备Id时间段
QueryWrapper<FwdRecord> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("tenantid",1);
queryWrapper.eq("fwd_group_id",forwarderName);
queryWrapper.eq("state",FwdRecord.STATE_UPLOAD_DONE);
List<FwdRecord> fwdRecordsList = fwdRecordsMapper.selectList(queryWrapper);
// 2.检索这个这个时间段的解算结果如果有数据则单个终端转发标志记录为已补传
@ -76,7 +93,7 @@ public class ForwardGnssTask {
}
}
private void forwardGnssToXFZ(int tenantId) {
private void forwardGnssToXFZ(String fwdGroupId) {
LocalDateTime nowTime = LocalDateTime.now();
ConcurrentHashMap<String, List<GnssCalcData>> projects = new ConcurrentHashMap<>();
@ -85,7 +102,7 @@ public class ForwardGnssTask {
String sendAfterTime = nowTime.minusMinutes(30).format(formatter);
QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("tenantid", tenantId);
queryWrapper.eq("fwd_group_id", fwdGroupId);
List<GnssDevice> gnssDeviceList = deviceMapper.selectList(queryWrapper);
List<GnssCalcData> recordsToSend;
for(GnssDevice device:gnssDeviceList){
@ -111,33 +128,42 @@ public class ForwardGnssTask {
}
// 按项目打包推送
int totalSendNum = 0;
for (Map.Entry<String, List<GnssCalcData>> entry: projects.entrySet()){
SendToXFZ(entry.getKey(), entry.getValue());
// 记录推送
FwdRecord fwdRecord = new FwdRecord();
fwdRecord.setProject_id(entry.getKey());
fwdRecord.setTenantid(1);
fwdRecord.setDevicenum((short) entry.getValue().size());
fwdRecord.setStarttime(nowTime);
fwdRecord.setState(FwdRecord.STATE_FWD_DONE);
fwdRecordsMapper.insert(fwdRecord);
int sendNum = SendToXFZ(entry.getKey(), entry.getValue());
if(sendNum > 0) {
totalSendNum += sendNum;
// 记录推送
FwdRecord fwdRecord = new FwdRecord();
fwdRecord.setProject_id(entry.getKey());
fwdRecord.setTenantid(1);
fwdRecord.setDevicenum((short) entry.getValue().size());
fwdRecord.setStarttime(nowTime);
fwdRecord.setState(FwdRecord.STATE_FWD_DONE);
fwdRecordsMapper.insert(fwdRecord);
}
}
// 更新推送信息
if(totalSendNum>0) updateFwd(totalSendNum, true);
}
void SendToXFZ(String projectId, List<GnssCalcData> records){
if(records.size() == 0) return;
int SendToXFZ(String projectId, List<GnssCalcData> records){
int sendNum = 0;
if(records.size() == 0) return 0;
XFZTcpMessage xfzTcpMessage = new XFZTcpMessage();
XFZData xfzTcpMessage = new XFZData();
xfzTcpMessage.setProjectID(projectId);
xfzTcpMessage.setWorkPointID(projectId);
List<XFZTcpMessage.Data> dataList = new ArrayList<>(records.size());
List<XFZData.Data> dataList = new ArrayList<>(records.size());
xfzTcpMessage.setData(dataList);
for(GnssCalcData locationRecord: records) {
if(!locationRecord.getEnabled()) continue;
XFZTcpMessage.Data data = new XFZTcpMessage.Data();
XFZData.Data data = new XFZData.Data();
dataList.add(data);
data.setDataTime(locationRecord.getCreatetime().format(dateFormatter));
data.setDevNum(locationRecord.getDeviceid());
@ -146,11 +172,13 @@ public class ForwardGnssTask {
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));
sendNum++;
}
String json = GsonUtil.toJson(xfzTcpMessage);
xfzTcpClient.writeAndFlush(json);
logger.info("project " + projectId + ": push calculation result to XFZ");
logger.info(json);
return sendNum;
}
void BatchToXFZ(String projectId, List<GnssCalcData> records){
@ -173,27 +201,4 @@ public class ForwardGnssTask {
}
void SendOneToXFZ(String projectId, GnssCalcData calcData, String sendTime){
XFZTcpMessage xfzTcpMessage = new XFZTcpMessage();
xfzTcpMessage.setProjectID(projectId);
xfzTcpMessage.setWorkPointID(projectId);
List<XFZTcpMessage.Data> dataList = new ArrayList<>();
xfzTcpMessage.setData(dataList);
XFZTcpMessage.Data data = new XFZTcpMessage.Data();
dataList.add(data);
data.setDataTime(sendTime);
data.setDevNum(calcData.getDeviceid());
data.setDevtype("GNSS");
// 单位由mm转化为m
data.setX(NumberUtils.scale(calcData.getRb562e() * 0.001, 5));
data.setY(NumberUtils.scale(calcData.getRb562n() * 0.001, 5));
data.setZ(NumberUtils.scale(calcData.getRb562d() * 0.001, 5));
String json = GsonUtil.toJson(xfzTcpMessage);
xfzTcpClient.writeAndFlush(json);
logger.info("project " + projectId + ": push one calculation result to XFZ");
logger.info(json);
}
}

View File

@ -1,11 +0,0 @@
package com.imdroid.beidou_fwd.task;
public class ThirdPartyForwarder {
public void forward(){
// 1.根据模板查询转发组列表
// 2.根据转发组号查询转发地址协议设备列表
// 3.查询设备最后一条解算记录
// 4.按项目打包解算记录
// 5.向目的地址按模板推送解算记录
}
}

View File

@ -0,0 +1,27 @@
server.port=9906
server.servlet.context-path=/gnss
spring.application.name=fwd-gnss
spring.application.build=20240106
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = none
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
spring.datasource.url = jdbc:mysql://localhost:3306/beidou?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
spring.datasource.username = admin
spring.datasource.password = DBMgr_2022
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
spring.jackson.dateFormat = yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone = GMT+8
app.format.date = yyyy-MM-dd
app.format.time = HH:mm:ss
app.format.datetime = yyyy-MM-dd HH:mm:ss
mybatis-plus.configuration.map-underscore-to-camel-case=false
#xfz.server.host = 171.106.48.63
#xfz.server.port = 52000
xfz.server.host = 115.236.153.174
xfz.server.port = 31035

View File

@ -3,6 +3,7 @@ package com.imdroid.sideslope.calc;
import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.secapi.dto.FwdRecord;
import com.imdroid.secapi.dto.FwdRecordMapper;
import com.imdroid.secapi.dto.GnssGroupFwd;
import com.imdroid.secapi.dto.GnssStatus;
import com.imdroid.sideslope.message.BaseMessage;
import com.imdroid.sideslope.message.D341LocationMessage;
@ -100,6 +101,8 @@ public class MultiLineGNSSCalcService {
void createFwdReord(D342LocationMessage d342Message){
String deviceId = d342Message.getId();
// 查找这个设备是否有项目号
if(d342Message.getFwdId()==null || d342Message.getFwdId().equals(GnssGroupFwd.FWD_TYPE_NONE)) return;
FwdRecord fwdRecord = new FwdRecord();
fwdRecord.setDeviceid(deviceId);
fwdRecord.setTenantid(d342Message.getTenantId());
@ -107,6 +110,7 @@ public class MultiLineGNSSCalcService {
fwdRecord.setState(FwdRecord.STATE_UPLOADING);
fwdRecord.setStarttime(d342Message.getOriginalTime());
fwdRecord.setDevicenum((short) 1);
fwdRecord.setFwd_group_id(d342Message.getFwdId());
fwdRecordMap.put(deviceId, fwdRecord);
}

View File

@ -30,6 +30,7 @@ public class D342LocationMessageExecutor implements Executor<D342LocationMessage
if(device == null) return null;
message.setTenantId(device.getTenantId());
message.setProjectId(device.getProjectId());
message.setFwdId(device.getFwdId());
ThreadManager.getFixedThreadPool().submit(() -> {
gnssCalcService.calc(message);

View File

@ -1,115 +0,0 @@
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.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="171.106.48.63";
//@Value("${xfz.server.port}")
private int port=52000;
//@Value("${xfz.server.data.send}")
private boolean send=true;
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

@ -1,158 +0,0 @@
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

@ -1,50 +0,0 @@
package com.imdroid.sideslope.fwd;
import com.imdroid.common.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

@ -18,6 +18,7 @@ public class D342LocationMessage extends BaseMessage {
LocalDateTime originalTime; //补传前记录的时间
List<BaseMessage> messageList = new ArrayList<>();
String projectId;
String fwdId;
@Override
public void decodeBody(ByteBuf src) {
// d3 51 length(2048+6) device_id(4bytes) seq(2bytes) data

View File

@ -35,6 +35,7 @@ public class DbDeviceServiceImpl implements DeviceService {
device.setProjectId(gnssDevice.getProject_id());
device.setCalcGroupId(gnssDevice.getCalc_group_id());
device.setOpMode(gnssDevice.getOpmode());
device.setFwdId(gnssDevice.getFwd_group_id());
return device;
}
@ -53,6 +54,7 @@ public class DbDeviceServiceImpl implements DeviceService {
device.setProjectId(gnssDevice.getProject_id());
device.setCalcGroupId(gnssDevice.getCalc_group_id());
device.setOpMode(gnssDevice.getOpmode());
device.setFwdId(gnssDevice.getFwd_group_id());
deviceList.add(device);
}
return deviceList;

View File

@ -28,6 +28,7 @@ public class Device {
private String parentId;
private String projectId;
private String fwdId;
private Integer deviceType;

View File

@ -205,7 +205,7 @@ public class GnssDeviceController extends BasicController{
}
}
void updateFwdGroupAssociatedNum(int groupId) {
void updateFwdGroupAssociatedNum(String groupId) {
// 更新推送参数组
QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("fwd_group_id", groupId);

View File

@ -0,0 +1,57 @@
package com.imdroid.beidou.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imdroid.secapi.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class GnssFwdController {
@Autowired
GnssGroupFwdMapper gnssGroupFwdMapper;
@Autowired
FwdRecordMapper fwdRecordMapper;
/********* 推送页面 *********/
@RequestMapping("/page/fwd_agents")
public String fwdAgents() {
return "/page/fwd_agents";
}
@RequestMapping("/page/fwd_records")
public String fwdRecords() {
return "/page/fwd_records";
}
/********* 基本参数组 *********/
@RequestMapping("/fwd/agents")
@ResponseBody
public JSONObject listAgents(int page, int limit) {
Page<GnssGroupFwd> pageable = new Page<>(page, limit);
IPage<GnssGroupFwd> cs = gnssGroupFwdMapper.selectPage(pageable, null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0);
jsonObject.put("msg", "");
jsonObject.put("count", cs.getTotal());
jsonObject.put("data", cs.getRecords());
return jsonObject;
}
@RequestMapping("/fwd/records")
@ResponseBody
public JSONObject listRecords(int page, int limit) {
Page<FwdRecord> pageable = new Page<>(page, limit);
IPage<FwdRecord> cs = fwdRecordMapper.selectPage(pageable, null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0);
jsonObject.put("msg", "");
jsonObject.put("count", cs.getTotal());
jsonObject.put("data", cs.getRecords());
return jsonObject;
}
}

View File

@ -15,8 +15,6 @@ public class GnssGroupController {
GnssGroupMapper gnssGroupMapper;
@Autowired
GnssGroupCalcMapper gnssGroupCalcMapper;
@Autowired
GnssGroupFwdMapper gnssGroupFwdMapper;
@Autowired
GnssDeviceMapper deviceMapper;
@ -32,11 +30,6 @@ public class GnssGroupController {
return "/page/table/gnss_add_group_calc";
}
@RequestMapping("/page/table/gnss_add_group_fwd")
public String gnssAddPushGroup() {
return "/page/table/gnss_add_group_fwd";
}
@RequestMapping("/page/gnss_group_cfg")
public String gnssGroupCfg() {
return "/page/gnss_group_cfg";
@ -145,50 +138,4 @@ public class GnssGroupController {
} else return HttpResult.ok();
}
/********* 转发参数组 *********/
@RequestMapping("/gnss/group/list_fwd")
@ResponseBody
public JSONObject listFwd(int page, int limit) {
Page<GnssGroupFwd> pageable = new Page<>(page, limit);
IPage<GnssGroupFwd> cs = gnssGroupFwdMapper.selectPage(pageable, null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0);
jsonObject.put("msg", "");
jsonObject.put("count", cs.getTotal());
jsonObject.put("data", cs.getRecords());
return jsonObject;
}
@PostMapping("/gnss/group/update_fwd")
@ResponseBody
public String updateFwd(@RequestBody JSONObject object) {
int num = 0;
GnssGroupFwd group = JSONObject.toJavaObject(object,GnssGroupFwd.class);
if(null != gnssGroupFwdMapper.selectById(group.getId())) {
num = gnssGroupFwdMapper.updateById(group);
}
else{
num = gnssGroupFwdMapper.insert(group);
}
if (num == 0) {
return HttpResult.failed();
} else return HttpResult.ok();
}
@PostMapping("/gnss/group/delete_fwd")
@ResponseBody
public String deleteFwd(@RequestParam int del_id) {
GnssGroupFwd group = gnssGroupFwdMapper.selectById(del_id);
if(group == null) return HttpResult.failed();
if(group.getDevice_num() >0){
return HttpResult.result(HttpResult.HTTP_RSP_FAILED,"this group is in used");
}
int num = gnssGroupFwdMapper.deleteById(del_id);
if (num == 0) {
return HttpResult.failed();
} else return HttpResult.ok();
}
}

View File

@ -49,7 +49,7 @@ CREATE TABLE IF NOT EXISTS `gnssdevices` (
`project_id` varchar(64) DEFAULT NULL COMMENT '项目id',
`group_id` int DEFAULT 1,
`calc_group_id` int DEFAULT 1,
`fwd_group_id` int DEFAULT 0,
`fwd_group_id` varchar(64) DEFAULT NULL,
`syn` bit(1) DEFAULT 0 COMMENT '是否已同步',
`pictures` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
@ -80,19 +80,13 @@ CREATE TABLE IF NOT EXISTS `gnssgroupcalc` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `gnssgroupfwd` (
`id` int NOT NULL,
`description` varchar(64) DEFAULT NULL,
`type1` smallint DEFAULT 0,
`protocol1` smallint DEFAULT 0,
`addr1` varchar(128) DEFAULT NULL,
`port1` int DEFAULT 0,
`template1` varchar(64) DEFAULT NULL,
`type2` smallint DEFAULT 0,
`protocol2` smallint DEFAULT 0,
`addr2` varchar(128) DEFAULT NULL,
`port2` int DEFAULT 0,
`template2` varchar(64) DEFAULT NULL,
`id` int AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`description` varchar(256) DEFAULT NULL,
`updatetime` datetime DEFAULT NULL,
`device_num` int DEFAULT 0,
`fwd_device_num` int DEFAULT 0,
`result` bit(1) DEFAULT 0 COMMENT '推送是否成功',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@ -245,9 +239,10 @@ CREATE TABLE IF NOT EXISTS `fwdrecords` (
`tenantid` int NOT NULL,
`project_id` varchar(64) DEFAULT NULL COMMENT '项目id',
`devicenum` smallint NOT NULL,
`deviceid` varchar(20) NOT NULL,
`deviceid` varchar(20) DEFAULT NULL,
`starttime` datetime DEFAULT NULL,
`endtime` datetime DEFAULT NULL,
`state` smallint DEFAULT 0,
`fwd_group_id` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -104,6 +104,26 @@
"target": "_self"
}
]
},
{
"title": "数据推送",
"href": "",
"icon": "fa fa-send-o",
"target": "_self",
"child": [
{
"title": "转发代理",
"href": "page/fwd_agents",
"icon": "fa fa-minus",
"target": "_self"
},
{
"title": "推送记录",
"href": "page/fwd_records",
"icon": "fa fa-minus",
"target": "_self"
}
]
}
]
},

View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>转发代理</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="../lib/layui-v2.6.3/css/layui.css" media="all">
<link rel="stylesheet" href="../css/public.css" media="all">
</head>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<div class="layui-card top-panel">
<div class="layui-card-header">代理信息</div>
<div class="layui-card-body">
<table class="layui-hide" id="forwardParaTableId" lay-filter="forwardParaTableFilter"></table>
</div>
</div>
</div>
</div>
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script th:inline="none">
layui.use(['form', 'table'], function () {
var $ = layui.$,
form = layui.form,
table = layui.table;
/**
** 推送参数组
**/
table.render({
elem: '#forwardParaTableId',
url: '/fwd/agents',
toolbar: '#toolbarTable',
cols: [[
{field: 'name', title: '名称'},
{field: 'description', title: '描述'},
{field: 'updatetime', title: '更新时间', templet: "<div>{{layui.util.toDateString(d.updatetime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
{field: 'fwd_device_num', title: '推送设备数'},
{field: 'result', title: '推送结果',templet: '#resultTrans'}
]],
limit: 10,
page: true,
skin: 'line'
});
});
</script>
<script type="text/html" id="resultTrans">
{{# if(d.syn == 0){ }}
<span class="layui-badge layui-bg-orange">失败</span>
{{# } else { }}
<span class="layui-badge layui-bg-green">成功</span>
{{# } }}
</script>
</body>
</html>

View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>推送记录</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="../lib/layui-v2.6.3/css/layui.css" media="all">
<link rel="stylesheet" href="../css/public.css" media="all">
</head>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<div class="layui-card top-panel">
<div class="layui-card-header">推送记录</div>
<div class="layui-card-body">
<table class="layui-hide" id="forwardParaTableId" lay-filter="forwardParaTableFilter"></table>
</div>
</div>
</div>
</div>
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script th:inline="none">
layui.use(['form', 'table'], function () {
var $ = layui.$,
form = layui.form,
table = layui.table;
/**
** 推送参数组
**/
table.render({
elem: '#forwardParaTableId',
url: '/fwd/records',
toolbar: '#toolbarTable',
cols: [[
{field: 'deviceid', title: '设备号', sort: true},
{field: 'project_id', title: '项目号'},
{field: 'devicenum', title: '推送设备数'},
{field: 'starttime', title: '起始时间', templet: "<div>{{layui.util.toDateString(d.starttime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
{field: 'endtime', title: '结束时间', templet: "<div>{{layui.util.toDateString(d.endtime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
{field: 'fwd_group_id', title: '推送组'},
{field: 'state', title: '状态',templet: '#stateTrans'}
]],
limit: 10,
page: true,
skin: 'line'
});
});
</script>
<script type="text/html" id="stateTrans">
{{# if(d.state == 0){ }}
<span>推送完成</span>
{{# } else if(d.state == 2){ }}
<span>补传中</span>
{{# } else if(d.state == 3){ }}
<span>补传完成</span>
{{# } else { }}
<span >等待</span>
{{# } }}
</script>
</body>
</html>

View File

@ -25,13 +25,7 @@
<table class="layui-hide" id="calcParaTableId" lay-filter="calcParaTableFilter"></table>
</div>
</div>
<div class="layui-card top-panel">
<div class="layui-card-header">推送参数</div>
<div class="layui-card-body">
<table class="layui-hide" id="forwardParaTableId" lay-filter="forwardParaTableFilter"></table>
</div>
</div>
</div>
<script type="text/html" id="currentTableBar">
@ -215,89 +209,6 @@
});
}
});
/**
** 推送参数组
**/
table.render({
elem: '#forwardParaTableId',
url: '/gnss/group/list_fwd',//假数据
toolbar: '#toolbarTable',
cols: [[
{field: 'id', title: '组号', sort: true},
{field: 'description', title: '名称'},
{field: 'type1', title: '目标1类型', templet: '#type1Trans'},
{field: 'addr1', title: '目标1地址', templet: '<div >{{d.addr1}}:{{d.port1}}</div>'},
{field: 'template1', title: '目标1模板'},
{field: 'type2', title: '目标2类型', templet: '#type2Trans'},
{field: 'addr2', title: '目标2地址', templet: '<div >{{d.addr2}}:{{d.port2}}</div>'},
{field: 'template2', title: '目标1模板'},
{field: 'device_num', title: '关联设备数'},
{title: '操作', minWidth: 150, toolbar: '#currentTableBar', align: "center"}
]],
limit: 10,
page: true,
skin: 'line'
});
table.on('toolbar(forwardParaTableFilter)', function (obj) {
if (obj.event === 'add') {
var index = layer.open({
title: '新增推送参数组',
type: 2,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: ['100%', '100%'],
content: '../page/table/gnss_add_group_fwd',
});
$(window).on("resize", function () {
layer.full(index);
});
}
});
table.on('tool(forwardParaTableFilter)', function (obj) {
var data = obj.data;
if (obj.event === 'edit') {
var index = layer.open({
title: '修改分组',
type: 2,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: ['100%', '100%'],
content: '../page/table/gnss_add_group_fwd',
success: function(layero, index) {
var iframe = window['layui-layer-iframe' + index];
iframe.setParams(data);
}
});
$(window).on("resize", function () {
layer.full(index);
});
return false;
} else if (obj.event === 'delete') {
layer.confirm('确定删除参数组'+data.id+"?", function(index){
$.ajax({
type:"POST",
url:"/gnss/group/delete_fwd",
data:{
'del_id':data.id
},
success: function (data) {
//data是cotroller相应处理函数的返回值
table.reload('forwardParaTableId');
},
error: function () {
console.log("ajax error");
}
});
layer.close(index);
});
}
});
});
function onBaseParaUpdated(){
@ -306,33 +217,8 @@
function onCalcParaUpdated(){
layui.table.reload('calcParaTableId');
}
function onFwdParaUpdated(){
layui.table.reload('forwardParaTableId');
}
</script>
<script type="text/html" id="type1Trans">
{{# if(d.type1 == 0){ }}
<span>禁用</span>
{{# } else if(d.type1 == 1){ }}
<span>解算结果</span>
{{# } else if(d.type1 == 2){ }}
<span>原始数据</span>
{{# } else { }}
<span>NTRIP</span>
{{# } }}
</script>
<script type="text/html" id="type2Trans">
{{# if(d.type2 == 0){ }}
<span>禁用</span>
{{# } else if(d.type2 == 1){ }}
<span>解算结果</span>
{{# } else if(d.type2 == 2){ }}
<span>原始数据</span>
{{# } else { }}
<span>NTRIP</span>
{{# } }}
</script>
</body>
</html>

View File

@ -77,11 +77,11 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">推送参数组</label>
<label class="layui-form-label">推送</label>
<div class="layui-input-inline">
<select name="fwd_group_id" id="fwd_group_id" lay-verify="required" lay-search="">
<option value="0">不推送</option>
<option th:each="item : ${gnss_group_fwd_list}" th:text="${item.id}" th:value="${item.id}"></option>
<option value="不推送">不推送</option>
<option th:each="item : ${gnss_group_fwd_list}" th:text="${item.name}" th:value="${item.name}"></option>
</select>
</div>
</div>

View File

@ -1,176 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>转发参数</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="../../lib/layui-v2.6.3/css/layui.css" media="all">
<link rel="stylesheet" href="../../css/public.css" media="all">
<style>
body {
background-color: #ffffff;
}
</style>
</head>
<body>
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">组号</label>
<div class="layui-input-block">
<input type="number" name="id" id="id" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入组号" value="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">名称</label>
<div class="layui-input-block">
<input type="text" name="description" id="description" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入单位名称" value="25" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标1类型</label>
<div class="layui-input-inline">
<select name="type1" id="type1" lay-filter="type1">
<option value="0">禁用</option>
<option value="1">解算结果</option>
<option value="2">原始数据</option>
<option value="3">NTRIP</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标1协议</label>
<div class="layui-input-inline">
<select name="protocol1" id="protocol1" lay-filter="type1">
<option value="0">TCP</option>
<option value="1">UDP</option>
<option value="2">HTTP</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">目标1地址</label>
<div class="layui-input-block">
<input type="text" name="addr1" id="addr1" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入域名或IP" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">目标1端口号</label>
<div class="layui-input-block">
<input type="number" name="port1" id="port1" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入端口号" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">目标1模板</label>
<div class="layui-input-inline">
</select>
<select name="template1" id="template1" lay-verify="required" lay-search="">
<option th:each="item : ${template_list}" th:text="${item.name}" th:value="${item.name}"></option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标2类型</label>
<div class="layui-input-inline">
<select name="type2" id="type2" lay-filter="type1">
<option value="0">禁用</option>
<option value="1">解算结果</option>
<option value="2">原始数据</option>
<option value="3">NTRIP</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标2协议</label>
<div class="layui-input-inline">
<select name="protocol2" id="protocol2" lay-filter="type1">
<option value="0">TCP</option>
<option value="1">UDP</option>
<option value="2">HTTP</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标2地址</label>
<div class="layui-input-block">
<input type="text" name="addr2" id="addr2" placeholder="请输入域名或IP" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标2端口号</label>
<div class="layui-input-block">
<input type="number" name="port2" id="port2" placeholder="请输入端口号" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">目标2模板</label>
<div class="layui-input-inline">
</select>
<select name="template2" id="template2" lay-verify="required" lay-search="">
<option th:each="item : ${template_list}" th:text="${item.name}" th:value="${item.name}"></option>
</select>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
<script src="../../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script>
layui.use(['form'], function () {
var form = layui.form,
$ = layui.$;
var iframeIndex = parent.layer.getFrameIndex(window.name);
//监听提交
form.on('submit(saveBtn)', function (data) {
console.log(JSON.stringify(data.field));
$.ajax({
type:"POST",
url:"/gnss/group/update_fwd",
contentType: "application/json;charset=UTF-8",
data: JSON.stringify(data.field),
success: function (result) {
console.log(result);
parent.onFwdParaUpdated();
parent.layer.close(iframeIndex);
},
error: function () {
console.log("ajax error");
parent.layer.close(iframeIndex);
}
});
return false;
});
});
function setParams(data){
var form = layui.form,
$ = layui.$;
var group_id = $('#id');
group_id.val(data.id);
group_id.attr('readonly',true);
$('#description').val(data.description);
$('#type1').val(data.type1);
$('#addr1').val(data.addr1);
$('#port1').val(data.port1);
$('#template1').val(data.template1);
$('#type2').val(data.type2);
$('#addr2').val(data.addr2);
$('#port2').val(data.port2);
$('#template1').val(data.template2);
form.render();
}
</script>
</body>
</html>