jackzhou 6 місяців тому
батько
коміт
7d2050e6a6
15 змінених файлів з 546 додано та 246 видалено
  1. 35 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/ComparisonOperator.java
  2. 39 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/SensorData.java
  3. 152 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/SensorDataService.java
  4. 32 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/SensorQueryCondition.java
  5. 10 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/config/JfcloudColdChainConstants.java
  6. 79 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/util/DateFormatter.java
  7. 55 62
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/controller/AppController.java
  8. 9 56
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDevice.java
  9. 4 18
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDeviceData.java
  10. 2 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/DeviceStatus.java
  11. 12 29
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/mock/AppDeviceTestDataGenerator.java
  12. 85 71
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/service/AppDeviceService.java
  13. 9 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/MonitorDeviceService.java
  14. 23 4
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/impl/MonitorDeviceServiceImpl.java
  15. 0 5
      snowy-plugin/snowy-plugin-sys/pom.xml

+ 35 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/ComparisonOperator.java

@@ -0,0 +1,35 @@
+package vip.xiaonuo.coldchain.core.bean.influxdb;
+
+/**
+ * @author jackzhou
+ * @version 1.0
+ * @project jfcloud-coldchain
+ * @description
+ * @date 2024/11/22 15:45:35
+ */
+public enum ComparisonOperator {
+    GT(">"),
+    LT("<"),
+    GTE(">="),
+    LTE("<=");
+
+    private final String operator;
+
+    ComparisonOperator(String operator) {
+        this.operator = operator;
+    }
+
+    // 根据字符串获取对应的枚举
+    public static ComparisonOperator fromString(String operator) {
+        for (ComparisonOperator op : ComparisonOperator.values()) {
+            if (op.operator.equalsIgnoreCase(operator)) {
+                return op;
+            }
+        }
+        throw new IllegalArgumentException("Invalid operator: " + operator);
+    }
+
+    public String getOperator() {
+        return operator;
+    }
+}

+ 39 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/SensorData.java

@@ -11,15 +11,22 @@ package vip.xiaonuo.coldchain.core.bean.influxdb;
 import com.github.jfcloud.influxdb.model.JfcloudInFluxEntity;
 import com.influxdb.annotations.Column;
 import com.influxdb.annotations.Measurement;
