Przeglądaj źródła

qhse体系证书查询

Zimo 1 tydzień temu
rodzic
commit
ffa79a3fbc

+ 38 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/TDDeviceMapper.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceTdVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.TDDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotZHBD.TDLogDO;
+import cn.iocoder.yudao.module.pms.job.SnTsVO;
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import org.apache.ibatis.annotations.Insert;
@@ -186,4 +187,41 @@ public interface TDDeviceMapper extends BaseMapperX<TDDeviceDO> {
     @InterceptorIgnore(tenantLine = "true")
     Integer selectRangeCount(@Param("deviceName") String tableName, @Param("identifier") String identifier,@Param("start") Timestamp start,@Param("end") Timestamp end,
                                     @Param("max") String max,@Param("min") String min);
+
+
+    /**
+     * 批量查询:哪些 device_xxx 子表真实存在
+     * @param fullTbNameList 完整子表名列表:["device_123","device_456"]
+     * @return 真实存在的完整子表名
+     */
+    @Select({"<script>",
+            "SELECT table_name FROM information_schema.ins_tables ",
+            "WHERE table_name IN ",
+            "<foreach collection='fullTbNameList' item='tb' open='(' separator=',' close=')'>",
+            "#{tb}",
+            "</foreach>",
+            "</script>"
+    })
+    @DS("tdengine")
+    @TenantIgnore
+    List<String> batchGetExistFullTbName(@Param("fullTbNameList") List<String> fullTbNameList);
+
+    /**
+     * 超级表批量获取每个设备过滤后最大ts,等价于循环执行selectLastTime
+     * 超级表:iot_log.device,tb_name为完整子表名 device_xxx
+     */
+    @Select({"<script>",
+            "SELECT tb_name, MAX(ts) AS ts ",
+            "FROM iot_log.device ",
+            "WHERE identity NOT IN ('lng','lat','today_distance','distance','todayoil','totaloil','online','oil1','oil2','oil3','oil4','vehicle_name') ",
+            "AND tb_name IN ",
+            "<foreach collection='fullTbNameList' item='tb' open='(' separator=',' close=')'>",
+            "#{tb}",
+            "</foreach>",
+            "GROUP BY tb_name",
+            "</script>"
+    })
+    @DS("tdengine")
+    @TenantIgnore
+    List<SnTsVO> batchQueryFilterLastTs(@Param("fullTbNameList") List<String> fullTbNameList);
 }

+ 13 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/SnTsVO.java

@@ -0,0 +1,13 @@
+package cn.iocoder.yudao.module.pms.job;
+
+import lombok.Data;
+import java.sql.Timestamp;
+
+@Data
+public class SnTsVO {
+    private String sn;
+    /** tb_name 完整子表名 device_xxxx */
+    private String tbName;
+    /** 过滤后最大时间戳 */
+    private Timestamp ts;
+}

+ 217 - 67
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/TdCronJob.java

@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
-import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.YfDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
@@ -21,9 +20,8 @@ import org.springframework.stereotype.Component;
 import javax.annotation.Resource;
 import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Component
 @Slf4j
