推式来源的工步名称改用判定出的方向(甲方原词)
现场对着甲方"实时"页确认:那一列叫「状态」(值 停止/放电/搁置/完成),甲方自己说这就是他们看的
"工步名称";随后核对工步方案 .pcj 确认方案里每个工步只有 <Step StepLabel="步_1"> 这种标号加
CtrlTypeName(实测 Rest/Current/Voltage 这类操作类型),没有描述性名称——源头能给的"名字"比我们
判定出的方向更难读。
因此工步名称填判定出的方向,用甲方那一列的原词:充电/放电/搁置。step_type 仍是
charge/discharge/rest;方向未知时名称与类型一起留空,不写没有根据的名字。
用真实落地数据核对:chlid=24 的工步名称依次为 放电/搁置/充电/搁置…;后端全量测试通过。
| | |
| | | */ |
| | | private enum StepDirection |
| | | { |
| | | CHARGE("charge"), DISCHARGE("discharge"), REST("rest"), UNKNOWN(null); |
| | | CHARGE("charge", "充电"), DISCHARGE("discharge", "放电"), REST("rest", "搁置"), UNKNOWN(null, null); |
| | | |
| | | private final String label; |
| | | private final String displayName; |
| | | |
| | | StepDirection(String label) { this.label = label; } |
| | | StepDirection(String label, String displayName) { this.label = label; this.displayName = displayName; } |
| | | |
| | | /** 写进工步记录的类型:来源没给类型时交出的是判定出的方向名称,未知方向留空。 */ |
| | | String label() { return label; } |
| | | |
| | | /** |
| | | * 交出去的工步名称。这类来源的工步方案里只有「步_N」这种标号,没有描述性名称 |
| | | * (2026-10-09 现场核对 .pcj:<Step StepLabel="步_1"> + CtrlTypeName=Rest/Current); |
| | | * 而甲方软件那一列「状态」显示的就是充电/放电/搁置——所以用同一套词当工步名称, |
| | | * 值同样来自电流符号判定,**不是设备给的名称**(现场清单与 ADR-0067 都记了这一条)。 |
| | | */ |
| | | String displayName() { return displayName; } |
| | | |
| | | /** 该工步自身累计的单项值。搁置段实测两向都不增长,所以它的累计是 0 而不是缺失。 */ |
| | | BigDecimal own(BigDecimal charge, BigDecimal discharge) |
| | |
| | | putIfPresent(measurements, "dischargeEnergy", last.getDischargeEnergyWh()); |
| | | BigDecimal capacity = direction.own(last.getChargeCapacityAh(), last.getDischargeCapacityAh()); |
| | | BigDecimal energy = direction.own(last.getChargeEnergyWh(), last.getDischargeEnergyWh()); |
| | | // 工步名称用判定出的方向(充电/放电/搁置):该来源的方案里只有「步_N」标号,没有描述性名称, |
| | | // 而甲方软件自己那一列「状态」显示的就是这三个词。它和方向同源,不是设备给的名称。 |
| | | return new StepRecord(sourceRecordId(sourceRef, "step", group.key().cycleNo() + ":" + group.key().stepNo()), |
| | | group.key().cycleNo(), group.key().stepNo(), null, direction.label(), deviceTime(first), |
| | | group.key().cycleNo(), group.key().stepNo(), direction.displayName(), direction.label(), deviceTime(first), |
| | | deviceTime(last), decimal(last.getVoltageV()), decimal(last.getCurrentA()), |
| | | capacity == null ? null : capacity.doubleValue(), energy == null ? null : energy.doubleValue(), |
| | | last.getDeviceTimeRaw(), last.getTimezoneId(), receivedAt(last), measurements); |
| | |
| | | assertEquals(4, step.stepNo()); |
| | | // 方向取自该段电流符号:段内两行恒正即充电。 |
| | | assertEquals("charge", step.stepType()); |
| | | // 工步名称用同一套词(甲方软件那一列「状态」显示的就是充电/放电/搁置):该来源的方案里 |
| | | // 只有「步_N」标号,这个名称是判定出的方向,不是设备给的名称。 |
| | | assertEquals("充电", step.stepName()); |
| | | // 容量与能量是工步累计,取该段末行的值;工步时间是工步内相对时间(秒)。 |
| | | assertEquals(0.121, step.capacityAh(), 1e-9); |
| | | assertEquals(0.31, step.energyWh(), 1e-9); |
| | |
| | | .map(step -> step.cycleNo() + ":" + step.stepNo() + ":" + step.stepType()).toList()); |
| | | // 搁置段自身的累计是 0(该段什么都没充放),不是缺失。 |
| | | assertEquals(0.0, steps.get(1).capacityAh(), 1e-9); |
| | | // 搁置段的名称同样是判定出来的。 |
| | | assertEquals("搁置", steps.get(1).stepName()); |
| | | assertEquals(0.0, steps.get(1).energyWh(), 1e-9); |
| | | assertEquals(List.of(1), cycles.stream().map(CycleRecord::cycleNo).toList()); |
| | | |
| | |
| | | assertEquals(1, undecided.stepNo()); |
| | | // 方向不唯一时不猜:类型留空、单项容量与能量留空。 |
| | | assertNull(undecided.stepType()); |
| | | // 方向判不出来时名称也留空:不写一个没根据的名字。 |
| | | assertNull(undecided.stepName()); |
| | | assertNull(undecided.capacityAh()); |
| | | assertNull(undecided.energyWh()); |
| | | // 四组容量能量作为设备事实照原样保留,供核对。 |