R execute(Q query) { + Executorexecutor = (Executor)(executors.get(query.getClass())); + return executor.execute(query); + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D31xConfigAckMessageExecutor.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D31xConfigAckMessageExecutor.java new file mode 100644 index 00000000..52ef6685 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D31xConfigAckMessageExecutor.java @@ -0,0 +1,23 @@ +package com.imdroid.sideslope.executor; + +import com.imdroid.sideslope.message.D31xConfigAckMessage; +import com.imdroid.sideslope.message.D3F0SelfCheckMessage; +import org.springframework.stereotype.Component; + +/** + * @author Layton + * @date 2023/2/2 20:40 + */ +@Component +public class D31xConfigAckMessageExecutor implements Executor{ + + @Override + public Void execute(D31xConfigAckMessage message) { + return null; + } + + @Override + public Class> getMessageType() { + return D3F0SelfCheckMessage.class; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D331RtcmMessageExecutor.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D331RtcmMessageExecutor.java new file mode 100644 index 00000000..7623dd36 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D331RtcmMessageExecutor.java @@ -0,0 +1,60 @@ +package com.imdroid.sideslope.executor; + +import com.imdroid.sideslope.message.D331RtcmMessage; +import com.imdroid.sideslope.sal.Device; +import com.imdroid.sideslope.sal.DeviceService; +import com.imdroid.sideslope.server.OnlineChannels; +import com.imdroid.sideslope.util.ThreadManager; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * @author Layton + * @date 2023/2/2 20:49 + */ +@Component +public class D331RtcmMessageExecutor implements Executor { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource(name = "local") + private DeviceService deviceService; + + @Override + public Void execute(D331RtcmMessage message) { + if (logger.isDebugEnabled()) { + logger.debug("receive d331 rtcm message of device:{}", message.getId()); + } + String id = message.getId(); + byte[] forwardBytes = message.getSrcData(); + List deviceList = deviceService.findByParentId(id); + for (Device device : deviceList) { + String deviceId = device.getDeviceId(); + OnlineChannels.INSTANCE.get(deviceId).ifPresent(deviceChannel -> { + if (logger.isDebugEnabled()) { + logger.debug("forward d331 rtcm message to device {}", deviceId); + } + ByteBuf buf = Unpooled.buffer(); + buf.writeBytes(forwardBytes); + deviceChannel.writeAndFlush(buf); + }); + } + final Date now = new Date(); + ThreadManager.getFixedThreadPool().execute(() -> { + deviceService.updateLatestDataTime(id, now); + }); + return null; + } + + @Override + public Class> getMessageType() { + return D331RtcmMessage.class; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D341LocationMessageExecutor.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D341LocationMessageExecutor.java new file mode 100644 index 00000000..27b3cc05 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D341LocationMessageExecutor.java @@ -0,0 +1,42 @@ +package com.imdroid.sideslope.executor; + +import com.imdroid.sideslope.calc.GNSSCalcService; +import com.imdroid.sideslope.message.D341LocationMessage; +import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService; +import com.imdroid.sideslope.util.ThreadManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Layton + * @date 2023/2/2 20:50 + */ +@Component +public class D341LocationMessageExecutor implements Executor { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private GNSSCalcService gnssCalcService; + @Autowired + private GNSSDeviceLocationRecordService dataPersistService; + @Override + public Void execute(D341LocationMessage message) { + if (logger.isDebugEnabled()) { + logger.debug("receive d341 location message of device:{}", message.getId()); + } + ThreadManager.getFixedThreadPool().submit(() -> { + gnssCalcService.calcSingle(message); + dataPersistService.saveSingleCalcData(message); + }); + + return null; + } + + @Override + public Class> getMessageType() { + return D341LocationMessage.class; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D3F0SelfCheckMessageExecutor.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D3F0SelfCheckMessageExecutor.java new file mode 100644 index 00000000..a0856e3f --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D3F0SelfCheckMessageExecutor.java @@ -0,0 +1,33 @@ +package com.imdroid.sideslope.executor; + +import com.imdroid.sideslope.message.D3F0SelfCheckMessage; +import com.imdroid.sideslope.service.DataPersistService; +import com.imdroid.sideslope.util.ThreadManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Layton + * @date 2023/2/2 20:40 + */ +@Component +public class D3F0SelfCheckMessageExecutor implements Executor { + + @Autowired + private DataPersistService dataPersistService; + + @Override + public Void execute(D3F0SelfCheckMessage message) { + // 存储最新设备状态信息到数据库中 + ThreadManager.getFixedThreadPool().submit(() -> { + dataPersistService.saveDeviceState(message); + }); + + return null; + } + + @Override + public Class> getMessageType() { + return D3F0SelfCheckMessage.class; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D3F2StopIndicationMessageExecutor.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D3F2StopIndicationMessageExecutor.java new file mode 100644 index 00000000..f52fa116 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/D3F2StopIndicationMessageExecutor.java @@ -0,0 +1,46 @@ +package com.imdroid.sideslope.executor; + +import com.imdroid.sideslope.message.D3F2StopIndicationMessage; +import com.imdroid.sideslope.sal.DeviceService; +import com.imdroid.sideslope.service.DataPersistService; +import com.imdroid.sideslope.util.ThreadManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Date; + +/** + * 停止指示消息处理器 + * + * @author LiGang + */ +@Component +public class D3F2StopIndicationMessageExecutor implements Executor { + + @Autowired + private DataPersistService dataPersistService; + + @Resource(name = "local") + private DeviceService deviceService; + + @Override + public Void execute(D3F2StopIndicationMessage message) { + // 储设备收发字节数统计信息 + ThreadManager.getFixedThreadPool().submit(() -> { + dataPersistService.saveDeviceTrxStat(message); + }); + + // 更新设备的最新数据时间 + final Date now = new Date(); + ThreadManager.getFixedThreadPool().submit(() -> { + deviceService.updateLatestDataTime(message.getId(), now); + }); + return null; + } + + @Override + public Class> getMessageType() { + return D3F2StopIndicationMessage.class; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/Executor.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/Executor.java new file mode 100644 index 00000000..b531babc --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/Executor.java @@ -0,0 +1,12 @@ +package com.imdroid.sideslope.executor; + +/** + * @author Layton + * @date 2022/4/8 22:32 + */ +public interface Executor { + + R execute(Q message); + + Class> getMessageType(); +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/MessageParser.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/MessageParser.java new file mode 100644 index 00000000..745ffa1c --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/executor/MessageParser.java @@ -0,0 +1,47 @@ +package com.imdroid.sideslope.executor; + +import com.imdroid.sideslope.exception.UnSupportedMessageException; +import com.imdroid.sideslope.message.*; +import io.netty.buffer.ByteBuf; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Layton + * @date 2023/2/2 20:41 + */ +public class MessageParser { + + private static final Map> types = new HashMap<>(); + + public static final MessageParser instance = new MessageParser(); + + private MessageParser() { + + } + + static { + types.put((short)0xd3f0, D3F0SelfCheckMessage.class); + types.put((short)0xd3f2, D3F2StopIndicationMessage.class); + //types.put((short)0xd330, D330RtcmMessage.class); + //types.put((short)0xd340, D340LocationMessage.class); + types.put((short)0xd331, D331RtcmMessage.class); + types.put((short)0xd341, D341LocationMessage.class); + types.put((short)0xd310, D31xConfigAckMessage.class);//GNSS配置应答 + types.put((short)0xd311, D31xConfigAckMessage.class);//单片机配置应答 + types.put((short)0xd31A, D31xConfigAckMessage.class);//DTU配置应答 + } + + + public BaseMessage parse(ByteBuf src) throws Exception { + short flag = src.getShort(0); + Class extends BaseMessage> clz = types.get(flag); + if (clz == null) { + throw new UnSupportedMessageException(); + } + BaseMessage message = clz.newInstance(); + message.decode(src); + return message; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/BaseMessage.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/BaseMessage.java new file mode 100644 index 00000000..1ff53010 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/BaseMessage.java @@ -0,0 +1,81 @@ +package com.imdroid.sideslope.message; + +import com.imdroid.sideslope.util.WrongMessageRecorder; +import io.netty.buffer.ByteBuf; + +/** + * @author Layton + * @date 2023/2/2 20:32 + */ +public abstract class BaseMessage { + protected byte[] header; + protected String id; + protected int len; + protected int pps; + + protected byte[] srcData;//message在线程中处理,需要把channel传递过来的数据拷贝出来 + + public void decode(ByteBuf src) { + if (shouldDecodeHeader()) { + // read操作会移动ByteBuf内部指针,除D331外,其他都用read来读 + int packetLen = src.readableBytes(); + this.header = new byte[2]; + src.readBytes(header); + + this.len = src.readUnsignedShort(); + this.id = String.valueOf(src.readUnsignedInt()); + if (packetLen - 4 != this.len) { + String msg = (String.format("id[%s],长度字段值[%s]与包的消息体长度[%s]不匹配", id, this.len, packetLen - 4)); + WrongMessageRecorder.INSTANCE.append("receive wrong message," + msg); + } + this.pps = src.readUnsignedShort(); + } + decodeBody(src); + } + + public abstract void decodeBody(ByteBuf src); + + public boolean shouldDecodeHeader() { + return true; + } + + public byte[] getHeader() { + return header; + } + + public void setHeader(byte[] header) { + this.header = header; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getLen() { + return len; + } + + public void setLen(int len) { + this.len = len; + } + + public int getPps() { + return pps; + } + + public void setPps(int pps) { + this.pps = pps; + } + + public byte[] getSrcData() { + return srcData; + } + + public void setSrcData(byte[] srcData) { + this.srcData = srcData; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D31xConfigAckMessage.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D31xConfigAckMessage.java new file mode 100644 index 00000000..49a6b412 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D31xConfigAckMessage.java @@ -0,0 +1,31 @@ +package com.imdroid.sideslope.message; + +import com.imdroid.sideslope.util.WrongMessageRecorder; +import io.netty.buffer.ByteBuf; + +/** + * @author Layton + * @date 2023/2/2 20:47 + */ +public class D31xConfigAckMessage extends BaseMessage { + + @Override + public void decodeBody(ByteBuf src) { + // get操作不会移动指针,这样可以确保整个全转发出去 + this.header = new byte[2]; + src.getBytes(0, header); // flag + this.len = src.getUnsignedShort(2); // length + this.id = String.valueOf(src.getUnsignedInt(4)); //id + if (src.readableBytes() - 4 != this.len) { + String msg = String.format("id[%s],长度字段值[%s]与包的消息体长度[%s]不匹配", id, this.len, src.readableBytes() - 4); + WrongMessageRecorder.INSTANCE.append("receive wrong message," + msg); + } + this.srcData = new byte[src.readableBytes()]; + src.readBytes(this.srcData); + } + + @Override + public boolean shouldDecodeHeader() { + return false; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D331RtcmMessage.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D331RtcmMessage.java new file mode 100644 index 00000000..8fe2cf85 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D331RtcmMessage.java @@ -0,0 +1,31 @@ +package com.imdroid.sideslope.message; + +import com.imdroid.sideslope.util.WrongMessageRecorder; +import io.netty.buffer.ByteBuf; + +/** + * @author Layton + * @date 2023/2/2 20:47 + */ +public class D331RtcmMessage extends BaseMessage { + + @Override + public void decodeBody(ByteBuf src) { + // get操作不会移动指针,这样可以确保整个全转发出去 + this.header = new byte[2]; + src.getBytes(0, header); // flag + this.len = src.getUnsignedShort(2); // length + this.id = String.valueOf(src.getUnsignedInt(4)); //id + if (src.readableBytes() - 4 != this.len) { + String msg = String.format("id[%s],长度字段值[%s]与包的消息体长度[%s]不匹配", id, this.len, src.readableBytes() - 4); + WrongMessageRecorder.INSTANCE.append("receive wrong message," + msg); + } + this.srcData = new byte[src.readableBytes()]; + src.readBytes(this.srcData); + } + + @Override + public boolean shouldDecodeHeader() { + return false; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D341LocationMessage.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D341LocationMessage.java new file mode 100644 index 00000000..4e724e46 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D341LocationMessage.java @@ -0,0 +1,25 @@ +package com.imdroid.sideslope.message; + +import com.imdroid.sideslope.bd.Tilt; +import com.imdroid.sideslope.bd.UBXUtil; +import com.imdroid.sideslope.util.WrongMessageRecorder; +import io.netty.buffer.ByteBuf; +import lombok.Data; + +/** + * @author Layton + * @date 2023/2/2 20:50 + */ +@Data +public class D341LocationMessage extends BaseMessage { + Tilt tilt; + double[] b562_loc; + @Override + public void decodeBody(ByteBuf src) { + // 读到pitch了,readable不不含pitch之前 + tilt = new Tilt(src.readFloat(), src.readFloat(),src.readFloat(),src.readFloat()); + // b562 + b562_loc = UBXUtil.getLocation(src); + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D3F0SelfCheckMessage.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D3F0SelfCheckMessage.java new file mode 100644 index 00000000..3ab6a638 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D3F0SelfCheckMessage.java @@ -0,0 +1,40 @@ +package com.imdroid.sideslope.message; + +import com.imdroid.secapi.dto.GnssStatusMsg; +import io.netty.buffer.ByteBuf; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * 自检消息 + * + * @author Layton + * @date 2023/2/2 20:38 + */ +@Data +public class D3F0SelfCheckMessage extends BaseMessage { + + GnssStatusMsg statusMsg = new GnssStatusMsg(); + + @Override + public void decodeBody(ByteBuf src) { + statusMsg.setDeviceid(getId()); + statusMsg.setUpdatetime(new Timestamp(System.currentTimeMillis())); + statusMsg.setDevicetime(new Timestamp(getPps()*1000)); + statusMsg.setPitch(src.readFloat()); + statusMsg.setRoll(src.readFloat()); + statusMsg.setYaw(src.readFloat()); + // skip shock + src.readFloat(); + statusMsg.setDtustate(src.readUnsignedByte()); + statusMsg.setRssi(src.readUnsignedByte()); + statusMsg.setVoltage(src.readUnsignedShort()); + // skip version + src.readUnsignedShort(); + statusMsg.setTemperature(src.readUnsignedShort()/10); + statusMsg.setHumidity(src.readUnsignedShort()/10); + + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D3F2StopIndicationMessage.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D3F2StopIndicationMessage.java new file mode 100644 index 00000000..d6b034c7 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/message/D3F2StopIndicationMessage.java @@ -0,0 +1,44 @@ +package com.imdroid.sideslope.message; + +import com.imdroid.secapi.dto.GnssTrxMsg; +import io.netty.buffer.ByteBuf; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * 停止指示消息 + * + * @author LiGang + */ +@Data +public class D3F2StopIndicationMessage extends BaseMessage { + + private GnssTrxMsg trxMsg = new GnssTrxMsg();; + + @Override + public void decodeBody(ByteBuf src) { + trxMsg.setDeviceid(getId()); + trxMsg.setUpdatetime(new Timestamp(System.currentTimeMillis())); + trxMsg.setDevicetime(new Timestamp(getPps()*1000)); + int keys = (this.len - 6) / 5; + for (int i = 0; i < keys; i++) { + int key = src.readUnsignedByte(); + long value = src.readUnsignedInt(); + if (key == 0) { + trxMsg.setUart1txbytes(value); + } else if (key == 1) { + trxMsg.setUart1rxbytes(value); + } else if (key == 2) { + trxMsg.setUart1unknown(value); + } else if (key == 3) { + trxMsg.setUart2txbytes(value); + } else if (key == 4) { + trxMsg.setUart2rxbytes(value); + } else if (key == 5) { + trxMsg.setUart2unknown(value); + } + } + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/rabbitmq/RabbitmqConfig.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/rabbitmq/RabbitmqConfig.java new file mode 100644 index 00000000..0ea05504 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/rabbitmq/RabbitmqConfig.java @@ -0,0 +1,36 @@ +package com.imdroid.sideslope.rabbitmq; + +import org.springframework.amqp.core.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * rabbitmq 配置类 + * + * @author LiGang + */ +@Configuration +public class RabbitmqConfig { + + public static final String QUEUE_GNSS_LOCATION_RECORD = "gnss_location_record"; + public static final String EXCHANGE_GNSS = "exchange_gnss"; + + /** + * 声明交换机 + */ + @Bean(EXCHANGE_GNSS) + public Exchange EXCHANGE_GNSS() { + return ExchangeBuilder.topicExchange(EXCHANGE_GNSS).durable(true).build(); + } + + /** + * 声明QUEUE_INFORM_EMAIL队列 + * @return Queue + */ + @Bean(QUEUE_GNSS_LOCATION_RECORD) + public Queue QUEUE_INFORM_EMAIL() { + return new Queue(QUEUE_GNSS_LOCATION_RECORD); + } + + +} \ No newline at end of file diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DbDeviceServiceImpl.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DbDeviceServiceImpl.java new file mode 100644 index 00000000..9ee2e939 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DbDeviceServiceImpl.java @@ -0,0 +1,80 @@ +package com.imdroid.sideslope.sal; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.imdroid.secapi.dto.GnssDevice; +import com.imdroid.secapi.dto.GnssDeviceMapper; +import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService; +import com.imdroid.sideslope.util.ThreadManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 描述 + * + * @author LiGang + */ +@Component(value = "db") +public class DbDeviceServiceImpl implements DeviceService { + + private final Logger logger = LoggerFactory.getLogger(DbDeviceServiceImpl.class); + + @Autowired + private GnssDeviceMapper gnssDeviceRepository; + + @Autowired + private GNSSDeviceLocationRecordService gnssDeviceLocationRecordService; + + @Override + public Device findByDeviceId(String deviceId) { + GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId); + if (gnssDevice == null) { + return null; + } + Device device = new Device(); + device.setDeviceId(gnssDevice.getDeviceid()); + device.setDeviceType(gnssDevice.getDevicetype()); + device.setParentId(gnssDevice.getParentid()); + device.setName(gnssDevice.getName()); + return device; + } + + @Override + public List findByParentId(String parentId) { + QueryWrapper query = new QueryWrapper(); + query.eq("parentid", parentId); + List gnssDeviceList = gnssDeviceRepository.selectList(query); + List deviceList = new ArrayList<>(gnssDeviceList.size()); + for (GnssDevice gnssDevice : gnssDeviceList) { + Device device = new Device(); + device.setDeviceId(gnssDevice.getDeviceid()); + device.setDeviceType(gnssDevice.getDevicetype()); + device.setParentId(gnssDevice.getParentid()); + device.setName(gnssDevice.getName()); + deviceList.add(device); + } + return deviceList; + } + + @Override + public boolean postLocationRecord(LocationRecordDTO locationRecord) { + ThreadManager.getFixedThreadPool().submit(() -> { + try { + gnssDeviceLocationRecordService.save(locationRecord); + } catch (Exception e) { + logger.error(e.toString()); + } + }); + return true; + } + + @Override + public void updateLatestDataTime(String deviceId, Date latestDataTime) { + + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/Device.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/Device.java new file mode 100644 index 00000000..06fbce92 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/Device.java @@ -0,0 +1,32 @@ +package com.imdroid.sideslope.sal; + +import lombok.Data; + +/** + * 基站 & 测站设备 + * + * @author Layton + * @date 2023/2/3 20:39 + */ +@Data +public class Device { + + /** + * 基站 + */ + public static final int DEVICE_BASE_STATION = 1; + + /** + * 测站 + */ + public static final int DEVICE_ROVER = 0; + + private String name; + + private String deviceId; + + private String parentId; + + private Integer deviceType; + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DeviceService.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DeviceService.java new file mode 100644 index 00000000..11aa8f92 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DeviceService.java @@ -0,0 +1,19 @@ +package com.imdroid.sideslope.sal; + +import java.util.Date; +import java.util.List; + +/** + * @author Layton + * @date 2023/2/3 20:37 + */ +public interface DeviceService { + + Device findByDeviceId(String deviceId); + + List findByParentId(String parentId); + + boolean postLocationRecord(LocationRecordDTO locationRecord); + + void updateLatestDataTime(String deviceId, Date latestDataTime); +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocalDeviceServiceImpl.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocalDeviceServiceImpl.java new file mode 100644 index 00000000..c7312a19 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocalDeviceServiceImpl.java @@ -0,0 +1,61 @@ +package com.imdroid.sideslope.sal; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author Layton + * @date 2023/2/3 20:46 + */ +@Component(value = "local") +public class LocalDeviceServiceImpl implements DeviceService { + + private static final Cache deviceCache = CacheBuilder.newBuilder(). + expireAfterWrite(30, TimeUnit.MINUTES).build(); + + private static final Cache > subDeviceCache = CacheBuilder.newBuilder(). + expireAfterWrite(10, TimeUnit.MINUTES).build(); + + @Resource(name = "db") + private DeviceService delegate; + + @Override + public Device findByDeviceId(String deviceId) { + Device device = deviceCache.getIfPresent(deviceId); + if (device == null) { + device = delegate.findByDeviceId(deviceId); + if (device != null) { + deviceCache.put(deviceId, device); + } + } + return device; + } + + @Override + public List findByParentId(String parentId) { + List device = subDeviceCache.getIfPresent(parentId); + if (device == null) { + device = delegate.findByParentId(parentId); + if (device != null) { + subDeviceCache.put(parentId, device); + } + } + return device; + } + + @Override + public boolean postLocationRecord(LocationRecordDTO locationRecord) { + return delegate.postLocationRecord(locationRecord); + } + + @Override + public void updateLatestDataTime(String deviceId, Date latestDataTime) { + delegate.updateLatestDataTime(deviceId, latestDataTime); + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocationRecordDTO.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocationRecordDTO.java new file mode 100644 index 00000000..e37eda1e --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocationRecordDTO.java @@ -0,0 +1,81 @@ +package com.imdroid.sideslope.sal; + + +/** + * @author Layton + * @date 2023/2/15 20:58 + */ +public class LocationRecordDTO { + + private String deviceId; + + /** + * 北斗位置(b562),相对坐标 + */ + private String b562; + + /** + * 惯导位置(9250),相对坐标 + */ + private String r9250; + + /** + * 融合位置,相对坐标 + */ + private String result; + + + private String flag; + + public LocationRecordDTO() { + + } + + public LocationRecordDTO(String deviceId, String b562, String r9250, String result, String flag) { + this.deviceId = deviceId; + this.b562 = b562; + this.r9250 = r9250; + this.result = result; + this.flag = flag; + } + + public String getFlag() { + return flag; + } + + public void setFlag(String flag) { + this.flag = flag; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getB562() { + return b562; + } + + public void setB562(String b562) { + this.b562 = b562; + } + + public String getR9250() { + return r9250; + } + + public void setR9250(String r9250) { + this.r9250 = r9250; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/DeviceChannel.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/DeviceChannel.java new file mode 100644 index 00000000..f78328d1 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/DeviceChannel.java @@ -0,0 +1,61 @@ +package com.imdroid.sideslope.server; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.socket.DatagramPacket; +import lombok.Data; + +import java.net.InetSocketAddress; + +/** + * @author Layton + * @date 2023/2/2 21:00 + */ +@Data +public class DeviceChannel { + private String deviceId; + + private Channel channel; + + private InetSocketAddress address; + + private long lastTime; + + private boolean tcp; + int txbytes = 0; + int rxbytes = 0; + int d3xxbytes = 0; + int b562bytes = 0; + + public DeviceChannel(String deviceId, Channel channel, InetSocketAddress address) { + this.deviceId = deviceId; + this.channel = channel; + this.address = address; + lastTime = System.currentTimeMillis(); + this.tcp = address == null; + } + + public boolean isOnline() { + if (tcp) { + return channel.isActive(); + } +// return (System.currentTimeMillis() - lastTime) < 28 * 1000L; + return true; + } + + public void writeAndFlush(ByteBuf buf) { + txbytes += buf.readableBytes(); + if (tcp) { + channel.writeAndFlush(buf); + } else { + channel.writeAndFlush(new DatagramPacket(buf, address)); + } + } + + public void updateRxBytes(int bytes, byte[] header){ + rxbytes += bytes; + int gnss_bytes = header[0]<<8 | header[1]; + if(gnss_bytes == 0xd331) d3xxbytes += bytes; + else if(gnss_bytes == 0xd341) b562bytes += bytes; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/OnlineChannels.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/OnlineChannels.java new file mode 100644 index 00000000..752dad77 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/OnlineChannels.java @@ -0,0 +1,62 @@ +package com.imdroid.sideslope.server; + +import cn.hutool.core.collection.ConcurrentHashSet; +import io.netty.channel.Channel; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author Layton + * @date 2023/2/2 21:00 + */ +public class OnlineChannels { + + public static final OnlineChannels INSTANCE = new OnlineChannels(); + + // DTU已连接,有imei上报,但deviceId还没上报 + // 记录DTU连接的好处:当DTU重连接而设备还没上报deviceId时,可以通过IMEI或广播消息来找到设备 + private final Map dtuChannels = new ConcurrentHashMap<>(); + + // 设备已连接,deviceId已上报 + private final Map channels = new ConcurrentHashMap<>(); + + private OnlineChannels() {} + + public boolean isNewChannel(Channel channel){ + Attribute attr = channel.attr(AttributeKey.valueOf("imei")); + return (attr.get()==null); + } + + public boolean isNewDeviceChannel(Channel channel){ + Attribute attr = channel.attr(AttributeKey.valueOf("device_id")); + return (attr.get()==null); + } + + public void putDtuChannel(Channel channel, String imei){ + dtuChannels.put(imei, channel); + Attribute attr = channel.attr(AttributeKey.valueOf("imei")); + attr.set(imei); + } + + public void putDeviceChannel(DeviceChannel channel) { + Attribute attr = channel.getChannel().attr(AttributeKey.valueOf("device_id")); + attr.set(channel.getDeviceId()); + channels.put(channel.getDeviceId(), channel); + } + + public Optional get(String deviceId) { + return Optional.ofNullable(channels.get(deviceId)); + } + + public List getIfPresent(List deviceIds) { + return deviceIds.stream().map(x -> channels.get(x)).filter(Objects::nonNull).collect(Collectors.toList()); + } + + public DeviceChannel getDeviceChannel(String deviceId){ + return channels.get(deviceId); + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/udp/RtcmUdpHandler.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/udp/RtcmUdpHandler.java new file mode 100644 index 00000000..6237ab64 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/udp/RtcmUdpHandler.java @@ -0,0 +1,88 @@ +package com.imdroid.sideslope.server.udp; + +import com.imdroid.sideslope.exception.UnSupportedMessageException; +import com.imdroid.sideslope.executor.BizExecutors; +import com.imdroid.sideslope.executor.MessageParser; +import com.imdroid.sideslope.message.BaseMessage; +import com.imdroid.sideslope.server.DeviceChannel; +import com.imdroid.sideslope.server.OnlineChannels; +import com.imdroid.sideslope.util.DataTypeUtil; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.socket.DatagramPacket; +import io.netty.util.ReferenceCountUtil; +import org.apache.ibatis.javassist.bytecode.ByteArray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +/** + * @author Layton + * @date 2023/2/13 11:47 + */ +@ChannelHandler.Sharable +@Component +public class RtcmUdpHandler extends ChannelInboundHandlerAdapter { + + private static final Logger logger = LoggerFactory.getLogger(RtcmUdpHandler.class); + + @Autowired + private BizExecutors bizExecutors; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + DatagramPacket packet = (DatagramPacket) msg; + OnlineChannels onlineChannels = OnlineChannels.INSTANCE; + try { + if (packet.content() == null) { + return; + } + if (logger.isDebugEnabled()) { + byte[] data = new byte[packet.content().readableBytes()]; + packet.content().getBytes(0, data); + logger.debug("receive message:" + DataTypeUtil.getHexString(data)); + } + // 消息解析 + BaseMessage message = MessageParser.instance.parse(packet.content()); + // 更新通道 + DeviceChannel deviceChannel; + if(onlineChannels.isNewDeviceChannel(ctx.channel())){ + deviceChannel = new DeviceChannel(message.getId(), ctx.channel(), packet.sender()); + onlineChannels.putDeviceChannel(deviceChannel); + } + else{ + deviceChannel = onlineChannels.getDeviceChannel(message.getId()); + } + deviceChannel.updateRxBytes(message.getLen(), message.getHeader()); + // 业务处理 + bizExecutors.execute(message); + } catch (UnSupportedMessageException e) { + // DTU注册消息 + if(onlineChannels.isNewChannel(ctx.channel())){ + byte[] data = new byte[packet.content().readableBytes()]; + packet.content().getBytes(0, data); + if(data.length == 15 && data[0]=='8' && data[1]=='6') { + OnlineChannels.INSTANCE.putDtuChannel(ctx.channel(), new String(data)); + } + else logger.warn("receive un supported message: {}", e.getMessage()); + } + else logger.warn("receive un supported message: {}", e.getMessage()); + } catch (Exception e) { + logger.error("channel read error: {}", e.toString()); + } finally { + ReferenceCountUtil.release(msg); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + super.exceptionCaught(ctx, cause); + ctx.close(); + logger.error("Exception caught: {}", cause.toString()); + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/udp/RtcmUdpServer.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/udp/RtcmUdpServer.java new file mode 100644 index 00000000..4d1e3575 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/server/udp/RtcmUdpServer.java @@ -0,0 +1,60 @@ +package com.imdroid.sideslope.server.udp; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioDatagramChannel; +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.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +/** + * @author Layton + * @date 2023/2/13 11:47 + */ +@Component +public class RtcmUdpServer implements ApplicationRunner { + + private final Logger logger = LoggerFactory.getLogger(RtcmUdpServer.class); + + @Value("${netty.port:9903}") + private Integer port; + + @Autowired + private RtcmUdpHandler rtcmUdpHandler; + + public RtcmUdpServer() { + + } + + @Override + public void run(ApplicationArguments args) throws Exception { + new Thread(this::start0, "udp-server").start(); + } + + + private void start0() { + EventLoopGroup group = new NioEventLoopGroup(); + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(group) + .channel(NioDatagramChannel.class) + .option(ChannelOption.SO_SNDBUF, 512) + .option(ChannelOption.SO_RCVBUF, 512) + .handler(rtcmUdpHandler); + try { + ChannelFuture future = bootstrap.bind(port).sync().channel().closeFuture(); + logger.info("udp server start at port {}", port); + future.await(); + } catch (Exception e) { + logger.error("Error starting Imdroid protocol at port {}", port, e); + } finally { + group.shutdownGracefully(); + } + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DataPersistService.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DataPersistService.java new file mode 100644 index 00000000..c9eb2c41 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DataPersistService.java @@ -0,0 +1,16 @@ +package com.imdroid.sideslope.service; + +import com.imdroid.sideslope.message.D3F0SelfCheckMessage; +import com.imdroid.sideslope.message.D3F2StopIndicationMessage; + +/** + * 设备数据持久化接口 + * + * @author LiGang + */ +public interface DataPersistService { + + void saveDeviceState(D3F0SelfCheckMessage d3F0SelfCheckMessage); + + void saveDeviceTrxStat(D3F2StopIndicationMessage d3F2StopIndicationMessage); +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DataPersistServiceImpl.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DataPersistServiceImpl.java new file mode 100644 index 00000000..9f3afe39 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DataPersistServiceImpl.java @@ -0,0 +1,86 @@ +package com.imdroid.sideslope.service; + +import com.imdroid.secapi.dto.*; +import com.imdroid.sideslope.message.D3F0SelfCheckMessage; +import com.imdroid.sideslope.message.D3F2StopIndicationMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 设备数据持久化实现 + * + * @author LiGang + */ +@Service +public class DataPersistServiceImpl implements DataPersistService { + + @Autowired + private GnssStatusMapper deviceStateRepository; + + @Autowired + private GnssStatusMsgMapper statusMsgMapper; + + @Autowired + private GnssTrxMsgMapper trxMsgMapper; + + @Override + public void saveDeviceState(D3F0SelfCheckMessage message) { + try { + // 保存到statusmsg数据表里 + GnssStatusMsg statusMsg = message.getStatusMsg(); + statusMsgMapper.insert(statusMsg); + + //新增或更新到status数据表里 + GnssStatus deviceState = deviceStateRepository.getByDeviceId(message.getId()); + boolean new_flag = false; + if(null == deviceState) { + deviceState = new GnssStatus(); + new_flag = true; + } + //deviceState.setId(SequenceUtil.getSequence()); + deviceState.setDeviceid(message.getId()); + deviceState.setUpdatetime(statusMsg.getUpdatetime()); + deviceState.setRoll(statusMsg.getRoll()); + deviceState.setPitch(statusMsg.getPitch()); + deviceState.setYaw(statusMsg.getYaw()); + deviceState.setRssi(statusMsg.getRssi()); + deviceState.setVoltage(statusMsg.getVoltage()); + deviceState.setTemperature(statusMsg.getTemperature()); + deviceState.setHumidity(statusMsg.getHumidity()); + + // 检测状态和告警 + deviceState.setState(GnssStatus.STATE_ACTIVE); + + if(new_flag) deviceStateRepository.insert(deviceState); + else deviceStateRepository.updateById(deviceState); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void saveDeviceTrxStat(D3F2StopIndicationMessage message) { + try { + // 添加到trxmsg里 + trxMsgMapper.insert(message.getTrxMsg()); + + // 检测该对象是否已存在 + GnssStatus deviceState = deviceStateRepository.getByDeviceId(message.getId()); + //新增或更新到status数据表里 + if(null != deviceState) { + // 记录服务端收发统计 + /*deviceState.setTxbytes(txbytes); + deviceState.setRxbytes(rxbytes); + deviceState.setD3xxbytes(d3xxbytes); + deviceState.setB562bytes(b562bytes);*/ + deviceState.setState(GnssStatus.STATE_IDLE); + deviceStateRepository.updateById(deviceState); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/GNSSDeviceLocationRecordService.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/GNSSDeviceLocationRecordService.java new file mode 100644 index 00000000..f4b9dd5a --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/GNSSDeviceLocationRecordService.java @@ -0,0 +1,15 @@ +package com.imdroid.sideslope.service; + +import com.imdroid.sideslope.message.D341LocationMessage; +import com.imdroid.sideslope.sal.LocationRecordDTO; + + +/** + * @author Layton + * @date 2023/2/4 20:18 + */ +public interface GNSSDeviceLocationRecordService { + + public void save(LocationRecordDTO importRecord) throws Exception; + public void saveSingleCalcData(D341LocationMessage message); +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/GNSSDeviceLocationRecordServiceImpl.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/GNSSDeviceLocationRecordServiceImpl.java new file mode 100644 index 00000000..e6b7c044 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/GNSSDeviceLocationRecordServiceImpl.java @@ -0,0 +1,198 @@ +package com.imdroid.sideslope.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.imdroid.secapi.dto.*; +import com.imdroid.sideslope.bd.Tilt; +import com.imdroid.sideslope.message.D341LocationMessage; +import com.imdroid.sideslope.rabbitmq.RabbitmqConfig; +import com.imdroid.sideslope.sal.LocationRecordDTO; +import com.imdroid.sideslope.util.GsonUtil; +import com.imdroid.sideslope.util.NumberUtils; +import io.dt20.common.persistence.Attribute; +import io.dt20.common.repo.AttributeRepository; +import io.dt20.util.SequenceUtil; +import io.dt20.util.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Layton + * @date 2023/2/15 21:05 + */ +@Service +public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRecordService{ + + private final Logger logger = LoggerFactory.getLogger(this.getClazz()); + + @Autowired + private GnssCalcDataMapper repository; + @Autowired + private GnssSingleCalcDataMapper singleCalcDataMapper; + + @Autowired + private GnssDeviceMapper gnssDeviceRepository; + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Autowired + private AttributeRepository attributeRepository; + + private int a, b = 25 * 60 * 60 * 1000; + + + protected Class getClazz() { + return GnssCalcData.class; + } + + @Override + public void save(LocationRecordDTO importRecord) throws Exception { + GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(importRecord.getDeviceId()); + + GnssCalcData locationRecord = new GnssCalcData(); + locationRecord.setDeviceid(importRecord.getDeviceId()); + locationRecord.setCreatetime(new Timestamp(System.currentTimeMillis())); + locationRecord.setEnabled(true); + locationRecord.setId(SequenceUtil.getSequence()); + if (!StringUtil.isEmpty(importRecord.getB562())) { + String resultStr = NumberUtils.removeBrackets(importRecord.getB562()); + String[] arr = resultStr.split(","); + // 由cm转化为mm + locationRecord.setB562e(NumberUtils.scaleTwo(Double.parseDouble(arr[0]) * 10)); + locationRecord.setB562n(NumberUtils.scaleTwo(Double.parseDouble(arr[1]) * 10)); + locationRecord.setB562d(NumberUtils.scaleTwo(Double.parseDouble(arr[2]) * 10)); + } + if (!StringUtil.isEmpty(importRecord.getR9250())) { + String resultStr = NumberUtils.removeBrackets(importRecord.getR9250()); + String[] arr = resultStr.split(","); + locationRecord.setR9250e(NumberUtils.scaleTwo(arr[0])); + locationRecord.setR9250n(NumberUtils.scaleTwo(arr[1])); + locationRecord.setR9250d(NumberUtils.scaleTwo(arr[2])); + } + if (!StringUtil.isEmpty(importRecord.getResult())) { + String resultStr = NumberUtils.removeBrackets(importRecord.getResult()); + String[] arr = resultStr.split(","); + locationRecord.setResulte(NumberUtils.scaleTwo(arr[0])); + locationRecord.setResultn(NumberUtils.scaleTwo(arr[1])); + locationRecord.setResultd(NumberUtils.scaleTwo(arr[2])); + + // 做滤波 水平方向按照shock 若 >1.5 用6h滤波 否则用25h + // 垂直方向 用6+12 + List attributes = attributeRepository.findByObjectAndPid(gnssDevice.getObjectName(), gnssDevice.getId()); + if (!StringUtil.isEmpty(importRecord.getFlag()) && Boolean.parseBoolean(importRecord.getFlag())) { + a = 6 * 60 * 60 * 1000; + b = 6 * 60 * 60 * 1000; + } + for (Attribute attribute : attributes) { + if (attribute.getValueNumber() == null) { + continue; + } + double[] avgEND = avgEND(gnssDevice.getDeviceid(), locationRecord, a, b); + if (ATTR_B562E.equals(attribute.getKey())) { + locationRecord.setRb562e(NumberUtils.scaleTwo(avgEND[0] * 10 - attribute.getValueNumber())); + } + if (ATTR_B562N.equals(attribute.getKey())) { + locationRecord.setRb562n(NumberUtils.scaleTwo(avgEND[1] * 10 - attribute.getValueNumber())); + } + if (ATTR_B562D.equals(attribute.getKey())) { + locationRecord.setRb562d(NumberUtils.scaleTwo(avgEND[2] * 10 - attribute.getValueNumber())); + } + } + a = 25 * 60 * 60 * 1000; + b = 25 * 60 * 60 * 1000; + } + sendDataToMq(locationRecord); + repository.insert(locationRecord); + + } + + public static final String ATTR_B562E = "b562e"; + public static final String ATTR_B562N = "b562n"; + public static final String ATTR_B562D = "b562d"; + + + /** + * 计算东北天的最近融合数据的加权平均, 刘畅20230725 copy 自 avgEND; id>20, 滤波参数6h 或 25h + */ + public double[] avgEND(String deviceId, GnssCalcData last, int a, int b) { + //double c = 0.5467; + double c = 0.5; + ArrayList gnssDeviceLocationRecords = new ArrayList<>(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("deviceid",deviceId); + wrapper.last("limit 20"); + + List GNSSDeviceLocationRecords = repository.selectList(wrapper); + gnssDeviceLocationRecords.addAll(GNSSDeviceLocationRecords); + + if (gnssDeviceLocationRecords.size() > 0) { + double sumE = last.getResulte(), sumE2 = last.getResulte(); + double sumN = last.getResultn(), sumN2 = last.getResultn(); + double sumD = last.getResultd(), sumD2 = last.getResultd(); + double[] lastLocation = {last.getResulte(), last.getResultn(), last.getResultd()}; + int count = 1, count2 = 1; + for (int i = 0; i < gnssDeviceLocationRecords.size(); i++) { + double[] findLocation = {gnssDeviceLocationRecords.get(i).getResulte(), gnssDeviceLocationRecords.get(i).getResultn(), gnssDeviceLocationRecords.get(i).getResultd()}; + if (disXY(lastLocation, findLocation) > 100) { + continue; + } + long time = System.currentTimeMillis() - gnssDeviceLocationRecords.get(i).getCreatetime().getTime(); + if (time < a) { + sumE += gnssDeviceLocationRecords.get(i).getResulte(); + sumN += gnssDeviceLocationRecords.get(i).getResultn(); + sumD += gnssDeviceLocationRecords.get(i).getResultd(); + count++; + } + if (time < b) { + sumE2 += gnssDeviceLocationRecords.get(i).getResulte(); + sumN2 += gnssDeviceLocationRecords.get(i).getResultn(); + sumD2 += gnssDeviceLocationRecords.get(i).getResultd(); + count2++; + } + + } + double e = sumE / count * c + sumE2 / count2 * (1 - c); + double n = sumN / count * c + sumN2 / count2 * (1 - c); + double d = sumD / count * c + sumD2 / count2 * (1 - c); + return new double[]{e, n, d}; + } else { + return new double[]{last.getResulte(), last.getResultn(), last.getResultd()}; + } + } + + + public static double disXY(double[] a, double[] b) { + return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)); + } + + private void sendDataToMq(GnssCalcData locationRecord) { + String message = GsonUtil.toJson(locationRecord); + rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_GNSS, RabbitmqConfig.QUEUE_GNSS_LOCATION_RECORD, message); + } + + @Override + public void saveSingleCalcData(D341LocationMessage message){ + GnssSingleCalcData data = new GnssSingleCalcData(); + data.setDeviceid(message.getId()); + data.setCreatetime(new Timestamp(System.currentTimeMillis())); + Tilt tilt = message.getTilt(); + data.setRoll(tilt.getRoll()); + data.setPitch(tilt.getPitch()); + data.setYaw(tilt.getYaw()); + data.setShock(tilt.getShock()); + double[] b562_loc = message.getB562_loc(); + if(b562_loc!=null) { + data.setB562e(b562_loc[0]); + data.setB562n(b562_loc[1]); + data.setB562d(b562_loc[2]); + } + singleCalcDataMapper.insert(data); + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/DataTypeUtil.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/DataTypeUtil.java new file mode 100644 index 00000000..766a47d5 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/DataTypeUtil.java @@ -0,0 +1,393 @@ +package com.imdroid.sideslope.util; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +/** + * @author Layton + * @date 2022/3/21 15:36 + */ +public class DataTypeUtil { + + public static byte[] intToByteLittle(int n) { + byte[] b = new byte[4]; + b[0] = (byte) (n & 0xff); + b[1] = (byte) (n >> 8 & 0xff); + b[2] = (byte) (n >> 16 & 0xff); + b[3] = (byte) (n >> 24 & 0xff); + return b; + } + + public static byte[] intToByteBig(int number) { + byte[] b = new byte[4]; + + b[0] = (byte) (number >> 24); + b[1] = (byte) (number >> 16); + b[2] = (byte) (number >> 8); + b[3] = (byte) number; + + return b; + } + + public static byte[] floatToByteLittle(float n) { + int fbit = Float.floatToIntBits(n); + return intToByteLittle(fbit); + } + + public static byte[] floatToByteBig(float n) { + int fbit = Float.floatToIntBits(n); + return intToByteBig(fbit); + } + + /** + * 将byte数组转换为long数据 (大端模式) + * + * @param data + * length为8的byte数组 + * @return + */ + public static long byteToLong(byte[] data) { + ByteBuffer buffer = ByteBuffer.allocate(8); + + buffer.put(data, 0, 8); + buffer.flip(); + + return buffer.getLong(); + } + + /** + * 将byte数组转换为long数据 (大端模式) + * + * @param data + * length为8的byte数组 + * @return + */ + public static long byteToLong(byte[] data, int offset) { + ByteBuffer buffer = ByteBuffer.allocate(8); + + buffer.put(data, offset, 8); + buffer.flip(); + + return buffer.getLong(); + } + + /** + * 将byte数组转为int数据 (大端模式) + * + * @param data + * length为4的byte数组 + * @return + */ + public static int byteToInt(byte[] data) { + ByteBuffer buffer = ByteBuffer.allocate(4); + + buffer.put(data, 0, 4); + buffer.flip(); + + return buffer.getInt(); + } + + /** + * 将byte数组转为int数据 (大端模式) + * + * @param data + * length为4的byte数组 + * @return + */ + public static int byteToInt(byte[] data, int offset) { + ByteBuffer buffer = ByteBuffer.allocate(4); + + buffer.put(data, offset, 4); + buffer.flip(); + + return buffer.getInt(); + } + + /** + * 将byte数组转为short数据 (大端模式) + * + * @param data + * length为2的byte数组 + * @return + */ + public static short byteToShort(byte[] data) { + ByteBuffer buffer = ByteBuffer.allocate(2); + + buffer.put(data, 0, 2); + buffer.flip(); + + return buffer.getShort(); + } + + /** + * 将byte数组转为float数据(大端模式) + * + * @param data + * length为4的byte数组 + * @return + */ + public static float bytesToFloat(byte[] data) { + int value = byteToInt(data); + return Float.intBitsToFloat(value); + } + + /** + * 将byte数组转为float数据(小端模式) + * + * @param data + * length为4的byte数组 + * @return + */ + public static float lowBytesToFloat(byte[] data) { + int len = data.length; + // 获得一个反的数组 + byte[] dest = new byte[len]; + + for (int i = 0; i < len; i++) { + dest[len - i - 1] = data[i]; + } + + int value = byteToInt(dest); + return Float.intBitsToFloat(value); + } + + /** + * byte数组大小端反转 + * + * @param bytes 数据 + */ + public static void bytesReverse(byte[] bytes) { + int half = bytes.length / 2; + for (int i = 0; i < half; i++) { + byte temp = bytes[i]; + bytes[i] = bytes[bytes.length - i - 1]; + bytes[bytes.length - i - 1] = temp; + } + } + + /** + * 将long转为byte数组 (大端模式) + * + * @param number + * @return + */ + public static byte[] longToByte(long number) { + byte[] b = new byte[8]; + + b[0] = (byte) (number >> 56); + b[1] = (byte) (number >> 48); + b[2] = (byte) (number >> 40); + b[3] = (byte) (number >> 32); + b[4] = (byte) (number >> 24); + b[5] = (byte) (number >> 16); + b[6] = (byte) (number >> 8); + b[7] = (byte) number; + + return b; + } + + /** + * 将short转为byte数组 (小端模式) + * + * @param number + * @return + */ + public static byte[] shortToByteLittle(short number) { + + byte[] src = new byte[2]; + src[1] = (byte) ((number >> 8) & 0xFF); + src[0] = (byte) (number & 0xFF); + return src; + } + + /** + * 将short转为byte数组 (大端模式) + * + * @param number + * @return + */ + public static byte[] shortToByteBig(short number) { + + byte[] src = new byte[2]; + src[0] = (byte) ((number >> 8) & 0xFF); + src[1] = (byte) (number & 0xFF); + return src; + } + + + public static short byteToShort(byte byte0, byte byte1) { + return (short) (((byte0 & 0xff) << 8) | (byte1 & 0xff)); + } + + /** + * 将byte转换为一个长度为8的byte数组,数组每个值代表bit + * + * @param b + * @return + */ + public static byte[] getBitArray(byte b) { + byte[] array = new byte[8]; + for (int i = 7; i >= 0; i--) { + array[i] = (byte) (b & 1); + b = (byte) (b >> 1); + } + return array; + } + + /** + * 把byte转为字符串的bit + * + * @param b + * @return + */ + public static String byteToBit(byte b) { + return "" + + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1) + + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1) + + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1) + + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1); + } + + /** + * bit 转换为byte + * + * @param byteStr 位字符串 + * @return + */ + public static byte bitToByte(String byteStr) { + int re, len; + if (null == byteStr) { + return 0; + } + len = byteStr.length(); + if (len != 4 && len != 8) { + return 0; + } + if (len == 8) {// 8 bit处理 + if (byteStr.charAt(0) == '0') {// 正数 + re = Integer.parseInt(byteStr, 2); + } else {// 负数 + re = Integer.parseInt(byteStr, 2) - 256; + } + } else {//4 bit处理 + re = Integer.parseInt(byteStr, 2); + } + return (byte) re; + } + + public static String getHexString(byte[] bs, int start, int end) { + StringBuilder stringBuilder = new StringBuilder(""); + if (bs == null || bs.length <= 0) { + return null; + } + for (int i = start; i < end; i++) { + int v = bs[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString(); + } + + + //bytes to string + public static String getHexString(byte[] bs) { + StringBuilder stringBuilder = new StringBuilder(""); + if (bs == null || bs.length <= 0) { + return null; + } + for (int i = 0; i < bs.length; i++) { + int v = bs[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString(); + } + + //Hex String to bytes + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || "".equals(hexString)) { + return null; + } + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + + private static byte charToByte(char c) { + return (byte) "0123456789ABCDEF".indexOf(c); + } + + public static String getString(byte[] bytes) { + return getString(bytes, "GBK"); + } + + public static String getUTFString(byte[] bytes) { + return new String(bytes); + } + + public static String getString(byte[] bytes, String charsetName) { + return new String(bytes, Charset.forName(charsetName)); + } + + /** + * Ascii转换为字符串 + * + * @param value + * @return + */ + public static String asciiToString(String value) { + StringBuilder sbu = new StringBuilder(); + String[] chars = value.split(","); + for (int i = 0; i < chars.length; i++) { + sbu.append((char) Integer.parseInt(chars[i])); + } + return sbu.toString(); + } + + /** + * 浮点转换为字节 (小端模式) + * + * @param f + * @return + */ + public static byte[] floatTobyteLittle(float f) { + + // 把float转换为byte[] + int fbit = Float.floatToIntBits(f); + + byte[] b = new byte[4]; + for (int i = 0; i < 4; i++) { + b[i] = (byte) (fbit >> (24 - i * 8)); + } + + // 翻转数组 + int len = b.length; + // 建立一个与源数组元素类型相同的数组 + byte[] dest = new byte[len]; + // 为了防止修改源数组,将源数组拷贝一份副本 + System.arraycopy(b, 0, dest, 0, len); + byte temp; + // 将顺位第i个与倒数第i个交换 + for (int i = 0; i < len / 2; ++i) { + temp = dest[i]; + dest[i] = dest[len - i - 1]; + dest[len - i - 1] = temp; + } + + return dest; + + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/GsonUtil.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/GsonUtil.java new file mode 100644 index 00000000..e127858e --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/GsonUtil.java @@ -0,0 +1,76 @@ +package com.imdroid.sideslope.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.lang.reflect.Type; + +/** + * @author Layton + * @date 2022/3/28 15:35 + */ +public class GsonUtil { + + private static final Gson gson = new Gson(); + + private static final Gson serializeNullGson = new GsonBuilder().serializeNulls().disableHtmlEscaping().create(); + + private static final Gson serializeExposeGson = new GsonBuilder().serializeNulls().excludeFieldsWithoutExposeAnnotation().create(); + + public static String toJsonSerializeNull(Object c) { + return serializeNullGson.toJson(c); + } + + public static String toJson(Object c) { + return gson.toJson(c); + } + + public static String toJsonExpose(Object c) { + return serializeExposeGson.toJson(c); + } + + public static T fromJson(String json, Class clz) { + return gson.fromJson(json, clz); + } + + public static T fromJson(String json, Type typeOfT) { + return gson.fromJson(json, typeOfT); + } + + public static String getValue(JsonObject jsonObject, String key) { + JsonElement element = jsonObject.has(key) ? jsonObject.get(key) : null; + if (element == null) { + return ""; + } + if (element.isJsonObject()) { + return element.getAsJsonObject().toString(); + } else if (element.isJsonNull()) { + return ""; + } else if (element.isJsonArray()) { + return element.getAsJsonArray().toString(); + } else { + if (element.getAsJsonPrimitive().isBoolean()) { + return element.getAsBoolean() ? "true" : "false"; + } else { + return element.getAsString(); + } + } + } + + public static Number getNumber(JsonElement element) { ; + if (element == null) { + return null; + } + if (element.isJsonNull()) { + return null; + } else { + try { + return element.getAsNumber(); + } catch (Exception e) { + return null; + } + } + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/HttpUtils.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/HttpUtils.java new file mode 100644 index 00000000..a6778445 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/HttpUtils.java @@ -0,0 +1,392 @@ +package com.imdroid.sideslope.util; + +import com.google.gson.JsonObject; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.*; +import org.apache.http.client.utils.HttpClientUtils; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.ssl.SSLContexts; +import org.apache.http.ssl.TrustStrategy; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + + +/** + * @author layton + * @date 2021/6/21 + */ +public class HttpUtils { + + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + public HttpUtils() { + } + + /** + * 多线程共享实例 + */ + private static final CloseableHttpClient httpClient; + + static { + SSLContext sslContext = createSSLContext(); + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); + // 注册http套接字工厂和https套接字工厂 + Registry socketFactoryRegistry = RegistryBuilder. create() + .register("http", PlainConnectionSocketFactory.INSTANCE) + .register("https", sslsf) + .build(); + // 连接池管理器 + PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + //连接池最大连接数 + connMgr.setMaxTotal(50); + //每个路由最大连接数,设置的过小,无法支持大并发 + connMgr.setDefaultMaxPerRoute(50); + //在从连接池获取连接时,连接不活跃多长时间后需要进行一次验证 + connMgr.setValidateAfterInactivity(5 * 1000); + // 请求参数配置管理器 + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(60000) + .setSocketTimeout(60000) + .setConnectionRequestTimeout(60000) + .build(); + // 获取httpClient客户端 + httpClient = HttpClients.custom() + .setConnectionManager(connMgr) + .setDefaultRequestConfig(requestConfig) + .build(); + } + + /** + * GET请求 + * + * @param url + * @return + */ + public static String getUrl(String url) { + return sendHttp(HttpMethod.GET, url, null, null); + } + + /** + * GET请求 + * + * @param url + * @return + */ + public static String getUrl(String url, Map param, Map header) { + return sendHttp(HttpMethod.GET, url, header, param); + } + + /** + * GET请求/带头部的信息 + * + * @param url + * @param header + * @return + */ + public static String getUrl(String url, Map header) { + return sendHttp(HttpMethod.GET, url, header, null); + } + + /** + * POST请求/无参数 + * + * @param url + * @return + */ + public static String postJson(String url) { + return postJson(url, null, null); + } + + /** + * POST请求/有参数 + * + * @param url + * @param param + * @return + */ + public static String postJson(String url, String param) { + return postJson(url, null, param); + } + + /** + * POST请求/有参数 + * + * @param url + * @param param + * @return + */ + public static String postJsonObj(String url, JsonObject param) { + return postJsonObj(url, null, param); + } + + /** + * POST请求/无参数带头部 + * + * @param url + * @param header + * @return + */ + public static String postJson(String url, Map header) { + return postJson(url, header, null); + } + + /** + * POST请求/有参数带头部 + * + * @param url + * @param header + * @param params + * @return + */ + public static String postJson(String url, Map header, String params) { + return sendHttp(HttpMethod.POST, url, header, params); + } + + /** + * POST请求/有参数带头部 + * + * @param url + * @param header + * @param params + * @return + */ + public static String postJsonObj(String url, Map header, JsonObject params) { + return sendHttp(HttpMethod.POST, url, header, params); + } + + + /** + * 从下载地址获取文件流(如果链接出现双斜杠,请用OKHttp) + * + * @param url + * @return + */ + public static ByteArrayOutputStream getDownloadFileStream(String url) { + String infoMessage = new StringBuilder().append("request getDownloadFileStream,url:").append(url).toString(); + log.info(infoMessage); + ByteArrayOutputStream byteOutStream = null; + try { + CloseableHttpResponse response = httpClient.execute(new HttpGet(url)); + log.info("getDownloadFileStream response status:{}", response.getStatusLine()); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_OK) { + //请求成功 + HttpEntity entity = response.getEntity(); + if (entity != null && entity.getContent() != null) { + //复制输入流 + byteOutStream = cloneInputStream(entity.getContent()); + } + } + HttpClientUtils.closeQuietly(response); + } catch (Exception e) { + log.error(infoMessage + " failure", e); + } + return byteOutStream; + } + + + /** + * 发送http请求(通用方法) + * + * @param httpMethod 请求方式(GET、POST、PUT、DELETE) + * @param url 请求路径 + * @param header 请求头 + * @param params 请求body(json数据) + * @return 响应文本 + */ + public static String sendHttp(HttpMethod httpMethod, String url, Map header, Object params) { + String infoMessage = new StringBuilder().append("request sendHttp,url:").append(url) + .append(",method:").append(httpMethod.name()).append(",header:") + .append(GsonUtil.toJson(header)).append(",param:").append(params).toString(); + if (log.isDebugEnabled()) { + log.debug(infoMessage); + } + //返回结果 + String result = null; + long beginTime = System.currentTimeMillis(); + try { + ContentType contentType = ContentType.APPLICATION_JSON.withCharset("UTF-8"); + HttpRequestBase request = buildHttpMethod(httpMethod, url); + if (Objects.nonNull(header) && !header.isEmpty()) { + for (Map.Entry entry : header.entrySet()) { + //打印头部信息 + if (log.isDebugEnabled()) { + log.debug(entry.getKey() + ":" + entry.getValue()); + } + request.setHeader(entry.getKey(), entry.getValue()); + } + } + if (params != null) { + if (HttpMethod.POST.equals(httpMethod) || HttpMethod.PUT.equals(httpMethod)) { + if (params instanceof JsonObject || params instanceof String) { + String jsonString = params.toString(); + if (jsonString != null && jsonString.length() > 0) { + ((HttpEntityEnclosingRequest) request).setEntity(new StringEntity(jsonString, contentType)); + } + } else { + Map paramsHashMap = (Map ) params; + List formparams = new ArrayList (); + for (String key : paramsHashMap.keySet()) { + formparams.add(new BasicNameValuePair(key, paramsHashMap.get(key))); + } + ((HttpEntityEnclosingRequest) request).setEntity(new UrlEncodedFormEntity(formparams, "UTF-8")); + } + } + } + CloseableHttpResponse response = httpClient.execute(request); + HttpEntity httpEntity = response.getEntity(); + if (log.isDebugEnabled()) { + log.debug("sendHttp response status:{}", response.getStatusLine()); + } + if (Objects.nonNull(httpEntity)) { + result = EntityUtils.toString(httpEntity, "UTF-8"); + if (log.isDebugEnabled()) { + log.debug("sendHttp response body:{}", result); + } + } + //关闭返回对象 + HttpClientUtils.closeQuietly(response); + } catch (Exception e) { + log.error(infoMessage + " failure", e); + } + long endTime = System.currentTimeMillis(); + if (log.isDebugEnabled()) { + log.debug("request sendHttp response time cost:" + (endTime - beginTime) + " ms"); + } + return result; + } + + /** + * 请求方法(全大些)GET POST PUT DELETE + */ + public enum HttpMethod { + GET, POST, PUT, DELETE + } + + /** + * 构建请求方法 + * + * @param method + * @param url + * @return + */ + public static HttpRequestBase buildHttpMethod(HttpMethod method, String url) { + if (HttpMethod.GET.equals(method)) { + return new HttpGet(url); + } else if (HttpMethod.POST.equals(method)) { + return new HttpPost(url); + } else if (HttpMethod.PUT.equals(method)) { + return new HttpPut(url); + } else if (HttpMethod.DELETE.equals(method)) { + return new HttpDelete(url); + } else { + return null; + } + } + + /** + * 配置证书 + * + * @return + */ + public static SSLContext createSSLContext() { + try { + //信任所有,支持导入ssl证书 + TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; + SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); + return sslContext; + } catch (Exception e) { + log.error("初始化ssl配置失败", e); + throw new RuntimeException("初始化ssl配置失败"); + } + } + + /** + * 复制文件流 + * + * @param input + * @return + */ + public static ByteArrayOutputStream cloneInputStream(InputStream input) { + try { + ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = input.read(buffer)) > -1) { + byteOutStream.write(buffer, 0, len); + } + byteOutStream.flush(); + return byteOutStream; + } catch (IOException e) { + log.warn("copy InputStream error,", e); + } + return null; + } + + /** + * 输入流转字节流 + * + * @param in + * @return + */ + public static byte[] inputStream2byte(InputStream in) { + ByteArrayOutputStream bos = null; + try { + bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = in.read(b)) != -1) { + bos.write(b, 0, n); + } + in.close(); + bos.close(); + byte[] buffer = bos.toByteArray(); + return buffer; + } catch (IOException e) { + log.warn("inputStream transfer byte error,", e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + log.error("clone inputStream error", e); + } + try { + if (bos != null) { + bos.close(); + } + } catch (IOException e) { + log.error("clone outputStream error", e); + } + } + return null; + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/NumberUtils.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/NumberUtils.java new file mode 100644 index 00000000..cb6f33e2 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/NumberUtils.java @@ -0,0 +1,32 @@ +package com.imdroid.sideslope.util; + +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * @author Layton + * @date 2023/2/19 20:17 + */ +public class NumberUtils { + + public static Double scaleTwo(String str) { + return BigDecimal.valueOf(Double.parseDouble(str)).setScale(2, RoundingMode.HALF_UP).doubleValue(); + } + + public static Double scaleTwo(Double value) { + return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).doubleValue(); + } + + public static Double scale(Double value, int scale) { + return BigDecimal.valueOf(value).setScale(scale, RoundingMode.HALF_UP).doubleValue(); + } + + public static String removeBrackets(String str) { + if (StringUtils.isEmpty(str)) { + return str; + } + return str.replaceAll("\\[", "").replaceAll("]", ""); + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/RtcmGgaUtil.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/RtcmGgaUtil.java new file mode 100644 index 00000000..c448fa69 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/RtcmGgaUtil.java @@ -0,0 +1,261 @@ +package com.imdroid.sideslope.util; + +import com.imdroid.sideslope.bd.ByteUtil; +import com.imdroid.sideslope.bd.Gga; + +import java.math.BigDecimal; + +import static java.lang.Math.*; + +public class RtcmGgaUtil { + + //gga样本:*后面跟的是校验和,其中76代表校验和,对$和*之间的数据(不包括这两个字符)按字节进行异或运算(二进制)的结果 + private static final String ggaExample = "$GNGGA,020850.50,2258.10508,N,11317.67958,E,4,12,0.74,3.9,M,-5.4,M,1.3,0000*76"; + + /** + * 获取rtcm数据类型 + * @param bytes + * @return + */ + public static int getType(byte[] bytes){ + String binaryStrFromByteArr = ByteUtil.getBinaryStrFromByteArr(bytes); + if(binaryStrFromByteArr.length() > 8 + 6 + 10 + 12){ + String substring = binaryStrFromByteArr.substring(8 + 6 + 10, 8 + 6 + 10 + 12); + int i = ByteUtil.binaryToInt(substring); + return i; + }else{ + return -1; + } + } + + public static String ggaMock(double lat, double lon){ + String originLat = getOriginLatLon(lat); + String originLon = getOriginLatLon(lon); + StringBuilder sb = new StringBuilder(ggaExample); + sb.replace(sb.indexOf(",N,")-10,sb.indexOf(",N,"),originLat); + sb.replace(sb.indexOf(",E,")-11,sb.indexOf(",E,"),originLon); + String substring = sb.substring(sb.indexOf("$") + 1, sb.indexOf("*")); + byte[] bytes = substring.getBytes(); + //校验位 + byte b = bytes[0]; + for (int i = 1; i < bytes.length; i++) { + b ^= bytes[i]; + } + sb.replace(sb.length()-2,sb.length(),ByteUtil.byteToHexString(b)); + return sb.toString(); + } + + public static String getGNGGAString(byte[] bytes){ + String hex = ByteUtil.bytesToHexString(bytes); + int start = hex.indexOf("24474e474741");//$GNGGA + int end = hex.indexOf("0d0a");//\r\n + if(start != -1 && end > start){ + String substring = hex.substring(start,end); + //System.out.println(new String(ByteUtil.hexStringTobyte(substring))); + return new String(ByteUtil.hexStringTobyte(substring)); + } + return ""; + } + + public static Gga getGga(String msg){ + try{ + String[] strings = msg.split(","); + double latitude = getLatLon(Double.parseDouble(strings[2])); + double longitude = getLatLon(Double.parseDouble(strings[4])); + double altitude = 100*(Double.parseDouble(strings[9]) + Double.parseDouble(strings[11])); + int status = Integer.parseInt(strings[6]); + return new Gga(latitude,longitude,altitude,status); + }catch (Exception e){ + return null; + } + } + + + /** + * 解析阉割版gga,为了那点流量... + * @param msg + * @return + */ + public static Gga getGga2(String msg){ + try{ + String[] split = msg.split(","); + double lat = getLatLon(Double.parseDouble(split[1])); + double lon = getLatLon(Double.parseDouble(split[3])); + double altitude = Double.parseDouble(split[5]); + return new Gga(lat,lon,altitude,0); + }catch (Exception e){ + return null; + } + } + + /** + * 解析阉割版gga,为了那点流量... + * @param msg + * @return + */ + public static Gga getGga3(String msg){ + try{ + String[] split = msg.split(","); + double lat = getLatLon(Double.parseDouble(split[1])); + double lon = getLatLon(Double.parseDouble(split[3])); + int status = Integer.parseInt(split[5]); + double altitude = Double.parseDouble(split[6]); + return new Gga(lat,lon,altitude,status); + }catch (Exception e){ + return null; + } + } + + + /** + * 求相对坐标 + * @param gps_info + * @param origin + * @return + */ + public static double[] ggaToXyz(Gga gps_info,Gga origin){ + return ggaToXyz(gps_info,origin,0); + } + + /** + * 求相对坐标 + * @param gps_info + * @param origin + * @param angle 与北偏角 + * @return + */ + public static double[] ggaToXyz(Gga gps_info,Gga origin, double angle){ + double Ea = 6378137 * 100; //赤道的半径,单位是cm + //cout << "Ea" << Ea << endl; + double Eb = 6356725 * 100; //极半径,单位是cm + double Db = 39940638; //极周长,单位是cm,如果直接 39940538*100 double类型会溢出,所以把*100放到 dN 的计算式中 + //cout << "Db=" << Db << endl; + double R = Eb + (Ea - Eb) * (90 - origin.getLatitude()) / 90; + double pD = R * 2 * PI * cos(origin.getLatitude() * PI / 180); + double dE = pD * (gps_info.getLongitude() - origin.getLongitude()) / 360; //计算在正东方向上的位移 + double dN = Db * (gps_info.getLatitude() - origin.getLatitude()) / 360 * 100; //计算在正北方向上的位移 + //接下来根据场地的朝向来把朝东朝北的偏移转化成x方向和y方向的位移 + //这个位移也就是车辆在场地中的x坐标和y坐标 + double x = dE * cos(angle * PI / 180) - dN * sin(angle * PI / 180); + double y = dN * cos(angle * PI / 180) + dE * sin(angle * PI / 180); + double z = gps_info.getAltitude() - origin.getAltitude(); + return new double[]{x,y,z}; + } + + //一度为60分 + public static double getLatLon(Double location) { + if (location != 0.0) { + //int head = Integer.parseInt(String.valueOf(location).substring(0, 2)); + int head = (int)(location/100); + // System.out.println(head); + return head + (location / 100 - head) * 10 / 6; + } + return 0.0; + } + + //逆向转化 + public static String getOriginLatLon(double latlon){ + double result = 100*((int)latlon) + (latlon-(int)latlon)*6/10*100; + BigDecimal bd = new BigDecimal(result); + result = bd.setScale(5,BigDecimal.ROUND_HALF_EVEN).doubleValue(); + return StringUtil.roundByScale(result, 5); + } + + /** + * 求航向角 + * @param backLat + * @param backLon + * @param frontLat + * @param frontLon + * @return + */ + public static double latLonToAngle(double backLat, double backLon, double frontLat, double frontLon){ + double[] doubles = ggaToXyz(new Gga(frontLat, frontLon), new Gga(backLat, backLon)); + double angle = Math.atan2(doubles[0],doubles[1]) * 180/ Math.PI; + angle = (angle + 360) % 360; + return angle; + } + + /** + * 正北 + * ^ ^ y轴 + * \ | + * \ +-----------+ (x,y) + * \ | | + * \ | | + * \| | + * -------+-----------+----> + * origin| x轴 + * | + * + * 求某一个坐标的经纬度 + * @param x 单位厘米 + * @param y + * @param origin 参考点的经纬度 + * @param angle_from_north y轴与正北夹角 + * @return + */ + public static Gga xyToGga(double x, double y, Gga origin, double angle_from_north){ + double latitude1 = -x * sin(angle_from_north * PI /180) + + y * cos(angle_from_north * PI /180); + double longitude1 = x / cos(angle_from_north * PI /180) + + (y - (x * tan(angle_from_north * PI /180))) + * sin(angle_from_north * PI /180); + + Gga ggaInfo1 = new Gga(); + ggaInfo1.setLatitude(origin.getLatitude() + 0.000001); + ggaInfo1.setLongitude(origin.getLongitude()); + Gga ggaInfo2 = new Gga(); + ggaInfo2.setLatitude(origin.getLatitude()); + ggaInfo2.setLongitude(origin.getLongitude() + 0.000001); + + double[] location1 = ggaToXyz(ggaInfo1,origin); + double[] location2 = ggaToXyz(ggaInfo2,origin); + + double a = location1[1]; + double b = location2[0]; + + double latitude = latitude1 / a * 0.000001; + double longitude = longitude1 / b * 0.000001; + + Gga ggaInfo = new Gga(); + ggaInfo.setLatitude(origin.getLatitude() + latitude); + ggaInfo.setLongitude(origin.getLongitude() + longitude); + return ggaInfo; + } + + /** + * 计算两点之间距离,10厘米以下也能计算,精度更高,单位厘米, + */ + public static double getDistance2(double latitude, double longitude, double nowLatitude, double nowLongitude) { + Gga gga1 = new Gga(latitude, longitude); + Gga gga2 = new Gga(nowLatitude, nowLongitude); + double[] doubles = ggaToXyz(gga1, gga2); + return Math.sqrt(Math.pow(doubles[0],2) + Math.pow(doubles[1],2)); + } + + /** + * 计算两点之间距离,单位米 + */ + public static double getDistance(double sourceLat, double sourceLog, double desLat, double desLog) { + //转为弧度 + double lat1 = (Math.PI / 180) * sourceLat; + double lat2 = (Math.PI / 180) * desLat; + + double lon1 = (Math.PI / 180) * sourceLog; + double lon2 = (Math.PI / 180) * desLog; + + //地球半径 + double R = 6371.004; + + //两点间距离 km,如果想要米的话,结果*1000 + double d = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * R; + + if (Double.isNaN(d * 1000)) { + return 0.0; + } + + return d * 1000; + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/StringUtil.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/StringUtil.java new file mode 100644 index 00000000..0412d177 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/StringUtil.java @@ -0,0 +1,47 @@ +package com.imdroid.sideslope.util; + +import java.text.DecimalFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StringUtil { + + /** + * @param data 指定字符串 + * @param str 需要定位的特殊字符或者字符串 + * @param num 第n次出现 + * @return 第n次出现的位置索引 + */ + public static int getIndexOf(String data,String str,int num){ + Pattern pattern = Pattern.compile(str); + Matcher findMatcher = pattern.matcher(data); + //标记遍历字符串的位置 + int indexNum=0; + while(findMatcher.find()) { + indexNum++; + if(indexNum==num){ + return findMatcher.start(); + } + } + //System.out.println("字符或者字符串"+str+"第"+num+"次出现的位置为:"+findMatcher.start()); + return -1; + } + + /** + * 保留小数点多少位,不足补零 + * @param v + * @param scale 大于等于0 + * @return + */ + public static String roundByScale(double v, int scale) { + if(scale == 0){ + return new DecimalFormat("0").format(v); + } + String formatStr = "0."; + for(int i=0;i mExecutorServiceMap = new HashMap<>(); + private static final Object lock = new Object(); + + private static final class FixedThreadPoolHolder { + //固定线程池 + static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); + } + + public static ExecutorService getFixedThreadPool() { + return FixedThreadPoolHolder.fixedThreadPool; + } + + private static final class ScheduledThreadPoolHolder { + //定时线程池 + static final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4); + } + + public static ScheduledExecutorService getScheduledThreadPool() { + return ScheduledThreadPoolHolder.scheduledThreadPool; + } + + + public static ExecutorService getSingleThreadPool(String name) { + ExecutorService singleThreadExecutor = mExecutorServiceMap.get(name); + if (singleThreadExecutor == null) { + synchronized (lock) { + singleThreadExecutor = mExecutorServiceMap.get(name); + if (singleThreadExecutor == null) { + singleThreadExecutor = Executors.newSingleThreadExecutor(); + mExecutorServiceMap.put(name, singleThreadExecutor); + } + } + } + return singleThreadExecutor; + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/WrongMessageRecorder.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/WrongMessageRecorder.java new file mode 100644 index 00000000..36af2696 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/util/WrongMessageRecorder.java @@ -0,0 +1,43 @@ +package com.imdroid.sideslope.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.file.FileAppender; + +import java.io.File; + +/** + * 设备发送过来的错误消息记录器 + * 错误消息:长度字段与实际消息体长度不匹配 + * + * @author LiGang + * @date 2023/4/8 11:15 + */ +public class WrongMessageRecorder { + + private FileAppender appender; + + public static final WrongMessageRecorder INSTANCE = new WrongMessageRecorder(); + + private WrongMessageRecorder() { + try { + String filePath = "/home/devop/runtime/sideslope_wrong_message_" + DateUtil.today() + ".log"; + File file = new File(filePath); + if (!file.exists()) { + file.createNewFile(); + } + appender = new FileAppender(file, 2, true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void append(String message) { + try { + appender.append(DateUtil.now() + ": " + message); + appender.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/ApiController.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/ApiController.java new file mode 100644 index 00000000..7f79acb7 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/ApiController.java @@ -0,0 +1,107 @@ +package com.imdroid.sideslope.web; + +import com.imdroid.sideslope.calc.GNSSCalcService; +import com.imdroid.sideslope.server.DeviceChannel; +import com.imdroid.sideslope.server.OnlineChannels; +import com.imdroid.sideslope.util.DataTypeUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * @author LiGang + * @date 2023/9/24 10:01 + */ +@RestController +public class ApiController { + + private final Logger logger = LoggerFactory.getLogger(ApiController.class); + + @Autowired + private GNSSCalcService gnssCalcService; + + @RequestMapping(value = "/config") + public HttpResp config(String deviceId, String configuration) { + Map status = new HashMap<>(); + HttpResp resp = new HttpResp(); + OnlineChannels.INSTANCE + .get(deviceId) + .filter(DeviceChannel::isOnline) + .ifPresent(x -> { + status.put("status", "Online"); + status.put("lastUpdate", x.getLastTime()); + // send command + ByteBuf buf = Unpooled.buffer(); + byte[] data = getBinaryData(ConfigDataTypeEnum.JSON, configuration); + logger.info("send command:{}", configuration); + buf.writeBytes(data); + x.writeAndFlush(buf); + }); + if (status.isEmpty()) { + status.put("status", "Offline"); + resp.setResponseCode("-10001"); + resp.setResponseMessage("Offline."); + } else { + resp.setResponseMessage("Command sent."); + } + resp.setResponseObject(status); + return resp; + } + + @RequestMapping(value = "/gnssconfig") + public HttpResp gnssConfig(String deviceId, String configuration) { + Map status = new HashMap<>(); + HttpResp resp = new HttpResp(); + OnlineChannels.INSTANCE + .get(deviceId) + .filter(DeviceChannel::isOnline) + .ifPresent(x -> { + status.put("status", "Online"); + status.put("lastUpdate", x.getLastTime()); + // send command + ByteBuf buf = Unpooled.buffer(); + byte[] data = getBinaryData(ConfigDataTypeEnum.HEX, configuration); + logger.info("send command:{}", configuration); + buf.writeBytes(data); + x.writeAndFlush(buf); + }); + if (status.isEmpty()) { + status.put("status", "Offline"); + resp.setResponseCode("-10001"); + resp.setResponseMessage("Offline."); + } else { + resp.setResponseMessage("Command sent."); + } + resp.setResponseObject(status); + return resp; + } + + @RequestMapping(value = "/clean-tilt") + public HttpResp config(String deviceId) { + // 清空指定设备的惯导值 + gnssCalcService.cleanTiltByDeviceId(deviceId); + HttpResp resp = new HttpResp(); + resp.setResponseMessage("succeed"); + return resp; + } + + private static byte[] getBinaryData(ConfigDataTypeEnum dataTypeEnum, String text) { + if (dataTypeEnum == ConfigDataTypeEnum.HEX) { + return DataTypeUtil.hexStringToBytes(text); + } else if (dataTypeEnum == ConfigDataTypeEnum.JSON) { + String content = URLDecoder.decode(text); + return content.getBytes(StandardCharsets.UTF_8); + } else { + return text.getBytes(StandardCharsets.UTF_8); + } + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/ConfigDataTypeEnum.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/ConfigDataTypeEnum.java new file mode 100644 index 00000000..09b302cd --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/ConfigDataTypeEnum.java @@ -0,0 +1,10 @@ +package com.imdroid.sideslope.web; + +/** + * @author Layton + * @date 2023/2/13 19:20 + */ +public enum ConfigDataTypeEnum { + + HEX, JSON; +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/HttpResp.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/HttpResp.java new file mode 100644 index 00000000..4cbeb83c --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/web/HttpResp.java @@ -0,0 +1,49 @@ +package com.imdroid.sideslope.web; + +public class HttpResp { + private String responseCode = "10000"; + private String responseMessage; + private String responseType; + private int rows; + private T responseObject; + + public String getResponseCode() { + return responseCode; + } + + public void setResponseCode(String responseCode) { + this.responseCode = responseCode; + } + + public String getResponseMessage() { + return responseMessage; + } + + public void setResponseMessage(String responseMessage) { + this.responseMessage = responseMessage; + } + + public String getResponseType() { + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } + + public int getRows() { + return rows; + } + + public void setRows(int rows) { + this.rows = rows; + } + + public T getResponseObject() { + return responseObject; + } + + public void setResponseObject(T responseObject) { + this.responseObject = responseObject; + } +} diff --git a/sec-beidou-rtcm/src/main/resources/application.properties b/sec-beidou-rtcm/src/main/resources/application.properties new file mode 100644 index 00000000..6620ce2a --- /dev/null +++ b/sec-beidou-rtcm/src/main/resources/application.properties @@ -0,0 +1,29 @@ +server.port=9904 +server.servlet.context-path=/gnss + +spring.application.name=bis-gnss +spring.application.build=20230924 + +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/bis-device?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai +spring.datasource.username = root +spring.datasource.password = +spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver + +spring.jackson.dateFormat = yyyy-MM-dd HH:mm:ss +spring.jackson.time-zone = GMT+8 + +# rabbitmq +spring.rabbitmq.host=127.0.0.1 +spring.rabbitmq.port=5672 +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtualHost=/ + +netty.port=9903 + +app.format.date = yyyy-MM-dd +app.format.time = HH:mm:ss +app.format.datetime = yyyy-MM-dd HH:mm:ss \ No newline at end of file diff --git a/sec-beidou-rtcm/src/main/resources/logback.xml b/sec-beidou-rtcm/src/main/resources/logback.xml new file mode 100644 index 00000000..1742b9e7 --- /dev/null +++ b/sec-beidou-rtcm/src/main/resources/logback.xml @@ -0,0 +1,27 @@ + + + \ No newline at end of file diff --git a/sec-beidou-rtcm/src/test/java/UBXTest.java b/sec-beidou-rtcm/src/test/java/UBXTest.java new file mode 100644 index 00000000..ec80151e --- /dev/null +++ b/sec-beidou-rtcm/src/test/java/UBXTest.java @@ -0,0 +1,48 @@ +import com.imdroid.sideslope.bd.FocusCalculator; +import com.imdroid.sideslope.bd.UBXUtil; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class UBXTest { + + public static void main(String[] args) throws Exception { + test(); + } + + public static void test() throws IOException { + //读取本地数据模拟 + /* FileInputStream fileInputStream = new FileInputStream("2023-02-02-151826.txt"); + int mSize = 0; + int temp; + List+ + + ++ +${LOG_PATTERN} ++ + +${LOG_HOME}/sideslopertcm.log ++ + +${LOG_HOME}/sideslopertcm.%d{yyyy-MM-dd}.%i.log +10MB +20 ++ +${LOG_PATTERN} ++ ++ + mList = new ArrayList<>(); + FocusCalculator focusCalculator = new FocusCalculator(150,null,null); + while ((temp = fileInputStream.read()) != -1){ + mList.add((byte)temp); //添加数据 + mSize++; + if (mList.size() >= 2 && mList.get(mSize - 2) == '\r' && mList.get(mSize - 1) == '\n') { + byte[] bytes = new byte[mList.size() - 2]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = mList.get(i); + } + //提取得到b562数据 + double[] doubles = UBXUtil.dataAnalysis(bytes,16); + //计算到单次相对位置xyz并记录 + System.out.println(Arrays.toString(doubles)); + focusCalculator.addXyz(doubles); + mList.clear(); + mSize = 0; + } + } + //融合 + double[] result = focusCalculator.resultB562(null); + if(result != null){ + System.out.println("result:"+ Arrays.toString(result)); + } + fileInputStream.close();*/ + } + +} diff --git a/sec-beidou/pom.xml b/sec-beidou/pom.xml new file mode 100644 index 00000000..39b7ac37 --- /dev/null +++ b/sec-beidou/pom.xml @@ -0,0 +1,162 @@ + + + diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/BeidouApplication.java b/sec-beidou/src/main/java/com/imdroid/beidou/BeidouApplication.java new file mode 100644 index 00000000..883e04c1 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/BeidouApplication.java @@ -0,0 +1,15 @@ +package com.imdroid.beidou; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Configuration; + +@SpringBootApplication(scanBasePackages = {"com.imdroid"}) +@MapperScan({"com.imdroid.secapi","com.imdroid.beidou.entity"}) +public class BeidouApplication { + + public static void main(String[] args) { + SpringApplication.run(BeidouApplication.class, args); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/GlobalExceptionHandler.java b/sec-beidou/src/main/java/com/imdroid/beidou/GlobalExceptionHandler.java new file mode 100644 index 00000000..0e719d28 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/GlobalExceptionHandler.java @@ -0,0 +1,21 @@ +package com.imdroid.beidou; + +import com.imdroid.beidou.common.HttpResult; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + + + @ExceptionHandler(Exception.class) + @ResponseBody + public HttpResult handleException(Exception e) { + log.error("全局捕获异常:", e); + return HttpResult.fail(e.getMessage()); + } + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/auth/AuthInterceptor.java b/sec-beidou/src/main/java/com/imdroid/beidou/auth/AuthInterceptor.java new file mode 100644 index 00000000..1c8a6e3d --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/auth/AuthInterceptor.java @@ -0,0 +1,37 @@ +package com.imdroid.beidou.auth; + +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 登录拦截器 + * + * @author LiGang + */ +@Component +public class AuthInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String username = SessionUtils.getCurrentUser(request); + if (!StringUtils.isEmpty(username)) { + return true; + } + response.sendRedirect("/login"); + return false; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/auth/SessionUtils.java b/sec-beidou/src/main/java/com/imdroid/beidou/auth/SessionUtils.java new file mode 100644 index 00000000..f9d03083 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/auth/SessionUtils.java @@ -0,0 +1,37 @@ +package com.imdroid.beidou.auth; + +import com.imdroid.beidou.entity.Tenant; +import com.imdroid.beidou.entity.User; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +/** + * session 工具类 + * + * @author LiGang + */ +public class SessionUtils { + + public static final String SESSION_CURRENT_USER = "login_user"; + + public static String getCurrentUser(HttpServletRequest request) { + return (String) request.getSession().getAttribute(SESSION_CURRENT_USER); + } + + public static void setCurrentUser(HttpServletRequest request, User user, Tenant tenant) { + HttpSession session = request.getSession(); + session.setAttribute(SESSION_CURRENT_USER, user.getName()); + session.setAttribute("tenant_id", user.getTenant_id()); + session.setAttribute("tenant_name", tenant.getName()); + session.setAttribute("role", user.getRole()); + } + + public static Integer getTenantId(HttpServletRequest request) { + return (Integer) request.getSession().getAttribute("tenant_id"); + } + + public static String getRole(HttpServletRequest request) { + return (String) request.getSession().getAttribute("role"); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/auth/WebMvcConfig.java b/sec-beidou/src/main/java/com/imdroid/beidou/auth/WebMvcConfig.java new file mode 100644 index 00000000..bf198ea5 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/auth/WebMvcConfig.java @@ -0,0 +1,26 @@ +package com.imdroid.beidou.auth; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 登录拦截器配置 + * + * @author LiGang + */ + +@Configuration +@RequiredArgsConstructor +public class WebMvcConfig implements WebMvcConfigurer { + + private final AuthInterceptor authInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authInterceptor) + .addPathPatterns("/**") + .excludePathPatterns("/**/*.js","/**/*.css","/**/*.jpg","/**/*.png", "/do_login", "/mini-register", "/login"); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/common/HttpResult.java b/sec-beidou/src/main/java/com/imdroid/beidou/common/HttpResult.java new file mode 100644 index 00000000..150e7936 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/common/HttpResult.java @@ -0,0 +1,47 @@ +package com.imdroid.beidou.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class HttpResult implements Serializable { + public static int HTTP_RSP_OK = 0; + public static int HTTP_RSP_FAILED = 1; + public static int HTTP_RSP_USER_NOT_EXIST = 2; + int code; + String msg; + Object data; + + public static String result(int code, String msg) { + HttpResult rsp = new HttpResult(); + rsp.code = code; + rsp.msg = msg; + return JSONObject.toJSONString(rsp); + } + + public static String ok() { + return result(HTTP_RSP_OK, "ok"); + } + + public static String failed() { + return result(HTTP_RSP_FAILED, "failed"); + } + + public static HttpResult success(Object data) { + return new HttpResult(HTTP_RSP_OK, "ok", data); + } + + public static HttpResult fail(String msg) { + return new HttpResult(HTTP_RSP_FAILED, msg, null); + } + + public static HttpResult fail(int code, String msg) { + return new HttpResult(code, msg, null); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/common/Role.java b/sec-beidou/src/main/java/com/imdroid/beidou/common/Role.java new file mode 100644 index 00000000..c4455859 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/common/Role.java @@ -0,0 +1,15 @@ +package com.imdroid.beidou.common; + +/**************************************** + * 1)系统管理员:ADMIN,所有权限,并且可以设置自己的企业ID + * 2)企业管理员:MANAGER,本企业内数据的查改增删、增加和删除本企业的账号、查看操作日志。 + * 不能看设备消息和设置设备数据LOG + * 3)普通用户:USER,本企业内的数据查看和设备配置 + * 用户角色以字节传到页面,bit1:admin;bit2:manager;bit3:user + */ + +public class Role { + public static final String ADMIN = "ADMIN"; + public static final String MANAGER = "MANAGER"; + public static final String USER = "USER"; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/config/AliyunOssProperties.java b/sec-beidou/src/main/java/com/imdroid/beidou/config/AliyunOssProperties.java new file mode 100644 index 00000000..4dc88841 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/config/AliyunOssProperties.java @@ -0,0 +1,28 @@ +package com.imdroid.beidou.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 阿里云oss配置类 + * + * @author LiGang + */ +@Setter +@Getter +@Configuration +@ConfigurationProperties(prefix = "aliyun.oss") +public class AliyunOssProperties { + + private String endpoint; + + private String accessKey; + + private String accessSecret; + + private String bucket; + + private String publicReadUrl; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/config/WxMiniProperties.java b/sec-beidou/src/main/java/com/imdroid/beidou/config/WxMiniProperties.java new file mode 100644 index 00000000..e7117b4f --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/config/WxMiniProperties.java @@ -0,0 +1,36 @@ +package com.imdroid.beidou.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 微信小程序配置 + * + * @author LiGang + */ +@Configuration +@ConfigurationProperties("app.bis") +public class WxMiniProperties { + + private String appid; + + private String secret; + + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/BasicController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/BasicController.java new file mode 100644 index 00000000..a0de0f88 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/BasicController.java @@ -0,0 +1,22 @@ +package com.imdroid.beidou.controller; + +import org.springframework.ui.Model; + +import javax.servlet.http.HttpSession; + +/** + * 利用HTTP Session保存会话期的用户信息,并发送到页面,用于显示控制 + */ +public class BasicController { + public static int QUERY_ALL = -1; + + public void initModel(Model m, HttpSession session) + { + String role = (String) session.getAttribute("role"); + int tenant_id = (int) session.getAttribute("tenant_id"); + m.addAttribute("login_user", session.getAttribute("login_user")); + m.addAttribute("role", role); + m.addAttribute("tenant_id", tenant_id); + m.addAttribute("tenant_name", session.getAttribute("tenant_name")); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssDeviceController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssDeviceController.java new file mode 100644 index 00000000..824bef31 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssDeviceController.java @@ -0,0 +1,189 @@ +package com.imdroid.beidou.controller; + +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.github.pagehelper.StringUtil; +import com.imdroid.beidou.common.HttpResult; +import com.imdroid.beidou.data.vo.device.DeviceInstallVO; +import com.imdroid.beidou.data.vo.device.DeviceStatusVO; +import com.imdroid.beidou.entity.*; +import com.imdroid.secapi.dto.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; + +import javax.servlet.http.HttpSession; +import java.sql.Timestamp; +import java.util.List; + +@Controller +public class GnssDeviceController extends BasicController{ + @Autowired + GnssGroupMapper gnssGroupMapper; + @Autowired + GnssGroupCalcMapper gnssGroupCalcMapper; + @Autowired + GnssGroupFwdMapper gnssGroupFwdMapper; + @Autowired + GnssDeviceMapper gnssDeviceMapper; + @Autowired + TenantMapper tenantMapper; + @Autowired + private GnssStatusMapper gnssStatusMapper; + + /**** 推送页面 *****/ + @RequestMapping("/page/gnss_dev_cfg") + public String gnssDevCfg(Model m, HttpSession session)throws Exception { + initModel(m, session); + + return "/page/gnss_dev_cfg"; + } + + @RequestMapping("/page/table/gnss_add_dev") + public String gnssUpdateDev(Model m)throws Exception { + //以下用于下拉框数据 + List4.0.0 + ++ + +com.imdroid +security-monitor +1.0-SNAPSHOT +com.imdroid +sec-beidou +0.0.1-SNAPSHOT +beidou +beidou + ++ + +8 ++ + + + + + ++ +org.springframework.boot +spring-boot-starter-thymeleaf ++ +org.springframework.boot +spring-boot-starter-web ++ + +org.thymeleaf.extras +thymeleaf-extras-springsecurity5 ++ + +com.github.yulichang +mybatis-plus-join-boot-starter +1.4.3 ++ +com.baomidou +mybatis-plus-boot-starter +3.5.2 ++ +mysql +mysql-connector-java +8.0.24 ++ +org.springframework.boot +spring-boot-configuration-processor +true ++ +org.projectlombok +lombok +true ++ +org.springframework.boot +spring-boot-starter-test +test ++ +org.springframework.security +spring-security-test +test ++ +io.netty +netty-all +4.1.85.Final ++ +com.alibaba +fastjson +1.2.76 ++ +com.github.pagehelper +pagehelper +4.1.6 ++ +io.jsonwebtoken +jjwt +0.9.1 ++ + + +com.google.code.gson +gson +2.9.1 ++ + + +org.apache.httpcomponents +httpclient +4.5.7 ++ + + +jakarta.validation +jakarta.validation-api +2.0.2 ++ + +com.aliyun.oss +aliyun-sdk-oss +3.10.2 ++ + +com.imdroid +sec-api +1.0-SNAPSHOT ++ + ++ ++ +org.springframework.boot +spring-boot-maven-plugin ++ ++ ++ +org.projectlombok +lombok ++ + ++ +central +ali-mirror +https://maven.aliyun.com/repository/central ++ +true ++ +true +gnssGroups = gnssGroupMapper.selectList(null); + List gnssGroupCalcs = gnssGroupCalcMapper.selectList(null); + List gnssGroupFwds = gnssGroupFwdMapper.selectList(null); + List tenants = tenantMapper.selectList(null); + + m.addAttribute("tenant_list", tenants); + m.addAttribute("gnss_group_list", gnssGroups); + m.addAttribute("gnss_group_calc_list", gnssGroupCalcs); + m.addAttribute("gnss_group_fwd_list", gnssGroupFwds); + + return "/page/table/gnss_add_dev"; + } + + /**** 推送数据 *****/ + @RequestMapping("/gnss/device/list") + @ResponseBody + public JSONObject list(HttpSession session, int page, int limit, String searchParams) { + PageHelper.startPage(page, limit); + QueryWrapper queryWrapper = new QueryWrapper<>(); + + // 条件查询 + if(searchParams != null) { + JSONObject search = (JSONObject) JSONObject.parse(searchParams); + //设备号 + String deviceid = search.getString("deviceid"); + if (StringUtil.isNotEmpty(deviceid)) { + queryWrapper.like("deviceid", deviceid); + } + //父设备号 + String parentid = search.getString("parentid"); + if (StringUtil.isNotEmpty(parentid)) { + queryWrapper.like("parentid", parentid); + } + //设备类型 + Integer devicetype = search.getInteger("devicetype"); + if (devicetype != null && devicetype != QUERY_ALL) { + queryWrapper.eq("devicetype", devicetype); + } + } + + List cs = gnssDeviceMapper.selectList(queryWrapper); + PageInfo pageInfo = new PageInfo<>(cs); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 0); + jsonObject.put("msg", ""); + jsonObject.put("count", pageInfo.getTotal()); + jsonObject.put("data", pageInfo.getList()); + return jsonObject; + } + + @PostMapping("/gnss/device/update") + @ResponseBody + public String update(HttpSession session, @RequestBody JSONObject object) throws Exception { + // 从请求参数中创建对象 + GnssDevice device = JSONObject.toJavaObject(object,GnssDevice.class); + QueryWrapper tenantQueryWrapper = new QueryWrapper<>(); + tenantQueryWrapper.eq("name", device.getTenantname()); + Tenant tenant = tenantMapper.selectOne(tenantQueryWrapper); + if(tenant==null) return HttpResult.result(2, "invalid tenant"); + device.setTenantid(tenant.getId()); + device.setUpdatetime(new Timestamp(System.currentTimeMillis())); + device.setUpdateuser((String) session.getAttribute("login_user")); + + // 检测该对象是否已存在 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("deviceid",device.getDeviceid()); + GnssDevice old_device = gnssDeviceMapper.selectOne(wrapper); + //新增或更新 + int num = 0; + if(null != old_device) { + device.setId(old_device.getId()); + device.setCreateuser(old_device.getCreateuser()); + device.setCreatetime(old_device.getCreatetime()); + num = gnssDeviceMapper.updateById(device); + } + else{ + device.setCreatetime(new Timestamp(System.currentTimeMillis())); + device.setCreateuser((String) session.getAttribute("login_user")); + num = gnssDeviceMapper.insert(device); //id自增 + } + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } + + @PostMapping("/gnss/device/delete") + @ResponseBody + public String delete(@RequestParam String del_id) throws Exception { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("deviceid",del_id); + int num = gnssDeviceMapper.delete(wrapper); + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } + + /** + * 设备现场安装 + * + * @param deviceInstallVO 设备安装信息 + * @return HttpResult + * @throws Exception + */ + @PostMapping("/gnss/device/install") + @ResponseBody + public HttpResult install(@Validated DeviceInstallVO deviceInstallVO) throws Exception { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("deviceid",deviceInstallVO.getDeviceId()); + GnssDevice gnssDevice = gnssDeviceMapper.selectOne(wrapper); + if (gnssDevice == null) { + return HttpResult.fail(""); + } + GnssDevice tempDevice = new GnssDevice(); + tempDevice.setId(gnssDevice.getId()); + //安装位置通过GNSS坐标自动获取 + //tempDevice.setLocation(deviceInstallVO.getLocation()); + tempDevice.setPictures(deviceInstallVO.getPictures()); + gnssDeviceMapper.updateById(tempDevice); + + return HttpResult.success(null); + } + + /** + * 根据主键id查找设备信息 + * + * @param id 主键id + * @return 设备信息 DeviceStatusVO + */ + @PostMapping("/gnss/device/status") + @ResponseBody + public HttpResult findById(Long id) { + GnssDevice gnssDevice = gnssDeviceMapper.selectById(id); + if (gnssDevice == null) { + return HttpResult.fail(""); + } + GnssStatusJoin gnssStatus = gnssStatusMapper.queryByDeviceId(gnssDevice.getDeviceid()); + DeviceStatusVO deviceStatusVO = new DeviceStatusVO(gnssDevice, gnssStatus); + return HttpResult.success(deviceStatusVO); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssGroupController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssGroupController.java new file mode 100644 index 00000000..ae4e48a3 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssGroupController.java @@ -0,0 +1,168 @@ +package com.imdroid.beidou.controller; + +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.imdroid.beidou.common.HttpResult; +import com.imdroid.beidou.entity.*; +import com.imdroid.secapi.dto.GnssGroup; +import com.imdroid.secapi.dto.GnssGroupMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Controller +public class GnssGroupController { + @Autowired + GnssGroupMapper gnssGroupMapper; + @Autowired + GnssGroupCalcMapper gnssGroupCalcMapper; + @Autowired + GnssGroupFwdMapper gnssGroupFwdMapper; + + /********* 推送页面 *********/ + @RequestMapping("/page/table/gnss_add_group") + public String gnssAddGroup()throws Exception { + return "/page/table/gnss_add_group"; + } + + @RequestMapping("/page/table/gnss_add_group_calc") + public String gnssAddCalcGroup()throws Exception { + return "/page/table/gnss_add_group_calc"; + } + + @RequestMapping("/page/table/gnss_add_group_fwd") + public String gnssAddPushGroup()throws Exception { + return "/page/table/gnss_add_group_fwd"; + } + + @RequestMapping("/page/gnss_group_cfg") + public String gnssGroupCfg()throws Exception { + return "/page/gnss_group_cfg"; + } + + /********* 基本参数组 *********/ + @RequestMapping("/gnss/group/list") + @ResponseBody + public JSONObject list(int page, int limit) { + PageHelper.startPage(page, limit); + List cs = gnssGroupMapper.selectList(null); + PageInfo pageInfo = new PageInfo<>(cs); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 0); + jsonObject.put("msg", ""); + jsonObject.put("count", pageInfo.getTotal()); + jsonObject.put("data", pageInfo.getList()); + return jsonObject; + } + + @PostMapping("/gnss/group/update") + @ResponseBody + public String update(@RequestBody JSONObject object) throws Exception { + int num = 0; + GnssGroup group = JSONObject.toJavaObject(object,GnssGroup.class); + if(null != gnssGroupMapper.selectById(group.getId())) { + num = gnssGroupMapper.updateById(group); + } + else{ + num = gnssGroupMapper.insert(group); + } + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } + + @PostMapping("/gnss/group/delete") + @ResponseBody + public String delete(@RequestParam int del_id) throws Exception { + int num = gnssGroupMapper.deleteById(del_id); + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } + + /********* 解算参数组 *********/ + @RequestMapping("/gnss/group/list_calc") + @ResponseBody + public JSONObject listCalc(int page, int limit) { + PageHelper.startPage(page, limit); + List cs = gnssGroupCalcMapper.selectList(null); + PageInfo pageInfo = new PageInfo<>(cs); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 0); + jsonObject.put("msg", ""); + jsonObject.put("count", pageInfo.getTotal()); + jsonObject.put("data", pageInfo.getList()); + return jsonObject; + } + + @PostMapping("/gnss/group/update_calc") + @ResponseBody + public String updateCalc(@RequestBody JSONObject object) throws Exception { + int num = 0; + GnssGroupCalc group = JSONObject.toJavaObject(object,GnssGroupCalc.class); + if(null != gnssGroupCalcMapper.selectById(group.getId())) { + num = gnssGroupCalcMapper.updateById(group); + } + else{ + num = gnssGroupCalcMapper.insert(group); + } + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } + + @PostMapping("/gnss/group/delete_calc") + @ResponseBody + public String deleteCalc(@RequestParam int del_id) throws Exception { + int num = gnssGroupCalcMapper.deleteById(del_id); + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } + + /********* 转发参数组 *********/ + @RequestMapping("/gnss/group/list_fwd") + @ResponseBody + public JSONObject listFwd(int page, int limit) { + PageHelper.startPage(page, limit); + List cs = gnssGroupFwdMapper.selectList(null); + PageInfo pageInfo = new PageInfo<>(cs); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 0); + jsonObject.put("msg", ""); + jsonObject.put("count", pageInfo.getTotal()); + jsonObject.put("data", pageInfo.getList()); + return jsonObject; + } + + @PostMapping("/gnss/group/update_fwd") + @ResponseBody + public String updateFwd(@RequestBody JSONObject object) throws Exception { + 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) throws Exception { + int num = gnssGroupFwdMapper.deleteById(del_id); + if (num == 0) { + return HttpResult.failed(); + } else return HttpResult.ok(); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssStatusController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssStatusController.java new file mode 100644 index 00000000..b6f80ee0 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssStatusController.java @@ -0,0 +1,74 @@ +package com.imdroid.beidou.controller; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.StringUtil; +import com.github.yulichang.query.MPJQueryWrapper; +import com.imdroid.secapi.dto.GnssStatus; +import com.imdroid.secapi.dto.GnssStatusJoin; +import com.imdroid.secapi.dto.GnssStatusMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpSession; + +@Controller +public class GnssStatusController extends BasicController{ + @Autowired + GnssStatusMapper gnssStatusMapper; + + /**** 推送页面 *****/ + @RequestMapping("/page/gnss_status") + public String gnssStatus(Model m, HttpSession session)throws Exception { + initModel(m, session); + + return "/page/gnss_status"; + } + + + /**** 推送数据 *****/ + @RequestMapping("/gnss/status/list") + @ResponseBody + public JSONObject list(HttpSession session, int page, int limit, String searchParams) { + PageHelper.startPage(page, limit); + + MPJQueryWrapper wrapper = new MPJQueryWrapper () + .selectAll(GnssStatus.class) + .select("d.devicetype as devicetype","d.tenantid as tenantid") + .leftJoin("gnssdevices d on t.deviceid = d.deviceid"); + + // 条件查询 + if(searchParams != null) { + JSONObject search = (JSONObject) JSONObject.parse(searchParams); + //设备号 + String deviceid = search.getString("deviceid"); + if (StringUtil.isNotEmpty(deviceid)) { + wrapper.like("deviceid", deviceid); + } + //状态 + Integer state = search.getInteger("state"); + if(state!=null && state != QUERY_ALL){ + wrapper.eq("state", state); + } + //告警 + Integer warning = search.getInteger("warning"); + if(warning!=null && warning != QUERY_ALL){ + wrapper.eq("warning", warning); + } + } + + //分页查询 (需要启用 mybatis plus 分页插件) + Page listPage = gnssStatusMapper.selectJoinPage(new Page<>(page, limit), GnssStatusJoin.class, wrapper); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", 0); + jsonObject.put("msg", ""); + jsonObject.put("count", listPage.getTotal()); + jsonObject.put("data", listPage.getRecords()); + return jsonObject; + } + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/LayuiController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/LayuiController.java new file mode 100644 index 00000000..a36413a3 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/LayuiController.java @@ -0,0 +1,63 @@ +package com.imdroid.beidou.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class LayuiController extends BasicController{ + @RequestMapping("/login") + public String login() throws Exception { + return "/login"; + } + + @RequestMapping("/") + public String index0()throws Exception { + return "/index"; + } + + @RequestMapping("/index") + public String index()throws Exception { + return "/index"; + } + + @RequestMapping("/page/device_overview") + public String deviceOverview()throws Exception { + return "/page/device_overview"; + } + + @RequestMapping("/page/gnss_data_calc") + public String gnssDataCalc()throws Exception { + return "/page/gnss_data_calc"; + } + + @RequestMapping("/page/gnss_data_raw") + public String gnssDataRaw()throws Exception { + return "/page/gnss_data_raw"; + } + + @RequestMapping("/page/gnss_data_tools") + public String gnssDataTools()throws Exception { + return "/page/gnss_data_tools"; + } + + + @RequestMapping("/page/gnss_msg") + public String gnssMsg()throws Exception { + return "/page/gnss_msg"; + } + + @RequestMapping("/page/gnss_msg_status") + public String gnssMsgStatus()throws Exception { + return "/page/gnss_msg_status"; + } + + @RequestMapping("/page/gnss_msg_trx") + public String gnssMsgTrx()throws Exception { + return "/page/gnss_msg_trx"; + } + + @RequestMapping("/page/warning") + public String warning()throws Exception { + return "/page/warning"; + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/LoginController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/LoginController.java new file mode 100644 index 00000000..da55fd68 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/LoginController.java @@ -0,0 +1,120 @@ +package com.imdroid.beidou.controller; + +import com.imdroid.beidou.auth.SessionUtils; +import com.imdroid.beidou.common.HttpResult; +import com.imdroid.beidou.data.WxMiniUserSession; +import com.imdroid.beidou.data.vo.MiniUserRegisterVO; +import com.imdroid.beidou.data.vo.MiniUserVO; +import com.imdroid.beidou.data.vo.UserLoginVO; +import com.imdroid.beidou.entity.Tenant; +import com.imdroid.beidou.entity.TenantMapper; +import com.imdroid.beidou.entity.User; +import com.imdroid.beidou.entity.UserMapper; +import com.imdroid.beidou.utils.WXUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 描述 + * + * @author LiGang + */ +@RequestMapping +@RestController +public class LoginController { + + @Autowired + private UserMapper userMapper; + + @Autowired + private TenantMapper tenantMapper; + + @Autowired + private WXUtils wxUtils; + + @PostMapping(value = "/do_login") + @ResponseBody + public HttpResult login(UserLoginVO userLoginVO, HttpServletRequest request, HttpServletResponse response) throws Exception { + if (UserLoginVO.LOGIN_TYPE_MINI.equals(userLoginVO.getType())) { + // 小程序登录 + WxMiniUserSession wxMiniUserSession = wxUtils.getMiniProgramUserOpenid(userLoginVO.getCode()); + if (wxMiniUserSession == null) { + return HttpResult.fail("用户code错误"); + } + User user = userMapper.queryByOpenid(wxMiniUserSession.getOpenid()); + if (user == null) { + return HttpResult.fail(HttpResult.HTTP_RSP_USER_NOT_EXIST, "用户不存在"); + } + Tenant tenant = tenantMapper.selectById(user.getTenant_id()); + SessionUtils.setCurrentUser(request, user, tenant); + + return HttpResult.success(buildMiniUser(user, tenant)); + } else { + // web登录 + User user = userMapper.queryByName(userLoginVO.getUsername()); + if (user == null) { + return HttpResult.fail("用户不存在"); + } + if (!user.getPassword().equals(userLoginVO.getPassword())) { + return HttpResult.fail("用户名或密码错误"); + } + Tenant tenant = tenantMapper.selectById(user.getTenant_id()); + SessionUtils.setCurrentUser(request, user, tenant); + //response.sendRedirect("/index"); //发这条没用,会导致login.html收不到应答,也跳转不了 + HttpResult rsp = HttpResult.success(null); + return HttpResult.success(null); + } + } + + private MiniUserVO buildMiniUser(User user, Tenant tenant) { + MiniUserVO miniUserVO = new MiniUserVO(); + miniUserVO.setUsername(user.getUsername()); + miniUserVO.setMobile(user.getMobile()); + miniUserVO.setNickName(user.getNickname()); + miniUserVO.setAvatarUrl(user.getAvatar_url()); + miniUserVO.setTenantName(tenant.getName()); + return miniUserVO; + } + + /** + * 小程序用户注册 + * + * @param miniUserRegisterVO miniUserRegisterVO + * @return HttpResult + */ + @PostMapping(value = "/mini-register") + public HttpResult miniUserRegister(@Validated MiniUserRegisterVO miniUserRegisterVO) { + WxMiniUserSession wxMiniUserSession = wxUtils.getMiniProgramUserOpenid(miniUserRegisterVO.getCode()); + if (wxMiniUserSession == null) { + return HttpResult.fail("用户code错误"); + } + User user = userMapper.queryByOpenid(wxMiniUserSession.getOpenid()); + if (user != null) { + return HttpResult.fail("用户已注册"); + } + user = userMapper.queryByMobile(miniUserRegisterVO.getMobile()); + if (user == null) { + return HttpResult.fail(HttpResult.HTTP_RSP_USER_NOT_EXIST, "用户不存在"); + } + // 更新用户信息 + User newUser = new User(); + newUser.setId(user.getId()); + newUser.setAvatar_url(miniUserRegisterVO.getAvatarUrl()); + newUser.setOpenid(wxMiniUserSession.getOpenid()); + newUser.setNickname(miniUserRegisterVO.getNickName()); + userMapper.updateById(newUser); + + return HttpResult.success(null); + } + + @RequestMapping(value = "/do_logout") + public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException { + request.getSession().invalidate(); + response.sendRedirect("/login"); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/controller/OssFileController.java b/sec-beidou/src/main/java/com/imdroid/beidou/controller/OssFileController.java new file mode 100644 index 00000000..e42c3079 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/OssFileController.java @@ -0,0 +1,54 @@ +package com.imdroid.beidou.controller; + +import com.imdroid.beidou.common.HttpResult; +import com.imdroid.beidou.utils.AliyunOssUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.UUID; + +/** + * 文件上次接口 + * + * @author LiGang + */ +@RestController +@RequestMapping("/file") +public class OssFileController { + + @Autowired + private AliyunOssUtils aliyunOssUtils; + + /** + * 上传文件通用接口 + * + * @param multipartFile multipartFile + * @return HttpResult + * @throws Exception + */ + @RequestMapping("/upload") + public HttpResult upload(@RequestParam("file") MultipartFile multipartFile) throws Exception { + String filename = multipartFile.getOriginalFilename(); + String url = aliyunOssUtils.uploadFile(multipartFile, filename, "common"); + return HttpResult.success(url); + } + + + /** + * 上传设备现场安装图片,保存到oss + * + * @param multipartFile multipartFile + * @return HttpResult + * @throws IOException + */ + @RequestMapping("/upload-device-image") + public HttpResult upload(@RequestParam("file") MultipartFile multipartFile, String deviceId) throws Exception { + String filename = deviceId + "_" + UUID.randomUUID().toString().replace("-", "") + ".jpg"; + String url = aliyunOssUtils.uploadFile(multipartFile, filename, "device-img"); + return HttpResult.success(url); + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/data/WxMiniUserSession.java b/sec-beidou/src/main/java/com/imdroid/beidou/data/WxMiniUserSession.java new file mode 100644 index 00000000..b1140963 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/data/WxMiniUserSession.java @@ -0,0 +1,37 @@ +package com.imdroid.beidou.data; + +/** + * 描述 + * + * @author LiGang + */ +public class WxMiniUserSession { + + private String sessionKey; + private String openid; + + public WxMiniUserSession() { + + } + + public WxMiniUserSession(String sessionKey, String openid) { + this.sessionKey = sessionKey; + this.openid = openid; + } + + public String getSessionKey() { + return sessionKey; + } + + public void setSessionKey(String sessionKey) { + this.sessionKey = sessionKey; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/MiniUserRegisterVO.java b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/MiniUserRegisterVO.java new file mode 100644 index 00000000..2d7bc034 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/MiniUserRegisterVO.java @@ -0,0 +1,29 @@ +package com.imdroid.beidou.data.vo; + +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; + +/** + * 小程序用户注册VO + * + * @author LiGang + */ +@Setter +@Getter +public class MiniUserRegisterVO { + + + @NotBlank(message = "用户code不能为空") + private String code; + + @NotBlank(message = "用户头像不能为空") + private String avatarUrl; + + @NotBlank(message = "手机号不能为空") + private String mobile; + + @NotBlank(message = "昵称不能为空") + private String nickName; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/MiniUserVO.java b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/MiniUserVO.java new file mode 100644 index 00000000..0f596909 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/MiniUserVO.java @@ -0,0 +1,24 @@ +package com.imdroid.beidou.data.vo; + +import lombok.Getter; +import lombok.Setter; + +/** + * 小程序用户信息VO + * + * @author LiGang + */ +@Setter +@Getter +public class MiniUserVO { + + private String avatarUrl; + + private String mobile; + + private String nickName; + + private String username; + + private String tenantName; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/UserLoginVO.java b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/UserLoginVO.java new file mode 100644 index 00000000..8e8a2b6e --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/UserLoginVO.java @@ -0,0 +1,31 @@ +package com.imdroid.beidou.data.vo; + +import lombok.Getter; +import lombok.Setter; + +/** + * 用户登录VO + * + * @author LiGang + */ +@Setter +@Getter +public class UserLoginVO { + + public static final String LOGIN_TYPE_WEB = "web"; + + public static final String LOGIN_TYPE_MINI = "mini"; + + private String username; + + private String password; + + private String type; + + /** + * 小程序用户code + */ + private String code; + + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/device/DeviceInstallVO.java b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/device/DeviceInstallVO.java new file mode 100644 index 00000000..cc8d441c --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/device/DeviceInstallVO.java @@ -0,0 +1,26 @@ +package com.imdroid.beidou.data.vo.device; + +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; + +/** + * 设备现场安装VO类 + * + * @author LiGang + */ +@Setter +@Getter +public class DeviceInstallVO { + + @NotBlank(message = "设备编号不能为空") + private String deviceId; + + @NotBlank(message = "设备安装位置的经纬度不能为空") + private String location; + + @NotBlank(message = "现场图片不能为空") + private String pictures; + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/device/DeviceStatusVO.java b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/device/DeviceStatusVO.java new file mode 100644 index 00000000..ff4ccc95 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/data/vo/device/DeviceStatusVO.java @@ -0,0 +1,85 @@ +package com.imdroid.beidou.data.vo.device; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.imdroid.secapi.dto.GnssDevice; +import com.imdroid.secapi.dto.GnssStatusJoin; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @author LiGang + * @date 2023/10/13 21:50 + */ +@Setter +@Getter +public class DeviceStatusVO { + + private Long id; + + private String deviceId; + + private String name; + + private String location; + + private String pictures; + + private String tenantName; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date latestDataTime; + + private Float roll; + private Float pitch; + private Float yaw; + private Integer rssi; + private Integer voltage; + private Float temperature; + private Float humidity; + private Integer txbytes; + private Integer rxbytes; + private Integer b562bytes; + private Integer d3xxbytes; + private Integer satelliteinview; + private Integer satelliteinuse; + + private Short dtuState; + + + public DeviceStatusVO() { + + } + + public DeviceStatusVO(GnssDevice gnssDevice, GnssStatusJoin gnssStatus) { + this.id = gnssDevice.getId(); + this.deviceId = gnssDevice.getDeviceid(); + this.name = gnssDevice.getName(); + //this.location = gnssDevice.getLocation(); + this.pictures = gnssDevice.getPictures(); + this.tenantName = gnssDevice.getTenantname(); + //this.latestDataTime = gnssDevice.getLatest_data_time(); + + if (gnssStatus != null) { + this.latestDataTime = gnssStatus.getUpdatetime(); + this.location = gnssStatus.getLocation(); + this.roll = gnssStatus.getRoll(); + this.pitch = gnssStatus.getPitch(); + this.yaw = gnssStatus.getYaw(); + this.rssi = gnssStatus.getRssi(); + this.voltage = gnssStatus.getVoltage(); + this.temperature = gnssStatus.getTemperature(); + this.humidity = gnssStatus.getHumidity(); + this.txbytes = gnssStatus.getTxbytes(); + this.rxbytes = gnssStatus.getRxbytes(); + this.d3xxbytes = gnssStatus.getD3xxbytes(); + this.b562bytes = gnssStatus.getB562bytes(); + this.satelliteinview = gnssStatus.getSatelliteinview(); + this.satelliteinuse = gnssStatus.getSatelliteinuse(); + this.dtuState = gnssStatus.getState(); + } + } +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupCalc.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupCalc.java new file mode 100644 index 00000000..ded8a682 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupCalc.java @@ -0,0 +1,16 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName(value = "gnssgroupcalc") +public class GnssGroupCalc { + int id; + int long_cycle; + int short_cycle; + float shock; + float h_weight; + float v_weight; + int device_num; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupCalcMapper.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupCalcMapper.java new file mode 100644 index 00000000..6b25c2d9 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupCalcMapper.java @@ -0,0 +1,9 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface GnssGroupCalcMapper extends BaseMapper { + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupFwd.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupFwd.java new file mode 100644 index 00000000..e8302a8e --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupFwd.java @@ -0,0 +1,14 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName(value = "gnssgroupfwd") +public class GnssGroupFwd { + int id; + String description; + String addr; + int port; + String fwd_template; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupFwdMapper.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupFwdMapper.java new file mode 100644 index 00000000..ab60f850 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/GnssGroupFwdMapper.java @@ -0,0 +1,9 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface GnssGroupFwdMapper extends BaseMapper { + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/Tenant.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/Tenant.java new file mode 100644 index 00000000..0ee01671 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/Tenant.java @@ -0,0 +1,16 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +@Data +@TableName(value = "TenantCfg") +public class Tenant implements Serializable { + int id; + String name; + Timestamp create_time; + String contact; +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/TenantMapper.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/TenantMapper.java new file mode 100644 index 00000000..4ea95617 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/TenantMapper.java @@ -0,0 +1,13 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.*; + +/** + * 用户配置,一个用户由name(手机号)唯一确定 + */ + +@Mapper +public interface TenantMapper extends BaseMapper { + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/User.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/User.java new file mode 100644 index 00000000..07856478 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/User.java @@ -0,0 +1,66 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName(value = "UserCfg") +public class User { + + @TableId + private Long id; + + int tenant_id; + private String name;//用电话号码,确保唯一,也便于第三方鉴权 + private String pwd; + String role; + private boolean locked; + private String nickname; + private boolean init_pwd=true; + private String mobile; + private String avatar_url; + private String openid; + + public String getUsername() { + return name; + } + + public String getPassword() { + return pwd; + } + + +// @Override +// public Collection extends GrantedAuthority> getAuthorities() { +// List authorities = new ArrayList<>(); +// // 必须加上ROLE_,否则授权不通过 +// authorities.add(new SimpleGrantedAuthority("ROLE_"+role)); +// return authorities; +// } +// +// @Override +// public boolean isAccountNonExpired() { +// return true; +// } +// +// @Override +// public boolean isAccountNonLocked() { +// return !locked; +// } +// +// @Override +// public boolean isCredentialsNonExpired() { +// return true; +// } +// +// @Override +// public boolean isEnabled() { +// return true; +// } + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/UserMapper.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/UserMapper.java new file mode 100644 index 00000000..732a6254 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/UserMapper.java @@ -0,0 +1,20 @@ +package com.imdroid.beidou.entity; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.*; + +/** + * 用户配置,一个用户由name(手机号)唯一确定 + */ + +@Mapper +public interface UserMapper extends BaseMapper { + @Select({"select * from UserCfg where name=#{name}"}) + User queryByName(String name); + + @Select({"select * from UserCfg where mobile=#{mobile}"}) + User queryByMobile(String mobile); + + @Select({"select * from UserCfg where openid=#{openid}"}) + User queryByOpenid(String openid); +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/entity/UserService.java b/sec-beidou/src/main/java/com/imdroid/beidou/entity/UserService.java new file mode 100644 index 00000000..1caaeeb4 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/entity/UserService.java @@ -0,0 +1,26 @@ +package com.imdroid.beidou.entity;//package com.imdroid.beidou.entity; +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.security.core.userdetails.UserDetails; +//import org.springframework.security.core.userdetails.UserDetailsService; +//import org.springframework.security.core.userdetails.UsernameNotFoundException; +//import org.springframework.stereotype.Service; +// +//@Service +//public class UserService implements UserDetailsService { +// @Autowired +// UserMapper userMapper; +// +// @Override +// public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { +// User user = userMapper.queryByName(username); +// if (user == null) { +// throw new UsernameNotFoundException("账户不存在!"); +// } +// //user.setRoles(userMapper.getUserRolesByUid(user.getId())); +// return user; +// +// } +// +//} +// diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/service/ServiceEnvInit.java b/sec-beidou/src/main/java/com/imdroid/beidou/service/ServiceEnvInit.java new file mode 100644 index 00000000..122ffcf4 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/service/ServiceEnvInit.java @@ -0,0 +1,59 @@ +package com.imdroid.beidou.service; + + +import com.imdroid.beidou.entity.Tenant; +import com.imdroid.beidou.entity.TenantMapper; +import com.imdroid.beidou.entity.User; +import com.imdroid.beidou.entity.UserMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +// springboot启动完成后,立即进行业务初始化 +@Slf4j +@Component +public class ServiceEnvInit implements ApplicationRunner { + @Value("${default_user_name}") + String default_user_name; + @Value("${default_pwd}") + String default_pwd; + + @Autowired + UserMapper userMapper; + @Autowired + TenantMapper tenantMapper; + + @Override + public void run(ApplicationArguments args) throws Exception { + if(tenantMapper.selectById(0) == null) + { + createDefaultTenant(); + } + //如果用户表为空,自动创建admin,初始密码admin123 + if(userMapper.selectCount(null)==0){ + createDefualtUser(); + } + } + + private void createDefualtUser(){ + log.info("create default user"); + User user = new User(); + user.setId(0L); + user.setName(default_user_name); +// user.setPwd(new BCryptPasswordEncoder().encode(default_pwd)); + user.setPwd(default_pwd); + user.setRole("ADMIN"); + userMapper.insert(user); + } + + private void createDefaultTenant(){ + log.info("create default tenant"); + Tenant tenant = new Tenant(); + tenant.setId(0); + tenant.setName("系统管理"); + tenantMapper.insert(tenant); + } +} \ No newline at end of file diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/utils/AliyunOssUtils.java b/sec-beidou/src/main/java/com/imdroid/beidou/utils/AliyunOssUtils.java new file mode 100644 index 00000000..3b0ed2b6 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/utils/AliyunOssUtils.java @@ -0,0 +1,82 @@ +package com.imdroid.beidou.utils; + +import com.imdroid.beidou.config.AliyunOssProperties; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.internal.OSSHeaders; +import com.aliyun.oss.model.CannedAccessControlList; +import com.aliyun.oss.model.ObjectMetadata; +import com.aliyun.oss.model.PutObjectRequest; +import com.aliyun.oss.model.StorageClass; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.nio.file.Files; + +/** + * 阿里云oss + * + * @author LiGang + */ +@Component +@RequiredArgsConstructor +public class AliyunOssUtils { + + private final AliyunOssProperties ossProperties; + + /** + * 发送报告至oss静态资源保存 + * + * @param file 文件 + * @param filename 保存后的文件名称 + * @param directory 保存的文件夹 + * @return 文件访问url + */ + public String uploadFile(File file, String filename, String directory) throws Exception { + //连接oss + OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(), ossProperties.getAccessKey(), ossProperties.getAccessSecret()); + String objectName = directory + "/" + filename; + PutObjectRequest putObjectRequest = new PutObjectRequest(ossProperties.getBucket(), objectName, new ByteArrayInputStream( + Files.readAllBytes(file.toPath()))); + //设置公共读 + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); + metadata.setObjectAcl(CannedAccessControlList.PublicRead); + putObjectRequest.setMetadata(metadata); + //上传文件 + ossClient.putObject(putObjectRequest); + ossClient.shutdown(); + + return ossProperties.getPublicReadUrl() + "/" + directory + "/" + filename; + } + + /** + * 发送报告至oss静态资源保存 + * + * @param multipartFile 文件 + * @param filename 保存后的文件名称 + * @param directory 保存的文件夹 + * @return 文件访问url + */ + public String uploadFile(MultipartFile multipartFile, String filename, String directory) throws Exception { + //连接oss + OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(), ossProperties.getAccessKey(), ossProperties.getAccessSecret()); + String objectName = directory + "/" + filename; + byte[] data = multipartFile.getBytes(); + PutObjectRequest putObjectRequest = new PutObjectRequest(ossProperties.getBucket(), objectName, new ByteArrayInputStream(data)); + //设置公共读 + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); + metadata.setObjectAcl(CannedAccessControlList.PublicRead); + putObjectRequest.setMetadata(metadata); + //上传文件 + ossClient.putObject(putObjectRequest); + ossClient.shutdown(); + + return ossProperties.getPublicReadUrl() + "/" + directory + "/" + filename; + } + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/utils/HttpUtil.java b/sec-beidou/src/main/java/com/imdroid/beidou/utils/HttpUtil.java new file mode 100644 index 00000000..babefe23 --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/utils/HttpUtil.java @@ -0,0 +1,279 @@ +package com.imdroid.beidou.utils; + +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * The http utility + */ +public class HttpUtil { + /** + * Http Request(Get) + * + * @param url the request url + * @param param the request parameter + * @return return content + * @throws URISyntaxException + * @throws IOException + * @throws ClientProtocolException + */ + public static String doGet(String url, Map param) throws URISyntaxException, IOException { + + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + HttpGet httpGet = new HttpGet(uri); + + response = httpclient.execute(httpGet); + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * Http Request(Get) + * + * @param url the request url + * @param param the request parameter + * @param header the request header + * @return return content + * @throws URISyntaxException + * @throws IOException + * @throws ClientProtocolException + */ + public static String doGet(String url, Map param, Map header) throws URISyntaxException, IOException { + + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + HttpGet httpGet = new HttpGet(uri); + if (header != null) { + for (String key : header.keySet()) { + httpGet.addHeader(key, header.get(key)); + } + } + response = httpclient.execute(httpGet); + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * Http Request(Get) + * + * @param url the request url + * @return return content + */ + public static String doGet(String url) throws Exception { + return doGet(url, null); + } + + + /** + * Http Request(Post) + * + * @param url the request url + * @param param the request parameter + * @return return content + */ + public static String doPost(String url, Map param) throws IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + HttpPost httpPost = new HttpPost(url); + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8"); + httpPost.setEntity(entity); + } + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return resultString; + } + /** + * Http Request(Post) + * + * @param url the request url + * @param param the request parameter + * @return return content + */ + public static String doPost(String url, Map param, Map header) throws IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + HttpPost httpPost = new HttpPost(url); + if (param != null) { + List paramList = new ArrayList<>(); + if(param!=null) { + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + } + if (header != null) { + for (String key : header.keySet()) { + httpPost.addHeader(key, header.get(key)); + } + } + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8"); + httpPost.setEntity(entity); + } + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return resultString; + } + /** + * Http Request(Post) + * + * @param url the request url + * @return return content + */ + public static String doPost(String url) throws IOException { + return doPost(url, null); + } + + /** + * Http Request(Post in Json) + * + * @param url the request url + * @param json the json object + * @return return content + */ + public static String doPostJson(String url, String json) throws IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + HttpPost httpPost = new HttpPost(url); + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 读取请求内容 + * @param request the request + * @return 请求内容 + * @throws IOException + */ + public static String getContent(HttpServletRequest request) throws IOException { + //读取请求内容 + BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream())); + String line = null; + StringBuilder sb = new StringBuilder(); + while((line = br.readLine())!=null){ + sb.append(line); + } + // 将资料解码 + String reqBody = sb.toString(); + return URLDecoder.decode(reqBody, "utf-8"); + } + +} diff --git a/sec-beidou/src/main/java/com/imdroid/beidou/utils/WXUtils.java b/sec-beidou/src/main/java/com/imdroid/beidou/utils/WXUtils.java new file mode 100644 index 00000000..1412e92a --- /dev/null +++ b/sec-beidou/src/main/java/com/imdroid/beidou/utils/WXUtils.java @@ -0,0 +1,46 @@ +package com.imdroid.beidou.utils; + + +import com.imdroid.beidou.config.WxMiniProperties; +import com.imdroid.beidou.data.WxMiniUserSession; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 描述 + * + * @author LiGang + */ +@Slf4j +@Component +public class WXUtils { + + private final WxMiniProperties wxMiniProperties; + + public WXUtils(WxMiniProperties wxMiniProperties) { + this.wxMiniProperties = wxMiniProperties; + } + + /** + * 微信api地址 + */ + protected final String API_URL = "https://api.weixin.qq.com/sns/jscode2session"; + + public WxMiniUserSession getMiniProgramUserOpenid(String code) { + String requestURL = String.format(API_URL + "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code" + , wxMiniProperties.getAppid(), wxMiniProperties.getSecret(), code); + try { + final String response = HttpUtil.doGet(requestURL); + log.info("小程序登录结果:{}", response); + JsonObject jsonObject = JsonParser.parseString(response).getAsJsonObject(); + String sessionKey = jsonObject.get("session_key").getAsString(); + String openid = jsonObject.get("openid").getAsString(); + return new WxMiniUserSession(sessionKey, openid); + } catch (Exception e) { + return null; + } + + } +} diff --git a/sec-beidou/src/main/resources/application.properties b/sec-beidou/src/main/resources/application.properties new file mode 100644 index 00000000..cd708a8b --- /dev/null +++ b/sec-beidou/src/main/resources/application.properties @@ -0,0 +1,40 @@ +# Attention: serverTimezone=Asia/Shanghai !!! +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/beidou?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=true +spring.datasource.username=admin +spring.datasource.password=DBMgr_2022 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.properties.hibernate.hbm2ddl.auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MYSQL5InnoDBDialect +spring.jpa.show-sql=true + +spring.sql.init.mode=always +#spring.datasource.initialize=true +spring.sql.init.schema-locations=classpath:db/schema.sql + +spring.thymeleaf.cache=false +#server.port=8091 + +#log设置 +logging.file.name=log/dtu.log + + +#security +server.port=8668 +server.servlet.context-path = / +#server.ssl.key-store=classpath:tianheng.keystore +#server.ssl.key-store-password=nbb2021 +#server.ssl.keyAlias=tianheng + +#defualt user +default_user_name = admin +default_pwd = 666666 + +# miniprogram info +app.bis.appid = wxb51f83011ecef07f +app.bis.secret = fa046f918a7a10fe6f21c6ccfc4ea918 + +aliyun.oss.endpoint = https://oss-cn-shanghai.aliyuncs.com +aliyun.oss.accessKey = LTAI4G6hmpX7h9hQvUnwKWxj +aliyun.oss.accessSecret = GHVzHKLLor8i5ZR1qyeoi4KMf3mjHb +aliyun.oss.bucket = imdroid-device-management +aliyun.oss.publicReadUrl = https://imdroid-device-management.oss-cn-shanghai.aliyuncs.com diff --git a/sec-beidou/src/main/resources/application.yml b/sec-beidou/src/main/resources/application.yml new file mode 100644 index 00000000..3925fac1 --- /dev/null +++ b/sec-beidou/src/main/resources/application.yml @@ -0,0 +1,9 @@ +spring: + thymeleaf: + prefix: classpath:/templates + suffix: .html + cache: false + +mybatis-plus: + configuration: + map-underscore-to-camel-case: false #关闭驼峰命名法 \ No newline at end of file diff --git a/sec-beidou/src/main/resources/db/schema.sql b/sec-beidou/src/main/resources/db/schema.sql new file mode 100644 index 00000000..71e30a82 --- /dev/null +++ b/sec-beidou/src/main/resources/db/schema.sql @@ -0,0 +1,173 @@ +CREATE TABLE IF NOT EXISTS `UserCfg` ( + `id` bigint(20), + `tenant_id` int DEFAULT 0, + `name` varchar(20) NOT NULL, + `pwd` varchar(64) NOT NULL, + `role` varchar(24) NOT NULL, + `locked` boolean DEFAULT false, + `nickname` varchar(20) DEFAULT NULL, + `init_pwd` boolean DEFAULT true, + `mobile` varchar(20) DEFAULT NULL, + `avatar_url` varchar(255) DEFAULT NULL, + `openid` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `TenantCfg` ( + `id` int NOT NULL, + `name` varchar(128) NOT NULL, + `create_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3), + `contact` varchar(64) default NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `gnssdevices` ( + `id` bigint AUTO_INCREMENT, + `opmode` smallint DEFAULT 0, + `createtime` datetime DEFAULT NULL, + `createuser` varchar(50) DEFAULT NULL, + `updatetime` datetime DEFAULT NULL, + `updateuser` varchar(50) DEFAULT NULL, + `deviceid` varchar(20) NOT NULL, + `name` varchar(50) NOT NULL, + `parentid` varchar(20) DEFAULT NULL, + `devicetype` smallint DEFAULT 0, + `tenantid` int NOT NULL, + `tenantname` varchar(100) NOT NULL, + `gnssconfiguration` varchar(100) NOT NULL, + `project_id` int NOT NULL DEFAULT 0 COMMENT '项目id', + `group_id` int DEFAULT 1, + `calc_group_id` int DEFAULT 1, + `fwd_group_id` int DEFAULT 0, + `syn` bit(1) DEFAULT 0 COMMENT '是否已同步', + `pictures` varchar(100) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `gnssgroup` ( + `id` int NOT NULL, + `work_cycle` int DEFAULT 0, + `active_time` int DEFAULT 0, + `active_offset` int DEFAULT 0, + `sample` smallint DEFAULT 0, + `power_mode` smallint DEFAULT 0, + `device_num` int DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `gnssgroupcalc` ( + `id` int NOT NULL, + `long_cycle` int DEFAULT 0, + `short_cycle` int DEFAULT 0, + `shock` float DEFAULT 0, + `h_weight` float DEFAULT 0, + `v_weight` float DEFAULT 0, + `device_num` int DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `gnssgroupfwd` ( + `id` int NOT NULL, + `description` varchar(128) DEFAULT NULL, + `addr` varchar(128) DEFAULT NULL, + `port` int DEFAULT 0, + `fwd_template` longtext, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `gnssstatus` ( + `id` bigint AUTO_INCREMENT, + `updatetime` datetime DEFAULT NULL, + `devicetime` datetime DEFAULT NULL, + `deviceid` varchar(20) NOT NULL, + `location` varchar(100) DEFAULT NULL, + `roll` float DEFAULT 0, + `pitch` float DEFAULT 0, + `yaw` float DEFAULT 0, + `rssi` int DEFAULT 0, + `voltage` int DEFAULT 0, + `temperature` float DEFAULT 0, + `humidity` float DEFAULT 0, + `satelliteinview` float DEFAULT 0, + `satelliteinuse` float DEFAULT 0, + `txbytes` int DEFAULT 0, + `rxbytes` int DEFAULT 0, + `b562bytes` int DEFAULT 0, + `d3xxbytes` int DEFAULT 0, + `state` smallint DEFAULT 0, + `warning` smallint DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `gnssdevicelocationrecords` ( + `id` bigint AUTO_INCREMENT, + `enabled` bit(1) DEFAULT NULL, + `createtime` datetime DEFAULT NULL, + `createuser` varchar(50) CHARACTER SET utf8 DEFAULT NULL, + `updatetime` datetime DEFAULT NULL, + `updateuser` varchar(50) CHARACTER SET utf8 DEFAULT NULL, + `deviceid` varchar(20) CHARACTER SET utf8 NOT NULL, + `b562e` double DEFAULT NULL COMMENT '原始北斗位置东E', + `b562n` double DEFAULT NULL COMMENT '原始北斗位置北N', + `b562d` double DEFAULT NULL COMMENT '原始北斗位置天D', + `r9250e` double DEFAULT NULL, + `r9250n` double DEFAULT NULL, + `r9250d` double DEFAULT NULL, + `resulte` double DEFAULT NULL, + `resultn` double DEFAULT NULL, + `resultd` double DEFAULT NULL, + `tenantid` int NOT NULL, + `rb562e` double DEFAULT NULL COMMENT '相对北斗位置东E', + `rb562d` double DEFAULT NULL COMMENT '相对北斗位置北N', + `rb562n` double DEFAULT NULL COMMENT '相对北斗位置天D', + PRIMARY KEY (`id`), + KEY `idx_deviceid_time` (`deviceid`,`createtime`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE IF NOT EXISTS `gnsssinglecalcdata` ( + `id` bigint AUTO_INCREMENT, + `createtime` datetime DEFAULT NULL, + `deviceid` varchar(20) CHARACTER SET utf8 NOT NULL, + `b562e` double DEFAULT NULL COMMENT '原始北斗位置东E', + `b562n` double DEFAULT NULL COMMENT '原始北斗位置北N', + `b562d` double DEFAULT NULL COMMENT '原始北斗位置天D', + `roll` double DEFAULT NULL, + `pitch` double DEFAULT NULL, + `yaw` double DEFAULT NULL, + `shock` double DEFAULT NULL, + PRIMARY KEY (`id`), + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE IF NOT EXISTS `gnssstatusmsg` ( + `id` bigint AUTO_INCREMENT, + `updatetime` datetime DEFAULT NULL, + `devicetime` datetime DEFAULT NULL, + `deviceid` varchar(20) NOT NULL, + `roll` float DEFAULT 0, + `pitch` float DEFAULT 0, + `yaw` float DEFAULT 0, + `dtustate` smallint DEFAULT 0, + `rssi` int DEFAULT 0, + `voltage` int DEFAULT 0, + `temperature` float DEFAULT 0, + `humidity` float DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `gnsstrxmsg` ( + `id` bigint AUTO_INCREMENT, + `updatetime` datetime DEFAULT NULL, + `devicetime` datetime DEFAULT NULL, + `deviceid` varchar(20) NOT NULL, + `uart1txbytes` int DEFAULT 0, + `uart1rxbytes` int DEFAULT 0, + `uart1unknown` int DEFAULT 0, + `uart2txbytes` int DEFAULT 0, + `uart2rxbytes` int DEFAULT 0, + `uart2unknown` int DEFAULT 0, + `servertxbytes` int DEFAULT 0, + `serverrxbytes` int DEFAULT 0, + `b562bytes` int DEFAULT 0, + `d3xxbytes` int DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/sec-beidou/src/main/resources/static/api/clear.json b/sec-beidou/src/main/resources/static/api/clear.json new file mode 100644 index 00000000..e0f5ed74 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/clear.json @@ -0,0 +1,4 @@ +{ + "code": 1, + "msg": "服务端清理缓存成功" +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/gnss_data_calc.json b/sec-beidou/src/main/resources/static/api/gnss_data_calc.json new file mode 100644 index 00000000..b90ca6e2 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/gnss_data_calc.json @@ -0,0 +1,64 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "data": [ + { + "deviceid": "2307001", + "report_time": "2023-01-01 12:23:56", + "b562e": "22.12", + "b562n": "10.24", + "b562d": "5.1", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "resulte": "22.13", + "resultn": "10.11", + "resultd": "5.2", + "rb562e": "22.13", + "rb562n": "10.11", + "rb562d": "5.2", + "pps": "512", + "sat_count": "24", + "sat_used": "10" + }, + { + "deviceid": "2307001", + "report_time": "2023-01-01 12:23:56", + "b562e": "22.12", + "b562n": "10.24", + "b562d": "5.1", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "resulte": "22.13", + "resultn": "10.11", + "resultd": "5.2", + "rb562e": "22.13", + "rb562n": "10.11", + "rb562d": "5.2", + "pps": "512", + "sat_count": "24", + "sat_used": "10" + }, + { + "deviceid": "2307001", + "report_time": "2023-01-01 12:23:56", + "b562e": "22.12", + "b562n": "10.24", + "b562d": "5.1", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "resulte": "22.13", + "resultn": "10.11", + "resultd": "5.2", + "rb562e": "22.13", + "rb562n": "10.11", + "rb562d": "5.2", + "pps": "512", + "sat_count": "24", + "sat_used": "10" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/gnss_data_raw.json b/sec-beidou/src/main/resources/static/api/gnss_data_raw.json new file mode 100644 index 00000000..7e49315e --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/gnss_data_raw.json @@ -0,0 +1,46 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "data": [ + { + "deviceid": "2307001", + "report_time": "2023-01-01 12:23:56", + "b562e": "22.12", + "b562n": "10.24", + "b562d": "5.1", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "pps": "512", + "sat_count": "24", + "sat_used": "10" + }, + { + "deviceid": "2307001", + "report_time": "2023-01-01 12:23:56", + "b562e": "22.12", + "b562n": "10.24", + "b562d": "5.1", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "pps": "512", + "sat_count": "24", + "sat_used": "10" + }, + { + "deviceid": "2307001", + "report_time": "2023-01-01 12:23:56", + "b562e": "22.12", + "b562n": "10.24", + "b562d": "5.1", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "pps": "512", + "sat_count": "24", + "sat_used": "10" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/gnss_dev_cfg.json b/sec-beidou/src/main/resources/static/api/gnss_dev_cfg.json new file mode 100644 index 00000000..c53c44ae --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/gnss_dev_cfg.json @@ -0,0 +1,55 @@ +{ + "code": 0, + "msg": "", + "count": 100, + "data": [ + { + "id": "2307001", + "name": "1号机", + "parent_id": "", + "device_type": "基站", + "location": "广州", + "project_id": "0", + "group_id": "1", + "calc_id": "1", + "op_mode": "正常", + "syn": "是" + }, + { + "id": "2307002", + "name": "2号机", + "parent_id": "2307001", + "device_type": "测站", + "location": "广州", + "project_id": "0", + "group_id": "1", + "calc_id": "1", + "op_mode": "正常", + "syn": "是" + }, + { + "id": "2307003", + "name": "3号机", + "parent_id": "2307001", + "device_type": "测站", + "location": "广州", + "project_id": "0", + "group_id": "1", + "calc_id": "1", + "op_mode": "正常", + "syn": "是" + }, + { + "id": "2307004", + "name": "1号机", + "parent_id": "2307001", + "device_type": "测站", + "location": "广州", + "project_id": "0", + "group_id": "1", + "calc_id": "1", + "op_mode": "维护", + "syn": "否" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/gnss_msg.json b/sec-beidou/src/main/resources/static/api/gnss_msg.json new file mode 100644 index 00000000..357c7525 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/gnss_msg.json @@ -0,0 +1,31 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "data": [ + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "type": "配置", + "content": "D3 11 00 09 00 23 33 DD 1E 06 00 00 01" + }, + { + "device_id": "2307011", + "report_time": "2023-01-01 12:23:56", + "type": "配置应答", + "content": "D3 11 00 0A 00 23 33 DD 1E 06 00 00 01 01" + }, + { + "device_id": "2307021", + "report_time": "2023-01-01 12:23:56", + "type": "通知", + "content": "D3 F0 00 09 00 23 33 DD" + }, + { + "device_id": "2307031", + "report_time": "2023-01-01 12:23:56", + "type": "通知", + "content": "D3 F2 00 09 00 23 33 DD" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/gnss_msg_status.json b/sec-beidou/src/main/resources/static/api/gnss_msg_status.json new file mode 100644 index 00000000..16ea5009 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/gnss_msg_status.json @@ -0,0 +1,55 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "data": [ + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "2023-01-01 12:23:56", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "rssi": "31", + "voltage": "9900", + "temperature": "45", + "humidity": "30" + }, + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "2023-01-01 12:23:56", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "rssi": "31", + "voltage": "9900", + "temperature": "45", + "humidity": "30" + }, + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "2023-01-01 12:23:56", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "rssi": "31", + "voltage": "9900", + "temperature": "45", + "humidity": "30" + }, + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "2023-01-01 12:23:56", + "roll": "0.1", + "pitch": "0.2", + "yaw": "90.1", + "rssi": "31", + "voltage": "9900", + "temperature": "45", + "humidity": "30" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/gnss_msg_trx.json b/sec-beidou/src/main/resources/static/api/gnss_msg_trx.json new file mode 100644 index 00000000..4e949622 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/gnss_msg_trx.json @@ -0,0 +1,59 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "data": [ + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "12:23:56", + "server_rx": "300123", + "server_tx": "212200", + "uart1_rx": "212200", + "uart1_tx": "300123", + "uart1_unknown": "9900", + "uart2_rx": "300123", + "uart2_tx": "212200", + "uart2_unknown": "30" + }, + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "12:23:56", + "server_rx": "300123", + "server_tx": "212200", + "uart1_rx": "212200", + "uart1_tx": "300123", + "uart1_unknown": "9900", + "uart2_rx": "300123", + "uart2_tx": "212200", + "uart2_unknown": "30" + }, + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "12:23:56", + "server_rx": "300123", + "server_tx": "212200", + "uart1_rx": "212200", + "uart1_tx": "300123", + "uart1_unknown": "9900", + "uart2_rx": "300123", + "uart2_tx": "212200", + "uart2_unknown": "30" + }, + { + "device_id": "2307001", + "report_time": "2023-01-01 12:23:56", + "local_time": "12:23:56", + "server_rx": "300123", + "server_tx": "212200", + "uart1_rx": "212200", + "uart1_tx": "300123", + "uart1_unknown": "9900", + "uart2_rx": "300123", + "uart2_tx": "212200", + "uart2_unknown": "30" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/init.json b/sec-beidou/src/main/resources/static/api/init.json new file mode 100644 index 00000000..0f2d7cf0 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/init.json @@ -0,0 +1,259 @@ +{ + "homeInfo": { + "title": "首页", + "href": "page/device_overview" + }, + "logoInfo": { + "title": "形变监测平台", + "image": "images/logo.png", + "href": "" + }, + "menuInfo": [ + { + "title": "设备管理", + "icon": "fa fa-address-book", + "href": "", + "target": "_self", + "child": [ + { + "title": "设备总览", + "href": "page/device_overview", + "icon": "fa fa-home", + "target": "_self" + }, + { + "title": "告警管理", + "href": "page/warning", + "icon": "fa fa-bell-o", + "target": "_self" + }, + { + "title": "北斗", + "href": "", + "icon": "fa fa-star-o", + "target": "", + "child": [ + { + "title": "运行状态", + "href": "page/gnss_status", + "icon": "fa fa-tachometer", + "target": "_self" + }, + { + "title": "配置管理", + "href": "", + "icon": "fa fa-gear", + "target": "_self", + "child": [ + { + "title": "通用参数", + "href": "page/gnss_group_cfg", + "icon": "fa fa-minus", + "target": "_self" + }, + { + "title": "设备参数", + "href": "page/gnss_dev_cfg", + "icon": "fa fa-minus", + "target": "_self" + } + ] + }, + { + "title": "设备消息", + "href": "", + "icon": "fa fa-file-text-o", + "target": "_self", + "child": [ + { + "title": "消息摘要", + "href": "page/gnss_msg", + "icon": "fa fa-minus", + "target": "_self" + }, + { + "title": "状态消息", + "href": "page/gnss_msg_status", + "icon": "fa fa-minus", + "target": "_self" + }, + { + "title": "统计消息", + "href": "page/gnss_msg_trx", + "icon": "fa fa-minus", + "target": "_self" + } + ] + } + ] + }, + { + "title": "测斜仪", + "href": "", + "icon": "fa fa-area-chart", + "target": "", + "child": [ + { + "title": "运行状态", + "href": "", + "icon": "fa fa-tachometer", + "target": "_self" + }, + { + "title": "配置管理", + "href": "", + "icon": "fa fa-gear", + "target": "_self" + } + ] + }, + { + "title": "光伏DTU", + "href": "", + "icon": "fa fa-sun-o", + "target": "", + "child": [ + { + "title": "运行状态", + "href": "", + "icon": "fa fa-tachometer", + "target": "_self" + }, + { + "title": "配置管理", + "href": "", + "icon": "fa fa-gear", + "target": "_self", + "child": [ + { + "title": "通用参数", + "href": "", + "icon": "fa fa-minus", + "target": "_self" + }, + { + "title": "设备参数", + "href": "", + "icon": "fa fa-minus", + "target": "_self" + } + ] + }, + { + "title": "设备消息", + "href": "", + "icon": "fa fa-file-text-o", + "target": "_self", + "child": [ + { + "title": "消息摘要", + "href": "", + "icon": "fa fa-minus", + "target": "_self" + }, + { + "title": "状态消息", + "href": "", + "icon": "fa fa-minus", + "target": "_self" + }, + { + "title": "统计消息", + "href": "", + "icon": "fa fa-minus", + "target": "_self" + } + ] + } + ] + } + ] + }, + { + "title": "系统管理", + "icon": "fa fa-lemon-o", + "href": "", + "target": "_self", + "child": [ + { + "title": "系统状态", + "href": "", + "icon": "fa fa-server", + "target": "_self" + }, + { + "title": "系统参数", + "href": "", + "icon": "fa fa-gears", + "target": "_self" + }, + { + "title": "用户管理", + "href": "", + "icon": "fa fa-user", + "target": "_self", + "child": [ + { + "title": "组织管理", + "href": "", + "icon": "fa fa-university", + "target": "_self" + }, + { + "title": "账号管理", + "href": "", + "icon": "fa fa-key", + "target": "_self" + } + ] + }, + { + "title": "操作日志", + "href": "", + "icon": "fa fa-pencil-square-o", + "target": "_self" + } + ] + }, + { + "title": "监测数据", + "icon": "fa fa-slideshare", + "href": "", + "target": "_self", + "child": [ + { + "title": "北斗", + "href": "", + "icon": "fa fa-star-o", + "target": "", + "child": [ + { + "title": "解算结果", + "href": "page/gnss_data_calc", + "icon": "fa fa-calculator", + "target": "_self" + }, + { + "title": "原始数据", + "href": "page/gnss_data_raw", + "icon": "fa fa-database", + "target": "_self" + }, + { + "title": "测试工具", + "href": "page/gnss_data_tools", + "icon": "fa fa-wrench", + "target": "_self" + } + ] + }, + { + "title": "测斜仪", + "href": "", + "icon": "fa fa-area-chart", + "target": "_self" + } + ] + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/menus.json b/sec-beidou/src/main/resources/static/api/menus.json new file mode 100644 index 00000000..e14d00ed --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/menus.json @@ -0,0 +1,254 @@ +{ + "code": 0, + "msg": "", + "count": 19, + "data": [ + { + "authorityId": 1, + "authorityName": "系统管理", + "orderNumber": 1, + "menuUrl": null, + "menuIcon": "layui-icon-set", + "createTime": "2018/06/29 11:05:41", + "authority": null, + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 0, + "parentId": -1 + }, + { + "authorityId": 2, + "authorityName": "用户管理", + "orderNumber": 2, + "menuUrl": "system/user", + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": null, + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 0, + "parentId": 1 + }, + { + "authorityId": 3, + "authorityName": "查询用户", + "orderNumber": 3, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/07/21 13:54:16", + "authority": "user:view", + "checked": 0, + "updateTime": "2018/07/21 13:54:16", + "isMenu": 1, + "parentId": 2 + }, + { + "authorityId": 4, + "authorityName": "添加用户", + "orderNumber": 4, + "menuUrl": null, + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": "user:add", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 2 + }, + { + "authorityId": 5, + "authorityName": "修改用户", + "orderNumber": 5, + "menuUrl": null, + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": "user:edit", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 2 + }, + { + "authorityId": 6, + "authorityName": "删除用户", + "orderNumber": 6, + "menuUrl": null, + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": "user:delete", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 2 + }, + { + "authorityId": 7, + "authorityName": "角色管理", + "orderNumber": 7, + "menuUrl": "system/role", + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": null, + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 0, + "parentId": 1 + }, + { + "authorityId": 8, + "authorityName": "查询角色", + "orderNumber": 8, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/07/21 13:54:59", + "authority": "role:view", + "checked": 0, + "updateTime": "2018/07/21 13:54:58", + "isMenu": 1, + "parentId": 7 + }, + { + "authorityId": 9, + "authorityName": "添加角色", + "orderNumber": 9, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/06/29 11:05:41", + "authority": "role:add", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 7 + }, + { + "authorityId": 10, + "authorityName": "修改角色", + "orderNumber": 10, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/06/29 11:05:41", + "authority": "role:edit", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 7 + }, + { + "authorityId": 11, + "authorityName": "删除角色", + "orderNumber": 11, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/06/29 11:05:41", + "authority": "role:delete", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 7 + }, + { + "authorityId": 12, + "authorityName": "角色权限管理", + "orderNumber": 12, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/06/29 11:05:41", + "authority": "role:auth", + "checked": 0, + "updateTime": "2018/07/13 15:27:18", + "isMenu": 1, + "parentId": 7 + }, + { + "authorityId": 13, + "authorityName": "权限管理", + "orderNumber": 13, + "menuUrl": "system/authorities", + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": null, + "checked": 0, + "updateTime": "2018/07/13 15:45:13", + "isMenu": 0, + "parentId": 1 + }, + { + "authorityId": 14, + "authorityName": "查询权限", + "orderNumber": 14, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/07/21 13:55:57", + "authority": "authorities:view", + "checked": 0, + "updateTime": "2018/07/21 13:55:56", + "isMenu": 1, + "parentId": 13 + }, + { + "authorityId": 15, + "authorityName": "添加权限", + "orderNumber": 15, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/06/29 11:05:41", + "authority": "authorities:add", + "checked": 0, + "updateTime": "2018/06/29 11:05:41", + "isMenu": 1, + "parentId": 13 + }, + { + "authorityId": 16, + "authorityName": "修改权限", + "orderNumber": 16, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/07/13 09:13:42", + "authority": "authorities:edit", + "checked": 0, + "updateTime": "2018/07/13 09:13:42", + "isMenu": 1, + "parentId": 13 + }, + { + "authorityId": 17, + "authorityName": "删除权限", + "orderNumber": 17, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/06/29 11:05:41", + "authority": "authorities:delete", + "checked": 0, + "updateTime": "2018/06/29 11:05:41", + "isMenu": 1, + "parentId": 13 + }, + { + "authorityId": 18, + "authorityName": "登录日志", + "orderNumber": 18, + "menuUrl": "system/loginRecord", + "menuIcon": null, + "createTime": "2018/06/29 11:05:41", + "authority": null, + "checked": 0, + "updateTime": "2018/06/29 11:05:41", + "isMenu": 0, + "parentId": 1 + }, + { + "authorityId": 19, + "authorityName": "查询登录日志", + "orderNumber": 19, + "menuUrl": "", + "menuIcon": "", + "createTime": "2018/07/21 13:56:43", + "authority": "loginRecord:view", + "checked": 0, + "updateTime": "2018/07/21 13:56:43", + "isMenu": 1, + "parentId": 18 + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/tableSelect.json b/sec-beidou/src/main/resources/static/api/tableSelect.json new file mode 100644 index 00000000..37fb0ed8 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/tableSelect.json @@ -0,0 +1,23 @@ +{ + "code": 0, + "msg": "", + "count": 16, + "data": [ + { "id":"001", "username":"张玉林", "sex":"女" }, + { "id":"002", "username":"刘晓军", "sex":"男" }, + { "id":"003", "username":"张恒", "sex":"男" }, + { "id":"004", "username":"朱一", "sex":"男" }, + { "id":"005", "username":"刘佳能", "sex":"女" }, + { "id":"006", "username":"晓梅", "sex":"女" }, + { "id":"007", "username":"马冬梅", "sex":"女" }, + { "id":"008", "username":"刘晓庆", "sex":"女" }, + { "id":"009", "username":"刘晓庆", "sex":"女" }, + { "id":"010", "username":"刘晓庆", "sex":"女" }, + { "id":"011", "username":"刘晓庆", "sex":"女" }, + { "id":"012", "username":"刘晓庆", "sex":"女" }, + { "id":"013", "username":"刘晓庆", "sex":"女" }, + { "id":"014", "username":"刘晓庆", "sex":"女" }, + { "id":"015", "username":"刘晓庆", "sex":"女" }, + { "id":"016", "username":"刘晓庆", "sex":"女" } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/api/upload.json b/sec-beidou/src/main/resources/static/api/upload.json new file mode 100644 index 00000000..691902df --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/upload.json @@ -0,0 +1,10 @@ +{ + "code": 1, + "msg": "上传成功", + "data": { + "url": [ + "../images/logo.png", + "../images/captcha.jpg" + ] + } +} diff --git a/sec-beidou/src/main/resources/static/api/warning_data.json b/sec-beidou/src/main/resources/static/api/warning_data.json new file mode 100644 index 00000000..4e207f78 --- /dev/null +++ b/sec-beidou/src/main/resources/static/api/warning_data.json @@ -0,0 +1,28 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "data": [ + { + "rp_time": "2023-01-01 12:23:56", + "device_id": "2307001", + "device_type": "北斗", + "level": "一般", + "content": "位移加速" + }, + { + "rp_time": "2023-02-01 12:23:56", + "device_id": "1602301001", + "device_type": "测斜仪", + "level": "一般", + "content": "位移加速" + }, + { + "rp_time": "2023-03-01 12:23:56", + "device_id": "861380138000", + "device_type": "光伏DTU", + "level": "严重", + "content": "低电压" + } + ] +} \ No newline at end of file diff --git a/sec-beidou/src/main/resources/static/css/layuimini.css b/sec-beidou/src/main/resources/static/css/layuimini.css new file mode 100644 index 00000000..b67e5e8b --- /dev/null +++ b/sec-beidou/src/main/resources/static/css/layuimini.css @@ -0,0 +1,803 @@ +/** +配色方案(如有需要,请自行配置) + */ +/**头部-配色*/ +.layui-layout-admin .layui-header { + background-color: #1aa094 !important; +} + +.layui-header > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover { + background-color: #197971 !important; +} + +.layui-header .layuimini-header-content > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover { + background-color: #197971 !important; +} + +/**logo-配色*/ +.layui-layout-admin .layuimini-logo { + background-color: #243346 !important; +} + +/**左侧-配色*/ +.layui-side.layui-bg-black, .layui-side.layui-bg-black > .layuimini-menu-left > ul { + background-color: #2f4056 !important; +} + +.layuimini-menu-left .layui-nav .layui-nav-child a:hover:not(.layui-this) { + background-color: #3b3f4b; +} + +/**左侧菜单选中-配色*/ +.layui-layout-admin .layui-nav-tree .layui-this, .layui-layout-admin .layui-nav-tree .layui-this > a, .layui-layout-admin .layui-nav-tree .layui-nav-child dd.layui-this, .layui-layout-admin .layui-nav-tree .layui-nav-child dd.layui-this a { + background-color: #1aa094 !important; +} + + +/**头部样式 */ +.layui-layout-admin .header { + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; +} + +.layuimini-header-menu, .layui-header { + height: 60px !important; +} + +.layuimini-header-menu > .layui-nav-item { + color: #1b1d21; + height: 60px !important; + line-height: 60px !important; +} + +.layui-header > .layui-layout-right > .layui-nav-item { + height: 60px !important; + line-height: 60px !important; +} + +.layui-layout-left { + left: 295px !important; +} + +.layui-nav.layui-layout-left.layuimini-header-menu.layuimini-pc-show { + font-weight: bold; + transition: all .2s; +} + + +/**logo演示(通用) */ +.layui-layout-admin .layuimini-logo { + font-weight: bold; + color: #ffffff !important; + height: 60px !important; + line-height: 60px !important; + overflow: hidden; + line-height: 64px; + transition: all .2s !important; +} + +.layui-layout-admin .layuimini-logo img { + display: inline-block; + height: 40px; + vertical-align: middle; +} + +.layui-layout-admin .layuimini-logo h1 { + display: inline-block; + margin: 0 0 0 12px; + color: #ffffff; + font-weight: 600; + font-size: 20px; + font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; + vertical-align: middle; +} + +/**缩放工具(通用) */ +.layuimini-tool { + position: absolute !important; + top: 0; + left: 235px; + width: 60px; + height: 100%; + line-height: 60px; + text-align: center; + color: #ffffff !important; + transition: all .2s; +} + +/**缩放工具(缩放) */ +.layuimini-tool i { + display: block; + color: #bbe3df; + width: 32px; + height: 32px; + line-height: 32px; + border-radius: 3px; + text-align: center; + margin-top: 15px; + cursor: pointer; +} + + +.layuimini-page-header { + overflow: hidden; + display: block; + height: 35px; + line-height: 35px; + margin-bottom: 0; + border-radius: 0; + border-bottom: 1px solid #e1dddd; +} + +.layuimini-page-header .layui-breadcrumb { + border-top: 1px solid #f6f6f6; + padding: 0 15px; + visibility: visible; +} + + +/**左侧菜单栏 (通用) */ +.layui-side.layui-bg-black { + transition: all .2s; +} + +.layui-side.layui-bg-black > .layuimini-menu-left > ul { + transition: all .2s; +} + +.layui-side.layui-bg-black > .layuimini-menu-left > ul > .layui-nav-item:first-child { + border-top: 1px solid #4b5461; +} + +.layuimini-menu-left .layui-nav .layui-nav-item a { + height: 40px; + line-height: 40px; + padding-right: 30px; +} + +.layuimini-menu-left .layui-nav .layui-nav-item > a { + padding-top: 5px; + padding-bottom: 5px; +} + +.layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child { + background: 0 0 !important +} + +.layuimini-menu-left .layui-nav .layui-nav-more { + right: 15px; +} + +.layuimini-menu-left .layui-nav .layui-nav-item a:hover { + background-color: transparent !important; +} + +.layuimini-menu-left .layui-nav { + background-color: transparent !important; +} + + +/**左侧菜单栏 (正常) */ +.layui-layout-body .layui-nav-itemed .layui-nav-child a, .layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child a { + padding-left: 35px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child a { + padding-left: 45px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child .layui-nav-child a { + padding-left: 55px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child .layui-nav-child .layui-nav-child a { + padding-left: 65px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-itemed > .layui-nav-child { + padding: 5px 0; +} + +/**内容主体(通用) */ +.layui-layout-admin .layui-body { + /*position: fixed;*/ + overflow: hidden; + bottom: 0px !important; + top: 60px !important; + transition: all .2s; +} + +/**选择配色方案 */ +.layuimini-color .color-title { + padding: 10px 0 10px 20px; + border-bottom: 1px solid #d9dada; + margin-bottom: 8px; +} + +.layuimini-color .color-content { + padding: 10px 5px 0 5px; +} + +.layuimini-color .color-content ul { + list-style: none; + text-align: center; +} + +.layuimini-color .color-content ul li { + position: relative; + display: inline-block; + vertical-align: top; + width: 80px; + height: 50px; + margin: 0 15px 15px 0; + padding: 2px 2px 4px 2px; + background-color: #f2f2f2; + cursor: pointer; + font-size: 12px; + color: #666; +} + +.layuimini-color .color-content li.layui-this:after, .layuimini-color .color-content li:hover:after { + width: 100%; + height: 100%; + padding: 4px; + top: -5px; + left: -5px; + border-color: #d8d8d8; + opacity: 1; +} + +.layuimini-color .color-content li:after { + content: ''; + position: absolute; + z-index: 20; + top: 50%; + left: 50%; + width: 1px; + height: 0; + border: 1px solid #f2f2f2; + transition: all .3s; + -webkit-transition: all .3s; + opacity: 0; +} + + +/**其它 */ +.layui-tab-item { + width: 100% !important; + height: 100% !important; +} + +.layui-nav-item.layui-this { + background-color: #1b1d21; +} + +.layui-width-height { + width: 100%; + height: 95%; +} + +.layui-tab { + margin: 0 0 0 0; + z-index: 99999; +} + +.text-center { + height: 30px !important; + line-height: 30px !important; + text-align: center !important; +} + +.layui-nav { + padding: 0 !important; +} + +.layui-nav .layui-this:after, .layui-nav-bar, .layui-nav-tree .layui-nav-itemed:after { + width: 0 !important; + height: 0 !important; +} + +.layui-layout-admin .layui-side { + top: 60px !important; +} + +.layui-tab-card { + box-shadow: 0px 0px 0px #888888; + border-bottom: 0; +} + + +/*打开页面动画*/ +.layui-tab-item.layui-show { + animation: moveTop 1s; + -webkit-animation: moveTop 1s; + animation-fill-mode: both; + -webkit-animation-fill-mode: both; + position: relative; + height: 100%; + -webkit-overflow-scrolling: touch; + overflow: auto; +} + +@keyframes moveTop { + 0% { + opacity: 0; + -webkit-transform: translateY(30px); + -ms-transform: translateY(30px); + transform: translateY(30px); + } + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +@-o-keyframes moveTop { + 0% { + opacity: 0; + -webkit-transform: translateY(30px); + -ms-transform: translateY(30px); + transform: translateY(30px); + } + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +@-moz-keyframes moveTop { + 0% { + opacity: 0; + -webkit-transform: translateY(30px); + -ms-transform: translateY(30px); + transform: translateY(30px); + } + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +@-webkit-keyframes moveTop { + 0% { + opacity: 0; + -webkit-transform: translateY(30px); + -ms-transform: translateY(30px); + transform: translateY(30px); + } + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +/**自定义滚动条样式 */ +::-webkit-scrollbar { + width: 6px; + height: 6px +} + +::-webkit-scrollbar-track { + background-color: transparent; + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em; +} + +::-webkit-scrollbar-thumb { + background-color: #9c9da0; + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em +} + + +.layuimini-content-page { + overflow: auto; + width: 100%; + height: 100%; +} + + +/*移动端遮罩层*/ +.layuimini-make { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 1000; + background: rgba(0, 0, 0, .5); + display: none; +} + +.layuimini-mini .layui-header { + z-index: 1001; +} + +/**初始化加载层*/ +.layuimini-loader { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #ffffff; + z-index: 999999; +} + +.layuimini-loader .layuimini-loader-inner { + display: block; + position: relative; + left: 50%; + top: 50%; + width: 150px; + height: 150px; + margin: -75px 0 0 -75px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #1E9FFF; + animation: spin 2s linear infinite; +} + +.layuimini-loader .layuimini-loader-inner:before { + content: ""; + position: absolute; + top: 5px; + left: 5px; + right: 5px; + bottom: 5px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #1E9FFF; + animation: spin 3s linear infinite; +} + +.layuimini-loader .layuimini-loader-inner:after { + content: ""; + position: absolute; + top: 15px; + left: 15px; + right: 15px; + bottom: 15px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #1E9FFF; + animation: spin 1.5s linear infinite; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + to { + transform: rotate(1turn); + } +} + +/*系统设置*/ + +.layuimini-color .layui-word-aux { + position: absolute; + left: 60px; + top: 12px; + font-size: 12px; +} + +.layuimini-color .layui-input-block { + margin-left: 15px; + min-height: 36px; +} + +.layuimini-color .more-menu-list { + width: 100%; + margin-top: 30px; +} + + +.layuimini-color .more-menu-item:first-child { + border-top: 1px solid #e8e8e8; +} + +.layuimini-color .more-menu-item .layui-icon { + font-size: 18px; + padding-right: 10px; +} + +.layuimini-color .more-menu-item { + color: #595959; + height: 50px; + line-height: 50px; + font-size: 16px; + padding: 0 25px; + border-bottom: 1px solid #e8e8e8; + font-style: normal; + display: block; +} + +.layuimini-color .more-menu-item:hover { + background-color: whitesmoke; +} + +.layuimini-color .more-menu-item:after { + color: #8c8c8c; + right: 16px; + content: "\e602"; + position: absolute; + font-family: layui-icon !important; +} + +/** +菜单缩放 + */ +.popup-tips .layui-layer-TipsG{ + display: none; +} +.popup-tips.layui-layer-tips .layui-layer-content{ + padding: 0; +} +.popup-tips .layui-nav-tree{ + width: 150px; + border-radius: 10px; +} + +/**左侧菜单字体间距*/ +.layuimini-menu-left .layui-nav-item a span { + letter-spacing: 1px; +} + +/**头部菜单字体间距*/ +.layui-layout-admin .layui-header .layuimini-header-menu.layuimini-pc-show,.layui-layout-admin .layui-header .layuimini-header-menu.layuimini-mobile-show { + letter-spacing: 1px; +} + + +/**左侧菜单更多下拉样式*/ +.layuimini-menu-left .layui-nav-more,.layuimini-menu-left-zoom .layui-nav-more { + font-family: layui-icon !important; + font-size: 12px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow: hidden; + width: auto; + height: auto; + line-height: normal; + border: none; + display: inline-block; + margin-top: -6px !important; +} + +.layuimini-menu-left .layui-nav-child .layui-nav-more { + margin-top: -6px !important; +} + +.layuimini-menu-left .layui-nav .layui-nav-mored,.layuimini-menu-left .layui-nav-itemed>a .layui-nav-more{ + margin-top: -9px!important; +} + +.layuimini-menu-left-zoom.layui-nav .layui-nav-mored,.layuimini-menu-left-zoom.layui-nav-itemed>a .layui-nav-more{ + margin-top: -9px!important; +} + +.layuimini-menu-left .layui-nav-more:before,.layuimini-menu-left-zoom .layui-nav-more:before { + content: "\e61a"; +} +.layuimini-menu-left .layui-nav-itemed > a > .layui-nav-more,.layuimini-menu-left-zoom .layui-nav-itemed > a > .layui-nav-more { + transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -o-transform: rotate(180deg); + width: 12px; + text-align: center; + border-style:none; +} + +.layuimini-menu-left .layui-nav-itemed > a > .layui-nav-more:before,.layuimini-menu-left-zoom .layui-nav-itemed > a > .layui-nav-more:before { + content: '\e61a'; + background-color: transparent; + display: inline-block; + vertical-align: middle; +} + +/**修复左侧菜单字体不对齐的问题*/ +.layuimini-menu-left .layui-nav-item a .fa,.layuimini-menu-left .layui-nav-item a .layui-icon{ + width: 20px; +} + + + +/** + PC版样式 + */ +@media screen and (min-width: 1025px) { + /**头部样式(缩放) */ + .layuimini-mini .layui-layout-left.layuimini-header-menu.layuimini-pc-show { + left: 155px !important; + } + + /**logo演示(缩放) */ + .layuimini-mini .layui-layout-admin .layuimini-logo { + width: 60px !important; + } + + .layuimini-mini .layui-layout-admin .layuimini-logo h1 { + display: none; + } + + /**左侧菜单栏(缩放) */ + .layuimini-mini .layuimini-menu-left { + width: 80px !important; + } + + .layuimini-mini .layui-side.layui-bg-black, .layuimini-mini .layuimini-menu-left > ul, .layuimini-mini .layuimini-menu-left > ul li i { + width: 60px !important; + } + + .layuimini-mini .layuimini-menu-left > ul li span:first-child { + display: none; + } + + .layuimini-mini .layuimini-menu-left > ul li span:last-child { + float: right; + right: 7px; + } + + .layuimini-mini .layuimini-menu-left .layui-nav .layui-nav-item a { + height: 40px; + line-height: 40px; + padding-right: 0px !important; + } + + /**内容主体(缩放) */ + .layuimini-mini .layui-layout-admin .layui-body { + left: 60px !important; + } + + .layuimini-mini .layuimini-tool { + left: 95px !important; + } + + .layuimini-pc-show{ + display: block; + } + .layuimini-mobile-show{ + display: none; + } + + /**菜单缩放*/ + .layuimini-mini .layuimini-menu-left .layui-nav-more,.layuimini-mini .layuimini-menu-left .layui-nav-child{ + display: none!important; + } + +} + +/** + 手机自适应样式 +*/ +@media screen and (max-width: 1024px) { + + .layuimini-pc-show{ + display: none; + } + .layuimini-mobile-show{ + display: block; + } + + .layuimini-header-content { + left: 0; + } + + .layui-layout-admin .layui-body .layui-tab-item.layui-show { + border-top: 1px solid #e2e2e2; + } + + .layuimini-all .layui-layout-left.layuimini-header-menu { + left: 15px !important + } + + .layuimini-mini .layui-layout-left.layuimini-header-menu { + left: 205px !important + } + + .layui-layout-admin .layui-nav.layui-layout-right > li:not(.layuimini-setting) { + width: 40px !important; + } + + .layui-layout-admin .layui-nav.layui-layout-right > li:not(.layuimini-setting) a { + padding: 0 15px; + } + + .layuimini-all .layui-layout-admin .layui-body { + left: 0px !important; + } + + .layuimini-mini .layui-layout-admin .layuimini-menu-left, .layuimini-mini .layui-header .layuimini-logo { + left: 0; + transition: left .2s; + z-index: 1001 !important; + } + + .layuimini-all .layui-layout-admin .layuimini-menu-left, .layuimini-all .layui-header .layuimini-logo { + left: -200px; + transition: left .2s; + top: 0; + z-index: 1002; + } + + .layuimini-mini .layui-layout-admin .layui-body { + left: 0!important; + transition: left .2s; + top: 0; + z-index: 998; + } + + .layuimini-mini .layuimini-make { + display: block; + } + + .layuimini-multi-module .layuimini-header-content .layuimini-tool { + display: none; + } + + .layuimini-single-module .layuimini-header-content .layuimini-tool { + left: 15px; + } + + .layuimini-mini .layuimini-site-mobile { + display: none !important; + } + + .layuimini-site-mobile { + display: block !important; + position: fixed; + z-index: 100000; + bottom: 15px; + left: 15px; + width: 40px; + height: 40px; + line-height: 40px; + border-radius: 2px; + text-align: center; + background-color: rgba(0, 0, 0, .7); + color: #fff; + } + + .layuimini-header-content { + z-index: 997; + } + + .layuimini-content-page { + -webkit-overflow-scrolling: touch; + } + + /*修复UC之类的浏览器点击无效*/ + .layuimini-make { + cursor: pointer; + } + + .layuimini-site-mobile { + cursor: pointer; + } + +} + +@media screen and (max-width: 550px){ + + /**头部右侧数据*/ + .layuimini-multi-module.layuimini-mini .layuimini-header-content .layui-layout-right { + display: none; + } +} diff --git a/sec-beidou/src/main/resources/static/css/public.css b/sec-beidou/src/main/resources/static/css/public.css new file mode 100644 index 00000000..6fbdf171 --- /dev/null +++ b/sec-beidou/src/main/resources/static/css/public.css @@ -0,0 +1,13 @@ +.layuimini-content-page{background-color:#f2f2f2!important;} +.layuimini-container {border:1px solid #f2f2f2;border-radius:5px;background-color:#f2f2f2} +.layuimini-main {margin:10px 10px 10px 10px;border:5px solid #ffffff;border-radius:5px;background-color:#ffffff} +.layui-breadcrumb>* {font-size: 13px;!important;} + +/**必填红点 */ +.layuimini-form>.layui-form-item>.required:after {content:'*';color:red;position:absolute;margin-left:4px;font-weight:bold;line-height:1.8em;top:6px;right:5px;} +.layuimini-form>.layui-form-item>.layui-form-label {width:120px !important;} +.layuimini-form>.layui-form-item>.layui-input-block {margin-left:150px !important;} +.layuimini-form>.layui-form-item>.layui-input-block >tip {display:inline-block;margin-top:10px;line-height:10px;font-size:10px;color:#a29c9c;} + +/**搜索框*/ +.layuimini-container .table-search-fieldset {margin: 0;border: 1px solid #e6e6e6;padding: 10px 20px 5px 20px;color: #6b6b6b;} diff --git a/sec-beidou/src/main/resources/static/css/themes/default.css b/sec-beidou/src/main/resources/static/css/themes/default.css new file mode 100644 index 00000000..4f3cefb3 --- /dev/null +++ b/sec-beidou/src/main/resources/static/css/themes/default.css @@ -0,0 +1,95 @@ +/*头部右侧背景色 headerRightBg */ +.layui-layout-admin .layui-header { + background-color: #ffffff !important; +} + +/*头部右侧选中背景色 headerRightBgThis */ +.layui-layout-admin .layui-header .layuimini-header-content > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover { + background-color: #e4e4e4 !important; +} + +/*头部右侧字体颜色 headerRightColor */ +.layui-layout-admin .layui-header .layui-nav .layui-nav-item a { + color: rgba(107, 107, 107, 0.7); +} + +/**头部右侧下拉字体颜色 headerRightChildColor */ +.layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child a { + color: rgba(107, 107, 107, 0.7) !important; +} + +/*头部右侧鼠标选中 headerRightColorThis */ +.layui-header .layuimini-menu-header-pc.layui-nav .layui-nav-item a:hover, .layui-header .layuimini-header-menu.layuimini-pc-show.layui-nav .layui-this a { + color: #565656 !important; +} + +/*头部右侧更多下拉颜色 headerRightNavMore */ +.layui-header .layui-nav .layui-nav-more { + border-top-color: rgba(160, 160, 160, 0.7) !important; +} + +/*头部右侧更多下拉颜色 headerRightNavMore */ +.layui-header .layui-nav .layui-nav-mored, .layui-header .layui-nav-itemed > a .layui-nav-more { + border-color: transparent transparent rgba(160, 160, 160, 0.7) !important; +} + +/**头部右侧更多下拉配置色 headerRightNavMoreBg headerRightNavMoreColor */ +.layui-header .layui-nav .layui-nav-child dd.layui-this a, .layui-header .layui-nav-child dd.layui-this, .layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child .layui-this a { + background-color: #1E9FFF !important; + color: #ffffff !important; +} + +/*头部缩放按钮样式 headerRightToolColor */ +.layui-layout-admin .layui-header .layuimini-tool i { + color: #565656; +} + +/*logo背景颜色 headerLogoBg */ +.layui-layout-admin .layuimini-logo { + background-color: #192027 !important; +} + +/*logo字体颜色 headerLogoColor */ +.layui-layout-admin .layuimini-logo h1 { + color: rgb(191, 187, 187); +} + +/*左侧菜单更多下拉样式 leftMenuNavMore */ +.layuimini-menu-left .layui-nav .layui-nav-more, .layuimini-menu-left-zoom.layui-nav .layui-nav-more { + border-top-color: rgb(191, 187, 187); +} + +/*左侧菜单更多下拉样式 leftMenuNavMore */ +.layuimini-menu-left .layui-nav .layui-nav-mored, .layuimini-menu-left .layui-nav-itemed > a .layui-nav-more, .layuimini-menu-left-zoom.layui-nav .layui-nav-mored, .layuimini-menu-left-zoom.layui-nav-itemed > a .layui-nav-more { + border-color: transparent transparent rgb(191, 187, 187) !important; +} + +/*左侧菜单背景 leftMenuBg */ +.layui-side.layui-bg-black, .layui-side.layui-bg-black > .layuimini-menu-left > ul, .layuimini-menu-left-zoom > ul { + background-color: #28333E !important; +} + +/*左侧菜单选中背景 leftMenuBgThis */ +.layuimini-menu-left .layui-nav-tree .layui-this, .layuimini-menu-left .layui-nav-tree .layui-this > a, .layuimini-menu-left .layui-nav-tree .layui-nav-child dd.layui-this, .layuimini-menu-left .layui-nav-tree .layui-nav-child dd.layui-this a, .layuimini-menu-left-zoom.layui-nav-tree .layui-this, .layuimini-menu-left-zoom.layui-nav-tree .layui-this > a, .layuimini-menu-left-zoom.layui-nav-tree .layui-nav-child dd.layui-this, .layuimini-menu-left-zoom.layui-nav-tree .layui-nav-child dd.layui-this a { + background-color: #1E9FFF !important +} + +/*左侧菜单子菜单背景 leftMenuChildBg */ +.layuimini-menu-left .layui-nav-itemed > .layui-nav-child { + background-color: #0c0f13 !important; +} + +/*左侧菜单字体颜色 leftMenuColor */ +.layuimini-menu-left .layui-nav .layui-nav-item a, .layuimini-menu-left-zoom.layui-nav .layui-nav-item a { + color: rgb(191, 187, 187) !important; +} + +/*左侧菜单选中字体颜色 leftMenuColorThis */ +.layuimini-menu-left .layui-nav .layui-nav-item a:hover, .layuimini-menu-left .layui-nav .layui-this a, .layuimini-menu-left-zoom.layui-nav .layui-nav-item a:hover, .layuimini-menu-left-zoom.layui-nav .layui-this a { + color: #ffffff !important; +} + +/**tab选项卡选中颜色 tabActiveColor */ +.layuimini-tab .layui-tab-title .layui-this .layuimini-tab-active { + background-color: #1e9fff; +} diff --git a/sec-beidou/src/main/resources/static/images/bg.jpg b/sec-beidou/src/main/resources/static/images/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d5870f5033f1b0ff98b6e94db9f0a84d253c86d3 GIT binary patch literal 26174 zcmb5WeOMgleKz{cFoTDYaCTu9nbk=%S|K_N60yW?iIum>4BFwv8?QaH%p$ar8d=r{ zTCNhQlIk{TlhF#P%OHBdhD2FeC!>)d!vd~kiv}xoiycXqtQZv`ph+sZuADfwn!0V0 zx@r36&AA7qz24LRj%;ArU10b3ao_jv kkh0Q; zxQ9y1xQ95NFI!Pw^^x+GE6Z04p+J@R(MUx6=*K=*BSqKO)NcIEk9};zZ*SNbYudbd z^V<4P$3OjvEz!p|H~GJW;(5M&WqJ4`9|HG3UmpAmQfoFoU7;EW2anSKjHf)}|M-7B zy8Il9p-b>cRq(&vPYC|v_sL59Ejm~dB%da~_+9>!dp`Svu|#fu 1+W1DfBSQQ_Vw4CPL3U?t(|>$(kaa>M`ZcVxD$}LUqYS=IqbNar&!&&+=AXoG^y2 zm@b{SE-7S8ZA%Sn)vQ4n!KhOzhJ@XrFOU69R}zxj_A|ZWJ!yyy{4WyFDuy*YxOYfM z=(ZTi4|QDfxDkaXf+8psF-T@;%*>cUp4HEODL@j$&>2=yDuxwRVFDx|RBkZ>EJFg0 zNKRP!;b-+qWlo7!-_nBuvu9FCYKk&fsoy>j3{kOFDVnzmww3qfZ1#SMG%qBR=3G)+ zm}~9dl M%oyV!?x3;N4J^1zCAE;hfnraGedu#A~X 4`H_p$WydTZI)Ssm{%||w6NA3J&>y6@R zt8jY$gW4aFyjM0hJ?0epyp^_fx_5lc^S;x%vM@Hy*^vv~4IdWDreSC{TK(3b_a>9v z@ojBSxV3C-vRiyKTd;4m3{>BGwxZ+%RvmoTC6_cpKK?@H4J|udxTK9F^vrR&xR5~P zY9mV3F!4i~1T{t~b&8g=Mv+r?S%Qc{P?N P&J+l7X?3+1h(6U1zNF;Q6_|YYpnmO=D6`HHMXa+T0@{qQ$H4w9eJnP1YW(3n$eN zUkeSto3e_gQ