+import com.influxdb.query.FluxRecord;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import lombok.SneakyThrows;
+import vip.xiaonuo.coldchain.core.config.JfcloudColdChainConstants;
 import vip.xiaonuo.coldchain.core.service.dataprocess.model.PowerEnum;
 
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+import java.util.Optional;
+
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-@Measurement(name = "sensor_data")
+@Measurement(name = JfcloudColdChainConstants.INFLUXDB_DEFAULT_MEASUREMENT_NAME)
 public class SensorData extends JfcloudInFluxEntity {
     /**
      * 温度字段
@@ -87,4 +94,35 @@ public class SensorData extends JfcloudInFluxEntity {
     @Column(name = "model_name", tag = true)
     private String modelName;
 
+    @SneakyThrows
+    public static SensorData mapToSensorData(FluxRecord record) {
+        SensorData sensorData = new SensorData();
+        // Safely extract values and handle nulls
+        sensorData.setDeviceId(Optional.ofNullable(record.getValueByKey("device_id")).map(Object::toString).orElse(null));
+        sensorData.setRoads(getIntegerValue(record, "roads"));
+        sensorData.setTemperature(getDoubleValue(record, "temperature"));
+        sensorData.setHumidity(getDoubleValue(record, "humidity"));
+        sensorData.setCo2(getDoubleValue(record, "co2"));
+        sensorData.setBattery(getDoubleValue(record, "battery"));
+        sensorData.setPlugInStatus(Optional.ofNullable(record.getValueByKey("plugInStatus")).map(Object::toString).orElse(null));
+        sensorData.setLocation(Optional.ofNullable(record.getValueByKey("location")).map(Object::toString).orElse(null));
+        sensorData.setLng(getDoubleValue(record, "longitude"));
+        sensorData.setLat(getDoubleValue(record, "latitude"));
+        Instant time = record.getTime();
+        if (time != null) {
+            sensorData.setTime(Instant.parse(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(time)));
+        }
+        return sensorData;
+    }
+
+    // Helper method to safely extract Integer values
+    private static Integer getIntegerValue(FluxRecord record, String key) {
+        return Optional.ofNullable(record.getValueByKey(key)).map(value -> (Integer) value).orElse(null);
+    }
+
+    // Helper method to safely extract Double values
+    private static Double getDoubleValue(FluxRecord record, String key) {
+        return Optional.ofNullable(record.getValueByKey(key)).map(value -> (Double) value).orElse(null);
+    }
+
 }

+ 152 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/SensorDataService.java

@@ -0,0 +1,152 @@
+package vip.xiaonuo.coldchain.core.bean.influxdb;
+
+import com.github.jfcloud.influxdb.config.JfcloudInfluxDB2Properties;
+import com.github.jfcloud.influxdb.service.JfcloudInfluxDBService;
+import com.influxdb.annotations.Column;
+import com.influxdb.annotations.Measurement;
+import com.influxdb.client.QueryApi;
+import com.influxdb.query.FluxTable;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import vip.xiaonuo.coldchain.core.config.JfcloudColdChainConstants;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @description: Service for querying SensorData from InfluxDB
+ */
+@Component
+@RequiredArgsConstructor
+public class SensorDataService {
+
+    private final JfcloudInfluxDBService jfcloudInfluxDBService;
+    private final JfcloudInfluxDB2Properties jfcloudInfluxDB2Properties;
+
+    /**
+     * 获取 measurement(表名)通过反射
+     *
+     * @param clazz 要查询的实体类
+     * @return measurement(表名)
+     */
+    public String getMeasurement(Class<?> clazz) {
+        Measurement measurement = clazz.getAnnotation(Measurement.class);
+        if (measurement != null) {
+            return measurement.name();
+        }
+        // 默认表名
+        return JfcloudColdChainConstants.INFLUXDB_DEFAULT_MEASUREMENT_NAME;
+    }
+
+    /**
+     * 获取所有的字段名称,通过反射
+     *
+     * @param clazz 要查询的实体类
+     * @return 字段名称列表
+     */
+    public List<String> getFieldNames(Class<?> clazz) {
+        return Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(Column.class)).map(field -> field.getAnnotation(Column.class).name()).collect(Collectors.toList());
+    }
+
+    /**
+     * 构建 Flux 查询语句的公共方法
+     *
+     * @param deviceId        设备 ID
+     * @param roads           路数
+     * @param startTime       查询开始时间
+     * @param endTime         查询结束时间
+     * @param queryConditions 其他查询条件(如温度、湿度等)
+     * @param sensorDataClass SensorData 类
+     * @return 构建的 Flux 查询语句
+     */
+    public String buildFluxQuery(String deviceId, int roads, Instant startTime, Instant endTime, List<SensorQueryCondition> queryConditions, Class<?> sensorDataClass) {
+        StringBuilder fluxQuery = new StringBuilder();
+
+        // 获取 measurement(表名)
+        String measurement = getMeasurement(sensorDataClass);
+
+        // 获取字段名称列表
+        List<String> fieldNames = getFieldNames(sensorDataClass);
+
+        fluxQuery.append("from(bucket: \"").append(getBucketName()).append("\") ")  // 使用动态获取的桶名
+                .append("|> range(start: ").append(startTime).append(", stop: ").append(endTime).append(") ")  // 设置时间范围
+                .append("|> filter(fn: (r) => r._measurement == \"").append(measurement).append("\" and r.device_id == \"").append(deviceId).append("\" and r.roads == ").append(roads).append(") ");
+
+        // 添加自定义查询条件
+        if (queryConditions != null) {
+            for (SensorQueryCondition condition : queryConditions) {
+                fluxQuery.append("|> filter(fn: (r) => r._field == \"").append(condition.getField()).append("\" and r._value ").append(condition.getOperator().getOperator()).append(" ").append(condition.getValue()).append(") ");
+            }
+        }
+
+        fluxQuery.append("|> sort(columns: [\"_time\"], desc: true)");  // 按时间降序排列
+        return fluxQuery.toString();
+    }
+
+    /**
+     * 根据 deviceId、roads、时间范围和查询条件查询数据
+     *
+     * @param deviceId        设备 ID
+     * @param roads           路数
+     * @param startTime       查询开始时间
+     * @param endTime         查询结束时间
+     * @param queryConditions 查询条件列表
+     * @return 查询到的传感器数据列表
+     */
+    public List<SensorData> querySensorData(String deviceId, int roads, Instant startTime, Instant endTime, List<SensorQueryCondition> queryConditions) {
+        String fluxQuery = buildFluxQuery(deviceId, roads, startTime, endTime, queryConditions, SensorData.class);
+        QueryApi queryApi = jfcloudInfluxDBService.getInfluxDBClient().getQueryApi();
+        List<FluxTable> tables = queryApi.query(fluxQuery);
+
+        // 将查询结果映射为 SensorData 实体
+        return tables.stream().flatMap(table -> table.getRecords().stream()).map(SensorData::mapToSensorData).collect(Collectors.toList());
+    }
+
+    /**
+     * 根据 deviceId 和 roads 查询最新的数据
+     *
+     * @param deviceId 设备 ID
+     * @param roads    路数
+     * @return 最新的传感器数据
+     */
+    public SensorData queryLatestDataByDeviceIdAndRoads(String deviceId, Integer roads) {
+        // 构建 Flux 查询,获取最新一条记录
+        String fluxQuery = String.format("from(bucket: \"%s\") |> range(start: -30d) |> filter(fn: (r) => r._measurement == \"%s\" and r.device_id == \"%s\" and r.roads == %d) |> sort(columns: [\"_time\"], desc: true) |> limit(n: 1)", getBucketName(), getMeasurement(SensorData.class), deviceId, roads);
+
+        QueryApi queryApi = jfcloudInfluxDBService.getInfluxDBClient().getQueryApi();
+        List<FluxTable> tables = queryApi.query(fluxQuery);
+
+        // 将查询结果映射为 SensorData 实体
+        return tables.stream().flatMap(table -> table.getRecords().stream()).map(SensorData::mapToSensorData).findFirst().orElse(null);  // 如果没有数据,返回 null
+    }
+
+    /**
+     * 根据 deviceId、roads 和时间范围查询数据
+     *
+     * @param deviceId  设备 ID
+     * @param roads     路数
+     * @param startTime 查询开始时间
+     * @param endTime   查询结束时间
+     * @return 查询到的传感器数据列表
+     */
+    public List<SensorData> queryDataByDeviceIdAndRoads(String deviceId, Integer roads, String startTime, String endTime) {
+        String query = String.format("SELECT * FROM \"%s\" WHERE \"device_id\" = '%s' AND \"roads\" = %d AND time >= '%s' AND time <= '%s' ORDER BY time DESC", getMeasurement(SensorData.class), deviceId, roads, startTime, endTime);
+        QueryApi queryApi = jfcloudInfluxDBService.getInfluxDBClient().getQueryApi();
+        List<FluxTable> results = queryApi.query(query);
+
+        // 将查询结果转换为 SensorData 实体
+        return results.stream().flatMap(table -> table.getRecords().stream()).map(SensorData::mapToSensorData).collect(Collectors.toList());
+    }
+
+    /**
+     * 获取桶名(通过配置类获取或返回默认桶名)
+     *
+     * @return 桶名
+     */
+    public String getBucketName() {
+        return jfcloudInfluxDB2Properties.getBucket() == null ? JfcloudColdChainConstants.INFLUXDB_DEFAULT_BUCKET_NAME : jfcloudInfluxDB2Properties.getBucket();
+    }
+
+}

+ 32 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/bean/influxdb/SensorQueryCondition.java

