DeviceDataStorage.java 7.26 KB
package com.iot.scheduler.utils;

import java.io.*;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class DeviceDataStorage {

    private static final String DATA_DIR = "/thingskit/iot-scheduler/reportData"; // 存储目录
    private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    static {
        // 确保存储目录存在
        try {
            Files.createDirectories(Paths.get(DATA_DIR));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新设备数据(追加一条记录)
     *
     * @param deviceCode 设备编码
     * @param timestamp  时间戳(毫秒)
     * @param value      实时值
     */
    public synchronized void updateData(String deviceCode, long timestamp, double value) {
        String fileName = getFileName(deviceCode);
        String line = formatDataLine(timestamp, value) + System.lineSeparator();
        try (FileWriter fw = new FileWriter(fileName, true);
             BufferedWriter bw = new BufferedWriter(fw)) {
            bw.write(line);
        } catch (IOException e) {
            System.err.println("写入设备数据失败: " + deviceCode);
            e.printStackTrace();
        }
    }

    /**
     * 查询设备上次存储的数据(最新一条)
     *
     * @param deviceCode 设备编码
     * @return DeviceRecord 对象,若无数据则返回 null
     */
    public DeviceRecord getLastRecord(String deviceCode) {
        String fileName = getFileName(deviceCode);
        File file = new File(fileName);
        if (!file.exists()) {
            return null;
        }

        String lastLine = null;
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (!line.trim().isEmpty()) {
                    lastLine = line;
                }
            }
        } catch (IOException e) {
            System.err.println("读取设备数据失败: " + deviceCode);
            e.printStackTrace();
            return null;
        }

        if (lastLine == null) {
            return null;
        }
        return parseRecord(lastLine);
    }

    /**
     * 根据设备编码和时间戳查询指定时间的数据(精确匹配)
     *
     * @param deviceCode 设备编码
     * @param timestamp  时间戳(毫秒)
     * @return DeviceRecord 对象,若不存在则返回 null
     */
    public DeviceRecord getRecordByTimestamp(String deviceCode, long timestamp) {
        String fileName = getFileName(deviceCode);
        File file = new File(fileName);
        if (!file.exists()) {
            return null;
        }

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (line.trim().isEmpty()) continue;
                DeviceRecord record = parseRecord(line);
                if (record != null && record.getTimestamp() == timestamp) {
                    return record;
                }
            }
        } catch (IOException e) {
            System.err.println("读取设备数据失败: " + deviceCode);
            e.printStackTrace();
        }
        return null;
    }

    // 获取设备文件路径
    private String getFileName(String deviceCode) {
        return DATA_DIR + File.separator + deviceCode + ".txt";
    }

    // 格式化存储行: 时间戳 | 数值
    private String formatDataLine(long timestamp, double value) {
        String timeStr = formatTimestamp(timestamp);
        return timeStr + " | " + value + " | " + timestamp;
    }

    // 将时间戳转为可读格式
    private String formatTimestamp(long timestamp) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(
                java.time.Instant.ofEpochMilli(timestamp),
                ZoneId.systemDefault()
        );
        return dateTime.format(TIMESTAMP_FORMAT);
    }

    // 解析记录行
    private DeviceRecord parseRecord(String line) {
        String[] parts = line.split("\\|");
        if (parts.length < 3) {
            // 兼容旧格式
            if (parts.length == 2) {
                try {
                    String timestampStr = parts[0].trim();
                    double value = Double.parseDouble(parts[1].trim());
                    LocalDateTime ldt = LocalDateTime.parse(timestampStr, TIMESTAMP_FORMAT);
                    long timestamp = ldt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                    return new DeviceRecord(timestamp, value);
                } catch (Exception e) {
                    return null;
                }
            }
            return null;
        }

        try {
            long timestamp = Long.parseLong(parts[2].trim());
            double value = Double.parseDouble(parts[1].trim());
            return new DeviceRecord(timestamp, value);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    // 记录实体类
    public static class DeviceRecord {
        private final long timestamp; // 毫秒时间戳
        private final double value;

        public DeviceRecord(long timestamp, double value) {
            this.timestamp = timestamp;
            this.value = value;
        }

        public long getTimestamp() {
            return timestamp;
        }

        public double getValue() {
            return value;
        }

        @Override
        public String toString() {
            LocalDateTime dateTime = LocalDateTime.ofInstant(
                    java.time.Instant.ofEpochMilli(timestamp),
                    ZoneId.systemDefault()
            );
            return "DeviceRecord{" +
                    "timestamp=" + timestamp +
                    " (" + dateTime.format(TIMESTAMP_FORMAT) + ")" +
                    ", value=" + value +
                    '}';
        }
    }


    public static void main(String[] args) {
        DeviceDataStorage storage = new DeviceDataStorage();

        // 模拟不同时间点的数据(时间戳作为参数传入)
        long time1 = 1718352000000L; // 2024-06-14 16:00:00
        long time2 = 1718438400000L; // 2024-06-15 16:00:00
        long time3 = 1718524800000L; // 2024-06-16 16:00:00

        // 更新设备数据(传入时间戳)
        storage.updateData("device_001", time1, 23.5);
        storage.updateData("device_001", time2, 24.1);
        storage.updateData("device_001", time3, 25.3);

        storage.updateData("device_002", time1, 68.3);
        storage.updateData("device_002", time2, 69.1);

        // 查询上次存储的数据
        DeviceDataStorage.DeviceRecord lastRecord = storage.getLastRecord("device_001");
        System.out.println("device_001 最后一条数据: " + lastRecord);

        // 根据具体时间戳查询
        DeviceDataStorage.DeviceRecord record = storage.getRecordByTimestamp("device_001", time2);
        System.out.println("device_001 指定时间的数据: " + record);

        // 查询不存在的设备
        DeviceDataStorage.DeviceRecord notExist = storage.getLastRecord("device_999");
        System.out.println("device_999: " + (notExist == null ? "无数据" : notExist));
    }

}