fix: preserve mileage metadata on location events
This commit is contained in:
@@ -16,6 +16,7 @@ import java.time.Instant;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -96,10 +97,13 @@ public final class YutongEventMapper implements EventMapper<MqttPayload> {
|
|||||||
speed == null ? 0.0 : speed,
|
speed == null ? 0.0 : speed,
|
||||||
direction == null ? 0.0 : direction,
|
direction == null ? 0.0 : direction,
|
||||||
0, 0);
|
0, 0);
|
||||||
|
Map<String, String> locationMeta = mileage == null
|
||||||
|
? meta
|
||||||
|
: withMeta(meta, "total_mileage_km", formatDouble(mileage));
|
||||||
out.add(new VehicleEvent.Location(
|
out.add(new VehicleEvent.Location(
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
vin, ProtocolId.MQTT_YUTONG, payload.deviceTime(), ingestTime,
|
vin, ProtocolId.MQTT_YUTONG, payload.deviceTime(), ingestTime,
|
||||||
null, meta, loc));
|
null, locationMeta, loc));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -233,6 +237,13 @@ public final class YutongEventMapper implements EventMapper<MqttPayload> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String formatDouble(double value) {
|
||||||
|
String formatted = String.format(Locale.ROOT, "%.6f", value);
|
||||||
|
return formatted.indexOf('.') < 0
|
||||||
|
? formatted
|
||||||
|
: formatted.replaceAll("0+$", "").replaceAll("\\.$", "");
|
||||||
|
}
|
||||||
|
|
||||||
private record IdentityResolution(VehicleIdentity identity, String errorMessage) {
|
private record IdentityResolution(VehicleIdentity identity, String errorMessage) {
|
||||||
private static IdentityResolution ok(VehicleIdentity identity) {
|
private static IdentityResolution ok(VehicleIdentity identity) {
|
||||||
return new IdentityResolution(identity, null);
|
return new IdentityResolution(identity, null);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class YutongEventMapperTest {
|
|||||||
VehicleEvent.Location loc = (VehicleEvent.Location) events.stream()
|
VehicleEvent.Location loc = (VehicleEvent.Location) events.stream()
|
||||||
.filter(e -> e instanceof VehicleEvent.Location).findFirst().orElseThrow();
|
.filter(e -> e instanceof VehicleEvent.Location).findFirst().orElseThrow();
|
||||||
assertThat(loc.payload().longitude()).isEqualTo(116.397128, org.assertj.core.data.Offset.offset(0.000001));
|
assertThat(loc.payload().longitude()).isEqualTo(116.397128, org.assertj.core.data.Offset.offset(0.000001));
|
||||||
|
assertThat(loc.metadata()).containsEntry("total_mileage_km", "123456.7");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.time.Instant;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -164,10 +165,13 @@ public final class Gb32960EventMapper implements EventMapper<Gb32960Message> {
|
|||||||
p.longitude, p.latitude, 0.0,
|
p.longitude, p.latitude, 0.0,
|
||||||
v != null && v.speedKmh != null ? v.speedKmh : 0.0,
|
v != null && v.speedKmh != null ? v.speedKmh : 0.0,
|
||||||
0.0, 0, p.statusFlag);
|
0.0, 0, p.statusFlag);
|
||||||
|
Map<String, String> locationMeta = v != null && v.totalMileageKm != null
|
||||||
|
? withMeta(meta, "total_mileage_km", formatDouble(v.totalMileageKm))
|
||||||
|
: meta;
|
||||||
out.add(new VehicleEvent.Location(
|
out.add(new VehicleEvent.Location(
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
header.vin(), ProtocolId.GB32960, eventTime, ingestTime,
|
header.vin(), ProtocolId.GB32960, eventTime, ingestTime,
|
||||||
null, meta, loc));
|
null, locationMeta, loc));
|
||||||
}
|
}
|
||||||
if (alarm != null && shouldEmitAlarm(alarm)) {
|
if (alarm != null && shouldEmitAlarm(alarm)) {
|
||||||
// 只在存在告警等级或氢安全关键位时发 Alarm,减少正常高频帧对告警消费者的噪声。
|
// 只在存在告警等级或氢安全关键位时发 Alarm,减少正常高频帧对告警消费者的噪声。
|
||||||
@@ -330,4 +334,17 @@ public final class Gb32960EventMapper implements EventMapper<Gb32960Message> {
|
|||||||
if (codes == null || codes.isEmpty()) return;
|
if (codes == null || codes.isEmpty()) return;
|
||||||
for (Long c : codes) out.add(prefix + "-" + Long.toHexString(c));
|
for (Long c : codes) out.add(prefix + "-" + Long.toHexString(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> withMeta(Map<String, String> meta, String key, String value) {
|
||||||
|
java.util.HashMap<String, String> copy = new java.util.HashMap<>(meta);
|
||||||
|
copy.put(key, value == null ? "" : value);
|
||||||
|
return Map.copyOf(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatDouble(double value) {
|
||||||
|
String formatted = String.format(Locale.ROOT, "%.6f", value);
|
||||||
|
return formatted.indexOf('.') < 0
|
||||||
|
? formatted
|
||||||
|
: formatted.replaceAll("0+$", "").replaceAll("\\.$", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ class Gb32960EventMapperTest {
|
|||||||
assertThat(events).anyMatch(e -> e instanceof VehicleEvent.Location);
|
assertThat(events).anyMatch(e -> e instanceof VehicleEvent.Location);
|
||||||
assertThat(events).allMatch(e -> e.source() == ProtocolId.GB32960);
|
assertThat(events).allMatch(e -> e.source() == ProtocolId.GB32960);
|
||||||
assertThat(events).allMatch(e -> e.vin().equals("LTEST000000000002"));
|
assertThat(events).allMatch(e -> e.vin().equals("LTEST000000000002"));
|
||||||
|
VehicleEvent.Location location = events.stream()
|
||||||
|
.filter(VehicleEvent.Location.class::isInstance)
|
||||||
|
.map(VehicleEvent.Location.class::cast)
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
assertThat(location.metadata()).containsEntry("total_mileage_km", "123456.7");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user