| | |
| | | /** 返回指定检测柜通道最近一次实时观测;没有成功观测时返回空值。 */ |
| | | CabinetRealtime latestCabinet(ChannelIdentity channel); |
| | | |
| | | /** 返回采集器独立实时快照;不得通过历史下载补采。 */ |
| | | CollectorRealtime latestCollector(String collectorCode); |
| | | /** |
| | | * 返回采集器独立实时快照;不得通过历史下载补采。 |
| | | * 采集器测量按"同一来源的辅助测量"表达(ADR-0064),所以必须指名是哪个来源实例, |
| | | * 否则多实例下无法确定该向哪台机器请求。 |
| | | */ |
| | | CollectorRealtime latestCollector(String adapterCode, String collectorCode); |
| | | |
| | | /** 返回设备直接提供的工步统计,不从实时采样推导。 */ |
| | | List<StepRecord> stepRecords(ChannelIdentity channel); |
| | | |
| | | /** 返回设备直接提供的循环统计,不补齐设备未返回的记录。 */ |
| | | /** |
| | | * 返回该来源的循环统计。设备直接提供循环汇总行时原样返回;设备只有工步层时由适配器按循环聚合, |
| | | * 并用 {@link CycleRecord#sourceKind()} 标注为聚合来源,使调用方与界面能区分推导值与设备事实。 |
| | | * 不补齐来源未提供的循环,也不跨循环借值。 |
| | | */ |
| | | List<CycleRecord> cycleRecords(ChannelIdentity channel); |
| | | |
| | | /** 返回适配器定义的实时持久化槽位间隔。 */ |
| | |
| | | /** 返回设备计划方案;设备未提供时保持为空,不推导计划。 */ |
| | | default TestPlan testPlan(ChannelIdentity channel) { return null; } |
| | | |
| | | /** |
| | | * 读取通道当前的接收水位。水位是来源里已存在的最新一行(设备绝对时间 + 协议序号), |
| | | * 用于把"开始接收"和"继续接收"切在这一时刻之后:水位之前的数据行即使仍在来源里也不进本测试。 |
| | | * |
| | | * <p>返回空值表示该来源不按设备数据行接收(例如由系统轮询产生槽位的来源),此时不启用逐行接收。 |
| | | * 设备时间为空的水位表示这一刻来源里没有任何可用行,之后出现的行全部属于本次接收。 |
| | | * 来源不可达时必须抛出异常,不能返回空值——空值会被误当作"来源不按行接收"。 |
| | | */ |
| | | default SampleWatermark currentWatermark(ChannelIdentity channel) { return null; } |
| | | |
| | | /** |
| | | * 返回严格晚于水位的设备数据行,按设备时间与协议序号升序。 |
| | | * 同一绝对秒内的多行各自成立,调用方不得按秒合并。 |
| | | * 水位为空表示调用方尚未取得水位,此时返回空列表:不把来源里的设备历史并入本次接收。 |
| | | */ |
| | | default List<CabinetRealtime> samplesSince(ChannelIdentity channel, SampleWatermark watermark) { return List.of(); } |
| | | |
| | | /** 接收水位:设备绝对时间与协议序号的二元组;序号在同一厂商测试内有效。 */ |
| | | record SampleWatermark(Instant deviceTime, long sequenceId) { } |
| | | |
| | | record TestPlan(int currentCycleNo, int currentStepNo, int plannedCycleCount, List<PlanRow> rows) { } |
| | | record PlanRow(String rowType, int stepNo, Integer cyclePosition, String stepName, double durationSeconds, |
| | | Double voltageV, String executionStatus, Integer cycleCount, Long recordCount) { } |
| | | |
| | | /** 柜端成功观测;相对时长使用设备提供的秒数,缺失不按采样时间推算。 */ |
| | | /** |
| | | * 柜端成功观测;相对时长使用设备提供的秒数,缺失不按采样时间推算。 |
| | | * {@code sourceRecordId} 是来源行的稳定身份(如厂商测试编号加协议序号), |
| | | * 供幂等与冲突判定使用;来源不提供时保持为空,调用方退化为按协议序号识别。 |
| | | */ |
| | | record CabinetRealtime(long sequenceId, Instant deviceTime, double currentA, double voltageV, |
| | | double capacityAh, double energyWh, int cycleNo, int stepNo, String stepName, String stepType, |
| | | Instant serverReceivedAt, String deviceTimeRaw, String timezoneId, Long relativeTimeSeconds) { } |
| | | Instant serverReceivedAt, String deviceTimeRaw, String timezoneId, Long relativeTimeSeconds, |
| | | String sourceRecordId) |
| | | { |
| | | /** 兼容不携带来源行身份的既有适配器。 */ |
| | | public CabinetRealtime(long sequenceId, Instant deviceTime, double currentA, double voltageV, |
| | | double capacityAh, double energyWh, int cycleNo, int stepNo, String stepName, String stepType, |
| | | Instant serverReceivedAt, String deviceTimeRaw, String timezoneId, Long relativeTimeSeconds) |
| | | { |
| | | this(sequenceId, deviceTime, currentA, voltageV, capacityAh, energyWh, cycleNo, stepNo, stepName, |
| | | stepType, serverReceivedAt, deviceTimeRaw, timezoneId, relativeTimeSeconds, null); |
| | | } |
| | | } |
| | | |
| | | record CollectorRealtime(String collectorCode, boolean online, int sampleIntervalMs, |
| | | List<CollectorMeasurement> measurements, String timezoneId) |
| | |
| | | record CollectorMeasurement(String channelCode, long sequenceId, Instant deviceTime, String deviceTimeRaw, |
| | | Instant serverReceivedAt, String metricCode, BigDecimal value, String unit) { } |
| | | |
| | | /** |
| | | * 一条设备工步层记录。{@code stepType} 保留设备给出的原始类型(新威为数字枚举), |
| | | * 方向由调用方按该类型解释,不由适配器按电流符号推断。 |
| | | * |
| | | * <p>{@code endVoltageV} 与 {@code endCurrentA} 是该工步结束时的设备读数。 |
| | | * {@code capacityAh} 与 {@code energyWh} 是该工步自身累计的单项值,只在方向已确认时给出; |
| | | * 方向未知时保持为空,四个方向的容量能量仍在 {@code measurements} 中作为设备事实保留。 |
| | | */ |
| | | record StepRecord(String sourceRecordId, int cycleNo, int stepNo, String stepName, String stepType, |
| | | Instant startedAt, Instant endedAt, double endVoltageV, double capacityAh, double energyWh, |
| | | String deviceTimeRaw, String timezoneId, Instant serverReceivedAt, |
| | | Instant startedAt, Instant endedAt, double endVoltageV, double endCurrentA, Double capacityAh, |
| | | Double energyWh, String deviceTimeRaw, String timezoneId, Instant serverReceivedAt, |
| | | java.util.Map<String, BigDecimal> measurements) { } |
| | | |
| | | /** |
| | | * 一条循环统计。{@code sourceRecordId} 是来源行的稳定身份,供幂等与冲突判定使用。 |
| | | * |
| | | * <p>设备没有循环汇总行时,循环统计由工步层按循环聚合得出;{@code sourceKind} 记录这个来源事实, |
| | | * 使界面与导出能明确标注"这个数是聚合的还是设备给的",取值只能是下面三个常量之一。 |
| | | * |
| | | * <p>{@code efficiency} 为单位为百分比的充放电效率。该循环没有可用的充电容量时保持为空: |
| | | * 未知比率不用零代替,零值只表示设备确实给出零。 |
| | | */ |
| | | record CycleRecord(String sourceRecordId, int cycleNo, Instant startedAt, Instant endedAt, |
| | | double chargeCapacityAh, double dischargeCapacityAh, double chargeEnergyWh, |
| | | double dischargeEnergyWh, double efficiency, String deviceTimeRaw, String timezoneId, |
| | | Instant serverReceivedAt) { } |
| | | double dischargeEnergyWh, Double efficiency, String deviceTimeRaw, String timezoneId, |
| | | Instant serverReceivedAt, String sourceKind) |
| | | { |
| | | /** 来源类别:设备直接提供。 */ |
| | | public static final String SOURCE_DEVICE = "DEVICE"; |
| | | /** 来源类别:来源没有循环汇总行,由工步层按循环聚合得出。 */ |
| | | public static final String SOURCE_AGGREGATED = "AGGREGATED"; |
| | | /** 来源类别:授权文件导入。 */ |
| | | public static final String SOURCE_IMPORTED = "IMPORTED"; |
| | | |
| | | public CycleRecord |
| | | { |
| | | // 未标注一律按设备事实:引入聚合之前写进库的循环记录都来自设备或文件。 |
| | | sourceKind = sourceKind == null || sourceKind.isBlank() ? SOURCE_DEVICE : sourceKind; |
| | | } |
| | | } |
| | | } |