补齐控制台来源身份与时间字段
查询返回适配器和设备通道完整身份以及工步循环服务器接收时间,避免不同来源碰撞。
| | |
| | | void appliesRealtimeEditAndFiltersDeletedRow() |
| | | { |
| | | when(tests.selectTestById(7L)).thenReturn(new TTest()); |
| | | Map<String, Object> edited = row("deviceId", 22L, "channelId", 8L, "sequenceId", 3L, |
| | | Map<String, Object> edited = row("adapterId", 1L, "devtype", 22, "deviceId", 22L, "subdevid", 0, "channelId", 8L, "sequenceId", 3L, |
| | | "voltage", 3.7d); |
| | | Map<String, Object> deleted = row("deviceId", 22L, "channelId", 8L, "sequenceId", 4L, |
| | | Map<String, Object> deleted = row("adapterId", 1L, "devtype", 22, "deviceId", 22L, "subdevid", 0, "channelId", 8L, "sequenceId", 4L, |
| | | "voltage", 3.8d); |
| | | TTestDataOverride edit = override("22:8:3", "{\"voltage\":\"4.1000\"}", false); |
| | | TTestDataOverride remove = override("22:8:4", null, true); |
| | | TTestDataOverride edit = override("1:22:22:0:8:3", "{\"voltage\":\"4.1000\"}", false); |
| | | TTestDataOverride remove = override("1:22:22:0:8:4", null, true); |
| | | when(mapper.selectPersistedRecords(7L)).thenReturn(List.of(edited, deleted)); |
| | | when(mapper.selectDataOverrides(7L, "REALTIME")).thenReturn(List.of(edit, remove)); |
| | | |
| | |
| | | void usesStepAndCycleStableIdentities() |
| | | { |
| | | when(tests.selectTestById(8L)).thenReturn(new TTest()); |
| | | Map<String, Object> step = row("deviceId", 22L, "channelId", 8L, "cycleNo", 2, "stepNo", 4, |
| | | Map<String, Object> step = row("adapterId", 1L, "devtype", 22, "deviceId", 22L, "subdevid", 0, "channelId", 8L, "cycleNo", 2, "stepNo", 4, |
| | | "capacity", 1d); |
| | | Map<String, Object> cycle = row("deviceId", 22L, "channelId", 8L, "cycleNo", 2, |
| | | Map<String, Object> cycle = row("adapterId", 1L, "devtype", 22, "deviceId", 22L, "subdevid", 0, "channelId", 8L, "cycleNo", 2, |
| | | "efficiency", 90d); |
| | | when(mapper.selectPersistedSteps(8L)).thenReturn(List.of(step)); |
| | | when(mapper.selectPersistedCycles(8L)).thenReturn(List.of(cycle)); |
| | | when(mapper.selectDataOverrides(8L, "STEP")).thenReturn(List.of(override("step:22:8:2:4", |
| | | when(mapper.selectDataOverrides(8L, "STEP")).thenReturn(List.of(override("step:1:22:22:0:8:2:4", |
| | | "{\"capacity\":\"2.0000\"}", false))); |
| | | when(mapper.selectDataOverrides(8L, "CYCLE")).thenReturn(List.of(override("cycle:22:8:2", |
| | | when(mapper.selectDataOverrides(8L, "CYCLE")).thenReturn(List.of(override("cycle:1:22:22:0:8:2", |
| | | "{\"efficiency\":\"95.00\"}", false))); |
| | | TestDataQueryServiceImpl service = new TestDataQueryServiceImpl(mapper, tests); |
| | | |
| | |
| | | private Long[] parseDeleteIdentity(String value, String dataType) |
| | | { |
| | | String[] parts = value.split(":", -1); |
| | | int expectedLength = "STEP".equals(dataType) ? 5 : "CYCLE".equals(dataType) ? 4 : 3; |
| | | if (parts.length != expectedLength) return null; |
| | | int expectedLength = "STEP".equals(dataType) ? 8 : "CYCLE".equals(dataType) ? 7 : 6; |
| | | int legacyLength = "STEP".equals(dataType) ? 5 : "CYCLE".equals(dataType) ? 4 : 3; |
| | | if (parts.length != expectedLength && parts.length != legacyLength) return null; |
| | | int offset = "REALTIME".equals(dataType) ? 0 : 1; |
| | | try |
| | | { |
| | | if (parts.length == legacyLength && "STEP".equals(dataType)) |
| | | return new Long[] { Long.valueOf(parts[1]), Long.valueOf(parts[2]), |
| | | Long.valueOf(parts[3]), Long.valueOf(parts[4]) }; |
| | | if (parts.length == legacyLength) |
| | | return new Long[] { Long.valueOf(parts[0]), Long.valueOf(parts[1]), Long.valueOf(parts[2]) }; |
| | | if ("STEP".equals(dataType)) |
| | | return new Long[] { Long.valueOf(parts[offset]), Long.valueOf(parts[offset + 1]), |
| | | Long.valueOf(parts[offset + 2]), Long.valueOf(parts[offset + 3]) }; |
| | | Long.valueOf(parts[offset + 2]), Long.valueOf(parts[offset + 3]), |
| | | Long.valueOf(parts[offset + 4]), Long.valueOf(parts[offset + 5]), |
| | | Long.valueOf(parts[offset + 6]) }; |
| | | return new Long[] { Long.valueOf(parts[offset]), Long.valueOf(parts[offset + 1]), |
| | | Long.valueOf(parts[offset + 2]) }; |
| | | Long.valueOf(parts[offset + 2]), Long.valueOf(parts[offset + 3]), |
| | | Long.valueOf(parts[offset + 4]), Long.valueOf(parts[offset + 5]) }; |
| | | } |
| | | catch (NumberFormatException exception) { return null; } |
| | | } |
| | |
| | | |
| | | private String stableIdentity(String dataType, Map<String, Object> row) |
| | | { |
| | | String deviceId = value(row, "deviceId"); |
| | | String channelId = value(row, "channelId"); |
| | | String adapterId = identityPart(row, "adapterId"); |
| | | String devtype = identityPart(row, "devtype"); |
| | | String deviceId = identityPart(row, "deviceId"); |
| | | String subdevid = identityPart(row, "subdevid"); |
| | | String channelId = identityPart(row, "channelId"); |
| | | String cycleNo = value(row, "cycleNo"); |
| | | if ("REALTIME".equals(dataType)) return deviceId + ":" + channelId + ":" + value(row, "sequenceId"); |
| | | if ("STEP".equals(dataType)) return "step:" + deviceId + ":" + channelId + ":" + cycleNo + ":" + value(row, "stepNo"); |
| | | return "cycle:" + deviceId + ":" + channelId + ":" + cycleNo; |
| | | String channelIdentity = String.join(":", adapterId, devtype, deviceId, subdevid, channelId); |
| | | if ("REALTIME".equals(dataType)) return channelIdentity + ":" + value(row, "sequenceId"); |
| | | if ("STEP".equals(dataType)) return "step:" + channelIdentity + ":" + cycleNo + ":" + value(row, "stepNo"); |
| | | return "cycle:" + channelIdentity + ":" + cycleNo; |
| | | } |
| | | |
| | | private String identityPart(Map<String, Object> row, String key) |
| | | { |
| | | Object value = row == null ? null : row.get(key); |
| | | return value == null ? "" : String.valueOf(value); |
| | | } |
| | | |
| | | private String value(Map<String, Object> row, String key) |
| | | { |
| | | Object value = row == null ? null : row.get(key); |
| | | return value == null ? "" : String.valueOf(value); |
| | | return identityPart(row, key); |
| | | } |
| | | |
| | | private void requireTest(Long testId) |
| | |
| | | sample.device_time_utc recordedAt, sample.device_time_utc absoluteTime, |
| | | sample.device_time_utc deviceTime, sample.received_at_utc serverReceivedAt, |
| | | sample.voltage_v voltage, sample.current_a current, sample.capacity_ah capacity, |
| | | sample.energy_wh energy, channel.devid deviceId, channel.chlid channelId |
| | | sample.energy_wh energy, channel.adapter_id adapterId, channel.adapter_code adapterCode, |
| | | channel.devtype devtype, channel.devid deviceId, channel.subdevid subdevid, channel.chlid channelId |
| | | from t_test_sample sample |
| | | join t_test_battery battery on battery.relation_id = sample.binding_id and battery.del_flag = 0 |
| | | join t_detection_channel channel on channel.channel_id = sample.channel_id and channel.del_flag = 0 |
| | |
| | | sample.step_type stepType, coalesce(sample.step_name, sample.step_type) actualStepLabel, |
| | | count(*) recordCount, |
| | | min(sample.device_time_utc) recordedAt, min(sample.device_time_utc) absoluteTime, |
| | | max(sample.received_at_utc) serverReceivedAt, |
| | | timestampdiff(second, min(sample.device_time_utc), max(sample.device_time_utc)) stepDuration, |
| | | max(sample.capacity_ah) capacity, max(sample.energy_wh) energy, |
| | | min(sample.voltage_v) startVoltage, |
| | | max(sample.voltage_v) endVoltage, |
| | | max(case when sample.current_a >= 0 then sample.voltage_v end) chargePeakVoltage, |
| | | min(case when sample.current_a < 0 then sample.voltage_v end) dischargeValleyVoltage, |
| | | channel.devid deviceId, channel.chlid channelId |
| | | channel.adapter_id adapterId, channel.adapter_code adapterCode, channel.devtype devtype, |
| | | channel.devid deviceId, channel.subdevid subdevid, channel.chlid channelId |
| | | from t_test_sample sample |
| | | join t_test_battery battery on battery.relation_id = sample.binding_id and battery.del_flag = 0 |
| | | join t_detection_channel channel on channel.channel_id = sample.channel_id and channel.del_flag = 0 |
| | | where sample.test_id = #{testId} |
| | | group by sample.binding_id, battery.battery_no, channel.devid, channel.chlid, sample.cycle_no, sample.step_no, |
| | | group by sample.binding_id, battery.battery_no, channel.adapter_id, channel.adapter_code, channel.devtype, |
| | | channel.devid, channel.subdevid, channel.chlid, sample.cycle_no, sample.step_no, |
| | | sample.step_type, sample.step_name |
| | | order by sample.cycle_no, sample.step_no, battery.battery_no |
| | | </select> |
| | |
| | | concat('CYCLE-', channel.devid, '-', channel.chlid, '-', sample.cycle_no) recordNo, |
| | | battery.battery_no batteryNo, sample.cycle_no cycleNo, count(*) recordCount, |
| | | min(sample.device_time_utc) recordedAt, min(sample.device_time_utc) absoluteTime, |
| | | max(sample.received_at_utc) serverReceivedAt, |
| | | greatest(max(case when sample.current_a >= 0 then sample.capacity_ah end), 0) chargeCapacity, |
| | | greatest(max(case when sample.current_a < 0 then sample.capacity_ah end), 0) dischargeCapacity, |
| | | greatest(max(case when sample.current_a >= 0 then sample.energy_wh end), 0) chargeEnergy, |
| | |
| | | then greatest(max(case when sample.current_a < 0 then sample.capacity_ah end), 0) |
| | | / max(case when sample.current_a >= 0 then sample.capacity_ah end) * 100 |
| | | else 0 end efficiency, |
| | | channel.devid deviceId, channel.chlid channelId |
| | | channel.adapter_id adapterId, channel.adapter_code adapterCode, channel.devtype devtype, |
| | | channel.devid deviceId, channel.subdevid subdevid, channel.chlid channelId |
| | | from t_test_sample sample |
| | | join t_test_battery battery on battery.relation_id = sample.binding_id and battery.del_flag = 0 |
| | | join t_detection_channel channel on channel.channel_id = sample.channel_id and channel.del_flag = 0 |
| | | where sample.test_id = #{testId} |
| | | group by sample.binding_id, battery.battery_no, channel.devid, channel.chlid, sample.cycle_no |
| | | group by sample.binding_id, battery.battery_no, channel.adapter_id, channel.adapter_code, channel.devtype, |
| | | channel.devid, channel.subdevid, channel.chlid, sample.cycle_no |
| | | order by sample.cycle_no, battery.battery_no |
| | | </select> |
| | | <select id="selectTestResults" parameterType="TTestResult" resultMap="TTestResultResultMap"> |