From 147428971be43eed90a79f3849f15000d3855390 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期一, 28 九月 2026 15:15:22 +0800
Subject: [PATCH] 实现新威 7.6 直连取数与逐行接收
---
battery-device-api/src/main/java/com/battery/device/api/TestDataObservationAdapter.java | 47 +++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/battery-device-api/src/main/java/com/battery/device/api/TestDataObservationAdapter.java b/battery-device-api/src/main/java/com/battery/device/api/TestDataObservationAdapter.java
index 3dd9033..ef44f5d 100644
--- a/battery-device-api/src/main/java/com/battery/device/api/TestDataObservationAdapter.java
+++ b/battery-device-api/src/main/java/com/battery/device/api/TestDataObservationAdapter.java
@@ -12,8 +12,12 @@
/** 返回指定检测柜通道最近一次实时观测;没有成功观测时返回空值。 */
CabinetRealtime latestCabinet(ChannelIdentity channel);
- /** 返回采集器独立实时快照;不得通过历史下载补采。 */
- CollectorRealtime latestCollector(String collectorCode);
+ /**
+ * 返回采集器独立实时快照;不得通过历史下载补采。
+ * 采集器测量按"同一来源的辅助测量"表达(ADR-0064),所以必须指名是哪个来源实例,
+ * 否则多实例下无法确定该向哪台机器请求。
+ */
+ CollectorRealtime latestCollector(String adapterCode, String collectorCode);
/** 返回设备直接提供的工步统计,不从实时采样推导。 */
List<StepRecord> stepRecords(ChannelIdentity channel);
@@ -27,14 +31,49 @@
/** 返回设备计划方案;设备未提供时保持为空,不推导计划。 */
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)
--
Gitblit v1.7.1