@@ -40,76 +38,170 @@ public class TdCronJob implements JobHandler {
     @Override
     @TenantIgnore
     public String execute(String param) throws Exception {
-        List<String> codes = new ArrayList<>();
+
+        //1.查询源设备,构建sn -> YfDeviceDO map,避免循环内stream findFirst
         List<YfDeviceDO> allDevice = yfDeviceService.getAllDevice();
-        allDevice.forEach(d -> {
-            codes.add(d.getSerialNumber());
+        Map<String, YfDeviceDO> yfDeviceMap = allDevice.stream()
+                .collect(Collectors.toMap(YfDeviceDO::getSerialNumber, e -> e));
+        List<String> rawSnList = new ArrayList<>(yfDeviceMap.keySet());
+        if(CollUtil.isEmpty(rawSnList)){
+            return "";
+        }
+
+        //2.查询iot设备
+        List<IotDeviceDO> devices = iotDeviceMapper.selectByCodeIn(rawSnList);
+        if (CollUtil.isEmpty(devices)) {
+            return "";
+        }
+
+        // ===================== TDengine批量预处理(替代循环内tableIfExist、selectLastTime) =====================
+        // 子表完整表名:device_${sn}
+        List<String> fullTbNameList = rawSnList.stream()
+                .map(sn -> "device_" + sn)
+                .collect(Collectors.toList());
+        for (String s : fullTbNameList) {
+            System.out.println("--------------"+s);
+        }
+        //批量查询哪些子表真实存在
+        List<String> existFullTbList = deviceMapper.batchGetExistFullTbName(fullTbNameList);
+        existFullTbList.forEach(device -> {
+            System.out.println("%%%%%%%%%%%%%%%%"+device);
         });
-        List<IotDeviceDO> devices = iotDeviceMapper.selectByCodeIn(codes);
+        // key:完整表名 device_xxx ; value:原始sn
+        Map<String, String> fullTbToRawSnMap = new HashMap<>();
+        for (String sn : rawSnList) {
+            fullTbToRawSnMap.put("device_" + sn, sn);
+        }
+
+        //批量查询【带identity过滤条件】每个设备最大ts
+        Map<String, Timestamp> rawSnLastTsMap = new HashMap<>();
+        if (CollUtil.isNotEmpty(existFullTbList)) {
+            List<SnTsVO> snTsVOList = deviceMapper.batchQueryFilterLastTs(existFullTbList);
+            System.out.println("=========================="+JSON.toJSONString(snTsVOList));
+            for (SnTsVO vo : snTsVOList) {
+                String rawSn = fullTbToRawSnMap.get(vo.getTbName());
+                if(rawSn != null && vo.getTs() != null){
+                    rawSnLastTsMap.put(rawSn, vo.getTs());
+                }
+            }
+        }
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+        // ===================== Redis批量获取hash字段,减少网络IO =====================
+        Set<String> deviceCodeSet = devices.stream().map(IotDeviceDO::getDeviceCode).collect(Collectors.toSet());
+        Map<String, Map<Object, Object>> redisHashCache = new HashMap<>();
+        for (String code : deviceCodeSet) {
+            String hashKey = "TSLV:" + code;
+            List<Object> multiGet = redisTemplate.opsForHash().multiGet(hashKey, Arrays.asList("lat", "lng", "online"));
+            Map<Object, Object> fieldMap = new HashMap<>();
+            fieldMap.put("lat", multiGet.get(0));
+            fieldMap.put("lng", multiGet.get(1));
+            fieldMap.put("online", multiGet.get(2));
+            redisHashCache.put(code, fieldMap);
+        }
+
+        // ===================== 业务组装,循环内部不再任何DB调用 =====================
         List<IotDeviceDO> deviceDOS = new ArrayList<>();
         for (IotDeviceDO device : devices) {
             String deviceCode = device.getDeviceCode();
-            allDevice.stream().filter(e -> e.getSerialNumber().equals(deviceCode)).findFirst().ifPresent(e -> {
-                device.setYfDeviceId(e.getDeviceId());
-                Integer i = deviceMapper.tableIfExist(e.getSerialNumber().toLowerCase());
-                if (i==1) {
-                    List<DeviceVO> deviceVOS = deviceMapper.selectLastTime(e.getSerialNumber());
-                    if (CollUtil.isNotEmpty(deviceVOS)) {
-                        Timestamp ts = deviceVOS.get(0).getTs();
-                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                        String format = sdf.format(ts);
-                        device.setLastInlineTime(format);
-                    }
-                }
-                if (e.getStatus()==1) {//未激活状态
-
-                    if (StringUtils.isNotBlank(device.getLastInlineTime())) {
-                        try {
-                            if (DateUtils.checkIfFullDayDifference(device.getLastInlineTime())) {
-                                device.setIfInline(4);
-                            } else {
-                                device.setIfInline(3);
-                            }
-                        } catch (Exception ex) {
-                            throw new RuntimeException(ex.getMessage());
-                        }
-                    } else {
-                        device.setIfInline(4);
-                    }
-
-                    Object lat = redisTemplate.opsForHash().get("TSLV:" + device.getDeviceCode(), "lat");
-                    if (Objects.nonNull(lat)) {
-                        JSONObject jsonObject = JSON.parseObject(lat.toString());
-                        device.setLat(Double.valueOf((String) jsonObject.get("value")));
-                    }
-                    Object lng = redisTemplate.opsForHash().get("TSLV:" + device.getDeviceCode(), "lng");
-                    if (Objects.nonNull(lng)) {
-                        JSONObject jsonObject = JSON.parseObject(lng.toString());
-                        device.setLng(Double.valueOf((String) jsonObject.get("value")));
-                    }
-                    Object online = redisTemplate.opsForHash().get("TSLV:" + device.getDeviceCode(), "online");
-                    if (Objects.nonNull(online)) {
-                        JSONObject jsonObject = JSON.parseObject(online.toString());
-                        String value = String.valueOf(jsonObject.get("value"));
-                        device.setIfInline("true".equals(value)?3:4);
-                    }
-                } else {
-                        if (StringUtils.isNotBlank(device.getLastInlineTime())) {
-                            if (DateUtils.checkIfFullDayDifference(device.getLastInlineTime())) {
-                                device.setIfInline(4);
-                            } else {
-                                device.setIfInline(e.getStatus());
-                            }
-                        } else {
-                            device.setIfInline(4);
-                        }
-                    }
-//                iotDeviceMapper.updateTdCron(device);
-                deviceDOS.add(device);
-            });
+            YfDeviceDO yfDevice = yfDeviceMap.get(deviceCode);
+            if (yfDevice == null) {
+                continue;
+            }
+            device.setYfDeviceId(yfDevice.getDeviceId());
+            String sn = yfDevice.getSerialNumber();
+
+            //从预加载map拿ts,完全替代循环调用selectLastTime
+            Timestamp ts = rawSnLastTsMap.get(sn);
+            if (ts != null) {
+                device.setLastInlineTime(sdf.format(ts));
+            } else {
+                device.setLastInlineTime(null);
+            }
+
+            //填充在线状态逻辑
+            fillInlineStatus(device, yfDevice);
+            //填充经纬度、redis在线标记
+            fillLocationAndOnline(device, redisHashCache.get(deviceCode));
+
+            deviceDOS.add(device);
+        }
+
+        if (CollUtil.isNotEmpty(deviceDOS)) {
+            iotDeviceMapper.updateBatch(deviceDOS);
         }
-        iotDeviceMapper.updateBatch(deviceDOS);
         return "";
+//        List<String> codes = new ArrayList<>();
+//        List<YfDeviceDO> allDevice = yfDeviceService.getAllDevice();
+//        allDevice.forEach(d -> {
+//            codes.add(d.getSerialNumber());
+//        });
+//        List<IotDeviceDO> devices = iotDeviceMapper.selectByCodeIn(codes);
+//        List<IotDeviceDO> deviceDOS = new ArrayList<>();
+//        for (IotDeviceDO device : devices) {
+//            String deviceCode = device.getDeviceCode();
+//            allDevice.stream().filter(e -> e.getSerialNumber().equals(deviceCode)).findFirst().ifPresent(e -> {
+//                device.setYfDeviceId(e.getDeviceId());
+//                Integer i = deviceMapper.tableIfExist(e.getSerialNumber().toLowerCase());
+//                if (i==1) {
+//                    List<DeviceVO> deviceVOS = deviceMapper.selectLastTime(e.getSerialNumber());
+//                    if (CollUtil.isNotEmpty(deviceVOS)) {
+//                        Timestamp ts = deviceVOS.get(0).getTs();
+//                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//                        String format = sdf.format(ts);
+//                        device.setLastInlineTime(format);
+//                    }
+//                }
+//                if (e.getStatus()==1) {//未激活状态
+//
+//                    if (StringUtils.isNotBlank(device.getLastInlineTime())) {
+//                        try {
+//                            if (DateUtils.checkIfFullDayDifference(device.getLastInlineTime())) {
+//                                device.setIfInline(4);
+//                            } else {
+//                                device.setIfInline(3);
+//                            }
+//                        } catch (Exception ex) {
+//                            throw new RuntimeException(ex.getMessage());
+//                        }
+//                    } else {
+//                        device.setIfInline(4);
+//                    }
+//
+//                    Object lat = redisTemplate.opsForHash().get("TSLV:" + device.getDeviceCode(), "lat");
+//                    if (Objects.nonNull(lat)) {
+//                        JSONObject jsonObject = JSON.parseObject(lat.toString());
+//                        device.setLat(Double.valueOf((String) jsonObject.get("value")));
+//                    }
+//                    Object lng = redisTemplate.opsForHash().get("TSLV:" + device.getDeviceCode(), "lng");
+//                    if (Objects.nonNull(lng)) {
+//                        JSONObject jsonObject = JSON.parseObject(lng.toString());
+//                        device.setLng(Double.valueOf((String) jsonObject.get("value")));
+//                    }
+//                    Object online = redisTemplate.opsForHash().get("TSLV:" + device.getDeviceCode(), "online");
+//                    if (Objects.nonNull(online)) {
+//                        JSONObject jsonObject = JSON.parseObject(online.toString());
+//                        String value = String.valueOf(jsonObject.get("value"));
+//                        device.setIfInline("true".equals(value)?3:4);
+//                    }
+//                } else {
+//                        if (StringUtils.isNotBlank(device.getLastInlineTime())) {
+//                            if (DateUtils.checkIfFullDayDifference(device.getLastInlineTime())) {
+//                                device.setIfInline(4);
+//                            } else {
+//                                device.setIfInline(e.getStatus());
+//                            }
+//                        } else {
+//                            device.setIfInline(4);
+//                        }
+//                    }
+////                iotDeviceMapper.updateTdCron(device);
+//                deviceDOS.add(device);
+//            });
+//        }
+//        iotDeviceMapper.updateBatch(deviceDOS);
+//        return "";
     }
 
 
@@ -117,4 +209,62 @@ public class TdCronJob implements JobHandler {
         String abc = "2026-01-21 10:25:40";
         System.out.println(DateUtils.checkIfFullDayDifference(abc));
     }
+
+
+    /**
+     * 填充在线状态逻辑,原业务逻辑完全保留
+     */
+    private void fillInlineStatus(IotDeviceDO device, YfDeviceDO yfDevice) throws Exception {
+        String lastInlineTime = device.getLastInlineTime();
+        Integer yfStatus = yfDevice.getStatus();
+        if (yfStatus == 1) {
+            //未激活状态
+            if (StringUtils.isNotBlank(lastInlineTime)) {
+                if (DateUtils.checkIfFullDayDifference(lastInlineTime)) {
+                    device.setIfInline(4);
+                } else {
+                    device.setIfInline(3);
+                }
+            } else {
+                device.setIfInline(4);
+            }
+        } else {
+            if (StringUtils.isNotBlank(lastInlineTime)) {
+                if (DateUtils.checkIfFullDayDifference(lastInlineTime)) {
+                    device.setIfInline(4);
+                } else {
+                    device.setIfInline(yfStatus);
+                }
+            } else {
+                device.setIfInline(4);
+            }
+        }
+    }
+
+    /**
+     * 填充经纬度、redis的online状态
+     */
+    private void fillLocationAndOnline(IotDeviceDO device, Map<Object, Object> redisFields) {
+        if (redisFields == null) {
+            return;
+        }
+        Object latObj = redisFields.get("lat");
+        if (Objects.nonNull(latObj)) {
+            JSONObject jsonObject = JSON.parseObject(latObj.toString());
+            device.setLat(Double.valueOf(String.valueOf(jsonObject.get("value"))));
+        }
+
+        Object lngObj = redisFields.get("lng");
+        if (Objects.nonNull(lngObj)) {
+            JSONObject jsonObject = JSON.parseObject(lngObj.toString());
+            device.setLng(Double.valueOf(String.valueOf(jsonObject.get("value"))));
+        }
+
+        Object onlineObj = redisFields.get("online");
+        if (Objects.nonNull(onlineObj)) {
+            JSONObject jsonObject = JSON.parseObject(onlineObj.toString());
+            String value = String.valueOf(jsonObject.get("value"));
+            device.setIfInline("true".equals(value) ? 3 : 4);
+        }
+    }
 }