@@ -0,0 +1,32 @@
+package vip.xiaonuo.coldchain.core.bean.influxdb;
+
+/**
+ * @author jackzhou
+ * @version 1.0
+ * @project jfcloud-coldchain
+ * @description
+ * @date 2024/11/22 15:48:29
+ */
+public class SensorQueryCondition {
+    private String field;             // 字段名(如 "temperature", "humidity", "co2")
+    private ComparisonOperator operator;  // 比较符号(GT, LT, GTE, LTE)
+    private Double value;             // 查询的阈值
+
+    public SensorQueryCondition(String field, ComparisonOperator operator, Double value) {
+        this.field = field;
+        this.operator = operator;
+        this.value = value;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public ComparisonOperator getOperator() {
+        return operator;
+    }
+
+    public Double getValue() {
+        return value;
+    }
+}

+ 10 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/config/JfcloudColdChainConstants.java

@@ -24,4 +24,14 @@ public interface JfcloudColdChainConstants {
      * 每 1 分钟定期执行设备缓存更新
      */
     Long CACHE_UPDATE_INTERVAL = 5 * 60 * 1000L;
+
+    /**
+     * influxDB default bucketName
+     */
+    String INFLUXDB_DEFAULT_BUCKET_NAME = "coldchain";
+
+    /**
+     * influxDB default Measurement
+     */
+    String INFLUXDB_DEFAULT_MEASUREMENT_NAME = "sensor_data";
 }

+ 79 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/util/DateFormatter.java

@@ -0,0 +1,79 @@
+package vip.xiaonuo.coldchain.core.util;
+
+/**
+ * @author jackzhou
+ * @version 1.0
+ * @project jfcloud-coldchain
+ * @description
+ * @date 2024/11/22 14:50:28
+ */
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+public class DateFormatter {
+
+    // 批量格式化多个 Date 对象的方法
+    public List<String> getFormattedLastUpdated(List<Date> dateList) {
+        List<String> formattedDates = new ArrayList<>();
+        for (Date lastUpdated : dateList) {
+            // 如果 lastUpdated 为 null,返回默认值
+            if (lastUpdated == null) {
+                formattedDates.add("");  // 可以返回适当的默认值
+                continue;
+            }
+            // 将 Date 转换为 LocalDateTime
+            LocalDateTime lastUpdatedLocal = lastUpdated.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+
+            // 获取当前时间
+            LocalDateTime now = LocalDateTime.now();
+
+            // 计算两个日期的差值(以天为单位)
+            long daysDiff = ChronoUnit.DAYS.between(lastUpdatedLocal, now);
+
+            // 根据日期差异来格式化输出
+            if (daysDiff <= 7) {
+                // 使用 Locale.CHINESE 进行格式化,显示中文星期几
+                DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("EEEE", Locale.SIMPLIFIED_CHINESE);
+                formattedDates.add(lastUpdatedLocal.format(dayFormatter));  // 返回中文星期几
+            } else {
+                // 超过 7 天,显示完整的日期时间格式
+                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                formattedDates.add(lastUpdatedLocal.format(formatter));  // 返回完整的日期时间
+            }
+        }
+
+        return formattedDates;
+    }
+
+    // 单个 Date 格式化的方法
+    public String getFormattedSingleDate(Date lastUpdated) {
+        // 如果 lastUpdated 为 null,返回默认值
+        if (lastUpdated == null) {
+            return "";
+        }
+        // 将 Date 转换为 LocalDateTime
+        LocalDateTime lastUpdatedLocal = lastUpdated.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+
+        // 获取当前时间
+        LocalDateTime now = LocalDateTime.now();
+
+        // 计算两个日期的差值(以天为单位)
+        long daysDiff = ChronoUnit.DAYS.between(lastUpdatedLocal, now);
+
+        // 根据日期差异来格式化输出
+        if (daysDiff <= 7) {
+            // 使用 Locale.CHINESE 进行格式化,显示中文星期几
+            DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("EEEE", Locale.SIMPLIFIED_CHINESE);
+            return lastUpdatedLocal.format(dayFormatter);  // 返回中文星期几
+        } else {
+            // 超过 7 天,显示完整的日期时间格式
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            return lastUpdatedLocal.format(formatter);  // 返回完整的日期时间
+        }
+    }
+}
+

+ 55 - 62
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/controller/AppController.java

@@ -6,14 +6,11 @@ import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.validation.Valid;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 import vip.xiaonuo.coldchain.modular.app.param.*;
 import vip.xiaonuo.coldchain.modular.app.service.AppDeviceService;
 import vip.xiaonuo.coldchain.modular.app.service.MessageService;
-import vip.xiaonuo.coldchain.modular.monitortarget.param.TargetStatus;
 import vip.xiaonuo.common.pojo.CommonResult;
 
 import java.io.ByteArrayInputStream;
@@ -33,19 +30,15 @@ public class AppController {
 
     @GetMapping("/device-status")
     @Operation(summary = "设备总缆")
-    public CommonResult<TargetStatus> getDeviceStatus(String keyword) {
-//        int totalDevices = 180;
-//        int onlineDevices = 120;
-//        int offlineDevices = 60;
-//        DeviceStatus deviceStatus = new DeviceStatus(totalDevices, onlineDevices, offlineDevices);
-        TargetStatus deviceStatus = appDeviceService.getDeviceStatus(keyword);
+    public CommonResult<DeviceStatus> getDeviceStatus(String keyword) {
+        DeviceStatus deviceStatus = appDeviceService.getDeviceStatus(keyword);
         return CommonResult.data(deviceStatus);
     }
 
     @GetMapping("/devices")
     @Operation(summary = "设备列表")
     public CommonResult<Page<AppDevice>> devices(AppDevicePageParam appDevicePageParam) {
-        return CommonResult.data(appDeviceService.getAllDevices(appDevicePageParam));
+        return CommonResult.data(null);
     }
 
     @Operation(summary = "分页设备")
@@ -78,25 +71,23 @@ public class AppController {
     @PostMapping("/device/view/{deviceCode}")
     @Operation(summary = "查询采集设备数据")
     public List<AppDeviceData> queryDeviceData(@RequestBody AppDeviceQueryParams appDeviceQueryParams, @PathVariable(value = "deviceCode", required = true) String deviceCode) {
-
-        // 校验查询条件
-        appDeviceQueryParams.validate();
-
-        // 获取查询结果
-        List<AppDeviceData> appDeviceDataList = appDeviceService.getDeviceData(appDeviceQueryParams, deviceCode);
-
-        // 根据metric筛选数据
-        Metric metric = appDeviceQueryParams.getMetric();
-        if (metric == Metric.TEMPERATURE) {
-            return filterTemperatureData(appDeviceDataList);
-        } else if (metric == Metric.HUMIDITY) {
-            return filterHumidityData(appDeviceDataList);
-        } else if (metric == Metric.CO2_LEVEL) {
-            return filterCo2LevelData(appDeviceDataList);
-        } else {
-            // 默认返回所有数据
-            return appDeviceDataList;
-        }
+//        // 校验查询条件
+//        appDeviceQueryParams.validate();
+//        // 获取查询结果
+////        List<AppDeviceData> appDeviceDataList = appDeviceService.getDeviceData(appDeviceQueryParams, deviceCode);
+//        // 根据metric筛选数据
+//        Metric metric = appDeviceQueryParams.getMetric();
+//        if (metric == Metric.TEMPERATURE) {
+//            return filterTemperatureData(appDeviceDataList);
+//        } else if (metric == Metric.HUMIDITY) {
+//            return filterHumidityData(appDeviceDataList);
+//        } else if (metric == Metric.CO2_LEVEL) {
+//            return filterCo2LevelData(appDeviceDataList);
+//        } else {
+//            // 默认返回所有数据
+//            return appDeviceDataList;
+//        }
+        return null;
     }
 
     // 根据温度过滤数据
@@ -121,43 +112,45 @@ public class AppController {
     @PostMapping("/device/download/{deviceCode}")
     @Operation(summary = "下载采集器设备数据接口")
     public ResponseEntity<InputStreamResource> downloadDeviceData(@RequestBody AppDeviceQueryParams appDeviceQueryParams, @PathVariable(value = "deviceCode", required = true) String deviceCode) throws IOException {
-
-        // 校验查询条件
-        appDeviceQueryParams.validate();
-
-        // 获取查询结果
-        List<AppDeviceData> appDeviceDataList = appDeviceService.getDeviceData(appDeviceQueryParams, deviceCode);
-
-        // 根据metric筛选数据
-        Metric metric = appDeviceQueryParams.getMetric();
-        if (metric == Metric.TEMPERATURE) {
-            appDeviceDataList = filterTemperatureData(appDeviceDataList);
-        } else if (metric == Metric.HUMIDITY) {
-            appDeviceDataList = filterHumidityData(appDeviceDataList);
-        } else if (metric == Metric.CO2_LEVEL) {
-            appDeviceDataList = filterCo2LevelData(appDeviceDataList);
-        }
-
-        // 生成 CSV 或 Excel 文件数据流
-        ByteArrayInputStream byteArrayInputStream = generateCSV(appDeviceDataList);
-
-        // 设置响应头,指示文件下载
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("Content-Disposition", "attachment; filename=devices_data.csv");
-
-        return ResponseEntity.ok().headers(headers).contentType(MediaType.parseMediaType("text/csv")).body(new InputStreamResource(byteArrayInputStream));
+//
+//        // 校验查询条件
+//        appDeviceQueryParams.validate();
+//
+//        // 获取查询结果
+//        List<AppDeviceData> appDeviceDataList = appDeviceService.getDeviceData(appDeviceQueryParams, deviceCode);
+//
+//        // 根据metric筛选数据
+//        Metric metric = appDeviceQueryParams.getMetric();
+//        if (metric == Metric.TEMPERATURE) {
+//            appDeviceDataList = filterTemperatureData(appDeviceDataList);
+//        } else if (metric == Metric.HUMIDITY) {
+//            appDeviceDataList = filterHumidityData(appDeviceDataList);
+//        } else if (metric == Metric.CO2_LEVEL) {
+//            appDeviceDataList = filterCo2LevelData(appDeviceDataList);
+//        }
+//
+//        // 生成 CSV 或 Excel 文件数据流
+//        ByteArrayInputStream byteArrayInputStream = generateCSV(appDeviceDataList);
+//
+//        // 设置响应头,指示文件下载
+//        HttpHeaders headers = new HttpHeaders();
+//        headers.add("Content-Disposition", "attachment; filename=devices_data.csv");
+//
+//        return ResponseEntity.ok().headers(headers).contentType(MediaType.parseMediaType("text/csv")).body(new InputStreamResource(byteArrayInputStream));
+        return null;
     }
 
     // 生成 CSV 文件的 ByteArrayInputStream
     private ByteArrayInputStream generateCSV(List<AppDeviceData> appDeviceDataList) {
-        StringBuilder csvContent = new StringBuilder();
-        csvContent.append("DeviceCode,Timestamp,Temperature,Humidity,CO2 Level,Battery Percentage,Device Name\n");
-
-        for (AppDeviceData data : appDeviceDataList) {
-            csvContent.append(data.getDeviceCode()).append(",").append(data.getTimestamp()).append(",").append(data.getTemperature()).append(",").append(data.getHumidity()).append(",").append(data.getCo2Level()).append(",").append(data.getBatteryPercentage()).append(",").append(data.getDeviceName()).append("\n");
-        }
-
-        return new ByteArrayInputStream(csvContent.toString().getBytes());
+//        StringBuilder csvContent = new StringBuilder();
+//        csvContent.append("DeviceCode,Timestamp,Temperature,Humidity,CO2 Level,Battery Percentage,Device Name\n");
+//
+//        for (AppDeviceData data : appDeviceDataList) {
+//            csvContent.append(data.getDeviceCode()).append(",").append(data.getTimestamp()).append(",").append(data.getTemperature()).append(",").append(data.getHumidity()).append(",").append(data.getCo2Level()).append(",").append(data.getBatteryPercentage()).append(",").append(data.getDeviceName()).append("\n");
+//        }
+//
+//        return new ByteArrayInputStream(csvContent.toString().getBytes());
+        return null;
     }
 
     @GetMapping("/message/unread/count")

+ 9 - 56
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDevice.java

@@ -12,54 +12,29 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import vip.xiaonuo.coldchain.core.service.dataprocess.model.PowerEnum;
+import vip.xiaonuo.coldchain.modular.monitortarget.entity.MonitorTarget;
 
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-public class AppDevice {
-    @Schema(description = "设备名称")
-    private String deviceName;
-    @Schema(description = "设备编码")
-    private String deviceCode;
-    /**
-     * 状态(1:正常,2:闲置)
-     */
-    @Schema(description = "状态(1:正常,2:停用)")
-    private Integer status = 1;
-
-    /**
-     * 电池电量 (%)
-     */
-    @Schema(description = "电池电量 (%)")
-    private double batteryPercentage;
-    /**
-     * 最近更新时间
-     */
-    @Schema(description = "最近更新时间")
-    private LocalDateTime lastUpdated;
-
+public class AppDevice extends MonitorTarget {
     /**
      * 是否插电
      *
      * @return
      */
-    @Schema(description = "是否插电")
-    private boolean plugIn = false;
+    @Schema(description = "AC电源 DC电池")
+    private String plugInStatus = PowerEnum.AC.getCode();
 
     /**
-     * 最近一次登录时间
-     *
-     * @return
+     * 电池电量 (%)
      */
-    @Schema(description = "最近一次登录时间")
-    private LocalDateTime lastLoginTime;
+    @Schema(description = "电池电量 (%)")
+    private double batteryPercentage;
 
     /**
      * 关键的设备探头集合
@@ -67,28 +42,6 @@ public class AppDevice {
      * @return
      */
     @Schema(description = "关键的设备探头集合")
-    private List<AppDeviceData> children=new ArrayList<AppDeviceData>();
-
+    private List<AppDeviceData> children = new ArrayList<AppDeviceData>();
 
-    // 格式化 lastUpdated 的显示方法
-    public String getFormattedLastUpdated() {
-        // 如果 lastUpdated 为 null,返回默认值
-        if (lastUpdated == null) {
-            return "暂不可用";  // 可以返回适当的默认值
-        }
-        // 获取当前时间
-        LocalDateTime now = LocalDateTime.now();
-        // 计算两个日期的差值(以天为单位)
-        long daysDiff = ChronoUnit.DAYS.between(lastUpdated, now);
-        // 如果日期在 7 天之内,显示中文星期几
-        if (daysDiff <= 7) {
-            // 使用 Locale.CHINESE 进行格式化,显示中文星期几
-            DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("EEEE", Locale.SIMPLIFIED_CHINESE);
-            return lastUpdated.format(dayFormatter); // 返回中文星期几,例如 星期一, 星期二
-        } else {
-            // 超过 7 天,显示完整的日期时间格式
-            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            return lastUpdated.format(formatter);
-        }
-    }
 }

+ 4 - 18
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDeviceData.java

@@ -9,34 +9,20 @@ package vip.xiaonuo.coldchain.modular.app.param;
  */
 
 import lombok.Data;
+import vip.xiaonuo.coldchain.core.service.dataprocess.model.PowerEnum;
+import vip.xiaonuo.coldchain.modular.monitortargetregion.entity.MonitorTargetRegion;
 
 import java.time.LocalDateTime;
 
 @Data
-public class AppDeviceData {
-    private String deviceCode;          // 设备唯一标识符
-    private String deviceName;          // 设备名称
+public class AppDeviceData extends MonitorTargetRegion {
     private LocalDateTime timestamp;    // 数据记录的时间
     private Double temperature;         // 设备温度 (℃)
     private Double humidity;            // 设备湿度 (%)
     private Double co2Level;            // 二氧化碳浓度 (ppm)
     private Double batteryPercentage;   // 电池电量 (%)
-
-    /**
-     * 路数,默认路数1
-     */
-    private Integer roads = 1;
+    private String plugInStatus = PowerEnum.AC.getCode();
 
     public AppDeviceData() {
     }
-
-    public AppDeviceData(String deviceCode, LocalDateTime timestamp, Double temperature, Double humidity, Double co2Level, Double batteryPercentage, String deviceName) {
-        this.deviceCode = deviceCode;
-        this.timestamp = timestamp;
-        this.temperature = temperature;
-        this.humidity = humidity;
-        this.co2Level = co2Level;
-        this.batteryPercentage = batteryPercentage;
-        this.deviceName = deviceName;
-    }
 }

+ 2 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/DeviceStatus.java

@@ -26,4 +26,6 @@ public class DeviceStatus {
         this.offline = offlineDevices;
     }
 
+    public DeviceStatus() {
+    }
 }

+ 12 - 29
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/mock/AppDeviceTestDataGenerator.java

@@ -28,13 +28,7 @@ public class AppDeviceTestDataGenerator {
                         int result = 0;
                         switch (sortField) {
                             case "deviceName":
-                                result = device1.getDeviceName().compareTo(device2.getDeviceName());
-                                break;
-                            case "deviceCode":
-                                result = device1.getDeviceCode().compareTo(device2.getDeviceCode());
-                                break;
-                            case "status":
-                                result = Integer.compare(device1.getStatus(), device2.getStatus());
+                                result = device1.getName().compareTo(device2.getName());
                                 break;
                             default:
                                 break;
@@ -78,18 +72,7 @@ public class AppDeviceTestDataGenerator {
             LocalDateTime lastUpdated = LocalDateTime.now().minusDays(ThreadLocalRandom.current().nextInt(10)); // 最近更新时间:最近 10 天内
             boolean plugIn = ThreadLocalRandom.current().nextBoolean();  // 插电状态
             LocalDateTime lastLoginTime = LocalDateTime.now().minusDays(ThreadLocalRandom.current().nextInt(5));  // 上次登录时间:最近 5 天内
-
-            AppDevice device = new AppDevice(
-                    deviceName,
-                    deviceCode,
-                    status,
-                    batteryPercentage,
-                    lastUpdated,
-                    plugIn,
-                    lastLoginTime,
-                    generateDeviceDataList(i)
-            );
-
+            AppDevice device = new AppDevice();
             devices.add(device);
         }
 
@@ -106,16 +89,16 @@ public class AppDeviceTestDataGenerator {
         List<AppDeviceData> deviceDataList = new ArrayList<>();
 
         for (int i = 1; i <= 5; i++) {
-            AppDeviceData data = new AppDeviceData(
-                    "设备编号" + deviceIndex + "-数据" + i,
-                    LocalDateTime.now().minusMinutes(ThreadLocalRandom.current().nextInt(60)),  // 随机时间戳:最近 1 小时内
-                    15 + ThreadLocalRandom.current().nextDouble() * 10,  // 温度 15℃ 到 25℃
-                    30 + ThreadLocalRandom.current().nextDouble() * 40,  // 湿度 30% 到 70%
-                    350 + ThreadLocalRandom.current().nextDouble() * 150,  // CO2浓度 350ppm 到 500ppm
-                    20 + (80 * ThreadLocalRandom.current().nextDouble()),  // 电池电量 20% 到 100%
-                    "子设备-" + deviceIndex + "-传感器" + i
-            );
-            deviceDataList.add(data);
+//            AppDeviceData data = new AppDeviceData(
+//                    "设备编号" + deviceIndex + "-数据" + i,
+//                    LocalDateTime.now().minusMinutes(ThreadLocalRandom.current().nextInt(60)),  // 随机时间戳:最近 1 小时内
+//                    15 + ThreadLocalRandom.current().nextDouble() * 10,  // 温度 15℃ 到 25℃
+//                    30 + ThreadLocalRandom.current().nextDouble() * 40,  // 湿度 30% 到 70%
+//                    350 + ThreadLocalRandom.current().nextDouble() * 150,  // CO2浓度 350ppm 到 500ppm
+//                    20 + (80 * ThreadLocalRandom.current().nextDouble()),  // 电池电量 20% 到 100%
+//                    "子设备-" + deviceIndex + "-传感器" + i
+//            );
+//            deviceDataList.add(data);
         }
 
         return deviceDataList;

+ 85 - 71
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/service/AppDeviceService.java

@@ -8,97 +8,42 @@ package vip.xiaonuo.coldchain.modular.app.service;
  * @date 2024/11/17 22:30:41
  */
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.jfcloud.influxdb.service.JfcloudInfluxDBService;
 import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
 import vip.xiaonuo.coldchain.modular.app.param.*;
-import vip.xiaonuo.coldchain.modular.app.param.mock.AppDeviceTestDataGenerator;
 import vip.xiaonuo.coldchain.modular.monitordevice.service.MonitorDeviceService;
 import vip.xiaonuo.coldchain.modular.monitortarget.entity.MonitorTarget;
 import vip.xiaonuo.coldchain.modular.monitortarget.param.MonitorTargetPageParam;
 import vip.xiaonuo.coldchain.modular.monitortarget.param.TargetStatus;
 import vip.xiaonuo.coldchain.modular.monitortarget.service.MonitorTargetService;
+import vip.xiaonuo.coldchain.modular.monitortargetregion.entity.MonitorTargetRegion;
+import vip.xiaonuo.coldchain.modular.monitortargetregion.service.MonitorTargetRegionService;
 
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 @Service
 @RequiredArgsConstructor
 public class AppDeviceService {
     private final MonitorTargetService monitorTargetService;
+    private final MonitorTargetRegionService monitorTargetRegionService;
+    private final JfcloudInfluxDBService jfcloudInfluxDBService;
     private final MonitorDeviceService monitorDeviceService;
 
-    public Page<AppDevice> getAllDevices(AppDevicePageParam appDevicePageParam) {
-        // 获取分页数据
-        return AppDeviceTestDataGenerator.getPagedDeviceData(appDevicePageParam);
-    }
-
     // 模拟设备保存操作,实际应用中可能会是数据库操作
     public boolean addDevice(AppDeviceAddParam device) {
         System.out.println("设备已添加:" + device);
         return true; // 假设设备保存成功
     }
 
-    // 查询设备数据的方法
-    public List<AppDeviceData> getDeviceData(AppDeviceQueryParams appDeviceQueryParams, String deviceCode) {
-        // 模拟的设备数据列表,添加了 deviceCode
-        List<AppDeviceData> appDeviceDataList = new ArrayList<>();
-        appDeviceDataList.add(new AppDeviceData("DEVICE001", LocalDateTime.parse("2023-03-18T14:00:40"), 21.0, 60.0, 400.0, 85.0, "Device A"));
-        appDeviceDataList.add(new AppDeviceData("DEVICE002", LocalDateTime.parse("2023-03-20T10:15:30"), 18.5, 65.0, 420.0, 75.0, "Device B"));
-        appDeviceDataList.add(new AppDeviceData("DEVICE001", LocalDateTime.parse("2023-03-25T12:30:00"), 19.2, 63.0, 410.0, 80.0, "Device A"));
-        appDeviceDataList.add(new AppDeviceData("DEVICE003", LocalDateTime.parse("2023-03-28T13:45:10"), 22.5, 55.0, 450.0, 90.0, "Device C"));
-
-        List<AppDeviceData> filteredData = new ArrayList<>();
-        for (AppDeviceData data : appDeviceDataList) {
-            boolean matches = true;
-
-            // 时间范围过滤
-            if (appDeviceQueryParams.getStartTime() != null && data.getTimestamp().isBefore(appDeviceQueryParams.getStartTime())) {
-                matches = false;
-            }
-            if (appDeviceQueryParams.getEndTime() != null && data.getTimestamp().isAfter(appDeviceQueryParams.getEndTime())) {
-                matches = false;
-            }
-
-            // 温度范围过滤
-            if (appDeviceQueryParams.getMinTemperature() != null && data.getTemperature() < appDeviceQueryParams.getMinTemperature()) {
-                matches = false;
-            }
-            if (appDeviceQueryParams.getMaxTemperature() != null && data.getTemperature() > appDeviceQueryParams.getMaxTemperature()) {
-                matches = false;
-            }
-
-            // 湿度范围过滤
-            if (appDeviceQueryParams.getMinHumidity() != null && data.getHumidity() < appDeviceQueryParams.getMinHumidity()) {
-                matches = false;
-            }
-            if (appDeviceQueryParams.getMaxHumidity() != null && data.getHumidity() > appDeviceQueryParams.getMaxHumidity()) {
-                matches = false;
-            }
-
-            // 二氧化碳浓度范围过滤
-            if (appDeviceQueryParams.getMinCo2Level() != null && data.getCo2Level() < appDeviceQueryParams.getMinCo2Level()) {
-                matches = false;
-            }
-            if (appDeviceQueryParams.getMaxCo2Level() != null && data.getCo2Level() > appDeviceQueryParams.getMaxCo2Level()) {
-                matches = false;
-            }
-
-            // 设备编码过滤
-            if (deviceCode != null && !deviceCode.equals(data.getDeviceCode())) {
-                matches = false;
-            }
-
-            if (matches) {
-                filteredData.add(data);
-            }
-        }
-        return filteredData;
-    }
-
     /**
      * 监控对象列表包含温湿度监控指标--全部
      *
@@ -116,27 +61,96 @@ public class AppDeviceService {
      * @return
      */
     public Page<AppDevice> pageDevices(AppDevicePageParam appDevicePageParam) {
+        // 用于存储最终返回的 AppDevice 列表
         List<AppDevice> rlt = Lists.newArrayList();
+        // 创建监控目标分页查询参数对象
         MonitorTargetPageParam monitorTargetPageParam = new MonitorTargetPageParam();
+        // 获取当前登录用户的 ID,并设置到查询参数中
         monitorTargetPageParam.setUserId(StpLoginUserUtil.getLoginUser().getId());
+        // 设置分页参数:当前页和每页记录数
         monitorTargetPageParam.setCurrent(appDevicePageParam.getCurrent());
         monitorTargetPageParam.setSize(appDevicePageParam.getSize());
+
+        // 调用 monitorTargetService 查询当前用户的监控目标数据,分页结果
         Page<MonitorTarget> pageByUser = monitorTargetService.getPageByUser(monitorTargetPageParam);
-        pageByUser.getRecords().forEach(mt -> {
-            //获取通道的集合
-//            List<MonitorChannel> monitorChannels = monitorChannelService.listByTargetId(mt.getId());
-            //单个通道的温湿度信息
+
+        // 遍历监控目标分页记录
+        pageByUser.getRecords().forEach(monitorTarget -> {
+            // 创建新的 AppDevice 对象来存储转换后的设备信息
+            AppDevice appDevice = new AppDevice();
+            // 将监控目标信息复制到 AppDevice 中
+            BeanUtil.copyProperties(monitorTarget, appDevice);
+
+            // 获取当前监控目标的 ID,用于查询子设备数据
+            String monitorTargetId = monitorTarget.getId();
+
+            // 获取当前监控目标下的所有监控区域(子设备数据)
+            List<MonitorTargetRegion> monitorTargetRegions = monitorTargetRegionService.getRegionListByTargetId(monitorTargetId);
+
+            // 如果监控目标下存在区域(即有子设备)
+            if (!monitorTargetRegions.isEmpty()) {
+                // 遍历每个区域,将其转换为子设备数据,并添加到 AppDevice 的子设备列表中
+                for (MonitorTargetRegion monitorTargetRegion : monitorTargetRegions) {
+                    // 获取 AppDevice 的子设备列表
+                    List<AppDeviceData> children = appDevice.getChildren();
+                    // 如果子设备列表为空,初始化一个空的列表
+                    if (children == null) {
+                        children = new ArrayList<>();
+                        appDevice.setChildren(children);
+                    }
+                    // 创建新的 AppDeviceData 对象,将监控区域数据复制到该子设备对象中
+                    AppDeviceData appDeviceData = new AppDeviceData();
+                    children.add(appDeviceData);
+                    BeanUtil.copyProperties(monitorTargetRegion, appDeviceData);
+                    String deviceId = appDeviceData.getDeviceCode();
+                    // 传感器路数
+                    Integer sensorRoute = appDeviceData.getSensorRoute();
+                    if (!Objects.isNull(sensorRoute) && StrUtil.isNotBlank(deviceId)) {
+                        String startTime = null, endTime = null;
+                        SensorData sensorData = monitorDeviceService.queryLatestDataByDeviceIdAndRoads(deviceId, sensorRoute);
+                        List<SensorData> sensorDataList = monitorDeviceService.queryDataByDeviceIdAndRoads(deviceId, sensorRoute, startTime, endTime);
+                    }
+
+                    // 这里可以调用外部服务(如 InfluxDB)获取实时数据(温湿度、CO2 等),
+                    // 但目前这个逻辑的实际获取部分尚未实现
+                }
+
+                // 更新设备的电池电量和插电状态等信息
+                // 这里假设我们取第一个子设备的数据来填充主体设备的电池电量等信息
+                if (!appDevice.getChildren().isEmpty()) {
+                    AppDeviceData firstChild = appDevice.getChildren().get(0);
+                    appDevice.setPlugInStatus(firstChild.getPlugInStatus());
+                    appDevice.setBatteryPercentage(firstChild.getBatteryPercentage());
+                }
+            }
+
+            // 将转换后的设备对象添加到最终的设备列表中
+            rlt.add(appDevice);
         });
-        return null;
+
+        // 创建分页返回对象,设置分页信息和记录数据
+        Page<AppDevice> pageResult = new Page<>();
+        pageResult.setCurrent(appDevicePageParam.getCurrent()); // 当前页
+        pageResult.setSize(appDevicePageParam.getSize()); // 每页记录数
+        pageResult.setTotal(pageByUser.getTotal()); // 总记录数
+        pageResult.setPages(pageByUser.getPages()); // 总页数
+        pageResult.setRecords(rlt); // 设置当前页的设备数据
+
+        // 返回分页结果
+        return pageResult;
     }
 
+
     /**
      * 获取设备总数
      *
      * @param keyword
      * @return
      */
-    public TargetStatus getDeviceStatus(String keyword) {
-        return monitorTargetService.getTargetCount();
+    public DeviceStatus getDeviceStatus(String keyword) {
+        TargetStatus targetCount = monitorTargetService.getTargetCount();
+        DeviceStatus deviceStatus = new DeviceStatus();
+        BeanUtil.copyProperties(targetCount, deviceStatus);
+        return deviceStatus;
     }
 }

+ 9 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/MonitorDeviceService.java

@@ -16,12 +16,15 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import rk.netDevice.sdk.p2.ParamData;
 import rk.netDevice.sdk.p2.ParamIdsData;
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorQueryCondition;
 import vip.xiaonuo.coldchain.modular.monitordevice.entity.MonitorDevice;
 import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDeviceAddParam;
 import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDeviceEditParam;
 import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDeviceIdParam;
 import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDevicePageParam;
 
+import java.time.Instant;
 import java.util.Date;
 import java.util.List;
 
@@ -89,4 +92,10 @@ public interface MonitorDeviceService extends IService<MonitorDevice> {
     boolean updateLastHeartbeatTimeByDeviceId(Integer deviceId, Date timestamp);
 
     boolean updateLastLoginTimeByDeviceId(Integer deviceId, Date timestamp);
+
+    List<SensorData> queryDataByDeviceIdAndRoads(String deviceId, Integer sensorRoute, String startTime, String endTime);
+
+    SensorData queryLatestDataByDeviceIdAndRoads(String deviceId, Integer sensorRoute);
+
+    List<SensorData> querySensorData(String deviceId, int roads, Instant startTime, Instant endTime, List<SensorQueryCondition> queryConditions);
 }

+ 23 - 4
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/impl/MonitorDeviceServiceImpl.java

@@ -26,19 +26,20 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import rk.netDevice.sdk.p2.ParamData;
 import rk.netDevice.sdk.p2.ParamIdsData;
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorDataService;
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorQueryCondition;
 import vip.xiaonuo.coldchain.core.cache.monitordevice.MonitorDeviceCache;
 import vip.xiaonuo.coldchain.core.renke.RenKeService;
 import vip.xiaonuo.coldchain.modular.monitordevice.entity.MonitorDevice;
 import vip.xiaonuo.coldchain.modular.monitordevice.mapper.MonitorDeviceMapper;
-import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDeviceAddParam;
-import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDeviceEditParam;
-import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDeviceIdParam;
-import vip.xiaonuo.coldchain.modular.monitordevice.param.MonitorDevicePageParam;
+import vip.xiaonuo.coldchain.modular.monitordevice.param.*;
 import vip.xiaonuo.coldchain.modular.monitordevice.service.MonitorDeviceService;
 import vip.xiaonuo.common.enums.CommonSortOrderEnum;
 import vip.xiaonuo.common.exception.CommonException;
 import vip.xiaonuo.common.page.CommonPageRequest;
 
+import java.time.Instant;
 import java.util.Date;
 import java.util.List;
 
@@ -54,6 +55,9 @@ import java.util.List;
 public class MonitorDeviceServiceImpl extends ServiceImpl<MonitorDeviceMapper, MonitorDevice> implements MonitorDeviceService {
     private final RenKeService renKeService;
     private final MonitorDeviceCache monitorDeviceCache;
+    private final SensorDataService sensorDataService;
+
+    private String bucketName;
 
     @Override
     public Page<MonitorDevice> page(MonitorDevicePageParam monitorDevicePageParam) {
@@ -171,6 +175,7 @@ public class MonitorDeviceServiceImpl extends ServiceImpl<MonitorDeviceMapper, M
         return updateDeviceTimeByDeviceId(deviceId, timestamp, "lastLoginTime");
     }
 
+
     // 通用更新方法,避免代码重复,并处理 timestamp 为空的情况
     private boolean updateDeviceTimeByDeviceId(Integer deviceId, Date timestamp, String timeField) {
         if (timestamp == null) {
@@ -196,4 +201,18 @@ public class MonitorDeviceServiceImpl extends ServiceImpl<MonitorDeviceMapper, M
         return this.updateById(device);
     }
 
+    @Override
+    public List<SensorData> queryDataByDeviceIdAndRoads(String deviceId, Integer roads, String startTime, String endTime) {
+        return sensorDataService.queryDataByDeviceIdAndRoads(deviceId, roads, startTime, endTime);
+    }
+
+    @Override
+    public SensorData queryLatestDataByDeviceIdAndRoads(String deviceId, Integer roads) {
+        return sensorDataService.queryLatestDataByDeviceIdAndRoads(deviceId, roads);
+    }
+
+    @Override
+    public List<SensorData> querySensorData(String deviceId, int roads, Instant startTime, Instant endTime, List<SensorQueryCondition> queryConditions) {
+        return sensorDataService.querySensorData(deviceId, roads, startTime, endTime, queryConditions);
+    }
 }

+ 0 - 5
snowy-plugin/snowy-plugin-sys/pom.xml

@@ -39,10 +39,5 @@
             <artifactId>snowy-plugin-mobile-api</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>vip.xiaonuo</groupId>
-            <artifactId>snowy-plugin-api</artifactId>
-        </dependency>
-
     </dependencies>
 </project>