package com.battery.device.simulator; import java.math.BigDecimal; import java.time.Instant; import java.util.List; import com.battery.device.api.model.DeviceWorkStatus; /** 持久化开发模拟器配置;实现必须在返回前确认写入成功。 */ public interface BtsSimulatorStateStore { int CURRENT_VERSION = 1; /** 读取已有状态,仅在不存在时保存默认拓扑。 */ SimulatorState loadOrInitialize(SimulatorState defaultState); /** 保存设备配置和观测序号;返回前必须完成写入。 */ void save(SimulatorState state); /** 读取短期保留的最近请求。 */ List loadRecentRequests(); /** 保存短期保留的最近请求。 */ void saveRecentRequests(List requests); /** 人工重置主状态和最近请求。 */ void reset(SimulatorState defaultState); record SimulatorState(int version, List devices, List collectors, int nextDeviceId, int nextCollectorId, List tombstones, Boolean softwareAccessible, long observationSequence) { public SimulatorState(int version, List devices, List collectors, int nextDeviceId, int nextCollectorId, List tombstones) { this(version, devices, collectors, nextDeviceId, nextCollectorId, tombstones, true, 0L); } public SimulatorState { if (version != CURRENT_VERSION) throw new IllegalStateException("Unsupported BTS simulator state version: " + version); softwareAccessible = softwareAccessible == null ? true : softwareAccessible; devices = List.copyOf(devices); collectors = List.copyOf(collectors); tombstones = List.copyOf(tombstones); } } record DeviceState(int deviceId, String ip, boolean online, List channels, BtsDeviceProfile profile) { public DeviceState { channels = List.copyOf(channels); profile = profile == null ? BtsDeviceProfile.virtual(channels.size()) : profile; } /** 兼容旧版只保存拓扑和通道状态的模拟设备。 */ public DeviceState(int deviceId, String ip, boolean online, List channels) { this(deviceId, ip, online, channels, BtsDeviceProfile.virtual(channels.size())); } } record CollectorState(int collectorId, String deviceCode, String ip, String mac, String name, String manufacturer, String model, int channelCount, boolean online, int sampleIntervalMs, List channels, List latestMeasurements) { public CollectorState { channels = List.copyOf(channels); latestMeasurements = List.copyOf(latestMeasurements); } public CollectorState(int collectorId, String deviceCode, String ip, String mac, String name, String manufacturer, String model, int channelCount, boolean online) { this(collectorId, deviceCode, ip, mac, name, manufacturer, model, channelCount, online, DevelopmentCollectorSimulation.DEFAULT_SAMPLE_INTERVAL_MS, DevelopmentCollectorSimulation.defaultChannels(channelCount), List.of()); } } record CollectorChannelState(String channelCode, List metrics, DeviceWorkStatus workStatus) { public CollectorChannelState { metrics = List.copyOf(metrics); workStatus = workStatus == null ? DeviceWorkStatus.WORKING : workStatus; } public CollectorChannelState(String channelCode, List metrics) { this(channelCode, metrics, DeviceWorkStatus.WORKING); } } record CollectorMetricState(String metricCode, BigDecimal value, String unit) { } record CollectorRealtimeMeasurement(String adapterCode, String collectorCode, String channelCode, long sequenceId, Instant deviceTime, String deviceTimeRaw, Instant serverReceivedAt, String metricCode, BigDecimal value, String unit) { } record ChannelState(int channelId, boolean online, DeviceWorkStatus workStatus) { } /** BTS 检测柜的可配置厂商 profile;参数用于发现展示和边界内的演示数据生成。 */ record BtsDeviceProfile(int devtype, int subDeviceId, String name, String manufacturer, String model, String serialNumber, String firmwareVersion, int channelCount, BigDecimal currentMinA, BigDecimal currentMaxA, BigDecimal voltageMinV, BigDecimal voltageMaxV, int sampleIntervalMs) { public BtsDeviceProfile { if (devtype < 0 || subDeviceId < 0 || channelCount < 1 || sampleIntervalMs < 1) throw new IllegalArgumentException("Invalid BTS device profile limits"); if (name == null || name.isBlank() || manufacturer == null || manufacturer.isBlank() || model == null || model.isBlank() || serialNumber == null || serialNumber.isBlank() || firmwareVersion == null || firmwareVersion.isBlank()) throw new IllegalArgumentException("BTS device profile metadata must not be blank"); if (currentMinA == null || currentMaxA == null || voltageMinV == null || voltageMaxV == null || currentMinA.compareTo(currentMaxA) > 0 || voltageMinV.compareTo(voltageMaxV) > 0) throw new IllegalArgumentException("Invalid BTS device profile ranges"); } public static BtsDeviceProfile virtual(int channelCount) { return new BtsDeviceProfile(22, 1, "dev-sim 设备", "开发模拟器", "BTS Virtual Cabinet", "SIM-VIRTUAL", "dev-sim", channelCount, new BigDecimal("-6.000"), new BigDecimal("6.000"), BigDecimal.ZERO, new BigDecimal("5.000"), 100); } } record ChannelTombstone(int deviceId, String ip, int channelId, int remainingDiscoveries) { } record RecentRequest(Instant receivedAt, String command, String request, String response) { } }