瀏覽代碼

运行记录1219-运行记录日查询优化(数采设备赋值)

yuanchao 1 周之前
父節點
當前提交
309e8b7903

+ 63 - 20
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotopeationfill/IotOpeationFillController.java

@@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotmodeltemplateattrs.vo.Iot
 import cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportSaveReqVO;
+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.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountDataDO;
@@ -1190,12 +1191,13 @@ public class IotOpeationFillController {
         LocalDateTime midDay = LocalDateTime.of(createDate, LocalTime.of(12, 0));
 
         // 批量收集DeviceVO查询参数
-        List<DeviceVO> deviceVOQueries = new ArrayList<>();
+        List<DeviceTdVO> deviceVOQueries = new ArrayList<>();
         List<IotDeviceRunLogDO> logDOQueries = new ArrayList<>();
         for (IotModelTemplateAttrsDO attrsDO : attrsList) {
             if (isVirtualDevice) {
-                DeviceVO dv = new DeviceVO();
+                DeviceTdVO dv = new DeviceTdVO();
                 dv.setDeviceName(deviceCode.toLowerCase());
+                dv.setDeviceName1(deviceCode);
                 dv.setColName(attrsDO.getModelAttr());
                 dv.setTs(startTime);
                 dv.setTs1(endTime);
@@ -1212,12 +1214,40 @@ public class IotOpeationFillController {
         }
 
         // 批量查询(替代循环查询)
-        Map<String, DeviceVO> deviceVOMap = new HashMap<>();
-        if (isVirtualDevice && !deviceVOQueries.isEmpty()) {
-            List<DeviceVO> deviceVOList = iDeviceService.batchGetYesInfo(deviceVOQueries);
+        Map<String, DeviceTdVO> deviceVOMap = new HashMap<>();
+        /*if (isVirtualDevice && !deviceVOQueries.isEmpty()) {
+            List<DeviceTdVO> deviceVOList = iDeviceService.batchGetYesInfo(deviceVOQueries);
             deviceVOMap = deviceVOList.stream()
                     .filter(voObj -> !StringUtils.isEmpty(voObj.getEarliestData()) && !"0.0".equals(voObj.getEarliestData()))
-                    .collect(Collectors.toMap(DeviceVO::getDeviceName, Function.identity()));
+                    .collect(Collectors.toMap(DeviceTdVO::getDeviceName, Function.identity()));
+        }*/
+
+
+        if (isVirtualDevice && !deviceVOQueries.isEmpty()) {
+            List<DeviceTdVO> deviceVOList = iDeviceService.batchGetYesInfo(deviceVOQueries);
+            if(deviceVOList.size()>0){
+
+                deviceVOMap = deviceVOList.stream()
+                        // 增强过滤:排除deviceName为null、earliestData为null/空/0.0的记录
+                        .filter(voObj -> {
+                            // 过滤deviceName为null/空的情况
+                            if (StringUtils.isEmpty(voObj.getColName())) {
+                                return false;
+                            }
+                            // 过滤earliestData为null/空/0.0的情况
+                            String earliest = voObj.getEarliestData();
+                            return earliest != null && !earliest.isEmpty() && !"0.0".equals(earliest);
+                        })
+                        // 使用重载方法:key重复时保留后面的记录(或根据业务选择保留前面的)
+                        .collect(Collectors.toMap(
+                                DeviceTdVO::getColName,  // key:deviceName
+                                Function.identity(),       // value:自身
+                                (v1, v2) -> v2             // 重复key时的合并策略(此处保留后一个)
+                        ));
+            }else{
+                isVirtualDevice = false;
+            }
+
         }
 
         // 批量查询logInfo和maxLog
@@ -1232,32 +1262,45 @@ public class IotOpeationFillController {
 
         // 处理属性数据
         for (IotModelTemplateAttrsDO attrsDO : attrsList) {
-            String attrId = attrsDO.getId().toString();
+            String attrId = attrsDO.getModelAttr();
             String attrName = attrsDO.getName();
             if (isVirtualDevice) {
-                DeviceVO deviceVO = deviceVOMap.get(attrId);
+                DeviceTdVO deviceVO = deviceVOMap.get(attrId);
                 if (deviceVO != null) {
                     // 数采设备逻辑
                     double diff = Double.parseDouble(deviceVO.getLatestData()) - Double.parseDouble(deviceVO.getEarliestData());
                     attrsDO.setFillContent(String.valueOf(diff));
                     attrsDO.setTotalRunTime(BigDecimal.valueOf(Double.parseDouble(deviceVO.getLatestData())));
                     attrsDO.setIsCollection(1);
-                    continue;
+                }else{
+                    IotDeviceRunLogDO logInfo = logInfoMap.get(attrName);
+                    IotDeviceRunLogDO maxLog = maxLogMap.get(attrName);
+
+                    if (logInfo != null) {
+                        attrsDO.setFillContent(logInfo.getFillContent());
+                        attrsDO.setTotalRunTime(logInfo.getTotalRunTime() != null ? logInfo.getTotalRunTime() : BigDecimal.ZERO);
+                    } else {
+                        attrsDO.setFillContent("");
+                        attrsDO.setTotalRunTime(maxLog != null ? maxLog.getTotalRunTime() : BigDecimal.ZERO);
+                    }
+                    attrsDO.setIsCollection(0);
+                }
+            }else{
+                // 非数采设备逻辑
+                IotDeviceRunLogDO logInfo = logInfoMap.get(attrName);
+                IotDeviceRunLogDO maxLog = maxLogMap.get(attrName);
+
+                if (logInfo != null) {
+                    attrsDO.setFillContent(logInfo.getFillContent());
+                    attrsDO.setTotalRunTime(logInfo.getTotalRunTime() != null ? logInfo.getTotalRunTime() : BigDecimal.ZERO);
+                } else {
+                    attrsDO.setFillContent("");
+                    attrsDO.setTotalRunTime(maxLog != null ? maxLog.getTotalRunTime() : BigDecimal.ZERO);
                 }
+                attrsDO.setIsCollection(0);
             }
 
-            // 非数采设备逻辑
-            IotDeviceRunLogDO logInfo = logInfoMap.get(attrName);
-            IotDeviceRunLogDO maxLog = maxLogMap.get(attrName);
 
-            if (logInfo != null) {
-                attrsDO.setFillContent(logInfo.getFillContent());
-                attrsDO.setTotalRunTime(logInfo.getTotalRunTime() != null ? logInfo.getTotalRunTime() : BigDecimal.ZERO);
-            } else {
-                attrsDO.setFillContent("");
-                attrsDO.setTotalRunTime(maxLog != null ? maxLog.getTotalRunTime() : BigDecimal.ZERO);
-            }
-            attrsDO.setIsCollection(0);
         }
     }
 

+ 259 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/DeviceTdVO.java

@@ -0,0 +1,259 @@
+package cn.iocoder.yudao.module.pms.controller.admin.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.data.annotation.Transient;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.util.Date;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+
+/**
+ * 设备对象 iot_device
+ *
+ * @author kerwincui
+ * @date 2021-12-16
+ */
+@Schema(description = "管理后台 - 设备台账分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class DeviceTdVO extends PageParam {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description="表名称")
+    private String deviceName;
+
+    private String deviceName1;
+
+    /**
+     * 设备ID
+     */
+    @Schema(description="设备ID")
+    private Timestamp ts;
+
+    private Timestamp ts1;
+
+    /**
+     * 设备名称
+     */
+    @Schema(description="设备名称")
+    private String logValue;
+
+    /**
+     * 产品ID
+     */
+    @Schema(description="产品ID")
+    private String identity;
+
+    /**
+     * 产品名称
+     */
+    @Schema(description="产品名称")
+    private String productName;
+
+
+    /**
+     * 租户ID
+     */
+    @Schema(description="租户ID")
+    private Long tenantId;
+
+    /**
+     * 租户名称
+     */
+    @Schema(description="租户名称")
+    private String tenantName;
+
+    /**
+     * 设备编号
+     */
+    @Schema(description="设备编号")
+    private String serialNumber;
+
+    /**
+     * 固件版本
+     */
+    @Schema(description="固件版本")
+    private BigDecimal firmwareVersion;
+
+    /**
+     * 设备类型(1-直连设备、2-网关设备、3-监控设备)
+     */
+    @Schema(description="设备类型(1-直连设备、2-网关设备、3-监控设备 4-网关子设备)")
+    private Integer deviceType;
+
+    /**
+     * 设备状态(1-未激活,2-禁用,3-在线,4-离线)
+     */
+    @Schema(description="设备状态(1-未激活,2-禁用,3-在线,4-离线)")
+    private Integer status;
+
+    /**
+     * wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])
+     */
+    @Schema(description="wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])")
+    private Integer rssi;
+
+    /**
+     * 设备影子
+     */
+    @Schema(description="是否启用设备影子(0=禁用,1=启用)")
+    private Integer isShadow;
+
+    /**
+     * 设备所在地址
+     */
+    @Schema(description="设备所在地址")
+    private String networkAddress;
+
+    /**
+     * 设备入网IP
+     */
+    @Schema(description="设备入网IP")
+    private String networkIp;
+
+    /**
+     * 设备经度
+     */
+    @Schema(description="设备经度")
+    private BigDecimal longitude;
+
+    /**
+     * 设备纬度
+     */
+    @Schema(description="设备纬度")
+    private BigDecimal latitude;
+
+    /**
+     * 激活时间
+     */
+    @Schema(description="激活时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date activeTime;
+
+    /**
+     * 子设备网关编号
+     */
+    @Schema(description="子设备网关编号")
+    private String gwDevCode;
+
+    /**
+     * 物模型值
+     */
+    @Schema(description="物模型值")
+    private String thingsModelValue;
+
+    /**
+     * 图片地址
+     */
+    @Schema(description="图片地址")
+    private String imgUrl;
+
+    /**
+     * 是否自定义位置
+     **/
+    @Schema(description="定位方式(1=ip自动定位,2=设备定位,3=自定义)")
+    private Integer locationWay;
+
+    /**
+     * 设备摘要
+     **/
+    @Schema(description="设备摘要")
+    private String summary;
+
+    /**
+     * 分组ID,用于分组查询
+     **/
+    @Schema(description="分组ID,用于分组查询")
+    private Long groupId;
+
+    /**
+     * 是否设备所有者,用于查询
+     **/
+    @Schema(description="是否设备所有者,用于查询")
+    private Integer isOwner;
+    /**
+     * 子设备数量
+     */
+    @Schema(description="子设备数量")
+    private Integer subDeviceCount;
+    /**
+     * 是否是模拟设备
+     */
+    @Schema(description="是否是模拟设备")
+    private Integer isSimulate;
+    /**
+     * 子设备地址
+     */
+    @Schema(description="子设备地址")
+    private Integer slaveId;
+    /**
+     * 设备传输协议
+     */
+    @Schema(description="设备传输协议")
+    private String transport;
+
+    @Transient
+    @Schema(description="机构id")
+    private Long deptId;
+
+    @Transient
+    @Schema(description="是否显示下级")
+    private Boolean showChild;
+
+    private List<DeviceTdVO> subDeviceList;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @Schema(description="删除标志")
+    private String delFlag;
+
+    /**
+     * 关联组态,来源产品
+     */
+    private String guid;
+
+    //private List<SipRelation> sipRelationList;
+
+    private String clientId;
+
+    /**
+     * 发布
+     * */
+    private String postDev;
+
+    /**
+     * 订阅
+     * */
+    private String getDev;
+
+    private int mqttstats;
+
+    private String protocolCode;
+
+    private String colName;
+
+    private String earliestData;
+    private String latestData;
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    private Long timestamp;
+    private Double value;
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDate createTime;
+
+}

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

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pms.dal.mysql;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+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.iotZHBD.DeviceLogDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.TDDeviceDO;
@@ -82,11 +83,11 @@ public interface TDDeviceMapper extends BaseMapperX<TDDeviceDO> {
     DeviceVO getYesInfo(@Param("deviceName") String tableName, @Param("colName") String colName, @Param("ts") Timestamp ts,@Param("ts1")Timestamp ts1);
 
     // 7. 批量查询DeviceVO
-    @Select("<script>" +
+    /*@Select("<script>" +
             "<foreach collection='queries' item='item' index='index' separator='UNION ALL'>" +
             "SELECT" +
-            /*"  #{item.tableName} AS table_name," + // 关联入参表名
-            "  #{item.colName} AS col_name," +     // 关联入参列名*/
+            "  #{item.deviceName1} AS device_name," + // 关联入参表名
+            "  #{item.colName} AS col_name," +     // 关联入参列名
             "  FIRST(log_value) AS earliest_data," +
             "  LAST(log_value) AS latest_data" +
             " FROM iot_log.device_${item.deviceName}" + // 表名动态拼接(注意SQL注入风险)
@@ -96,10 +97,30 @@ public interface TDDeviceMapper extends BaseMapperX<TDDeviceDO> {
             "  AND log_value != 0.0" +
             "  AND _c0 IS NOT NULL" +
             "</foreach>" +
+            "</script>")*/
+    @Select("<script>" +
+            "<foreach collection='queries' item='item' index='index' separator='UNION ALL'>" +
+            "SELECT" +
+            "  CONCAT('', #{item.deviceName1}) AS device_name," + // 强制拼接空字符串,确保单引号
+            "  CONCAT('', #{item.colName}) AS col_name," +         // 同理,确保 col_name 带单引号
+            "  FIRST(log_value) AS earliest_data," +
+            "  LAST(log_value) AS latest_data" +
+            " FROM iot_log.device_${item.deviceName}" + // 确认表名大小写与实际一致(必须完全匹配)
+            " WHERE" +
+            "  ts BETWEEN #{item.ts} AND #{item.ts1}" +
+            "  AND log_value != 0.0" +
+            "  AND _c0 IS NOT NULL" +
+            "  <if test='item.colName != null and item.colName != \"\"'>" + // 增加空字符串判断
+            "    AND identity = #{item.colName}" +
+            "  </if>" +
+            "  <if test='item.colName == null or item.colName == \"\"'>" + // 空字符串也按 IS NULL 处理
+            "    AND identity IS NULL" +
+            "  </if>" +
+            "</foreach>" +
             "</script>")
     @DS("tdengine")
     @TenantIgnore
-    List<DeviceVO> batchGetYesInfo(@Param("queries") List<DeviceVO> queries);
+    List<DeviceTdVO> batchGetYesInfo(@Param("queries") List<DeviceTdVO> queries);
 
 
     @Select("SELECT   _WSTART AS ts, AVG(CAST(log_value AS FLOAT)) as log_value   FROM iot_log.device_${deviceName} " +

+ 2 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/DeviceServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.pms.service;
 
 
+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.mysql.TDDeviceMapper;
 import org.slf4j.Logger;
@@ -52,7 +53,7 @@ public class DeviceServiceImpl implements IDeviceService {
     }
 
     @Override
-    public List<DeviceVO> batchGetYesInfo(List<DeviceVO> queries) {
+    public List<DeviceTdVO> batchGetYesInfo(List<DeviceTdVO> queries) {
         return deviceMapper.batchGetYesInfo(queries);
     }
 

+ 2 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/IDeviceService.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.pms.service;
 
+import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceTdVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
 import org.apache.ibatis.annotations.Param;
 
@@ -34,6 +35,6 @@ public interface IDeviceService {
 
     DeviceVO getYesInfo(DeviceVO deviceVO);
 
-    List<DeviceVO> batchGetYesInfo(List<DeviceVO> queries);
+    List<DeviceTdVO> batchGetYesInfo(List<DeviceTdVO> queries);
 
 }