From 2e8c5b79ff8930b8e8efad2323c0b333a721d1df Mon Sep 17 00:00:00 2001
From: Michael7371 <40476797+Michael7371@users.noreply.github.com>
Date: Thu, 3 Jul 2025 17:26:07 -0600
Subject: [PATCH 01/24] updates for BSM deduplication
---
.vscode/settings.json | 3 +-
docker-compose.yml | 4 +-
jpo-deduplicator/pom.xml | 102 +++----
.../deduplicator/DeduplicatorProperties.java | 68 ++---
.../DeduplicatorServiceController.java | 140 +++++-----
.../processors/DeduplicationProcessor.java | 20 +-
.../processors/OdeBsmJsonProcessor.java | 122 ++++++---
.../processors/OdeMapJsonProcessor.java | 157 ++++++-----
.../OdeBsmJsonProcessorSupplier.java | 11 +-
.../serialization/JsonSerdes.java | 59 +++-
.../topologies/BsmDeduplicatorTopology.java | 80 ++++--
.../topologies/MapDeduplicatorTopology.java | 257 +++++++++---------
.../ProcessedBsmDeduplicatorTopology.java | 208 +++++++-------
.../ProcessedMapDeduplicatorTopology.java | 192 ++++++-------
.../ProcessedMapWktDeduplicatorTopology.java | 195 ++++++-------
.../ProcessedSpatDeduplicatorTopology.java | 201 +++++++-------
.../its/jpo/deduplicator/utils/GeoUtils.java | 24 +-
.../src/main/resources/application.yaml | 24 +-
.../src/main/resources/logback.xml | 20 --
.../BsmDeduplicatorTopologyTest.java | 190 +++++++++----
.../ode_bsm/sample.ode-bsm-reference.json | 208 ++++++++++++++
21 files changed, 1366 insertions(+), 919 deletions(-)
delete mode 100644 jpo-deduplicator/src/main/resources/logback.xml
create mode 100644 jpo-deduplicator/src/test/resources/json/ode_bsm/sample.ode-bsm-reference.json
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 2b4f8cd..403e8e2 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,4 @@
{
- "java.configuration.updateBuildConfiguration": "automatic"
+ "java.configuration.updateBuildConfiguration": "automatic",
+ "java.debug.settings.onBuildFailureProceed": true
}
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index d955ed7..fe8fded 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -16,7 +16,7 @@ services:
privileged: false # Set true to allow writing to /proc/sys/vm/drop_caches
restart: ${RESTART_POLICY}
ports:
- - "10091:10090" # JMX
+ - "10091:10090" # JMX
environment:
DOCKER_HOST_IP: ${DOCKER_HOST_IP}
KAFKA_BOOTSTRAP_SERVERS: ${KAFKA_BOOTSTRAP_SERVERS}
@@ -56,4 +56,4 @@ services:
depends_on:
kafka:
condition: service_healthy
- required: false
\ No newline at end of file
+ required: false
diff --git a/jpo-deduplicator/pom.xml b/jpo-deduplicator/pom.xml
index bf9cba4..2b595d8 100644
--- a/jpo-deduplicator/pom.xml
+++ b/jpo-deduplicator/pom.xml
@@ -7,7 +7,7 @@
org.springframework.boot
spring-boot-starter-parent
3.1.3
-
+
usdot.jpo.ode
jpo-deduplicator
@@ -32,6 +32,9 @@
reuseReports
${project.basedir}/target/site/jacoco/jacoco.xml
java
+ 5.0.0
+ 2.1.1
+ 1.5.0
@@ -101,17 +104,17 @@
usdot.jpo.ode
jpo-ode-core
- 4.1.1
+ ${jpo.ode.version}
usdot.jpo.ode
jpo-ode-plugins
- 4.1.1
+ ${jpo.ode.version}
usdot.jpo.ode
jpo-geojsonconverter
- 2.1.1
+ ${jpo.geojsonconverter.version}
junit
@@ -159,6 +162,13 @@
1.18.30
+
+ net.javacrumbs.json-unit
+ json-unit
+ 4.1.0
+ test
+
+
@@ -290,45 +300,45 @@
-
- package-jar
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.2.0
-
-
-
- true
- lib/
-
- us.dot.its.jpo.deduplicator.DeduplicatorApplication
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
- repackage
- none
-
-
-
-
-
-
-
-
-
-
- github
- GitHub Packages
- https://maven.pkg.github.com/${github_organization}/jpo-deduplicator
-
-
-
+
+ package-jar
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.2.0
+
+
+
+ true
+ lib/
+
+ us.dot.its.jpo.deduplicator.DeduplicatorApplication
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ repackage
+ none
+
+
+
+
+
+
+
+
+
+
+ github
+ GitHub Packages
+ https://maven.pkg.github.com/${github_organization}/jpo-deduplicator
+
+
+
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java
index 287d38e..aed2feb 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java
@@ -45,7 +45,7 @@
@Getter
@Setter
@ConfigurationProperties
-public class DeduplicatorProperties implements EnvironmentAware {
+public class DeduplicatorProperties implements EnvironmentAware {
private static final Logger logger = LoggerFactory.getLogger(DeduplicatorProperties.class);
@@ -79,7 +79,7 @@ public class DeduplicatorProperties implements EnvironmentAware {
private boolean enableOdeRawEncodedTimDeduplication;
private String kafkaStateStoreOdeRawEncodedTimJsonName = "OdeRawEncodedTimJson-store";
- //Ode BsmJson Configuration
+ // Ode BsmJson Configuration
private String kafkaTopicOdeBsmJson;
private String kafkaTopicDeduplicatedOdeBsmJson;
private boolean enableOdeBsmDeduplication;
@@ -110,41 +110,21 @@ public class DeduplicatorProperties implements EnvironmentAware {
private int lingerMs = 0;
-
-
@Autowired
@Setter(AccessLevel.NONE)
private Environment env;
- /*
- * General Properties
- */
private String version;
- // public static final int OUTPUT_SCHEMA_VERSION = 6;
-
+
@Setter(AccessLevel.NONE)
private String kafkaBrokers = null;
- private static final String DEFAULT_KAFKA_PORT = "9092";
- private static final String DEFAULT_CONNECT_PORT = "8083";
-
@Setter(AccessLevel.NONE)
private String hostId;
- // @Setter(AccessLevel.NONE)
- // private String connectURL = null;
-
- // @Setter(AccessLevel.NONE)
- // private String dockerHostIP = null;
-
@Setter(AccessLevel.NONE)
private String kafkaBrokerIP = null;
-
- // @Setter(AccessLevel.NONE)
- // private String dbHostIP = null;
-
-
@Setter(AccessLevel.NONE)
@Autowired
BuildProperties buildProperties;
@@ -155,9 +135,7 @@ void initialize() {
logger.info("groupId: {}", buildProperties.getGroup());
logger.info("artifactId: {}", buildProperties.getArtifact());
logger.info("version: {}", version);
- //OdeMsgMetadata.setStaticSchemaVersion(OUTPUT_SCHEMA_VERSION);
-
-
+ // OdeMsgMetadata.setStaticSchemaVersion(OUTPUT_SCHEMA_VERSION);
String hostname;
try {
@@ -169,7 +147,6 @@ void initialize() {
}
hostId = hostname;
logger.info("Host ID: {}", hostId);
- logger.info("Initializing services on host {}", hostId);
if (kafkaBrokers == null) {
@@ -189,11 +166,11 @@ void initialize() {
if (kafkaType != null) {
confluentCloudEnabled = kafkaType.equals("CONFLUENT");
if (confluentCloudEnabled) {
-
- logger.info("Enabling Confluent Cloud Integration");
- confluentKey = getEnvironmentVariable("CONFLUENT_KEY");
- confluentSecret = getEnvironmentVariable("CONFLUENT_SECRET");
+ logger.info("Enabling Confluent Cloud Integration");
+
+ confluentKey = getEnvironmentVariable("CONFLUENT_KEY");
+ confluentSecret = getEnvironmentVariable("CONFLUENT_SECRET");
}
}
}
@@ -221,8 +198,7 @@ public Properties createStreamProperties(String name) {
// Reduce cache buffering per topology to 1MB
streamProps.put(StreamsConfig.STATESTORE_CACHE_MAX_BYTES_CONFIG, 1 * 1024 * 1024L);
// Optionally, to disable caching:
- //streamProps.put(StreamsConfig.STATESTORE_CACHE_MAX_BYTES_CONFIG, 0);
-
+ // streamProps.put(StreamsConfig.STATESTORE_CACHE_MAX_BYTES_CONFIG, 0);
// Decrease default commit interval. Default for 'at least once' mode of 30000ms
// is too slow.
@@ -250,9 +226,8 @@ public Properties createStreamProperties(String name) {
streamProps.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "zstd");
streamProps.put(ProducerConfig.LINGER_MS_CONFIG, getKafkaLingerMs());
-
- streamProps.put("cleanup.policy", "compact,delete");
- streamProps.put("log.retention.ms", "7200000"); // 2-hour retention
+ streamProps.put("cleanup.policy", "compact,delete");
+ streamProps.put("log.retention.ms", "7200000"); // 2-hour retention
streamProps.put("log.segment.bytes", "1048576"); // 1 MB block size
if (confluentCloudEnabled) {
@@ -261,13 +236,13 @@ public Properties createStreamProperties(String name) {
streamProps.put("sasl.mechanism", "PLAIN");
if (confluentKey != null && confluentSecret != null) {
- String auth = "org.apache.kafka.common.security.plain.PlainLoginModule required " +
- "username=\"" + confluentKey + "\" " +
- "password=\"" + confluentSecret + "\";";
- streamProps.put("sasl.jaas.config", auth);
- }
- else {
- logger.error("Environment variables CONFLUENT_KEY and CONFLUENT_SECRET are not set. Set these in the .env file to use Confluent Cloud");
+ String auth = "org.apache.kafka.common.security.plain.PlainLoginModule required " +
+ "username=\"" + confluentKey + "\" " +
+ "password=\"" + confluentSecret + "\";";
+ streamProps.put("sasl.jaas.config", auth);
+ } else {
+ logger.error(
+ "Environment variables CONFLUENT_KEY and CONFLUENT_SECRET are not set. Set these in the .env file to use Confluent Cloud");
}
}
@@ -290,9 +265,8 @@ public Object getProperty(String key, int i) {
}
public Boolean getConfluentCloudStatus() {
- return confluentCloudEnabled;
- }
-
+ return confluentCloudEnabled;
+ }
@Value("${kafkaTopicProcessedMap}")
public void setKafkaTopicProcessedMap(String kafkaTopicProcessedMap) {
@@ -466,7 +440,7 @@ public int getKafkaLingerMs() {
private static String getEnvironmentVariable(String variableName) {
String value = System.getenv(variableName);
if (value == null || value.equals("")) {
- System.out.println("Something went wrong retrieving the environment variable " + variableName);
+ System.out.println("Something went wrong retrieving the environment variable " + variableName);
}
return value;
}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
index 8b7a01b..6055e39 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
@@ -14,13 +14,13 @@
import lombok.Getter;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.BsmDeduplicatorTopology;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
+// import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.TimDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.OdeRawEncodedTimDeduplicatorTopology;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
+// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
+// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
+// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
+// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
@Controller
@DependsOn("createKafkaTopics")
@@ -32,82 +32,86 @@ public class DeduplicatorServiceController {
// Temporary for KafkaStreams that don't implement the Algorithm interface
@Getter
final ConcurrentHashMap streamsMap = new ConcurrentHashMap();
-
+
@Autowired
- public DeduplicatorServiceController(final DeduplicatorProperties props,
+ public DeduplicatorServiceController(final DeduplicatorProperties props,
final KafkaTemplate kafkaTemplate) {
-
try {
- if(props.isEnableProcessedMapDeduplication()){
- logger.info("Starting Processed Map Deduplicator");
- ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapDeduplicatorTopology(
- props,
- props.createStreamProperties("ProcessedMapDeduplicator")
- );
- processedMapDeduplicatorTopology.start();
- }
-
- if(props.isEnableProcessedMapWktDeduplication()){
- logger.info("Starting Processed Map WKT Deduplicator");
- ProcessedMapWktDeduplicatorTopology processedMapWktDeduplicatorTopology = new ProcessedMapWktDeduplicatorTopology(
- props,
- props.createStreamProperties("ProcessedMapWKTdeduplicator")
- );
- processedMapWktDeduplicatorTopology.start();
- }
-
- if(props.isEnableProcessedMapDeduplication()){
- logger.info("Starting Map Deduplicator");
- MapDeduplicatorTopology mapDeduplicatorTopology = new MapDeduplicatorTopology(
- props,
- props.createStreamProperties("MapDeduplicator")
- );
- mapDeduplicatorTopology.start();
- }
-
- if(props.isEnableOdeTimDeduplication()){
- logger.info("Starting Tim Deduplicator");
- TimDeduplicatorTopology timDeduplicatorTopology = new TimDeduplicatorTopology(
- props,
- props.createStreamProperties("TimDeduplicator")
- );
- timDeduplicatorTopology.start();
- }
+ // if(props.isEnableProcessedMapDeduplication()){
+ // logger.info("Starting Processed Map Deduplicator");
+ // ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new
+ // ProcessedMapDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("ProcessedMapDeduplicator")
+ // );
+ // processedMapDeduplicatorTopology.start();
+ // }
- if(props.isEnableOdeRawEncodedTimDeduplication()){
- logger.info("Starting Raw Encoded TIM Deduplicator");
- OdeRawEncodedTimDeduplicatorTopology odeRawEncodedTimDeduplicatorTopology = new OdeRawEncodedTimDeduplicatorTopology(
- props,
- props.createStreamProperties("OdeRawEncodedTimDeduplicator")
- );
- odeRawEncodedTimDeduplicatorTopology.start();
- }
+ // if(props.isEnableProcessedMapWktDeduplication()){
+ // logger.info("Starting Processed Map WKT Deduplicator");
+ // ProcessedMapWktDeduplicatorTopology processedMapWktDeduplicatorTopology = new
+ // ProcessedMapWktDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("ProcessedMapWKTdeduplicator")
+ // );
+ // processedMapWktDeduplicatorTopology.start();
+ // }
- if(props.isEnableProcessedSpatDeduplication()){
- logger.info("Starting Processed Spat Deduplicator");
- ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new ProcessedSpatDeduplicatorTopology(
- props,
- props.createStreamProperties("ProcessedSpatDeduplicator")
- );
- processedSpatDeduplicatorTopology.start();
- }
+ // if(props.isEnableProcessedMapDeduplication()){
+ // logger.info("Starting Map Deduplicator");
+ // MapDeduplicatorTopology mapDeduplicatorTopology = new
+ // MapDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("MapDeduplicator")
+ // );
+ // mapDeduplicatorTopology.start();
+ // }
+
+ // if (props.isEnableOdeTimDeduplication()) {
+ // logger.info("Starting Tim Deduplicator");
+ // TimDeduplicatorTopology timDeduplicatorTopology = new
+ // TimDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("TimDeduplicator"));
+ // timDeduplicatorTopology.start();
+ // }
+
+ // if (props.isEnableOdeRawEncodedTimDeduplication()) {
+ // logger.info("Starting Raw Encoded TIM Deduplicator");
+ // OdeRawEncodedTimDeduplicatorTopology odeRawEncodedTimDeduplicatorTopology =
+ // new OdeRawEncodedTimDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("OdeRawEncodedTimDeduplicator"));
+ // odeRawEncodedTimDeduplicatorTopology.start();
+ // }
- if(props.isEnableOdeBsmDeduplication()){
+ // if(props.isEnableProcessedSpatDeduplication()){
+ // logger.info("Starting Processed Spat Deduplicator");
+ // ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new
+ // ProcessedSpatDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("ProcessedSpatDeduplicator")
+ // );
+ // processedSpatDeduplicatorTopology.start();
+ // }
+
+ if (props.isEnableOdeBsmDeduplication()) {
logger.info("Starting BSM Deduplicator");
BsmDeduplicatorTopology bsmDeduplicatorTopology = new BsmDeduplicatorTopology(props);
bsmDeduplicatorTopology.start();
}
- if(props.isEnableProcessedBsmDeduplication()){
- logger.info("Starting Processed BSM Deduplicator");
- ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new ProcessedBsmDeduplicatorTopology(
- props,
- props.createStreamProperties("ProcessedBsmDeduplicator")
- );
- processedBsmDeduplicatorTopology.start();
- }
+ // if(props.isEnableProcessedBsmDeduplication()){
+ // logger.info("Starting Processed BSM Deduplicator");
+ // ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new
+ // ProcessedBsmDeduplicatorTopology(
+ // props,
+ // props.createStreamProperties("ProcessedBsmDeduplicator")
+ // );
+ // processedBsmDeduplicatorTopology.start();
+ // }
} catch (Exception e) {
logger.error("Encountered issue with creating topologies", e);
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/DeduplicationProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/DeduplicationProcessor.java
index 78434a9..1452459 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/DeduplicationProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/DeduplicationProcessor.java
@@ -13,7 +13,7 @@
import org.apache.kafka.streams.state.KeyValueIterator;
import org.apache.kafka.streams.KeyValue;
-public abstract class DeduplicationProcessor implements Processor{
+public abstract class DeduplicationProcessor implements Processor {
private ProcessorContext context;
private KeyValueStore store;
@@ -32,36 +32,36 @@ public void init(ProcessorContext context) {
public void process(Record record) {
// Don't do anything if key is bad
- if(record.key().equals("")){
+ if (record.key().equals("")) {
return;
}
T lastRecord = store.get(record.key());
- if(lastRecord == null){
+ if (lastRecord == null) {
store.put(record.key(), record.value());
context.forward(record);
return;
}
- try{
- if(!isDuplicate(lastRecord, record.value())){
+ try {
+ if (!isDuplicate(lastRecord, record.value())) {
store.put(record.key(), record.value());
context.forward(record);
return;
}
- } catch(Exception e){
+ } catch (Exception e) {
logger.warn("Caught General Exception while Checking Duplicates" + e);
}
-
+
}
private void cleanupOldKeys(final long timestamp) {
try (KeyValueIterator iterator = store.all()) {
while (iterator.hasNext()) {
-
- KeyValue record = iterator.next();
+
+ KeyValue record = iterator.next();
// Delete any record more than 2 hours old.
- if(Instant.ofEpochMilli(timestamp).minusSeconds(2 * 60 * 60).isAfter(getMessageTime(record.value))){
+ if (Instant.ofEpochMilli(timestamp).minusSeconds(2 * 60 * 60).isAfter(getMessageTime(record.value))) {
store.delete(record.key);
}
}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeBsmJsonProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeBsmJsonProcessor.java
index f80a06f..55b5245 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeBsmJsonProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeBsmJsonProcessor.java
@@ -1,6 +1,5 @@
package us.dot.its.jpo.deduplicator.deduplicator.processors;
-
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
@@ -9,84 +8,131 @@
import org.slf4j.LoggerFactory;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.ode.model.OdeBsmData;
-import us.dot.its.jpo.ode.model.OdeBsmMetadata;
-import us.dot.its.jpo.ode.plugin.j2735.J2735Bsm;
-import us.dot.its.jpo.ode.plugin.j2735.J2735BsmCoreData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
+import us.dot.its.jpo.asn.j2735.r2024.BasicSafetyMessage.BasicSafetyMessageMessageFrame;
+import us.dot.its.jpo.asn.j2735.r2024.Common.BSMcoreData;
+import us.dot.its.jpo.asn.j2735.r2024.Common.Speed;
import us.dot.its.jpo.deduplicator.utils.GeoUtils;
-public class OdeBsmJsonProcessor extends DeduplicationProcessor{
+public class OdeBsmJsonProcessor extends DeduplicationProcessor {
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
DeduplicatorProperties props;
private static final Logger logger = LoggerFactory.getLogger(OdeBsmJsonProcessor.class);
- public OdeBsmJsonProcessor(String storeName, DeduplicatorProperties props){
+ public OdeBsmJsonProcessor(String storeName, DeduplicatorProperties props) {
this.storeName = storeName;
this.props = props;
}
-
@Override
- public Instant getMessageTime(OdeBsmData message) {
- String time = ((OdeBsmMetadata)message.getMetadata()).getOdeReceivedAt();
+ public Instant getMessageTime(OdeMessageFrameData message) {
try {
+ if (message == null || message.getMetadata() == null) {
+ logger.warn("BSM message or metadata is null, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
+ String time = ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt();
+ if (time == null || time.isEmpty()) {
+ logger.warn("BSM message has null or empty odeReceivedAt time, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
return Instant.from(formatter.parse(time));
} catch (Exception e) {
- logger.warn("Failed to Parse Time: " + time);
+ logger.warn("Failed to Parse Time: " + (message != null && message.getMetadata() != null
+ ? ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt()
+ : "null"), e);
return Instant.ofEpochMilli(0);
}
}
@Override
- public boolean isDuplicate(OdeBsmData lastMessage, OdeBsmData newMessage) {
- try{
+ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData newMessage) {
+ try {
Instant newValueTime = getMessageTime(newMessage);
Instant oldValueTime = getMessageTime(lastMessage);
- // If the messages are more than a certain time apart, forward the new message on
- if(newValueTime.minus(Duration.ofMillis(props.getOdeBsmMaximumTimeDelta())).isAfter(oldValueTime)){
- return false;
+ // If the messages are more than a certain time apart, forward the new message
+ // on
+ if (newValueTime.minus(Duration.ofMillis(props.getOdeBsmMaximumTimeDelta())).isAfter(oldValueTime)) {
+ return false;
}
- J2735BsmCoreData oldCore = ((J2735Bsm)lastMessage.getPayload().getData()).getCoreData();
- J2735BsmCoreData newCore = ((J2735Bsm)newMessage.getPayload().getData()).getCoreData();
+ // Add null checks for payload and data
+ if (lastMessage == null || lastMessage.getPayload() == null || lastMessage.getPayload().getData() == null ||
+ newMessage == null || newMessage.getPayload() == null
+ || newMessage.getPayload().getData() == null) {
+ logger.warn("One or both BSM messages have null payload or data, treating as non-duplicate");
+ return false;
+ }
- // If the speed field of the message is different from the previous speed field
- if(newCore.getSpeed() == null && oldCore.getSpeed() != null || newCore.getSpeed() != null && oldCore.getSpeed() == null){
+ BSMcoreData oldCore = ((BasicSafetyMessageMessageFrame) lastMessage.getPayload().getData()).getValue()
+ .getCoreData();
+ BSMcoreData newCore = ((BasicSafetyMessageMessageFrame) newMessage.getPayload().getData()).getValue()
+ .getCoreData();
+
+ // Check if speed availability status has changed (null, unavailable, or
+ // available)
+ boolean oldSpeedAvailable = isSpeedAvailable(oldCore.getSpeed());
+ boolean newSpeedAvailable = isSpeedAvailable(newCore.getSpeed());
+
+ // If the speed availability status has changed, forward the message
+ if (oldSpeedAvailable != newSpeedAvailable) {
return false;
}
- // If the Vehicle is moving, forward the message on
- if(newCore.getSpeed() != null && newCore.getSpeed().doubleValue() > props.getOdeBsmAlwaysIncludeAtSpeed()){
- return false;
+ // If the Vehicle is moving (speed is available and above threshold), forward
+ // the message on
+ if (newSpeedAvailable && newCore.getSpeed().getValue() > props.getOdeBsmAlwaysIncludeAtSpeed()) {
+ return false;
}
// If the new core and the old core have different null conditions
- if((oldCore.getPosition() == null && newCore.getPosition() != null) || // Used to be null, but now is non-null
- (oldCore.getPosition() != null && newCore.getPosition() == null)){ // Used to be populated, but is now null
+ if (((oldCore.getLat() == null || oldCore.getLong_() == null)
+ // Used to be null, but now is non-null
+ && (newCore.getLat() != null || newCore.getLong_() != null)) ||
+ ((oldCore.getLat() != null || oldCore.getLong_() != null)
+ && (newCore.getLat() == null || newCore.getLong_() == null))) {
return false;
- }else if(oldCore.getPosition() == null && newCore.getPosition() == null){ // both are null, message is a duplicate
+ // both are null, message is a duplicate
+ } else if (oldCore.getLat() == null && newCore.getLat() == null && oldCore.getLong_() == null
+ && newCore.getLong_() == null) {
return true;
- }else{
-
- double distance = GeoUtils.calculateGeodeticDistance(
- newCore.getPosition().getLatitude().doubleValue(),
- newCore.getPosition().getLongitude().doubleValue(),
- oldCore.getPosition().getLatitude().doubleValue(),
- oldCore.getPosition().getLongitude().doubleValue()
- );
-
- // If the position delta between the messages is suitable large, forward the message on
- if(distance > props.getOdeBsmMaximumPositionDelta()){
+ } else {
+ double distance = GeoUtils.calculateGeodeticDistanceJ2735(
+ newCore.getLat().getValue(),
+ newCore.getLong_().getValue(),
+ oldCore.getLat().getValue(),
+ oldCore.getLong_().getValue());
+
+ // If the position delta between the messages is suitable large, forward the
+ // message on
+ if (distance > props.getOdeBsmMaximumPositionDelta()) {
return false;
}
}
- } catch(Exception e){
+ } catch (Exception e) {
logger.warn("Caught General Exception" + e);
}
return true;
}
+
+ /**
+ * Determines if the speed value is available (not null and not unavailable)
+ *
+ * @param speed The speed object to check
+ * @return true if speed is available, false otherwise
+ */
+ private boolean isSpeedAvailable(Speed speed) {
+ if (speed == null) {
+ return false;
+ }
+ // Speed value 8191 indicates unavailable in J2735 standard
+ return speed.getValue() != 8191;
+ }
}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java
index 4c1e4dc..a95bae6 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java
@@ -1,79 +1,78 @@
-package us.dot.its.jpo.deduplicator.deduplicator.processors;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import java.util.Objects;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.ode.model.OdeMapData;
-import us.dot.its.jpo.ode.model.OdeMapMetadata;
-import us.dot.its.jpo.ode.model.OdeMapPayload;
-
-public class OdeMapJsonProcessor extends DeduplicationProcessor{
-
- DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-
- DeduplicatorProperties props;
-
- private static final Logger logger = LoggerFactory.getLogger(OdeMapJsonProcessor.class);
-
- public OdeMapJsonProcessor(DeduplicatorProperties props){
- this.props = props;
- this.storeName = props.getKafkaStateStoreOdeMapJsonName();
- }
-
-
- @Override
- public Instant getMessageTime(OdeMapData message) {
- try {
- String time = ((OdeMapMetadata)message.getMetadata()).getOdeReceivedAt();
- return Instant.from(formatter.parse(time));
- } catch (Exception e) {
- return Instant.ofEpochMilli(0);
- }
- }
-
- @Override
- public boolean isDuplicate(OdeMapData lastMessage, OdeMapData newMessage) {
- try{
- Instant newValueTime = getMessageTime(newMessage);
- Instant oldValueTime = getMessageTime(lastMessage);
-
- if(newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)){
- return false;
-
- }else{
- OdeMapPayload oldPayload = (OdeMapPayload)lastMessage.getPayload();
- OdeMapPayload newPayload = (OdeMapPayload)newMessage.getPayload();
-
- Integer oldTimestamp = oldPayload.getMap().getTimeStamp();
- Integer newTimestamp = newPayload.getMap().getTimeStamp();
-
-
- newPayload.getMap().setTimeStamp(oldTimestamp);
-
- int oldHash = hashMapMessage(lastMessage);
- int newhash = hashMapMessage(newMessage);
-
- if(oldHash != newhash){
- newPayload.getMap().setTimeStamp(newTimestamp);
- return false;
- }
- }
- } catch(Exception e){
- logger.warn("Caught General Exception" + e);
- }
-
- return true;
- }
-
- public int hashMapMessage(OdeMapData map){
- OdeMapPayload payload = (OdeMapPayload)map.getPayload();
- return Objects.hash(payload.toJson());
-
- }
-}
+// package us.dot.its.jpo.deduplicator.deduplicator.processors;
+
+// import java.time.Duration;
+// import java.time.Instant;
+// import java.time.format.DateTimeFormatter;
+// import java.util.Objects;
+
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import us.dot.its.jpo.ode.model.OdeMapData;
+// import us.dot.its.jpo.ode.model.OdeMapMetadata;
+// import us.dot.its.jpo.ode.model.OdeMapPayload;
+
+// public class OdeMapJsonProcessor extends DeduplicationProcessor{
+
+// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+
+// DeduplicatorProperties props;
+
+// private static final Logger logger =
+// LoggerFactory.getLogger(OdeMapJsonProcessor.class);
+
+// public OdeMapJsonProcessor(DeduplicatorProperties props){
+// this.props = props;
+// this.storeName = props.getKafkaStateStoreOdeMapJsonName();
+// }
+
+// @Override
+// public Instant getMessageTime(OdeMapData message) {
+// try {
+// String time = ((OdeMapMetadata)message.getMetadata()).getOdeReceivedAt();
+// return Instant.from(formatter.parse(time));
+// } catch (Exception e) {
+// return Instant.ofEpochMilli(0);
+// }
+// }
+
+// @Override
+// public boolean isDuplicate(OdeMapData lastMessage, OdeMapData newMessage) {
+// try{
+// Instant newValueTime = getMessageTime(newMessage);
+// Instant oldValueTime = getMessageTime(lastMessage);
+
+// if(newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)){
+// return false;
+
+// }else{
+// OdeMapPayload oldPayload = (OdeMapPayload)lastMessage.getPayload();
+// OdeMapPayload newPayload = (OdeMapPayload)newMessage.getPayload();
+
+// Integer oldTimestamp = oldPayload.getMap().getTimeStamp();
+// Integer newTimestamp = newPayload.getMap().getTimeStamp();
+
+// newPayload.getMap().setTimeStamp(oldTimestamp);
+
+// int oldHash = hashMapMessage(lastMessage);
+// int newhash = hashMapMessage(newMessage);
+
+// if(oldHash != newhash){
+// newPayload.getMap().setTimeStamp(newTimestamp);
+// return false;
+// }
+// }
+// } catch(Exception e){
+// logger.warn("Caught General Exception" + e);
+// }
+
+// return true;
+// }
+
+// public int hashMapMessage(OdeMapData map){
+// OdeMapPayload payload = (OdeMapPayload)map.getPayload();
+// return Objects.hash(payload.toJson());
+
+// }
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeBsmJsonProcessorSupplier.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeBsmJsonProcessorSupplier.java
index 6b08b9f..d41f70c 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeBsmJsonProcessorSupplier.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeBsmJsonProcessorSupplier.java
@@ -6,21 +6,22 @@
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.processors.OdeBsmJsonProcessor;
-import us.dot.its.jpo.ode.model.OdeBsmData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+
+public class OdeBsmJsonProcessorSupplier
+ implements ProcessorSupplier {
-public class OdeBsmJsonProcessorSupplier implements ProcessorSupplier {
-
String storeName;
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
DeduplicatorProperties props;
- public OdeBsmJsonProcessorSupplier(String storeName, DeduplicatorProperties props){
+ public OdeBsmJsonProcessorSupplier(String storeName, DeduplicatorProperties props) {
this.storeName = storeName;
this.props = props;
}
@Override
- public Processor get() {
+ public Processor get() {
return new OdeBsmJsonProcessor(storeName, props);
}
}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java
index 29c9778..e1f7875 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java
@@ -1,5 +1,6 @@
package us.dot.its.jpo.deduplicator.deduplicator.serialization;
+import org.apache.kafka.common.serialization.Deserializer;
import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serdes;
@@ -7,18 +8,64 @@
import us.dot.its.jpo.geojsonconverter.serialization.deserializers.JsonDeserializer;
import us.dot.its.jpo.geojsonconverter.serialization.serializers.JsonSerializer;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
import us.dot.its.jpo.ode.model.OdeTimData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
public class JsonSerdes {
- public static Serde OdeTim() {
+
+ private static final Logger logger = LoggerFactory.getLogger(JsonSerdes.class);
+
+ /**
+ * A wrapper deserializer that handles deserialization errors gracefully
+ */
+ private static class SafeJsonDeserializer implements Deserializer {
+ private final JsonDeserializer delegate;
+
+ public SafeJsonDeserializer(Class clazz) {
+ this.delegate = new JsonDeserializer<>(clazz);
+ }
+
+ @Override
+ public T deserialize(String topic, byte[] data) {
+ try {
+ return delegate.deserialize(topic, data);
+ } catch (Exception e) {
+ logger.warn("Failed to deserialize data for topic {}: {}", topic, e.getMessage());
+ return null;
+ }
+ }
+ }
+
+ public static Serde OdeTim(DeduplicatorProperties props) {
return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(OdeTimData.class));
+ new JsonSerializer(),
+ new JsonDeserializer<>(OdeTimData.class));
}
- public static Serde JSON(){
+ public static Serde OdeMessageFrame(DeduplicatorProperties props) {
return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(JsonNode.class));
+ new JsonSerializer(),
+ new SafeJsonDeserializer<>(OdeMessageFrameData.class));
+ }
+
+ public static Serde JSON(DeduplicatorProperties props) {
+ return Serdes.serdeFrom(
+ new JsonSerializer(),
+ new JsonDeserializer<>(JsonNode.class));
+ }
+
+ public static Serde OdeTim() {
+ return OdeTim(null);
+ }
+
+ public static Serde OdeMessageFrame() {
+ return OdeMessageFrame(null);
+ }
+
+ public static Serde JSON() {
+ return JSON(null);
}
}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/BsmDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/BsmDeduplicatorTopology.java
index 30d05fc..b6639dd 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/BsmDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/BsmDeduplicatorTopology.java
@@ -8,12 +8,9 @@
import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.ode.model.OdeBsmData;
-import us.dot.its.jpo.ode.model.OdeBsmMetadata;
-import us.dot.its.jpo.ode.model.OdeMapData;
-import us.dot.its.jpo.ode.model.OdeMapPayload;
-import us.dot.its.jpo.ode.plugin.j2735.J2735Bsm;
-import us.dot.its.jpo.ode.plugin.j2735.J2735BsmCoreData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
+import us.dot.its.jpo.asn.j2735.r2024.BasicSafetyMessage.BasicSafetyMessageMessageFrame;
import org.apache.kafka.streams.kstream.*;
import org.apache.kafka.streams.state.Stores;
import org.slf4j.Logger;
@@ -23,11 +20,10 @@
import java.time.Instant;
import java.time.format.DateTimeFormatter;
-import java.util.Objects;
import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeBsmJsonProcessorSupplier;
import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
public class BsmDeduplicatorTopology {
@@ -58,39 +54,65 @@ public void start() {
streams.start();
}
- public Instant getInstantFromBsm(OdeBsmData bsm) {
- String time = ((OdeBsmMetadata) bsm.getMetadata()).getOdeReceivedAt();
-
- return Instant.from(formatter.parse(time));
- }
-
- public int hashMapMessage(OdeMapData map) {
- OdeMapPayload payload = (OdeMapPayload) map.getPayload();
- return Objects.hash(payload.toJson());
-
+ public Instant getInstantFromBsm(OdeMessageFrameData bsm) {
+ try {
+ if (bsm == null || bsm.getMetadata() == null) {
+ logger.warn("BSM message or metadata is null, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
+ String time = ((OdeMessageFrameMetadata) bsm.getMetadata()).getOdeReceivedAt();
+ if (time == null || time.isEmpty()) {
+ logger.warn("BSM message has null or empty odeReceivedAt time, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
+ return Instant.from(formatter.parse(time));
+ } catch (Exception e) {
+ logger.warn("Failed to parse time from BSM: " + (bsm != null && bsm.getMetadata() != null
+ ? ((OdeMessageFrameMetadata) bsm.getMetadata()).getOdeReceivedAt()
+ : "null"), e);
+ return Instant.ofEpochMilli(0);
+ }
}
public Topology buildTopology() {
StreamsBuilder builder = new StreamsBuilder();
- KStream inputStream = builder.stream(this.props.getKafkaTopicOdeBsmJson(),
- Consumed.with(Serdes.Void(), JsonSerdes.OdeBsm()));
+ KStream inputStream = builder.stream(this.props.getKafkaTopicOdeBsmJson(),
+ Consumed.with(Serdes.Void(), JsonSerdes.OdeMessageFrame()));
builder.addStateStore(
Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeBsmJsonName()),
- Serdes.String(), JsonSerdes.OdeBsm()));
-
- KStream bsmRekeyedStream = inputStream.selectKey((key, value) -> {
- J2735BsmCoreData core = ((J2735Bsm) value.getPayload().getData()).getCoreData();
- return core.getId();
- }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeBsm()));
-
- KStream deduplicatedStream = bsmRekeyedStream.process(
+ Serdes.String(), JsonSerdes.OdeMessageFrame()));
+
+ KStream bsmRekeyedStream = inputStream.selectKey((key, value) -> {
+ try {
+ if (value == null || value.getPayload() == null || value.getPayload().getData() == null) {
+ logger.warn("Received BSM message with null payload or data, using default key");
+ return "unknown";
+ }
+
+ BasicSafetyMessageMessageFrame mf = (BasicSafetyMessageMessageFrame) value.getPayload().getData();
+ if (mf == null || mf.getValue() == null || mf.getValue().getCoreData() == null ||
+ mf.getValue().getCoreData().getId() == null) {
+ logger.warn("Received BSM message with null message frame data, using default key");
+ return "unknown";
+ }
+
+ return mf.getValue().getCoreData().getId().getValue();
+ } catch (Exception e) {
+ logger.error("Error extracting key from BSM message: " + e.getMessage(), e);
+ return "unknown";
+ }
+ }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
+
+ KStream deduplicatedStream = bsmRekeyedStream.process(
new OdeBsmJsonProcessorSupplier(props.getKafkaStateStoreOdeBsmJsonName(), props),
props.getKafkaStateStoreOdeBsmJsonName());
deduplicatedStream.to(this.props.getKafkaTopicDeduplicatedOdeBsmJson(),
- Produced.with(Serdes.String(), JsonSerdes.OdeBsm()));
+ Produced.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
return builder.build();
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
index c8ac7f6..957ad33 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
@@ -1,121 +1,136 @@
-package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KafkaStreams;
-import org.apache.kafka.streams.StreamsBuilder;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.KafkaStreams.StateListener;
-import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeMapJsonProcessorSupplier;
-import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.geojsonconverter.partitioner.RsuIntersectionKey;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import us.dot.its.jpo.ode.model.OdeMapData;
-import us.dot.its.jpo.ode.model.OdeMapMetadata;
-import us.dot.its.jpo.ode.model.OdeMapPayload;
-import us.dot.its.jpo.ode.plugin.j2735.J2735IntersectionReferenceID;
-
-import org.apache.kafka.streams.kstream.*;
-import org.apache.kafka.streams.state.Stores;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import java.util.Objects;
-import java.util.Properties;
-
-public class MapDeduplicatorTopology {
-
- private static final Logger logger = LoggerFactory.getLogger(MapDeduplicatorTopology.class);
-
- Topology topology;
- KafkaStreams streams;
- String inputTopic;
- String outputTopic;
- Properties streamsProperties;
- ObjectMapper objectMapper;
- DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
- DeduplicatorProperties props;
-
-
- public MapDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties){
- this.props = props;
- this.streamsProperties = streamsProperties;
- this.objectMapper = DateJsonMapper.getInstance();
- }
-
-
-
- public void start() {
- if (streams != null && streams.state().isRunningOrRebalancing()) {
- throw new IllegalStateException("Start called while streams is already running.");
- }
- Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
- if (exceptionHandler != null) streams.setUncaughtExceptionHandler(exceptionHandler);
- if (stateListener != null) streams.setStateListener(stateListener);
- logger.info("Starting Map Deduplicator Topology");
- streams.start();
- }
-
- public Instant getInstantFromMap(OdeMapData map){
- String time = ((OdeMapMetadata)map.getMetadata()).getOdeReceivedAt();
-
- return Instant.from(formatter.parse(time));
- }
-
- public int hashMapMessage(OdeMapData map){
- OdeMapPayload payload = (OdeMapPayload)map.getPayload();
- return Objects.hash(payload.toJson());
-
- }
-
- public Topology buildTopology() {
- StreamsBuilder builder = new StreamsBuilder();
-
- KStream inputStream = builder.stream(props.getKafkaTopicOdeMapJson(), Consumed.with(Serdes.Void(), JsonSerdes.OdeMap()));
-
- builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeMapJsonName()),
- Serdes.String(), JsonSerdes.OdeMap()));
-
- KStream mapRekeyedStream = inputStream.selectKey((key, value)->{
- J2735IntersectionReferenceID intersectionId = ((OdeMapPayload)value.getPayload()).getMap().getIntersections().getIntersections().get(0).getId();
- RsuIntersectionKey newKey = new RsuIntersectionKey();
- newKey.setRsuId(((OdeMapMetadata)value.getMetadata()).getOriginIp());
- newKey.setIntersectionReferenceID(intersectionId);
- return newKey.toString();
- }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMap()));
-
- KStream deduplicatedStream = mapRekeyedStream.process(new OdeMapJsonProcessorSupplier(props), props.getKafkaStateStoreOdeMapJsonName());
-
- deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeMapJson(), Produced.with(Serdes.String(), JsonSerdes.OdeMap()));
-
- return builder.build();
-
- }
-
- public void stop() {
- logger.info("Stopping Map Deduplicator Socket Broadcast Topology.");
- if (streams != null) {
- streams.close();
- streams.cleanUp();
- streams = null;
- }
- logger.info("Stopped Map Deduplicator Socket Broadcast Topology.");
- }
-
- StateListener stateListener;
- public void registerStateListener(StateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- StreamsUncaughtExceptionHandler exceptionHandler;
- public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-}
+// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KafkaStreams;
+// import org.apache.kafka.streams.StreamsBuilder;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.KafkaStreams.StateListener;
+// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeMapJsonProcessorSupplier;
+// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+// import us.dot.its.jpo.geojsonconverter.partitioner.RsuIntersectionKey;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import us.dot.its.jpo.ode.model.OdeMapData;
+// import us.dot.its.jpo.ode.model.OdeMapMetadata;
+// import us.dot.its.jpo.ode.model.OdeMapPayload;
+// import us.dot.its.jpo.ode.plugin.j2735.J2735IntersectionReferenceID;
+
+// import org.apache.kafka.streams.kstream.*;
+// import org.apache.kafka.streams.state.Stores;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+
+// import com.fasterxml.jackson.databind.ObjectMapper;
+
+// import java.time.Instant;
+// import java.time.format.DateTimeFormatter;
+// import java.util.Objects;
+// import java.util.Properties;
+
+// public class MapDeduplicatorTopology {
+
+// private static final Logger logger =
+// LoggerFactory.getLogger(MapDeduplicatorTopology.class);
+
+// Topology topology;
+// KafkaStreams streams;
+// String inputTopic;
+// String outputTopic;
+// Properties streamsProperties;
+// ObjectMapper objectMapper;
+// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+// DeduplicatorProperties props;
+
+// public MapDeduplicatorTopology(DeduplicatorProperties props, Properties
+// streamsProperties) {
+// this.props = props;
+// this.streamsProperties = streamsProperties;
+// this.objectMapper = DateJsonMapper.getInstance();
+// }
+
+// public void start() {
+// if (streams != null && streams.state().isRunningOrRebalancing()) {
+// throw new IllegalStateException("Start called while streams is already
+// running.");
+// }
+// Topology topology = buildTopology();
+// streams = new KafkaStreams(topology, streamsProperties);
+// if (exceptionHandler != null)
+// streams.setUncaughtExceptionHandler(exceptionHandler);
+// if (stateListener != null)
+// streams.setStateListener(stateListener);
+// logger.info("Starting Map Deduplicator Topology");
+// streams.start();
+// }
+
+// public Instant getInstantFromMap(OdeMapData map) {
+// String time = ((OdeMapMetadata) map.getMetadata()).getOdeReceivedAt();
+
+// return Instant.from(formatter.parse(time));
+// }
+
+// public int hashMapMessage(OdeMapData map) {
+// OdeMapPayload payload = (OdeMapPayload) map.getPayload();
+// return Objects.hash(payload.toJson());
+
+// }
+
+// public Topology buildTopology() {
+// StreamsBuilder builder = new StreamsBuilder();
+
+// KStream inputStream =
+// builder.stream(props.getKafkaTopicOdeMapJson(),
+// Consumed.with(Serdes.Void(), JsonSerdes.OdeMap()));
+
+// builder.addStateStore(
+// Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeMapJsonName()),
+// Serdes.String(), JsonSerdes.OdeMap()));
+
+// KStream mapRekeyedStream = inputStream.selectKey((key,
+// value) -> {
+// J2735IntersectionReferenceID intersectionId = ((OdeMapPayload)
+// value.getPayload()).getMap()
+// .getIntersections().getIntersections().get(0).getId();
+// RsuIntersectionKey newKey = new RsuIntersectionKey();
+// newKey.setRsuId(((OdeMapMetadata) value.getMetadata()).getOriginIp());
+// newKey.setIntersectionReferenceID(intersectionId);
+// return newKey.toString();
+// }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMap()));
+
+// KStream deduplicatedStream = mapRekeyedStream
+// .process(new OdeMapJsonProcessorSupplier(props),
+// props.getKafkaStateStoreOdeMapJsonName());
+
+// deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeMapJson(),
+// Produced.with(Serdes.String(), JsonSerdes.OdeMap()));
+
+// return builder.build();
+
+// }
+
+// public void stop() {
+// logger.info("Stopping Map Deduplicator Socket Broadcast Topology.");
+// if (streams != null) {
+// streams.close();
+// streams.cleanUp();
+// streams = null;
+// }
+// logger.info("Stopped Map Deduplicator Socket Broadcast Topology.");
+// }
+
+// StateListener stateListener;
+
+// public void registerStateListener(StateListener stateListener) {
+// this.stateListener = stateListener;
+// }
+
+// StreamsUncaughtExceptionHandler exceptionHandler;
+
+// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
+// exceptionHandler) {
+// this.exceptionHandler = exceptionHandler;
+// }
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java
index f401b17..7418f7e 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java
@@ -1,97 +1,111 @@
-package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KafkaStreams;
-import org.apache.kafka.streams.StreamsBuilder;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.KafkaStreams.StateListener;
-import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import org.apache.kafka.streams.kstream.*;
-import org.apache.kafka.streams.state.Stores;
-import org.geotools.referencing.GeodeticCalculator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.time.format.DateTimeFormatter;
-import java.util.Properties;
-
-import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedBsmJsonProcessorSupplier;
-import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
-
-public class ProcessedBsmDeduplicatorTopology {
-
- private static final Logger logger = LoggerFactory.getLogger(ProcessedBsmDeduplicatorTopology.class);
-
- Topology topology;
- KafkaStreams streams;
- DeduplicatorProperties props;
- ObjectMapper objectMapper;
- DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
- GeodeticCalculator calculator;
- Properties streamsProperties;
-
-
- public ProcessedBsmDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties){
- this.props = props;
- this.streamsProperties = streamsProperties;
- this.objectMapper = DateJsonMapper.getInstance();
- }
-
-
-
- public void start() {
- if (streams != null && streams.state().isRunningOrRebalancing()) {
- throw new IllegalStateException("Start called while streams is already running.");
- }
- Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
- if (exceptionHandler != null) streams.setUncaughtExceptionHandler(exceptionHandler);
- if (stateListener != null) streams.setStateListener(stateListener);
- logger.info("Starting Processed Bsm Deduplicator Topology");
- streams.start();
- }
-
- public Topology buildTopology() {
- StreamsBuilder builder = new StreamsBuilder();
-
- KStream> inputStream = builder.stream(this.props.getKafkaTopicProcessedBsm(), Consumed.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
-
- builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedBsmName()),
- Serdes.String(), JsonSerdes.ProcessedBsm()));
-
- KStream> deduplicatedStream = inputStream.process(new ProcessedBsmJsonProcessorSupplier(props.getKafkaStateStoreProcessedBsmName(), props), props.getKafkaStateStoreProcessedBsmName());
-
-
- deduplicatedStream.to(this.props.getKafkaTopicDeduplicatedProcessedBsm(), Produced.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
-
- return builder.build();
-
- }
-
- public void stop() {
- logger.info("Stopping Processed Bsm deduplicator Topology.");
- if (streams != null) {
- streams.close();
- streams.cleanUp();
- streams = null;
- }
- logger.info("Stopped Processed Bsm deduplicator Topology.");
- }
-
- StateListener stateListener;
- public void registerStateListener(StateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- StreamsUncaughtExceptionHandler exceptionHandler;
- public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-}
+// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KafkaStreams;
+// import org.apache.kafka.streams.StreamsBuilder;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.KafkaStreams.StateListener;
+// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import org.apache.kafka.streams.kstream.*;
+// import org.apache.kafka.streams.state.Stores;
+// import org.geotools.referencing.GeodeticCalculator;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+
+// import com.fasterxml.jackson.databind.ObjectMapper;
+
+// import java.time.format.DateTimeFormatter;
+// import java.util.Properties;
+
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedBsmJsonProcessorSupplier;
+// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
+
+// public class ProcessedBsmDeduplicatorTopology {
+
+// private static final Logger logger =
+// LoggerFactory.getLogger(ProcessedBsmDeduplicatorTopology.class);
+
+// Topology topology;
+// KafkaStreams streams;
+// DeduplicatorProperties props;
+// ObjectMapper objectMapper;
+// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+// GeodeticCalculator calculator;
+// Properties streamsProperties;
+
+// public ProcessedBsmDeduplicatorTopology(DeduplicatorProperties props,
+// Properties streamsProperties) {
+// this.props = props;
+// this.streamsProperties = streamsProperties;
+// this.objectMapper = DateJsonMapper.getInstance();
+// }
+
+// public void start() {
+// if (streams != null && streams.state().isRunningOrRebalancing()) {
+// throw new IllegalStateException("Start called while streams is already
+// running.");
+// }
+// Topology topology = buildTopology();
+// streams = new KafkaStreams(topology, streamsProperties);
+// if (exceptionHandler != null)
+// streams.setUncaughtExceptionHandler(exceptionHandler);
+// if (stateListener != null)
+// streams.setStateListener(stateListener);
+// logger.info("Starting Processed Bsm Deduplicator Topology");
+// streams.start();
+// }
+
+// public Topology buildTopology() {
+// StreamsBuilder builder = new StreamsBuilder();
+
+// KStream> inputStream =
+// builder.stream(this.props.getKafkaTopicProcessedBsm(),
+// Consumed.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
+
+// builder.addStateStore(
+// Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedBsmName()),
+// Serdes.String(), JsonSerdes.ProcessedBsm()));
+
+// KStream> deduplicatedStream =
+// inputStream.process(
+// new
+// ProcessedBsmJsonProcessorSupplier(props.getKafkaStateStoreProcessedBsmName(),
+// props),
+// props.getKafkaStateStoreProcessedBsmName());
+
+// deduplicatedStream.to(this.props.getKafkaTopicDeduplicatedProcessedBsm(),
+// Produced.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
+
+// return builder.build();
+
+// }
+
+// public void stop() {
+// logger.info("Stopping Processed Bsm deduplicator Topology.");
+// if (streams != null) {
+// streams.close();
+// streams.cleanUp();
+// streams = null;
+// }
+// logger.info("Stopped Processed Bsm deduplicator Topology.");
+// }
+
+// StateListener stateListener;
+
+// public void registerStateListener(StateListener stateListener) {
+// this.stateListener = stateListener;
+// }
+
+// StreamsUncaughtExceptionHandler exceptionHandler;
+
+// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
+// exceptionHandler) {
+// this.exceptionHandler = exceptionHandler;
+// }
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java
index 5f9da3d..037f1bd 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java
@@ -1,92 +1,100 @@
-package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KafkaStreams;
-import org.apache.kafka.streams.StreamsBuilder;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.KafkaStreams.StateListener;
-import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapProcessorSupplier;
-import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import org.apache.kafka.streams.kstream.*;
-import org.apache.kafka.streams.state.Stores;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-
-import java.util.Properties;
-
-public class ProcessedMapDeduplicatorTopology {
-
- private static final Logger logger = LoggerFactory.getLogger(MapDeduplicatorTopology.class);
-
- Topology topology;
- KafkaStreams streams;
- Properties streamsProperties;
- ObjectMapper objectMapper;
- DeduplicatorProperties props;
-
- public ProcessedMapDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties){
- this.props = props;
- this.streamsProperties = streamsProperties;
- this.objectMapper = DateJsonMapper.getInstance();
- }
-
-
- public void start() {
- if (streams != null && streams.state().isRunningOrRebalancing()) {
- throw new IllegalStateException("Start called while streams is already running.");
- }
- Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
- if (exceptionHandler != null) streams.setUncaughtExceptionHandler(exceptionHandler);
- if (stateListener != null) streams.setStateListener(stateListener);
- logger.info("Starting Processed Map Deduplicator Topology");
- streams.start();
- }
-
- public Topology buildTopology() {
- StreamsBuilder builder = new StreamsBuilder();
-
- KStream> inputStream = builder.stream(props.getKafkaTopicProcessedMap(), Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
-
- builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapName()),
- Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
-
- KStream> deduplicatedStream = inputStream.process(new ProcessedMapProcessorSupplier(props), props.getKafkaStateStoreProcessedMapName());
-
- deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMap(), Produced.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
-
- return builder.build();
-
- }
-
- public void stop() {
- logger.info("Stopping Processed Map deduplicator Socket Broadcast Topology.");
- if (streams != null) {
- streams.close();
- streams.cleanUp();
- streams = null;
- }
- logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
- }
-
- StateListener stateListener;
- public void registerStateListener(StateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- StreamsUncaughtExceptionHandler exceptionHandler;
- public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-
-
-
-}
+// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KafkaStreams;
+// import org.apache.kafka.streams.StreamsBuilder;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.KafkaStreams.StateListener;
+// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapProcessorSupplier;
+// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import org.apache.kafka.streams.kstream.*;
+// import org.apache.kafka.streams.state.Stores;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+
+// import java.util.Properties;
+
+// public class ProcessedMapDeduplicatorTopology {
+
+// private static final Logger logger =
+// LoggerFactory.getLogger(MapDeduplicatorTopology.class);
+
+// Topology topology;
+// KafkaStreams streams;
+// Properties streamsProperties;
+// ObjectMapper objectMapper;
+// DeduplicatorProperties props;
+
+// public ProcessedMapDeduplicatorTopology(DeduplicatorProperties props,
+// Properties streamsProperties){
+// this.props = props;
+// this.streamsProperties = streamsProperties;
+// this.objectMapper = DateJsonMapper.getInstance();
+// }
+
+// public void start() {
+// if (streams != null && streams.state().isRunningOrRebalancing()) {
+// throw new IllegalStateException("Start called while streams is already
+// running.");
+// }
+// Topology topology = buildTopology();
+// streams = new KafkaStreams(topology, streamsProperties);
+// if (exceptionHandler != null)
+// streams.setUncaughtExceptionHandler(exceptionHandler);
+// if (stateListener != null) streams.setStateListener(stateListener);
+// logger.info("Starting Processed Map Deduplicator Topology");
+// streams.start();
+// }
+
+// public Topology buildTopology() {
+// StreamsBuilder builder = new StreamsBuilder();
+
+// KStream> inputStream =
+// builder.stream(props.getKafkaTopicProcessedMap(),
+// Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
+
+// builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapName()),
+// Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
+
+// KStream> deduplicatedStream =
+// inputStream.process(new ProcessedMapProcessorSupplier(props),
+// props.getKafkaStateStoreProcessedMapName());
+
+// deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMap(),
+// Produced.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
+
+// return builder.build();
+
+// }
+
+// public void stop() {
+// logger.info("Stopping Processed Map deduplicator Socket Broadcast
+// Topology.");
+// if (streams != null) {
+// streams.close();
+// streams.cleanUp();
+// streams = null;
+// }
+// logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
+// }
+
+// StateListener stateListener;
+// public void registerStateListener(StateListener stateListener) {
+// this.stateListener = stateListener;
+// }
+
+// StreamsUncaughtExceptionHandler exceptionHandler;
+// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
+// exceptionHandler) {
+// this.exceptionHandler = exceptionHandler;
+// }
+
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java
index 872e66f..4c4a633 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java
@@ -1,93 +1,102 @@
-package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KafkaStreams;
-import org.apache.kafka.streams.StreamsBuilder;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.KafkaStreams.StateListener;
-import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapWktProcessorSupplier;
-import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-
-import org.apache.kafka.streams.kstream.*;
-import org.apache.kafka.streams.state.Stores;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.util.Properties;
-
-public class ProcessedMapWktDeduplicatorTopology {
-
- private static final Logger logger = LoggerFactory.getLogger(MapDeduplicatorTopology.class);
-
- Topology topology;
- KafkaStreams streams;
- String inputTopic;
- String outputTopic;
- Properties streamsProperties;
- ObjectMapper objectMapper;
- DeduplicatorProperties props;
-
- public ProcessedMapWktDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties){
- this.props = props;
- this.streamsProperties = streamsProperties;
- this.objectMapper = DateJsonMapper.getInstance();
- }
-
-
- public void start() {
- if (streams != null && streams.state().isRunningOrRebalancing()) {
- throw new IllegalStateException("Start called while streams is already running.");
- }
- Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
- if (exceptionHandler != null) streams.setUncaughtExceptionHandler(exceptionHandler);
- if (stateListener != null) streams.setStateListener(stateListener);
- logger.info("Starting Processed Map WKT Deduplicator Topology");
- streams.start();
- }
-
- public Topology buildTopology() {
- StreamsBuilder builder = new StreamsBuilder();
-
- KStream> inputStream = builder.stream(props.getKafkaTopicProcessedMapWKT(), Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
-
- builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapWKTName()),
- Serdes.String(), JsonSerdes.ProcessedMapWKT()));
-
- KStream> deduplicatedStream = inputStream.process(new ProcessedMapWktProcessorSupplier(props), props.getKafkaStateStoreProcessedMapWKTName());
-
- deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMapWKT(), Produced.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
-
- return builder.build();
-
- }
-
- public void stop() {
- logger.info("Stopping Processed Map deduplicator Socket Broadcast Topology.");
- if (streams != null) {
- streams.close();
- streams.cleanUp();
- streams = null;
- }
- logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
- }
-
- StateListener stateListener;
- public void registerStateListener(StateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- StreamsUncaughtExceptionHandler exceptionHandler;
- public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-
-
-
-}
+// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KafkaStreams;
+// import org.apache.kafka.streams.StreamsBuilder;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.KafkaStreams.StateListener;
+// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapWktProcessorSupplier;
+// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+
+// import org.apache.kafka.streams.kstream.*;
+// import org.apache.kafka.streams.state.Stores;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+
+// import java.util.Properties;
+
+// public class ProcessedMapWktDeduplicatorTopology {
+
+// private static final Logger logger =
+// LoggerFactory.getLogger(MapDeduplicatorTopology.class);
+
+// Topology topology;
+// KafkaStreams streams;
+// String inputTopic;
+// String outputTopic;
+// Properties streamsProperties;
+// ObjectMapper objectMapper;
+// DeduplicatorProperties props;
+
+// public ProcessedMapWktDeduplicatorTopology(DeduplicatorProperties props,
+// Properties streamsProperties){
+// this.props = props;
+// this.streamsProperties = streamsProperties;
+// this.objectMapper = DateJsonMapper.getInstance();
+// }
+
+// public void start() {
+// if (streams != null && streams.state().isRunningOrRebalancing()) {
+// throw new IllegalStateException("Start called while streams is already
+// running.");
+// }
+// Topology topology = buildTopology();
+// streams = new KafkaStreams(topology, streamsProperties);
+// if (exceptionHandler != null)
+// streams.setUncaughtExceptionHandler(exceptionHandler);
+// if (stateListener != null) streams.setStateListener(stateListener);
+// logger.info("Starting Processed Map WKT Deduplicator Topology");
+// streams.start();
+// }
+
+// public Topology buildTopology() {
+// StreamsBuilder builder = new StreamsBuilder();
+
+// KStream> inputStream =
+// builder.stream(props.getKafkaTopicProcessedMapWKT(),
+// Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
+
+// builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapWKTName()),
+// Serdes.String(), JsonSerdes.ProcessedMapWKT()));
+
+// KStream> deduplicatedStream =
+// inputStream.process(new ProcessedMapWktProcessorSupplier(props),
+// props.getKafkaStateStoreProcessedMapWKTName());
+
+// deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMapWKT(),
+// Produced.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
+
+// return builder.build();
+
+// }
+
+// public void stop() {
+// logger.info("Stopping Processed Map deduplicator Socket Broadcast
+// Topology.");
+// if (streams != null) {
+// streams.close();
+// streams.cleanUp();
+// streams = null;
+// }
+// logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
+// }
+
+// StateListener stateListener;
+// public void registerStateListener(StateListener stateListener) {
+// this.stateListener = stateListener;
+// }
+
+// StreamsUncaughtExceptionHandler exceptionHandler;
+// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
+// exceptionHandler) {
+// this.exceptionHandler = exceptionHandler;
+// }
+
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java
index 6f55329..05a91fa 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java
@@ -1,96 +1,105 @@
-package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KafkaStreams;
-import org.apache.kafka.streams.StreamsBuilder;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.KafkaStreams.StateListener;
-import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedSpatProcessorSupplier;
-import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-
-import org.apache.kafka.streams.kstream.*;
-import org.apache.kafka.streams.state.Stores;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.time.format.DateTimeFormatter;
-import java.util.Properties;
-
-public class ProcessedSpatDeduplicatorTopology {
-
- private static final Logger logger = LoggerFactory.getLogger(ProcessedSpatDeduplicatorTopology.class);
-
- Topology topology;
- KafkaStreams streams;
- String inputTopic;
- String outputTopic;
- Properties streamsProperties;
- ObjectMapper objectMapper;
- DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
- DeduplicatorProperties props;
-
-
- public ProcessedSpatDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties){
- this.props = props;
- this.streamsProperties = streamsProperties;
- this.objectMapper = DateJsonMapper.getInstance();
- }
-
-
-
- public void start() {
- if (streams != null && streams.state().isRunningOrRebalancing()) {
- throw new IllegalStateException("Start called while streams is already running.");
- }
- Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
- if (exceptionHandler != null) streams.setUncaughtExceptionHandler(exceptionHandler);
- if (stateListener != null) streams.setStateListener(stateListener);
- logger.info("Starting Map Deduplicator Topology");
- streams.start();
- }
-
- public Topology buildTopology() {
- StreamsBuilder builder = new StreamsBuilder();
-
- KStream inputStream = builder.stream(props.getKafkaTopicProcessedSpat(), Consumed.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
-
- builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedSpatName()),
- Serdes.String(), JsonSerdes.ProcessedSpat()));
-
- KStream deduplicatedStream = inputStream.process(new ProcessedSpatProcessorSupplier(props), props.getKafkaStateStoreProcessedSpatName());
-
-
- deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedSpat(), Produced.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
-
- return builder.build();
-
- }
-
- public void stop() {
- logger.info("Stopping Processed SPaT deduplicator Socket Broadcast Topology.");
- if (streams != null) {
- streams.close();
- streams.cleanUp();
- streams = null;
- }
- logger.info("Stopped Processed SPaT deduplicator Socket Broadcast Topology.");
- }
-
- StateListener stateListener;
- public void registerStateListener(StateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- StreamsUncaughtExceptionHandler exceptionHandler;
- public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-}
+// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KafkaStreams;
+// import org.apache.kafka.streams.StreamsBuilder;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.KafkaStreams.StateListener;
+// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedSpatProcessorSupplier;
+// import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+
+// import org.apache.kafka.streams.kstream.*;
+// import org.apache.kafka.streams.state.Stores;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+
+// import com.fasterxml.jackson.databind.ObjectMapper;
+
+// import java.time.format.DateTimeFormatter;
+// import java.util.Properties;
+
+// public class ProcessedSpatDeduplicatorTopology {
+
+// private static final Logger logger =
+// LoggerFactory.getLogger(ProcessedSpatDeduplicatorTopology.class);
+
+// Topology topology;
+// KafkaStreams streams;
+// String inputTopic;
+// String outputTopic;
+// Properties streamsProperties;
+// ObjectMapper objectMapper;
+// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+// DeduplicatorProperties props;
+
+// public ProcessedSpatDeduplicatorTopology(DeduplicatorProperties props,
+// Properties streamsProperties){
+// this.props = props;
+// this.streamsProperties = streamsProperties;
+// this.objectMapper = DateJsonMapper.getInstance();
+// }
+
+// public void start() {
+// if (streams != null && streams.state().isRunningOrRebalancing()) {
+// throw new IllegalStateException("Start called while streams is already
+// running.");
+// }
+// Topology topology = buildTopology();
+// streams = new KafkaStreams(topology, streamsProperties);
+// if (exceptionHandler != null)
+// streams.setUncaughtExceptionHandler(exceptionHandler);
+// if (stateListener != null) streams.setStateListener(stateListener);
+// logger.info("Starting Map Deduplicator Topology");
+// streams.start();
+// }
+
+// public Topology buildTopology() {
+// StreamsBuilder builder = new StreamsBuilder();
+
+// KStream inputStream =
+// builder.stream(props.getKafkaTopicProcessedSpat(),
+// Consumed.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
+
+// builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedSpatName()),
+// Serdes.String(), JsonSerdes.ProcessedSpat()));
+
+// KStream deduplicatedStream = inputStream.process(new
+// ProcessedSpatProcessorSupplier(props),
+// props.getKafkaStateStoreProcessedSpatName());
+
+// deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedSpat(),
+// Produced.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
+
+// return builder.build();
+
+// }
+
+// public void stop() {
+// logger.info("Stopping Processed SPaT deduplicator Socket Broadcast
+// Topology.");
+// if (streams != null) {
+// streams.close();
+// streams.cleanUp();
+// streams = null;
+// }
+// logger.info("Stopped Processed SPaT deduplicator Socket Broadcast
+// Topology.");
+// }
+
+// StateListener stateListener;
+// public void registerStateListener(StateListener stateListener) {
+// this.stateListener = stateListener;
+// }
+
+// StreamsUncaughtExceptionHandler exceptionHandler;
+// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
+// exceptionHandler) {
+// this.exceptionHandler = exceptionHandler;
+// }
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/GeoUtils.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/GeoUtils.java
index fec5033..245a788 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/GeoUtils.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/GeoUtils.java
@@ -6,15 +6,17 @@
@Slf4j
public class GeoUtils {
private static final GeodeticCalculator calculator = new GeodeticCalculator();
+ private static final double J2735_SCALE_FACTOR = 10000000; // 10000000 = 1 meter
-
/**
* Calculates the geodetic distance between two points on Earth
+ *
* @param lat1 Latitude of first point (-90 to 90)
* @param lon1 Longitude of first point (-180 to 180)
* @param lat2 Latitude of second point (-90 to 90)
* @param lon2 Longitude of second point (-180 to 180)
- * @return Distance in meters between the two points, or -1 if coordinates are invalid
+ * @return Distance in meters between the two points, or -1 if coordinates are
+ * invalid
*/
public static double calculateGeodeticDistance(double lat1, double lon1, double lat2, double lon2) {
try {
@@ -22,7 +24,7 @@ public static double calculateGeodeticDistance(double lat1, double lon1, double
log.error("Invalid latitude value(s). Latitude must be between -90 and 90 degrees.");
return -1;
}
-
+
if (lon1 < -180 || lon1 > 180 || lon2 < -180 || lon2 > 180) {
log.error("Invalid longitude value(s). Longitude must be between -180 and 180 degrees.");
return -1;
@@ -37,4 +39,20 @@ public static double calculateGeodeticDistance(double lat1, double lon1, double
}
}
+
+ /**
+ * Calculates the geodetic distance between two points on Earth with J2735 scale
+ * factor
+ *
+ * @param lat1 Latitude of first point (-900000000 to 900000000)
+ * @param lon1 Longitude of first point (-1800000000 to 1800000000)
+ * @param lat2 Latitude of second point (-900000000 to 900000000)
+ * @param lon2 Longitude of second point (-1800000000 to 1800000000)
+ * @return Distance in meters between the two points, or -1 if coordinates are
+ * invalid
+ */
+ public static double calculateGeodeticDistanceJ2735(double lat1, double lon1, double lat2, double lon2) {
+ return calculateGeodeticDistance(lat1 / J2735_SCALE_FACTOR, lon1 / J2735_SCALE_FACTOR,
+ lat2 / J2735_SCALE_FACTOR, lon2 / J2735_SCALE_FACTOR);
+ }
}
diff --git a/jpo-deduplicator/src/main/resources/application.yaml b/jpo-deduplicator/src/main/resources/application.yaml
index c5cdadc..0a7d512 100644
--- a/jpo-deduplicator/src/main/resources/application.yaml
+++ b/jpo-deduplicator/src/main/resources/application.yaml
@@ -7,12 +7,15 @@ server.port: 8085
# Kafka properties
spring.kafka.bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
-logging.level.org.apache.kafka: INFO
-logging.level: INFO
-log4j.logger.kafka: OFF
-log4j.logger.org.apache.kafka: OFF
-
-
+logging:
+ level:
+ root: INFO
+ org.springframework.kafka: info
+ org.springframework.web: WARN
+ guru.springframework.controllers: WARN
+ org.springframework.integration.mqtt: INFO
+ us.dot.its.jpo.ode.mec.deposit: ${LOGGING_LEVEL:INFO}
+ org.apache.kafka: WARN
# Processed Map Configuration
kafkaTopicProcessedMap: topic.ProcessedMap
@@ -45,12 +48,12 @@ kafkaTopicDeduplicatedOdeBsmJson: topic.DeduplicatedOdeBsmJson
enableOdeBsmDeduplication: ${ENABLE_ODE_BSM_DEDUPLICATION:true}
odeBsmMaximumTimeDelta: 10000 # Milliseconds
odeBsmMaximumPositionDelta: 1 # Meter
-odeBsmAlwaysIncludeAtSpeed: 1 # Meter / Second
+odeBsmAlwaysIncludeAtSpeed: 20 # Meter / Second
# Processed Map Configuration
kafkaTopicProcessedSpat: topic.ProcessedSpat
kafkaTopicDeduplicatedProcessedSpat: topic.DeduplicatedProcessedSpat
-enableProcessedSpatDeduplication: ${ENABLE_PROCESSED_SPAT_DEDUPLICATION:true}
+enableProcessedSpatDeduplication: ${ENABLE_PROCESSED_SPAT_DEDUPLICATION:true}
# Processed Bsm Configuration
kafkaTopicProcessedBsm: topic.ProcessedBsm
@@ -65,7 +68,7 @@ kafka.linger_ms: 50
# Custom kafka properties
kafka.topics:
- autoCreateTopics: true # Override auto-create in test properties
+ autoCreateTopics: true # Override auto-create in test properties
numPartitions: 1
numReplicas: 1
createTopics:
@@ -105,6 +108,3 @@ kafka.topics:
- name: ${kafkaTopicDeduplicatedProcessedBsm}
cleanupPolicy: delete
retentionMs: 300000
-
-
-
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/resources/logback.xml b/jpo-deduplicator/src/main/resources/logback.xml
deleted file mode 100644
index 860df15..0000000
--- a/jpo-deduplicator/src/main/resources/logback.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
- %date{"yyyy-MM-dd HH:mm:ss", UTC} [%thread] %-5level %logger{0} - %msg %n
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
index 1bee3ec..e448d3a 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
@@ -1,6 +1,8 @@
package us.dot.its.jpo.deduplicator.deduplicator;
-
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
@@ -8,6 +10,7 @@
import org.apache.kafka.streams.TestOutputTopic;
import org.apache.kafka.streams.Topology;
import org.apache.kafka.streams.TopologyTestDriver;
+import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -15,57 +18,138 @@
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import us.dot.its.jpo.asn.j2735.r2024.BasicSafetyMessage.BasicSafetyMessageMessageFrame;
+import us.dot.its.jpo.asn.j2735.r2024.Common.BSMcoreData;
+import us.dot.its.jpo.asn.j2735.r2024.Common.Latitude;
+import us.dot.its.jpo.asn.j2735.r2024.Common.Longitude;
+import us.dot.its.jpo.asn.j2735.r2024.Common.Speed;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.BsmDeduplicatorTopology;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import us.dot.its.jpo.ode.model.OdeBsmData;
+import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.Instant;
import java.util.List;
-
public class BsmDeduplicatorTopologyTest {
String inputTopic = "topic.OdeBsmJson";
String outputTopic = "topic.DeduplicatedOdeBsmJson";
ObjectMapper objectMapper;
- // Reference BSM, Should be forwarded
- String inputBsm1 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:24.693Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.5659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":0.28,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
-
+ String inputBsm1;
// Same as BSM 1 - No Message should be generated
- String inputBsm2 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:24.793Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.5659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":0.28,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
-
+ String inputBsm2;
+
// Increase Time from Bsm 1, Should be forwarded
- String inputBsm3 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:34.793Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.5659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":0.28,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
-
+ String inputBsm3;
+
// Vehicle Speed not 0, Should be Forwarded
- String inputBsm4 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:34.893Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.5659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":5,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
+ String inputBsm4;
// Vehicle Position has changed, Should be Forwarded
- String inputBsm5 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:34.993Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.6659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":0.28,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
-
+ String inputBsm5;
+
// Vehicle Position was removed. Should be Forwarded
- String inputBsm6 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:35.093Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":0.28,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
+ String inputBsm6;
// Vehicle Position was added back in. Should be Forwarded
- String inputBsm7 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"speed\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:35.193Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.6659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"speed\":0.28,\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
+ String inputBsm7;
// Vehicle is missing its speed section, Should be Forwarded
- String inputBsm8 = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"unavailable\",\"longitude\":\"unavailable\",\"elevation\":\"unavailable\",\"heading\":\"unavailable\"},\"rxSource\":\"RSU\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeBsmPayload\",\"serialId\":{\"streamId\":\"9bc470d1-babe-415b-8c5a-4cd4a9403350\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2025-01-31T23:14:35.293Z\",\"schemaVersion\":8,\"maxDurationTime\":0,\"recordGeneratedAt\":\"\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"odePacketID\":\"\",\"odeTimStartDateTime\":\"\",\"asn1\":\"001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00761E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00\",\"originIp\":\"172.20.0.1\"},\"payload\":{\"data\":{\"coreData\":{\"msgCnt\":37,\"id\":\"31325433\",\"secMark\":25399,\"position\":{\"latitude\":40.6659938,\"longitude\":-105.0317754,\"elevation\":1440.9},\"accelSet\":{\"accelLat\":0.00,\"accelLong\":0.27,\"accelVert\":0.00,\"accelYaw\":0.00},\"accuracy\":{\"semiMajor\":9.30,\"semiMinor\":12.05},\"transmission\":\"UNAVAILABLE\",\"heading\":313.2500,\"brakes\":{\"wheelBrakes\":{\"leftFront\":false,\"rightFront\":false,\"unavailable\":true,\"leftRear\":false,\"rightRear\":false},\"traction\":\"unavailable\",\"abs\":\"unavailable\",\"scs\":\"unavailable\",\"brakeBoost\":\"unavailable\",\"auxBrakes\":\"unavailable\"},\"size\":{\"width\":190,\"length\":570}},\"partII\":[{\"id\":\"VehicleSafetyExtensions\",\"value\":{\"pathHistory\":{\"crumbData\":[{\"elevationOffset\":-0.6,\"latOffset\":-0.0000113,\"lonOffset\":0.0000181,\"timeOffset\":1.90},{\"elevationOffset\":-2.3,\"latOffset\":-0.0000310,\"lonOffset\":0.0000472,\"timeOffset\":6.10},{\"elevationOffset\":-1.4,\"latOffset\":-0.0000103,\"lonOffset\":0.0000636,\"timeOffset\":15.70},{\"elevationOffset\":-1.3,\"latOffset\":-0.0000052,\"lonOffset\":0.0000615,\"timeOffset\":18.70},{\"elevationOffset\":-1.7,\"latOffset\":0.0000614,\"lonOffset\":0.0001150,\"timeOffset\":25.89},{\"elevationOffset\":0.7,\"latOffset\":0.0001878,\"lonOffset\":0.0002503,\"timeOffset\":39.59},{\"elevationOffset\":3.1,\"latOffset\":0.0002333,\"lonOffset\":0.0002816,\"timeOffset\":45.39},{\"elevationOffset\":3.9,\"latOffset\":0.0002187,\"lonOffset\":0.0002952,\"timeOffset\":49.59},{\"elevationOffset\":4.6,\"latOffset\":0.0001976,\"lonOffset\":0.0002721,\"timeOffset\":56.99},{\"elevationOffset\":8.4,\"latOffset\":0.0001891,\"lonOffset\":0.0003655,\"timeOffset\":60.50},{\"elevationOffset\":13.7,\"latOffset\":0.0002022,\"lonOffset\":0.0004886,\"timeOffset\":63.49},{\"elevationOffset\":14.4,\"latOffset\":0.0001973,\"lonOffset\":0.0004861,\"timeOffset\":67.60},{\"elevationOffset\":14.4,\"latOffset\":0.0001795,\"lonOffset\":0.0004815,\"timeOffset\":72.70},{\"elevationOffset\":13.5,\"latOffset\":0.0001710,\"lonOffset\":0.0004749,\"timeOffset\":75.70},{\"elevationOffset\":12.1,\"latOffset\":0.0001609,\"lonOffset\":0.0004566,\"timeOffset\":78.80}]},\"pathPrediction\":{\"confidence\":0.0,\"radiusOfCurve\":0.0}}},{\"id\":\"SupplementalVehicleExtensions\",\"value\":{\"classDetails\":{\"fuelType\":\"unknownFuel\",\"hpmsType\":\"none\",\"keyType\":0,\"role\":\"basicVehicle\"},\"vehicleData\":{\"height\":1.90},\"doNotUse2\":{}}}]},\"dataType\":\"us.dot.its.jpo.ode.plugin.j2735.J2735Bsm\"}}";
-
+ String inputBsm8;
+
+ // Vehicle is missing its set to unavailable
+ String inputBsm9;
+
@Autowired
DeduplicatorProperties props;
-
+ @Before
+ public void setup() throws IOException {
+ objectMapper = new ObjectMapper();
+
+ // Load test files from resources
+
+ // Reference MAP
+ String bsmReference = new String(
+ Files.readAllBytes(Paths
+ .get("src/test/resources/json/ode_bsm/sample.ode-bsm-reference.json")));
+ OdeMessageFrameData bsmReferenceData = objectMapper.readValue(bsmReference, OdeMessageFrameData.class);
+
+ // Reference BSM, Should be forwarded
+ inputBsm1 = bsmReferenceData.toJson();
+
+ // Duplicate of Number 1, should be dropped
+ inputBsm2 = bsmReferenceData.toJson();
+
+ // Increase Time from Bsm 1, Should be forwarded
+ OdeMessageFrameData bsmIncreaseTime = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ String originalTime = bsmIncreaseTime.getMetadata().getOdeReceivedAt();
+ Instant instant = Instant.parse(originalTime);
+ Instant newInstant = instant.plusMillis(15000);
+ bsmIncreaseTime.getMetadata().setOdeReceivedAt(newInstant.toString());
+ inputBsm3 = bsmIncreaseTime.toJson();
+
+ // Vehicle Speed not 0, Should be Forwarded
+ OdeMessageFrameData bsmSpeedNotZero = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ BasicSafetyMessageMessageFrame bsmMfSpeedNotZero = (BasicSafetyMessageMessageFrame) bsmSpeedNotZero
+ .getPayload()
+ .getData();
+ bsmMfSpeedNotZero.getValue().getCoreData().setSpeed(new Speed(105));
+ inputBsm4 = bsmSpeedNotZero.toJson();
+
+ // Vehicle Position has changed, Should be Forwarded
+ OdeMessageFrameData bsmPositionChanged = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ BasicSafetyMessageMessageFrame bsmMfPositionChanged = (BasicSafetyMessageMessageFrame) bsmPositionChanged
+ .getPayload().getData();
+ BSMcoreData coreData = bsmMfPositionChanged.getValue().getCoreData();
+ coreData.setLat(new Latitude(400000000));
+ coreData.setLong_(new Longitude(-1050000000));
+ inputBsm5 = bsmPositionChanged.toJson();
+
+ // Vehicle Position was removed. Should be Forwarded
+ OdeMessageFrameData bsmPositionRemoved = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ BasicSafetyMessageMessageFrame bsmMfPositionRemoved = (BasicSafetyMessageMessageFrame) bsmPositionRemoved
+ .getPayload().getData();
+ bsmMfPositionRemoved.getValue().getCoreData().setLat(null);
+ bsmMfPositionRemoved.getValue().getCoreData().setLong_(null);
+ inputBsm6 = bsmPositionRemoved.toJson();
+
+ // Vehicle Position was added back in. Should be Forwarded
+ OdeMessageFrameData bsmPositionAddedBack = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ inputBsm7 = bsmPositionAddedBack.toJson();
+
+ // Vehicle is missing its speed section, Should be Forwarded
+ OdeMessageFrameData bsmSpeedMissing = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ BasicSafetyMessageMessageFrame bsmMfSpeedMissing = (BasicSafetyMessageMessageFrame) bsmSpeedMissing
+ .getPayload().getData();
+ bsmMfSpeedMissing.getValue().getCoreData().setSpeed(null);
+ inputBsm8 = bsmSpeedMissing.toJson();
+
+ // Vehicle is missing its set to unavailable, should be forwarded
+ OdeMessageFrameData bsmSetToUnavailable = objectMapper.readValue(bsmReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ BasicSafetyMessageMessageFrame bsmMfSetToUnavailable = (BasicSafetyMessageMessageFrame) bsmSetToUnavailable
+ .getPayload().getData();
+ bsmMfSetToUnavailable.getValue().getCoreData().setSpeed(new Speed(8191));
+ inputBsm9 = bsmSetToUnavailable.toJson();
+
+ }
@Test
public void testTopology() {
-
-
-
-
-
props = new DeduplicatorProperties();
props.setAlwaysIncludeAtSpeed(1);
props.setenableOdeBsmDeduplication(true);
@@ -78,18 +162,16 @@ public void testTopology() {
Topology topology = bsmDeduplicatorTopology.buildTopology();
try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputOdeBsmData = driver.createInputTopic(
- inputTopic,
- Serdes.Void().serializer(),
- Serdes.String().serializer());
+ TestInputTopic inputOdeBsmData = driver.createInputTopic(
+ inputTopic,
+ Serdes.Void().serializer(),
+ Serdes.String().serializer());
- TestOutputTopic outputOdeBsmData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- JsonSerdes.OdeBsm().deserializer());
+ TestOutputTopic outputOdeBsmData = driver.createOutputTopic(
+ outputTopic,
+ Serdes.String().deserializer(),
+ JsonSerdes.OdeMessageFrame().deserializer());
inputOdeBsmData.pipeInput(null, inputBsm1);
inputOdeBsmData.pipeInput(null, inputBsm2);
@@ -99,31 +181,31 @@ public void testTopology() {
inputOdeBsmData.pipeInput(null, inputBsm6);
inputOdeBsmData.pipeInput(null, inputBsm7);
inputOdeBsmData.pipeInput(null, inputBsm8);
+ inputOdeBsmData.pipeInput(null, inputBsm9);
+ List> bsmDeduplicationResults = outputOdeBsmData
+ .readKeyValuesToList();
- List> bsmDeduplicationResults = outputOdeBsmData.readKeyValuesToList();
-
- // validate that only 7 messages make it through
+ // validate that only 8 messages make it through
assertEquals(7, bsmDeduplicationResults.size());
objectMapper = new ObjectMapper();
- OdeBsmData bsm1 = objectMapper.readValue(inputBsm1, OdeBsmData.class);
- OdeBsmData bsm3 = objectMapper.readValue(inputBsm3, OdeBsmData.class);
- OdeBsmData bsm4 = objectMapper.readValue(inputBsm4, OdeBsmData.class);
- OdeBsmData bsm5 = objectMapper.readValue(inputBsm5, OdeBsmData.class);
- OdeBsmData bsm6 = objectMapper.readValue(inputBsm6, OdeBsmData.class);
- OdeBsmData bsm7 = objectMapper.readValue(inputBsm7, OdeBsmData.class);
- OdeBsmData bsm8 = objectMapper.readValue(inputBsm8, OdeBsmData.class);
-
- // Since each Test BSM has a unique Timestamp, it is sufficient just to compare timestamps to make sure everthing came out in the right order.
- assertEquals(bsm1.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(0).value.getMetadata().getOdeReceivedAt());
- assertEquals(bsm3.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(1).value.getMetadata().getOdeReceivedAt());
- assertEquals(bsm4.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(2).value.getMetadata().getOdeReceivedAt());
- assertEquals(bsm5.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(3).value.getMetadata().getOdeReceivedAt());
- assertEquals(bsm6.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(4).value.getMetadata().getOdeReceivedAt());
- assertEquals(bsm7.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(5).value.getMetadata().getOdeReceivedAt());
- assertEquals(bsm8.getMetadata().getOdeReceivedAt(), bsmDeduplicationResults.get(6).value.getMetadata().getOdeReceivedAt());
-
+ OdeMessageFrameData bsm1 = objectMapper.readValue(inputBsm1, OdeMessageFrameData.class);
+ OdeMessageFrameData bsm3 = objectMapper.readValue(inputBsm3, OdeMessageFrameData.class);
+ OdeMessageFrameData bsm4 = objectMapper.readValue(inputBsm4, OdeMessageFrameData.class);
+ OdeMessageFrameData bsm5 = objectMapper.readValue(inputBsm5, OdeMessageFrameData.class);
+ OdeMessageFrameData bsm6 = objectMapper.readValue(inputBsm6, OdeMessageFrameData.class);
+ OdeMessageFrameData bsm7 = objectMapper.readValue(inputBsm7, OdeMessageFrameData.class);
+ OdeMessageFrameData bsm8 = objectMapper.readValue(inputBsm8, OdeMessageFrameData.class);
+
+ assertThat(bsmDeduplicationResults.get(0).value.toJson(), jsonEquals(bsm1.toJson()));
+ assertThat(bsmDeduplicationResults.get(1).value.toJson(), jsonEquals(bsm3.toJson()));
+ assertThat(bsmDeduplicationResults.get(2).value.toJson(), jsonEquals(bsm4.toJson()));
+ assertThat(bsmDeduplicationResults.get(3).value.toJson(), jsonEquals(bsm5.toJson()));
+ assertThat(bsmDeduplicationResults.get(4).value.toJson(), jsonEquals(bsm6.toJson()));
+ assertThat(bsmDeduplicationResults.get(5).value.toJson(), jsonEquals(bsm7.toJson()));
+ assertThat(bsmDeduplicationResults.get(6).value.toJson(), jsonEquals(bsm8.toJson()));
+
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
diff --git a/jpo-deduplicator/src/test/resources/json/ode_bsm/sample.ode-bsm-reference.json b/jpo-deduplicator/src/test/resources/json/ode_bsm/sample.ode-bsm-reference.json
new file mode 100644
index 0000000..31d0aaf
--- /dev/null
+++ b/jpo-deduplicator/src/test/resources/json/ode_bsm/sample.ode-bsm-reference.json
@@ -0,0 +1,208 @@
+{
+ "metadata": {
+ "logFileName": "",
+ "recordType": "bsmTx",
+ "securityResultCode": "success",
+ "receivedMessageDetails": {
+ "locationData": {
+ "latitude": "unavailable",
+ "longitude": "unavailable",
+ "elevation": "unavailable",
+ "speed": "unavailable",
+ "heading": "unavailable"
+ },
+ "rxSource": "RSU"
+ },
+ "payloadType": "us.dot.its.jpo.ode.model.OdeMessageFramePayload",
+ "serialId": {
+ "streamId": "ca80eb0f-7d31-4f66-b842-a3efee685099",
+ "bundleSize": 1,
+ "bundleId": 0,
+ "recordId": 0,
+ "serialNumber": 0
+ },
+ "odeReceivedAt": "2025-07-03T19:56:46.773Z",
+ "schemaVersion": 9,
+ "maxDurationTime": 0,
+ "recordGeneratedAt": "",
+ "recordGeneratedBy": "OBU",
+ "sanitized": false,
+ "odePacketID": "",
+ "odeTimStartDateTime": "",
+ "asn1": "001480B8494C4C950CD8CDE6E9651116579F22A424DD78FFFFF00061E4FD7EB7D07F7FFF80005F11D1020214C1C0FFC7C016AFF4017A0FF65403B0FD204C20FFCCC04F8FE40C420FFE6404CEFE60E9A10133408FCFDE1438103AB4138F00E1EEC1048EC160103E237410445C171104E26BC103DC4154305C2C84103B1C1C8F0A82F42103F34262D1123198103DAC25FB12034CE10381C259F12038CA103574251B10E3B2210324C23AD0F23D8EFFFE0000209340D10000004264BF00",
+ "source": "EV",
+ "originIp": "172.19.0.1",
+ "isCertPresent": false
+ },
+ "payload": {
+ "data": {
+ "messageId": 20,
+ "value": {
+ "BasicSafetyMessage": {
+ "coreData": {
+ "msgCnt": 37,
+ "id": "31325433",
+ "secMark": 25399,
+ "lat": 405659938,
+ "long": -1050317754,
+ "elev": 14409,
+ "accuracy": {
+ "semiMajor": 186,
+ "semiMinor": 241,
+ "orientation": 65535
+ },
+ "transmission": "unavailable",
+ "speed": 0,
+ "heading": 25060,
+ "angle": 127,
+ "accelSet": {
+ "long": 27,
+ "lat": 0,
+ "vert": 0,
+ "yaw": 0
+ },
+ "brakes": {
+ "wheelBrakes": "80",
+ "traction": "unavailable",
+ "abs": "unavailable",
+ "scs": "unavailable",
+ "brakeBoost": "unavailable",
+ "auxBrakes": "unavailable"
+ },
+ "size": {
+ "width": 190,
+ "length": 570
+ }
+ },
+ "partII": [
+ {
+ "partII-Id": 0,
+ "partII-Value": {
+ "VehicleSafetyExtensions": {
+ "pathHistory": {
+ "crumbData": [
+ {
+ "latOffset": -113,
+ "lonOffset": 181,
+ "elevationOffset": -6,
+ "timeOffset": 190
+ },
+ {
+ "latOffset": -310,
+ "lonOffset": 472,
+ "elevationOffset": -23,
+ "timeOffset": 610
+ },
+ {
+ "latOffset": -103,
+ "lonOffset": 636,
+ "elevationOffset": -14,
+ "timeOffset": 1570
+ },
+ {
+ "latOffset": -52,
+ "lonOffset": 615,
+ "elevationOffset": -13,
+ "timeOffset": 1870
+ },
+ {
+ "latOffset": 614,
+ "lonOffset": 1150,
+ "elevationOffset": -17,
+ "timeOffset": 2589
+ },
+ {
+ "latOffset": 1878,
+ "lonOffset": 2503,
+ "elevationOffset": 7,
+ "timeOffset": 3959
+ },
+ {
+ "latOffset": 2333,
+ "lonOffset": 2816,
+ "elevationOffset": 31,
+ "timeOffset": 4539
+ },
+ {
+ "latOffset": 2187,
+ "lonOffset": 2952,
+ "elevationOffset": 39,
+ "timeOffset": 4959
+ },
+ {
+ "latOffset": 1976,
+ "lonOffset": 2721,
+ "elevationOffset": 46,
+ "timeOffset": 5699
+ },
+ {
+ "latOffset": 1891,
+ "lonOffset": 3655,
+ "elevationOffset": 84,
+ "timeOffset": 6050
+ },
+ {
+ "latOffset": 2022,
+ "lonOffset": 4886,
+ "elevationOffset": 137,
+ "timeOffset": 6349
+ },
+ {
+ "latOffset": 1973,
+ "lonOffset": 4861,
+ "elevationOffset": 144,
+ "timeOffset": 6760
+ },
+ {
+ "latOffset": 1795,
+ "lonOffset": 4815,
+ "elevationOffset": 144,
+ "timeOffset": 7270
+ },
+ {
+ "latOffset": 1710,
+ "lonOffset": 4749,
+ "elevationOffset": 135,
+ "timeOffset": 7570
+ },
+ {
+ "latOffset": 1609,
+ "lonOffset": 4566,
+ "elevationOffset": 121,
+ "timeOffset": 7880
+ }
+ ]
+ },
+ "pathPrediction": {
+ "radiusOfCurve": 32767,
+ "confidence": 0
+ }
+ }
+ }
+ },
+ {
+ "partII-Id": 2,
+ "partII-Value": {
+ "SupplementalVehicleExtensions": {
+ "classDetails": {
+ "keyType": 0,
+ "role": "basicVehicle",
+ "hpmsType": "none",
+ "fuelType": 0
+ },
+ "vehicleData": {
+ "height": 38
+ },
+ "doNotUse2": {
+ "airTemp": 191
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "dataType": "us.dot.its.jpo.asn.j2735.r2024.BasicSafetyMessage.BasicSafetyMessageMessageFrame"
+ }
+}
\ No newline at end of file
From cb2e3c6974a225361e6922a6c63016a85f00b571 Mon Sep 17 00:00:00 2001
From: Michael7371 <40476797+Michael7371@users.noreply.github.com>
Date: Thu, 3 Jul 2025 17:44:11 -0600
Subject: [PATCH 02/24] comment out broken code to fix build issues
---
jpo-deduplicator/pom.xml | 7 -
.../deduplicator/models/OdeBsmPair.java | 32 +-
.../deduplicator/models/OdeMapPair.java | 32 +-
.../OdeMapJsonProcessorSupplier.java | 36 +-
.../serialization/PairSerdes.java | 41 +-
.../BsmDeduplicatorTopologyTest.java | 1 -
.../MapDeduplicatorTopologyTest.java | 235 +++++-----
...RawEncodedTimDeduplicatorTopologyTest.java | 217 +++++----
.../ProcessedBsmDeduplicatorTopologyTest.java | 319 +++++++------
.../ProcessedMapDeduplicatorTopologyTest.java | 253 ++++++-----
...ocessedMapWktDeduplicatorTopologyTest.java | 250 ++++++-----
...ProcessedSpatDeduplicatorTopologyTest.java | 419 +++++++++++++-----
12 files changed, 1055 insertions(+), 787 deletions(-)
diff --git a/jpo-deduplicator/pom.xml b/jpo-deduplicator/pom.xml
index 2b595d8..24861c5 100644
--- a/jpo-deduplicator/pom.xml
+++ b/jpo-deduplicator/pom.xml
@@ -149,13 +149,6 @@
33.0.0-jre
-
-
-
org.projectlombok
lombok
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java
index 208622b..2516f63 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java
@@ -1,20 +1,20 @@
-package us.dot.its.jpo.deduplicator.deduplicator.models;
+// package us.dot.its.jpo.deduplicator.deduplicator.models;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import us.dot.its.jpo.ode.model.OdeBsmData;
+// import lombok.Getter;
+// import lombok.NoArgsConstructor;
+// import lombok.Setter;
+// import us.dot.its.jpo.ode.model.OdeBsmData;
-@NoArgsConstructor
-@Setter
-@Getter
-public class OdeBsmPair {
+// @NoArgsConstructor
+// @Setter
+// @Getter
+// public class OdeBsmPair {
- public OdeBsmData message;
- public boolean shouldSend;
+// public OdeBsmData message;
+// public boolean shouldSend;
- public OdeBsmPair(OdeBsmData message, boolean shouldSend){
- this.message = message;
- this.shouldSend = shouldSend;
- }
-}
+// public OdeBsmPair(OdeBsmData message, boolean shouldSend){
+// this.message = message;
+// this.shouldSend = shouldSend;
+// }
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java
index 24c265a..43a78dd 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java
@@ -1,20 +1,20 @@
-package us.dot.its.jpo.deduplicator.deduplicator.models;
+// package us.dot.its.jpo.deduplicator.deduplicator.models;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import us.dot.its.jpo.ode.model.OdeMapData;
+// import lombok.Getter;
+// import lombok.NoArgsConstructor;
+// import lombok.Setter;
+// import us.dot.its.jpo.ode.model.OdeMapData;
-@NoArgsConstructor
-@Setter
-@Getter
-public class OdeMapPair {
+// @NoArgsConstructor
+// @Setter
+// @Getter
+// public class OdeMapPair {
- public OdeMapData message;
- public boolean shouldSend;
+// public OdeMapData message;
+// public boolean shouldSend;
- public OdeMapPair(OdeMapData message, boolean shouldSend){
- this.message = message;
- this.shouldSend = shouldSend;
- }
-}
+// public OdeMapPair(OdeMapData message, boolean shouldSend){
+// this.message = message;
+// this.shouldSend = shouldSend;
+// }
+// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java
index 829af13..7b0c2fd 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java
@@ -1,22 +1,24 @@
-package us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers;
+// package us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers;
-import org.apache.kafka.streams.processor.api.Processor;
-import org.apache.kafka.streams.processor.api.ProcessorSupplier;
+// import org.apache.kafka.streams.processor.api.Processor;
+// import org.apache.kafka.streams.processor.api.ProcessorSupplier;
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.processors.OdeMapJsonProcessor;
-import us.dot.its.jpo.ode.model.OdeMapData;
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.processors.OdeMapJsonProcessor;
+// import us.dot.its.jpo.ode.model.OdeMapData;
-public class OdeMapJsonProcessorSupplier implements ProcessorSupplier {
-
- DeduplicatorProperties props;
+// public class OdeMapJsonProcessorSupplier implements ProcessorSupplier {
- public OdeMapJsonProcessorSupplier(DeduplicatorProperties props){
- this.props = props;
- }
+// DeduplicatorProperties props;
- @Override
- public Processor get() {
- return new OdeMapJsonProcessor(props);
- }
-}
\ No newline at end of file
+// public OdeMapJsonProcessorSupplier(DeduplicatorProperties props) {
+// this.props = props;
+// }
+
+// @Override
+// public Processor get() {
+// return new OdeMapJsonProcessor(props);
+// }
+// }
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java
index e509fa0..2e8f10b 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java
@@ -5,48 +5,47 @@
import us.dot.its.jpo.deduplicator.deduplicator.models.ProcessedMapPair;
import us.dot.its.jpo.deduplicator.deduplicator.models.ProcessedMapWktPair;
-import us.dot.its.jpo.deduplicator.deduplicator.models.OdeMapPair;
-import us.dot.its.jpo.deduplicator.deduplicator.models.OdeBsmPair;
+// import us.dot.its.jpo.deduplicator.deduplicator.models.OdeMapPair;
+// import us.dot.its.jpo.deduplicator.deduplicator.models.OdeBsmPair;
import us.dot.its.jpo.deduplicator.deduplicator.models.JsonPair;
import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.DeserializedRawMap;
import us.dot.its.jpo.geojsonconverter.serialization.deserializers.JsonDeserializer;
import us.dot.its.jpo.geojsonconverter.serialization.serializers.JsonSerializer;
-
public class PairSerdes {
public static Serde ProcessedMapPair() {
return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(ProcessedMapPair.class));
+ new JsonSerializer(),
+ new JsonDeserializer<>(ProcessedMapPair.class));
}
public static Serde ProcessedMapWktPair() {
return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(ProcessedMapWktPair.class));
+ new JsonSerializer(),
+ new JsonDeserializer<>(ProcessedMapWktPair.class));
}
- public static Serde OdeMapPair() {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(OdeMapPair.class));
- }
+ // public static Serde OdeMapPair() {
+ // return Serdes.serdeFrom(
+ // new JsonSerializer(),
+ // new JsonDeserializer<>(OdeMapPair.class));
+ // }
- public static Serde OdeBsmPair() {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(OdeBsmPair.class));
- }
+ // public static Serde OdeBsmPair() {
+ // return Serdes.serdeFrom(
+ // new JsonSerializer(),
+ // new JsonDeserializer<>(OdeBsmPair.class));
+ // }
public static Serde RawMap() {
return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(DeserializedRawMap.class));
+ new JsonSerializer(),
+ new JsonDeserializer<>(DeserializedRawMap.class));
}
public static Serde JsonPair() {
return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(JsonPair.class));
+ new JsonSerializer(),
+ new JsonDeserializer<>(JsonPair.class));
}
}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
index e448d3a..c130aab 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
@@ -2,7 +2,6 @@
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.notNullValue;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
index b9c689f..219aee4 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
@@ -1,115 +1,120 @@
-package us.dot.its.jpo.deduplicator.deduplicator;
-
-
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KeyValue;
-import org.apache.kafka.streams.TestInputTopic;
-import org.apache.kafka.streams.TestOutputTopic;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.TopologyTestDriver;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import us.dot.its.jpo.ode.model.OdeMapData;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
-
-
-public class MapDeduplicatorTopologyTest {
-
- String inputTopic = "topic.OdeMapJson";
- String outputTopic = "topic.DeduplicatedOdeMapJson";
- ObjectMapper objectMapper;
-
- String inputMap1 = "";
- String inputMap2 = "";
- String inputMap3 = "";
- String inputMap4 = "";
-
- @Autowired
- DeduplicatorProperties props;
-
- @Before
- public void setup() throws IOException {
- // Load test files from resources
-
- // Reference MAP
- inputMap1 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
-
- // Duplicate of Number 1
- inputMap2 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
-
- // A different Message entirely
- inputMap3 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-different.json")));
-
- // Message 1 but 1 hour later
- inputMap4 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json")));
- }
-
- @Test
- public void testTopology() {
-
- props = new DeduplicatorProperties();
- props.setKafkaTopicOdeMapJson(inputTopic);
- props.setKafkaTopicDeduplicatedOdeMapJson(outputTopic);
-
- MapDeduplicatorTopology mapDeduplicatorTopology = new MapDeduplicatorTopology(props, null);
-
- Topology topology = mapDeduplicatorTopology.buildTopology();
-
- try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputOdeMapData = driver.createInputTopic(
- inputTopic,
- Serdes.Void().serializer(),
- Serdes.String().serializer());
-
-
- TestOutputTopic outputOdeMapData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- JsonSerdes.OdeMap().deserializer());
-
- inputOdeMapData.pipeInput(null, inputMap1);
- inputOdeMapData.pipeInput(null, inputMap2);
- inputOdeMapData.pipeInput(null, inputMap3);
- inputOdeMapData.pipeInput(null, inputMap4);
-
- List> mapDeduplicationResults = outputOdeMapData.readKeyValuesToList();
-
- // validate that only 3 messages make it through
- assertEquals(3, mapDeduplicationResults.size());
-
- objectMapper = new ObjectMapper();
- OdeMapData map1 = objectMapper.readValue(inputMap1, OdeMapData.class);
- OdeMapData map3 = objectMapper.readValue(inputMap3, OdeMapData.class);
- OdeMapData map4 = objectMapper.readValue(inputMap4, OdeMapData.class);
-
-
- assertEquals(map1.getMetadata().getOdeReceivedAt(), mapDeduplicationResults.get(0).value.getMetadata().getOdeReceivedAt());
- assertEquals(map3.getMetadata().getOdeReceivedAt(), mapDeduplicationResults.get(1).value.getMetadata().getOdeReceivedAt());
- assertEquals(map4.getMetadata().getOdeReceivedAt(), mapDeduplicationResults.get(2).value.getMetadata().getOdeReceivedAt());
-
- } catch (JsonMappingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (JsonProcessingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-}
\ No newline at end of file
+// package us.dot.its.jpo.deduplicator.deduplicator;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KeyValue;
+// import org.apache.kafka.streams.TestInputTopic;
+// import org.apache.kafka.streams.TestOutputTopic;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.TopologyTestDriver;
+// import org.junit.Before;
+// import org.junit.Test;
+// import org.springframework.beans.factory.annotation.Autowired;
+
+// import com.fasterxml.jackson.core.JsonProcessingException;
+// import com.fasterxml.jackson.databind.JsonMappingException;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import us.dot.its.jpo.ode.model.OdeMapData;
+// import static org.junit.jupiter.api.Assertions.assertEquals;
+
+// import java.io.IOException;
+// import java.nio.file.Files;
+// import java.nio.file.Paths;
+// import java.util.List;
+
+// public class MapDeduplicatorTopologyTest {
+
+// String inputTopic = "topic.OdeMapJson";
+// String outputTopic = "topic.DeduplicatedOdeMapJson";
+// ObjectMapper objectMapper;
+
+// String inputMap1 = "";
+// String inputMap2 = "";
+// String inputMap3 = "";
+// String inputMap4 = "";
+
+// @Autowired
+// DeduplicatorProperties props;
+
+// @Before
+// public void setup() throws IOException {
+// // Load test files from resources
+
+// // Reference MAP
+// inputMap1 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
+
+// // Duplicate of Number 1
+// inputMap2 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
+
+// // A different Message entirely
+// inputMap3 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-different.json")));
+
+// // Message 1 but 1 hour later
+// inputMap4 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json")));
+// }
+
+// @Test
+// public void testTopology() {
+
+// props = new DeduplicatorProperties();
+// props.setKafkaTopicOdeMapJson(inputTopic);
+// props.setKafkaTopicDeduplicatedOdeMapJson(outputTopic);
+
+// MapDeduplicatorTopology mapDeduplicatorTopology = new
+// MapDeduplicatorTopology(props, null);
+
+// Topology topology = mapDeduplicatorTopology.buildTopology();
+
+// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+// TestInputTopic inputOdeMapData = driver.createInputTopic(
+// inputTopic,
+// Serdes.Void().serializer(),
+// Serdes.String().serializer());
+
+// TestOutputTopic outputOdeMapData =
+// driver.createOutputTopic(
+// outputTopic,
+// Serdes.String().deserializer(),
+// JsonSerdes.OdeMap().deserializer());
+
+// inputOdeMapData.pipeInput(null, inputMap1);
+// inputOdeMapData.pipeInput(null, inputMap2);
+// inputOdeMapData.pipeInput(null, inputMap3);
+// inputOdeMapData.pipeInput(null, inputMap4);
+
+// List> mapDeduplicationResults =
+// outputOdeMapData.readKeyValuesToList();
+
+// // validate that only 3 messages make it through
+// assertEquals(3, mapDeduplicationResults.size());
+
+// objectMapper = new ObjectMapper();
+// OdeMapData map1 = objectMapper.readValue(inputMap1, OdeMapData.class);
+// OdeMapData map3 = objectMapper.readValue(inputMap3, OdeMapData.class);
+// OdeMapData map4 = objectMapper.readValue(inputMap4, OdeMapData.class);
+
+// assertEquals(map1.getMetadata().getOdeReceivedAt(),
+// mapDeduplicationResults.get(0).value.getMetadata().getOdeReceivedAt());
+// assertEquals(map3.getMetadata().getOdeReceivedAt(),
+// mapDeduplicationResults.get(1).value.getMetadata().getOdeReceivedAt());
+// assertEquals(map4.getMetadata().getOdeReceivedAt(),
+// mapDeduplicationResults.get(2).value.getMetadata().getOdeReceivedAt());
+
+// } catch (JsonMappingException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// } catch (JsonProcessingException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+// }
+// }
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java
index 29cf340..947eb22 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java
@@ -1,89 +1,128 @@
-package us.dot.its.jpo.deduplicator.deduplicator;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KeyValue;
-import org.apache.kafka.streams.TestInputTopic;
-import org.apache.kafka.streams.TestOutputTopic;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.TopologyTestDriver;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.OdeRawEncodedTimDeduplicatorTopology;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.List;
-
-
-public class OdeRawEncodedTimDeduplicatorTopologyTest {
-
- String inputTopic = "topic.OdeRawEncodedTIMJson";
- String outputTopic = "topic.DeduplicatedOdeRawEncodedTIMJson";
-
- ObjectMapper objectMapper = new ObjectMapper();
-
- // Original Message
- String inputTim1 = "{ \"metadata\": { \"securityResultCode\": \"success\", \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\": \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0, \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\", \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\": \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\": \"2024-07-22T23:23:29.553Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": { \"data\": { \"bytes\": \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\" }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
- // Shifted Forward .1 seconds - Should be deduplicated
- String inputTim2 = "{ \"metadata\": { \"securityResultCode\": \"success\", \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\": \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0, \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\", \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\": \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\": \"2024-07-22T23:23:29.653Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": { \"data\": { \"bytes\": \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\" }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
- // Shifted Forward 1 hour Should be allowed to pass through
- String inputTim3 = "{ \"metadata\": { \"securityResultCode\": \"success\", \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\": \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0, \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\", \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\": \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\": \"2024-07-23T00:23:29.653Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": { \"data\": { \"bytes\": \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\" }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
- // Has a different payload ID. Should be allowed through
- String inputTim4 = "{ \"metadata\": { \"securityResultCode\": \"success\", \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\": \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0, \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\", \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\": \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\": \"2024-07-22T23:23:29.553Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": { \"data\": { \"bytes\": \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\" }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
- @Autowired
- DeduplicatorProperties props;
-
- @Test
- public void testTopology() {
-
- props = new DeduplicatorProperties();
- props.setKafkaTopicOdeRawEncodedTimJson(inputTopic);
- props.setKafkaTopicDeduplicatedOdeRawEncodedTimJson(outputTopic);
-
- OdeRawEncodedTimDeduplicatorTopology TimDeduplicatorTopology = new OdeRawEncodedTimDeduplicatorTopology(props, null);
-
- Topology topology = TimDeduplicatorTopology.buildTopology();
- objectMapper.registerModule(new JavaTimeModule());
-
- try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputTimData = driver.createInputTopic(
- inputTopic,
- Serdes.Void().serializer(),
- Serdes.String().serializer());
-
-
- TestOutputTopic outputTimData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- Serdes.String().deserializer());
-
- inputTimData.pipeInput(null, inputTim1);
- inputTimData.pipeInput(null, inputTim2);
- inputTimData.pipeInput(null, inputTim3);
- inputTimData.pipeInput(null, inputTim4);
-
- List> timDeduplicatedResults = outputTimData.readKeyValuesToList();
-
- // validate that only 3 messages make it through
- assertEquals(3, timDeduplicatedResults.size());
- inputTim1 = inputTim1.strip();
-
- assertEquals(inputTim1.replace(" ", ""), timDeduplicatedResults.get(0).value.replace(" ", ""));
- assertEquals(inputTim3.replace(" ", ""), timDeduplicatedResults.get(1).value.replace(" ", ""));
- assertEquals(inputTim4.replace(" ", ""), timDeduplicatedResults.get(2).value.replace(" ", ""));
-
- }catch(Exception e){
- e.printStackTrace();
- }
- }
-}
+// package us.dot.its.jpo.deduplicator.deduplicator;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KeyValue;
+// import org.apache.kafka.streams.TestInputTopic;
+// import org.apache.kafka.streams.TestOutputTopic;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.TopologyTestDriver;
+// import org.junit.Test;
+// import org.springframework.beans.factory.annotation.Autowired;
+
+// import com.fasterxml.jackson.databind.ObjectMapper;
+// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.topologies.OdeRawEncodedTimDeduplicatorTopology;
+// import static org.junit.jupiter.api.Assertions.assertEquals;
+
+// import java.util.List;
+
+// public class OdeRawEncodedTimDeduplicatorTopologyTest {
+
+// String inputTopic = "topic.OdeRawEncodedTIMJson";
+// String outputTopic = "topic.DeduplicatedOdeRawEncodedTIMJson";
+
+// ObjectMapper objectMapper = new ObjectMapper();
+
+// // Original Message
+// String inputTim1 = "{ \"metadata\": { \"securityResultCode\": \"success\",
+// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
+// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
+// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
+// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
+// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
+// \"2024-07-22T23:23:29.553Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
+// \"data\": { \"bytes\":
+// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
+// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
+
+// // Shifted Forward .1 seconds - Should be deduplicated
+// String inputTim2 = "{ \"metadata\": { \"securityResultCode\": \"success\",
+// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
+// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
+// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
+// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
+// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
+// \"2024-07-22T23:23:29.653Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
+// \"data\": { \"bytes\":
+// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
+// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
+
+// // Shifted Forward 1 hour Should be allowed to pass through
+// String inputTim3 = "{ \"metadata\": { \"securityResultCode\": \"success\",
+// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
+// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
+// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
+// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
+// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
+// \"2024-07-23T00:23:29.653Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
+// \"data\": { \"bytes\":
+// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
+// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
+
+// // Has a different payload ID. Should be allowed through
+// String inputTim4 = "{ \"metadata\": { \"securityResultCode\": \"success\",
+// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
+// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
+// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
+// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
+// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
+// \"2024-07-22T23:23:29.553Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
+// \"data\": { \"bytes\":
+// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
+// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
+
+// @Autowired
+// DeduplicatorProperties props;
+
+// @Test
+// public void testTopology() {
+
+// props = new DeduplicatorProperties();
+// props.setKafkaTopicOdeRawEncodedTimJson(inputTopic);
+// props.setKafkaTopicDeduplicatedOdeRawEncodedTimJson(outputTopic);
+
+// OdeRawEncodedTimDeduplicatorTopology TimDeduplicatorTopology = new
+// OdeRawEncodedTimDeduplicatorTopology(props, null);
+
+// Topology topology = TimDeduplicatorTopology.buildTopology();
+// objectMapper.registerModule(new JavaTimeModule());
+
+// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+// TestInputTopic inputTimData = driver.createInputTopic(
+// inputTopic,
+// Serdes.Void().serializer(),
+// Serdes.String().serializer());
+
+// TestOutputTopic outputTimData = driver.createOutputTopic(
+// outputTopic,
+// Serdes.String().deserializer(),
+// Serdes.String().deserializer());
+
+// inputTimData.pipeInput(null, inputTim1);
+// inputTimData.pipeInput(null, inputTim2);
+// inputTimData.pipeInput(null, inputTim3);
+// inputTimData.pipeInput(null, inputTim4);
+
+// List> timDeduplicatedResults =
+// outputTimData.readKeyValuesToList();
+
+// // validate that only 3 messages make it through
+// assertEquals(3, timDeduplicatedResults.size());
+// inputTim1 = inputTim1.strip();
+
+// assertEquals(inputTim1.replace(" ", ""),
+// timDeduplicatedResults.get(0).value.replace(" ", ""));
+// assertEquals(inputTim3.replace(" ", ""),
+// timDeduplicatedResults.get(1).value.replace(" ", ""));
+// assertEquals(inputTim4.replace(" ", ""),
+// timDeduplicatedResults.get(2).value.replace(" ", ""));
+
+// }catch(Exception e){
+// e.printStackTrace();
+// }
+// }
+// }
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java
index 2c13f9c..c143ae8 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java
@@ -1,146 +1,173 @@
-package us.dot.its.jpo.deduplicator.deduplicator;
-
-
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KeyValue;
-import org.apache.kafka.streams.TestInputTopic;
-import org.apache.kafka.streams.TestOutputTopic;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.TopologyTestDriver;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.core.type.TypeReference;
-
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
-
-
-public class ProcessedBsmDeduplicatorTopologyTest {
-
- String inputTopic = "topic.ProcessedBsmJson";
- String outputTopic = "topic.DeduplicatedOdeBsmJson";
- ObjectMapper objectMapper;
-
- String inputProcessedBsmReference = "";
-
- // Same as BSM 1 - No Message should be generated
- String inputProcessedBsmDuplicate = "";
-
- // Increase Time from Bsm 1
- String inputProcessedBsmTimeDelta = "";
-
- // Vehicle Speed not 0
- String inputProcessedBsmWithSpeed = "";
-
- // Vehicle Position has changed
- String inputProcessedBsmChanged = "";
-
- // Vehicle Position was removed
- String inputProcessedBsmMissingPosition = "";
-
- // Vehicle Position was added back in
- String inputProcessedBsmWithPosition = "";
-
- // Vehicle Speed was added back in
- String inputProcessedBsmMissingSpeed = "";
-
- String key = "{\"rsuId\":\"172.19.0.1\",\"logId\":\"1234567890\",\"bsmId\":\"31325433\"}";
-
-
- @Autowired
- DeduplicatorProperties props;
-
- @Before
- public void setup() throws IOException {
- inputProcessedBsmReference = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json")));
- inputProcessedBsmDuplicate = inputProcessedBsmReference;
- inputProcessedBsmTimeDelta = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json")));
- inputProcessedBsmWithSpeed = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json")));
- inputProcessedBsmChanged = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-different.json")));
- inputProcessedBsmMissingPosition = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json")));
- inputProcessedBsmWithPosition = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json")));
- inputProcessedBsmMissingSpeed = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json")));
-
- }
-
- @Test
- public void testTopology() {
- props = new DeduplicatorProperties();
- props.setAlwaysIncludeAtSpeed(1);
- props.setEnableProcessedBsmDeduplication(true);
- props.setProcessedBsmMaximumPositionDelta(1);
- props.setProcessedBsmMaximumTimeDelta(10000);
- props.setKafkaTopicProcessedBsm(inputTopic);
- props.setKafkaTopicDeduplicatedProcessedBsm(outputTopic);
-
- ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new ProcessedBsmDeduplicatorTopology(props, null);
- Topology topology = processedBsmDeduplicatorTopology.buildTopology();
-
- try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputProcessedBsmData = driver.createInputTopic(
- inputTopic,
- Serdes.String().serializer(),
- Serdes.String().serializer());
-
-
- TestOutputTopic> outputProcessedBsmData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- JsonSerdes.ProcessedBsm().deserializer());
-
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmReference);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmDuplicate);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmTimeDelta);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmWithSpeed);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmChanged);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmMissingPosition);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmWithPosition);
- inputProcessedBsmData.pipeInput(key, inputProcessedBsmMissingSpeed);
-
- List>> processedBsmDeduplicationResults = outputProcessedBsmData.readKeyValuesToList();
-
- // validate that only 7 messages make it through
- assertEquals(7, processedBsmDeduplicationResults.size());
-
- objectMapper = new ObjectMapper();
- ProcessedBsm outputProcessedBsmReference = objectMapper.readValue(inputProcessedBsmReference, new TypeReference>() {});
- ProcessedBsm outputProcessedBsmTimeDelta = objectMapper.readValue(inputProcessedBsmTimeDelta, new TypeReference>() {});
- ProcessedBsm outputProcessedBsmWithSpeed = objectMapper.readValue(inputProcessedBsmWithSpeed, new TypeReference>() {});
- ProcessedBsm outputProcessedBsmChanged = objectMapper.readValue(inputProcessedBsmChanged, new TypeReference>() {});
- ProcessedBsm outputProcessedBsmMissingPosition = objectMapper.readValue(inputProcessedBsmChanged, new TypeReference>() {});
- ProcessedBsm outputProcessedBsmWithPosition = objectMapper.readValue(inputProcessedBsmWithPosition, new TypeReference>() {});
- ProcessedBsm outputProcessedBsmMissingSpeed = objectMapper.readValue(inputProcessedBsmMissingSpeed, new TypeReference>() {});
-
-
- assertEquals(outputProcessedBsmReference.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(0).value.getProperties().getOdeReceivedAt());
- assertEquals(outputProcessedBsmTimeDelta.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(1).value.getProperties().getOdeReceivedAt());
- assertEquals(outputProcessedBsmWithSpeed.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(2).value.getProperties().getOdeReceivedAt());
- assertEquals(outputProcessedBsmChanged.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(3).value.getProperties().getOdeReceivedAt());
- assertEquals(outputProcessedBsmMissingPosition.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(4).value.getProperties().getOdeReceivedAt());
- assertEquals(outputProcessedBsmWithPosition.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(5).value.getProperties().getOdeReceivedAt());
- assertEquals(outputProcessedBsmMissingSpeed.getProperties().getOdeReceivedAt(), processedBsmDeduplicationResults.get(6).value.getProperties().getOdeReceivedAt());
-
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- }
-}
\ No newline at end of file
+// package us.dot.its.jpo.deduplicator.deduplicator;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KeyValue;
+// import org.apache.kafka.streams.TestInputTopic;
+// import org.apache.kafka.streams.TestOutputTopic;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.TopologyTestDriver;
+// import org.junit.Before;
+// import org.junit.Test;
+// import org.springframework.beans.factory.annotation.Autowired;
+
+// import com.fasterxml.jackson.core.JsonProcessingException;
+// import com.fasterxml.jackson.databind.JsonMappingException;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+// import com.fasterxml.jackson.core.type.TypeReference;
+
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
+// import static org.junit.jupiter.api.Assertions.assertEquals;
+
+// import java.io.IOException;
+// import java.nio.file.Files;
+// import java.nio.file.Paths;
+// import java.util.List;
+
+// public class ProcessedBsmDeduplicatorTopologyTest {
+
+// String inputTopic = "topic.ProcessedBsmJson";
+// String outputTopic = "topic.DeduplicatedOdeBsmJson";
+// ObjectMapper objectMapper;
+
+// String inputProcessedBsmReference = "";
+
+// // Same as BSM 1 - No Message should be generated
+// String inputProcessedBsmDuplicate = "";
+
+// // Increase Time from Bsm 1
+// String inputProcessedBsmTimeDelta = "";
+
+// // Vehicle Speed not 0
+// String inputProcessedBsmWithSpeed = "";
+
+// // Vehicle Position has changed
+// String inputProcessedBsmChanged = "";
+
+// // Vehicle Position was removed
+// String inputProcessedBsmMissingPosition = "";
+
+// // Vehicle Position was added back in
+// String inputProcessedBsmWithPosition = "";
+
+// // Vehicle Speed was added back in
+// String inputProcessedBsmMissingSpeed = "";
+
+// String key =
+// "{\"rsuId\":\"172.19.0.1\",\"logId\":\"1234567890\",\"bsmId\":\"31325433\"}";
+
+// @Autowired
+// DeduplicatorProperties props;
+
+// @Before
+// public void setup() throws IOException {
+// inputProcessedBsmReference = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json")));
+// inputProcessedBsmDuplicate = inputProcessedBsmReference;
+// inputProcessedBsmTimeDelta = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json")));
+// inputProcessedBsmWithSpeed = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json")));
+// inputProcessedBsmChanged = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-different.json")));
+// inputProcessedBsmMissingPosition = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json")));
+// inputProcessedBsmWithPosition = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json")));
+// inputProcessedBsmMissingSpeed = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json")));
+
+// }
+
+// @Test
+// public void testTopology() {
+// props = new DeduplicatorProperties();
+// props.setAlwaysIncludeAtSpeed(1);
+// props.setEnableProcessedBsmDeduplication(true);
+// props.setProcessedBsmMaximumPositionDelta(1);
+// props.setProcessedBsmMaximumTimeDelta(10000);
+// props.setKafkaTopicProcessedBsm(inputTopic);
+// props.setKafkaTopicDeduplicatedProcessedBsm(outputTopic);
+
+// ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new
+// ProcessedBsmDeduplicatorTopology(props, null);
+// Topology topology = processedBsmDeduplicatorTopology.buildTopology();
+
+// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+// TestInputTopic inputProcessedBsmData =
+// driver.createInputTopic(
+// inputTopic,
+// Serdes.String().serializer(),
+// Serdes.String().serializer());
+
+// TestOutputTopic> outputProcessedBsmData =
+// driver.createOutputTopic(
+// outputTopic,
+// Serdes.String().deserializer(),
+// JsonSerdes.ProcessedBsm().deserializer());
+
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmReference);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmDuplicate);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmTimeDelta);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmWithSpeed);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmChanged);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmMissingPosition);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmWithPosition);
+// inputProcessedBsmData.pipeInput(key, inputProcessedBsmMissingSpeed);
+
+// List>> processedBsmDeduplicationResults
+// = outputProcessedBsmData.readKeyValuesToList();
+
+// // validate that only 7 messages make it through
+// assertEquals(7, processedBsmDeduplicationResults.size());
+
+// objectMapper = new ObjectMapper();
+// ProcessedBsm outputProcessedBsmReference =
+// objectMapper.readValue(inputProcessedBsmReference, new
+// TypeReference>() {});
+// ProcessedBsm outputProcessedBsmTimeDelta =
+// objectMapper.readValue(inputProcessedBsmTimeDelta, new
+// TypeReference>() {});
+// ProcessedBsm outputProcessedBsmWithSpeed =
+// objectMapper.readValue(inputProcessedBsmWithSpeed, new
+// TypeReference>() {});
+// ProcessedBsm outputProcessedBsmChanged =
+// objectMapper.readValue(inputProcessedBsmChanged, new
+// TypeReference>() {});
+// ProcessedBsm outputProcessedBsmMissingPosition =
+// objectMapper.readValue(inputProcessedBsmChanged, new
+// TypeReference>() {});
+// ProcessedBsm outputProcessedBsmWithPosition =
+// objectMapper.readValue(inputProcessedBsmWithPosition, new
+// TypeReference>() {});
+// ProcessedBsm outputProcessedBsmMissingSpeed =
+// objectMapper.readValue(inputProcessedBsmMissingSpeed, new
+// TypeReference>() {});
+
+// assertEquals(outputProcessedBsmReference.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(0).value.getProperties().getOdeReceivedAt());
+// assertEquals(outputProcessedBsmTimeDelta.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(1).value.getProperties().getOdeReceivedAt());
+// assertEquals(outputProcessedBsmWithSpeed.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(2).value.getProperties().getOdeReceivedAt());
+// assertEquals(outputProcessedBsmChanged.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(3).value.getProperties().getOdeReceivedAt());
+// assertEquals(outputProcessedBsmMissingPosition.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(4).value.getProperties().getOdeReceivedAt());
+// assertEquals(outputProcessedBsmWithPosition.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(5).value.getProperties().getOdeReceivedAt());
+// assertEquals(outputProcessedBsmMissingSpeed.getProperties().getOdeReceivedAt(),
+// processedBsmDeduplicationResults.get(6).value.getProperties().getOdeReceivedAt());
+
+// } catch (JsonMappingException e) {
+// e.printStackTrace();
+// } catch (JsonProcessingException e) {
+// e.printStackTrace();
+// }
+// }
+// }
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java
index 3ed14a2..4e4f316 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java
@@ -1,128 +1,139 @@
-package us.dot.its.jpo.deduplicator.deduplicator;
+// package us.dot.its.jpo.deduplicator.deduplicator;
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KeyValue;
-import org.apache.kafka.streams.TestInputTopic;
-import org.apache.kafka.streams.TestOutputTopic;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.TopologyTestDriver;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KeyValue;
+// import org.apache.kafka.streams.TestInputTopic;
+// import org.apache.kafka.streams.TestOutputTopic;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.TopologyTestDriver;
+// import org.junit.Before;
+// import org.junit.Test;
+// import org.springframework.beans.factory.annotation.Autowired;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+// import com.fasterxml.jackson.core.JsonProcessingException;
+// import com.fasterxml.jackson.core.type.TypeReference;
+// import com.fasterxml.jackson.databind.JsonMappingException;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import static org.junit.jupiter.api.Assertions.assertEquals;
-import java.util.List;
+// import java.util.List;
+
+// import java.io.IOException;
+// import java.nio.file.Files;
+// import java.nio.file.Paths;
+
+// public class ProcessedMapDeduplicatorTopologyTest {
+
+// String inputTopic = "topic.ProcessedMap";
+// String outputTopic = "topic.DeduplicatedProcessedMap";
+
+// TypeReference> typeReference = new
+// TypeReference<>(){};
+// ObjectMapper objectMapper = new ObjectMapper();
+
+// // Reference MAP
+// String inputProcessedMap1 = "";
+
+// // Duplicate of Number 1
+// String inputProcessedMap2 = "";
+
+// // A different Message entirely
+// String inputProcessedMap3 = "";
+
+// // Message 1 but 1 hour later
+// String inputProcessedMap4 = "";
+
+// String key =
+// "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
+
+// @Autowired
+// DeduplicatorProperties props;
+
+// @Before
+// public void setup() throws IOException {
+// // Load test files from resources
+
+// // Reference MAP
+// inputProcessedMap1 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
+
+// // Duplicate of Number 1
+// inputProcessedMap2 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
+
+// // A different Message entirely
+// inputProcessedMap3 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-different.json")));
+
+// // Message 1 but 1 hour later
+// inputProcessedMap4 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json")));
+// }
+
+// @Test
+// public void testTopology() {
+
+// props = new DeduplicatorProperties();
+// props.setKafkaTopicProcessedMap(inputTopic);
+// props.setKafkaTopicDeduplicatedProcessedMap(outputTopic);
+
+// ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new
+// ProcessedMapDeduplicatorTopology(props, null);
+
+// Topology topology = processedMapDeduplicatorTopology.buildTopology();
+// objectMapper.registerModule(new JavaTimeModule());
+
+// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+// TestInputTopic inputProcessedMapData =
+// driver.createInputTopic(
+// inputTopic,
+// Serdes.String().serializer(),
+// Serdes.String().serializer());
+
+// TestOutputTopic> outputProcessedMapData =
+// driver.createOutputTopic(
+// outputTopic,
+// Serdes.String().deserializer(),
+// JsonSerdes.ProcessedMapGeoJson().deserializer());
+
+// inputProcessedMapData.pipeInput(key, inputProcessedMap1);
+// inputProcessedMapData.pipeInput(key, inputProcessedMap2);
+// inputProcessedMapData.pipeInput(key, inputProcessedMap3);
+// inputProcessedMapData.pipeInput(key, inputProcessedMap4);
+
+// List>> mapDeduplicatorResults =
+// outputProcessedMapData.readKeyValuesToList();
+
+// // validate that only 3 messages make it through
+// assertEquals(3, mapDeduplicatorResults.size());
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+// ProcessedMap map1 = objectMapper.readValue(inputProcessedMap1,
+// typeReference);
+// ProcessedMap map3 = objectMapper.readValue(inputProcessedMap3,
+// typeReference);
+// ProcessedMap map4 = objectMapper.readValue(inputProcessedMap4,
+// typeReference);
-public class ProcessedMapDeduplicatorTopologyTest {
+// assertEquals(map1.getProperties().getOdeReceivedAt(),
+// mapDeduplicatorResults.get(0).value.getProperties().getOdeReceivedAt());
+// assertEquals(map3.getProperties().getOdeReceivedAt(),
+// mapDeduplicatorResults.get(1).value.getProperties().getOdeReceivedAt());
+// assertEquals(map4.getProperties().getOdeReceivedAt(),
+// mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt());
- String inputTopic = "topic.ProcessedMap";
- String outputTopic = "topic.DeduplicatedProcessedMap";
-
-
- TypeReference> typeReference = new TypeReference<>(){};
- ObjectMapper objectMapper = new ObjectMapper();
-
- // Reference MAP
- String inputProcessedMap1 = "";
-
- // Duplicate of Number 1
- String inputProcessedMap2 = "";
-
- // A different Message entirely
- String inputProcessedMap3 = "";
-
- // Message 1 but 1 hour later
- String inputProcessedMap4 = "";
-
-
- String key = "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
-
- @Autowired
- DeduplicatorProperties props;
-
-
- @Before
- public void setup() throws IOException {
- // Load test files from resources
-
- // Reference MAP
- inputProcessedMap1 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
-
- // Duplicate of Number 1
- inputProcessedMap2 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
-
- // A different Message entirely
- inputProcessedMap3 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-different.json")));
-
- // Message 1 but 1 hour later
- inputProcessedMap4 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json")));
- }
-
-
- @Test
- public void testTopology() {
-
- props = new DeduplicatorProperties();
- props.setKafkaTopicProcessedMap(inputTopic);
- props.setKafkaTopicDeduplicatedProcessedMap(outputTopic);
-
- ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapDeduplicatorTopology(props, null);
-
- Topology topology = processedMapDeduplicatorTopology.buildTopology();
- objectMapper.registerModule(new JavaTimeModule());
-
- try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputProcessedMapData = driver.createInputTopic(
- inputTopic,
- Serdes.String().serializer(),
- Serdes.String().serializer());
-
-
- TestOutputTopic> outputProcessedMapData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- JsonSerdes.ProcessedMapGeoJson().deserializer());
-
- inputProcessedMapData.pipeInput(key, inputProcessedMap1);
- inputProcessedMapData.pipeInput(key, inputProcessedMap2);
- inputProcessedMapData.pipeInput(key, inputProcessedMap3);
- inputProcessedMapData.pipeInput(key, inputProcessedMap4);
-
- List>> mapDeduplicatorResults = outputProcessedMapData.readKeyValuesToList();
-
- // validate that only 3 messages make it through
- assertEquals(3, mapDeduplicatorResults.size());
-
- ProcessedMap map1 = objectMapper.readValue(inputProcessedMap1, typeReference);
- ProcessedMap map3 = objectMapper.readValue(inputProcessedMap3, typeReference);
- ProcessedMap map4 = objectMapper.readValue(inputProcessedMap4, typeReference);
-
- assertEquals(map1.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(0).value.getProperties().getOdeReceivedAt());
- assertEquals(map3.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(1).value.getProperties().getOdeReceivedAt());
- assertEquals(map4.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt());
-
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- }
-}
+// } catch (JsonMappingException e) {
+// e.printStackTrace();
+// } catch (JsonProcessingException e) {
+// e.printStackTrace();
+// }
+// }
+// }
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java
index fff6a71..a464264 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java
@@ -1,129 +1,137 @@
-package us.dot.its.jpo.deduplicator.deduplicator;
+// package us.dot.its.jpo.deduplicator.deduplicator;
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KeyValue;
-import org.apache.kafka.streams.TestInputTopic;
-import org.apache.kafka.streams.TestOutputTopic;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.TopologyTestDriver;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KeyValue;
+// import org.apache.kafka.streams.TestInputTopic;
+// import org.apache.kafka.streams.TestOutputTopic;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.TopologyTestDriver;
+// import org.junit.Before;
+// import org.junit.Test;
+// import org.springframework.beans.factory.annotation.Autowired;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+// import com.fasterxml.jackson.core.JsonProcessingException;
+// import com.fasterxml.jackson.core.type.TypeReference;
+// import com.fasterxml.jackson.databind.JsonMappingException;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
+// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import static org.junit.jupiter.api.Assertions.assertEquals;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+// import java.io.IOException;
+// import java.nio.file.Files;
+// import java.nio.file.Paths;
+
+// import java.util.List;
-import java.util.List;
+// public class ProcessedMapWktDeduplicatorTopologyTest {
+
+// String inputTopic = "topic.ProcessedMapWKT";
+// String outputTopic = "topic.DeduplicatedProcessedMapWKT";
+
+// TypeReference> typeReference = new TypeReference<>(){};
+// ObjectMapper objectMapper = new ObjectMapper();
+
+// // Reference MAP
+// String inputProcessedMapWkt1 = "";
+
+// // Duplicate of Number 1
+// String inputProcessedMapWkt2 = "";
+
+// // A different Message entirely
+// String inputProcessedMapWkt3 = "";
+
+// // Message 1 but 1 hour later
+// String inputProcessedMapWkt4 = "";
+
+// String key =
+// "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
+
+// @Autowired
+// DeduplicatorProperties props;
+
+// @Before
+// public void setup() throws IOException {
+// // Load test files from resources
+
+// // Reference MAP
+// inputProcessedMapWkt1 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json")));
+
+// // Duplicate of Number 1
+// inputProcessedMapWkt2 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json")));
+
+// // A different Message entirely
+// inputProcessedMapWkt3 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json")));
+
+// // Message 1 but 1 hour later
+// inputProcessedMapWkt4 = new
+// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json")));
+// }
+
+// @Test
+// public void testTopology() {
+
+// props = new DeduplicatorProperties();
+// props.setKafkaTopicProcessedMapWKT(inputTopic);
+// props.setKafkaTopicDeduplicatedProcessedMapWKT(outputTopic);
+
+// ProcessedMapWktDeduplicatorTopology processedMapDeduplicatorTopology = new
+// ProcessedMapWktDeduplicatorTopology(props, null);
+
+// Topology topology = processedMapDeduplicatorTopology.buildTopology();
+// objectMapper.registerModule(new JavaTimeModule());
+
+// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+// TestInputTopic inputProcessedMapData =
+// driver.createInputTopic(
+// inputTopic,
+// Serdes.String().serializer(),
+// Serdes.String().serializer());
+
+// TestOutputTopic> outputProcessedMapData =
+// driver.createOutputTopic(
+// outputTopic,
+// Serdes.String().deserializer(),
+// JsonSerdes.ProcessedMapWKT().deserializer());
+
+// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt1);
+// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt2);
+// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt3);
+// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt4);
+
+// List>> mapDeduplicatorResults =
+// outputProcessedMapData.readKeyValuesToList();
+
+// // validate that only 3 messages make it through
+// assertEquals(3, mapDeduplicatorResults.size());
-public class ProcessedMapWktDeduplicatorTopologyTest {
+// ProcessedMap map1 = objectMapper.readValue(inputProcessedMapWkt1,
+// typeReference);
+// ProcessedMap map2 = objectMapper.readValue(inputProcessedMapWkt2,
+// typeReference);
+// ProcessedMap map4 = objectMapper.readValue(inputProcessedMapWkt4,
+// typeReference);
- String inputTopic = "topic.ProcessedMapWKT";
- String outputTopic = "topic.DeduplicatedProcessedMapWKT";
-
+// assertEquals(map1.getProperties().getOdeReceivedAt(),
+// mapDeduplicatorResults.get(0).value.getProperties().getOdeReceivedAt());
+// assertEquals(map2.getProperties().getOdeReceivedAt(),
+// mapDeduplicatorResults.get(1).value.getProperties().getOdeReceivedAt());
+// assertEquals(map4.getProperties().getOdeReceivedAt(),
+// mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt());
-
- TypeReference> typeReference = new TypeReference<>(){};
- ObjectMapper objectMapper = new ObjectMapper();
-
- // Reference MAP
- String inputProcessedMapWkt1 = "";
-
- // Duplicate of Number 1
- String inputProcessedMapWkt2 = "";
-
- // A different Message entirely
- String inputProcessedMapWkt3 = "";
-
- // Message 1 but 1 hour later
- String inputProcessedMapWkt4 = "";
-
- String key = "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
-
- @Autowired
- DeduplicatorProperties props;
-
-
- @Before
- public void setup() throws IOException {
- // Load test files from resources
-
- // Reference MAP
- inputProcessedMapWkt1 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json")));
-
- // Duplicate of Number 1
- inputProcessedMapWkt2 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json")));
-
- // A different Message entirely
- inputProcessedMapWkt3 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json")));
-
- // Message 1 but 1 hour later
- inputProcessedMapWkt4 = new String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json")));
- }
-
-
- @Test
- public void testTopology() {
-
- props = new DeduplicatorProperties();
- props.setKafkaTopicProcessedMapWKT(inputTopic);
- props.setKafkaTopicDeduplicatedProcessedMapWKT(outputTopic);
-
- ProcessedMapWktDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapWktDeduplicatorTopology(props, null);
-
- Topology topology = processedMapDeduplicatorTopology.buildTopology();
- objectMapper.registerModule(new JavaTimeModule());
-
- try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputProcessedMapData = driver.createInputTopic(
- inputTopic,
- Serdes.String().serializer(),
- Serdes.String().serializer());
-
-
- TestOutputTopic> outputProcessedMapData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- JsonSerdes.ProcessedMapWKT().deserializer());
-
- inputProcessedMapData.pipeInput(key, inputProcessedMapWkt1);
- inputProcessedMapData.pipeInput(key, inputProcessedMapWkt2);
- inputProcessedMapData.pipeInput(key, inputProcessedMapWkt3);
- inputProcessedMapData.pipeInput(key, inputProcessedMapWkt4);
-
- List>> mapDeduplicatorResults = outputProcessedMapData.readKeyValuesToList();
-
- // validate that only 3 messages make it through
- assertEquals(3, mapDeduplicatorResults.size());
-
- ProcessedMap map1 = objectMapper.readValue(inputProcessedMapWkt1, typeReference);
- ProcessedMap map2 = objectMapper.readValue(inputProcessedMapWkt2, typeReference);
- ProcessedMap map4 = objectMapper.readValue(inputProcessedMapWkt4, typeReference);
-
- assertEquals(map1.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(0).value.getProperties().getOdeReceivedAt());
- assertEquals(map2.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(1).value.getProperties().getOdeReceivedAt());
- assertEquals(map4.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt());
-
-
-
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- }
-}
+// } catch (JsonMappingException e) {
+// e.printStackTrace();
+// } catch (JsonProcessingException e) {
+// e.printStackTrace();
+// }
+// }
+// }
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java
index dc54e47..1ef5442 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java
@@ -1,117 +1,302 @@
-package us.dot.its.jpo.deduplicator.deduplicator;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KeyValue;
-import org.apache.kafka.streams.TestInputTopic;
-import org.apache.kafka.streams.TestOutputTopic;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.TopologyTestDriver;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
-import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
-import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.List;
-
-
-public class ProcessedSpatDeduplicatorTopologyTest {
-
- String inputTopic = "topic.ProcessedSpat";
- String outputTopic = "topic.DeduplicatedProcessedSpat";
-
-
- TypeReference typeReference = new TypeReference<>(){};
- ObjectMapper objectMapper = new ObjectMapper();
-
- // Reference Message
- String inputProcessedSpat1 = "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:04:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp: is missing but it is required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:04:35.176Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
- // Deduplicated Message - Same as Reference.
- String inputProcessedSpat2 = "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp: is missing but it is required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:04:35.276Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
- // Fast forward 1 minute
- String inputProcessedSpat3 = "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:57.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp: is missing but it is required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:36.376Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
- // Remove a Signal Group
- String inputProcessedSpat4 = "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp: is missing but it is required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:36.496Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
- // Change the ID of a Signal Group
- String inputProcessedSpat5 = "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp: is missing but it is required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:35.576Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":7,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
- // Change the Light State of one of the Signal Groups
- String inputProcessedSpat6 = "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp: is missing but it is required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime: is missing but it is required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:35.676Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
- String key = "{\"rsuId\": \"10.164.6.16\", \"intersectionId\": 6311, \"region\": -1}";
-
- @Autowired
- DeduplicatorProperties props;
-
-
- @Test
- public void testTopology() {
-
- props = new DeduplicatorProperties();
- props.setKafkaTopicProcessedSpat(inputTopic);
- props.setKafkaTopicDeduplicatedProcessedSpat(outputTopic);
-
- ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new ProcessedSpatDeduplicatorTopology(props, null);
-
- Topology topology = processedSpatDeduplicatorTopology.buildTopology();
- objectMapper.registerModule(new JavaTimeModule());
-
- try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
- TestInputTopic inputProcessedSpatData = driver.createInputTopic(
- inputTopic,
- Serdes.String().serializer(),
- Serdes.String().serializer());
-
-
- TestOutputTopic outputProcessedSpatData = driver.createOutputTopic(
- outputTopic,
- Serdes.String().deserializer(),
- JsonSerdes.ProcessedSpat().deserializer());
-
- inputProcessedSpatData.pipeInput(key, inputProcessedSpat1);
- inputProcessedSpatData.pipeInput(key, inputProcessedSpat2);
- inputProcessedSpatData.pipeInput(key, inputProcessedSpat3);
- inputProcessedSpatData.pipeInput(key, inputProcessedSpat4);
- inputProcessedSpatData.pipeInput(key, inputProcessedSpat5);
- inputProcessedSpatData.pipeInput(key, inputProcessedSpat6);
-
- List> spatDeduplicatorResults = outputProcessedSpatData.readKeyValuesToList();
-
- // validate that only 5 messages make it through
- assertEquals(5, spatDeduplicatorResults.size());
-
- ProcessedSpat spat1 = objectMapper.readValue(inputProcessedSpat1, typeReference);
- ProcessedSpat spat3 = objectMapper.readValue(inputProcessedSpat3, typeReference); // forwarded because the time on the message changes by 1 minute
- ProcessedSpat spat4 = objectMapper.readValue(inputProcessedSpat4, typeReference); // forwarded because the signal state changes
- ProcessedSpat spat5 = objectMapper.readValue(inputProcessedSpat5, typeReference); // forwarded because the number of signal groups changed
- ProcessedSpat spat6 = objectMapper.readValue(inputProcessedSpat6, typeReference); // forwarded because a signal group ID changed
-
- assertEquals(spat1.getUtcTimeStamp(), spatDeduplicatorResults.get(0).value.getUtcTimeStamp());
- assertEquals(spat3.getUtcTimeStamp(), spatDeduplicatorResults.get(1).value.getUtcTimeStamp());
- assertEquals(spat4.getUtcTimeStamp(), spatDeduplicatorResults.get(2).value.getUtcTimeStamp());
- assertEquals(spat5.getUtcTimeStamp(), spatDeduplicatorResults.get(3).value.getUtcTimeStamp());
- assertEquals(spat6.getUtcTimeStamp(), spatDeduplicatorResults.get(4).value.getUtcTimeStamp());
-
-
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- }
-}
+// package us.dot.its.jpo.deduplicator.deduplicator;
+
+// import org.apache.kafka.common.serialization.Serdes;
+// import org.apache.kafka.streams.KeyValue;
+// import org.apache.kafka.streams.TestInputTopic;
+// import org.apache.kafka.streams.TestOutputTopic;
+// import org.apache.kafka.streams.Topology;
+// import org.apache.kafka.streams.TopologyTestDriver;
+// import org.junit.Test;
+// import org.springframework.beans.factory.annotation.Autowired;
+
+// import com.fasterxml.jackson.core.JsonProcessingException;
+// import com.fasterxml.jackson.core.type.TypeReference;
+// import com.fasterxml.jackson.databind.JsonMappingException;
+// import com.fasterxml.jackson.databind.ObjectMapper;
+// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+// import
+// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
+// import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
+// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+// import static org.junit.jupiter.api.Assertions.assertEquals;
+
+// import java.util.List;
+
+// public class ProcessedSpatDeduplicatorTopologyTest {
+
+// String inputTopic = "topic.ProcessedSpat";
+// String outputTopic = "topic.DeduplicatedProcessedSpat";
+
+// TypeReference typeReference = new TypeReference<>(){};
+// ObjectMapper objectMapper = new ObjectMapper();
+
+// // Reference Message
+// String inputProcessedSpat1 =
+// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:04:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:04:35.176Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
+
+// // Deduplicated Message - Same as Reference.
+// String inputProcessedSpat2 =
+// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:04:35.276Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
+
+// // Fast forward 1 minute
+// String inputProcessedSpat3 =
+// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:57.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:36.376Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
+
+// // Remove a Signal Group
+// String inputProcessedSpat4 =
+// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:36.496Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
+
+// // Change the ID of a Signal Group
+// String inputProcessedSpat5 =
+// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:35.576Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":7,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
+
+// // Change the Light State of one of the Signal Groups
+// String inputProcessedSpat6 =
+// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
+// is missing but it is
+// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:35.676Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
+
+// String key = "{\"rsuId\": \"10.164.6.16\", \"intersectionId\": 6311,
+// \"region\": -1}";
+
+// @Autowired
+// DeduplicatorProperties props;
+
+// @Test
+// public void testTopology() {
+
+// props = new DeduplicatorProperties();
+// props.setKafkaTopicProcessedSpat(inputTopic);
+// props.setKafkaTopicDeduplicatedProcessedSpat(outputTopic);
+
+// ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new
+// ProcessedSpatDeduplicatorTopology(props, null);
+
+// Topology topology = processedSpatDeduplicatorTopology.buildTopology();
+// objectMapper.registerModule(new JavaTimeModule());
+
+// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+// TestInputTopic inputProcessedSpatData =
+// driver.createInputTopic(
+// inputTopic,
+// Serdes.String().serializer(),
+// Serdes.String().serializer());
+
+// TestOutputTopic outputProcessedSpatData =
+// driver.createOutputTopic(
+// outputTopic,
+// Serdes.String().deserializer(),
+// JsonSerdes.ProcessedSpat().deserializer());
+
+// inputProcessedSpatData.pipeInput(key, inputProcessedSpat1);
+// inputProcessedSpatData.pipeInput(key, inputProcessedSpat2);
+// inputProcessedSpatData.pipeInput(key, inputProcessedSpat3);
+// inputProcessedSpatData.pipeInput(key, inputProcessedSpat4);
+// inputProcessedSpatData.pipeInput(key, inputProcessedSpat5);
+// inputProcessedSpatData.pipeInput(key, inputProcessedSpat6);
+
+// List> spatDeduplicatorResults =
+// outputProcessedSpatData.readKeyValuesToList();
+
+// // validate that only 5 messages make it through
+// assertEquals(5, spatDeduplicatorResults.size());
+
+// ProcessedSpat spat1 = objectMapper.readValue(inputProcessedSpat1,
+// typeReference);
+// ProcessedSpat spat3 = objectMapper.readValue(inputProcessedSpat3,
+// typeReference); // forwarded because the time on the message changes by 1
+// minute
+// ProcessedSpat spat4 = objectMapper.readValue(inputProcessedSpat4,
+// typeReference); // forwarded because the signal state changes
+// ProcessedSpat spat5 = objectMapper.readValue(inputProcessedSpat5,
+// typeReference); // forwarded because the number of signal groups changed
+// ProcessedSpat spat6 = objectMapper.readValue(inputProcessedSpat6,
+// typeReference); // forwarded because a signal group ID changed
+
+// assertEquals(spat1.getUtcTimeStamp(),
+// spatDeduplicatorResults.get(0).value.getUtcTimeStamp());
+// assertEquals(spat3.getUtcTimeStamp(),
+// spatDeduplicatorResults.get(1).value.getUtcTimeStamp());
+// assertEquals(spat4.getUtcTimeStamp(),
+// spatDeduplicatorResults.get(2).value.getUtcTimeStamp());
+// assertEquals(spat5.getUtcTimeStamp(),
+// spatDeduplicatorResults.get(3).value.getUtcTimeStamp());
+// assertEquals(spat6.getUtcTimeStamp(),
+// spatDeduplicatorResults.get(4).value.getUtcTimeStamp());
+
+// } catch (JsonMappingException e) {
+// e.printStackTrace();
+// } catch (JsonProcessingException e) {
+// e.printStackTrace();
+// }
+// }
+// }
From 6c6bbf9494a82e9b611f703ebdd99cf36bbb0a41 Mon Sep 17 00:00:00 2001
From: Michael7371 <40476797+Michael7371@users.noreply.github.com>
Date: Thu, 3 Jul 2025 18:23:33 -0600
Subject: [PATCH 03/24] updates to fix build
---
Dockerfile | 4 +---
jpo-deduplicator/pom.xml | 10 ++++++++++
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 49e558c..ef57571 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -27,19 +27,17 @@ FROM amazoncorretto:21
WORKDIR /home
COPY --from=builder /home/jpo-deduplicator/src/main/resources/application.yaml /home
-COPY --from=builder /home/jpo-deduplicator/src/main/resources/logback.xml /home
COPY --from=builder /home/jpo-deduplicator/target/jpo-deduplicator.jar /home
#COPY cert.crt /home/cert.crt
#RUN keytool -import -trustcacerts -keystore /usr/local/openjdk-11/lib/security/cacerts -storepass changeit -noprompt -alias mycert -file cert.crt
RUN amazon-linux-extras install -y epel && \
- yum install -y jemalloc-devel
+ yum install -y jemalloc-devel
ENV LD_PRELOAD="/usr/lib64/libjemalloc.so"
ENTRYPOINT ["java", \
"-Djava.rmi.server.hostname=$DOCKER_HOST_IP", \
- "-Dlogback.configurationFile=/home/logback.xml", \
"-Xmx1024M", \
"-Xms128M", \
"-XX:+UseG1GC", \
diff --git a/jpo-deduplicator/pom.xml b/jpo-deduplicator/pom.xml
index 24861c5..02f789e 100644
--- a/jpo-deduplicator/pom.xml
+++ b/jpo-deduplicator/pom.xml
@@ -115,6 +115,16 @@
usdot.jpo.ode
jpo-geojsonconverter
${jpo.geojsonconverter.version}
+
+
+ usdot.jpo.ode
+ jpo-ode-core
+
+
+ usdot.jpo.ode
+ jpo-ode-plugins
+
+
junit
From 2124e6d914b2485cb86e98365f3bda4931cdad8a Mon Sep 17 00:00:00 2001
From: Michael7371 <40476797+Michael7371@users.noreply.github.com>
Date: Tue, 15 Jul 2025 15:51:51 -0600
Subject: [PATCH 04/24] updates to ODE MAP deduplicator topologies
---
.../DeduplicatorServiceController.java | 16 +-
.../processors/OdeMapJsonProcessor.java | 167 +-
.../OdeMapJsonProcessorSupplier.java | 37 +-
.../topologies/MapDeduplicatorTopology.java | 278 +-
.../MapDeduplicatorTopologyTest.java | 261 +-
.../ode_map/sample.ode-map-different.json | 1063 ++-----
...sample.ode-map-reference-1-hour-later.json | 2814 -----------------
.../ode_map/sample.ode-map-reference.json | 1888 +++--------
8 files changed, 1075 insertions(+), 5449 deletions(-)
delete mode 100644 jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
index 6055e39..927e493 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
@@ -14,7 +14,7 @@
import lombok.Getter;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.BsmDeduplicatorTopology;
-// import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.TimDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.OdeRawEncodedTimDeduplicatorTopology;
// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
@@ -59,15 +59,11 @@ public DeduplicatorServiceController(final DeduplicatorProperties props,
// processedMapWktDeduplicatorTopology.start();
// }
- // if(props.isEnableProcessedMapDeduplication()){
- // logger.info("Starting Map Deduplicator");
- // MapDeduplicatorTopology mapDeduplicatorTopology = new
- // MapDeduplicatorTopology(
- // props,
- // props.createStreamProperties("MapDeduplicator")
- // );
- // mapDeduplicatorTopology.start();
- // }
+ if (props.isEnableOdeMapDeduplication()) {
+ logger.info("Starting Map Deduplicator");
+ MapDeduplicatorTopology mapDeduplicatorTopology = new MapDeduplicatorTopology(props);
+ mapDeduplicatorTopology.start();
+ }
// if (props.isEnableOdeTimDeduplication()) {
// logger.info("Starting Tim Deduplicator");
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java
index a95bae6..cc631d3 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeMapJsonProcessor.java
@@ -1,78 +1,89 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.processors;
-
-// import java.time.Duration;
-// import java.time.Instant;
-// import java.time.format.DateTimeFormatter;
-// import java.util.Objects;
-
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import us.dot.its.jpo.ode.model.OdeMapData;
-// import us.dot.its.jpo.ode.model.OdeMapMetadata;
-// import us.dot.its.jpo.ode.model.OdeMapPayload;
-
-// public class OdeMapJsonProcessor extends DeduplicationProcessor{
-
-// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-
-// DeduplicatorProperties props;
-
-// private static final Logger logger =
-// LoggerFactory.getLogger(OdeMapJsonProcessor.class);
-
-// public OdeMapJsonProcessor(DeduplicatorProperties props){
-// this.props = props;
-// this.storeName = props.getKafkaStateStoreOdeMapJsonName();
-// }
-
-// @Override
-// public Instant getMessageTime(OdeMapData message) {
-// try {
-// String time = ((OdeMapMetadata)message.getMetadata()).getOdeReceivedAt();
-// return Instant.from(formatter.parse(time));
-// } catch (Exception e) {
-// return Instant.ofEpochMilli(0);
-// }
-// }
-
-// @Override
-// public boolean isDuplicate(OdeMapData lastMessage, OdeMapData newMessage) {
-// try{
-// Instant newValueTime = getMessageTime(newMessage);
-// Instant oldValueTime = getMessageTime(lastMessage);
-
-// if(newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)){
-// return false;
-
-// }else{
-// OdeMapPayload oldPayload = (OdeMapPayload)lastMessage.getPayload();
-// OdeMapPayload newPayload = (OdeMapPayload)newMessage.getPayload();
-
-// Integer oldTimestamp = oldPayload.getMap().getTimeStamp();
-// Integer newTimestamp = newPayload.getMap().getTimeStamp();
-
-// newPayload.getMap().setTimeStamp(oldTimestamp);
-
-// int oldHash = hashMapMessage(lastMessage);
-// int newhash = hashMapMessage(newMessage);
-
-// if(oldHash != newhash){
-// newPayload.getMap().setTimeStamp(newTimestamp);
-// return false;
-// }
-// }
-// } catch(Exception e){
-// logger.warn("Caught General Exception" + e);
-// }
-
-// return true;
-// }
-
-// public int hashMapMessage(OdeMapData map){
-// OdeMapPayload payload = (OdeMapPayload)map.getPayload();
-// return Objects.hash(payload.toJson());
-
-// }
-// }
+package us.dot.its.jpo.deduplicator.deduplicator.processors;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
+import us.dot.its.jpo.asn.j2735.r2024.MapData.MapDataMessageFrame;
+
+public class OdeMapJsonProcessor extends DeduplicationProcessor {
+
+ DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+ DeduplicatorProperties props;
+
+ private static final Logger logger = LoggerFactory.getLogger(OdeMapJsonProcessor.class);
+
+ public OdeMapJsonProcessor(String storeName, DeduplicatorProperties props) {
+ this.storeName = storeName;
+ this.props = props;
+ }
+
+ @Override
+ public Instant getMessageTime(OdeMessageFrameData message) {
+ try {
+ if (message == null || message.getMetadata() == null) {
+ logger.warn("Map message or metadata is null, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
+ String time = ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt();
+ if (time == null || time.isEmpty()) {
+ logger.warn("Map message has null or empty odeReceivedAt time, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
+ return Instant.from(formatter.parse(time));
+ } catch (Exception e) {
+ logger.warn("Failed to parse time from Map: " + (message != null && message.getMetadata() != null
+ ? ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt()
+ : "null"), e);
+ return Instant.ofEpochMilli(0);
+ }
+ }
+
+ @Override
+ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData newMessage) {
+ try {
+ Instant newValueTime = getMessageTime(newMessage);
+ Instant oldValueTime = getMessageTime(lastMessage);
+
+ // If the messages are more than an hour apart, forward the new message on
+ if (newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)) {
+ return false;
+ }
+
+ // Add null checks for payload and data
+ if (lastMessage == null || lastMessage.getPayload() == null || lastMessage.getPayload().getData() == null ||
+ newMessage == null || newMessage.getPayload() == null
+ || newMessage.getPayload().getData() == null) {
+ logger.warn("One or both Map messages have null payload or data, treating as non-duplicate");
+ return false;
+ }
+
+ MapDataMessageFrame oldMap = (MapDataMessageFrame) lastMessage.getPayload().getData();
+ MapDataMessageFrame newMap = (MapDataMessageFrame) newMessage.getPayload().getData();
+
+ // Compare map data for equality
+ if (oldMap == null || newMap == null || oldMap.getValue() == null || newMap.getValue() == null) {
+ return false;
+ }
+
+ // For now, treat maps as duplicates if they have the same intersection ID and
+ // are within the time window
+ // This is a simplified approach - in a real implementation you might want to
+ // compare more map properties
+ return true;
+
+ } catch (Exception e) {
+ logger.warn("Caught General Exception while checking Map duplicates: " + e.getMessage(), e);
+ }
+
+ return true;
+ }
+}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java
index 7b0c2fd..4d7628f 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeMapJsonProcessorSupplier.java
@@ -1,24 +1,25 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers;
+package us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers;
-// import org.apache.kafka.streams.processor.api.Processor;
-// import org.apache.kafka.streams.processor.api.ProcessorSupplier;
+import org.apache.kafka.streams.processor.api.Processor;
+import org.apache.kafka.streams.processor.api.ProcessorSupplier;
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.processors.OdeMapJsonProcessor;
-// import us.dot.its.jpo.ode.model.OdeMapData;
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.processors.OdeMapJsonProcessor;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
-// public class OdeMapJsonProcessorSupplier implements ProcessorSupplier {
+public class OdeMapJsonProcessorSupplier
+ implements ProcessorSupplier {
-// DeduplicatorProperties props;
+ private String storeName;
+ private DeduplicatorProperties props;
-// public OdeMapJsonProcessorSupplier(DeduplicatorProperties props) {
-// this.props = props;
-// }
+ public OdeMapJsonProcessorSupplier(String storeName, DeduplicatorProperties props) {
+ this.storeName = storeName;
+ this.props = props;
+ }
-// @Override
-// public Processor get() {
-// return new OdeMapJsonProcessor(props);
-// }
-// }
\ No newline at end of file
+ @Override
+ public Processor get() {
+ return new OdeMapJsonProcessor(storeName, props);
+ }
+}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
index 957ad33..b1cd07f 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
@@ -1,136 +1,142 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KafkaStreams;
-// import org.apache.kafka.streams.StreamsBuilder;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.KafkaStreams.StateListener;
-// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeMapJsonProcessorSupplier;
-// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-// import us.dot.its.jpo.geojsonconverter.partitioner.RsuIntersectionKey;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import us.dot.its.jpo.ode.model.OdeMapData;
-// import us.dot.its.jpo.ode.model.OdeMapMetadata;
-// import us.dot.its.jpo.ode.model.OdeMapPayload;
-// import us.dot.its.jpo.ode.plugin.j2735.J2735IntersectionReferenceID;
-
-// import org.apache.kafka.streams.kstream.*;
-// import org.apache.kafka.streams.state.Stores;
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-
-// import com.fasterxml.jackson.databind.ObjectMapper;
-
-// import java.time.Instant;
-// import java.time.format.DateTimeFormatter;
-// import java.util.Objects;
-// import java.util.Properties;
-
-// public class MapDeduplicatorTopology {
-
-// private static final Logger logger =
-// LoggerFactory.getLogger(MapDeduplicatorTopology.class);
-
-// Topology topology;
-// KafkaStreams streams;
-// String inputTopic;
-// String outputTopic;
-// Properties streamsProperties;
-// ObjectMapper objectMapper;
-// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-// DeduplicatorProperties props;
-
-// public MapDeduplicatorTopology(DeduplicatorProperties props, Properties
-// streamsProperties) {
-// this.props = props;
-// this.streamsProperties = streamsProperties;
-// this.objectMapper = DateJsonMapper.getInstance();
-// }
-
-// public void start() {
-// if (streams != null && streams.state().isRunningOrRebalancing()) {
-// throw new IllegalStateException("Start called while streams is already
-// running.");
-// }
-// Topology topology = buildTopology();
-// streams = new KafkaStreams(topology, streamsProperties);
-// if (exceptionHandler != null)
-// streams.setUncaughtExceptionHandler(exceptionHandler);
-// if (stateListener != null)
-// streams.setStateListener(stateListener);
-// logger.info("Starting Map Deduplicator Topology");
-// streams.start();
-// }
-
-// public Instant getInstantFromMap(OdeMapData map) {
-// String time = ((OdeMapMetadata) map.getMetadata()).getOdeReceivedAt();
-
-// return Instant.from(formatter.parse(time));
-// }
-
-// public int hashMapMessage(OdeMapData map) {
-// OdeMapPayload payload = (OdeMapPayload) map.getPayload();
-// return Objects.hash(payload.toJson());
-
-// }
-
-// public Topology buildTopology() {
-// StreamsBuilder builder = new StreamsBuilder();
-
-// KStream inputStream =
-// builder.stream(props.getKafkaTopicOdeMapJson(),
-// Consumed.with(Serdes.Void(), JsonSerdes.OdeMap()));
-
-// builder.addStateStore(
-// Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeMapJsonName()),
-// Serdes.String(), JsonSerdes.OdeMap()));
-
-// KStream mapRekeyedStream = inputStream.selectKey((key,
-// value) -> {
-// J2735IntersectionReferenceID intersectionId = ((OdeMapPayload)
-// value.getPayload()).getMap()
-// .getIntersections().getIntersections().get(0).getId();
-// RsuIntersectionKey newKey = new RsuIntersectionKey();
-// newKey.setRsuId(((OdeMapMetadata) value.getMetadata()).getOriginIp());
-// newKey.setIntersectionReferenceID(intersectionId);
-// return newKey.toString();
-// }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMap()));
-
-// KStream deduplicatedStream = mapRekeyedStream
-// .process(new OdeMapJsonProcessorSupplier(props),
-// props.getKafkaStateStoreOdeMapJsonName());
-
-// deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeMapJson(),
-// Produced.with(Serdes.String(), JsonSerdes.OdeMap()));
-
-// return builder.build();
-
-// }
-
-// public void stop() {
-// logger.info("Stopping Map Deduplicator Socket Broadcast Topology.");
-// if (streams != null) {
-// streams.close();
-// streams.cleanUp();
-// streams = null;
-// }
-// logger.info("Stopped Map Deduplicator Socket Broadcast Topology.");
-// }
-
-// StateListener stateListener;
-
-// public void registerStateListener(StateListener stateListener) {
-// this.stateListener = stateListener;
-// }
-
-// StreamsUncaughtExceptionHandler exceptionHandler;
-
-// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
-// exceptionHandler) {
-// this.exceptionHandler = exceptionHandler;
-// }
-// }
+package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KafkaStreams;
+import org.apache.kafka.streams.StreamsBuilder;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.KafkaStreams.StateListener;
+import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
+
+import org.apache.kafka.streams.kstream.*;
+import org.apache.kafka.streams.state.Stores;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeMapJsonProcessorSupplier;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
+
+public class MapDeduplicatorTopology {
+
+ private static final Logger logger = LoggerFactory.getLogger(MapDeduplicatorTopology.class);
+
+ Topology topology;
+ KafkaStreams streams;
+ DeduplicatorProperties props;
+ ObjectMapper objectMapper;
+ DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+
+ public MapDeduplicatorTopology(DeduplicatorProperties props) {
+ this.props = props;
+ this.objectMapper = DateJsonMapper.getInstance();
+ }
+
+ public void start() {
+ if (streams != null && streams.state().isRunningOrRebalancing()) {
+ throw new IllegalStateException("Start called while streams is already running.");
+ }
+ Topology topology = buildTopology();
+ streams = new KafkaStreams(topology, props.createStreamProperties("MapDeduplicator"));
+ if (exceptionHandler != null)
+ streams.setUncaughtExceptionHandler(exceptionHandler);
+ if (stateListener != null)
+ streams.setStateListener(stateListener);
+ logger.info("Starting Map Deduplicator Topology");
+ streams.start();
+ }
+
+ // public Instant getInstantFromMap(OdeMessageFrameData map) {
+ // try {
+ // if (map == null || map.getMetadata() == null) {
+ // logger.warn("Map message or metadata is null, using epoch time");
+ // return Instant.ofEpochMilli(0);
+ // }
+
+ // String time = ((OdeMessageFrameMetadata)
+ // map.getMetadata()).getOdeReceivedAt();
+ // if (time == null || time.isEmpty()) {
+ // logger.warn("Map message has null or empty odeReceivedAt time, using epoch
+ // time");
+ // return Instant.ofEpochMilli(0);
+ // }
+
+ // return Instant.from(formatter.parse(time));
+ // } catch (Exception e) {
+ // logger.warn("Failed to parse time from Map: " + (map != null &&
+ // map.getMetadata() != null
+ // ? ((OdeMessageFrameMetadata) map.getMetadata()).getOdeReceivedAt()
+ // : "null"), e);
+ // return Instant.ofEpochMilli(0);
+ // }
+ // }
+
+ public Topology buildTopology() {
+ StreamsBuilder builder = new StreamsBuilder();
+
+ KStream inputStream = builder.stream(props.getKafkaTopicOdeMapJson(),
+ Consumed.with(Serdes.Void(), JsonSerdes.OdeMessageFrame()));
+
+ builder.addStateStore(
+ Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeMapJsonName()),
+ Serdes.String(), JsonSerdes.OdeMessageFrame()));
+
+ KStream mapRekeyedStream = inputStream.selectKey((key, value) -> {
+ try {
+ if (value == null || value.getPayload() == null || value.getPayload().getData() == null) {
+ logger.warn("Received Map message with null payload or data, using default key");
+ return "unknown";
+ }
+
+ // For now, use a simple key based on RSU IP and timestamp
+ // This can be enhanced later with proper intersection ID extraction
+ String rsuIp = ((OdeMessageFrameMetadata) value.getMetadata()).getOriginIp();
+ String timestamp = ((OdeMessageFrameMetadata) value.getMetadata()).getOdeReceivedAt();
+ return rsuIp + "_" + timestamp;
+ } catch (Exception e) {
+ logger.error("Error extracting key from Map message: " + e.getMessage(), e);
+ return "unknown";
+ }
+ }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
+
+ KStream deduplicatedStream = mapRekeyedStream.process(
+ new OdeMapJsonProcessorSupplier(props.getKafkaStateStoreOdeMapJsonName(), props),
+ props.getKafkaStateStoreOdeMapJsonName());
+
+ deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeMapJson(),
+ Produced.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
+
+ return builder.build();
+
+ }
+
+ public void stop() {
+ logger.info("Stopping Map Deduplicator Socket Broadcast Topology.");
+ if (streams != null) {
+ streams.close();
+ streams.cleanUp();
+ streams = null;
+ }
+ logger.info("Stopped Map Deduplicator Socket Broadcast Topology.");
+ }
+
+ StateListener stateListener;
+
+ public void registerStateListener(StateListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ StreamsUncaughtExceptionHandler exceptionHandler;
+
+ public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
index 219aee4..8752c6f 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
@@ -1,120 +1,141 @@
-// package us.dot.its.jpo.deduplicator.deduplicator;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KeyValue;
-// import org.apache.kafka.streams.TestInputTopic;
-// import org.apache.kafka.streams.TestOutputTopic;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.TopologyTestDriver;
-// import org.junit.Before;
-// import org.junit.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
-
-// import com.fasterxml.jackson.core.JsonProcessingException;
-// import com.fasterxml.jackson.databind.JsonMappingException;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import us.dot.its.jpo.ode.model.OdeMapData;
-// import static org.junit.jupiter.api.Assertions.assertEquals;
-
-// import java.io.IOException;
-// import java.nio.file.Files;
-// import java.nio.file.Paths;
-// import java.util.List;
-
-// public class MapDeduplicatorTopologyTest {
-
-// String inputTopic = "topic.OdeMapJson";
-// String outputTopic = "topic.DeduplicatedOdeMapJson";
-// ObjectMapper objectMapper;
-
-// String inputMap1 = "";
-// String inputMap2 = "";
-// String inputMap3 = "";
-// String inputMap4 = "";
-
-// @Autowired
-// DeduplicatorProperties props;
-
-// @Before
-// public void setup() throws IOException {
-// // Load test files from resources
-
-// // Reference MAP
-// inputMap1 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
-
-// // Duplicate of Number 1
-// inputMap2 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
-
-// // A different Message entirely
-// inputMap3 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-different.json")));
-
-// // Message 1 but 1 hour later
-// inputMap4 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json")));
-// }
-
-// @Test
-// public void testTopology() {
-
-// props = new DeduplicatorProperties();
-// props.setKafkaTopicOdeMapJson(inputTopic);
-// props.setKafkaTopicDeduplicatedOdeMapJson(outputTopic);
-
-// MapDeduplicatorTopology mapDeduplicatorTopology = new
-// MapDeduplicatorTopology(props, null);
-
-// Topology topology = mapDeduplicatorTopology.buildTopology();
-
-// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-// TestInputTopic inputOdeMapData = driver.createInputTopic(
-// inputTopic,
-// Serdes.Void().serializer(),
-// Serdes.String().serializer());
-
-// TestOutputTopic outputOdeMapData =
-// driver.createOutputTopic(
-// outputTopic,
-// Serdes.String().deserializer(),
-// JsonSerdes.OdeMap().deserializer());
-
-// inputOdeMapData.pipeInput(null, inputMap1);
-// inputOdeMapData.pipeInput(null, inputMap2);
-// inputOdeMapData.pipeInput(null, inputMap3);
-// inputOdeMapData.pipeInput(null, inputMap4);
-
-// List> mapDeduplicationResults =
-// outputOdeMapData.readKeyValuesToList();
-
-// // validate that only 3 messages make it through
-// assertEquals(3, mapDeduplicationResults.size());
-
-// objectMapper = new ObjectMapper();
-// OdeMapData map1 = objectMapper.readValue(inputMap1, OdeMapData.class);
-// OdeMapData map3 = objectMapper.readValue(inputMap3, OdeMapData.class);
-// OdeMapData map4 = objectMapper.readValue(inputMap4, OdeMapData.class);
-
-// assertEquals(map1.getMetadata().getOdeReceivedAt(),
-// mapDeduplicationResults.get(0).value.getMetadata().getOdeReceivedAt());
-// assertEquals(map3.getMetadata().getOdeReceivedAt(),
-// mapDeduplicationResults.get(1).value.getMetadata().getOdeReceivedAt());
-// assertEquals(map4.getMetadata().getOdeReceivedAt(),
-// mapDeduplicationResults.get(2).value.getMetadata().getOdeReceivedAt());
-
-// } catch (JsonMappingException e) {
-// // TODO Auto-generated catch block
-// e.printStackTrace();
-// } catch (JsonProcessingException e) {
-// // TODO Auto-generated catch block
-// e.printStackTrace();
-// }
-// }
-// }
\ No newline at end of file
+package us.dot.its.jpo.deduplicator.deduplicator;
+
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KeyValue;
+import org.apache.kafka.streams.TestInputTopic;
+import org.apache.kafka.streams.TestOutputTopic;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.TopologyTestDriver;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
+import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+
+public class MapDeduplicatorTopologyTest {
+
+ String inputTopic = "topic.OdeMapJson";
+ String outputTopic = "topic.DeduplicatedOdeMapJson";
+ ObjectMapper objectMapper;
+
+ String inputMap1 = "";
+ String inputMap2 = "";
+ String inputMap4 = "";
+ String inputMap5 = "";
+ String inputMap3 = "";
+
+ @Autowired
+ DeduplicatorProperties props;
+
+ @Before
+ public void setup() throws IOException {
+ objectMapper = new ObjectMapper();
+
+ // Load test files from resources
+ // Reference MAP
+ String mapReference = new String(
+ Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-reference.json")));
+ OdeMessageFrameData mapReferenceData = objectMapper.readValue(mapReference, OdeMessageFrameData.class);
+
+ inputMap1 = mapReferenceData.toJson();
+
+ // Duplicate of Number 1 - should be deduplicated
+ inputMap2 = mapReferenceData.toJson();
+
+ // Message 1 but 5 minutes later - should be deduplicated
+ OdeMessageFrameData map5MinutesLater = objectMapper.readValue(mapReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ String originalTime = mapReferenceData.getMetadata().getOdeReceivedAt();
+ Instant instant = Instant.parse(originalTime);
+ Instant newInstant = instant.plus(5, ChronoUnit.MINUTES);
+ map5MinutesLater.getMetadata().setOdeReceivedAt(newInstant.toString());
+ inputMap3 = map5MinutesLater.toJson();
+
+ // A different Message entirely - should be kept
+ String mapDifferent = new String(
+ Files.readAllBytes(Paths.get("src/test/resources/json/ode_map/sample.ode-map-different.json")));
+ OdeMessageFrameData mapDifferentData = objectMapper.readValue(mapDifferent, OdeMessageFrameData.class);
+ inputMap4 = mapDifferentData.toJson();
+
+ // Message 1 but 1 hour later - should be kept
+ OdeMessageFrameData map1HourLater = objectMapper.readValue(mapReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ originalTime = map1HourLater.getMetadata().getOdeReceivedAt();
+ instant = Instant.parse(originalTime);
+ newInstant = instant.plus(1, ChronoUnit.HOURS);
+ map1HourLater.getMetadata().setOdeReceivedAt(newInstant.toString());
+ inputMap5 = map1HourLater.toJson();
+ }
+
+ @Test
+ public void testTopology() {
+
+ props = new DeduplicatorProperties();
+ props.setKafkaTopicOdeMapJson(inputTopic);
+ props.setKafkaTopicDeduplicatedOdeMapJson(outputTopic);
+
+ MapDeduplicatorTopology mapDeduplicatorTopology = new MapDeduplicatorTopology(props);
+
+ Topology topology = mapDeduplicatorTopology.buildTopology();
+
+ try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+ TestInputTopic inputOdeMapData = driver.createInputTopic(
+ inputTopic,
+ Serdes.Void().serializer(),
+ Serdes.String().serializer());
+
+ TestOutputTopic outputOdeMapData = driver.createOutputTopic(
+ outputTopic,
+ Serdes.String().deserializer(),
+ JsonSerdes.OdeMessageFrame().deserializer());
+
+ inputOdeMapData.pipeInput(null, inputMap1);
+ inputOdeMapData.pipeInput(null, inputMap2);
+ inputOdeMapData.pipeInput(null, inputMap4);
+ inputOdeMapData.pipeInput(null, inputMap5);
+ inputOdeMapData.pipeInput(null, inputMap3);
+
+ List> mapDeduplicationResults = outputOdeMapData
+ .readKeyValuesToList();
+
+ // validate that only 3 messages make it through
+ assertEquals(3, mapDeduplicationResults.size());
+
+ objectMapper = new ObjectMapper();
+ OdeMessageFrameData map1 = objectMapper.readValue(inputMap1, OdeMessageFrameData.class);
+ OdeMessageFrameData map3 = objectMapper.readValue(inputMap4, OdeMessageFrameData.class);
+ OdeMessageFrameData map4 = objectMapper.readValue(inputMap5, OdeMessageFrameData.class);
+
+ assertThat(mapDeduplicationResults.get(0).value.toJson(), jsonEquals(map1.toJson()));
+ assertThat(mapDeduplicationResults.get(1).value.toJson(), jsonEquals(map3.toJson()));
+ assertThat(mapDeduplicationResults.get(2).value.toJson(), jsonEquals(map4.toJson()));
+
+ } catch (JsonMappingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (JsonProcessingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-different.json b/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-different.json
index 9af4acc..35ec34c 100644
--- a/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-different.json
+++ b/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-different.json
@@ -6,16 +6,16 @@
"receivedMessageDetails": {
"rxSource": "NA"
},
- "payloadType": "us.dot.its.jpo.ode.model.OdeMapPayload",
+ "payloadType": "us.dot.its.jpo.ode.model.OdeMessageFramePayload",
"serialId": {
- "streamId": "35ecef57-56ce-44ca-beca-16279d7471e1",
+ "streamId": "5879e404-3479-467b-b95f-4c00e531da97",
"bundleSize": 1,
"bundleId": 0,
"recordId": 0,
"serialNumber": 0
},
- "odeReceivedAt": "2025-01-31T00:00:00.000Z",
- "schemaVersion": 8,
+ "odeReceivedAt": "2025-07-15T21:03:47.721Z",
+ "schemaVersion": 9,
"maxDurationTime": 0,
"recordGeneratedAt": "",
"recordGeneratedBy": "RSU",
@@ -23,81 +23,50 @@
"odePacketID": "",
"odeTimStartDateTime": "",
"asn1": "0012820038033000205EA60D4D383C3B2CA7114251C802DC1C580C68000002000195D3B9FDA4ACED70318D6FAE8119027D9ACA8F03C4050535DEF6012C0A0A0586200020096029A000001C000A574B07DF62B39E40D4B5B99604D809F66B34DC0B5014145673C82726B69A414D013D857A7C81141587C000200AC350001008B0211000000800026BDF34287036E50516257A64D1B0FE52B3C04FB3620E259C809E20581C0003009603A200000100004D7A89855A02828B11C9306ED882C9644027D9B11292E5E04F102C120001804B0255000000400036BFAC42D4814145805684DE2C39D4A22B61F9E55D409F66C3F6CABA813C40B0F40001012C0A540000010000DB01D10B4E050516005E1279B0F892AC804FB361F42566009F66C3B449EC013D80B0E4000101100B6200000001B08A50C0805051601FE042040318800000006C2D042C3014145806E80FD100D6200000000B0E0B09D6D80568102028284039C800000002C42E3FA6960805FE4C403DC800000002C3E33EAA160779FF30B0085000000800032C07ABCE5B5ED2DC8D809EC6B88CABE88139CD6EFD53BB02761ADDC4A69E04E70AC32000080561700004045802280000050001960A91E72DAF618E3A804F635C3D55F2409CE6B761A9B2013B0D6F02536F02738561B000040230F2000210042200000000AECF8F5C257FAA7EBF10032200000000AF07CF58857FAF7ED00142857ED47FFA10072200000001AF1150904050A15FB9A000040208800000006BC4AC2F00142857EE080002C0A3400000200019AFB5D1346050A35FFA6177C0A0A2BFE64464B5FD921F600A0A6BF14443981428D7CF6891302851AF5E11142050A35EED218340A0A058EC00020096049A0000004000ED7C1B896902851AFFE90DCE050535FE5E2E3C0A0A6BFB3C26781414D7E5C883402829AF9911096050A35F57A14CC0A142BE86C25D35F2F610940A0A218412000AC7A000100C60E40004581668000002000135FB8226D80A146BFF1C7C401414D7F3C878202829AFB531352050A02C590001C04B030D000000400036C00BC4E681428D801789A302828AFF8D0F76D7F0E877C02829AFC950CA4050502C554001C0440350800000006C0DD44F88142858000814D100E4200000001B06A713CA050536000205480A0A2C197400000200001B079CED3004F135FF1113200A3205874000400960D3A00000100000D8234765D027B1AFFF08A14051402C360002004B06DD000000400006C0653B22013D8D800A4518028A0160C80006025838E8000002000035FDB1D84C09EC6C003BA14814140B0540003012C187400000080011B13F6EDB804F115FA6DFC10AFC94FC6A57EE07DCE2BFA7BED3B5FFCD72E80A1E018C9000082DA50180060282814420202000",
- "mapSource": "RSU",
- "originIp": "8.8.8.8"
+ "source": "RSU",
+ "originIp": "8.8.8.1",
+ "isCertPresent": false
},
"payload": {
"data": {
- "msgIssueRevision": 3,
- "layerType": "intersectionData",
- "layerID": 0,
- "intersections": {
- "intersectionGeometry": [
- {
- "id": {
- "id": 12115
- },
- "revision": 3,
- "refPoint": {
- "latitude": 39.5531067,
- "longitude": -105.0853565,
- "elevation": 1684.0
- },
- "laneWidth": 366,
- "laneSet": {
- "GenericLane": [
+ "messageId": 18,
+ "value": {
+ "MapData": {
+ "msgIssueRevision": 3,
+ "layerType": "intersectionData",
+ "layerID": 0,
+ "intersections": [
+ {
+ "id": {
+ "id": 12115
+ },
+ "revision": 3,
+ "refPoint": {
+ "lat": 395531067,
+ "long": -1050853565,
+ "elevation": 16840
+ },
+ "laneWidth": 366,
+ "laneSet": [
{
"laneID": 6,
"ingressApproach": 3,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2834,
"y": -151
}
@@ -105,7 +74,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -6293,
"y": 396
}
@@ -113,7 +82,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4178,
"y": 281
}
@@ -124,7 +93,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -6841,
"y": 482
}
@@ -135,7 +104,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2115,
"y": 75
}
@@ -146,84 +115,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 12,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 12,
+ "maneuver": "4000"
+ },
+ "signalGroup": 4,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 5,
"ingressApproach": 3,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "E000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2896,
"y": -522
}
@@ -231,7 +152,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -6340,
"y": 425
}
@@ -239,7 +160,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4507,
"y": 310
}
@@ -250,7 +171,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -6501,
"y": 362
}
@@ -261,7 +182,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -6340,
"y": 626
}
@@ -269,7 +190,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4812,
"y": 666
}
@@ -280,7 +201,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1412,
"y": 276
}
@@ -288,105 +209,44 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 15,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 1
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 15,
+ "maneuver": "8000"
+ },
+ "signalGroup": 4,
+ "connectionID": 1
+ },
+ {
+ "connectingLane": {
+ "lane": 13,
+ "maneuver": "4000"
},
- {
- "connectingLane": {
- "lane": 13,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 2
- }
- ]
- }
+ "signalGroup": 4,
+ "connectionID": 2
+ }
+ ]
},
{
"laneID": 8,
"ingressApproach": 4,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1050,
"y": 1294
}
@@ -398,7 +258,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2398,
"y": 6452
}
@@ -406,7 +266,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2034,
"y": 5534
}
@@ -417,7 +277,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2104,
"y": 5746
}
@@ -428,84 +288,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 3,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 6,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 3,
+ "maneuver": "8000"
+ },
+ "signalGroup": 6,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 7,
"ingressApproach": 4,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1399,
"y": 1370
}
@@ -516,7 +328,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2276,
"y": 6199
}
@@ -524,7 +336,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2092,
"y": 5700
}
@@ -535,7 +347,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2196,
"y": 5935
}
@@ -546,84 +358,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 4,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 6,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 4,
+ "maneuver": "8000"
+ },
+ "signalGroup": 6,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 9,
"ingressApproach": 5,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -168,
"y": 1449
}
@@ -634,7 +398,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 86,
"y": 1246
}
@@ -642,7 +406,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1850,
"y": 5189
}
@@ -650,7 +414,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2023,
"y": 5493
}
@@ -661,7 +425,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2029,
"y": 5493
}
@@ -672,84 +436,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 15,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 1,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 15,
+ "maneuver": "4000"
+ },
+ "signalGroup": 1,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 10,
"ingressApproach": 5,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 232,
"y": 1447
}
@@ -760,7 +476,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 23,
"y": 1182
}
@@ -768,7 +484,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1988,
"y": 5476
}
@@ -779,7 +495,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2000,
"y": 5528
}
@@ -790,7 +506,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1896,
"y": 5080
}
@@ -801,62 +517,27 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 14,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 1,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 14,
+ "maneuver": "4000"
+ },
+ "signalGroup": 1,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 11,
"egressApproach": 6,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -864,7 +545,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1106,
"y": 1540
}
@@ -875,7 +556,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 127,
"y": 264
}
@@ -888,32 +569,12 @@
"laneID": 12,
"egressApproach": 6,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -921,7 +582,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1440,
"y": 1414
}
@@ -932,7 +593,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 110,
"y": 253
}
@@ -945,32 +606,12 @@
"laneID": 13,
"egressApproach": 6,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -978,7 +619,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1797,
"y": 1259
}
@@ -986,7 +627,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 86,
"y": 258
}
@@ -1002,32 +643,12 @@
"laneID": 14,
"egressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1035,7 +656,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2140,
"y": -179
}
@@ -1043,7 +664,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 513,
"y": -109
}
@@ -1056,32 +677,12 @@
"laneID": 15,
"egressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1089,7 +690,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1990,
"y": -684
}
@@ -1097,7 +698,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 478,
"y": -52
}
@@ -1110,54 +711,21 @@
"laneID": 2,
"ingressApproach": 1,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 245,
"y": -1589
}
@@ -1165,7 +733,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1205,
"y": -3530
}
@@ -1176,7 +744,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -3815,
"y": -10287
}
@@ -1187,7 +755,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4355,
"y": -11333
}
@@ -1198,7 +766,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4382,
"y": -11441
}
@@ -1209,105 +777,44 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 12,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 1
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 12,
+ "maneuver": "8000"
+ },
+ "signalGroup": 2,
+ "connectionID": 1
+ },
+ {
+ "connectingLane": {
+ "lane": 11,
+ "maneuver": "8000"
},
- {
- "connectingLane": {
- "lane": 11,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 2
- }
- ]
- }
+ "signalGroup": 2,
+ "connectionID": 2
+ }
+ ]
},
{
"laneID": 1,
"ingressApproach": 1,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "A000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 676,
"y": -1589
}
@@ -1315,7 +822,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1268,
"y": -3628
}
@@ -1326,7 +833,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -3851,
"y": -10295
}
@@ -1337,7 +844,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4413,
"y": -11420
}
@@ -1348,7 +855,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -4350,
"y": -11409
}
@@ -1359,82 +866,34 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 13,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 1
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 13,
+ "maneuver": "8000"
+ },
+ "signalGroup": 2,
+ "connectionID": 1
+ },
+ {
+ "connectingLane": {
+ "lane": 15,
+ "maneuver": "2000"
},
- {
- "connectingLane": {
- "lane": 15,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 2
- }
- ]
- }
+ "connectionID": 2
+ }
+ ]
},
{
"laneID": 4,
"egressApproach": 2,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1442,7 +901,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2436,
"y": -1311
}
@@ -1450,7 +909,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -86,
"y": -321
}
@@ -1463,32 +922,12 @@
"laneID": 3,
"egressApproach": 2,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1496,7 +935,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1986,
"y": -1340
}
@@ -1504,7 +943,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -81,
"y": -304
}
@@ -1515,10 +954,10 @@
}
]
}
- }
- ]
+ ]
+ }
}
},
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.J2735MAP"
+ "dataType": "us.dot.its.jpo.asn.j2735.r2024.MapData.MapDataMessageFrame"
}
}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json b/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json
deleted file mode 100644
index e7df02d..0000000
--- a/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference-1-hour-later.json
+++ /dev/null
@@ -1,2814 +0,0 @@
-{
- "metadata": {
- "logFileName": "",
- "recordType": "mapTx",
- "securityResultCode": "success",
- "receivedMessageDetails": {
- "rxSource": "NA"
- },
- "payloadType": "us.dot.its.jpo.ode.model.OdeMapPayload",
- "serialId": {
- "streamId": "d963d421-fba0-4b21-b991-229e8d3bf9c1",
- "bundleSize": 1,
- "bundleId": 0,
- "recordId": 0,
- "serialNumber": 0
- },
- "odeReceivedAt": "2025-01-31T01:01:00.000Z",
- "schemaVersion": 8,
- "maxDurationTime": 0,
- "recordGeneratedAt": "",
- "recordGeneratedBy": "RSU",
- "sanitized": false,
- "odePacketID": "",
- "odeTimStartDateTime": "",
- "asn1": "001283C138003000205E9C014D3EAB092CA624B5518202DC3658042800000400023622C60CA009F66D48ABFAF81388D8AD18070027D9B2FFCFE9804F13667B1FFD009EC2C76E3FFC82C4E0001004B00C5000000800066C4574101813ECD8B757FAE027D9B30E6FF5604EC363561FE7809EC6CD69BFEC813C4D8A617FC9027D9B2147008604FB163666000016250000802580228000001000096229E1309B51A6FE4204DD361CF1FE5009F6018E1000096020A00000080004D88A57F84027D9B3827002804EC36087600A009F62C289407282C310001C0440188800000006C46DBE02813EC5816D800710052200000001B11B6FAD404FB16054A0000401C8800000006C47B3D24813EC5816D801B100C4200000000AF890F12C580007E87100D4200000008AF4C0F12C580077E7A2C0004000160002001CB028D000000800052C160BC40B5FFFD8A9409D86BFEBB5B40141457FEF53B76C008B467014145800080002BFFCBFFC82C6A0001804B024D000000800036C2213C3B013ECD80096D64027D9AFFD8CDFC04F635FF7983BC09F66C0082AA2014280B1B80006012C0B3400000100004B02BCF0F6D7FE065D602788B0138EB900B1240001012C083400000080009B0C2AF0B804FB15FE6DE171AFFF6C63E04EC15FE1DE670060E40002581EA8000004000135DA6DF0180A0A6ADC2C00D0143CD51897FDA028C8ABB25001A0B0680008012C105400000200009AEDBEFAE005053540EE003C0A326A9CF3FED8143C5667780010582C0004009608AA00000080004D76DE7EE402829ABA88FFDC050F354525FFF80A322BCF23FA602C690000C04B0395000000200016BB4FBD4E01414D3215800802940AB108FFF2030D2000110126200000001AEE5103BE050A15F6F1FFC8404D8800000006BB97C18E0142857DFA800010146200000001AEE89099A050A15F8720000B05DD000000800046BE3743B781428D80E1B00002879B00514B4404F63600827D8C09E22C000400015FFE6007016190000402582CE8000004000135ECEE1DE80A146C02E54758143CD8059AD3E027B1B00613DD004F102C360000804B055D000000200046BCC7C3C781428D80108C6E02829B002B2ECE050A16019A4B29B00AB5C3604F136004E410409EC018A10000960C3A00000080004D7DE9878602851B003923CC05053601623B440A0A6BFB8C3A5014140B0640005012C197400000100005AFE570EF2050A36003A47C80A0A6BFD2C45F014140B054000501101A8200000001B05A90EDC050535FFE605800A0A101B8200000001B08A30EC0050535FFE605300A0A101C8200000005B0C6F0EA4050515FFCA0568B0001000E",
- "mapSource": "RSU",
- "originIp": "8.8.8.8"
- },
- "payload": {
- "data": {
- "msgIssueRevision": 0,
- "layerType": "intersectionData",
- "layerID": 0,
- "intersections": {
- "intersectionGeometry": [
- {
- "id": {
- "id": 12110
- },
- "revision": 0,
- "refPoint": {
- "latitude": 39.5952649,
- "longitude": -105.0914122,
- "elevation": 1677.0
- },
- "laneWidth": 366,
- "laneSet": {
- "GenericLane": [
- {
- "laneID": 2,
- "ingressApproach": 1,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2225,
- "y": 808
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 10517,
- "y": -161
- }
- },
- "attributes": {
- "dElevation": -60
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 2769,
- "y": 112
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 6142,
- "y": -180
- }
- },
- "attributes": {
- "dElevation": -30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 6636,
- "y": -12
- }
- },
- "attributes": {
- "dElevation": -20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 3804,
- "y": -7
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 19,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 3,
- "ingressApproach": 1,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2222,
- "y": 515
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 2933,
- "y": -82
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 6259,
- "y": -85
- }
- },
- "attributes": {
- "dElevation": -40
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 3416,
- "y": -98
- }
- },
- "attributes": {
- "dElevation": -20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 6867,
- "y": -39
- }
- },
- "attributes": {
- "dElevation": -30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 2657,
- "y": -55
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 4259,
- "y": 67
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 3481,
- "y": 0
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 18,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 1,
- "ingressApproach": 1,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2215,
- "y": 1218
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 10451,
- "y": -223
- }
- },
- "attributes": {
- "dElevation": -70
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 1852,
- "y": -108
- }
- },
- "attributes": {
- "dElevation": -10
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 28,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 4,
- "ingressApproach": 1,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2213,
- "y": -124
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 7187,
- "y": 20
- }
- },
- "attributes": {
- "dElevation": -40
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 541,
- "y": 40
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 1298,
- "y": 229
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 12,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 7,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 6,
- "egressApproach": 2,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2267,
- "y": -1019
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 365,
- "y": 7
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 5,
- "egressApproach": 2,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2267,
- "y": -662
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 338,
- "y": 0
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 7,
- "egressApproach": 2,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 2294,
- "y": -1463
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 365,
- "y": 27
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 12,
- "egressApproach": 4,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -952,
- "y": -1898
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 0,
- "y": -377
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 13,
- "egressApproach": 4,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -1440,
- "y": -1898
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 7,
- "y": -390
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 0,
- "y": 0
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 0,
- "y": 7
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 10,
- "ingressApproach": 3,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 705,
- "y": -1919
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -1,
- "y": -7515
- }
- },
- "attributes": {
- "dElevation": -40
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -41,
- "y": -5272
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -17,
- "y": -11337
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 17,
- "y": -5938
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 0,
- "y": 0
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -7,
- "y": -7
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 26,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 6,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 9,
- "ingressApproach": 3,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 1090,
- "y": -1930
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 9,
- "y": -4764
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -20,
- "y": -6402
- }
- },
- "attributes": {
- "dElevation": -20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -34,
- "y": -7953
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 16,
- "y": -10940
- }
- },
- "attributes": {
- "dElevation": 20
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 27,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 6,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 11,
- "ingressApproach": 3,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 350,
- "y": -1925
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -32,
- "y": -6698
- }
- },
- "attributes": {
- "dElevation": -30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 156,
- "y": -2616
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 18,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 1,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 8,
- "ingressApproach": 3,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 1557,
- "y": -1956
- }
- },
- "attributes": {
- "dElevation": -10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -101,
- "y": -1956
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -5,
- "y": -7393
- }
- },
- "attributes": {
- "dElevation": -40
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -121,
- "y": -1636
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 7,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 15,
- "ingressApproach": 5,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2405,
- "y": -1018
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -9339,
- "y": 26
- }
- },
- "attributes": {
- "dElevation": 30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -11895,
- "y": -38
- }
- },
- "attributes": {
- "dElevation": 50
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -8814,
- "y": 13
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 6,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 8,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 16,
- "ingressApproach": 5,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2337,
- "y": -656
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -12229,
- "y": 15
- }
- },
- "attributes": {
- "dElevation": 50
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -11362,
- "y": -37
- }
- },
- "attributes": {
- "dElevation": 30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -6537,
- "y": 1
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 5,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 8,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 17,
- "ingressApproach": 5,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2338,
- "y": -284
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -8892,
- "y": -18
- }
- },
- "attributes": {
- "dElevation": 30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -11959,
- "y": -2
- }
- },
- "attributes": {
- "dElevation": 50
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -1564,
- "y": -180
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 26,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 3,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 14,
- "ingressApproach": 5,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2401,
- "y": -1380
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -19947,
- "y": 8
- }
- },
- "attributes": {
- "dElevation": 80
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -10108,
- "y": -7
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 13,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 18,
- "egressApproach": 6,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2264,
- "y": 479
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -580,
- "y": -14
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 19,
- "egressApproach": 6,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2257,
- "y": 796
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -518,
- "y": 0
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 20,
- "egressApproach": 6,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -2236,
- "y": 1229
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -484,
- "y": 0
- }
- }
- }
- ]
- }
- },
- {
- "laneID": 23,
- "ingressApproach": 7,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -914,
- "y": 1903
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 225,
- "y": 12288
- }
- },
- "attributes": {
- "dElevation": 30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 40,
- "y": 9634
- }
- },
- "attributes": {
- "dElevation": -20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 32,
- "y": 8035
- }
- },
- "attributes": {
- "dElevation": -30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 0,
- "y": 0
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -7,
- "y": 28
- }
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 12,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 22,
- "ingressApproach": 7,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -1221,
- "y": 1914
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 92,
- "y": 10475
- }
- },
- "attributes": {
- "dElevation": 30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 89,
- "y": 11582
- }
- },
- "attributes": {
- "dElevation": -20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 48,
- "y": 7912
- }
- },
- "attributes": {
- "dElevation": -30
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 13,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 21,
- "ingressApproach": 7,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -1649,
- "y": 1935
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 16,
- "y": 3182
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 21,
- "y": 5991
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 102,
- "y": 4810
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 85,
- "y": 11803
- }
- },
- "attributes": {
- "dElevation": -30
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 19,
- "y": 4161
- }
- },
- "attributes": {
- "dElevation": -20
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 20,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 24,
- "ingressApproach": 7,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -535,
- "y": 1926
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 28,
- "y": 4582
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 88,
- "y": 3793
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -143,
- "y": 1866
- }
- },
- "attributes": {
- "dElevation": 10
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 6,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 5,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 25,
- "ingressApproach": 7,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": -213,
- "y": 1913
- }
- },
- "attributes": {
- "dElevation": 20
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 14,
- "y": 4594
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -91,
- "y": 2238
- }
- },
- "attributes": {
- "dElevation": 10
- }
- }
- ]
- },
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 5,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 5,
- "connectionID": 1
- }
- ]
- }
- },
- {
- "laneID": 26,
- "egressApproach": 8,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 724,
- "y": 1902
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -7,
- "y": 352
- }
- },
- "attributes": {
- "dElevation": 10
- }
- }
- ]
- }
- },
- {
- "laneID": 27,
- "egressApproach": 8,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 1105,
- "y": 1888
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -7,
- "y": 332
- }
- },
- "attributes": {
- "dElevation": 10
- }
- }
- ]
- }
- },
- {
- "laneID": 28,
- "egressApproach": 8,
- "laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
- "laneType": {
- "vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
- }
- }
- },
- "nodeList": {
- "nodes": [
- {
- "delta": {
- "nodeXY6": {
- "x": 1591,
- "y": 1874
- }
- },
- "attributes": {
- "dElevation": 10
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": -14,
- "y": 346
- }
- }
- },
- {
- "delta": {
- "nodeXY6": {
- "x": 0,
- "y": 7
- }
- }
- }
- ]
- }
- }
- ]
- }
- }
- ]
- }
- },
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.J2735MAP"
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference.json b/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference.json
index e1a7a87..0ec484d 100644
--- a/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference.json
+++ b/jpo-deduplicator/src/test/resources/json/ode_map/sample.ode-map-reference.json
@@ -6,16 +6,16 @@
"receivedMessageDetails": {
"rxSource": "NA"
},
- "payloadType": "us.dot.its.jpo.ode.model.OdeMapPayload",
+ "payloadType": "us.dot.its.jpo.ode.model.OdeMessageFramePayload",
"serialId": {
- "streamId": "d963d421-fba0-4b21-b991-229e8d3bf9c1",
+ "streamId": "339e6941-400a-4f7b-87fd-6020e9af28b7",
"bundleSize": 1,
"bundleId": 0,
"recordId": 0,
"serialNumber": 0
},
- "odeReceivedAt": "2025-01-31T00:00:00.000Z",
- "schemaVersion": 8,
+ "odeReceivedAt": "2025-07-15T21:00:28.938Z",
+ "schemaVersion": 9,
"maxDurationTime": 0,
"recordGeneratedAt": "",
"recordGeneratedBy": "RSU",
@@ -23,81 +23,50 @@
"odePacketID": "",
"odeTimStartDateTime": "",
"asn1": "001283C138003000205E9C014D3EAB092CA624B5518202DC3658042800000400023622C60CA009F66D48ABFAF81388D8AD18070027D9B2FFCFE9804F13667B1FFD009EC2C76E3FFC82C4E0001004B00C5000000800066C4574101813ECD8B757FAE027D9B30E6FF5604EC363561FE7809EC6CD69BFEC813C4D8A617FC9027D9B2147008604FB163666000016250000802580228000001000096229E1309B51A6FE4204DD361CF1FE5009F6018E1000096020A00000080004D88A57F84027D9B3827002804EC36087600A009F62C289407282C310001C0440188800000006C46DBE02813EC5816D800710052200000001B11B6FAD404FB16054A0000401C8800000006C47B3D24813EC5816D801B100C4200000000AF890F12C580007E87100D4200000008AF4C0F12C580077E7A2C0004000160002001CB028D000000800052C160BC40B5FFFD8A9409D86BFEBB5B40141457FEF53B76C008B467014145800080002BFFCBFFC82C6A0001804B024D000000800036C2213C3B013ECD80096D64027D9AFFD8CDFC04F635FF7983BC09F66C0082AA2014280B1B80006012C0B3400000100004B02BCF0F6D7FE065D602788B0138EB900B1240001012C083400000080009B0C2AF0B804FB15FE6DE171AFFF6C63E04EC15FE1DE670060E40002581EA8000004000135DA6DF0180A0A6ADC2C00D0143CD51897FDA028C8ABB25001A0B0680008012C105400000200009AEDBEFAE005053540EE003C0A326A9CF3FED8143C5667780010582C0004009608AA00000080004D76DE7EE402829ABA88FFDC050F354525FFF80A322BCF23FA602C690000C04B0395000000200016BB4FBD4E01414D3215800802940AB108FFF2030D2000110126200000001AEE5103BE050A15F6F1FFC8404D8800000006BB97C18E0142857DFA800010146200000001AEE89099A050A15F8720000B05DD000000800046BE3743B781428D80E1B00002879B00514B4404F63600827D8C09E22C000400015FFE6007016190000402582CE8000004000135ECEE1DE80A146C02E54758143CD8059AD3E027B1B00613DD004F102C360000804B055D000000200046BCC7C3C781428D80108C6E02829B002B2ECE050A16019A4B29B00AB5C3604F136004E410409EC018A10000960C3A00000080004D7DE9878602851B003923CC05053601623B440A0A6BFB8C3A5014140B0640005012C197400000100005AFE570EF2050A36003A47C80A0A6BFD2C45F014140B054000501101A8200000001B05A90EDC050535FFE605800A0A101B8200000001B08A30EC0050535FFE605300A0A101C8200000005B0C6F0EA4050515FFCA0568B0001000E",
- "mapSource": "RSU",
- "originIp": "8.8.8.8"
+ "source": "RSU",
+ "originIp": "8.8.8.8",
+ "isCertPresent": false
},
"payload": {
"data": {
- "msgIssueRevision": 0,
- "layerType": "intersectionData",
- "layerID": 0,
- "intersections": {
- "intersectionGeometry": [
- {
- "id": {
- "id": 12110
- },
- "revision": 0,
- "refPoint": {
- "latitude": 39.5952649,
- "longitude": -105.0914122,
- "elevation": 1677.0
- },
- "laneWidth": 366,
- "laneSet": {
- "GenericLane": [
+ "messageId": 18,
+ "value": {
+ "MapData": {
+ "msgIssueRevision": 0,
+ "layerType": "intersectionData",
+ "layerID": 0,
+ "intersections": [
+ {
+ "id": {
+ "id": 12110
+ },
+ "revision": 0,
+ "refPoint": {
+ "lat": 395952649,
+ "long": -1050914122,
+ "elevation": 16770
+ },
+ "laneWidth": 366,
+ "laneSet": [
{
"laneID": 2,
"ingressApproach": 1,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2225,
"y": 808
}
@@ -108,7 +77,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 10517,
"y": -161
}
@@ -119,7 +88,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2769,
"y": 112
}
@@ -130,7 +99,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 6142,
"y": -180
}
@@ -141,7 +110,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 6636,
"y": -12
}
@@ -152,7 +121,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 3804,
"y": -7
}
@@ -160,84 +129,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 19,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 19,
+ "maneuver": "8000"
+ },
+ "signalGroup": 4,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 3,
"ingressApproach": 1,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2222,
"y": 515
}
@@ -248,7 +169,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2933,
"y": -82
}
@@ -259,7 +180,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 6259,
"y": -85
}
@@ -270,7 +191,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 3416,
"y": -98
}
@@ -281,7 +202,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 6867,
"y": -39
}
@@ -292,7 +213,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2657,
"y": -55
}
@@ -303,7 +224,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 4259,
"y": 67
}
@@ -314,7 +235,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 3481,
"y": 0
}
@@ -322,84 +243,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 18,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 4,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 18,
+ "maneuver": "8000"
+ },
+ "signalGroup": 4,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 1,
"ingressApproach": 1,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "2000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2215,
"y": 1218
}
@@ -407,7 +280,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 10451,
"y": -223
}
@@ -418,7 +291,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1852,
"y": -108
}
@@ -429,83 +302,35 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 28,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 28,
+ "maneuver": "2000"
+ },
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 4,
"ingressApproach": 1,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2213,
"y": -124
}
@@ -516,7 +341,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 7187,
"y": 20
}
@@ -527,7 +352,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 541,
"y": 40
}
@@ -538,7 +363,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1298,
"y": 229
}
@@ -546,62 +371,27 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 12,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 7,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 12,
+ "maneuver": "4000"
+ },
+ "signalGroup": 7,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 6,
"egressApproach": 2,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -609,7 +399,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2267,
"y": -1019
}
@@ -620,7 +410,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 365,
"y": 7
}
@@ -633,32 +423,12 @@
"laneID": 5,
"egressApproach": 2,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -666,7 +436,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2267,
"y": -662
}
@@ -677,7 +447,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 338,
"y": 0
}
@@ -690,32 +460,12 @@
"laneID": 7,
"egressApproach": 2,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -723,7 +473,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 2294,
"y": -1463
}
@@ -734,7 +484,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 365,
"y": 27
}
@@ -747,32 +497,12 @@
"laneID": 12,
"egressApproach": 4,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -780,7 +510,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -952,
"y": -1898
}
@@ -788,7 +518,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 0,
"y": -377
}
@@ -801,32 +531,12 @@
"laneID": 13,
"egressApproach": 4,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -834,7 +544,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1440,
"y": -1898
}
@@ -842,7 +552,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 7,
"y": -390
}
@@ -850,7 +560,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 0,
"y": 0
}
@@ -858,7 +568,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 0,
"y": 7
}
@@ -871,54 +581,21 @@
"laneID": 10,
"ingressApproach": 3,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 705,
"y": -1919
}
@@ -926,7 +603,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1,
"y": -7515
}
@@ -937,7 +614,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -41,
"y": -5272
}
@@ -948,7 +625,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -17,
"y": -11337
}
@@ -956,7 +633,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 17,
"y": -5938
}
@@ -967,7 +644,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 0,
"y": 0
}
@@ -975,7 +652,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -7,
"y": -7
}
@@ -983,84 +660,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 26,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 6,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 26,
+ "maneuver": "8000"
+ },
+ "signalGroup": 6,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 9,
"ingressApproach": 3,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1090,
"y": -1930
}
@@ -1071,7 +700,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 9,
"y": -4764
}
@@ -1082,7 +711,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -20,
"y": -6402
}
@@ -1093,7 +722,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -34,
"y": -7953
}
@@ -1104,7 +733,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 16,
"y": -10940
}
@@ -1115,84 +744,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 27,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 6,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 27,
+ "maneuver": "8000"
+ },
+ "signalGroup": 6,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 11,
"ingressApproach": 3,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 350,
"y": -1925
}
@@ -1200,7 +781,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -32,
"y": -6698
}
@@ -1211,7 +792,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 156,
"y": -2616
}
@@ -1219,84 +800,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 18,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 1,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 18,
+ "maneuver": "4000"
+ },
+ "signalGroup": 1,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 8,
"ingressApproach": 3,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "2000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1557,
"y": -1956
}
@@ -1307,7 +840,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -101,
"y": -1956
}
@@ -1315,7 +848,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -5,
"y": -7393
}
@@ -1326,7 +859,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -121,
"y": -1636
}
@@ -1334,83 +867,35 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 7,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 7,
+ "maneuver": "2000"
+ },
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 15,
"ingressApproach": 5,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2405,
"y": -1018
}
@@ -1421,7 +906,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -9339,
"y": 26
}
@@ -1432,7 +917,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -11895,
"y": -38
}
@@ -1443,7 +928,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -8814,
"y": 13
}
@@ -1451,84 +936,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 6,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 8,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 6,
+ "maneuver": "8000"
+ },
+ "signalGroup": 8,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 16,
"ingressApproach": 5,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2337,
"y": -656
}
@@ -1539,7 +976,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -12229,
"y": 15
}
@@ -1550,7 +987,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -11362,
"y": -37
}
@@ -1561,7 +998,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -6537,
"y": 1
}
@@ -1569,84 +1006,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 5,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 8,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 5,
+ "maneuver": "8000"
+ },
+ "signalGroup": 8,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 17,
"ingressApproach": 5,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2338,
"y": -284
}
@@ -1657,7 +1046,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -8892,
"y": -18
}
@@ -1668,7 +1057,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -11959,
"y": -2
}
@@ -1679,7 +1068,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1564,
"y": -180
}
@@ -1687,84 +1076,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 26,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 3,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 26,
+ "maneuver": "4000"
+ },
+ "signalGroup": 3,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 14,
"ingressApproach": 5,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "2000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2401,
"y": -1380
}
@@ -1775,7 +1116,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -19947,
"y": 8
}
@@ -1786,7 +1127,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -10108,
"y": -7
}
@@ -1794,61 +1135,26 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 13,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 13,
+ "maneuver": "2000"
+ },
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 18,
"egressApproach": 6,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1856,7 +1162,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2264,
"y": 479
}
@@ -1867,7 +1173,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -580,
"y": -14
}
@@ -1880,32 +1186,12 @@
"laneID": 19,
"egressApproach": 6,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1913,7 +1199,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2257,
"y": 796
}
@@ -1924,7 +1210,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -518,
"y": 0
}
@@ -1937,32 +1223,12 @@
"laneID": 20,
"egressApproach": 6,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -1970,7 +1236,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -2236,
"y": 1229
}
@@ -1981,7 +1247,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -484,
"y": 0
}
@@ -1994,54 +1260,21 @@
"laneID": 23,
"ingressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -914,
"y": 1903
}
@@ -2052,7 +1285,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 225,
"y": 12288
}
@@ -2063,7 +1296,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 40,
"y": 9634
}
@@ -2074,7 +1307,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 32,
"y": 8035
}
@@ -2085,7 +1318,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 0,
"y": 0
}
@@ -2093,7 +1326,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -7,
"y": 28
}
@@ -2101,84 +1334,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 12,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 12,
+ "maneuver": "8000"
+ },
+ "signalGroup": 2,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 22,
"ingressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "8000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1221,
"y": 1914
}
@@ -2189,7 +1374,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 92,
"y": 10475
}
@@ -2200,7 +1385,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 89,
"y": 11582
}
@@ -2211,7 +1396,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 48,
"y": 7912
}
@@ -2222,84 +1407,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 13,
- "maneuver": {
- "maneuverStraightAllowed": true,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 2,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 13,
+ "maneuver": "8000"
+ },
+ "signalGroup": 2,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 21,
"ingressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "2000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -1649,
"y": 1935
}
@@ -2310,7 +1447,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 16,
"y": 3182
}
@@ -2321,7 +1458,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 21,
"y": 5991
}
@@ -2332,7 +1469,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 102,
"y": 4810
}
@@ -2340,7 +1477,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 85,
"y": 11803
}
@@ -2351,7 +1488,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 19,
"y": 4161
}
@@ -2362,83 +1499,35 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 20,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": false,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": true,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 20,
+ "maneuver": "2000"
+ },
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 24,
"ingressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -535,
"y": 1926
}
@@ -2449,7 +1538,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 28,
"y": 4582
}
@@ -2460,7 +1549,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 88,
"y": 3793
}
@@ -2471,7 +1560,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -143,
"y": 1866
}
@@ -2482,84 +1571,36 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 6,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 5,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 6,
+ "maneuver": "4000"
+ },
+ "signalGroup": 5,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 25,
"ingressApproach": 7,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": true,
- "egressPath": false
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "80",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
- "maneuvers": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- },
+ "maneuvers": "4000",
"nodeList": {
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -213,
"y": 1913
}
@@ -2570,7 +1611,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 14,
"y": 4594
}
@@ -2581,7 +1622,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -91,
"y": 2238
}
@@ -2592,62 +1633,27 @@
}
]
},
- "connectsTo": {
- "connectsTo": [
- {
- "connectingLane": {
- "lane": 5,
- "maneuver": {
- "maneuverStraightAllowed": false,
- "maneuverNoStoppingAllowed": false,
- "goWithHalt": false,
- "maneuverLeftAllowed": true,
- "maneuverUTurnAllowed": false,
- "maneuverLeftTurnOnRedAllowed": false,
- "reserved1": false,
- "maneuverRightAllowed": false,
- "maneuverLaneChangeAllowed": false,
- "yieldAllwaysRequired": false,
- "maneuverRightTurnOnRedAllowed": false,
- "caution": false
- }
- },
- "signalGroup": 5,
- "connectionID": 1
- }
- ]
- }
+ "connectsTo": [
+ {
+ "connectingLane": {
+ "lane": 5,
+ "maneuver": "4000"
+ },
+ "signalGroup": 5,
+ "connectionID": 1
+ }
+ ]
},
{
"laneID": 26,
"egressApproach": 8,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -2655,7 +1661,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 724,
"y": 1902
}
@@ -2666,7 +1672,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -7,
"y": 352
}
@@ -2682,32 +1688,12 @@
"laneID": 27,
"egressApproach": 8,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -2715,7 +1701,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1105,
"y": 1888
}
@@ -2726,7 +1712,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -7,
"y": 332
}
@@ -2742,32 +1728,12 @@
"laneID": 28,
"egressApproach": 8,
"laneAttributes": {
- "directionalUse": {
- "ingressPath": false,
- "egressPath": true
- },
- "shareWith": {
- "busVehicleTraffic": false,
- "trackedVehicleTraffic": false,
- "individualMotorizedVehicleTraffic": false,
- "taxiVehicleTraffic": false,
- "overlappingLaneDescriptionProvided": false,
- "cyclistVehicleTraffic": false,
- "otherNonMotorizedTrafficTypes": false,
- "multipleLanesTreatedAsOneLane": false,
- "pedestrianTraffic": false,
- "pedestriansTraffic": false
- },
+ "directionalUse": "40",
+ "sharedWith": "0000",
"laneType": {
"vehicle": {
- "isVehicleRevocableLane": false,
- "isVehicleFlyOverLane": false,
- "permissionOnRequest": false,
- "hasIRbeaconCoverage": false,
- "restrictedToBusUse": false,
- "restrictedToTaxiUse": false,
- "restrictedFromPublicUse": false,
- "hovLaneUseOnly": false
+ "value": "00",
+ "length": 8
}
}
},
@@ -2775,7 +1741,7 @@
"nodes": [
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 1591,
"y": 1874
}
@@ -2786,7 +1752,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": -14,
"y": 346
}
@@ -2794,7 +1760,7 @@
},
{
"delta": {
- "nodeXY6": {
+ "node-XY6": {
"x": 0,
"y": 7
}
@@ -2805,10 +1771,10 @@
}
]
}
- }
- ]
+ ]
+ }
}
},
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.J2735MAP"
+ "dataType": "us.dot.its.jpo.asn.j2735.r2024.MapData.MapDataMessageFrame"
}
}
\ No newline at end of file
From 8eadea77203d2fdddbc5fc9eb3e730fda89e3d30 Mon Sep 17 00:00:00 2001
From: Michael7371 <40476797+Michael7371@users.noreply.github.com>
Date: Tue, 15 Jul 2025 16:24:21 -0600
Subject: [PATCH 05/24] fixing map deduplication issues
---
.../topologies/MapDeduplicatorTopology.java | 49 +++++++------------
.../MapDeduplicatorTopologyTest.java | 2 +-
2 files changed, 19 insertions(+), 32 deletions(-)
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
index b1cd07f..38465f2 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
@@ -7,9 +7,12 @@
import org.apache.kafka.streams.KafkaStreams.StateListener;
import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+import us.dot.its.jpo.asn.j2735.r2024.Common.IntersectionReferenceID;
+import us.dot.its.jpo.asn.j2735.r2024.MapData.MapDataMessageFrame;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.ode.model.OdeMessageFrameData;
import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
+import us.dot.its.jpo.ode.plugin.j2735.J2735IntersectionReferenceID;
import org.apache.kafka.streams.kstream.*;
import org.apache.kafka.streams.state.Stores;
@@ -18,11 +21,11 @@
import com.fasterxml.jackson.databind.ObjectMapper;
-import java.time.Instant;
import java.time.format.DateTimeFormatter;
import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeMapJsonProcessorSupplier;
import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.geojsonconverter.partitioner.RsuIntersectionKey;
import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
public class MapDeduplicatorTopology {
@@ -54,31 +57,6 @@ public void start() {
streams.start();
}
- // public Instant getInstantFromMap(OdeMessageFrameData map) {
- // try {
- // if (map == null || map.getMetadata() == null) {
- // logger.warn("Map message or metadata is null, using epoch time");
- // return Instant.ofEpochMilli(0);
- // }
-
- // String time = ((OdeMessageFrameMetadata)
- // map.getMetadata()).getOdeReceivedAt();
- // if (time == null || time.isEmpty()) {
- // logger.warn("Map message has null or empty odeReceivedAt time, using epoch
- // time");
- // return Instant.ofEpochMilli(0);
- // }
-
- // return Instant.from(formatter.parse(time));
- // } catch (Exception e) {
- // logger.warn("Failed to parse time from Map: " + (map != null &&
- // map.getMetadata() != null
- // ? ((OdeMessageFrameMetadata) map.getMetadata()).getOdeReceivedAt()
- // : "null"), e);
- // return Instant.ofEpochMilli(0);
- // }
- // }
-
public Topology buildTopology() {
StreamsBuilder builder = new StreamsBuilder();
@@ -96,11 +74,20 @@ public Topology buildTopology() {
return "unknown";
}
- // For now, use a simple key based on RSU IP and timestamp
- // This can be enhanced later with proper intersection ID extraction
- String rsuIp = ((OdeMessageFrameMetadata) value.getMetadata()).getOriginIp();
- String timestamp = ((OdeMessageFrameMetadata) value.getMetadata()).getOdeReceivedAt();
- return rsuIp + "_" + timestamp;
+ MapDataMessageFrame mf = (MapDataMessageFrame) value.getPayload().getData();
+ if (mf == null || mf.getValue() == null || mf.getValue().getIntersections() == null ||
+ mf.getValue().getIntersections().isEmpty()) {
+ logger.warn("Received Map message with null message frame data, using default key");
+ return "unknown";
+ }
+
+ IntersectionReferenceID intersectionId = mf.getValue().getIntersections().get(0).getId();
+ RsuIntersectionKey newKey = new RsuIntersectionKey();
+ newKey.setRsuId(((OdeMessageFrameMetadata) value.getMetadata()).getOriginIp());
+ J2735IntersectionReferenceID j2735IntersectionId = new J2735IntersectionReferenceID();
+ j2735IntersectionId.setId((int) intersectionId.getId().getValue());
+ newKey.setIntersectionReferenceID(j2735IntersectionId);
+ return newKey.toString();
} catch (Exception e) {
logger.error("Error extracting key from Map message: " + e.getMessage(), e);
return "unknown";
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
index 8752c6f..e71a128 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
@@ -81,7 +81,7 @@ public void setup() throws IOException {
OdeMessageFrameData.class);
originalTime = map1HourLater.getMetadata().getOdeReceivedAt();
instant = Instant.parse(originalTime);
- newInstant = instant.plus(1, ChronoUnit.HOURS);
+ newInstant = instant.plus(61, ChronoUnit.HOURS);
map1HourLater.getMetadata().setOdeReceivedAt(newInstant.toString());
inputMap5 = map1HourLater.toJson();
}
From 7dddcd65b2a4690b95d7a9ac0882af083d63999f Mon Sep 17 00:00:00 2001
From: Drew Johnston
Date: Fri, 1 Aug 2025 03:54:29 -0600
Subject: [PATCH 06/24] Update deduplication for all message types except
ProcessedMap and ProcessedMapWKT
---
README.md | 1 -
docs/Release_notes.md | 5 +-
jpo-deduplicator/pom.xml | 4 +-
.../deduplicator/DeduplicatorProperties.java | 21 -
.../DeduplicatorServiceController.java | 57 +-
.../OdeRawEncodedTimJsonProcessor.java | 53 -
.../processors/OdeTimJsonProcessor.java | 33 +-
.../processors/ProcessedBsmJsonProcessor.java | 10 +-
.../processors/ProcessedSpatProcessor.java | 18 +-
.../OdeRawEncodedTimProcessorSupplier.java | 22 -
.../OdeTimJsonProcessorSupplier.java | 6 +-
.../serialization/JsonSerdes.java | 11 -
.../topologies/MapDeduplicatorTopology.java | 7 +-
.../OdeRawEncodedTimDeduplicatorTopology.java | 130 --
.../ProcessedBsmDeduplicatorTopology.java | 211 +-
.../ProcessedSpatDeduplicatorTopology.java | 203 +-
.../topologies/TimDeduplicatorTopology.java | 39 +-
.../src/main/resources/application.yaml | 5 -
.../BsmDeduplicatorTopologyTest.java | 30 +-
.../MapDeduplicatorTopologyTest.java | 26 +-
...RawEncodedTimDeduplicatorTopologyTest.java | 128 --
.../ProcessedBsmDeduplicatorTopologyTest.java | 399 ++--
...ProcessedSpatDeduplicatorTopologyTest.java | 486 ++---
.../TimDeduplicatorTopologyTest.java | 121 +-
.../ode_tim/sample.ode-tim-different.json | 1767 +++++------------
...sample.ode-tim-reference-1-hour-later.json | 1299 ------------
...mple.ode-tim-reference-1-second-later.json | 1299 ------------
.../ode_tim/sample.ode-tim-reference.json | 1473 ++------------
.../sample.processed_bsm-different.json | 53 -
...sample.processed_bsm-missing-position.json | 46 -
.../sample.processed_bsm-missing-speed.json | 52 -
...cessed_bsm-reference-10-seconds-later.json | 53 -
...le.processed_bsm-reference-with-speed.json | 53 -
.../sample.processed_bsm-reference.json | 55 +-
.../sample.processed_bsm-with-position.json | 53 -
.../sample.processed_spat-reference.json | 140 ++
36 files changed, 1647 insertions(+), 6722 deletions(-)
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeRawEncodedTimJsonProcessor.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeRawEncodedTimProcessorSupplier.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/OdeRawEncodedTimDeduplicatorTopology.java
delete mode 100644 jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java
delete mode 100644 jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-hour-later.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-second-later.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-different.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json
delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json
create mode 100644 jpo-deduplicator/src/test/resources/json/processed_spat/sample.processed_spat-reference.json
diff --git a/README.md b/README.md
index 036fe34..e2671b9 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,6 @@ The following topics currently support deduplication.
- topic.ProcessedMapWKT -> topic.DeduplicatedProcessedMapWKT
- topic.OdeMapJson -> topic.DeduplicatedOdeMapJson
- topic.OdeTimJson -> topic.DeduplicatedOdeTimJson
-- topic.OdeRawEncodedTIMJson -> topic.DeduplicatedOdeRawEncodedTIMJson
- topic.OdeBsmJson -> topic.DeduplicatedOdeBsmJson
- topic.ProcessedSpat -> topic.DeduplicatedProcessedSpat
diff --git a/docs/Release_notes.md b/docs/Release_notes.md
index 2a9b540..f99986b 100644
--- a/docs/Release_notes.md
+++ b/docs/Release_notes.md
@@ -15,9 +15,8 @@ The first release of the jpo-deduplicator package. This package focuses on remov
- ProcessedMapWKT
- ProcessedSpat
- OdeMapJson
- - OdeBSMJson
- - OdeTIMJson
- - OdeRawEncodedTIm
+ - OdeBsmJson
+ - OdeTimJson
This release also makes additional changes to the submodule components as follows
diff --git a/jpo-deduplicator/pom.xml b/jpo-deduplicator/pom.xml
index 02f789e..0e2d79c 100644
--- a/jpo-deduplicator/pom.xml
+++ b/jpo-deduplicator/pom.xml
@@ -32,8 +32,8 @@
reuseReports
${project.basedir}/target/site/jacoco/jacoco.xml
java
- 5.0.0
- 2.1.1
+ 5.0.2
+ 3.0.2
1.5.0
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java
index aed2feb..ff41acc 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/DeduplicatorProperties.java
@@ -73,12 +73,6 @@ public class DeduplicatorProperties implements EnvironmentAware {
private boolean enableOdeTimDeduplication;
private String kafkaStateStoreOdeTimJsonName = "OdeTimJson-store";
- // Ode Raw Encoded Tim Json Configuration
- private String kafkaTopicOdeRawEncodedTimJson;
- private String kafkaTopicDeduplicatedOdeRawEncodedTimJson;
- private boolean enableOdeRawEncodedTimDeduplication;
- private String kafkaStateStoreOdeRawEncodedTimJsonName = "OdeRawEncodedTimJson-store";
-
// Ode BsmJson Configuration
private String kafkaTopicOdeBsmJson;
private String kafkaTopicDeduplicatedOdeBsmJson;
@@ -328,21 +322,6 @@ public void setEnableOdeTimDeduplication(boolean enableOdeTimDeduplication) {
this.enableOdeTimDeduplication = enableOdeTimDeduplication;
}
- @Value("${kafkaTopicOdeRawEncodedTimJson}")
- public void setKafkaTopicOdeRawEncodedTimJson(String kafkaTopicOdeRawEncodedTimJson) {
- this.kafkaTopicOdeRawEncodedTimJson = kafkaTopicOdeRawEncodedTimJson;
- }
-
- @Value("${kafkaTopicDeduplicatedOdeRawEncodedTimJson}")
- public void setKafkaTopicDeduplicatedOdeRawEncodedTimJson(String kafkaTopicDeduplicatedOdeRawEncodedTimJson) {
- this.kafkaTopicDeduplicatedOdeRawEncodedTimJson = kafkaTopicDeduplicatedOdeRawEncodedTimJson;
- }
-
- @Value("${enableOdeRawEncodedTimDeduplication}")
- public void setEnableOdeRawEncodedTimDeduplication(boolean enableOdeRawEncodedTimDeduplication) {
- this.enableOdeRawEncodedTimDeduplication = enableOdeRawEncodedTimDeduplication;
- }
-
@Value("${kafkaTopicOdeBsmJson}")
public void setkafkaTopicOdeBsmJson(String kafkaTopicOdeBsmJson) {
this.kafkaTopicOdeBsmJson = kafkaTopicOdeBsmJson;
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
index 927e493..0b366e3 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
@@ -16,11 +16,10 @@
import us.dot.its.jpo.deduplicator.deduplicator.topologies.BsmDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.TimDeduplicatorTopology;
-import us.dot.its.jpo.deduplicator.deduplicator.topologies.OdeRawEncodedTimDeduplicatorTopology;
-// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
-// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
@Controller
@DependsOn("createKafkaTopics")
@@ -65,33 +64,18 @@ public DeduplicatorServiceController(final DeduplicatorProperties props,
mapDeduplicatorTopology.start();
}
- // if (props.isEnableOdeTimDeduplication()) {
- // logger.info("Starting Tim Deduplicator");
- // TimDeduplicatorTopology timDeduplicatorTopology = new
- // TimDeduplicatorTopology(
- // props,
- // props.createStreamProperties("TimDeduplicator"));
- // timDeduplicatorTopology.start();
- // }
-
- // if (props.isEnableOdeRawEncodedTimDeduplication()) {
- // logger.info("Starting Raw Encoded TIM Deduplicator");
- // OdeRawEncodedTimDeduplicatorTopology odeRawEncodedTimDeduplicatorTopology =
- // new OdeRawEncodedTimDeduplicatorTopology(
- // props,
- // props.createStreamProperties("OdeRawEncodedTimDeduplicator"));
- // odeRawEncodedTimDeduplicatorTopology.start();
- // }
+ if (props.isEnableOdeTimDeduplication()) {
+ logger.info("Starting TIM Deduplicator");
+ TimDeduplicatorTopology timDeduplicatorTopology = new TimDeduplicatorTopology(props);
+ timDeduplicatorTopology.start();
+ }
- // if(props.isEnableProcessedSpatDeduplication()){
- // logger.info("Starting Processed Spat Deduplicator");
- // ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new
- // ProcessedSpatDeduplicatorTopology(
- // props,
- // props.createStreamProperties("ProcessedSpatDeduplicator")
- // );
- // processedSpatDeduplicatorTopology.start();
- // }
+ if (props.isEnableProcessedSpatDeduplication()) {
+ logger.info("Starting Processed Spat Deduplicator");
+ ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new ProcessedSpatDeduplicatorTopology(
+ props);
+ processedSpatDeduplicatorTopology.start();
+ }
if (props.isEnableOdeBsmDeduplication()) {
logger.info("Starting BSM Deduplicator");
@@ -99,15 +83,12 @@ public DeduplicatorServiceController(final DeduplicatorProperties props,
bsmDeduplicatorTopology.start();
}
- // if(props.isEnableProcessedBsmDeduplication()){
- // logger.info("Starting Processed BSM Deduplicator");
- // ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new
- // ProcessedBsmDeduplicatorTopology(
- // props,
- // props.createStreamProperties("ProcessedBsmDeduplicator")
- // );
- // processedBsmDeduplicatorTopology.start();
- // }
+ if (props.isEnableProcessedBsmDeduplication()) {
+ logger.info("Starting Processed BSM Deduplicator");
+ ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new ProcessedBsmDeduplicatorTopology(
+ props);
+ processedBsmDeduplicatorTopology.start();
+ }
} catch (Exception e) {
logger.error("Encountered issue with creating topologies", e);
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeRawEncodedTimJsonProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeRawEncodedTimJsonProcessor.java
deleted file mode 100644
index 7565a57..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeRawEncodedTimJsonProcessor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.processors;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.JsonNode;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-
-public class OdeRawEncodedTimJsonProcessor extends DeduplicationProcessor{
-
- DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-
- DeduplicatorProperties props;
-
- private static final Logger logger = LoggerFactory.getLogger(OdeRawEncodedTimJsonProcessor.class);
-
- public OdeRawEncodedTimJsonProcessor(DeduplicatorProperties props){
- this.props = props;
- this.storeName = props.getKafkaStateStoreOdeRawEncodedTimJsonName();
- }
-
-
- @Override
- public Instant getMessageTime(JsonNode message) {
- try {
- String time = message.get("metadata").get("odeReceivedAt").asText();
- return Instant.from(formatter.parse(time));
- } catch (Exception e) {
- return Instant.ofEpochMilli(0);
- }
- }
-
- @Override
- public boolean isDuplicate(JsonNode lastMessage, JsonNode newMessage) {
- try{
- Instant oldValueTime = getMessageTime(lastMessage);
- Instant newValueTime = getMessageTime(newMessage);
-
- if(newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)){
- return false;
- }
-
- } catch(Exception e){
- logger.warn("Caught General Exception" + e);
- }
- return true;
- }
-}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeTimJsonProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeTimJsonProcessor.java
index bed4ae9..f036903 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeTimJsonProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/OdeTimJsonProcessor.java
@@ -8,10 +8,10 @@
import org.slf4j.LoggerFactory;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.ode.model.OdeTimData;
-import us.dot.its.jpo.ode.model.OdeTimMetadata;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
-public class OdeTimJsonProcessor extends DeduplicationProcessor{
+public class OdeTimJsonProcessor extends DeduplicationProcessor{
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
@@ -25,18 +25,30 @@ public OdeTimJsonProcessor(DeduplicatorProperties props){
@Override
- public Instant getMessageTime(OdeTimData message) {
+ public Instant getMessageTime(OdeMessageFrameData message) {
try {
- // String time = message.get("metadata").get("odeReceivedAt").asText();
- String time = ((OdeTimMetadata)message.getMetadata()).getOdeReceivedAt();
+ if (message == null || message.getMetadata() == null) {
+ logger.warn("TIM message or metadata is null, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
+ String time = message.getMetadata().getOdeReceivedAt();
+ if (time == null || time.isEmpty()) {
+ logger.warn("TIM message has null or empty odeReceivedAt time, using epoch time");
+ return Instant.ofEpochMilli(0);
+ }
+
return Instant.from(formatter.parse(time));
} catch (Exception e) {
+ logger.warn("Failed to Parse Time: " + (message != null && message.getMetadata() != null
+ ? ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt()
+ : "null"), e);
return Instant.ofEpochMilli(0);
}
}
@Override
- public boolean isDuplicate(OdeTimData lastMessage, OdeTimData newMessage) {
+ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData newMessage) {
try{
Instant oldValueTime = getMessageTime(lastMessage);
Instant newValueTime = getMessageTime(newMessage);
@@ -45,6 +57,13 @@ public boolean isDuplicate(OdeTimData lastMessage, OdeTimData newMessage) {
return false;
}
+ // Add null checks for payload and data
+ if (lastMessage == null || lastMessage.getPayload() == null || lastMessage.getPayload().getData() == null ||
+ newMessage == null || newMessage.getPayload() == null
+ || newMessage.getPayload().getData() == null) {
+ logger.warn("One or both TIM messages have null payload or data, treating as non-duplicate");
+ return false;
+ }
} catch(Exception e){
logger.warn("Caught General Exception" + e);
}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedBsmJsonProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedBsmJsonProcessor.java
index 07a1f27..6b358ab 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedBsmJsonProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedBsmJsonProcessor.java
@@ -1,7 +1,5 @@
package us.dot.its.jpo.deduplicator.deduplicator.processors;
-
-import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.ZonedDateTime;
@@ -51,10 +49,10 @@ public boolean isDuplicate(ProcessedBsm lastMessage, ProcessedBsm
}
// If the Vehicle is moving, forward the message on
- BigDecimal speed = newMessage.getProperties().getSpeed();
- BigDecimal oldSpeed = lastMessage.getProperties().getSpeed();
- if (speed != null && speed.doubleValue() > props.getProcessedBsmAlwaysIncludeAtSpeed()) {
- return false;
+ Double speed = newMessage.getProperties().getSpeed();
+ Double oldSpeed = lastMessage.getProperties().getSpeed();
+ if (speed != null && speed > props.getProcessedBsmAlwaysIncludeAtSpeed()) {
+ return false;
}
if((speed == null && oldSpeed != null) || (oldSpeed == null && speed != null)){
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedSpatProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedSpatProcessor.java
index 9f85e54..5ebdcd2 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedSpatProcessor.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedSpatProcessor.java
@@ -1,6 +1,5 @@
package us.dot.its.jpo.deduplicator.deduplicator.processors;
-
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
@@ -10,8 +9,8 @@
import org.slf4j.LoggerFactory;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.geojsonconverter.pojos.spat.MovementEvent;
-import us.dot.its.jpo.geojsonconverter.pojos.spat.MovementState;
+import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedMovementEvent;
+import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedMovementState;
import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
public class ProcessedSpatProcessor extends DeduplicationProcessor{
@@ -25,7 +24,6 @@ public ProcessedSpatProcessor(DeduplicatorProperties props){
this.storeName = props.getKafkaStateStoreProcessedSpatName();
}
-
@Override
public Instant getMessageTime(ProcessedSpat message) {
return message.getUtcTimeStamp().toInstant();
@@ -37,11 +35,11 @@ public boolean isDuplicate(ProcessedSpat lastMessage, ProcessedSpat newMessage)
Instant newValueTime = getMessageTime(newMessage);
Instant oldValueTime = getMessageTime(lastMessage);
- if(newValueTime.minus(Duration.ofMinutes(1)).isAfter(oldValueTime)){
+ if(newValueTime.minus(Duration.ofMinutes(1)).isAfter(oldValueTime)) {
return false;
- }else{
- HashMap> lastMessageStates = new HashMap<>();
- for(MovementState state: lastMessage.getStates()){
+ } else {
+ HashMap> lastMessageStates = new HashMap<>();
+ for(ProcessedMovementState state: lastMessage.getStates()){
lastMessageStates.put(state.getSignalGroup(), state.getStateTimeSpeed());
}
@@ -49,8 +47,8 @@ public boolean isDuplicate(ProcessedSpat lastMessage, ProcessedSpat newMessage)
return false; // message cannot be duplicate if the signal groups have a different number of signal groups
}
- for(MovementState state: newMessage.getStates()){
- List lastMessageState = lastMessageStates.get(state.getSignalGroup());
+ for(ProcessedMovementState state: newMessage.getStates()){
+ List lastMessageState = lastMessageStates.get(state.getSignalGroup());
if(lastMessageState == null){
return false; // messages cannot be duplicates if they have different signal groups
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeRawEncodedTimProcessorSupplier.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeRawEncodedTimProcessorSupplier.java
deleted file mode 100644
index ef0ebb7..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeRawEncodedTimProcessorSupplier.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers;
-
-import org.apache.kafka.streams.processor.api.Processor;
-import org.apache.kafka.streams.processor.api.ProcessorSupplier;
-import com.fasterxml.jackson.databind.JsonNode;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.processors.OdeRawEncodedTimJsonProcessor;
-
-public class OdeRawEncodedTimProcessorSupplier implements ProcessorSupplier {
-
- DeduplicatorProperties props;
-
- public OdeRawEncodedTimProcessorSupplier(DeduplicatorProperties props){
- this.props = props;
- }
-
- @Override
- public Processor get() {
- return new OdeRawEncodedTimJsonProcessor(props);
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeTimJsonProcessorSupplier.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeTimJsonProcessorSupplier.java
index 0c07e30..b71ec60 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeTimJsonProcessorSupplier.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/suppliers/OdeTimJsonProcessorSupplier.java
@@ -5,9 +5,9 @@
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.processors.OdeTimJsonProcessor;
-import us.dot.its.jpo.ode.model.OdeTimData;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
-public class OdeTimJsonProcessorSupplier implements ProcessorSupplier {
+public class OdeTimJsonProcessorSupplier implements ProcessorSupplier {
String storeName;
DeduplicatorProperties props;
@@ -16,7 +16,7 @@ public OdeTimJsonProcessorSupplier(DeduplicatorProperties props){
}
@Override
- public Processor get() {
+ public Processor get() {
return new OdeTimJsonProcessor(props);
}
}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java
index e1f7875..4a8407d 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/JsonSerdes.java
@@ -9,7 +9,6 @@
import us.dot.its.jpo.geojsonconverter.serialization.deserializers.JsonDeserializer;
import us.dot.its.jpo.geojsonconverter.serialization.serializers.JsonSerializer;
import us.dot.its.jpo.ode.model.OdeMessageFrameData;
-import us.dot.its.jpo.ode.model.OdeTimData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
@@ -39,12 +38,6 @@ public T deserialize(String topic, byte[] data) {
}
}
- public static Serde OdeTim(DeduplicatorProperties props) {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(OdeTimData.class));
- }
-
public static Serde OdeMessageFrame(DeduplicatorProperties props) {
return Serdes.serdeFrom(
new JsonSerializer(),
@@ -57,10 +50,6 @@ public static Serde JSON(DeduplicatorProperties props) {
new JsonDeserializer<>(JsonNode.class));
}
- public static Serde OdeTim() {
- return OdeTim(null);
- }
-
public static Serde OdeMessageFrame() {
return OdeMessageFrame(null);
}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
index 38465f2..11205fa 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/MapDeduplicatorTopology.java
@@ -7,12 +7,10 @@
import org.apache.kafka.streams.KafkaStreams.StateListener;
import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-import us.dot.its.jpo.asn.j2735.r2024.Common.IntersectionReferenceID;
import us.dot.its.jpo.asn.j2735.r2024.MapData.MapDataMessageFrame;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.ode.model.OdeMessageFrameData;
import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata;
-import us.dot.its.jpo.ode.plugin.j2735.J2735IntersectionReferenceID;
import org.apache.kafka.streams.kstream.*;
import org.apache.kafka.streams.state.Stores;
@@ -81,12 +79,9 @@ public Topology buildTopology() {
return "unknown";
}
- IntersectionReferenceID intersectionId = mf.getValue().getIntersections().get(0).getId();
RsuIntersectionKey newKey = new RsuIntersectionKey();
newKey.setRsuId(((OdeMessageFrameMetadata) value.getMetadata()).getOriginIp());
- J2735IntersectionReferenceID j2735IntersectionId = new J2735IntersectionReferenceID();
- j2735IntersectionId.setId((int) intersectionId.getId().getValue());
- newKey.setIntersectionReferenceID(j2735IntersectionId);
+ newKey.setIntersectionReferenceID(mf.getValue().getIntersections().get(0).getId());
return newKey.toString();
} catch (Exception e) {
logger.error("Error extracting key from Map message: " + e.getMessage(), e);
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/OdeRawEncodedTimDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/OdeRawEncodedTimDeduplicatorTopology.java
deleted file mode 100644
index e8bdc11..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/OdeRawEncodedTimDeduplicatorTopology.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-import org.apache.kafka.common.serialization.Serdes;
-import org.apache.kafka.streams.KafkaStreams;
-import org.apache.kafka.streams.StreamsBuilder;
-import org.apache.kafka.streams.Topology;
-import org.apache.kafka.streams.KafkaStreams.StateListener;
-import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
-import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-
-import org.apache.kafka.streams.kstream.*;
-import org.apache.kafka.streams.state.Stores;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import java.util.Objects;
-import java.util.Properties;
-
-import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeRawEncodedTimProcessorSupplier;
-
-public class OdeRawEncodedTimDeduplicatorTopology {
-
- private static final Logger logger = LoggerFactory.getLogger(OdeRawEncodedTimDeduplicatorTopology.class);
-
- Topology topology;
- KafkaStreams streams;
- String inputTopic;
- String outputTopic;
- Properties streamsProperties;
- ObjectMapper objectMapper;
- DeduplicatorProperties props;
- DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-
- public OdeRawEncodedTimDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties){
- this.streamsProperties = streamsProperties;
- this.objectMapper = DateJsonMapper.getInstance();
- this.props = props;
- }
-
-
- public void start() {
- if (streams != null && streams.state().isRunningOrRebalancing()) {
- throw new IllegalStateException("Start called while streams is already running.");
- }
- Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
- if (exceptionHandler != null) streams.setUncaughtExceptionHandler(exceptionHandler);
- if (stateListener != null) streams.setStateListener(stateListener);
- logger.info("Starting Tim Deduplicator Topology");
- streams.start();
- }
-
- public JsonNode genJsonNode(){
- return objectMapper.createObjectNode();
- }
-
- public Instant getInstantFromJsonTim(JsonNode tim){
- String time = tim.get("metadata").get("odeReceivedAt").asText();
- try{
- return Instant.from(formatter.parse(time));
- }catch(Exception e){
- logger.warn("Failed to parse time: " + time);
- return Instant.ofEpochMilli(0);
- }
- }
-
-
- public Topology buildTopology() {
- StreamsBuilder builder = new StreamsBuilder();
-
- KStream inputStream = builder.stream(props.getKafkaTopicOdeRawEncodedTimJson(), Consumed.with(Serdes.String(), JsonSerdes.JSON()));
-
- builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeRawEncodedTimJsonName()),
- Serdes.String(), JsonSerdes.JSON()));
-
- KStream timRekeyedStream = inputStream.selectKey((key, value)->{
- try{
- String messageBytes = value.get("payload")
- .get("data")
- .get("bytes").asText();
-
- int hash = Objects.hash(messageBytes);
-
- String rsuIP = value.get("metadata").get("originIp").asText();
-
- String newKey = rsuIP + "_" + hash;
- return newKey;
- }catch(Exception e){
- return "";
- }
- }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.JSON()));
-
-
-
- KStream deduplicatedStream = timRekeyedStream.process(new OdeRawEncodedTimProcessorSupplier(props), props.getKafkaStateStoreOdeRawEncodedTimJsonName());
-
- deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeRawEncodedTimJson(), Produced.with(Serdes.String(), JsonSerdes.JSON()));
-
- return builder.build();
-
- }
-
- public void stop() {
- logger.info("Stopping OdeRawEncodedTim Deduplicator Socket Broadcast Topology.");
- if (streams != null) {
- streams.close();
- streams.cleanUp();
- streams = null;
- }
- logger.info("Stopped OdeRawEncodedTim Deduplicator Socket Broadcast Topology.");
- }
-
- StateListener stateListener;
- public void registerStateListener(StateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- StreamsUncaughtExceptionHandler exceptionHandler;
- public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java
index 7418f7e..2a1e2e2 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedBsmDeduplicatorTopology.java
@@ -1,111 +1,100 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KafkaStreams;
-// import org.apache.kafka.streams.StreamsBuilder;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.KafkaStreams.StateListener;
-// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import org.apache.kafka.streams.kstream.*;
-// import org.apache.kafka.streams.state.Stores;
-// import org.geotools.referencing.GeodeticCalculator;
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-
-// import com.fasterxml.jackson.databind.ObjectMapper;
-
-// import java.time.format.DateTimeFormatter;
-// import java.util.Properties;
-
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedBsmJsonProcessorSupplier;
-// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
-
-// public class ProcessedBsmDeduplicatorTopology {
-
-// private static final Logger logger =
-// LoggerFactory.getLogger(ProcessedBsmDeduplicatorTopology.class);
-
-// Topology topology;
-// KafkaStreams streams;
-// DeduplicatorProperties props;
-// ObjectMapper objectMapper;
-// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-// GeodeticCalculator calculator;
-// Properties streamsProperties;
-
-// public ProcessedBsmDeduplicatorTopology(DeduplicatorProperties props,
-// Properties streamsProperties) {
-// this.props = props;
-// this.streamsProperties = streamsProperties;
-// this.objectMapper = DateJsonMapper.getInstance();
-// }
-
-// public void start() {
-// if (streams != null && streams.state().isRunningOrRebalancing()) {
-// throw new IllegalStateException("Start called while streams is already
-// running.");
-// }
-// Topology topology = buildTopology();
-// streams = new KafkaStreams(topology, streamsProperties);
-// if (exceptionHandler != null)
-// streams.setUncaughtExceptionHandler(exceptionHandler);
-// if (stateListener != null)
-// streams.setStateListener(stateListener);
-// logger.info("Starting Processed Bsm Deduplicator Topology");
-// streams.start();
-// }
-
-// public Topology buildTopology() {
-// StreamsBuilder builder = new StreamsBuilder();
-
-// KStream> inputStream =
-// builder.stream(this.props.getKafkaTopicProcessedBsm(),
-// Consumed.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
-
-// builder.addStateStore(
-// Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedBsmName()),
-// Serdes.String(), JsonSerdes.ProcessedBsm()));
-
-// KStream> deduplicatedStream =
-// inputStream.process(
-// new
-// ProcessedBsmJsonProcessorSupplier(props.getKafkaStateStoreProcessedBsmName(),
-// props),
-// props.getKafkaStateStoreProcessedBsmName());
-
-// deduplicatedStream.to(this.props.getKafkaTopicDeduplicatedProcessedBsm(),
-// Produced.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
-
-// return builder.build();
-
-// }
-
-// public void stop() {
-// logger.info("Stopping Processed Bsm deduplicator Topology.");
-// if (streams != null) {
-// streams.close();
-// streams.cleanUp();
-// streams = null;
-// }
-// logger.info("Stopped Processed Bsm deduplicator Topology.");
-// }
-
-// StateListener stateListener;
-
-// public void registerStateListener(StateListener stateListener) {
-// this.stateListener = stateListener;
-// }
-
-// StreamsUncaughtExceptionHandler exceptionHandler;
-
-// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
-// exceptionHandler) {
-// this.exceptionHandler = exceptionHandler;
-// }
-// }
+package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KafkaStreams;
+import org.apache.kafka.streams.StreamsBuilder;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.KafkaStreams.StateListener;
+import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import org.apache.kafka.streams.kstream.*;
+import org.apache.kafka.streams.state.Stores;
+import org.geotools.referencing.GeodeticCalculator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.time.format.DateTimeFormatter;
+
+import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedBsmJsonProcessorSupplier;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
+
+public class ProcessedBsmDeduplicatorTopology {
+
+ private static final Logger logger = LoggerFactory.getLogger(ProcessedBsmDeduplicatorTopology.class);
+
+ Topology topology;
+ KafkaStreams streams;
+ DeduplicatorProperties props;
+ ObjectMapper objectMapper;
+ DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+ GeodeticCalculator calculator;
+
+ public ProcessedBsmDeduplicatorTopology(DeduplicatorProperties props) {
+ this.props = props;
+ this.objectMapper = DateJsonMapper.getInstance();
+ }
+
+ public void start() {
+ if (streams != null && streams.state().isRunningOrRebalancing()) {
+ throw new IllegalStateException("Start called while streams is already running.");
+ }
+ Topology topology = buildTopology();
+ streams = new KafkaStreams(topology, props.createStreamProperties("ProcessedBsmDeduplicator"));
+ if (exceptionHandler != null)
+ streams.setUncaughtExceptionHandler(exceptionHandler);
+ if (stateListener != null)
+ streams.setStateListener(stateListener);
+ logger.info("Starting Processed Bsm Deduplicator Topology");
+ streams.start();
+ }
+
+ public Topology buildTopology() {
+ StreamsBuilder builder = new StreamsBuilder();
+
+ KStream> inputStream = builder.stream(this.props.getKafkaTopicProcessedBsm(),
+ Consumed.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
+
+ builder.addStateStore(
+ Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedBsmName()),
+ Serdes.String(), JsonSerdes.ProcessedBsm()));
+
+ KStream> deduplicatedStream = inputStream.process(
+ new ProcessedBsmJsonProcessorSupplier(props.getKafkaStateStoreProcessedBsmName(),
+ props),
+ props.getKafkaStateStoreProcessedBsmName());
+
+ deduplicatedStream.to(this.props.getKafkaTopicDeduplicatedProcessedBsm(),
+ Produced.with(Serdes.String(), JsonSerdes.ProcessedBsm()));
+
+ return builder.build();
+
+ }
+
+ public void stop() {
+ logger.info("Stopping Processed Bsm deduplicator Topology.");
+ if (streams != null) {
+ streams.close();
+ streams.cleanUp();
+ streams = null;
+ }
+ logger.info("Stopped Processed Bsm deduplicator Topology.");
+ }
+
+ StateListener stateListener;
+
+ public void registerStateListener(StateListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ StreamsUncaughtExceptionHandler exceptionHandler;
+
+ public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java
index 05a91fa..a0a30bd 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedSpatDeduplicatorTopology.java
@@ -1,105 +1,98 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KafkaStreams;
-// import org.apache.kafka.streams.StreamsBuilder;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.KafkaStreams.StateListener;
-// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedSpatProcessorSupplier;
-// import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-
-// import org.apache.kafka.streams.kstream.*;
-// import org.apache.kafka.streams.state.Stores;
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-
-// import com.fasterxml.jackson.databind.ObjectMapper;
-
-// import java.time.format.DateTimeFormatter;
-// import java.util.Properties;
-
-// public class ProcessedSpatDeduplicatorTopology {
-
-// private static final Logger logger =
-// LoggerFactory.getLogger(ProcessedSpatDeduplicatorTopology.class);
-
-// Topology topology;
-// KafkaStreams streams;
-// String inputTopic;
-// String outputTopic;
-// Properties streamsProperties;
-// ObjectMapper objectMapper;
-// DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
-// DeduplicatorProperties props;
-
-// public ProcessedSpatDeduplicatorTopology(DeduplicatorProperties props,
-// Properties streamsProperties){
-// this.props = props;
-// this.streamsProperties = streamsProperties;
-// this.objectMapper = DateJsonMapper.getInstance();
-// }
-
-// public void start() {
-// if (streams != null && streams.state().isRunningOrRebalancing()) {
-// throw new IllegalStateException("Start called while streams is already
-// running.");
-// }
-// Topology topology = buildTopology();
-// streams = new KafkaStreams(topology, streamsProperties);
-// if (exceptionHandler != null)
-// streams.setUncaughtExceptionHandler(exceptionHandler);
-// if (stateListener != null) streams.setStateListener(stateListener);
-// logger.info("Starting Map Deduplicator Topology");
-// streams.start();
-// }
-
-// public Topology buildTopology() {
-// StreamsBuilder builder = new StreamsBuilder();
-
-// KStream inputStream =
-// builder.stream(props.getKafkaTopicProcessedSpat(),
-// Consumed.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
-
-// builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedSpatName()),
-// Serdes.String(), JsonSerdes.ProcessedSpat()));
-
-// KStream deduplicatedStream = inputStream.process(new
-// ProcessedSpatProcessorSupplier(props),
-// props.getKafkaStateStoreProcessedSpatName());
-
-// deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedSpat(),
-// Produced.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
-
-// return builder.build();
-
-// }
-
-// public void stop() {
-// logger.info("Stopping Processed SPaT deduplicator Socket Broadcast
-// Topology.");
-// if (streams != null) {
-// streams.close();
-// streams.cleanUp();
-// streams = null;
-// }
-// logger.info("Stopped Processed SPaT deduplicator Socket Broadcast
-// Topology.");
-// }
-
-// StateListener stateListener;
-// public void registerStateListener(StateListener stateListener) {
-// this.stateListener = stateListener;
-// }
-
-// StreamsUncaughtExceptionHandler exceptionHandler;
-// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
-// exceptionHandler) {
-// this.exceptionHandler = exceptionHandler;
-// }
-// }
+package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KafkaStreams;
+import org.apache.kafka.streams.StreamsBuilder;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.KafkaStreams.StateListener;
+import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedSpatProcessorSupplier;
+import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+
+import org.apache.kafka.streams.kstream.*;
+import org.apache.kafka.streams.state.Stores;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.time.format.DateTimeFormatter;
+
+public class ProcessedSpatDeduplicatorTopology {
+
+ private static final Logger logger = LoggerFactory.getLogger(ProcessedSpatDeduplicatorTopology.class);
+
+ Topology topology;
+ KafkaStreams streams;
+ String inputTopic;
+ String outputTopic;
+ ObjectMapper objectMapper;
+ DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
+ DeduplicatorProperties props;
+
+ public ProcessedSpatDeduplicatorTopology(DeduplicatorProperties props) {
+ this.props = props;
+ this.objectMapper = DateJsonMapper.getInstance();
+ }
+
+ public void start() {
+ if (streams != null && streams.state().isRunningOrRebalancing()) {
+ throw new IllegalStateException("Start called while streams is already running.");
+ }
+ Topology topology = buildTopology();
+ streams = new KafkaStreams(topology, props.createStreamProperties("ProcessedSpatDeduplicator"));
+ if (exceptionHandler != null)
+ streams.setUncaughtExceptionHandler(exceptionHandler);
+ if (stateListener != null)
+ streams.setStateListener(stateListener);
+ logger.info("Starting Map Deduplicator Topology");
+ streams.start();
+ }
+
+ public Topology buildTopology() {
+ StreamsBuilder builder = new StreamsBuilder();
+
+ KStream inputStream = builder.stream(props.getKafkaTopicProcessedSpat(),
+ Consumed.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
+
+ builder.addStateStore(
+ Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedSpatName()),
+ Serdes.String(), JsonSerdes.ProcessedSpat()));
+
+ KStream deduplicatedStream = inputStream.process(
+ new ProcessedSpatProcessorSupplier(props),
+ props.getKafkaStateStoreProcessedSpatName());
+
+ deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedSpat(),
+ Produced.with(Serdes.String(), JsonSerdes.ProcessedSpat()));
+
+ return builder.build();
+
+ }
+
+ public void stop() {
+ logger.info("Stopping Processed SPaT deduplicator Socket Broadcast Topology.");
+ if (streams != null) {
+ streams.close();
+ streams.cleanUp();
+ streams = null;
+ }
+ logger.info("Stopped Processed SPaT deduplicator Socket Broadcast Topology.");
+ }
+
+ StateListener stateListener;
+
+ public void registerStateListener(StateListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ StreamsUncaughtExceptionHandler exceptionHandler;
+
+ public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/TimDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/TimDeduplicatorTopology.java
index f128da9..e8cd33f 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/TimDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/TimDeduplicatorTopology.java
@@ -8,9 +8,7 @@
import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-import us.dot.its.jpo.ode.model.OdeTimData;
-import us.dot.its.jpo.ode.model.OdeTimMetadata;
-import us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
import org.apache.kafka.streams.kstream.*;
import org.apache.kafka.streams.state.Stores;
@@ -21,8 +19,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.format.DateTimeFormatter;
-import java.util.Properties;
+import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformation;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeTimJsonProcessorSupplier;
import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
@@ -34,14 +32,12 @@ public class TimDeduplicatorTopology {
Topology topology;
KafkaStreams streams;
- Properties streamsProperties;
ObjectMapper objectMapper;
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
DeduplicatorProperties props;
- public TimDeduplicatorTopology(DeduplicatorProperties props, Properties streamsProperties) {
+ public TimDeduplicatorTopology(DeduplicatorProperties props) {
this.props = props;
- this.streamsProperties = streamsProperties;
this.objectMapper = DateJsonMapper.getInstance();
}
@@ -50,7 +46,7 @@ public void start() {
throw new IllegalStateException("Start called while streams is already running.");
}
Topology topology = buildTopology();
- streams = new KafkaStreams(topology, streamsProperties);
+ streams = new KafkaStreams(topology, props.createStreamProperties("TimDeduplicator"));
if (exceptionHandler != null)
streams.setUncaughtExceptionHandler(exceptionHandler);
if (stateListener != null)
@@ -68,34 +64,29 @@ public JsonNode genJsonNode() {
public Topology buildTopology() {
StreamsBuilder builder = new StreamsBuilder();
- KStream inputStream = builder.stream(props.getKafkaTopicOdeTimJson(),
- Consumed.with(Serdes.String(), JsonSerdes.OdeTim()));
+ KStream inputStream = builder.stream(props.getKafkaTopicOdeTimJson(),
+ Consumed.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreOdeTimJsonName()),
- Serdes.String(), JsonSerdes.OdeTim()));
+ Serdes.String(), JsonSerdes.OdeMessageFrame()));
- KStream timRekeyedStream = inputStream.selectKey((key, value) -> {
+ KStream timRekeyedStream = inputStream.selectKey((key, value) -> {
try {
-
- TravelerInformation travellerInformation = (TravelerInformation)value.getPayload().getData();
-
-
- String rsuIP = ((OdeTimMetadata)value.getMetadata()).getOriginIp();
- // String packetId = ((OdeTimPayload)value.getPayload()).getData();// .get("packetID").asText();
- String packetId = travellerInformation.getPacketID().toString();
- int msgCnt = travellerInformation.getMsgCnt().intValue();
-
+ TravelerInformation travellerInformation = (TravelerInformation) value.getPayload().getData().getValue();
+ String rsuIP = value.getMetadata().getOriginIp();
+ String packetId = travellerInformation.getPacketID().getValue();
+ int msgCnt = (int) travellerInformation.getMsgCnt().getValue();
String newKey = rsuIP + "_" + packetId + "_" + msgCnt;
return newKey;
} catch (Exception e) {
logger.error(e.toString());
return "";
}
- }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeTim()));
+ }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
- KStream deduplicatedStream = timRekeyedStream.process(new OdeTimJsonProcessorSupplier(props), props.getKafkaStateStoreOdeTimJsonName());
+ KStream deduplicatedStream = timRekeyedStream.process(new OdeTimJsonProcessorSupplier(props), props.getKafkaStateStoreOdeTimJsonName());
- deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeTimJson(), Produced.with(Serdes.String(), JsonSerdes.OdeTim()));
+ deduplicatedStream.to(props.getKafkaTopicDeduplicatedOdeTimJson(), Produced.with(Serdes.String(), JsonSerdes.OdeMessageFrame()));
return builder.build();
diff --git a/jpo-deduplicator/src/main/resources/application.yaml b/jpo-deduplicator/src/main/resources/application.yaml
index 0a7d512..366a30d 100644
--- a/jpo-deduplicator/src/main/resources/application.yaml
+++ b/jpo-deduplicator/src/main/resources/application.yaml
@@ -37,11 +37,6 @@ kafkaTopicOdeTimJson: topic.OdeTimJson
kafkaTopicDeduplicatedOdeTimJson: topic.DeduplicatedOdeTimJson
enableOdeTimDeduplication: ${ENABLE_ODE_TIM_DEDUPLICATION:true}
-# Ode Raw Encoded Tim Json Configuration
-kafkaTopicOdeRawEncodedTimJson: topic.OdeRawEncodedTIMJson
-kafkaTopicDeduplicatedOdeRawEncodedTimJson: topic.DeduplicatedOdeRawEncodedTIMJson
-enableOdeRawEncodedTimDeduplication: ${ENABLE_ODE_RAW_ENCODED_TIM_DEDUPLICATION:true}
-
# Ode Bsm Json Configuration
kafkaTopicOdeBsmJson: topic.OdeBsmJson
kafkaTopicDeduplicatedOdeBsmJson: topic.DeduplicatedOdeBsmJson
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
index c130aab..1a83f33 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/BsmDeduplicatorTopologyTest.java
@@ -2,7 +2,9 @@
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.TestInputTopic;
@@ -24,11 +26,10 @@
import us.dot.its.jpo.asn.j2735.r2024.Common.Speed;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.BsmDeduplicatorTopology;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
import us.dot.its.jpo.ode.model.OdeMessageFrameData;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -71,11 +72,11 @@ public class BsmDeduplicatorTopologyTest {
@Before
public void setup() throws IOException {
- objectMapper = new ObjectMapper();
+ objectMapper = DateJsonMapper.getInstance();
// Load test files from resources
- // Reference MAP
+ // Reference BSM
String bsmReference = new String(
Files.readAllBytes(Paths
.get("src/test/resources/json/ode_bsm/sample.ode-bsm-reference.json")));
@@ -137,14 +138,28 @@ public void setup() throws IOException {
bsmMfSpeedMissing.getValue().getCoreData().setSpeed(null);
inputBsm8 = bsmSpeedMissing.toJson();
- // Vehicle is missing its set to unavailable, should be forwarded
+ // Vehicle is missing its set to unavailable, should be dropped
OdeMessageFrameData bsmSetToUnavailable = objectMapper.readValue(bsmReferenceData.toJson(),
OdeMessageFrameData.class);
BasicSafetyMessageMessageFrame bsmMfSetToUnavailable = (BasicSafetyMessageMessageFrame) bsmSetToUnavailable
.getPayload().getData();
bsmMfSetToUnavailable.getValue().getCoreData().setSpeed(new Speed(8191));
inputBsm9 = bsmSetToUnavailable.toJson();
+ }
+ @Test
+ public void testSerialization() throws JsonMappingException, JsonProcessingException {
+ OdeMessageFrameData bsm = objectMapper.readValue(inputBsm1, OdeMessageFrameData.class);
+ String json = objectMapper.writeValueAsString(bsm);
+ assertEquals(inputBsm1, json);
+ }
+
+ @Test
+ public void testJsonSerdes() {
+ Serde serdes = JsonSerdes.OdeMessageFrame();
+ OdeMessageFrameData deserialized = serdes.deserializer().deserialize(null, inputBsm1.getBytes());
+ byte[] serialized = serdes.serializer().serialize(null, deserialized);
+ assertThat(new String(serialized), jsonEquals(inputBsm1));
}
@Test
@@ -185,10 +200,9 @@ public void testTopology() {
List> bsmDeduplicationResults = outputOdeBsmData
.readKeyValuesToList();
- // validate that only 8 messages make it through
+ // validate that only 7 messages make it through
assertEquals(7, bsmDeduplicationResults.size());
- objectMapper = new ObjectMapper();
OdeMessageFrameData bsm1 = objectMapper.readValue(inputBsm1, OdeMessageFrameData.class);
OdeMessageFrameData bsm3 = objectMapper.readValue(inputBsm3, OdeMessageFrameData.class);
OdeMessageFrameData bsm4 = objectMapper.readValue(inputBsm4, OdeMessageFrameData.class);
@@ -206,10 +220,8 @@ public void testTopology() {
assertThat(bsmDeduplicationResults.get(6).value.toJson(), jsonEquals(bsm8.toJson()));
} catch (JsonMappingException e) {
- // TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonProcessingException e) {
- // TODO Auto-generated catch block
e.printStackTrace();
}
}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
index e71a128..d78f5d1 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/MapDeduplicatorTopologyTest.java
@@ -2,7 +2,9 @@
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.TestInputTopic;
@@ -19,11 +21,10 @@
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
import us.dot.its.jpo.ode.model.OdeMessageFrameData;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -48,7 +49,7 @@ public class MapDeduplicatorTopologyTest {
@Before
public void setup() throws IOException {
- objectMapper = new ObjectMapper();
+ objectMapper = DateJsonMapper.getInstance();
// Load test files from resources
// Reference MAP
@@ -86,6 +87,21 @@ public void setup() throws IOException {
inputMap5 = map1HourLater.toJson();
}
+ @Test
+ public void testSerialization() throws JsonMappingException, JsonProcessingException {
+ OdeMessageFrameData map = objectMapper.readValue(inputMap1, OdeMessageFrameData.class);
+ String json = objectMapper.writeValueAsString(map);
+ assertEquals(inputMap1, json);
+ }
+
+ @Test
+ public void testJsonSerdes() {
+ Serde serdes = JsonSerdes.OdeMessageFrame();
+ OdeMessageFrameData deserialized = serdes.deserializer().deserialize(null, inputMap1.getBytes());
+ byte[] serialized = serdes.serializer().serialize(null, deserialized);
+ assertThat(new String(serialized), jsonEquals(inputMap1));
+ }
+
@Test
public void testTopology() {
@@ -94,7 +110,6 @@ public void testTopology() {
props.setKafkaTopicDeduplicatedOdeMapJson(outputTopic);
MapDeduplicatorTopology mapDeduplicatorTopology = new MapDeduplicatorTopology(props);
-
Topology topology = mapDeduplicatorTopology.buildTopology();
try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
@@ -121,7 +136,6 @@ public void testTopology() {
// validate that only 3 messages make it through
assertEquals(3, mapDeduplicationResults.size());
- objectMapper = new ObjectMapper();
OdeMessageFrameData map1 = objectMapper.readValue(inputMap1, OdeMessageFrameData.class);
OdeMessageFrameData map3 = objectMapper.readValue(inputMap4, OdeMessageFrameData.class);
OdeMessageFrameData map4 = objectMapper.readValue(inputMap5, OdeMessageFrameData.class);
@@ -131,10 +145,8 @@ public void testTopology() {
assertThat(mapDeduplicationResults.get(2).value.toJson(), jsonEquals(map4.toJson()));
} catch (JsonMappingException e) {
- // TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonProcessingException e) {
- // TODO Auto-generated catch block
e.printStackTrace();
}
}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java
deleted file mode 100644
index 947eb22..0000000
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/OdeRawEncodedTimDeduplicatorTopologyTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// package us.dot.its.jpo.deduplicator.deduplicator;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KeyValue;
-// import org.apache.kafka.streams.TestInputTopic;
-// import org.apache.kafka.streams.TestOutputTopic;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.TopologyTestDriver;
-// import org.junit.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
-
-// import com.fasterxml.jackson.databind.ObjectMapper;
-// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.topologies.OdeRawEncodedTimDeduplicatorTopology;
-// import static org.junit.jupiter.api.Assertions.assertEquals;
-
-// import java.util.List;
-
-// public class OdeRawEncodedTimDeduplicatorTopologyTest {
-
-// String inputTopic = "topic.OdeRawEncodedTIMJson";
-// String outputTopic = "topic.DeduplicatedOdeRawEncodedTIMJson";
-
-// ObjectMapper objectMapper = new ObjectMapper();
-
-// // Original Message
-// String inputTim1 = "{ \"metadata\": { \"securityResultCode\": \"success\",
-// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
-// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
-// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
-// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
-// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
-// \"2024-07-22T23:23:29.553Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
-// \"data\": { \"bytes\":
-// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
-// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
-// // Shifted Forward .1 seconds - Should be deduplicated
-// String inputTim2 = "{ \"metadata\": { \"securityResultCode\": \"success\",
-// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
-// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
-// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
-// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
-// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
-// \"2024-07-22T23:23:29.653Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
-// \"data\": { \"bytes\":
-// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
-// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
-// // Shifted Forward 1 hour Should be allowed to pass through
-// String inputTim3 = "{ \"metadata\": { \"securityResultCode\": \"success\",
-// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
-// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
-// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
-// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
-// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
-// \"2024-07-23T00:23:29.653Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
-// \"data\": { \"bytes\":
-// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
-// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
-// // Has a different payload ID. Should be allowed through
-// String inputTim4 = "{ \"metadata\": { \"securityResultCode\": \"success\",
-// \"recordGeneratedBy\": \"RSU\", \"schemaVersion\": 6, \"payloadType\":
-// \"us.dot.its.jpo.ode.model.OdeAsn1Payload\", \"serialId\": { \"recordId\": 0,
-// \"serialNumber\": 0, \"streamId\": \"5f470323-7770-4810-b225-8c45aa672103\",
-// \"bundleSize\": 1, \"bundleId\": 0 }, \"sanitized\": false, \"recordType\":
-// \"timMsg\", \"maxDurationTime\": 0, \"odeReceivedAt\":
-// \"2024-07-22T23:23:29.553Z\", \"originIp\": \"10.16.28.53\" }, \"payload\": {
-// \"data\": { \"bytes\":
-// \"001F63701409FF38D05CD47AF567A4570F775D9B0301C269D16DD9656F9637FFF93F421D3B001EA007F99937E1CF5AD1BB0BF4A9D5BEC5BB25CC5B2E64E173162DA00000000269D16DD9656F9631388C100021000EBF7272441F8CFDED60004008027BBAECD8A1A81EF1C153853DD08B394DDCE85F7F4F2222BE087C98000801004F775D9B002F378A81FD1358540F893502C0B711D815FF7883E0A9AACF804536FC9E2A39A67D4289155859ABA8ACBD4997855D345BA429991568E1CA702BA1D8ADFF4805456C0A46862B7F41BE614A122DFB8B0FA019FC52FC8AFF62A7DA3D3F1C9A00BC220AA6B0DC20571A23C142A8C0368F14D181D9B8E2FA859714531606FF8197DC2D81469C97540A33D8D25850D7CA7E82916C1F82142D3A8A20A4884311C320C8EB2290AD1BAC0C84856E8A1B1D760C51BE458B8189591FF0C64E68D0004008027BBAECD9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"
-// }, \"dataType\": \"us.dot.its.jpo.ode.model.OdeHexByteArray\" }}";
-
-// @Autowired
-// DeduplicatorProperties props;
-
-// @Test
-// public void testTopology() {
-
-// props = new DeduplicatorProperties();
-// props.setKafkaTopicOdeRawEncodedTimJson(inputTopic);
-// props.setKafkaTopicDeduplicatedOdeRawEncodedTimJson(outputTopic);
-
-// OdeRawEncodedTimDeduplicatorTopology TimDeduplicatorTopology = new
-// OdeRawEncodedTimDeduplicatorTopology(props, null);
-
-// Topology topology = TimDeduplicatorTopology.buildTopology();
-// objectMapper.registerModule(new JavaTimeModule());
-
-// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-// TestInputTopic inputTimData = driver.createInputTopic(
-// inputTopic,
-// Serdes.Void().serializer(),
-// Serdes.String().serializer());
-
-// TestOutputTopic outputTimData = driver.createOutputTopic(
-// outputTopic,
-// Serdes.String().deserializer(),
-// Serdes.String().deserializer());
-
-// inputTimData.pipeInput(null, inputTim1);
-// inputTimData.pipeInput(null, inputTim2);
-// inputTimData.pipeInput(null, inputTim3);
-// inputTimData.pipeInput(null, inputTim4);
-
-// List> timDeduplicatedResults =
-// outputTimData.readKeyValuesToList();
-
-// // validate that only 3 messages make it through
-// assertEquals(3, timDeduplicatedResults.size());
-// inputTim1 = inputTim1.strip();
-
-// assertEquals(inputTim1.replace(" ", ""),
-// timDeduplicatedResults.get(0).value.replace(" ", ""));
-// assertEquals(inputTim3.replace(" ", ""),
-// timDeduplicatedResults.get(1).value.replace(" ", ""));
-// assertEquals(inputTim4.replace(" ", ""),
-// timDeduplicatedResults.get(2).value.replace(" ", ""));
-
-// }catch(Exception e){
-// e.printStackTrace();
-// }
-// }
-// }
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java
index c143ae8..e88e2db 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedBsmDeduplicatorTopologyTest.java
@@ -1,173 +1,226 @@
-// package us.dot.its.jpo.deduplicator.deduplicator;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KeyValue;
-// import org.apache.kafka.streams.TestInputTopic;
-// import org.apache.kafka.streams.TestOutputTopic;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.TopologyTestDriver;
-// import org.junit.Before;
-// import org.junit.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
-
-// import com.fasterxml.jackson.core.JsonProcessingException;
-// import com.fasterxml.jackson.databind.JsonMappingException;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-// import com.fasterxml.jackson.core.type.TypeReference;
-
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
-// import static org.junit.jupiter.api.Assertions.assertEquals;
-
-// import java.io.IOException;
-// import java.nio.file.Files;
-// import java.nio.file.Paths;
-// import java.util.List;
-
-// public class ProcessedBsmDeduplicatorTopologyTest {
-
-// String inputTopic = "topic.ProcessedBsmJson";
-// String outputTopic = "topic.DeduplicatedOdeBsmJson";
-// ObjectMapper objectMapper;
-
-// String inputProcessedBsmReference = "";
-
-// // Same as BSM 1 - No Message should be generated
-// String inputProcessedBsmDuplicate = "";
-
-// // Increase Time from Bsm 1
-// String inputProcessedBsmTimeDelta = "";
-
-// // Vehicle Speed not 0
-// String inputProcessedBsmWithSpeed = "";
-
-// // Vehicle Position has changed
-// String inputProcessedBsmChanged = "";
-
-// // Vehicle Position was removed
-// String inputProcessedBsmMissingPosition = "";
-
-// // Vehicle Position was added back in
-// String inputProcessedBsmWithPosition = "";
-
-// // Vehicle Speed was added back in
-// String inputProcessedBsmMissingSpeed = "";
-
-// String key =
-// "{\"rsuId\":\"172.19.0.1\",\"logId\":\"1234567890\",\"bsmId\":\"31325433\"}";
-
-// @Autowired
-// DeduplicatorProperties props;
-
-// @Before
-// public void setup() throws IOException {
-// inputProcessedBsmReference = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json")));
-// inputProcessedBsmDuplicate = inputProcessedBsmReference;
-// inputProcessedBsmTimeDelta = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json")));
-// inputProcessedBsmWithSpeed = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json")));
-// inputProcessedBsmChanged = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-different.json")));
-// inputProcessedBsmMissingPosition = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json")));
-// inputProcessedBsmWithPosition = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json")));
-// inputProcessedBsmMissingSpeed = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json")));
-
-// }
-
-// @Test
-// public void testTopology() {
-// props = new DeduplicatorProperties();
-// props.setAlwaysIncludeAtSpeed(1);
-// props.setEnableProcessedBsmDeduplication(true);
-// props.setProcessedBsmMaximumPositionDelta(1);
-// props.setProcessedBsmMaximumTimeDelta(10000);
-// props.setKafkaTopicProcessedBsm(inputTopic);
-// props.setKafkaTopicDeduplicatedProcessedBsm(outputTopic);
-
-// ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new
-// ProcessedBsmDeduplicatorTopology(props, null);
-// Topology topology = processedBsmDeduplicatorTopology.buildTopology();
-
-// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-// TestInputTopic inputProcessedBsmData =
-// driver.createInputTopic(
-// inputTopic,
-// Serdes.String().serializer(),
-// Serdes.String().serializer());
-
-// TestOutputTopic> outputProcessedBsmData =
-// driver.createOutputTopic(
-// outputTopic,
-// Serdes.String().deserializer(),
-// JsonSerdes.ProcessedBsm().deserializer());
-
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmReference);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmDuplicate);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmTimeDelta);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmWithSpeed);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmChanged);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmMissingPosition);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmWithPosition);
-// inputProcessedBsmData.pipeInput(key, inputProcessedBsmMissingSpeed);
-
-// List>> processedBsmDeduplicationResults
-// = outputProcessedBsmData.readKeyValuesToList();
-
-// // validate that only 7 messages make it through
-// assertEquals(7, processedBsmDeduplicationResults.size());
-
-// objectMapper = new ObjectMapper();
-// ProcessedBsm outputProcessedBsmReference =
-// objectMapper.readValue(inputProcessedBsmReference, new
-// TypeReference>() {});
-// ProcessedBsm outputProcessedBsmTimeDelta =
-// objectMapper.readValue(inputProcessedBsmTimeDelta, new
-// TypeReference>() {});
-// ProcessedBsm outputProcessedBsmWithSpeed =
-// objectMapper.readValue(inputProcessedBsmWithSpeed, new
-// TypeReference>() {});
-// ProcessedBsm outputProcessedBsmChanged =
-// objectMapper.readValue(inputProcessedBsmChanged, new
-// TypeReference>() {});
-// ProcessedBsm outputProcessedBsmMissingPosition =
-// objectMapper.readValue(inputProcessedBsmChanged, new
-// TypeReference>() {});
-// ProcessedBsm outputProcessedBsmWithPosition =
-// objectMapper.readValue(inputProcessedBsmWithPosition, new
-// TypeReference>() {});
-// ProcessedBsm outputProcessedBsmMissingSpeed =
-// objectMapper.readValue(inputProcessedBsmMissingSpeed, new
-// TypeReference>() {});
-
-// assertEquals(outputProcessedBsmReference.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(0).value.getProperties().getOdeReceivedAt());
-// assertEquals(outputProcessedBsmTimeDelta.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(1).value.getProperties().getOdeReceivedAt());
-// assertEquals(outputProcessedBsmWithSpeed.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(2).value.getProperties().getOdeReceivedAt());
-// assertEquals(outputProcessedBsmChanged.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(3).value.getProperties().getOdeReceivedAt());
-// assertEquals(outputProcessedBsmMissingPosition.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(4).value.getProperties().getOdeReceivedAt());
-// assertEquals(outputProcessedBsmWithPosition.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(5).value.getProperties().getOdeReceivedAt());
-// assertEquals(outputProcessedBsmMissingSpeed.getProperties().getOdeReceivedAt(),
-// processedBsmDeduplicationResults.get(6).value.getProperties().getOdeReceivedAt());
-
-// } catch (JsonMappingException e) {
-// e.printStackTrace();
-// } catch (JsonProcessingException e) {
-// e.printStackTrace();
-// }
-// }
-// }
\ No newline at end of file
+package us.dot.its.jpo.deduplicator.deduplicator;
+
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.kafka.common.serialization.Serde;
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KeyValue;
+import org.apache.kafka.streams.TestInputTopic;
+import org.apache.kafka.streams.TestOutputTopic;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.TopologyTestDriver;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.Point;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.bsm.ProcessedBsm;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.Instant;
+import java.time.ZonedDateTime;
+import java.util.List;
+
+public class ProcessedBsmDeduplicatorTopologyTest {
+
+ String inputTopic = "topic.ProcessedBsmJson";
+ String outputTopic = "topic.DeduplicatedOdeBsmJson";
+ ObjectMapper objectMapper;
+
+ String inputProcessedBsm1 = "";
+
+ // Same as BSM 1 - No Message should be generated
+ String inputProcessedBsm2 = "";
+
+ // Increase Time from BSM 1
+ String inputProcessedBsm3 = "";
+
+ // Vehicle Speed not 0
+ String inputProcessedBsm4 = "";
+
+ // Vehicle Position has changed
+ String inputProcessedBsm5 = "";
+
+ // Vehicle Position was removed
+ String inputProcessedBsm6 = "";
+
+ // Vehicle Position was added back in
+ String inputProcessedBsm7 = "";
+
+ // Vehicle Speed was removed
+ String inputProcessedBsm8 = "";
+
+ String key = "{\"rsuId\":\"172.19.0.1\",\"logId\":\"1234567890\",\"bsmId\":\"31325433\"}";
+
+ @Autowired
+ DeduplicatorProperties props;
+
+ @Before
+ public void setup() throws IOException {
+ objectMapper = DateJsonMapper.getInstance();
+
+ // Load test files from resources
+ // Reference Processed BSM
+ String processedBsmReference = new String(
+ Files.readAllBytes(Paths
+ .get("src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json")));
+ ProcessedBsm processedBsmReferenceData = objectMapper.readValue(processedBsmReference,
+ new TypeReference>() {
+ });
+
+ // Reference Processed BSM, Should be forwarded
+ inputProcessedBsm1 = processedBsmReferenceData.toString();
+
+ // Duplicate of Number 1, should be dropped
+ inputProcessedBsm2 = processedBsmReferenceData.toString();
+
+ // Increase Time from Bsm 1, Should be forwarded
+ ProcessedBsm processedBsmIncreaseTime = objectMapper.readValue(processedBsmReferenceData.toString(),
+ new TypeReference>() {
+ });
+ // Convert ZonedDateTime to Instant, add 15 seconds, then convert back
+ ZonedDateTime originalZdt = processedBsmIncreaseTime.getProperties().getTimeStamp();
+ Instant newInstant = originalZdt.toInstant().plusSeconds(15);
+ processedBsmIncreaseTime.getProperties()
+ .setTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone()));
+ inputProcessedBsm3 = processedBsmIncreaseTime.toString();
+
+ // Vehicle Speed not 0, Should be Forwarded
+ ProcessedBsm processedBsmSpeedNotZero = objectMapper.readValue(processedBsmReferenceData.toString(),
+ new TypeReference>() {
+ });
+ processedBsmSpeedNotZero.getProperties().setSpeed(10.0);
+ inputProcessedBsm4 = processedBsmSpeedNotZero.toString();
+
+ // Vehicle Position has changed, Should be Forwarded
+ ProcessedBsm processedBsmPositionChanged = new ProcessedBsm(null,
+ new Point(new double[] { -105.0, 50.0 }), processedBsmReferenceData.getProperties());
+ inputProcessedBsm5 = processedBsmPositionChanged.toString();
+
+ // Vehicle Position was removed. Should be Forwarded
+ ProcessedBsm processedBsmPositionRemoved = new ProcessedBsm(null,
+ null, processedBsmReferenceData.getProperties());
+ inputProcessedBsm6 = processedBsmPositionRemoved.toString();
+
+ // Vehicle Position was added back in. Should be Forwarded
+ ProcessedBsm processedBsmPositionAddedBack = objectMapper.readValue(processedBsmReferenceData.toString(),
+ new TypeReference>() {
+ });
+ inputProcessedBsm7 = processedBsmPositionAddedBack.toString();
+
+ // Vehicle is missing its speed section, Should be Forwarded
+ ProcessedBsm processedBsmSpeedMissing = objectMapper.readValue(processedBsmReferenceData.toString(),
+ new TypeReference>() {
+ });
+ processedBsmSpeedMissing.getProperties().setSpeed(null);
+ inputProcessedBsm8 = processedBsmSpeedMissing.toString();
+ }
+
+ @Test
+ public void testSerialization() throws JsonMappingException, JsonProcessingException {
+ ProcessedBsm processedBsm = objectMapper.readValue(inputProcessedBsm1,
+ new TypeReference>() {
+ });
+ String json = processedBsm.toString();
+ assertEquals(inputProcessedBsm1, json);
+ }
+
+ @Test
+ public void testJsonSerdes() throws IOException {
+ Serde> serdes = JsonSerdes.ProcessedBsm();
+ ProcessedBsm deserialized = serdes.deserializer().deserialize(null, inputProcessedBsm1.getBytes());
+ byte[] serialized = serdes.serializer().serialize(null, deserialized);
+ String serializedString = new String(serialized);
+ assertThat(serializedString, jsonEquals(inputProcessedBsm1));
+ }
+
+ @Test
+ public void testTopology() {
+ props = new DeduplicatorProperties();
+ props.setAlwaysIncludeAtSpeed(1);
+ props.setEnableProcessedBsmDeduplication(true);
+ props.setProcessedBsmMaximumPositionDelta(1);
+ props.setProcessedBsmMaximumTimeDelta(10000);
+ props.setKafkaTopicProcessedBsm(inputTopic);
+ props.setKafkaTopicDeduplicatedProcessedBsm(outputTopic);
+
+ ProcessedBsmDeduplicatorTopology processedBsmDeduplicatorTopology = new ProcessedBsmDeduplicatorTopology(props);
+ Topology topology = processedBsmDeduplicatorTopology.buildTopology();
+
+ try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+ TestInputTopic inputProcessedBsmData = driver.createInputTopic(
+ inputTopic,
+ Serdes.String().serializer(),
+ Serdes.String().serializer());
+
+ TestOutputTopic> outputProcessedBsmData = driver.createOutputTopic(
+ outputTopic,
+ Serdes.String().deserializer(),
+ JsonSerdes.ProcessedBsm().deserializer());
+
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm1);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm2);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm3);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm4);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm5);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm6);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm7);
+ inputProcessedBsmData.pipeInput(key, inputProcessedBsm8);
+
+ List>> processedBsmDeduplicationResults = outputProcessedBsmData
+ .readKeyValuesToList();
+
+ // validate that only 7 messages make it through
+ assertEquals(7, processedBsmDeduplicationResults.size());
+
+ ProcessedBsm processedBsm1 = objectMapper.readValue(inputProcessedBsm1,
+ new TypeReference>() {
+ });
+ ProcessedBsm processedBsm3 = objectMapper.readValue(inputProcessedBsm3,
+ new TypeReference>() {
+ });
+ ProcessedBsm processedBsm4 = objectMapper.readValue(inputProcessedBsm4,
+ new TypeReference>() {
+ });
+ ProcessedBsm processedBsm5 = objectMapper.readValue(inputProcessedBsm5,
+ new TypeReference>() {
+ });
+ ProcessedBsm processedBsm6 = objectMapper.readValue(inputProcessedBsm6,
+ new TypeReference>() {
+ });
+ ProcessedBsm processedBsm7 = objectMapper.readValue(inputProcessedBsm7,
+ new TypeReference>() {
+ });
+ ProcessedBsm processedBsm8 = objectMapper.readValue(inputProcessedBsm8,
+ new TypeReference>() {
+ });
+
+ assertThat(processedBsmDeduplicationResults.get(0).value.toString(), jsonEquals(processedBsm1.toString()));
+ assertThat(processedBsmDeduplicationResults.get(1).value.toString(), jsonEquals(processedBsm3.toString()));
+ assertThat(processedBsmDeduplicationResults.get(2).value.toString(), jsonEquals(processedBsm4.toString()));
+ assertThat(processedBsmDeduplicationResults.get(3).value.toString(), jsonEquals(processedBsm5.toString()));
+ assertThat(processedBsmDeduplicationResults.get(4).value.toString(), jsonEquals(processedBsm6.toString()));
+ assertThat(processedBsmDeduplicationResults.get(5).value.toString(), jsonEquals(processedBsm7.toString()));
+ assertThat(processedBsmDeduplicationResults.get(6).value.toString(), jsonEquals(processedBsm8.toString()));
+
+ } catch (JsonMappingException e) {
+ e.printStackTrace();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java
index 1ef5442..e076104 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedSpatDeduplicatorTopologyTest.java
@@ -1,302 +1,184 @@
-// package us.dot.its.jpo.deduplicator.deduplicator;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KeyValue;
-// import org.apache.kafka.streams.TestInputTopic;
-// import org.apache.kafka.streams.TestOutputTopic;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.TopologyTestDriver;
-// import org.junit.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
-
-// import com.fasterxml.jackson.core.JsonProcessingException;
-// import com.fasterxml.jackson.core.type.TypeReference;
-// import com.fasterxml.jackson.databind.JsonMappingException;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
-// import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import static org.junit.jupiter.api.Assertions.assertEquals;
-
-// import java.util.List;
-
-// public class ProcessedSpatDeduplicatorTopologyTest {
-
-// String inputTopic = "topic.ProcessedSpat";
-// String outputTopic = "topic.DeduplicatedProcessedSpat";
-
-// TypeReference typeReference = new TypeReference<>(){};
-// ObjectMapper objectMapper = new ObjectMapper();
-
-// // Reference Message
-// String inputProcessedSpat1 =
-// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:04:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:04:35.176Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
-// // Deduplicated Message - Same as Reference.
-// String inputProcessedSpat2 =
-// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:04:35.276Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
-// // Fast forward 1 minute
-// String inputProcessedSpat3 =
-// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:57.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:36.376Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
-// // Remove a Signal Group
-// String inputProcessedSpat4 =
-// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:36.496Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
-// // Change the ID of a Signal Group
-// String inputProcessedSpat5 =
-// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:35.576Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":7,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
-// // Change the Light State of one of the Signal Groups
-// String inputProcessedSpat6 =
-// "{\"schemaVersion\":1,\"messageType\":\"SPAT\",\"odeReceivedAt\":\"2025-02-01T00:05:56.686Z\",\"originIp\":\"172.20.0.1\",\"intersectionId\":12111,\"cti4501Conformant\":false,\"validationMessages\":[{\"message\":\"$.payload.data.timeStamp:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data\",\"schemaPath\":\"#/$defs/J2735SPAT/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id.region:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].id\",\"schemaPath\":\"#/$defs/J2735IntersectionReferenceID/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[0].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[1].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[2].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[3].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[4].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.startTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"},{\"message\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing.nextTime:
-// is missing but it is
-// required\",\"jsonPath\":\"$.payload.data.intersectionStateList.intersectionStatelist[0].states.movementList[5].state_time_speed.movementEventList[0].timing\",\"schemaPath\":\"#/$defs/J2735TimeChangeDetails/required\"}],\"revision\":0,\"status\":{\"manualControlIsEnabled\":false,\"stopTimeIsActivated\":false,\"failureFlash\":false,\"preemptIsActive\":false,\"signalPriorityIsActive\":false,\"fixedTimeOperation\":false,\"trafficDependentOperation\":false,\"standbyOperation\":false,\"failureMode\":false,\"off\":false,\"recentMAPmessageUpdate\":false,\"recentChangeInMAPassignedLanesIDsUsed\":false,\"noValidMAPisAvailableAtThisTime\":false,\"noValidSPATisAvailableAtThisTime\":false},\"utcTimeStamp\":\"2025-02-01T00:05:35.676Z\",\"states\":[{\"signalGroup\":2,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":4,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:58.1Z\",\"maxEndTime\":\"2025-02-01T00:36:58.1Z\"}}]},{\"signalGroup\":6,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:52Z\",\"maxEndTime\":\"2025-02-01T00:36:52.1Z\"}}]},{\"signalGroup\":8,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":1,\"stateTimeSpeed\":[{\"eventState\":\"PROTECTED_MOVEMENT_ALLOWED\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]},{\"signalGroup\":5,\"stateTimeSpeed\":[{\"eventState\":\"STOP_AND_REMAIN\",\"timing\":{\"minEndTime\":\"2025-02-01T00:36:25.2Z\",\"maxEndTime\":\"2025-02-01T00:36:25.2Z\"}}]}]}";
-
-// String key = "{\"rsuId\": \"10.164.6.16\", \"intersectionId\": 6311,
-// \"region\": -1}";
-
-// @Autowired
-// DeduplicatorProperties props;
-
-// @Test
-// public void testTopology() {
-
-// props = new DeduplicatorProperties();
-// props.setKafkaTopicProcessedSpat(inputTopic);
-// props.setKafkaTopicDeduplicatedProcessedSpat(outputTopic);
-
-// ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new
-// ProcessedSpatDeduplicatorTopology(props, null);
-
-// Topology topology = processedSpatDeduplicatorTopology.buildTopology();
-// objectMapper.registerModule(new JavaTimeModule());
-
-// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-// TestInputTopic inputProcessedSpatData =
-// driver.createInputTopic(
-// inputTopic,
-// Serdes.String().serializer(),
-// Serdes.String().serializer());
-
-// TestOutputTopic outputProcessedSpatData =
-// driver.createOutputTopic(
-// outputTopic,
-// Serdes.String().deserializer(),
-// JsonSerdes.ProcessedSpat().deserializer());
-
-// inputProcessedSpatData.pipeInput(key, inputProcessedSpat1);
-// inputProcessedSpatData.pipeInput(key, inputProcessedSpat2);
-// inputProcessedSpatData.pipeInput(key, inputProcessedSpat3);
-// inputProcessedSpatData.pipeInput(key, inputProcessedSpat4);
-// inputProcessedSpatData.pipeInput(key, inputProcessedSpat5);
-// inputProcessedSpatData.pipeInput(key, inputProcessedSpat6);
-
-// List> spatDeduplicatorResults =
-// outputProcessedSpatData.readKeyValuesToList();
-
-// // validate that only 5 messages make it through
-// assertEquals(5, spatDeduplicatorResults.size());
-
-// ProcessedSpat spat1 = objectMapper.readValue(inputProcessedSpat1,
-// typeReference);
-// ProcessedSpat spat3 = objectMapper.readValue(inputProcessedSpat3,
-// typeReference); // forwarded because the time on the message changes by 1
-// minute
-// ProcessedSpat spat4 = objectMapper.readValue(inputProcessedSpat4,
-// typeReference); // forwarded because the signal state changes
-// ProcessedSpat spat5 = objectMapper.readValue(inputProcessedSpat5,
-// typeReference); // forwarded because the number of signal groups changed
-// ProcessedSpat spat6 = objectMapper.readValue(inputProcessedSpat6,
-// typeReference); // forwarded because a signal group ID changed
-
-// assertEquals(spat1.getUtcTimeStamp(),
-// spatDeduplicatorResults.get(0).value.getUtcTimeStamp());
-// assertEquals(spat3.getUtcTimeStamp(),
-// spatDeduplicatorResults.get(1).value.getUtcTimeStamp());
-// assertEquals(spat4.getUtcTimeStamp(),
-// spatDeduplicatorResults.get(2).value.getUtcTimeStamp());
-// assertEquals(spat5.getUtcTimeStamp(),
-// spatDeduplicatorResults.get(3).value.getUtcTimeStamp());
-// assertEquals(spat6.getUtcTimeStamp(),
-// spatDeduplicatorResults.get(4).value.getUtcTimeStamp());
-
-// } catch (JsonMappingException e) {
-// e.printStackTrace();
-// } catch (JsonProcessingException e) {
-// e.printStackTrace();
-// }
-// }
-// }
+package us.dot.its.jpo.deduplicator.deduplicator;
+
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.kafka.common.serialization.Serde;
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KeyValue;
+import org.apache.kafka.streams.TestInputTopic;
+import org.apache.kafka.streams.TestOutputTopic;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.TopologyTestDriver;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedMovementPhaseState;
+import us.dot.its.jpo.geojsonconverter.pojos.spat.ProcessedSpat;
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.Instant;
+import java.time.ZonedDateTime;
+import java.util.List;
+
+public class ProcessedSpatDeduplicatorTopologyTest {
+
+ String inputTopic = "topic.ProcessedSpat";
+ String outputTopic = "topic.DeduplicatedProcessedSpat";
+
+ ObjectMapper objectMapper;
+
+ // Reference Message
+ String inputProcessedSpat1;
+
+ // Same as Processed SPaT 1
+ String inputProcessedSpat2;
+
+ // Time change of +1 minute
+ String inputProcessedSpat3;
+
+ // With a signal group removed
+ String inputProcessedSpat4;
+
+ // With a signal group's id changed
+ String inputProcessedSpat5;
+
+ // With a change of the light state of a signal group
+ String inputProcessedSpat6;
+
+ String key = "{\"rsuId\": \"10.164.6.16\", \"intersectionId\": 6311,\"region\": -1}";
+
+ @Autowired
+ DeduplicatorProperties props;
+
+ @Before
+ public void setup() throws IOException {
+ objectMapper = DateJsonMapper.getInstance();
+
+ // Load test files from resources
+
+ // Reference Processed SPaT
+ String processedSpatReference = new String(
+ Files.readAllBytes(Paths
+ .get("src/test/resources/json/processed_spat/sample.processed_spat-reference.json")));
+ ProcessedSpat processedSpatReferenceData = objectMapper.readValue(processedSpatReference, ProcessedSpat.class);
+
+ // Reference Processed SPaT, Should be kept
+ inputProcessedSpat1 = processedSpatReferenceData.toString();
+
+ // Duplicate of Number 1, should be dropped
+ inputProcessedSpat2 = processedSpatReferenceData.toString();
+
+ // Time change of +1 minute, should be kept
+ ProcessedSpat processedSpatIncreaseTime = objectMapper.readValue(processedSpatReferenceData.toString(),
+ ProcessedSpat.class);
+ // Convert ZonedDateTime to Instant, add 61 seconds, then convert back to
+ // ZonedDateTime
+ ZonedDateTime originalZdt = processedSpatIncreaseTime.getUtcTimeStamp();
+ Instant newInstant = originalZdt.toInstant().plusSeconds(61);
+ processedSpatIncreaseTime.setUtcTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone()));
+ inputProcessedSpat3 = processedSpatIncreaseTime.toString();
+
+ // Signal group removed
+ ProcessedSpat processedSpatSignalGroupRemoved = objectMapper.readValue(processedSpatReferenceData.toString(),
+ ProcessedSpat.class);
+ processedSpatSignalGroupRemoved.getStates().remove(0);
+ inputProcessedSpat4 = processedSpatSignalGroupRemoved.toString();
+
+ // Signal group ID changed
+ ProcessedSpat processedSpatSignalGroupIdChanged = objectMapper.readValue(
+ processedSpatSignalGroupRemoved.toString(),
+ ProcessedSpat.class);
+ processedSpatSignalGroupIdChanged.getStates().get(0).setSignalGroup(500);
+ inputProcessedSpat5 = processedSpatSignalGroupIdChanged.toString();
+
+ // Signal group light state changed
+ ProcessedSpat processedSpatSignalGroupLightStateChanged = objectMapper.readValue(
+ processedSpatSignalGroupIdChanged.toString(),
+ ProcessedSpat.class);
+ processedSpatSignalGroupLightStateChanged.getStates().get(0).getStateTimeSpeed().get(0)
+ .setEventState(ProcessedMovementPhaseState.PROTECTED_CLEARANCE);
+ inputProcessedSpat6 = processedSpatSignalGroupLightStateChanged.toString();
+ }
+
+ @Test
+ public void testSerialization() throws JsonMappingException, JsonProcessingException {
+ ProcessedSpat processedSpat = objectMapper.readValue(inputProcessedSpat1, ProcessedSpat.class);
+ String json = processedSpat.toString();
+ assertEquals(inputProcessedSpat1, json);
+ }
+
+ @Test
+ public void testJsonSerdes() {
+ Serde serdes = JsonSerdes.ProcessedSpat();
+ ProcessedSpat deserialized = serdes.deserializer().deserialize(null, inputProcessedSpat1.getBytes());
+ byte[] serialized = serdes.serializer().serialize(null, deserialized);
+ assertThat(new String(serialized), jsonEquals(inputProcessedSpat1));
+ }
+
+ @Test
+ public void testTopology() {
+ props = new DeduplicatorProperties();
+ props.setKafkaTopicProcessedSpat(inputTopic);
+ props.setKafkaTopicDeduplicatedProcessedSpat(outputTopic);
+
+ ProcessedSpatDeduplicatorTopology processedSpatDeduplicatorTopology = new ProcessedSpatDeduplicatorTopology(
+ props);
+ Topology topology = processedSpatDeduplicatorTopology.buildTopology();
+
+ try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+ TestInputTopic inputProcessedSpatData = driver.createInputTopic(
+ inputTopic,
+ Serdes.String().serializer(),
+ Serdes.String().serializer());
+
+ TestOutputTopic outputProcessedSpatData = driver.createOutputTopic(
+ outputTopic,
+ Serdes.String().deserializer(),
+ JsonSerdes.ProcessedSpat().deserializer());
+
+ inputProcessedSpatData.pipeInput(key, inputProcessedSpat1);
+ inputProcessedSpatData.pipeInput(key, inputProcessedSpat2);
+ inputProcessedSpatData.pipeInput(key, inputProcessedSpat3);
+ inputProcessedSpatData.pipeInput(key, inputProcessedSpat4);
+ inputProcessedSpatData.pipeInput(key, inputProcessedSpat5);
+ inputProcessedSpatData.pipeInput(key, inputProcessedSpat6);
+
+ List> processedSpatDeduplicatorResults = outputProcessedSpatData
+ .readKeyValuesToList();
+
+ // validate that only 5 messages make it through
+ assertEquals(5, processedSpatDeduplicatorResults.size());
+
+ ProcessedSpat processedSpat1 = objectMapper.readValue(inputProcessedSpat1, ProcessedSpat.class);
+ ProcessedSpat processedSpat3 = objectMapper.readValue(inputProcessedSpat3, ProcessedSpat.class);
+ ProcessedSpat processedSpat4 = objectMapper.readValue(inputProcessedSpat4, ProcessedSpat.class);
+ ProcessedSpat processedSpat5 = objectMapper.readValue(inputProcessedSpat5, ProcessedSpat.class);
+ ProcessedSpat processedSpat6 = objectMapper.readValue(inputProcessedSpat6, ProcessedSpat.class);
+
+ assertThat(processedSpatDeduplicatorResults.get(0).value.toString(), jsonEquals(processedSpat1.toString()));
+ assertThat(processedSpatDeduplicatorResults.get(1).value.toString(), jsonEquals(processedSpat3.toString()));
+ assertThat(processedSpatDeduplicatorResults.get(2).value.toString(), jsonEquals(processedSpat4.toString()));
+ assertThat(processedSpatDeduplicatorResults.get(3).value.toString(), jsonEquals(processedSpat5.toString()));
+ assertThat(processedSpatDeduplicatorResults.get(4).value.toString(), jsonEquals(processedSpat6.toString()));
+
+ } catch (JsonMappingException e) {
+ e.printStackTrace();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/TimDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/TimDeduplicatorTopologyTest.java
index e174525..ddc61a1 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/TimDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/TimDeduplicatorTopologyTest.java
@@ -1,5 +1,10 @@
package us.dot.its.jpo.deduplicator.deduplicator;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.TestInputTopic;
@@ -10,19 +15,21 @@
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import us.dot.its.jpo.deduplicator.deduplicator.serialization.JsonSerdes;
import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.TimDeduplicatorTopology;
-import us.dot.its.jpo.ode.model.OdeTimData;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.ode.model.OdeMessageFrameData;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.List;
@@ -31,22 +38,70 @@ public class TimDeduplicatorTopologyTest {
String inputTopic = "topic.OdeTimJson";
String outputTopic = "topic.DeduplicatedOdeTimJson";
- ObjectMapper objectMapper = new ObjectMapper();
+ ObjectMapper objectMapper;
- String inputOdeTimReference = "";
- String inputOdeTimOneSecondTimeDelta = "";
- String inputOdeTimOneHourTimeDelta = "";
- String inputOdeTimDifferent = "";
+ String inputTim1 = "";
+ String inputTim2 = "";
+ String inputTim3 = "";
+ String inputTim4 = "";
+ String inputTim5 = "";
@Autowired
DeduplicatorProperties props;
@Before
public void setup() throws IOException {
- inputOdeTimReference = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_tim/sample.ode-tim-reference.json")));
- inputOdeTimOneSecondTimeDelta = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_tim/sample.ode-tim-reference-1-second-later.json")));
- inputOdeTimOneHourTimeDelta = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_tim/sample.ode-tim-reference-1-hour-later.json")));
- inputOdeTimDifferent = new String(Files.readAllBytes(Paths.get("src/test/resources/json/ode_tim/sample.ode-tim-different.json")));
+ objectMapper = DateJsonMapper.getInstance();
+
+ // Load test files from resources
+ // Reference TIM
+ String timReference = new String(
+ Files.readAllBytes(Paths.get("src/test/resources/json/ode_tim/sample.ode-tim-reference.json")));
+ OdeMessageFrameData timReferenceData = objectMapper.readValue(timReference, OdeMessageFrameData.class);
+
+ inputTim1 = timReferenceData.toJson();
+
+ // Duplicate of Number 1 - should be deduplicated
+ inputTim2 = timReferenceData.toJson();
+
+ // Message 1 but 5 minutes later - should be deduplicated
+ OdeMessageFrameData tim5MinutesLater = objectMapper.readValue(timReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ String originalTime = timReferenceData.getMetadata().getOdeReceivedAt();
+ Instant instant = Instant.parse(originalTime);
+ Instant newInstant = instant.plus(5, ChronoUnit.MINUTES);
+ tim5MinutesLater.getMetadata().setOdeReceivedAt(newInstant.toString());
+ inputTim3 = tim5MinutesLater.toJson();
+
+ // Message 1 but 1 hour later - should be kept
+ OdeMessageFrameData tim1HourLater = objectMapper.readValue(timReferenceData.toJson(),
+ OdeMessageFrameData.class);
+ originalTime = timReferenceData.getMetadata().getOdeReceivedAt();
+ instant = Instant.parse(originalTime);
+ newInstant = instant.plus(61, ChronoUnit.MINUTES);
+ tim1HourLater.getMetadata().setOdeReceivedAt(newInstant.toString());
+ inputTim4 = tim1HourLater.toJson();
+
+ // A different Message entirely - should be kept
+ String timDifferent = new String(
+ Files.readAllBytes(Paths.get("src/test/resources/json/ode_tim/sample.ode-tim-different.json")));
+ OdeMessageFrameData timDifferentData = objectMapper.readValue(timDifferent, OdeMessageFrameData.class);
+ inputTim5 = timDifferentData.toJson();
+ }
+
+ @Test
+ public void testSerialization() throws JsonMappingException, JsonProcessingException {
+ OdeMessageFrameData tim = objectMapper.readValue(inputTim1, OdeMessageFrameData.class);
+ String json = objectMapper.writeValueAsString(tim);
+ assertEquals(inputTim1, json);
+ }
+
+ @Test
+ public void testJsonSerdes() {
+ Serde serdes = JsonSerdes.OdeMessageFrame();
+ OdeMessageFrameData deserialized = serdes.deserializer().deserialize(null, inputTim1.getBytes());
+ byte[] serialized = serdes.serializer().serialize(null, deserialized);
+ assertThat(new String(serialized), jsonEquals(inputTim1));
}
@Test
@@ -56,44 +111,40 @@ public void testTopology() {
props.setKafkaTopicOdeTimJson(inputTopic);
props.setKafkaTopicDeduplicatedOdeTimJson(outputTopic);
- TimDeduplicatorTopology TimDeduplicatorTopology = new TimDeduplicatorTopology(props, null);
-
- Topology topology = TimDeduplicatorTopology.buildTopology();
- objectMapper.registerModule(new JavaTimeModule());
+ TimDeduplicatorTopology timDeduplicatorTopology = new TimDeduplicatorTopology(props);
+ Topology topology = timDeduplicatorTopology.buildTopology();
try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-
+
TestInputTopic inputTimData = driver.createInputTopic(
inputTopic,
Serdes.Void().serializer(),
Serdes.String().serializer());
-
- TestOutputTopic outputTimData = driver.createOutputTopic(
+ TestOutputTopic outputTimData = driver.createOutputTopic(
outputTopic,
Serdes.String().deserializer(),
- JsonSerdes.OdeTim().deserializer());
+ JsonSerdes.OdeMessageFrame().deserializer());
- inputTimData.pipeInput(null, inputOdeTimReference);
- inputTimData.pipeInput(null, inputOdeTimOneSecondTimeDelta);
- inputTimData.pipeInput(null, inputOdeTimOneHourTimeDelta);
- inputTimData.pipeInput(null, inputOdeTimDifferent);
+ inputTimData.pipeInput(null, inputTim1);
+ inputTimData.pipeInput(null, inputTim2);
+ inputTimData.pipeInput(null, inputTim3);
+ inputTimData.pipeInput(null, inputTim4);
+ inputTimData.pipeInput(null, inputTim5);
- List> timDeduplicatedResults = outputTimData.readKeyValuesToList();
+ List> timDeduplicatedResults = outputTimData.readKeyValuesToList();
// validate that only 3 messages make it through
assertEquals(3, timDeduplicatedResults.size());
- objectMapper = new ObjectMapper();
- OdeTimData inputOdeTimReferenceObj = objectMapper.readValue(inputOdeTimReference, OdeTimData.class);
- OdeTimData inputOdeTimOneHourTimeDeltaObj = objectMapper.readValue(inputOdeTimOneHourTimeDelta, OdeTimData.class);
- OdeTimData inputOdeTimDifferentObj = objectMapper.readValue(inputOdeTimDifferent, OdeTimData.class);
+ OdeMessageFrameData tim1 = objectMapper.readValue(inputTim1, OdeMessageFrameData.class);
+ OdeMessageFrameData tim4 = objectMapper.readValue(inputTim4, OdeMessageFrameData.class);
+ OdeMessageFrameData tim5 = objectMapper.readValue(inputTim5, OdeMessageFrameData.class);
+
+ assertEquals(tim1.getMetadata().getOdeReceivedAt(), timDeduplicatedResults.get(0).value.getMetadata().getOdeReceivedAt());
+ assertEquals(tim4.getMetadata().getOdeReceivedAt(), timDeduplicatedResults.get(1).value.getMetadata().getOdeReceivedAt());
+ assertEquals(tim5.getMetadata().getOdeReceivedAt(), timDeduplicatedResults.get(2).value.getMetadata().getOdeReceivedAt());
- assertEquals(inputOdeTimReferenceObj.getMetadata().getOdeReceivedAt(), timDeduplicatedResults.get(0).value.getMetadata().getOdeReceivedAt());
- assertEquals(inputOdeTimOneHourTimeDeltaObj.getMetadata().getOdeReceivedAt(), timDeduplicatedResults.get(1).value.getMetadata().getOdeReceivedAt());
- assertEquals(inputOdeTimDifferentObj.getMetadata().getOdeReceivedAt(), timDeduplicatedResults.get(2).value.getMetadata().getOdeReceivedAt());
-
}catch(Exception e){
e.printStackTrace();
}
diff --git a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-different.json b/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-different.json
index 954c585..1a41584 100644
--- a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-different.json
+++ b/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-different.json
@@ -1,1298 +1,495 @@
{
- "metadata": {
- "logFileName": "",
- "recordType": "timMsg",
- "securityResultCode": "success",
- "receivedMessageDetails": { "rxSource": "NA" },
- "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload",
- "serialId": {
- "streamId": "b2d15f2d-7461-4083-b3df-b4efadab4d17",
- "bundleSize": 1,
- "bundleId": 0,
- "recordId": 0,
- "serialNumber": 0
- },
- "odeReceivedAt": "2025-02-01T01:20:45.739Z",
- "schemaVersion": 8,
- "maxDurationTime": 0,
- "recordGeneratedAt": "",
- "recordGeneratedBy": "RSU",
- "sanitized": false,
- "odePacketID": "",
- "odeTimStartDateTime": "",
- "asn1": "001F83A175D472274F43544554205354520A4C16B18193D0D1F9CDF54733FB1BFC0C983FCFC48D24FF97A474B8A754A9112A6F690200192EFCB5FF96D90FA32D4E83FC0C9830B5F5FC150A5059C545235AC20227C697080018815F84759CB3BF452C850424643A30E028544E9C511560A9DD8C2629F0D4470DBB3DDB4316096FC100800809BC746A108C8F26FC4C3208DA0E61091B7429182D3BFC0C98359EA8B4B454C16E606F037AE007A1CDE32000152E6C0ECDF612A90558D403FC049BF003734AC1C240EC930B39E850A7990A808008C033EFC47606FDDFA252B4A9942280C1020C9D818700EC4B4A76680C001D9F981240013111914408214602F8173D850A0D48F09F5D75264929260B5A7D27260B5A65260B56744F43999104E394B5204FF09260B5A7D3E32C5F74A0DB09EA975B8C1724DC92D9201005800092D84A89EF67BC1B27429C710979A5FE0E4C16B4F5EE874A08F2404C40AA60E2A09E79F91602003E5DB0AA9B32A2E0A6F36507F829305ACEE93E6B134C1CCC3C2EF3FA5CB5D02ECE000142002950BD8FB7D02D26BB6CAFCB848BE4A9260B5A7D29260B5A7D19D28125C17566972EA98F7172471344010153D0C21C1D69E158731BFC1C982D69E2E4FEDB544A012D60EDDB5D7569995CCC001CB02000CB8B449E02D39DB1072106F80B79BFC14982D666D178E4A198A3579B12B09915D01723B0000A10002A973AEAF40B82284427D9124DFE024F9230F8DD6AD73490518F80A3B259CF3FC40014001266976FBC88CB08E20EE8AD087EC16463A2B7AC5E62CB83FC9C830B7275F28A3128CDB2491AFF05260B580BDABD3249C784B718EFDC1906727B228001160002B10C89FAF5F0E9BA4F0AC74920F4947402561EBFB6201930424BF9E8112A39CA22519425D8E01001A7A1E0222723B864CB17F849305AD3E92E6884164E2CE7F0A6BD84FE4E38949D300081A01A290029F8111120048308876C910829B04B5148014FC9621814460542FAA24A460FBF82D2CF1A8CE66032A7E6A0807028A04283228610217947C12CE3FFF20CA031F809A2007D242408F0B4510F23D2A2646294D48A41F4F8494C87B58CCFE2983829A707069C17A4BBF23992859B3A528C03ACD3506FF07260B5A7BBA7391E53AAABAA44EA1584A857727A910002C0020391DD0DEDC78D916CBD8D839D52DABDB084919305C975AABA210D2D0CDF7A0ABC1000D3D0D9D071298F916D83FC049B2CFCF26A78A5951B5CC28075CAF1EAC780042808048EB0ADE229537A0161356A3A68175E5809621740382083BEDD5810921240",
- "originIp": "172.20.0.1"
- },
- "payload": {
- "data": {
- "msgCnt": 93,
- "timeStamp": 291367,
- "packetID": "4F4354455420535453",
- "urlB": "IA5",
- "dataFrames": [
- {
- "doNotUse1": 0,
- "frameType": "commercialSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 1150,
- "startTime": 473045,
- "durationTime": 3687,
- "priority": 7,
- "doNotUse2": 22,
- "regions": [
- {
- "name": "IA",
- "id": { "region": 64764, "id": 18642 },
- "anchor": {
- "lat": 172032029,
- "long": -1025506517,
- "elevation": 13386
- },
- "laneWidth": 19949,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 9,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 252,
- "offsetXaxis": { "large": -5120 },
- "offsetYaxis": { "small": -585 },
- "rotateXY": 8692,
- "scaleXaxis": -422,
- "scaleYaxis": 464
- }
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 2911, "id": 24513 },
- "anchor": {
- "lat": 217001329,
- "long": -436271951,
- "elevation": 28809
- },
- "laneWidth": 30930,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 8,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL4": { "lon": 115258, "lat": 80231 }
- },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "hydrantPresent",
- "mergePoint",
- "divergePoint",
- "reserved"
- ],
- "disabled": [
- "transitStopOnRight",
- "adaptiveTimingPresent",
- "loadingzoneOnLeft",
- "costToPark"
- ],
- "enabled": ["curbOnLeft"],
- "data": [
- {
- "speedLimits": [
- {
- "type": "truckNightMaxSpeed",
- "speed": 6769
- },
- { "type": "truckMaxSpeed", "speed": 4438 },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 2679
- },
- {
- "type": "vehiclesWithTrailersNightMaxSpeed",
- "speed": 3110
- },
- { "type": "vehicleMaxSpeed", "speed": 1987 }
- ]
- }
- ],
- "dWidth": -188,
- "dElevation": -61
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": 5893850, "lat": -6770613 }
- },
- "attributes": {
- "localNode": ["closedToTraffic"],
- "disabled": ["bikeBoxInFront"],
- "enabled": ["mergingLaneRight"],
- "data": [{ "laneCrownPointLeft": -17 }],
- "dWidth": -396,
- "dElevation": -88
- }
- },
- {
- "delta": { "node-LL1": { "lon": -924, "lat": -109 } },
- "attributes": {
- "localNode": [
- "downstreamStopLine",
- "roundedCapStyleB"
- ],
- "disabled": ["whiteLine", "partialCurbIntrusion"],
- "enabled": [
- "loadingzoneOnLeft",
- "audibleSignalingPresent",
- "freeParking"
- ],
- "data": [
- { "laneCrownPointCenter": 55 },
- { "laneAngle": -98 }
- ],
- "dWidth": -319,
- "dElevation": -89
- }
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 23018, "id": 35659 },
- "anchor": {
- "lat": -544509288,
- "long": -1334375239,
- "elevation": -3608
- },
- "laneWidth": 14780,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": true,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 5,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 108,
- "offsetXaxis": { "small": -1574 },
- "offsetYaxis": { "large": -635 },
- "rotateXY": 21792,
- "scaleXaxis": 689,
- "scaleYaxis": 640
- }
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 32256, "id": 28265 },
- "anchor": {
- "lat": 725366646,
- "long": -566506763,
- "elevation": 6227
- },
- "laneWidth": 26178,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 1,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL5": { "lon": 2030663, "lat": -517129 }
- },
- "attributes": {
- "localNode": [
- "safeIsland",
- "hydrantPresent",
- "curbPresentAtStepOff"
- ],
- "disabled": [
- "sharedWithTrackedVehicle",
- "transitStopOnLeft",
- "headInParking",
- "audibleSignalingPresent"
- ],
- "enabled": ["doNotBlock", "mergingLaneLeft"],
- "data": [
- { "laneCrownPointRight": 48 },
- { "laneCrownPointRight": -114 }
- ],
- "dWidth": -505,
- "dElevation": -119
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": -5645920, "lat": -5242762 }
- },
- "attributes": {
- "localNode": [
- "reserved",
- "safeIsland",
- "mergePoint"
- ],
- "disabled": ["turnOutPointOnLeft"],
- "enabled": [
- "timeRestrictionsOnParking",
- "adaptiveTimingPresent",
- "turnOutPointOnRight",
- "bikeBoxInFront"
- ],
- "data": [
- { "laneCrownPointCenter": -58 },
- { "pathEndPointAngle": -55 },
- { "pathEndPointAngle": -58 }
- ],
- "dWidth": 472,
- "dElevation": -190
- }
- }
- ]
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 16,
- "doNotUse4": 13,
- "content": {
- "genericSign": [
- { "item": { "itis": 61599 } },
- { "item": { "itis": 47850 } },
- { "item": { "itis": 39204 } },
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5S" } }
- ]
- },
- "url": "IA5"
+ "metadata": {
+ "payloadType": "us.dot.its.jpo.ode.model.OdeMessageFramePayload",
+ "serialId": {
+ "streamId": "5524dafb-c58b-4949-af81-e6ab13c0b8cf",
+ "bundleSize": 1,
+ "bundleId": 702,
+ "recordId": 0,
+ "serialNumber": 702
},
- {
- "doNotUse1": 7,
- "frameType": "roadSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 2457,
- "startTime": 66787,
- "durationTime": 19034,
- "priority": 4,
- "doNotUse2": 16,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 61846, "id": 12218 },
- "anchor": {
- "lat": 202451669,
- "long": -1016248785,
- "elevation": 14777
- },
- "laneWidth": 4825,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": true,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100meters",
- "laneWidth": 23305,
- "circle": {
- "center": {
- "lat": 257084126,
- "long": -1572221105,
- "elevation": 10372
- },
- "radius": 3021,
- "units": "cm2-5"
- }
- }
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 44916, "id": 14928 },
- "anchor": {
- "lat": -391962488,
- "long": -1442690475,
- "elevation": 975
- },
- "laneWidth": 8081,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 15,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 216,
- "offsetXaxis": { "small": 682 },
- "offsetYaxis": { "large": -6571 },
- "rotateXY": 11786,
- "scaleXaxis": -269,
- "scaleYaxis": -432
- }
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 15268, "id": 63916 },
- "anchor": {
- "lat": -14883901,
- "long": 1470459302,
- "elevation": 47965
- },
- "laneWidth": 374,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100000meters",
- "area": {
- "circle": {
- "center": {
- "lat": 223434207,
- "long": -714422034,
- "elevation": 41663
- },
- "radius": 737,
- "units": "cm2-5"
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 2,
- "doNotUse4": 31,
- "content": {
- "workZone": [
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5St" } },
- { "item": { "itis": 52884 } }
- ]
- },
- "url": "I"
- },
- {
- "doNotUse1": 16,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 604037802,
- "long": -124613998,
- "elevation": 46289
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": true,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "guide",
- "crc": "4F43"
- }
- },
- "startYear": 135,
- "startTime": 30119,
- "durationTime": 17072,
- "priority": 7,
- "doNotUse2": 6,
- "regions": [
- {
- "name": "IA5S",
- "id": { "region": 35731, "id": 64365 },
- "anchor": {
- "lat": 251341270,
- "long": -1550588968,
- "elevation": 18073
- },
- "laneWidth": 19174,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": true
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 19339,
- "circle": {
- "center": {
- "lat": -590142898,
- "long": 192563845,
- "elevation": 3040
- },
- "radius": 734,
- "units": "meter"
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 13160, "id": 48242 },
- "anchor": {
- "lat": 227302831,
- "long": -891580621,
- "elevation": 7072
- },
- "laneWidth": 5923,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "area": {
- "circle": {
- "center": {
- "lat": 368610426,
- "long": -1703460317,
- "elevation": 1004
- },
- "radius": 2194,
- "units": "meter"
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 58508, "id": 15927 },
- "anchor": {
- "lat": 892488592,
- "long": -431640924,
- "elevation": 41561
- },
- "laneWidth": 26527,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "regionPointSet": {
- "anchor": {
- "lat": -113602543,
- "long": 717746718,
- "elevation": 49498
- },
- "scale": 1,
- "nodeList": [
- {
- "xOffset": 27670,
- "yOffset": -14790,
- "zOffset": -21638
- },
- { "xOffset": 3020, "yOffset": -9872, "zOffset": -109 },
- {
- "xOffset": -24382,
- "yOffset": 23709,
- "zOffset": -862
- },
- {
- "xOffset": -26476,
- "yOffset": -6439,
- "zOffset": -23411
- }
- ]
- }
- }
- }
- }
+ "odeReceivedAt": "2025-07-31T21:32:11.361Z",
+ "schemaVersion": 9,
+ "maxDurationTime": 30,
+ "recordGeneratedAt": "2025-06-26T14:11:10.000Z",
+ "recordGeneratedBy": "TMC",
+ "sanitized": false,
+ "odePacketID": "723FCE5C32F1EE19E0",
+ "odeTimStartDateTime": "2025-07-31T21:32:07.293Z",
+ "request": {
+ "ode": {
+ "version": 3,
+ "verb": "POST"
},
- {
- "name": "IA5",
- "id": { "region": 379, "id": 22438 },
- "anchor": {
- "lat": -281093797,
- "long": 556669965,
- "elevation": 29497
- },
- "laneWidth": 7880,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor500000meters",
- "laneWidth": 2148,
- "circle": {
- "center": {
- "lat": 163173661,
- "long": -872411303,
- "elevation": 55588
- },
- "radius": 489,
- "units": "cm2-5"
- }
+ "rsus": [
+ {
+ "rsuTarget": "172.16.28.121",
+ "rsuUsername": "rwUser",
+ "rsuPassword": "*",
+ "rsuRetries": 3,
+ "rsuTimeout": 5000,
+ "rsuIndex": 2,
+ "snmpProtocol": "FOURDOT1"
+ },
+ {
+ "rsuTarget": "172.16.28.5",
+ "rsuUsername": "rwUser",
+ "rsuPassword": "*",
+ "rsuRetries": 3,
+ "rsuTimeout": 5000,
+ "rsuIndex": 2,
+ "snmpProtocol": "FOURDOT1"
+ },
+ {
+ "rsuTarget": "172.16.28.7",
+ "rsuUsername": "rwUser",
+ "rsuPassword": "*",
+ "rsuRetries": 3,
+ "rsuTimeout": 5000,
+ "rsuIndex": 2,
+ "snmpProtocol": "FOURDOT1"
+ },
+ {
+ "rsuTarget": "172.16.28.92",
+ "rsuUsername": "rwUser",
+ "rsuPassword": "*",
+ "rsuRetries": 3,
+ "rsuTimeout": 5000,
+ "rsuIndex": 2,
+ "snmpProtocol": "FOURDOT1"
}
- }
+ ],
+ "snmp": {
+ "rsuid": "83",
+ "msgid": 31,
+ "mode": 1,
+ "channel": 183,
+ "interval": 1000,
+ "deliverystart": "2025-07-31T21:32:08Z",
+ "deliverystop": "2025-07-31T22:02:08Z",
+ "enable": 1,
+ "status": 4
}
- ],
- "doNotUse3": 8,
- "doNotUse4": 29,
- "content": {
- "advisory": [
- { "item": { "itis": 44093 } },
- { "item": { "itis": 65240 } },
- { "item": { "text": "IA" } }
- ]
- },
- "url": "I"
},
- {
- "doNotUse1": 31,
- "frameType": "advisory",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": -864002503,
- "long": -654286715,
- "elevation": 43804
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 3076,
- "startTime": 282183,
- "durationTime": 14436,
- "priority": 6,
- "doNotUse2": 11,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 11880, "id": 33814 },
- "anchor": {
- "lat": 51295938,
- "long": 799818234,
- "elevation": 10466
- },
- "laneWidth": 10554,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 10,
- "offset": {
- "xy": {
- "nodes": [
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": ["mergePoint"],
- "disabled": [
- "transitStopOnLeft",
- "bikeBoxInFront",
- "doNotBlock"
- ],
- "enabled": ["mergingLaneLeft", "mergingLaneRight"],
- "data": [
- { "laneCrownPointCenter": 91 },
- { "laneCrownPointLeft": -60 },
- { "laneCrownPointLeft": -118 }
- ],
- "dWidth": -80,
- "dElevation": -211
- }
- },
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": [
- "hydrantPresent",
- "roundedCapStyleA",
- "roundedCapStyleB"
- ],
- "disabled": ["turnOutPointOnRight"],
- "enabled": ["adjacentParkingOnRight", "curbOnLeft"],
- "data": [
- { "laneCrownPointCenter": -3 },
- { "laneCrownPointCenter": -23 },
- {
- "speedLimits": [
- { "type": "vehicleMinSpeed", "speed": 5260 },
- {
- "type": "maxSpeedInConstructionZone",
- "speed": 7676
- }
- ]
- }
- ],
- "dWidth": -98,
- "dElevation": -300
- }
- },
- {
- "delta": { "node-XY5": { "x": 6552, "y": -7382 } },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "stopLine",
- "reserved",
- "roundedCapStyleB"
- ],
- "disabled": [
- "curbOnLeft",
- "turnOutPointOnRight",
- "whiteLine",
- "curbOnRight"
- ],
- "enabled": [
- "sharedWithTrackedVehicle",
- "audibleSignalingPresent",
- "headInParking"
- ],
- "data": [
- { "laneCrownPointCenter": -7 },
- { "laneAngle": 68 },
- { "laneCrownPointLeft": -39 }
- ],
- "dWidth": 287,
- "dElevation": 510
- }
- },
+ "isCertPresent": false
+ },
+ "payload": {
+ "data": {
+ "messageId": 31,
+ "value": {
+ "TravelerInformation": {
+ "msgCnt": 1,
+ "timeStamp": 254291,
+ "packetID": "723FCE5C32F1EE19E0",
+ "urlB": "null",
+ "dataFrames": [
{
- "delta": { "node-XY1": { "x": -310, "y": -500 } },
- "attributes": {
- "localNode": ["roundedCapStyleA"],
- "disabled": [
- "timeRestrictionsOnParking",
- "reserved",
- "parallelParking",
- "midBlockCurbPresent"
- ],
- "enabled": [
- "transitStopOnRight",
- "whiteLine",
- "taperToCenterLine",
- "adjacentParkingOnLeft",
- "timeRestrictionsOnParking"
+ "doNotUse1": 1,
+ "frameType": "advisory",
+ "msgId": {
+ "roadSignID": {
+ "position": {
+ "lat": 397401367,
+ "long": -1049878457
+ },
+ "viewAngle": "FFFF",
+ "mutcdCode": "warning"
+ }
+ },
+ "startYear": 2025,
+ "startTime": 305132,
+ "durationTime": 30,
+ "priority": 5,
+ "doNotUse2": 1,
+ "regions": [
+ {
+ "name": "I_US-40_RSU_172.16.28.121",
+ "id": {
+ "region": 0,
+ "id": 0
+ },
+ "anchor": {
+ "lat": 397401367,
+ "long": -1049878457
+ },
+ "laneWidth": 5000,
+ "directionality": "both",
+ "closedPath": false,
+ "direction": "1800",
+ "description": {
+ "path": {
+ "scale": 0,
+ "offset": {
+ "ll": {
+ "nodes": [
+ {
+ "delta": {
+ "node-LL1": {
+ "lon": 1754,
+ "lat": -23
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": 2814,
+ "lat": -37
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 23917,
+ "lat": -292
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 14181,
+ "lat": -600
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 24773,
+ "lat": -222
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11911,
+ "lat": -107
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 12022,
+ "lat": -108
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 22330,
+ "lat": 39
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 16898,
+ "lat": 29
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 13728,
+ "lat": 24
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 12752,
+ "lat": 22
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 10599,
+ "lat": 18
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 13949,
+ "lat": 24
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 12212,
+ "lat": -47
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 24713,
+ "lat": -114
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 25162,
+ "lat": -117
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 24591,
+ "lat": -115
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 12302,
+ "lat": 91
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 10045,
+ "lat": 1203
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 13523,
+ "lat": 765
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11574,
+ "lat": -136
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11406,
+ "lat": -27
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 15497,
+ "lat": -35
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11569,
+ "lat": -26
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11865,
+ "lat": -27
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11738,
+ "lat": -27
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 12191,
+ "lat": -28
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11557,
+ "lat": -26
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11475,
+ "lat": -26
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11720,
+ "lat": -27
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 13947,
+ "lat": -32
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 20942,
+ "lat": -49
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11789,
+ "lat": 575
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 17542,
+ "lat": 15
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 17172,
+ "lat": 14
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 17057,
+ "lat": 14
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 17223,
+ "lat": 14
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11079,
+ "lat": 9
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11601,
+ "lat": 9
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11505,
+ "lat": 9
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 11622,
+ "lat": 9
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": 16945,
+ "lat": 12
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": 6260,
+ "lat": 5
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
],
- "data": [
- { "laneAngle": -59 },
- { "laneCrownPointCenter": 105 },
- { "laneCrownPointCenter": 25 },
- {
- "speedLimits": [
- {
- "type": "vehicleNightMaxSpeed",
- "speed": 2245
- },
- { "type": "vehicleMaxSpeed", "speed": 1700 }
+ "doNotUse3": 1,
+ "doNotUse4": 1,
+ "content": {
+ "workZone": [
+ {
+ "item": {
+ "itis": 1025
+ }
+ }
]
- },
- {
- "speedLimits": [
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 7839
- },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 1190
- },
- { "type": "truckMaxSpeed", "speed": 3947 }
- ]
- }
- ],
- "dWidth": 497,
- "dElevation": -208
- }
- },
- {
- "delta": {
- "node-LatLon": {
- "lon": -1625296958,
- "lat": 501091223
- }
- },
- "attributes": {
- "localNode": [
- "downstreamStartNode",
- "downstreamStopLine",
- "safeIsland"
- ],
- "disabled": [
- "adjacentParkingOnLeft",
- "partialCurbIntrusion",
- "taperToRight"
- ],
- "enabled": [
- "unEvenPavementPresent",
- "adjacentParkingOnRight"
- ],
- "data": [{ "laneCrownPointCenter": 86 }],
- "dWidth": -90,
- "dElevation": 131
- }
+ },
+ "url": "null"
}
- ]
- }
- }
+ ]
}
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 48039, "id": 14622 },
- "anchor": {
- "lat": 419808681,
- "long": -1470200813,
- "elevation": 37213
- },
- "laneWidth": 25845,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": true,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 25719,
- "circle": {
- "center": {
- "lat": -666313075,
- "long": 639822734,
- "elevation": 29597
- },
- "radius": 1325,
- "units": "foot"
- }
- }
- }
}
- ],
- "doNotUse3": 11,
- "doNotUse4": 27,
- "content": { "speedLimit": [{ "item": { "text": "I" } }] },
- "url": "IA"
},
- {
- "doNotUse1": 18,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 889823043,
- "long": -537303585,
- "elevation": 29359
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 1652,
- "startTime": 115878,
- "durationTime": 7970,
- "priority": 6,
- "doNotUse2": 27,
- "regions": [
- {
- "name": "I",
- "id": { "region": 26015, "id": 40525 },
- "anchor": {
- "lat": 112058765,
- "long": 1125609019,
- "elevation": 54648
- },
- "laneWidth": 31409,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "shapePointSet": {
- "anchor": {
- "lat": 733403986,
- "long": 1001009347,
- "elevation": 23252
- },
- "laneWidth": 14952,
- "directionality": "unavailable",
- "nodeList": {
- "computed": {
- "referenceLaneId": 188,
- "offsetXaxis": { "large": -8154 },
- "offsetYaxis": { "large": -28485 },
- "rotateXY": 224,
- "scaleXaxis": 32,
- "scaleYaxis": 1787
- }
- }
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 14,
- "doNotUse4": 21,
- "content": { "exitService": [{ "item": { "text": "I" } }] },
- "url": "I"
- }
- ]
- },
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation"
- }
-}
+ "dataType": "us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformationMessageFrame"
+ }
+}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-hour-later.json b/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-hour-later.json
deleted file mode 100644
index cedf98b..0000000
--- a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-hour-later.json
+++ /dev/null
@@ -1,1299 +0,0 @@
-{
- "metadata": {
- "logFileName": "",
- "recordType": "timMsg",
- "securityResultCode": "success",
- "receivedMessageDetails": { "rxSource": "NA" },
- "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload",
- "serialId": {
- "streamId": "b2d15f2d-7461-4083-b3df-b4efadab4d17",
- "bundleSize": 1,
- "bundleId": 0,
- "recordId": 0,
- "serialNumber": 0
- },
- "odeReceivedAt": "2025-02-01T01:20:45.739Z",
- "schemaVersion": 8,
- "maxDurationTime": 0,
- "recordGeneratedAt": "",
- "recordGeneratedBy": "RSU",
- "sanitized": false,
- "odePacketID": "",
- "odeTimStartDateTime": "",
- "asn1": "001F83A175D472274F43544554205354520A4C16B18193D0D1F9CDF54733FB1BFC0C983FCFC48D24FF97A474B8A754A9112A6F690200192EFCB5FF96D90FA32D4E83FC0C9830B5F5FC150A5059C545235AC20227C697080018815F84759CB3BF452C850424643A30E028544E9C511560A9DD8C2629F0D4470DBB3DDB4316096FC100800809BC746A108C8F26FC4C3208DA0E61091B7429182D3BFC0C98359EA8B4B454C16E606F037AE007A1CDE32000152E6C0ECDF612A90558D403FC049BF003734AC1C240EC930B39E850A7990A808008C033EFC47606FDDFA252B4A9942280C1020C9D818700EC4B4A76680C001D9F981240013111914408214602F8173D850A0D48F09F5D75264929260B5A7D27260B5A65260B56744F43999104E394B5204FF09260B5A7D3E32C5F74A0DB09EA975B8C1724DC92D9201005800092D84A89EF67BC1B27429C710979A5FE0E4C16B4F5EE874A08F2404C40AA60E2A09E79F91602003E5DB0AA9B32A2E0A6F36507F829305ACEE93E6B134C1CCC3C2EF3FA5CB5D02ECE000142002950BD8FB7D02D26BB6CAFCB848BE4A9260B5A7D29260B5A7D19D28125C17566972EA98F7172471344010153D0C21C1D69E158731BFC1C982D69E2E4FEDB544A012D60EDDB5D7569995CCC001CB02000CB8B449E02D39DB1072106F80B79BFC14982D666D178E4A198A3579B12B09915D01723B0000A10002A973AEAF40B82284427D9124DFE024F9230F8DD6AD73490518F80A3B259CF3FC40014001266976FBC88CB08E20EE8AD087EC16463A2B7AC5E62CB83FC9C830B7275F28A3128CDB2491AFF05260B580BDABD3249C784B718EFDC1906727B228001160002B10C89FAF5F0E9BA4F0AC74920F4947402561EBFB6201930424BF9E8112A39CA22519425D8E01001A7A1E0222723B864CB17F849305AD3E92E6884164E2CE7F0A6BD84FE4E38949D300081A01A290029F8111120048308876C910829B04B5148014FC9621814460542FAA24A460FBF82D2CF1A8CE66032A7E6A0807028A04283228610217947C12CE3FFF20CA031F809A2007D242408F0B4510F23D2A2646294D48A41F4F8494C87B58CCFE2983829A707069C17A4BBF23992859B3A528C03ACD3506FF07260B5A7BBA7391E53AAABAA44EA1584A857727A910002C0020391DD0DEDC78D916CBD8D839D52DABDB084919305C975AABA210D2D0CDF7A0ABC1000D3D0D9D071298F916D83FC049B2CFCF26A78A5951B5CC28075CAF1EAC780042808048EB0ADE229537A0161356A3A68175E5809621740382083BEDD5810921240",
- "originIp": "172.20.0.1"
- },
- "payload": {
- "data": {
- "msgCnt": 93,
- "timeStamp": 291367,
- "packetID": "4F4354455420535452",
- "urlB": "IA5",
- "dataFrames": [
- {
- "doNotUse1": 0,
- "frameType": "commercialSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 1150,
- "startTime": 473045,
- "durationTime": 3687,
- "priority": 7,
- "doNotUse2": 22,
- "regions": [
- {
- "name": "IA",
- "id": { "region": 64764, "id": 18642 },
- "anchor": {
- "lat": 172032029,
- "long": -1025506517,
- "elevation": 13386
- },
- "laneWidth": 19949,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 9,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 252,
- "offsetXaxis": { "large": -5120 },
- "offsetYaxis": { "small": -585 },
- "rotateXY": 8692,
- "scaleXaxis": -422,
- "scaleYaxis": 464
- }
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 2911, "id": 24513 },
- "anchor": {
- "lat": 217001329,
- "long": -436271951,
- "elevation": 28809
- },
- "laneWidth": 30930,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 8,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL4": { "lon": 115258, "lat": 80231 }
- },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "hydrantPresent",
- "mergePoint",
- "divergePoint",
- "reserved"
- ],
- "disabled": [
- "transitStopOnRight",
- "adaptiveTimingPresent",
- "loadingzoneOnLeft",
- "costToPark"
- ],
- "enabled": ["curbOnLeft"],
- "data": [
- {
- "speedLimits": [
- {
- "type": "truckNightMaxSpeed",
- "speed": 6769
- },
- { "type": "truckMaxSpeed", "speed": 4438 },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 2679
- },
- {
- "type": "vehiclesWithTrailersNightMaxSpeed",
- "speed": 3110
- },
- { "type": "vehicleMaxSpeed", "speed": 1987 }
- ]
- }
- ],
- "dWidth": -188,
- "dElevation": -61
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": 5893850, "lat": -6770613 }
- },
- "attributes": {
- "localNode": ["closedToTraffic"],
- "disabled": ["bikeBoxInFront"],
- "enabled": ["mergingLaneRight"],
- "data": [{ "laneCrownPointLeft": -17 }],
- "dWidth": -396,
- "dElevation": -88
- }
- },
- {
- "delta": { "node-LL1": { "lon": -924, "lat": -109 } },
- "attributes": {
- "localNode": [
- "downstreamStopLine",
- "roundedCapStyleB"
- ],
- "disabled": ["whiteLine", "partialCurbIntrusion"],
- "enabled": [
- "loadingzoneOnLeft",
- "audibleSignalingPresent",
- "freeParking"
- ],
- "data": [
- { "laneCrownPointCenter": 55 },
- { "laneAngle": -98 }
- ],
- "dWidth": -319,
- "dElevation": -89
- }
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 23018, "id": 35659 },
- "anchor": {
- "lat": -544509288,
- "long": -1334375239,
- "elevation": -3608
- },
- "laneWidth": 14780,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": true,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 5,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 108,
- "offsetXaxis": { "small": -1574 },
- "offsetYaxis": { "large": -635 },
- "rotateXY": 21792,
- "scaleXaxis": 689,
- "scaleYaxis": 640
- }
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 32256, "id": 28265 },
- "anchor": {
- "lat": 725366646,
- "long": -566506763,
- "elevation": 6227
- },
- "laneWidth": 26178,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 1,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL5": { "lon": 2030663, "lat": -517129 }
- },
- "attributes": {
- "localNode": [
- "safeIsland",
- "hydrantPresent",
- "curbPresentAtStepOff"
- ],
- "disabled": [
- "sharedWithTrackedVehicle",
- "transitStopOnLeft",
- "headInParking",
- "audibleSignalingPresent"
- ],
- "enabled": ["doNotBlock", "mergingLaneLeft"],
- "data": [
- { "laneCrownPointRight": 48 },
- { "laneCrownPointRight": -114 }
- ],
- "dWidth": -505,
- "dElevation": -119
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": -5645920, "lat": -5242762 }
- },
- "attributes": {
- "localNode": [
- "reserved",
- "safeIsland",
- "mergePoint"
- ],
- "disabled": ["turnOutPointOnLeft"],
- "enabled": [
- "timeRestrictionsOnParking",
- "adaptiveTimingPresent",
- "turnOutPointOnRight",
- "bikeBoxInFront"
- ],
- "data": [
- { "laneCrownPointCenter": -58 },
- { "pathEndPointAngle": -55 },
- { "pathEndPointAngle": -58 }
- ],
- "dWidth": 472,
- "dElevation": -190
- }
- }
- ]
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 16,
- "doNotUse4": 13,
- "content": {
- "genericSign": [
- { "item": { "itis": 61599 } },
- { "item": { "itis": 47850 } },
- { "item": { "itis": 39204 } },
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5S" } }
- ]
- },
- "url": "IA5"
- },
- {
- "doNotUse1": 7,
- "frameType": "roadSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 2457,
- "startTime": 66787,
- "durationTime": 19034,
- "priority": 4,
- "doNotUse2": 16,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 61846, "id": 12218 },
- "anchor": {
- "lat": 202451669,
- "long": -1016248785,
- "elevation": 14777
- },
- "laneWidth": 4825,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": true,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100meters",
- "laneWidth": 23305,
- "circle": {
- "center": {
- "lat": 257084126,
- "long": -1572221105,
- "elevation": 10372
- },
- "radius": 3021,
- "units": "cm2-5"
- }
- }
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 44916, "id": 14928 },
- "anchor": {
- "lat": -391962488,
- "long": -1442690475,
- "elevation": 975
- },
- "laneWidth": 8081,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 15,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 216,
- "offsetXaxis": { "small": 682 },
- "offsetYaxis": { "large": -6571 },
- "rotateXY": 11786,
- "scaleXaxis": -269,
- "scaleYaxis": -432
- }
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 15268, "id": 63916 },
- "anchor": {
- "lat": -14883901,
- "long": 1470459302,
- "elevation": 47965
- },
- "laneWidth": 374,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100000meters",
- "area": {
- "circle": {
- "center": {
- "lat": 223434207,
- "long": -714422034,
- "elevation": 41663
- },
- "radius": 737,
- "units": "cm2-5"
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 2,
- "doNotUse4": 31,
- "content": {
- "workZone": [
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5St" } },
- { "item": { "itis": 52884 } }
- ]
- },
- "url": "I"
- },
- {
- "doNotUse1": 16,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 604037802,
- "long": -124613998,
- "elevation": 46289
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": true,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "guide",
- "crc": "4F43"
- }
- },
- "startYear": 135,
- "startTime": 30119,
- "durationTime": 17072,
- "priority": 7,
- "doNotUse2": 6,
- "regions": [
- {
- "name": "IA5S",
- "id": { "region": 35731, "id": 64365 },
- "anchor": {
- "lat": 251341270,
- "long": -1550588968,
- "elevation": 18073
- },
- "laneWidth": 19174,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": true
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 19339,
- "circle": {
- "center": {
- "lat": -590142898,
- "long": 192563845,
- "elevation": 3040
- },
- "radius": 734,
- "units": "meter"
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 13160, "id": 48242 },
- "anchor": {
- "lat": 227302831,
- "long": -891580621,
- "elevation": 7072
- },
- "laneWidth": 5923,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "area": {
- "circle": {
- "center": {
- "lat": 368610426,
- "long": -1703460317,
- "elevation": 1004
- },
- "radius": 2194,
- "units": "meter"
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 58508, "id": 15927 },
- "anchor": {
- "lat": 892488592,
- "long": -431640924,
- "elevation": 41561
- },
- "laneWidth": 26527,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "regionPointSet": {
- "anchor": {
- "lat": -113602543,
- "long": 717746718,
- "elevation": 49498
- },
- "scale": 1,
- "nodeList": [
- {
- "xOffset": 27670,
- "yOffset": -14790,
- "zOffset": -21638
- },
- { "xOffset": 3020, "yOffset": -9872, "zOffset": -109 },
- {
- "xOffset": -24382,
- "yOffset": 23709,
- "zOffset": -862
- },
- {
- "xOffset": -26476,
- "yOffset": -6439,
- "zOffset": -23411
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 379, "id": 22438 },
- "anchor": {
- "lat": -281093797,
- "long": 556669965,
- "elevation": 29497
- },
- "laneWidth": 7880,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor500000meters",
- "laneWidth": 2148,
- "circle": {
- "center": {
- "lat": 163173661,
- "long": -872411303,
- "elevation": 55588
- },
- "radius": 489,
- "units": "cm2-5"
- }
- }
- }
- }
- ],
- "doNotUse3": 8,
- "doNotUse4": 29,
- "content": {
- "advisory": [
- { "item": { "itis": 44093 } },
- { "item": { "itis": 65240 } },
- { "item": { "text": "IA" } }
- ]
- },
- "url": "I"
- },
- {
- "doNotUse1": 31,
- "frameType": "advisory",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": -864002503,
- "long": -654286715,
- "elevation": 43804
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 3076,
- "startTime": 282183,
- "durationTime": 14436,
- "priority": 6,
- "doNotUse2": 11,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 11880, "id": 33814 },
- "anchor": {
- "lat": 51295938,
- "long": 799818234,
- "elevation": 10466
- },
- "laneWidth": 10554,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 10,
- "offset": {
- "xy": {
- "nodes": [
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": ["mergePoint"],
- "disabled": [
- "transitStopOnLeft",
- "bikeBoxInFront",
- "doNotBlock"
- ],
- "enabled": ["mergingLaneLeft", "mergingLaneRight"],
- "data": [
- { "laneCrownPointCenter": 91 },
- { "laneCrownPointLeft": -60 },
- { "laneCrownPointLeft": -118 }
- ],
- "dWidth": -80,
- "dElevation": -211
- }
- },
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": [
- "hydrantPresent",
- "roundedCapStyleA",
- "roundedCapStyleB"
- ],
- "disabled": ["turnOutPointOnRight"],
- "enabled": ["adjacentParkingOnRight", "curbOnLeft"],
- "data": [
- { "laneCrownPointCenter": -3 },
- { "laneCrownPointCenter": -23 },
- {
- "speedLimits": [
- { "type": "vehicleMinSpeed", "speed": 5260 },
- {
- "type": "maxSpeedInConstructionZone",
- "speed": 7676
- }
- ]
- }
- ],
- "dWidth": -98,
- "dElevation": -300
- }
- },
- {
- "delta": { "node-XY5": { "x": 6552, "y": -7382 } },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "stopLine",
- "reserved",
- "roundedCapStyleB"
- ],
- "disabled": [
- "curbOnLeft",
- "turnOutPointOnRight",
- "whiteLine",
- "curbOnRight"
- ],
- "enabled": [
- "sharedWithTrackedVehicle",
- "audibleSignalingPresent",
- "headInParking"
- ],
- "data": [
- { "laneCrownPointCenter": -7 },
- { "laneAngle": 68 },
- { "laneCrownPointLeft": -39 }
- ],
- "dWidth": 287,
- "dElevation": 510
- }
- },
- {
- "delta": { "node-XY1": { "x": -310, "y": -500 } },
- "attributes": {
- "localNode": ["roundedCapStyleA"],
- "disabled": [
- "timeRestrictionsOnParking",
- "reserved",
- "parallelParking",
- "midBlockCurbPresent"
- ],
- "enabled": [
- "transitStopOnRight",
- "whiteLine",
- "taperToCenterLine",
- "adjacentParkingOnLeft",
- "timeRestrictionsOnParking"
- ],
- "data": [
- { "laneAngle": -59 },
- { "laneCrownPointCenter": 105 },
- { "laneCrownPointCenter": 25 },
- {
- "speedLimits": [
- {
- "type": "vehicleNightMaxSpeed",
- "speed": 2245
- },
- { "type": "vehicleMaxSpeed", "speed": 1700 }
- ]
- },
- {
- "speedLimits": [
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 7839
- },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 1190
- },
- { "type": "truckMaxSpeed", "speed": 3947 }
- ]
- }
- ],
- "dWidth": 497,
- "dElevation": -208
- }
- },
- {
- "delta": {
- "node-LatLon": {
- "lon": -1625296958,
- "lat": 501091223
- }
- },
- "attributes": {
- "localNode": [
- "downstreamStartNode",
- "downstreamStopLine",
- "safeIsland"
- ],
- "disabled": [
- "adjacentParkingOnLeft",
- "partialCurbIntrusion",
- "taperToRight"
- ],
- "enabled": [
- "unEvenPavementPresent",
- "adjacentParkingOnRight"
- ],
- "data": [{ "laneCrownPointCenter": 86 }],
- "dWidth": -90,
- "dElevation": 131
- }
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 48039, "id": 14622 },
- "anchor": {
- "lat": 419808681,
- "long": -1470200813,
- "elevation": 37213
- },
- "laneWidth": 25845,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": true,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 25719,
- "circle": {
- "center": {
- "lat": -666313075,
- "long": 639822734,
- "elevation": 29597
- },
- "radius": 1325,
- "units": "foot"
- }
- }
- }
- }
- ],
- "doNotUse3": 11,
- "doNotUse4": 27,
- "content": { "speedLimit": [{ "item": { "text": "I" } }] },
- "url": "IA"
- },
- {
- "doNotUse1": 18,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 889823043,
- "long": -537303585,
- "elevation": 29359
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 1652,
- "startTime": 115878,
- "durationTime": 7970,
- "priority": 6,
- "doNotUse2": 27,
- "regions": [
- {
- "name": "I",
- "id": { "region": 26015, "id": 40525 },
- "anchor": {
- "lat": 112058765,
- "long": 1125609019,
- "elevation": 54648
- },
- "laneWidth": 31409,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "shapePointSet": {
- "anchor": {
- "lat": 733403986,
- "long": 1001009347,
- "elevation": 23252
- },
- "laneWidth": 14952,
- "directionality": "unavailable",
- "nodeList": {
- "computed": {
- "referenceLaneId": 188,
- "offsetXaxis": { "large": -8154 },
- "offsetYaxis": { "large": -28485 },
- "rotateXY": 224,
- "scaleXaxis": 32,
- "scaleYaxis": 1787
- }
- }
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 14,
- "doNotUse4": 21,
- "content": { "exitService": [{ "item": { "text": "I" } }] },
- "url": "I"
- }
- ]
- },
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation"
- }
- }
-
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-second-later.json b/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-second-later.json
deleted file mode 100644
index ac9934d..0000000
--- a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference-1-second-later.json
+++ /dev/null
@@ -1,1299 +0,0 @@
-{
- "metadata": {
- "logFileName": "",
- "recordType": "timMsg",
- "securityResultCode": "success",
- "receivedMessageDetails": { "rxSource": "NA" },
- "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload",
- "serialId": {
- "streamId": "b2d15f2d-7461-4083-b3df-b4efadab4d17",
- "bundleSize": 1,
- "bundleId": 0,
- "recordId": 0,
- "serialNumber": 0
- },
- "odeReceivedAt": "2025-02-01T00:19:46.739Z",
- "schemaVersion": 8,
- "maxDurationTime": 0,
- "recordGeneratedAt": "",
- "recordGeneratedBy": "RSU",
- "sanitized": false,
- "odePacketID": "",
- "odeTimStartDateTime": "",
- "asn1": "001F83A175D472274F43544554205354520A4C16B18193D0D1F9CDF54733FB1BFC0C983FCFC48D24FF97A474B8A754A9112A6F690200192EFCB5FF96D90FA32D4E83FC0C9830B5F5FC150A5059C545235AC20227C697080018815F84759CB3BF452C850424643A30E028544E9C511560A9DD8C2629F0D4470DBB3DDB4316096FC100800809BC746A108C8F26FC4C3208DA0E61091B7429182D3BFC0C98359EA8B4B454C16E606F037AE007A1CDE32000152E6C0ECDF612A90558D403FC049BF003734AC1C240EC930B39E850A7990A808008C033EFC47606FDDFA252B4A9942280C1020C9D818700EC4B4A76680C001D9F981240013111914408214602F8173D850A0D48F09F5D75264929260B5A7D27260B5A65260B56744F43999104E394B5204FF09260B5A7D3E32C5F74A0DB09EA975B8C1724DC92D9201005800092D84A89EF67BC1B27429C710979A5FE0E4C16B4F5EE874A08F2404C40AA60E2A09E79F91602003E5DB0AA9B32A2E0A6F36507F829305ACEE93E6B134C1CCC3C2EF3FA5CB5D02ECE000142002950BD8FB7D02D26BB6CAFCB848BE4A9260B5A7D29260B5A7D19D28125C17566972EA98F7172471344010153D0C21C1D69E158731BFC1C982D69E2E4FEDB544A012D60EDDB5D7569995CCC001CB02000CB8B449E02D39DB1072106F80B79BFC14982D666D178E4A198A3579B12B09915D01723B0000A10002A973AEAF40B82284427D9124DFE024F9230F8DD6AD73490518F80A3B259CF3FC40014001266976FBC88CB08E20EE8AD087EC16463A2B7AC5E62CB83FC9C830B7275F28A3128CDB2491AFF05260B580BDABD3249C784B718EFDC1906727B228001160002B10C89FAF5F0E9BA4F0AC74920F4947402561EBFB6201930424BF9E8112A39CA22519425D8E01001A7A1E0222723B864CB17F849305AD3E92E6884164E2CE7F0A6BD84FE4E38949D300081A01A290029F8111120048308876C910829B04B5148014FC9621814460542FAA24A460FBF82D2CF1A8CE66032A7E6A0807028A04283228610217947C12CE3FFF20CA031F809A2007D242408F0B4510F23D2A2646294D48A41F4F8494C87B58CCFE2983829A707069C17A4BBF23992859B3A528C03ACD3506FF07260B5A7BBA7391E53AAABAA44EA1584A857727A910002C0020391DD0DEDC78D916CBD8D839D52DABDB084919305C975AABA210D2D0CDF7A0ABC1000D3D0D9D071298F916D83FC049B2CFCF26A78A5951B5CC28075CAF1EAC780042808048EB0ADE229537A0161356A3A68175E5809621740382083BEDD5810921240",
- "originIp": "172.20.0.1"
- },
- "payload": {
- "data": {
- "msgCnt": 93,
- "timeStamp": 291367,
- "packetID": "4F4354455420535452",
- "urlB": "IA5",
- "dataFrames": [
- {
- "doNotUse1": 0,
- "frameType": "commercialSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 1150,
- "startTime": 473045,
- "durationTime": 3687,
- "priority": 7,
- "doNotUse2": 22,
- "regions": [
- {
- "name": "IA",
- "id": { "region": 64764, "id": 18642 },
- "anchor": {
- "lat": 172032029,
- "long": -1025506517,
- "elevation": 13386
- },
- "laneWidth": 19949,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 9,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 252,
- "offsetXaxis": { "large": -5120 },
- "offsetYaxis": { "small": -585 },
- "rotateXY": 8692,
- "scaleXaxis": -422,
- "scaleYaxis": 464
- }
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 2911, "id": 24513 },
- "anchor": {
- "lat": 217001329,
- "long": -436271951,
- "elevation": 28809
- },
- "laneWidth": 30930,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 8,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL4": { "lon": 115258, "lat": 80231 }
- },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "hydrantPresent",
- "mergePoint",
- "divergePoint",
- "reserved"
- ],
- "disabled": [
- "transitStopOnRight",
- "adaptiveTimingPresent",
- "loadingzoneOnLeft",
- "costToPark"
- ],
- "enabled": ["curbOnLeft"],
- "data": [
- {
- "speedLimits": [
- {
- "type": "truckNightMaxSpeed",
- "speed": 6769
- },
- { "type": "truckMaxSpeed", "speed": 4438 },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 2679
- },
- {
- "type": "vehiclesWithTrailersNightMaxSpeed",
- "speed": 3110
- },
- { "type": "vehicleMaxSpeed", "speed": 1987 }
- ]
- }
- ],
- "dWidth": -188,
- "dElevation": -61
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": 5893850, "lat": -6770613 }
- },
- "attributes": {
- "localNode": ["closedToTraffic"],
- "disabled": ["bikeBoxInFront"],
- "enabled": ["mergingLaneRight"],
- "data": [{ "laneCrownPointLeft": -17 }],
- "dWidth": -396,
- "dElevation": -88
- }
- },
- {
- "delta": { "node-LL1": { "lon": -924, "lat": -109 } },
- "attributes": {
- "localNode": [
- "downstreamStopLine",
- "roundedCapStyleB"
- ],
- "disabled": ["whiteLine", "partialCurbIntrusion"],
- "enabled": [
- "loadingzoneOnLeft",
- "audibleSignalingPresent",
- "freeParking"
- ],
- "data": [
- { "laneCrownPointCenter": 55 },
- { "laneAngle": -98 }
- ],
- "dWidth": -319,
- "dElevation": -89
- }
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 23018, "id": 35659 },
- "anchor": {
- "lat": -544509288,
- "long": -1334375239,
- "elevation": -3608
- },
- "laneWidth": 14780,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": true,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 5,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 108,
- "offsetXaxis": { "small": -1574 },
- "offsetYaxis": { "large": -635 },
- "rotateXY": 21792,
- "scaleXaxis": 689,
- "scaleYaxis": 640
- }
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 32256, "id": 28265 },
- "anchor": {
- "lat": 725366646,
- "long": -566506763,
- "elevation": 6227
- },
- "laneWidth": 26178,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 1,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL5": { "lon": 2030663, "lat": -517129 }
- },
- "attributes": {
- "localNode": [
- "safeIsland",
- "hydrantPresent",
- "curbPresentAtStepOff"
- ],
- "disabled": [
- "sharedWithTrackedVehicle",
- "transitStopOnLeft",
- "headInParking",
- "audibleSignalingPresent"
- ],
- "enabled": ["doNotBlock", "mergingLaneLeft"],
- "data": [
- { "laneCrownPointRight": 48 },
- { "laneCrownPointRight": -114 }
- ],
- "dWidth": -505,
- "dElevation": -119
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": -5645920, "lat": -5242762 }
- },
- "attributes": {
- "localNode": [
- "reserved",
- "safeIsland",
- "mergePoint"
- ],
- "disabled": ["turnOutPointOnLeft"],
- "enabled": [
- "timeRestrictionsOnParking",
- "adaptiveTimingPresent",
- "turnOutPointOnRight",
- "bikeBoxInFront"
- ],
- "data": [
- { "laneCrownPointCenter": -58 },
- { "pathEndPointAngle": -55 },
- { "pathEndPointAngle": -58 }
- ],
- "dWidth": 472,
- "dElevation": -190
- }
- }
- ]
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 16,
- "doNotUse4": 13,
- "content": {
- "genericSign": [
- { "item": { "itis": 61599 } },
- { "item": { "itis": 47850 } },
- { "item": { "itis": 39204 } },
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5S" } }
- ]
- },
- "url": "IA5"
- },
- {
- "doNotUse1": 7,
- "frameType": "roadSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 2457,
- "startTime": 66787,
- "durationTime": 19034,
- "priority": 4,
- "doNotUse2": 16,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 61846, "id": 12218 },
- "anchor": {
- "lat": 202451669,
- "long": -1016248785,
- "elevation": 14777
- },
- "laneWidth": 4825,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": true,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100meters",
- "laneWidth": 23305,
- "circle": {
- "center": {
- "lat": 257084126,
- "long": -1572221105,
- "elevation": 10372
- },
- "radius": 3021,
- "units": "cm2-5"
- }
- }
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 44916, "id": 14928 },
- "anchor": {
- "lat": -391962488,
- "long": -1442690475,
- "elevation": 975
- },
- "laneWidth": 8081,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 15,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 216,
- "offsetXaxis": { "small": 682 },
- "offsetYaxis": { "large": -6571 },
- "rotateXY": 11786,
- "scaleXaxis": -269,
- "scaleYaxis": -432
- }
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 15268, "id": 63916 },
- "anchor": {
- "lat": -14883901,
- "long": 1470459302,
- "elevation": 47965
- },
- "laneWidth": 374,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100000meters",
- "area": {
- "circle": {
- "center": {
- "lat": 223434207,
- "long": -714422034,
- "elevation": 41663
- },
- "radius": 737,
- "units": "cm2-5"
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 2,
- "doNotUse4": 31,
- "content": {
- "workZone": [
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5St" } },
- { "item": { "itis": 52884 } }
- ]
- },
- "url": "I"
- },
- {
- "doNotUse1": 16,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 604037802,
- "long": -124613998,
- "elevation": 46289
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": true,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "guide",
- "crc": "4F43"
- }
- },
- "startYear": 135,
- "startTime": 30119,
- "durationTime": 17072,
- "priority": 7,
- "doNotUse2": 6,
- "regions": [
- {
- "name": "IA5S",
- "id": { "region": 35731, "id": 64365 },
- "anchor": {
- "lat": 251341270,
- "long": -1550588968,
- "elevation": 18073
- },
- "laneWidth": 19174,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": true
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 19339,
- "circle": {
- "center": {
- "lat": -590142898,
- "long": 192563845,
- "elevation": 3040
- },
- "radius": 734,
- "units": "meter"
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 13160, "id": 48242 },
- "anchor": {
- "lat": 227302831,
- "long": -891580621,
- "elevation": 7072
- },
- "laneWidth": 5923,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "area": {
- "circle": {
- "center": {
- "lat": 368610426,
- "long": -1703460317,
- "elevation": 1004
- },
- "radius": 2194,
- "units": "meter"
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 58508, "id": 15927 },
- "anchor": {
- "lat": 892488592,
- "long": -431640924,
- "elevation": 41561
- },
- "laneWidth": 26527,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "regionPointSet": {
- "anchor": {
- "lat": -113602543,
- "long": 717746718,
- "elevation": 49498
- },
- "scale": 1,
- "nodeList": [
- {
- "xOffset": 27670,
- "yOffset": -14790,
- "zOffset": -21638
- },
- { "xOffset": 3020, "yOffset": -9872, "zOffset": -109 },
- {
- "xOffset": -24382,
- "yOffset": 23709,
- "zOffset": -862
- },
- {
- "xOffset": -26476,
- "yOffset": -6439,
- "zOffset": -23411
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 379, "id": 22438 },
- "anchor": {
- "lat": -281093797,
- "long": 556669965,
- "elevation": 29497
- },
- "laneWidth": 7880,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor500000meters",
- "laneWidth": 2148,
- "circle": {
- "center": {
- "lat": 163173661,
- "long": -872411303,
- "elevation": 55588
- },
- "radius": 489,
- "units": "cm2-5"
- }
- }
- }
- }
- ],
- "doNotUse3": 8,
- "doNotUse4": 29,
- "content": {
- "advisory": [
- { "item": { "itis": 44093 } },
- { "item": { "itis": 65240 } },
- { "item": { "text": "IA" } }
- ]
- },
- "url": "I"
- },
- {
- "doNotUse1": 31,
- "frameType": "advisory",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": -864002503,
- "long": -654286715,
- "elevation": 43804
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 3076,
- "startTime": 282183,
- "durationTime": 14436,
- "priority": 6,
- "doNotUse2": 11,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 11880, "id": 33814 },
- "anchor": {
- "lat": 51295938,
- "long": 799818234,
- "elevation": 10466
- },
- "laneWidth": 10554,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 10,
- "offset": {
- "xy": {
- "nodes": [
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": ["mergePoint"],
- "disabled": [
- "transitStopOnLeft",
- "bikeBoxInFront",
- "doNotBlock"
- ],
- "enabled": ["mergingLaneLeft", "mergingLaneRight"],
- "data": [
- { "laneCrownPointCenter": 91 },
- { "laneCrownPointLeft": -60 },
- { "laneCrownPointLeft": -118 }
- ],
- "dWidth": -80,
- "dElevation": -211
- }
- },
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": [
- "hydrantPresent",
- "roundedCapStyleA",
- "roundedCapStyleB"
- ],
- "disabled": ["turnOutPointOnRight"],
- "enabled": ["adjacentParkingOnRight", "curbOnLeft"],
- "data": [
- { "laneCrownPointCenter": -3 },
- { "laneCrownPointCenter": -23 },
- {
- "speedLimits": [
- { "type": "vehicleMinSpeed", "speed": 5260 },
- {
- "type": "maxSpeedInConstructionZone",
- "speed": 7676
- }
- ]
- }
- ],
- "dWidth": -98,
- "dElevation": -300
- }
- },
- {
- "delta": { "node-XY5": { "x": 6552, "y": -7382 } },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "stopLine",
- "reserved",
- "roundedCapStyleB"
- ],
- "disabled": [
- "curbOnLeft",
- "turnOutPointOnRight",
- "whiteLine",
- "curbOnRight"
- ],
- "enabled": [
- "sharedWithTrackedVehicle",
- "audibleSignalingPresent",
- "headInParking"
- ],
- "data": [
- { "laneCrownPointCenter": -7 },
- { "laneAngle": 68 },
- { "laneCrownPointLeft": -39 }
- ],
- "dWidth": 287,
- "dElevation": 510
- }
- },
- {
- "delta": { "node-XY1": { "x": -310, "y": -500 } },
- "attributes": {
- "localNode": ["roundedCapStyleA"],
- "disabled": [
- "timeRestrictionsOnParking",
- "reserved",
- "parallelParking",
- "midBlockCurbPresent"
- ],
- "enabled": [
- "transitStopOnRight",
- "whiteLine",
- "taperToCenterLine",
- "adjacentParkingOnLeft",
- "timeRestrictionsOnParking"
- ],
- "data": [
- { "laneAngle": -59 },
- { "laneCrownPointCenter": 105 },
- { "laneCrownPointCenter": 25 },
- {
- "speedLimits": [
- {
- "type": "vehicleNightMaxSpeed",
- "speed": 2245
- },
- { "type": "vehicleMaxSpeed", "speed": 1700 }
- ]
- },
- {
- "speedLimits": [
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 7839
- },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 1190
- },
- { "type": "truckMaxSpeed", "speed": 3947 }
- ]
- }
- ],
- "dWidth": 497,
- "dElevation": -208
- }
- },
- {
- "delta": {
- "node-LatLon": {
- "lon": -1625296958,
- "lat": 501091223
- }
- },
- "attributes": {
- "localNode": [
- "downstreamStartNode",
- "downstreamStopLine",
- "safeIsland"
- ],
- "disabled": [
- "adjacentParkingOnLeft",
- "partialCurbIntrusion",
- "taperToRight"
- ],
- "enabled": [
- "unEvenPavementPresent",
- "adjacentParkingOnRight"
- ],
- "data": [{ "laneCrownPointCenter": 86 }],
- "dWidth": -90,
- "dElevation": 131
- }
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 48039, "id": 14622 },
- "anchor": {
- "lat": 419808681,
- "long": -1470200813,
- "elevation": 37213
- },
- "laneWidth": 25845,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": true,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 25719,
- "circle": {
- "center": {
- "lat": -666313075,
- "long": 639822734,
- "elevation": 29597
- },
- "radius": 1325,
- "units": "foot"
- }
- }
- }
- }
- ],
- "doNotUse3": 11,
- "doNotUse4": 27,
- "content": { "speedLimit": [{ "item": { "text": "I" } }] },
- "url": "IA"
- },
- {
- "doNotUse1": 18,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 889823043,
- "long": -537303585,
- "elevation": 29359
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 1652,
- "startTime": 115878,
- "durationTime": 7970,
- "priority": 6,
- "doNotUse2": 27,
- "regions": [
- {
- "name": "I",
- "id": { "region": 26015, "id": 40525 },
- "anchor": {
- "lat": 112058765,
- "long": 1125609019,
- "elevation": 54648
- },
- "laneWidth": 31409,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "shapePointSet": {
- "anchor": {
- "lat": 733403986,
- "long": 1001009347,
- "elevation": 23252
- },
- "laneWidth": 14952,
- "directionality": "unavailable",
- "nodeList": {
- "computed": {
- "referenceLaneId": 188,
- "offsetXaxis": { "large": -8154 },
- "offsetYaxis": { "large": -28485 },
- "rotateXY": 224,
- "scaleXaxis": 32,
- "scaleYaxis": 1787
- }
- }
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 14,
- "doNotUse4": 21,
- "content": { "exitService": [{ "item": { "text": "I" } }] },
- "url": "I"
- }
- ]
- },
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation"
- }
- }
-
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference.json b/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference.json
index ddf761c..f0be88f 100644
--- a/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference.json
+++ b/jpo-deduplicator/src/test/resources/json/ode_tim/sample.ode-tim-reference.json
@@ -1,1298 +1,193 @@
{
- "metadata": {
- "logFileName": "",
- "recordType": "timMsg",
- "securityResultCode": "success",
- "receivedMessageDetails": { "rxSource": "NA" },
- "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload",
- "serialId": {
- "streamId": "b2d15f2d-7461-4083-b3df-b4efadab4d17",
- "bundleSize": 1,
- "bundleId": 0,
- "recordId": 0,
- "serialNumber": 0
- },
- "odeReceivedAt": "2025-02-01T00:19:45.739Z",
- "schemaVersion": 8,
- "maxDurationTime": 0,
- "recordGeneratedAt": "",
- "recordGeneratedBy": "RSU",
- "sanitized": false,
- "odePacketID": "",
- "odeTimStartDateTime": "",
- "asn1": "001F83A175D472274F43544554205354520A4C16B18193D0D1F9CDF54733FB1BFC0C983FCFC48D24FF97A474B8A754A9112A6F690200192EFCB5FF96D90FA32D4E83FC0C9830B5F5FC150A5059C545235AC20227C697080018815F84759CB3BF452C850424643A30E028544E9C511560A9DD8C2629F0D4470DBB3DDB4316096FC100800809BC746A108C8F26FC4C3208DA0E61091B7429182D3BFC0C98359EA8B4B454C16E606F037AE007A1CDE32000152E6C0ECDF612A90558D403FC049BF003734AC1C240EC930B39E850A7990A808008C033EFC47606FDDFA252B4A9942280C1020C9D818700EC4B4A76680C001D9F981240013111914408214602F8173D850A0D48F09F5D75264929260B5A7D27260B5A65260B56744F43999104E394B5204FF09260B5A7D3E32C5F74A0DB09EA975B8C1724DC92D9201005800092D84A89EF67BC1B27429C710979A5FE0E4C16B4F5EE874A08F2404C40AA60E2A09E79F91602003E5DB0AA9B32A2E0A6F36507F829305ACEE93E6B134C1CCC3C2EF3FA5CB5D02ECE000142002950BD8FB7D02D26BB6CAFCB848BE4A9260B5A7D29260B5A7D19D28125C17566972EA98F7172471344010153D0C21C1D69E158731BFC1C982D69E2E4FEDB544A012D60EDDB5D7569995CCC001CB02000CB8B449E02D39DB1072106F80B79BFC14982D666D178E4A198A3579B12B09915D01723B0000A10002A973AEAF40B82284427D9124DFE024F9230F8DD6AD73490518F80A3B259CF3FC40014001266976FBC88CB08E20EE8AD087EC16463A2B7AC5E62CB83FC9C830B7275F28A3128CDB2491AFF05260B580BDABD3249C784B718EFDC1906727B228001160002B10C89FAF5F0E9BA4F0AC74920F4947402561EBFB6201930424BF9E8112A39CA22519425D8E01001A7A1E0222723B864CB17F849305AD3E92E6884164E2CE7F0A6BD84FE4E38949D300081A01A290029F8111120048308876C910829B04B5148014FC9621814460542FAA24A460FBF82D2CF1A8CE66032A7E6A0807028A04283228610217947C12CE3FFF20CA031F809A2007D242408F0B4510F23D2A2646294D48A41F4F8494C87B58CCFE2983829A707069C17A4BBF23992859B3A528C03ACD3506FF07260B5A7BBA7391E53AAABAA44EA1584A857727A910002C0020391DD0DEDC78D916CBD8D839D52DABDB084919305C975AABA210D2D0CDF7A0ABC1000D3D0D9D071298F916D83FC049B2CFCF26A78A5951B5CC28075CAF1EAC780042808048EB0ADE229537A0161356A3A68175E5809621740382083BEDD5810921240",
- "originIp": "172.20.0.1"
- },
- "payload": {
- "data": {
- "msgCnt": 93,
- "timeStamp": 291367,
- "packetID": "4F4354455420535452",
- "urlB": "IA5",
- "dataFrames": [
- {
- "doNotUse1": 0,
- "frameType": "commercialSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 1150,
- "startTime": 473045,
- "durationTime": 3687,
- "priority": 7,
- "doNotUse2": 22,
- "regions": [
- {
- "name": "IA",
- "id": { "region": 64764, "id": 18642 },
- "anchor": {
- "lat": 172032029,
- "long": -1025506517,
- "elevation": 13386
- },
- "laneWidth": 19949,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 9,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 252,
- "offsetXaxis": { "large": -5120 },
- "offsetYaxis": { "small": -585 },
- "rotateXY": 8692,
- "scaleXaxis": -422,
- "scaleYaxis": 464
- }
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 2911, "id": 24513 },
- "anchor": {
- "lat": 217001329,
- "long": -436271951,
- "elevation": 28809
- },
- "laneWidth": 30930,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 8,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL4": { "lon": 115258, "lat": 80231 }
- },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "hydrantPresent",
- "mergePoint",
- "divergePoint",
- "reserved"
- ],
- "disabled": [
- "transitStopOnRight",
- "adaptiveTimingPresent",
- "loadingzoneOnLeft",
- "costToPark"
- ],
- "enabled": ["curbOnLeft"],
- "data": [
- {
- "speedLimits": [
- {
- "type": "truckNightMaxSpeed",
- "speed": 6769
- },
- { "type": "truckMaxSpeed", "speed": 4438 },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 2679
- },
- {
- "type": "vehiclesWithTrailersNightMaxSpeed",
- "speed": 3110
- },
- { "type": "vehicleMaxSpeed", "speed": 1987 }
- ]
- }
- ],
- "dWidth": -188,
- "dElevation": -61
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": 5893850, "lat": -6770613 }
- },
- "attributes": {
- "localNode": ["closedToTraffic"],
- "disabled": ["bikeBoxInFront"],
- "enabled": ["mergingLaneRight"],
- "data": [{ "laneCrownPointLeft": -17 }],
- "dWidth": -396,
- "dElevation": -88
- }
- },
- {
- "delta": { "node-LL1": { "lon": -924, "lat": -109 } },
- "attributes": {
- "localNode": [
- "downstreamStopLine",
- "roundedCapStyleB"
- ],
- "disabled": ["whiteLine", "partialCurbIntrusion"],
- "enabled": [
- "loadingzoneOnLeft",
- "audibleSignalingPresent",
- "freeParking"
- ],
- "data": [
- { "laneCrownPointCenter": 55 },
- { "laneAngle": -98 }
- ],
- "dWidth": -319,
- "dElevation": -89
- }
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA",
- "id": { "region": 23018, "id": 35659 },
- "anchor": {
- "lat": -544509288,
- "long": -1334375239,
- "elevation": -3608
- },
- "laneWidth": 14780,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": true,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 5,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 108,
- "offsetXaxis": { "small": -1574 },
- "offsetYaxis": { "large": -635 },
- "rotateXY": 21792,
- "scaleXaxis": 689,
- "scaleYaxis": 640
- }
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 32256, "id": 28265 },
- "anchor": {
- "lat": 725366646,
- "long": -566506763,
- "elevation": 6227
- },
- "laneWidth": 26178,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 1,
- "offset": {
- "ll": {
- "nodes": [
- {
- "delta": {
- "node-LL5": { "lon": 2030663, "lat": -517129 }
- },
- "attributes": {
- "localNode": [
- "safeIsland",
- "hydrantPresent",
- "curbPresentAtStepOff"
- ],
- "disabled": [
- "sharedWithTrackedVehicle",
- "transitStopOnLeft",
- "headInParking",
- "audibleSignalingPresent"
- ],
- "enabled": ["doNotBlock", "mergingLaneLeft"],
- "data": [
- { "laneCrownPointRight": 48 },
- { "laneCrownPointRight": -114 }
- ],
- "dWidth": -505,
- "dElevation": -119
- }
- },
- {
- "delta": {
- "node-LL6": { "lon": -5645920, "lat": -5242762 }
- },
- "attributes": {
- "localNode": [
- "reserved",
- "safeIsland",
- "mergePoint"
- ],
- "disabled": ["turnOutPointOnLeft"],
- "enabled": [
- "timeRestrictionsOnParking",
- "adaptiveTimingPresent",
- "turnOutPointOnRight",
- "bikeBoxInFront"
- ],
- "data": [
- { "laneCrownPointCenter": -58 },
- { "pathEndPointAngle": -55 },
- { "pathEndPointAngle": -58 }
- ],
- "dWidth": 472,
- "dElevation": -190
- }
- }
- ]
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 16,
- "doNotUse4": 13,
- "content": {
- "genericSign": [
- { "item": { "itis": 61599 } },
- { "item": { "itis": 47850 } },
- { "item": { "itis": 39204 } },
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5S" } }
- ]
- },
- "url": "IA5"
+ "metadata": {
+ "logFileName": "",
+ "recordType": "timMsg",
+ "securityResultCode": "success",
+ "receivedMessageDetails": {
+ "rxSource": "NA"
},
- {
- "doNotUse1": 7,
- "frameType": "roadSignage",
- "msgId": { "furtherInfoID": "4F43" },
- "startYear": 2457,
- "startTime": 66787,
- "durationTime": 19034,
- "priority": 4,
- "doNotUse2": 16,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 61846, "id": 12218 },
- "anchor": {
- "lat": 202451669,
- "long": -1016248785,
- "elevation": 14777
- },
- "laneWidth": 4825,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": true,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100meters",
- "laneWidth": 23305,
- "circle": {
- "center": {
- "lat": 257084126,
- "long": -1572221105,
- "elevation": 10372
- },
- "radius": 3021,
- "units": "cm2-5"
- }
- }
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 44916, "id": 14928 },
- "anchor": {
- "lat": -391962488,
- "long": -1442690475,
- "elevation": 975
- },
- "laneWidth": 8081,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 15,
- "offset": {
- "xy": {
- "computed": {
- "referenceLaneId": 216,
- "offsetXaxis": { "small": 682 },
- "offsetYaxis": { "large": -6571 },
- "rotateXY": 11786,
- "scaleXaxis": -269,
- "scaleYaxis": -432
- }
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 15268, "id": 63916 },
- "anchor": {
- "lat": -14883901,
- "long": 1470459302,
- "elevation": 47965
- },
- "laneWidth": 374,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor100000meters",
- "area": {
- "circle": {
- "center": {
- "lat": 223434207,
- "long": -714422034,
- "elevation": 41663
- },
- "radius": 737,
- "units": "cm2-5"
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 2,
- "doNotUse4": 31,
- "content": {
- "workZone": [
- { "item": { "text": "IA5St" } },
- { "item": { "text": "IA5St" } },
- { "item": { "itis": 52884 } }
- ]
- },
- "url": "I"
+ "payloadType": "us.dot.its.jpo.ode.model.OdeMessageFramePayload",
+ "serialId": {
+ "streamId": "561db635-0a2e-4e37-ba2e-2a8db78180da",
+ "bundleSize": 1,
+ "bundleId": 0,
+ "recordId": 0,
+ "serialNumber": 0
},
- {
- "doNotUse1": 16,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 604037802,
- "long": -124613998,
- "elevation": 46289
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": true,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "guide",
- "crc": "4F43"
- }
- },
- "startYear": 135,
- "startTime": 30119,
- "durationTime": 17072,
- "priority": 7,
- "doNotUse2": 6,
- "regions": [
- {
- "name": "IA5S",
- "id": { "region": 35731, "id": 64365 },
- "anchor": {
- "lat": 251341270,
- "long": -1550588968,
- "elevation": 18073
- },
- "laneWidth": 19174,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": true
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 19339,
- "circle": {
- "center": {
- "lat": -590142898,
- "long": 192563845,
- "elevation": 3040
- },
- "radius": 734,
- "units": "meter"
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 13160, "id": 48242 },
- "anchor": {
- "lat": 227302831,
- "long": -891580621,
- "elevation": 7072
- },
- "laneWidth": 5923,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": true,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": true,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "area": {
- "circle": {
- "center": {
- "lat": 368610426,
- "long": -1703460317,
- "elevation": 1004
- },
- "radius": 2194,
- "units": "meter"
- }
- }
- }
- }
- },
- {
- "name": "I",
- "id": { "region": 58508, "id": 15927 },
- "anchor": {
- "lat": 892488592,
- "long": -431640924,
- "elevation": 41561
- },
- "laneWidth": 26527,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": true,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "regionPointSet": {
- "anchor": {
- "lat": -113602543,
- "long": 717746718,
- "elevation": 49498
- },
- "scale": 1,
- "nodeList": [
- {
- "xOffset": 27670,
- "yOffset": -14790,
- "zOffset": -21638
- },
- { "xOffset": 3020, "yOffset": -9872, "zOffset": -109 },
- {
- "xOffset": -24382,
- "yOffset": 23709,
- "zOffset": -862
- },
- {
- "xOffset": -26476,
- "yOffset": -6439,
- "zOffset": -23411
- }
- ]
- }
- }
- }
- }
- },
- {
- "name": "IA5",
- "id": { "region": 379, "id": 22438 },
- "anchor": {
- "lat": -281093797,
- "long": 556669965,
- "elevation": 29497
- },
- "laneWidth": 7880,
- "directionality": "reverse",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": true,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor500000meters",
- "laneWidth": 2148,
- "circle": {
- "center": {
- "lat": 163173661,
- "long": -872411303,
- "elevation": 55588
- },
- "radius": 489,
- "units": "cm2-5"
- }
- }
- }
- }
- ],
- "doNotUse3": 8,
- "doNotUse4": 29,
- "content": {
- "advisory": [
- { "item": { "itis": 44093 } },
- { "item": { "itis": 65240 } },
- { "item": { "text": "IA" } }
- ]
- },
- "url": "I"
- },
- {
- "doNotUse1": 31,
- "frameType": "advisory",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": -864002503,
- "long": -654286715,
- "elevation": 43804
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": true,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 3076,
- "startTime": 282183,
- "durationTime": 14436,
- "priority": 6,
- "doNotUse2": 11,
- "regions": [
- {
- "name": "IA5St",
- "id": { "region": 11880, "id": 33814 },
- "anchor": {
- "lat": 51295938,
- "long": 799818234,
- "elevation": 10466
- },
- "laneWidth": 10554,
- "directionality": "forward",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "path": {
- "scale": 10,
- "offset": {
- "xy": {
- "nodes": [
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": ["mergePoint"],
- "disabled": [
- "transitStopOnLeft",
- "bikeBoxInFront",
- "doNotBlock"
- ],
- "enabled": ["mergingLaneLeft", "mergingLaneRight"],
- "data": [
- { "laneCrownPointCenter": 91 },
- { "laneCrownPointLeft": -60 },
- { "laneCrownPointLeft": -118 }
- ],
- "dWidth": -80,
- "dElevation": -211
- }
- },
- {
- "delta": { "node-XY1": { "x": 144, "y": -502 } },
- "attributes": {
- "localNode": [
- "hydrantPresent",
- "roundedCapStyleA",
- "roundedCapStyleB"
- ],
- "disabled": ["turnOutPointOnRight"],
- "enabled": ["adjacentParkingOnRight", "curbOnLeft"],
- "data": [
- { "laneCrownPointCenter": -3 },
- { "laneCrownPointCenter": -23 },
- {
- "speedLimits": [
- { "type": "vehicleMinSpeed", "speed": 5260 },
- {
- "type": "maxSpeedInConstructionZone",
- "speed": 7676
- }
- ]
- }
- ],
- "dWidth": -98,
- "dElevation": -300
- }
- },
- {
- "delta": { "node-XY5": { "x": 6552, "y": -7382 } },
- "attributes": {
- "localNode": [
- "curbPresentAtStepOff",
- "stopLine",
- "reserved",
- "roundedCapStyleB"
- ],
- "disabled": [
- "curbOnLeft",
- "turnOutPointOnRight",
- "whiteLine",
- "curbOnRight"
- ],
- "enabled": [
- "sharedWithTrackedVehicle",
- "audibleSignalingPresent",
- "headInParking"
- ],
- "data": [
- { "laneCrownPointCenter": -7 },
- { "laneAngle": 68 },
- { "laneCrownPointLeft": -39 }
- ],
- "dWidth": 287,
- "dElevation": 510
- }
- },
+ "odeReceivedAt": "2025-07-31T21:01:14.116Z",
+ "schemaVersion": 9,
+ "maxDurationTime": 0,
+ "recordGeneratedAt": "",
+ "recordGeneratedBy": "RSU",
+ "sanitized": false,
+ "odePacketID": "",
+ "odeTimStartDateTime": "",
+ "asn1": "001F8086701495F5E71EF1B442B7ECAB160F775D9B0309C26A40DC116643D477FFF93F4A53D7801EA107F97937E1CF5ACD85FA54EADF62C17316CB99385CC59328000000009A9037045990F51C4E230078084481F58AEC0FFEFBE2799443290A396270844A50C1C21C39C8C120957EC12E533B9F88DBBDF72C23D9BE00248DE7F98084801004F775D9B060018300026B7001DE6CA800026B706D283EA881010100030180C620FB90CAAD3B9C508208D80AAFBCB7C03A5339692100032896C1FA8400A9830101800348010100018381834FCCE62548FA70C82D206DAE759688C1A1C7FBF7131921895391398277408C2B8080A03244FF56A33C8202A2751950632772A8D8F3DE46E01C09DA84ADBC7EF1F450F4EA104144A1099626709DAB6667C9EA43726FCD6C95DE91EDB9E928AD1975B1",
+ "source": "RSU",
+ "originIp": "10.16.28.208",
+ "isCertPresent": false
+ },
+ "payload": {
+ "data": {
+ "messageId": 31,
+ "value": {
+ "TravelerInformation": {
+ "msgCnt": 1,
+ "timeStamp": 300533,
+ "packetID": "E71EF1B442B7ECAB16",
+ "urlB": "null",
+ "dataFrames": [
{
- "delta": { "node-XY1": { "x": -310, "y": -500 } },
- "attributes": {
- "localNode": ["roundedCapStyleA"],
- "disabled": [
- "timeRestrictionsOnParking",
- "reserved",
- "parallelParking",
- "midBlockCurbPresent"
- ],
- "enabled": [
- "transitStopOnRight",
- "whiteLine",
- "taperToCenterLine",
- "adjacentParkingOnLeft",
- "timeRestrictionsOnParking"
- ],
- "data": [
- { "laneAngle": -59 },
- { "laneCrownPointCenter": 105 },
- { "laneCrownPointCenter": 25 },
- {
- "speedLimits": [
- {
- "type": "vehicleNightMaxSpeed",
- "speed": 2245
- },
- { "type": "vehicleMaxSpeed", "speed": 1700 }
+ "doNotUse1": 1,
+ "frameType": "advisory",
+ "msgId": {
+ "roadSignID": {
+ "position": {
+ "lat": 396571266,
+ "long": -1048663921
+ },
+ "viewAngle": "FFFF",
+ "mutcdCode": "warning"
+ }
+ },
+ "startYear": 2025,
+ "startTime": 305071,
+ "durationTime": 30,
+ "priority": 5,
+ "doNotUse2": 1,
+ "regions": [
+ {
+ "name": "I_CO-30_RSU_10.16.28.122",
+ "id": {
+ "region": 0,
+ "id": 0
+ },
+ "anchor": {
+ "lat": 396571266,
+ "long": -1048663921
+ },
+ "laneWidth": 5000,
+ "directionality": "both",
+ "closedPath": false,
+ "direction": "00F0",
+ "description": {
+ "path": {
+ "scale": 0,
+ "offset": {
+ "ll": {
+ "nodes": [
+ {
+ "delta": {
+ "node-LL1": {
+ "lon": -42,
+ "lat": -1349
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL1": {
+ "lon": -1,
+ "lat": -33
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": -1644,
+ "lat": -15575
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": -3637,
+ "lat": -6943
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": -7003,
+ "lat": -7417
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": -7289,
+ "lat": -4538
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": -6107,
+ "lat": -2068
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": -9050,
+ "lat": -2241
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": -18705,
+ "lat": -565
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL2": {
+ "lon": -6221,
+ "lat": -256
+ }
+ }
+ },
+ {
+ "delta": {
+ "node-LL3": {
+ "lon": -14114,
+ "lat": -104
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ],
+ "doNotUse3": 1,
+ "doNotUse4": 1,
+ "content": {
+ "workZone": [
+ {
+ "item": {
+ "itis": 1025
+ }
+ }
]
- },
- {
- "speedLimits": [
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 7839
- },
- {
- "type": "maxSpeedInSchoolZone",
- "speed": 1190
- },
- { "type": "truckMaxSpeed", "speed": 3947 }
- ]
- }
- ],
- "dWidth": 497,
- "dElevation": -208
- }
- },
- {
- "delta": {
- "node-LatLon": {
- "lon": -1625296958,
- "lat": 501091223
- }
- },
- "attributes": {
- "localNode": [
- "downstreamStartNode",
- "downstreamStopLine",
- "safeIsland"
- ],
- "disabled": [
- "adjacentParkingOnLeft",
- "partialCurbIntrusion",
- "taperToRight"
- ],
- "enabled": [
- "unEvenPavementPresent",
- "adjacentParkingOnRight"
- ],
- "data": [{ "laneCrownPointCenter": 86 }],
- "dWidth": -90,
- "dElevation": 131
- }
+ },
+ "url": "null"
}
- ]
- }
- }
+ ]
}
- }
- },
- {
- "name": "IA5S",
- "id": { "region": 48039, "id": 14622 },
- "anchor": {
- "lat": 419808681,
- "long": -1470200813,
- "elevation": 37213
- },
- "laneWidth": 25845,
- "directionality": "unavailable",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": true,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "geometry": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": true,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor3meters",
- "laneWidth": 25719,
- "circle": {
- "center": {
- "lat": -666313075,
- "long": 639822734,
- "elevation": 29597
- },
- "radius": 1325,
- "units": "foot"
- }
- }
- }
}
- ],
- "doNotUse3": 11,
- "doNotUse4": 27,
- "content": { "speedLimit": [{ "item": { "text": "I" } }] },
- "url": "IA"
},
- {
- "doNotUse1": 18,
- "frameType": "roadSignage",
- "msgId": {
- "roadSignID": {
- "position": {
- "lat": 889823043,
- "long": -537303585,
- "elevation": 29359
- },
- "viewAngle": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": true,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "mutcdCode": "maintenance",
- "crc": "4F43"
- }
- },
- "startYear": 1652,
- "startTime": 115878,
- "durationTime": 7970,
- "priority": 6,
- "doNotUse2": 27,
- "regions": [
- {
- "name": "I",
- "id": { "region": 26015, "id": 40525 },
- "anchor": {
- "lat": 112058765,
- "long": 1125609019,
- "elevation": 54648
- },
- "laneWidth": 31409,
- "directionality": "both",
- "closedPath": true,
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": false,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": true,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "description": {
- "oldRegion": {
- "direction": {
- "from000-0to022-5degrees": false,
- "from022-5to045-0degrees": false,
- "from045-0to067-5degrees": false,
- "from067-5to090-0degrees": false,
- "from090-0to112-5degrees": false,
- "from112-5to135-0degrees": false,
- "from135-0to157-5degrees": false,
- "from157-5to180-0degrees": true,
- "from180-0to202-5degrees": false,
- "from202-5to225-0degrees": false,
- "from225-0to247-5degrees": false,
- "from247-5to270-0degrees": false,
- "from270-0to292-5degrees": false,
- "from292-5to315-0degrees": false,
- "from315-0to337-5degrees": false,
- "from337-5to360-0degrees": false
- },
- "extent": "useFor50000meters",
- "area": {
- "shapePointSet": {
- "anchor": {
- "lat": 733403986,
- "long": 1001009347,
- "elevation": 23252
- },
- "laneWidth": 14952,
- "directionality": "unavailable",
- "nodeList": {
- "computed": {
- "referenceLaneId": 188,
- "offsetXaxis": { "large": -8154 },
- "offsetYaxis": { "large": -28485 },
- "rotateXY": 224,
- "scaleXaxis": 32,
- "scaleYaxis": 1787
- }
- }
- }
- }
- }
- }
- }
- ],
- "doNotUse3": 14,
- "doNotUse4": 21,
- "content": { "exitService": [{ "item": { "text": "I" } }] },
- "url": "I"
- }
- ]
- },
- "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation"
- }
-}
+ "dataType": "us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformationMessageFrame"
+ }
+}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-different.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-different.json
deleted file mode 100644
index 810d8ee..0000000
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-different.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [
- -100.0342901,
- 20.5671913
- ]
- },
- "properties": {
- "schemaVersion": 1,
- "messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:14.111Z",
- "originIp": "172.19.0.1",
- "validationMessages": [],
- "timeStamp": "2024-08-12T12:32:14.1034091Z",
- "accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
- },
- "accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
- },
- "brakes": {
- "wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
- "unavailable": true,
- "leftRear": false,
- "rightRear": false
- },
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
- },
- "heading": 359.4,
- "id": "12A7A952",
- "msgCnt": 25,
- "secMark": 2800,
- "size": {
- "width": 208,
- "length": 586
- },
- "transmission": "UNAVAILABLE",
- "speed": 0
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json
deleted file mode 100644
index 0c29589..0000000
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-position.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "type": "Feature",
- "properties": {
- "schemaVersion": 1,
- "messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:14.211Z",
- "originIp": "172.19.0.1",
- "validationMessages": [],
- "timeStamp": "2024-08-12T12:32:14.2034091Z",
- "accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
- },
- "accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
- },
- "brakes": {
- "wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
- "unavailable": true,
- "leftRear": false,
- "rightRear": false
- },
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
- },
- "heading": 359.4,
- "id": "12A7A952",
- "msgCnt": 25,
- "secMark": 2800,
- "size": {
- "width": 208,
- "length": 586
- },
- "transmission": "UNAVAILABLE",
- "speed": 0
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json
deleted file mode 100644
index 028e268..0000000
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-missing-speed.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [
- -100.0342901,
- 20.5671913
- ]
- },
- "properties": {
- "schemaVersion": 1,
- "messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:14.411Z",
- "originIp": "172.19.0.1",
- "validationMessages": [],
- "timeStamp": "2024-08-12T12:32:14.4034091Z",
- "accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
- },
- "accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
- },
- "brakes": {
- "wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
- "unavailable": true,
- "leftRear": false,
- "rightRear": false
- },
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
- },
- "heading": 359.4,
- "id": "12A7A952",
- "msgCnt": 25,
- "secMark": 2800,
- "size": {
- "width": 208,
- "length": 586
- },
- "transmission": "UNAVAILABLE"
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json
deleted file mode 100644
index ce64228..0000000
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-10-seconds-later.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [
- -105.0342901,
- 40.5671913
- ]
- },
- "properties": {
- "schemaVersion": 1,
- "messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:13.911Z",
- "originIp": "172.19.0.1",
- "validationMessages": [],
- "timeStamp": "2024-08-12T12:32:13.91191Z",
- "accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
- },
- "accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
- },
- "brakes": {
- "wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
- "unavailable": true,
- "leftRear": false,
- "rightRear": false
- },
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
- },
- "heading": 359.4,
- "id": "12A7A951",
- "msgCnt": 25,
- "secMark": 2800,
- "size": {
- "width": 208,
- "length": 586
- },
- "transmission": "UNAVAILABLE",
- "speed": 0
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json
deleted file mode 100644
index 7620fcf..0000000
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference-with-speed.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [
- -105.0342901,
- 40.5671913
- ]
- },
- "properties": {
- "schemaVersion": 1,
- "messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:14.011Z",
- "originIp": "172.19.0.1",
- "validationMessages": [],
- "timeStamp": "2024-08-12T12:32:14.0114091Z",
- "accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
- },
- "accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
- },
- "brakes": {
- "wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
- "unavailable": true,
- "leftRear": false,
- "rightRear": false
- },
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
- },
- "heading": 359.4,
- "id": "12A7A951",
- "msgCnt": 25,
- "secMark": 2800,
- "size": {
- "width": 208,
- "length": 586
- },
- "transmission": "UNAVAILABLE",
- "speed": 20
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json
index 2ba1909..8dd97ca 100644
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json
+++ b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-reference.json
@@ -3,51 +3,50 @@
"geometry": {
"type": "Point",
"coordinates": [
- -105.0342901,
- 40.5671913
+ -104.91520469999999,
+ 39.647704499999996
]
},
"properties": {
- "schemaVersion": 1,
+ "schemaVersion": 2,
"messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:01.811Z",
- "originIp": "172.19.0.1",
+ "odeReceivedAt": "2025-08-01T08:34:00.051Z",
+ "timeStamp": "2025-08-01T08:34:38.6Z",
+ "originIp": "172.18.0.1",
+ "asn1": "00143D5EC4C1CC2625B226A355BA966083E828EC14140000708BE8E0FD7B4FA100802C80000000000058C0210B5CBE596FE209AE12CF4B976AF881BA6D898640",
"validationMessages": [],
- "timeStamp": "2024-08-12T12:32:01.3034091Z",
"accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
+ "accelLong": -0.28,
+ "accelYaw": 0.45
},
"accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
+ "semiMajor": 2.0,
+ "semiMinor": 2.0,
+ "orientation": 0.0
},
"brakes": {
"wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
"unavailable": true,
+ "leftFront": false,
"leftRear": false,
+ "rightFront": false,
"rightRear": false
},
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
+ "traction": "UNAVAILABLE",
+ "abs": "UNAVAILABLE",
+ "scs": "UNAVAILABLE",
+ "brakeBoost": "UNAVAILABLE",
+ "auxBrakes": "UNAVAILABLE"
},
- "heading": 359.4,
- "id": "12A7A951",
- "msgCnt": 25,
- "secMark": 2800,
+ "heading": 335.6,
+ "id": "13073098",
+ "msgCnt": 123,
+ "secMark": 38600,
"size": {
- "width": 208,
- "length": 586
+ "width": 0,
+ "length": 0
},
- "transmission": "UNAVAILABLE",
- "speed": 0
+ "speed": 0.0,
+ "transmission": "UNAVAILABLE"
}
}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json b/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json
deleted file mode 100644
index a3518b5..0000000
--- a/jpo-deduplicator/src/test/resources/json/processed_bsm/sample.processed_bsm-with-position.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [
- -100.0342901,
- 20.5671913
- ]
- },
- "properties": {
- "schemaVersion": 1,
- "messageType": "BSM",
- "odeReceivedAt": "2024-08-12T12:32:14.311Z",
- "originIp": "172.19.0.1",
- "validationMessages": [],
- "timeStamp": "2024-08-12T12:32:14.3034091Z",
- "accelSet": {
- "accelLat": 2001,
- "accelLong": 0,
- "accelVert": -127,
- "accelYaw": 0
- },
- "accuracy": {
- "semiMajor": 5,
- "semiMinor": 2,
- "orientation": 0
- },
- "brakes": {
- "wheelBrakes": {
- "leftFront": false,
- "rightFront": false,
- "unavailable": true,
- "leftRear": false,
- "rightRear": false
- },
- "traction": "unavailable",
- "abs": "unavailable",
- "scs": "unavailable",
- "brakeBoost": "unavailable",
- "auxBrakes": "unavailable"
- },
- "heading": 359.4,
- "id": "12A7A952",
- "msgCnt": 25,
- "secMark": 2800,
- "size": {
- "width": 208,
- "length": 586
- },
- "transmission": "UNAVAILABLE",
- "speed": 0
- }
-}
\ No newline at end of file
diff --git a/jpo-deduplicator/src/test/resources/json/processed_spat/sample.processed_spat-reference.json b/jpo-deduplicator/src/test/resources/json/processed_spat/sample.processed_spat-reference.json
new file mode 100644
index 0000000..e251473
--- /dev/null
+++ b/jpo-deduplicator/src/test/resources/json/processed_spat/sample.processed_spat-reference.json
@@ -0,0 +1,140 @@
+{
+ "schemaVersion": 2,
+ "messageType": "SPAT",
+ "odeReceivedAt": "2025-08-01T08:29:23.375Z",
+ "originIp": "172.18.0.1",
+ "asn1": "0381004003807C00134700081132000000E437070010434257925790010232119A11CE800C10D095E495E400808684AF24AF20050434257925790030232119A11CE801C10D095E495E401008684AF24AF200",
+ "validationMessages": [
+ {
+ "message": "CTI-4501 conformance issue: The SPAT 'timeStamp' DE_MinuteOfTheYear is missing"
+ },
+ {
+ "message": "CTI-4501 conformance issue: The intersections 'id.region' DE_RoadRegulatorID is missing"
+ },
+ {
+ "message": "CTI-4501 conformance issue: The state-time-speed 'timing.nextTime' DE_TimeMark is missing"
+ },
+ {
+ "message": "CTI-4501 conformance issue: The state-time-speed 'timing.startTime' DE_TimeMark is missing"
+ }
+ ],
+ "intersectionId": 8804,
+ "cti4501Conformant": false,
+ "revision": 0,
+ "status": {
+ "manualControlIsEnabled": false,
+ "stopTimeIsActivated": false,
+ "failureFlash": false,
+ "preemptIsActive": false,
+ "signalPriorityIsActive": false,
+ "fixedTimeOperation": false,
+ "trafficDependentOperation": false,
+ "standbyOperation": false,
+ "failureMode": false,
+ "off": false,
+ "recentMAPmessageUpdate": false,
+ "recentChangeInMAPassignedLanesIDsUsed": false,
+ "noValidMAPisAvailableAtThisTime": false,
+ "noValidSPATisAvailableAtThisTime": false
+ },
+ "utcTimeStamp": "2025-08-01T08:29:58.423Z",
+ "enabledLanes": [],
+ "states": [
+ {
+ "signalGroup": 1,
+ "stateTimeSpeed": [
+ {
+ "eventState": "STOP_AND_REMAIN",
+ "timing": {
+ "minEndTime": "2025-08-01T08:31:58.6Z",
+ "maxEndTime": "2025-08-01T08:31:58.6Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 2,
+ "stateTimeSpeed": [
+ {
+ "eventState": "PROTECTED_MOVEMENT_ALLOWED",
+ "timing": {
+ "minEndTime": "2025-08-01T08:30:02.4Z",
+ "maxEndTime": "2025-08-01T08:30:23.4Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 3,
+ "stateTimeSpeed": [
+ {
+ "eventState": "STOP_AND_REMAIN",
+ "timing": {
+ "minEndTime": "2025-08-01T08:31:58.6Z",
+ "maxEndTime": "2025-08-01T08:31:58.6Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 4,
+ "stateTimeSpeed": [
+ {
+ "eventState": "STOP_AND_REMAIN",
+ "timing": {
+ "minEndTime": "2025-08-01T08:31:58.6Z",
+ "maxEndTime": "2025-08-01T08:31:58.6Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 5,
+ "stateTimeSpeed": [
+ {
+ "eventState": "STOP_AND_REMAIN",
+ "timing": {
+ "minEndTime": "2025-08-01T08:31:58.6Z",
+ "maxEndTime": "2025-08-01T08:31:58.6Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 6,
+ "stateTimeSpeed": [
+ {
+ "eventState": "PROTECTED_MOVEMENT_ALLOWED",
+ "timing": {
+ "minEndTime": "2025-08-01T08:30:02.4Z",
+ "maxEndTime": "2025-08-01T08:30:23.4Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 7,
+ "stateTimeSpeed": [
+ {
+ "eventState": "STOP_AND_REMAIN",
+ "timing": {
+ "minEndTime": "2025-08-01T08:31:58.6Z",
+ "maxEndTime": "2025-08-01T08:31:58.6Z"
+ }
+ }
+ ]
+ },
+ {
+ "signalGroup": 8,
+ "stateTimeSpeed": [
+ {
+ "eventState": "STOP_AND_REMAIN",
+ "timing": {
+ "minEndTime": "2025-08-01T08:31:58.6Z",
+ "maxEndTime": "2025-08-01T08:31:58.6Z"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
From c3747ce681eb719657395f3aea917988f3731f46 Mon Sep 17 00:00:00 2001
From: Drew Johnston
Date: Fri, 1 Aug 2025 03:59:10 -0600
Subject: [PATCH 07/24] Remove all Pair model and Serdes since they are unused
---
.../deduplicator/models/JsonPair.java | 21 --------
.../deduplicator/models/OdeBsmPair.java | 20 --------
.../deduplicator/models/OdeMapPair.java | 20 --------
.../deduplicator/models/Pair.java | 19 -------
.../deduplicator/models/ProcessedMapPair.java | 21 --------
.../models/ProcessedMapWktPair.java | 20 --------
.../serialization/PairSerdes.java | 51 -------------------
7 files changed, 172 deletions(-)
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/JsonPair.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/Pair.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapPair.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapWktPair.java
delete mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/JsonPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/JsonPair.java
deleted file mode 100644
index d0f4377..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/JsonPair.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.models;
-
-import com.fasterxml.jackson.databind.JsonNode;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@NoArgsConstructor
-@Setter
-@Getter
-public class JsonPair {
-
- public JsonNode message;
- public boolean shouldSend;
-
- public JsonPair(JsonNode message, boolean shouldSend){
- this.message = message;
- this.shouldSend = shouldSend;
- }
-}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java
deleted file mode 100644
index 2516f63..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeBsmPair.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.models;
-
-// import lombok.Getter;
-// import lombok.NoArgsConstructor;
-// import lombok.Setter;
-// import us.dot.its.jpo.ode.model.OdeBsmData;
-
-// @NoArgsConstructor
-// @Setter
-// @Getter
-// public class OdeBsmPair {
-
-// public OdeBsmData message;
-// public boolean shouldSend;
-
-// public OdeBsmPair(OdeBsmData message, boolean shouldSend){
-// this.message = message;
-// this.shouldSend = shouldSend;
-// }
-// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java
deleted file mode 100644
index 43a78dd..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/OdeMapPair.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.models;
-
-// import lombok.Getter;
-// import lombok.NoArgsConstructor;
-// import lombok.Setter;
-// import us.dot.its.jpo.ode.model.OdeMapData;
-
-// @NoArgsConstructor
-// @Setter
-// @Getter
-// public class OdeMapPair {
-
-// public OdeMapData message;
-// public boolean shouldSend;
-
-// public OdeMapPair(OdeMapData message, boolean shouldSend){
-// this.message = message;
-// this.shouldSend = shouldSend;
-// }
-// }
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/Pair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/Pair.java
deleted file mode 100644
index fd0ee44..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/Pair.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.models;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@NoArgsConstructor
-@Setter
-@Getter
-public class Pair {
-
- public T message;
- public boolean shouldSend;
-
- public Pair(T message, boolean shouldSend){
- this.message = message;
- this.shouldSend = shouldSend;
- }
-}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapPair.java
deleted file mode 100644
index b1400c5..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapPair.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.models;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-
-@NoArgsConstructor
-@Setter
-@Getter
-public class ProcessedMapPair {
-
- public ProcessedMap message;
- public boolean shouldSend;
-
- public ProcessedMapPair(ProcessedMap message, boolean shouldSend){
- this.message = message;
- this.shouldSend = shouldSend;
- }
-}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapWktPair.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapWktPair.java
deleted file mode 100644
index d6acaca..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/models/ProcessedMapWktPair.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.models;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-
-@NoArgsConstructor
-@Setter
-@Getter
-public class ProcessedMapWktPair {
-
- public ProcessedMap message;
- public boolean shouldSend;
-
- public ProcessedMapWktPair(ProcessedMap message, boolean shouldSend){
- this.message = message;
- this.shouldSend = shouldSend;
- }
-}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java
deleted file mode 100644
index 2e8f10b..0000000
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/serialization/PairSerdes.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package us.dot.its.jpo.deduplicator.deduplicator.serialization;
-
-import org.apache.kafka.common.serialization.Serde;
-import org.apache.kafka.common.serialization.Serdes;
-
-import us.dot.its.jpo.deduplicator.deduplicator.models.ProcessedMapPair;
-import us.dot.its.jpo.deduplicator.deduplicator.models.ProcessedMapWktPair;
-// import us.dot.its.jpo.deduplicator.deduplicator.models.OdeMapPair;
-// import us.dot.its.jpo.deduplicator.deduplicator.models.OdeBsmPair;
-import us.dot.its.jpo.deduplicator.deduplicator.models.JsonPair;
-import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.DeserializedRawMap;
-import us.dot.its.jpo.geojsonconverter.serialization.deserializers.JsonDeserializer;
-import us.dot.its.jpo.geojsonconverter.serialization.serializers.JsonSerializer;
-
-public class PairSerdes {
- public static Serde ProcessedMapPair() {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(ProcessedMapPair.class));
- }
-
- public static Serde ProcessedMapWktPair() {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(ProcessedMapWktPair.class));
- }
-
- // public static Serde OdeMapPair() {
- // return Serdes.serdeFrom(
- // new JsonSerializer(),
- // new JsonDeserializer<>(OdeMapPair.class));
- // }
-
- // public static Serde OdeBsmPair() {
- // return Serdes.serdeFrom(
- // new JsonSerializer(),
- // new JsonDeserializer<>(OdeBsmPair.class));
- // }
-
- public static Serde RawMap() {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(DeserializedRawMap.class));
- }
-
- public static Serde JsonPair() {
- return Serdes.serdeFrom(
- new JsonSerializer(),
- new JsonDeserializer<>(JsonPair.class));
- }
-}
From ce73cbc8d23a5f97135dbe9cfd940c5908a5424f Mon Sep 17 00:00:00 2001
From: Drew Johnston
Date: Fri, 1 Aug 2025 04:08:24 -0600
Subject: [PATCH 08/24] Update ProcessedMap and WKT dedup
---
.../DeduplicatorServiceController.java | 34 +--
.../ProcessedMapDeduplicatorTopology.java | 193 +++++++------
.../ProcessedMapWktDeduplicatorTopology.java | 197 +++++++------
.../ProcessedMapDeduplicatorTopologyTest.java | 259 +++++++++---------
...ocessedMapWktDeduplicatorTopologyTest.java | 254 +++++++++--------
5 files changed, 453 insertions(+), 484 deletions(-)
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
index 0b366e3..dd811ce 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/DeduplicatorServiceController.java
@@ -17,8 +17,8 @@
import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.TimDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedBsmDeduplicatorTopology;
-// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
-// import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedSpatDeduplicatorTopology;
@Controller
@@ -38,25 +38,17 @@ public DeduplicatorServiceController(final DeduplicatorProperties props,
try {
- // if(props.isEnableProcessedMapDeduplication()){
- // logger.info("Starting Processed Map Deduplicator");
- // ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new
- // ProcessedMapDeduplicatorTopology(
- // props,
- // props.createStreamProperties("ProcessedMapDeduplicator")
- // );
- // processedMapDeduplicatorTopology.start();
- // }
-
- // if(props.isEnableProcessedMapWktDeduplication()){
- // logger.info("Starting Processed Map WKT Deduplicator");
- // ProcessedMapWktDeduplicatorTopology processedMapWktDeduplicatorTopology = new
- // ProcessedMapWktDeduplicatorTopology(
- // props,
- // props.createStreamProperties("ProcessedMapWKTdeduplicator")
- // );
- // processedMapWktDeduplicatorTopology.start();
- // }
+ if (props.isEnableProcessedMapDeduplication()) {
+ logger.info("Starting Processed Map Deduplicator");
+ ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapDeduplicatorTopology(props);
+ processedMapDeduplicatorTopology.start();
+ }
+
+ if (props.isEnableProcessedMapWktDeduplication()) {
+ logger.info("Starting Processed Map WKT Deduplicator");
+ ProcessedMapWktDeduplicatorTopology processedMapWktDeduplicatorTopology = new ProcessedMapWktDeduplicatorTopology(props);
+ processedMapWktDeduplicatorTopology.start();
+ }
if (props.isEnableOdeMapDeduplication()) {
logger.info("Starting Map Deduplicator");
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java
index 037f1bd..8b9b9ce 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapDeduplicatorTopology.java
@@ -1,100 +1,93 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KafkaStreams;
-// import org.apache.kafka.streams.StreamsBuilder;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.KafkaStreams.StateListener;
-// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapProcessorSupplier;
-// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import org.apache.kafka.streams.kstream.*;
-// import org.apache.kafka.streams.state.Stores;
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-
-// import java.util.Properties;
-
-// public class ProcessedMapDeduplicatorTopology {
-
-// private static final Logger logger =
-// LoggerFactory.getLogger(MapDeduplicatorTopology.class);
-
-// Topology topology;
-// KafkaStreams streams;
-// Properties streamsProperties;
-// ObjectMapper objectMapper;
-// DeduplicatorProperties props;
-
-// public ProcessedMapDeduplicatorTopology(DeduplicatorProperties props,
-// Properties streamsProperties){
-// this.props = props;
-// this.streamsProperties = streamsProperties;
-// this.objectMapper = DateJsonMapper.getInstance();
-// }
-
-// public void start() {
-// if (streams != null && streams.state().isRunningOrRebalancing()) {
-// throw new IllegalStateException("Start called while streams is already
-// running.");
-// }
-// Topology topology = buildTopology();
-// streams = new KafkaStreams(topology, streamsProperties);
-// if (exceptionHandler != null)
-// streams.setUncaughtExceptionHandler(exceptionHandler);
-// if (stateListener != null) streams.setStateListener(stateListener);
-// logger.info("Starting Processed Map Deduplicator Topology");
-// streams.start();
-// }
-
-// public Topology buildTopology() {
-// StreamsBuilder builder = new StreamsBuilder();
-
-// KStream> inputStream =
-// builder.stream(props.getKafkaTopicProcessedMap(),
-// Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
-
-// builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapName()),
-// Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
-
-// KStream> deduplicatedStream =
-// inputStream.process(new ProcessedMapProcessorSupplier(props),
-// props.getKafkaStateStoreProcessedMapName());
-
-// deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMap(),
-// Produced.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
-
-// return builder.build();
-
-// }
-
-// public void stop() {
-// logger.info("Stopping Processed Map deduplicator Socket Broadcast
-// Topology.");
-// if (streams != null) {
-// streams.close();
-// streams.cleanUp();
-// streams = null;
-// }
-// logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
-// }
-
-// StateListener stateListener;
-// public void registerStateListener(StateListener stateListener) {
-// this.stateListener = stateListener;
-// }
-
-// StreamsUncaughtExceptionHandler exceptionHandler;
-// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
-// exceptionHandler) {
-// this.exceptionHandler = exceptionHandler;
-// }
-
-// }
+package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KafkaStreams;
+import org.apache.kafka.streams.StreamsBuilder;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.KafkaStreams.StateListener;
+import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapProcessorSupplier;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+import org.apache.kafka.streams.kstream.*;
+import org.apache.kafka.streams.state.Stores;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ProcessedMapDeduplicatorTopology {
+
+ private static final Logger logger = LoggerFactory.getLogger(MapDeduplicatorTopology.class);
+
+ Topology topology;
+ KafkaStreams streams;
+ ObjectMapper objectMapper;
+ DeduplicatorProperties props;
+
+ public ProcessedMapDeduplicatorTopology(DeduplicatorProperties props) {
+ this.props = props;
+ this.objectMapper = DateJsonMapper.getInstance();
+ }
+
+ public void start() {
+ if (streams != null && streams.state().isRunningOrRebalancing()) {
+ throw new IllegalStateException("Start called while streams is already running.");
+ }
+ Topology topology = buildTopology();
+ streams = new KafkaStreams(topology, props.createStreamProperties("ProcessedMapDeduplicator"));
+ if (exceptionHandler != null)
+ streams.setUncaughtExceptionHandler(exceptionHandler);
+ if (stateListener != null)
+ streams.setStateListener(stateListener);
+ logger.info("Starting Processed Map Deduplicator Topology");
+ streams.start();
+ }
+
+ public Topology buildTopology() {
+ StreamsBuilder builder = new StreamsBuilder();
+
+ KStream> inputStream = builder.stream(props.getKafkaTopicProcessedMap(),
+ Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
+
+ builder.addStateStore(
+ Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapName()),
+ Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
+
+ KStream> deduplicatedStream = inputStream.process(
+ new ProcessedMapProcessorSupplier(props),
+ props.getKafkaStateStoreProcessedMapName());
+
+ deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMap(),
+ Produced.with(Serdes.String(), JsonSerdes.ProcessedMapGeoJson()));
+
+ return builder.build();
+
+ }
+
+ public void stop() {
+ logger.info("Stopping Processed Map deduplicator Socket Broadcast Topology.");
+ if (streams != null) {
+ streams.close();
+ streams.cleanUp();
+ streams = null;
+ }
+ logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
+ }
+
+ StateListener stateListener;
+
+ public void registerStateListener(StateListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ StreamsUncaughtExceptionHandler exceptionHandler;
+
+ public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+
+}
diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java
index 4c4a633..930c855 100644
--- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java
+++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/topologies/ProcessedMapWktDeduplicatorTopology.java
@@ -1,102 +1,95 @@
-// package us.dot.its.jpo.deduplicator.deduplicator.topologies;
-
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KafkaStreams;
-// import org.apache.kafka.streams.StreamsBuilder;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.KafkaStreams.StateListener;
-// import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
-
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapWktProcessorSupplier;
-// import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-
-// import org.apache.kafka.streams.kstream.*;
-// import org.apache.kafka.streams.state.Stores;
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-
-// import java.util.Properties;
-
-// public class ProcessedMapWktDeduplicatorTopology {
-
-// private static final Logger logger =
-// LoggerFactory.getLogger(MapDeduplicatorTopology.class);
-
-// Topology topology;
-// KafkaStreams streams;
-// String inputTopic;
-// String outputTopic;
-// Properties streamsProperties;
-// ObjectMapper objectMapper;
-// DeduplicatorProperties props;
-
-// public ProcessedMapWktDeduplicatorTopology(DeduplicatorProperties props,
-// Properties streamsProperties){
-// this.props = props;
-// this.streamsProperties = streamsProperties;
-// this.objectMapper = DateJsonMapper.getInstance();
-// }
-
-// public void start() {
-// if (streams != null && streams.state().isRunningOrRebalancing()) {
-// throw new IllegalStateException("Start called while streams is already
-// running.");
-// }
-// Topology topology = buildTopology();
-// streams = new KafkaStreams(topology, streamsProperties);
-// if (exceptionHandler != null)
-// streams.setUncaughtExceptionHandler(exceptionHandler);
-// if (stateListener != null) streams.setStateListener(stateListener);
-// logger.info("Starting Processed Map WKT Deduplicator Topology");
-// streams.start();
-// }
-
-// public Topology buildTopology() {
-// StreamsBuilder builder = new StreamsBuilder();
-
-// KStream> inputStream =
-// builder.stream(props.getKafkaTopicProcessedMapWKT(),
-// Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
-
-// builder.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapWKTName()),
-// Serdes.String(), JsonSerdes.ProcessedMapWKT()));
-
-// KStream> deduplicatedStream =
-// inputStream.process(new ProcessedMapWktProcessorSupplier(props),
-// props.getKafkaStateStoreProcessedMapWKTName());
-
-// deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMapWKT(),
-// Produced.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
-
-// return builder.build();
-
-// }
-
-// public void stop() {
-// logger.info("Stopping Processed Map deduplicator Socket Broadcast
-// Topology.");
-// if (streams != null) {
-// streams.close();
-// streams.cleanUp();
-// streams = null;
-// }
-// logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
-// }
-
-// StateListener stateListener;
-// public void registerStateListener(StateListener stateListener) {
-// this.stateListener = stateListener;
-// }
-
-// StreamsUncaughtExceptionHandler exceptionHandler;
-// public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler
-// exceptionHandler) {
-// this.exceptionHandler = exceptionHandler;
-// }
-
-// }
+package us.dot.its.jpo.deduplicator.deduplicator.topologies;
+
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KafkaStreams;
+import org.apache.kafka.streams.StreamsBuilder;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.KafkaStreams.StateListener;
+import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler;
+
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.ProcessedMapWktProcessorSupplier;
+import us.dot.its.jpo.geojsonconverter.DateJsonMapper;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+
+import org.apache.kafka.streams.kstream.*;
+import org.apache.kafka.streams.state.Stores;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ProcessedMapWktDeduplicatorTopology {
+
+ private static final Logger logger = LoggerFactory.getLogger(MapDeduplicatorTopology.class);
+
+ Topology topology;
+ KafkaStreams streams;
+ String inputTopic;
+ String outputTopic;
+ ObjectMapper objectMapper;
+ DeduplicatorProperties props;
+
+ public ProcessedMapWktDeduplicatorTopology(DeduplicatorProperties props) {
+ this.props = props;
+ this.objectMapper = DateJsonMapper.getInstance();
+ }
+
+ public void start() {
+ if (streams != null && streams.state().isRunningOrRebalancing()) {
+ throw new IllegalStateException("Start called while streams is already running.");
+ }
+ Topology topology = buildTopology();
+ streams = new KafkaStreams(topology, props.createStreamProperties("ProcessedMapWKTdeduplicator"));
+ if (exceptionHandler != null)
+ streams.setUncaughtExceptionHandler(exceptionHandler);
+ if (stateListener != null)
+ streams.setStateListener(stateListener);
+ logger.info("Starting Processed Map WKT Deduplicator Topology");
+ streams.start();
+ }
+
+ public Topology buildTopology() {
+ StreamsBuilder builder = new StreamsBuilder();
+
+ KStream> inputStream = builder.stream(props.getKafkaTopicProcessedMapWKT(),
+ Consumed.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
+
+ builder.addStateStore(Stores.keyValueStoreBuilder(
+ Stores.persistentKeyValueStore(props.getKafkaStateStoreProcessedMapWKTName()),
+ Serdes.String(), JsonSerdes.ProcessedMapWKT()));
+
+ KStream> deduplicatedStream = inputStream.process(
+ new ProcessedMapWktProcessorSupplier(props),
+ props.getKafkaStateStoreProcessedMapWKTName());
+
+ deduplicatedStream.to(props.getKafkaTopicDeduplicatedProcessedMapWKT(),
+ Produced.with(Serdes.String(), JsonSerdes.ProcessedMapWKT()));
+
+ return builder.build();
+
+ }
+
+ public void stop() {
+ logger.info("Stopping Processed Map deduplicator Socket Broadcast Topology.");
+ if (streams != null) {
+ streams.close();
+ streams.cleanUp();
+ streams = null;
+ }
+ logger.info("Stopped Processed Map deduplicator Socket Broadcast Topology.");
+ }
+
+ StateListener stateListener;
+
+ public void registerStateListener(StateListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ StreamsUncaughtExceptionHandler exceptionHandler;
+
+ public void registerUncaughtExceptionHandler(StreamsUncaughtExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+
+}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java
index 4e4f316..8030d50 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapDeduplicatorTopologyTest.java
@@ -1,139 +1,134 @@
-// package us.dot.its.jpo.deduplicator.deduplicator;
+package us.dot.its.jpo.deduplicator.deduplicator;
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KeyValue;
-// import org.apache.kafka.streams.TestInputTopic;
-// import org.apache.kafka.streams.TestOutputTopic;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.TopologyTestDriver;
-// import org.junit.Before;
-// import org.junit.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KeyValue;
+import org.apache.kafka.streams.TestInputTopic;
+import org.apache.kafka.streams.TestOutputTopic;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.TopologyTestDriver;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
-// import com.fasterxml.jackson.core.JsonProcessingException;
-// import com.fasterxml.jackson.core.type.TypeReference;
-// import com.fasterxml.jackson.databind.JsonMappingException;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import static org.junit.jupiter.api.Assertions.assertEquals;
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapDeduplicatorTopology;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.LineString;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+import static org.junit.jupiter.api.Assertions.assertEquals;
-// import java.util.List;
-
-// import java.io.IOException;
-// import java.nio.file.Files;
-// import java.nio.file.Paths;
-
-// public class ProcessedMapDeduplicatorTopologyTest {
-
-// String inputTopic = "topic.ProcessedMap";
-// String outputTopic = "topic.DeduplicatedProcessedMap";
-
-// TypeReference> typeReference = new
-// TypeReference<>(){};
-// ObjectMapper objectMapper = new ObjectMapper();
-
-// // Reference MAP
-// String inputProcessedMap1 = "";
-
-// // Duplicate of Number 1
-// String inputProcessedMap2 = "";
-
-// // A different Message entirely
-// String inputProcessedMap3 = "";
-
-// // Message 1 but 1 hour later
-// String inputProcessedMap4 = "";
-
-// String key =
-// "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
-
-// @Autowired
-// DeduplicatorProperties props;
-
-// @Before
-// public void setup() throws IOException {
-// // Load test files from resources
-
-// // Reference MAP
-// inputProcessedMap1 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
-
-// // Duplicate of Number 1
-// inputProcessedMap2 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
-
-// // A different Message entirely
-// inputProcessedMap3 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-different.json")));
-
-// // Message 1 but 1 hour later
-// inputProcessedMap4 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json")));
-// }
-
-// @Test
-// public void testTopology() {
-
-// props = new DeduplicatorProperties();
-// props.setKafkaTopicProcessedMap(inputTopic);
-// props.setKafkaTopicDeduplicatedProcessedMap(outputTopic);
-
-// ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new
-// ProcessedMapDeduplicatorTopology(props, null);
-
-// Topology topology = processedMapDeduplicatorTopology.buildTopology();
-// objectMapper.registerModule(new JavaTimeModule());
-
-// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-// TestInputTopic inputProcessedMapData =
-// driver.createInputTopic(
-// inputTopic,
-// Serdes.String().serializer(),
-// Serdes.String().serializer());
-
-// TestOutputTopic> outputProcessedMapData =
-// driver.createOutputTopic(
-// outputTopic,
-// Serdes.String().deserializer(),
-// JsonSerdes.ProcessedMapGeoJson().deserializer());
-
-// inputProcessedMapData.pipeInput(key, inputProcessedMap1);
-// inputProcessedMapData.pipeInput(key, inputProcessedMap2);
-// inputProcessedMapData.pipeInput(key, inputProcessedMap3);
-// inputProcessedMapData.pipeInput(key, inputProcessedMap4);
-
-// List>> mapDeduplicatorResults =
-// outputProcessedMapData.readKeyValuesToList();
-
-// // validate that only 3 messages make it through
-// assertEquals(3, mapDeduplicatorResults.size());
+import java.util.List;
-// ProcessedMap map1 = objectMapper.readValue(inputProcessedMap1,
-// typeReference);
-// ProcessedMap map3 = objectMapper.readValue(inputProcessedMap3,
-// typeReference);
-// ProcessedMap map4 = objectMapper.readValue(inputProcessedMap4,
-// typeReference);
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
-// assertEquals(map1.getProperties().getOdeReceivedAt(),
-// mapDeduplicatorResults.get(0).value.getProperties().getOdeReceivedAt());
-// assertEquals(map3.getProperties().getOdeReceivedAt(),
-// mapDeduplicatorResults.get(1).value.getProperties().getOdeReceivedAt());
-// assertEquals(map4.getProperties().getOdeReceivedAt(),
-// mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt());
+public class ProcessedMapDeduplicatorTopologyTest {
+
+ String inputTopic = "topic.ProcessedMap";
+ String outputTopic = "topic.DeduplicatedProcessedMap";
+
+ TypeReference> typeReference = new TypeReference<>() {
+ };
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ // Reference MAP
+ String inputProcessedMap1 = "";
+
+ // Duplicate of Number 1
+ String inputProcessedMap2 = "";
+
+ // A different Message entirely
+ String inputProcessedMap3 = "";
+
+ // Message 1 but 1 hour later
+ String inputProcessedMap4 = "";
+
+ String key = "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
+
+ @Autowired
+ DeduplicatorProperties props;
+
+ @Before
+ public void setup() throws IOException {
+ // Load test files from resources
+
+ // Reference MAP
+ inputProcessedMap1 = new String(Files
+ .readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
+
+ // Duplicate of Number 1
+ inputProcessedMap2 = new String(Files
+ .readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json")));
+
+ // A different Message entirely
+ inputProcessedMap3 = new String(Files
+ .readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-different.json")));
+
+ // Message 1 but 1 hour later
+ inputProcessedMap4 = new String(Files.readAllBytes(
+ Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json")));
+ }
+
+ @Test
+ public void testTopology() {
+
+ props = new DeduplicatorProperties();
+ props.setKafkaTopicProcessedMap(inputTopic);
+ props.setKafkaTopicDeduplicatedProcessedMap(outputTopic);
+
+ ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapDeduplicatorTopology(props);
+
+ Topology topology = processedMapDeduplicatorTopology.buildTopology();
+ objectMapper.registerModule(new JavaTimeModule());
+
+ try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
+
+ TestInputTopic inputProcessedMapData = driver.createInputTopic(
+ inputTopic,
+ Serdes.String().serializer(),
+ Serdes.String().serializer());
+
+ TestOutputTopic> outputProcessedMapData = driver.createOutputTopic(
+ outputTopic,
+ Serdes.String().deserializer(),
+ JsonSerdes.ProcessedMapGeoJson().deserializer());
+
+ inputProcessedMapData.pipeInput(key, inputProcessedMap1);
+ inputProcessedMapData.pipeInput(key, inputProcessedMap2);
+ inputProcessedMapData.pipeInput(key, inputProcessedMap3);
+ inputProcessedMapData.pipeInput(key, inputProcessedMap4);
+
+ List>> mapDeduplicatorResults = outputProcessedMapData
+ .readKeyValuesToList();
-// } catch (JsonMappingException e) {
-// e.printStackTrace();
-// } catch (JsonProcessingException e) {
-// e.printStackTrace();
-// }
-// }
-// }
+ // validate that only 3 messages make it through
+ assertEquals(3, mapDeduplicatorResults.size());
+
+ ProcessedMap map1 = objectMapper.readValue(inputProcessedMap1,
+ typeReference);
+ ProcessedMap map3 = objectMapper.readValue(inputProcessedMap3,
+ typeReference);
+ ProcessedMap map4 = objectMapper.readValue(inputProcessedMap4,
+ typeReference);
+
+ assertEquals(map1.getProperties().getOdeReceivedAt(),
+ mapDeduplicatorResults.get(0).value.getProperties().getOdeReceivedAt());
+ assertEquals(map3.getProperties().getOdeReceivedAt(),
+ mapDeduplicatorResults.get(1).value.getProperties().getOdeReceivedAt());
+ assertEquals(map4.getProperties().getOdeReceivedAt(),
+ mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt());
+
+ } catch (JsonMappingException e) {
+ e.printStackTrace();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java
index a464264..8c38ba0 100644
--- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java
+++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/deduplicator/ProcessedMapWktDeduplicatorTopologyTest.java
@@ -1,137 +1,133 @@
-// package us.dot.its.jpo.deduplicator.deduplicator;
+package us.dot.its.jpo.deduplicator.deduplicator;
-// import org.apache.kafka.common.serialization.Serdes;
-// import org.apache.kafka.streams.KeyValue;
-// import org.apache.kafka.streams.TestInputTopic;
-// import org.apache.kafka.streams.TestOutputTopic;
-// import org.apache.kafka.streams.Topology;
-// import org.apache.kafka.streams.TopologyTestDriver;
-// import org.junit.Before;
-// import org.junit.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.kafka.common.serialization.Serdes;
+import org.apache.kafka.streams.KeyValue;
+import org.apache.kafka.streams.TestInputTopic;
+import org.apache.kafka.streams.TestOutputTopic;
+import org.apache.kafka.streams.Topology;
+import org.apache.kafka.streams.TopologyTestDriver;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
-// import com.fasterxml.jackson.core.JsonProcessingException;
-// import com.fasterxml.jackson.core.type.TypeReference;
-// import com.fasterxml.jackson.databind.JsonMappingException;
-// import com.fasterxml.jackson.databind.ObjectMapper;
-// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-// import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
-// import
-// us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
-// import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
-// import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
-// import static org.junit.jupiter.api.Assertions.assertEquals;
+import us.dot.its.jpo.deduplicator.DeduplicatorProperties;
+import us.dot.its.jpo.deduplicator.deduplicator.topologies.ProcessedMapWktDeduplicatorTopology;
+import us.dot.its.jpo.geojsonconverter.pojos.geojson.map.ProcessedMap;
+import us.dot.its.jpo.geojsonconverter.serialization.JsonSerdes;
+import static org.junit.jupiter.api.Assertions.assertEquals;
-// import java.io.IOException;
-// import java.nio.file.Files;
-// import java.nio.file.Paths;
-
-// import java.util.List;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
-// public class ProcessedMapWktDeduplicatorTopologyTest {
-
-// String inputTopic = "topic.ProcessedMapWKT";
-// String outputTopic = "topic.DeduplicatedProcessedMapWKT";
-
-// TypeReference> typeReference = new TypeReference<>(){};
-// ObjectMapper objectMapper = new ObjectMapper();
-
-// // Reference MAP
-// String inputProcessedMapWkt1 = "";
-
-// // Duplicate of Number 1
-// String inputProcessedMapWkt2 = "";
-
-// // A different Message entirely
-// String inputProcessedMapWkt3 = "";
-
-// // Message 1 but 1 hour later
-// String inputProcessedMapWkt4 = "";
-
-// String key =
-// "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}";
-
-// @Autowired
-// DeduplicatorProperties props;
-
-// @Before
-// public void setup() throws IOException {
-// // Load test files from resources
-
-// // Reference MAP
-// inputProcessedMapWkt1 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json")));
-
-// // Duplicate of Number 1
-// inputProcessedMapWkt2 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json")));
-
-// // A different Message entirely
-// inputProcessedMapWkt3 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json")));
-
-// // Message 1 but 1 hour later
-// inputProcessedMapWkt4 = new
-// String(Files.readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json")));
-// }
-
-// @Test
-// public void testTopology() {
-
-// props = new DeduplicatorProperties();
-// props.setKafkaTopicProcessedMapWKT(inputTopic);
-// props.setKafkaTopicDeduplicatedProcessedMapWKT(outputTopic);
-
-// ProcessedMapWktDeduplicatorTopology processedMapDeduplicatorTopology = new
-// ProcessedMapWktDeduplicatorTopology(props, null);
-
-// Topology topology = processedMapDeduplicatorTopology.buildTopology();
-// objectMapper.registerModule(new JavaTimeModule());
-
-// try (TopologyTestDriver driver = new TopologyTestDriver(topology)) {
-
-// TestInputTopic inputProcessedMapData =
-// driver.createInputTopic(
-// inputTopic,
-// Serdes.String().serializer(),
-// Serdes.String().serializer());
-
-// TestOutputTopic> outputProcessedMapData =
-// driver.createOutputTopic(
-// outputTopic,
-// Serdes.String().deserializer(),
-// JsonSerdes.ProcessedMapWKT().deserializer());
-
-// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt1);
-// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt2);
-// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt3);
-// inputProcessedMapData.pipeInput(key, inputProcessedMapWkt4);
-
-// List>> mapDeduplicatorResults =
-// outputProcessedMapData.readKeyValuesToList();
-
-// // validate that only 3 messages make it through
-// assertEquals(3, mapDeduplicatorResults.size());
+import java.util.List;
-// ProcessedMap map1 = objectMapper.readValue(inputProcessedMapWkt1,
-// typeReference);
-// ProcessedMap map2 = objectMapper.readValue(inputProcessedMapWkt2,
-// typeReference);
-// ProcessedMap