diff --git a/sec-api/src/main/java/com/imdroid/secapi/client/RtcmClient.java b/sec-api/src/main/java/com/imdroid/secapi/client/RtcmClient.java index 50442e01..412f3b39 100644 --- a/sec-api/src/main/java/com/imdroid/secapi/client/RtcmClient.java +++ b/sec-api/src/main/java/com/imdroid/secapi/client/RtcmClient.java @@ -17,7 +17,7 @@ public interface RtcmClient { @GetMapping(value = "/get_device_info") public HttpResp getDeviceInfo(@RequestParam(name = "deviceId") String deviceId, @RequestParam(name = "cmd") String cmd); @PostMapping("/device_param_changed") - HttpResp deviceParamChanged(@RequestParam(name = "deviceId") String deviceId,@RequestParam(name = "oldParentId") String oldParentId); + HttpResp deviceParamChanged(@RequestParam(name = "deviceId") String deviceId,@RequestParam(name = "oldParentId") String oldParentId, @RequestParam("oldParentId1") String oldParentId1); @PostMapping("/group_param_changed") HttpResp groupParamChanged(); diff --git a/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDevice.java b/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDevice.java index 756f2ea3..9f58e9e2 100644 --- a/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDevice.java +++ b/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDevice.java @@ -40,6 +40,7 @@ public class GnssDevice { private String fwddeviceid; //推送的设备名 private String name; private String parentid; + private String parentid1; private Integer devicetype; private String tenantname; private String project_id; diff --git a/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDeviceJoin.java b/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDeviceJoin.java index 7fdc8e21..3a9760a8 100644 --- a/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDeviceJoin.java +++ b/sec-api/src/main/java/com/imdroid/secapi/dto/GnssDeviceJoin.java @@ -22,6 +22,7 @@ public class GnssDeviceJoin { private String fwddeviceid; //推送的设备名 private String name; private String parentid; + private String parentid1; private Integer devicetype; private String tenantname; private String project_id; 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 index f6de9b97..48c2f7d9 100644 --- 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 @@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -60,11 +61,17 @@ public class D331RtcmMessageExecutor implements Executor // 推送基站数据 if(deviceBs.getOpMode() == GnssDevice.OP_MODE_USE) { byte[] forwardBytes = message.getSrcData(); - // 要求快速转发,因此用缓存,不要每次都查数据库 - List deviceList = deviceService.findByParentId(id); - //logger.debug("base station {} has {} rovers: ", message.getId(),deviceList.size()); + // 获取使用该基站(包括作为主基站和备选基站)的所有测站 + List primaryDevices = deviceService.findByParentId(id); + List backupDevices = deviceService.findByParentId1(id); + + // 合并两个列表 + List allDevices = new ArrayList<>(); + allDevices.addAll(primaryDevices); + allDevices.addAll(backupDevices); + DeviceChannel deviceChannel = null; - for (Device device : deviceList) { + for (Device device : allDevices) { if (device.getOpMode() != GnssDevice.OP_MODE_USE) continue; if (device.getFixedNum()>0 && device.getGnssSampleRate()>1 && (deviceBs.getD3xxCount()%device.getGnssSampleRate()) != 0) { @@ -72,6 +79,23 @@ public class D331RtcmMessageExecutor implements Executor continue; } String deviceId = device.getDeviceId(); +<<<<<<< HEAD +======= + + // 检查该设备是否应该接收此基站的数据 + String primaryBaseId = device.getParentId(); + String backupBaseId = device.getParentId1(); + + // 如果当前基站是该设备的备选基站,需要检查主基站是否离线 + if (id.equals(backupBaseId)) { + Device primaryBase = deviceService.findByDeviceId(primaryBaseId); + // 如果主基站仍然在线,则跳过备选基站的数据 + if (primaryBase != null && isBaseStationOnline(primaryBase)) { + continue; + } + } + +>>>>>>> 3f0aa45 (添加备选基站) // 获取设备通道并发送数据 if(device.getDataChannelType() == Device.CHANNEL_TYPE_UDP) { deviceChannel = OnlineChannels.INSTANCE.getDataChannel(deviceId); @@ -79,6 +103,7 @@ public class D331RtcmMessageExecutor implements Executor deviceChannel = OnlineChannels.INSTANCE.getConfigChannel(deviceId); } +<<<<<<< HEAD // 读取数据库中model字段,判断基站类型 Short baseStationModel = deviceBs.getModel(); // 如果model为null,使用默认值0 @@ -96,6 +121,11 @@ public class D331RtcmMessageExecutor implements Executor ByteBuf buf = Unpooled.buffer(); buf.writeBytes(forwardBytes); deviceChannel.writeAndFlush(buf); +======= + if(deviceChannel != null && deviceChannel.isOnline()) { + if (logger.isDebugEnabled()) { + logger.debug("forward d331 rtcm from {} to device {}", id, deviceId); +>>>>>>> 3f0aa45 (添加备选基站) } } else if (baseStationModel == 0) { //logger.info("Base station model is 0 for device: {}", deviceId); @@ -297,4 +327,24 @@ public class D331RtcmMessageExecutor implements Executor public Class getMessageType() { return D331RtcmMessage.class; } +<<<<<<< HEAD } +======= + + /** + * 判断住基站是否在线 + * @param baseStation 基站 + * @return 是否在线 + */ + + private boolean isBaseStationOnline(Device baseStation){ + if(baseStation == null) return false; + + LocalDateTime now =LocalDateTime.now(); + return baseStation.getLastRxTime() !=null && + baseStation.getLastRxTime().isAfter(now.minusMinutes(30)); + } + + +} +>>>>>>> 3f0aa45 (添加备选基站) 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..09b09023 --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/DbDeviceServiceImpl.java @@ -0,0 +1,109 @@ +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 org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * 描述 + * + * @author LiGang + */ +@Component(value = "db") +public class DbDeviceServiceImpl implements DeviceService { + + @Autowired + private GnssDeviceMapper gnssDeviceRepository; + + @Override + public Device findByDeviceId(String deviceId) { + GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId); + if (gnssDevice == null) { + return null; + } + Device device = new Device(); + device.setTenantId(gnssDevice.getTenantid()); + device.setDeviceId(gnssDevice.getDeviceid()); + device.setDeviceType(gnssDevice.getDevicetype()); + device.setModel(gnssDevice.getModel()); + device.setParentId(gnssDevice.getParentid()); + device.setParentId1(gnssDevice.getParentid1()); + device.setName(gnssDevice.getName()); + device.setProjectId(gnssDevice.getProject_id()); + device.setCalcGroupId(gnssDevice.getCalc_group_id()); + device.setOpMode(gnssDevice.getOpmode()); + device.setFwdId(gnssDevice.getFwd_group_id()); + device.setIPose(gnssDevice.getIpose()); + device.setIPosn(gnssDevice.getIposn()); + device.setIPosd(gnssDevice.getIposd()); + device.setEcefx(gnssDevice.getEcefx()); + device.setEcefy(gnssDevice.getEcefy()); + device.setEcefz(gnssDevice.getEcefz()); + device.setLoggingmode(gnssDevice.getLoggingmode()); + device.setIccid(gnssDevice.getIccid()); + 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.setParentId1(gnssDevice.getParentid1()); + device.setName(gnssDevice.getName()); + device.setProjectId(gnssDevice.getProject_id()); + device.setCalcGroupId(gnssDevice.getCalc_group_id()); + device.setOpMode(gnssDevice.getOpmode()); + device.setFwdId(gnssDevice.getFwd_group_id()); + device.setIPose(gnssDevice.getIpose()); + device.setIPosn(gnssDevice.getIposn()); + device.setIPosd(gnssDevice.getIposd()); + device.setEcefx(gnssDevice.getEcefx()); + device.setEcefy(gnssDevice.getEcefy()); + device.setEcefz(gnssDevice.getEcefz()); + deviceList.add(device); + } + return deviceList; + } + + @Override + public List findByParentId1(String parentId1) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("parentid1", parentId1); + 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.setParentId1(gnssDevice.getParentid1()); // 添加备选基站ID + device.setName(gnssDevice.getName()); + device.setProjectId(gnssDevice.getProject_id()); + device.setCalcGroupId(gnssDevice.getCalc_group_id()); + device.setOpMode(gnssDevice.getOpmode()); + device.setFwdId(gnssDevice.getFwd_group_id()); + device.setIPose(gnssDevice.getIpose()); + device.setIPosn(gnssDevice.getIposn()); + device.setIPosd(gnssDevice.getIposd()); + device.setEcefx(gnssDevice.getEcefx()); + device.setEcefy(gnssDevice.getEcefy()); + device.setEcefz(gnssDevice.getEcefz()); + deviceList.add(device); + } + return deviceList; + } + +} 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..6652d22f --- /dev/null +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/sal/LocalDeviceServiceImpl.java @@ -0,0 +1,93 @@ +package com.imdroid.sideslope.sal; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.ArrayList; +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 final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /*static RemovalListener removalListener = new RemovalListener() { + public void onRemoval(RemovalNotification removal) { + + } + };*/ + private static final Cache deviceCache = CacheBuilder.newBuilder(). + expireAfterAccess(20, TimeUnit.MINUTES).build(); + + private static final Cache> subDeviceCache = CacheBuilder.newBuilder(). + expireAfterAccess(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) { + logger.debug("base station {} refresh: "+parentId); + device = delegate.findByParentId(parentId); + if (device != null) { + subDeviceCache.put(parentId, device); + } + } + return device; + } + + @Override + public List findByParentId1(String parentId1) { + if (parentId1 == null || parentId1.trim().isEmpty()){ + return new ArrayList<>(); + } + List device = subDeviceCache.getIfPresent("backup_" + parentId1); // 使用前缀区分备选基站的缓存 + if (device == null) { + logger.debug("backup base station {} refresh: " + parentId1); + device = delegate.findByParentId1(parentId1); + if (device != null) { + subDeviceCache.put("backup_" + parentId1, device); + } + } + return device; + } + + public void refresh(String deviceId, String oldParentId){ + Device device = deviceCache.getIfPresent(deviceId); + if (device != null) { + if(device.getParentId()!=null) { + subDeviceCache.invalidate(device.getParentId()); + if(oldParentId!=null && !oldParentId.equals(device.getParentId())){ + subDeviceCache.invalidate(oldParentId); + } + } + + if(device.getParentId1() != null || !device.getParentId1().trim().isEmpty()){ + subDeviceCache.invalidate("back_"+device.getParentId1()); + } + deviceCache.invalidate(deviceId); + } + } +} diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/Device.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/Device.java index af1c692c..0e46f102 100644 --- a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/Device.java +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/Device.java @@ -36,6 +36,7 @@ public class Device { private String deviceId; private String parentId; + private String parentId1; private String projectId; private String fwdId; diff --git a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DeviceService.java b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DeviceService.java index 7d927672..077d8798 100644 --- a/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DeviceService.java +++ b/sec-beidou-rtcm/src/main/java/com/imdroid/sideslope/service/DeviceService.java @@ -11,4 +11,6 @@ public interface DeviceService { Device findByDeviceId(String deviceId); List findByParentId(String parentId); + + List findByParentId1(String parentId1); } 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 index 28986a21..a4c3599f 100644 --- a/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssDeviceController.java +++ b/sec-beidou/src/main/java/com/imdroid/beidou/controller/GnssDeviceController.java @@ -24,6 +24,7 @@ import javax.servlet.http.HttpSession; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Objects; @Controller public class GnssDeviceController extends BasicController{ @@ -143,6 +144,11 @@ public class GnssDeviceController extends BasicController{ if (StringUtils.hasText(parentid)) { queryWrapper.like("parentid", parentid); } + //备选基站 + String parentid1 = search.getString("parentid1"); + if (StringUtils.hasText(parentid1)){ + queryWrapper.like("parentid1", parentid1); + } //项目号 String project_id = search.getString("project_id"); if (StringUtils.hasText(project_id)) { @@ -237,7 +243,9 @@ public class GnssDeviceController extends BasicController{ OpLogManager.OP_OBJ_DEVICE, device.getDeviceid() + " update: " + diff); device.setUpdatetime(LocalDateTime.now()); - if(!old_device.getGroup_id().equals(device.getGroup_id())){ + if(!old_device.getGroup_id().equals(device.getGroup_id())|| + !old_device.getParentid().equals(device.getParentid())|| + !Objects.equals(old_device.getParentid1(),device.getParentid1())){ device.setSyn(false); } num = gnssDeviceMapper.updateById(device); @@ -258,7 +266,7 @@ public class GnssDeviceController extends BasicController{ } else { // 更新组参数的关联个数 updateBasicGroupAssociatedNum(device,old_device); - rtcmClient.deviceParamChanged(device.getDeviceid(), device.getParentid()); + rtcmClient.deviceParamChanged(device.getDeviceid(), device.getParentid(), device.getParentid1()); return HttpResult.ok(); } } @@ -380,7 +388,7 @@ public class GnssDeviceController extends BasicController{ if (num == 0) { return HttpResult.failed(); } else{ - rtcmClient.deviceParamChanged(del_id, null); + rtcmClient.deviceParamChanged(del_id, null, null); return HttpResult.ok(); } } diff --git a/sec-beidou/src/main/resources/templates/page/gnss_dev_cfg.html b/sec-beidou/src/main/resources/templates/page/gnss_dev_cfg.html index eec193d9..c4afdee3 100644 --- a/sec-beidou/src/main/resources/templates/page/gnss_dev_cfg.html +++ b/sec-beidou/src/main/resources/templates/page/gnss_dev_cfg.html @@ -30,6 +30,12 @@ +
+ +
+ +
+
@@ -128,6 +134,7 @@ {field: 'group_id', title: '基本参数组', width: 60, sort: true}, {field: 'calc_group_id', title: '解算参数组', width: 60, sort: true}, {field: 'parentid', title: '基站编号', width: 80, sort: true}, + {field: 'parentid1', title: '备选基站', width: 80, sort: true}, {field: 'tenantname', title: '所属组织', width: 120}, {field: 'fwd_group_id', title: '推送组', width: 80}, {field: 'fwd_group_id2', title: '推送2', width: 80}, diff --git a/sec-beidou/src/main/resources/templates/page/table/gnss_add_dev.html b/sec-beidou/src/main/resources/templates/page/table/gnss_add_dev.html index 5e311686..f81d561f 100644 --- a/sec-beidou/src/main/resources/templates/page/table/gnss_add_dev.html +++ b/sec-beidou/src/main/resources/templates/page/table/gnss_add_dev.html @@ -82,6 +82,12 @@
+
+ +
+ +
+
@@ -299,6 +305,42 @@ } } +<<<<<<< HEAD +======= + function setParams(data){ + var form = layui.form, + $ = layui.$; + var device_id = $('#deviceid'); + device_id.val(data.deviceid); + device_id.attr('readonly',true); + $('#name').val(data.name); + $('#devicetype').val(data.devicetype); + $('#parentid').val(data.parentid); + $('#parentid1').val(data.parentid1); + $('#tenantname').val(data.tenantname); + $('#project_id').val(data.project_id); + $('#project2_id').val(data.project2_id); + $('#group_id').val(data.group_id); + $('#calc_group_id').val(data.calc_group_id); + $('#fwd_group_id').val(data.fwd_group_id); + $('#fwd_group_id2').val(data.fwd_group_id2); + $('#opmode').val(data.opmode); + $('#loggingmode').val(data.loggingmode); + $('#fwddeviceid').val(data.fwddeviceid); + $('#ipose').val(data.ipose); + $('#iposn').val(data.iposn); + $('#iposd').val(data.iposd); + $('#ecefx').val(data.ecefx); + $('#ecefy').val(data.ecefy); + $('#ecefz').val(data.ecefz); + $('#model').val(data.model); + $('#sector').val(data.sector); + $('#remark').val(data.remark); + $('#iccid').val(data.iccid); + setEcefEditor(); + form.render(); + } +>>>>>>> 3f0aa45 (添加备选基站)