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 map4 = objectMapper.readValue(inputProcessedMapWkt4, -// typeReference); +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); + + 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(); -// 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()); + // validate that only 3 messages make it through + assertEquals(3, mapDeduplicatorResults.size()); -// } catch (JsonMappingException e) { -// e.printStackTrace(); -// } catch (JsonProcessingException e) { -// e.printStackTrace(); -// } -// } -// } + 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(); + } + } +} From c998ad5f51953181dd875311eb39de60f352cf82 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 1 Aug 2025 04:20:51 -0600 Subject: [PATCH 09/24] Add additional serdes tests and fix issue for GeoUtils test being unseen --- .../ProcessedMapDeduplicatorTopologyTest.java | 36 +++++++++++++++---- ...ocessedMapWktDeduplicatorTopologyTest.java | 36 +++++++++++++++---- .../jpo/deduplicator/utils/GeoUtilsTest.java | 2 +- 3 files changed, 59 insertions(+), 15 deletions(-) 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 8030d50..5951274 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,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; @@ -14,14 +19,13 @@ 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.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 static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; @@ -33,10 +37,9 @@ public class ProcessedMapDeduplicatorTopologyTest { String inputTopic = "topic.ProcessedMap"; String outputTopic = "topic.DeduplicatedProcessedMap"; - + ObjectMapper objectMapper; TypeReference> typeReference = new TypeReference<>() { }; - ObjectMapper objectMapper = new ObjectMapper(); // Reference MAP String inputProcessedMap1 = ""; @@ -57,11 +60,15 @@ public class ProcessedMapDeduplicatorTopologyTest { @Before public void setup() throws IOException { - // Load test files from resources + objectMapper = DateJsonMapper.getInstance(); + // Load test files from resources // Reference MAP - inputProcessedMap1 = new String(Files + String processedMapReference = new String(Files .readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json"))); + ProcessedMap processedMapReferenceData = objectMapper.readValue(processedMapReference, typeReference); + + inputProcessedMap1 = processedMapReferenceData.toString(); // Duplicate of Number 1 inputProcessedMap2 = new String(Files @@ -76,6 +83,22 @@ public void setup() throws IOException { Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json"))); } + @Test + public void testSerialization() throws JsonMappingException, JsonProcessingException { + ProcessedMap processedMap = objectMapper.readValue(inputProcessedMap1, typeReference); + String json = processedMap.toString(); + assertEquals(inputProcessedMap1, json); + } + + @Test + public void testJsonSerdes() throws IOException { + Serde> serdes = JsonSerdes.ProcessedMapGeoJson(); + ProcessedMap deserialized = serdes.deserializer().deserialize(null, inputProcessedMap1.getBytes()); + byte[] serialized = serdes.serializer().serialize(null, deserialized); + String serializedString = new String(serialized); + assertThat(serializedString, jsonEquals(inputProcessedMap1)); + } + @Test public void testTopology() { @@ -86,7 +109,6 @@ public void testTopology() { ProcessedMapDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapDeduplicatorTopology(props); Topology topology = processedMapDeduplicatorTopology.buildTopology(); - objectMapper.registerModule(new JavaTimeModule()); try (TopologyTestDriver driver = new TopologyTestDriver(topology)) { 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 8c38ba0..2803a7e 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,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; @@ -14,13 +19,12 @@ 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.DateJsonMapper; 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; @@ -32,10 +36,9 @@ public class ProcessedMapWktDeduplicatorTopologyTest { String inputTopic = "topic.ProcessedMapWKT"; String outputTopic = "topic.DeduplicatedProcessedMapWKT"; - + ObjectMapper objectMapper; TypeReference> typeReference = new TypeReference<>() { }; - ObjectMapper objectMapper = new ObjectMapper(); // Reference MAP String inputProcessedMapWkt1 = ""; @@ -56,11 +59,15 @@ public class ProcessedMapWktDeduplicatorTopologyTest { @Before public void setup() throws IOException { - // Load test files from resources + objectMapper = DateJsonMapper.getInstance(); + // Load test files from resources // Reference MAP - inputProcessedMapWkt1 = new String(Files.readAllBytes( + String processedMapWktReference = new String(Files.readAllBytes( Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json"))); + ProcessedMap processedMapWktReferenceData = objectMapper.readValue(processedMapWktReference, typeReference); + + inputProcessedMapWkt1 = processedMapWktReferenceData.toString(); // Duplicate of Number 1 inputProcessedMapWkt2 = new String(Files.readAllBytes( @@ -75,6 +82,22 @@ public void setup() throws IOException { "src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json"))); } + @Test + public void testSerialization() throws JsonMappingException, JsonProcessingException { + ProcessedMap processedMap = objectMapper.readValue(inputProcessedMapWkt1, typeReference); + String json = processedMap.toString(); + assertEquals(inputProcessedMapWkt1, json); + } + + @Test + public void testJsonSerdes() throws IOException { + Serde> serdes = JsonSerdes.ProcessedMapWKT(); + ProcessedMap deserialized = serdes.deserializer().deserialize(null, inputProcessedMapWkt1.getBytes()); + byte[] serialized = serdes.serializer().serialize(null, deserialized); + String serializedString = new String(serialized); + assertThat(serializedString, jsonEquals(inputProcessedMapWkt1)); + } + @Test public void testTopology() { @@ -85,7 +108,6 @@ public void testTopology() { ProcessedMapWktDeduplicatorTopology processedMapDeduplicatorTopology = new ProcessedMapWktDeduplicatorTopology(props); Topology topology = processedMapDeduplicatorTopology.buildTopology(); - objectMapper.registerModule(new JavaTimeModule()); try (TopologyTestDriver driver = new TopologyTestDriver(topology)) { diff --git a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/utils/GeoUtilsTest.java b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/utils/GeoUtilsTest.java index e6e3420..4bb0bd1 100644 --- a/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/utils/GeoUtilsTest.java +++ b/jpo-deduplicator/src/test/java/us/dot/its/jpo/deduplicator/utils/GeoUtilsTest.java @@ -1,7 +1,7 @@ package us.dot.its.jpo.deduplicator.utils; import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.Test; +import org.junit.Test; public class GeoUtilsTest { From 9cd31f75140baa27b55e4f2dd6c6c779f0ae589f Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 1 Aug 2025 09:09:37 -0600 Subject: [PATCH 10/24] Rework the ProcessedMap and ProcessedMapWkt examples --- README.md | 1 - .../processors/ProcessedMapProcessor.java | 2 +- .../processors/ProcessedMapWktProcessor.java | 6 +- .../ProcessedMapDeduplicatorTopologyTest.java | 20 +- ...ocessedMapWktDeduplicatorTopologyTest.java | 42 +- .../sample.processed_map-different.json | 8327 ++++++++++------- ....processed_map-reference-1-hour-later.json | 3443 ------- .../sample.processed_map-reference.json | 6514 ++++++------- .../sample.processed_map_wkt-different.json | 4707 ++++++---- ...cessed_map_wkt-reference-1-hour-later.json | 1829 ---- .../sample.processed_map_wkt-reference.json | 1875 +++- 11 files changed, 12772 insertions(+), 13994 deletions(-) delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json delete mode 100644 jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json diff --git a/README.md b/README.md index e2671b9..1b961bd 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,6 @@ To manually configure deduplication for a topic, the following environment varia | `ENABLE_PROCESSED_MAP_WKT_DEDUPLICATION` | `true` / `false` - Enable ProcessedMap WKT message Deduplication | | `ENABLE_ODE_MAP_DEDUPLICATION` | `true` / `false` - Enable ODE MAP message Deduplication | | `ENABLE_ODE_TIM_DEDUPLICATION` | `true` / `false` - Enable ODE TIM message Deduplication | -| `ENABLE_ODE_RAW_ENCODED_TIM_DEDUPLICATION` | `true` / `false` - Enable ODE Raw Encoded TIM Deduplication | | `ENABLE_PROCESSED_SPAT_DEDUPLICATION` | `true` / `false` - Enable ProcessedSpat Deduplication | | `ENABLE_ODE_BSM_DEDUPLICATION` | `true` / `false` - Enable ODE BSM Deduplication | | `ENABLE_PROCESSED_BSM_DEDUPLICATION` | `true` / `false` - Enable Processed BSM Deduplication | diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java index 23c7d72..5e69542 100644 --- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java +++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java @@ -27,7 +27,7 @@ public ProcessedMapProcessor(DeduplicatorProperties props){ @Override public Instant getMessageTime(ProcessedMap message) { try { - return message.getProperties().getOdeReceivedAt().toInstant(); + return message.getProperties().getTimeStamp().toInstant(); } catch (Exception e) { return Instant.ofEpochMilli(0); } diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java index 5734557..e69814b 100644 --- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java +++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java @@ -25,7 +25,7 @@ public ProcessedMapWktProcessor(DeduplicatorProperties props){ @Override public Instant getMessageTime(ProcessedMap message) { try { - return message.getProperties().getOdeReceivedAt().toInstant(); + return message.getProperties().getTimeStamp().toInstant(); } catch (Exception e) { return Instant.ofEpochMilli(0); } @@ -34,8 +34,8 @@ public Instant getMessageTime(ProcessedMap message) { @Override public boolean isDuplicate(ProcessedMap lastMessage, ProcessedMap newMessage) { try{ - Instant newValueTime = newMessage.getProperties().getTimeStamp().toInstant(); - Instant oldValueTime = lastMessage.getProperties().getTimeStamp().toInstant(); + Instant newValueTime = getMessageTime(newMessage); + Instant oldValueTime = getMessageTime(lastMessage); if(newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)){ return false; 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 5951274..936c658 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 @@ -32,6 +32,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.Instant; +import java.time.ZonedDateTime; public class ProcessedMapDeduplicatorTopologyTest { @@ -71,16 +73,20 @@ public void setup() throws IOException { inputProcessedMap1 = processedMapReferenceData.toString(); // Duplicate of Number 1 - inputProcessedMap2 = new String(Files - .readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-reference.json"))); + inputProcessedMap2 = processedMapReferenceData.toString(); + // Message 1 but 1 hour later + ProcessedMap processedMap1HourLater = objectMapper.readValue(processedMapReference, typeReference); + ZonedDateTime originalZdt = processedMap1HourLater.getProperties().getTimeStamp(); + Instant newInstant = originalZdt.toInstant().plusSeconds(3601); + processedMap1HourLater.getProperties().setTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); + inputProcessedMap3 = processedMap1HourLater.toString(); + // A different Message entirely - inputProcessedMap3 = new String(Files + String differentProcessedMapReference = 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"))); + ProcessedMap processedMapDifferentData = objectMapper.readValue(differentProcessedMapReference, typeReference); + inputProcessedMap4 = processedMapDifferentData.toString(); } @Test 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 2803a7e..ac49555 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 @@ -29,7 +29,8 @@ 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 ProcessedMapWktDeduplicatorTopologyTest { @@ -70,16 +71,20 @@ public void setup() throws IOException { inputProcessedMapWkt1 = processedMapWktReferenceData.toString(); // 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"))); + inputProcessedMapWkt2 = processedMapWktReferenceData.toString(); // 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"))); + ProcessedMap processedMapWkt1HourLater = objectMapper.readValue(processedMapWktReference, typeReference); + ZonedDateTime originalZdt = processedMapWkt1HourLater.getProperties().getTimeStamp(); + Instant newInstant = originalZdt.toInstant().plusSeconds(3601); + processedMapWkt1HourLater.getProperties().setTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); + inputProcessedMapWkt3 = processedMapWkt1HourLater.toString(); + + // A different Message entirely + String differentProcessedMapWktReference = new String(Files + .readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json"))); + ProcessedMap processedMapWktDifferentData = objectMapper.readValue(differentProcessedMapWktReference, typeReference); + inputProcessedMapWkt4 = processedMapWktDifferentData.toString(); } @Test @@ -126,25 +131,22 @@ public void testTopology() { inputProcessedMapData.pipeInput(key, inputProcessedMapWkt3); inputProcessedMapData.pipeInput(key, inputProcessedMapWkt4); - List>> mapDeduplicatorResults = outputProcessedMapData + List>> processedMapWktDeduplicatorResults = outputProcessedMapData .readKeyValuesToList(); // validate that only 3 messages make it through - assertEquals(3, mapDeduplicatorResults.size()); + assertEquals(3, processedMapWktDeduplicatorResults.size()); - ProcessedMap map1 = objectMapper.readValue(inputProcessedMapWkt1, + ProcessedMap processedMapWkt1 = objectMapper.readValue(inputProcessedMapWkt1, typeReference); - ProcessedMap map2 = objectMapper.readValue(inputProcessedMapWkt2, + ProcessedMap processedMapWkt3 = objectMapper.readValue(inputProcessedMapWkt3, typeReference); - ProcessedMap map4 = objectMapper.readValue(inputProcessedMapWkt4, + ProcessedMap processedMapWkt4 = 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()); + assertThat(processedMapWktDeduplicatorResults.get(0).value.toString(), jsonEquals(processedMapWkt1.toString())); + assertThat(processedMapWktDeduplicatorResults.get(1).value.toString(), jsonEquals(processedMapWkt3.toString())); + assertThat(processedMapWktDeduplicatorResults.get(2).value.toString(), jsonEquals(processedMapWkt4.toString())); } catch (JsonMappingException e) { e.printStackTrace(); diff --git a/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-different.json b/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-different.json index d839175..410c231 100644 --- a/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-different.json +++ b/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-different.json @@ -1,3443 +1,4886 @@ { - "mapFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": 2, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911523, - 39.5953376 - ], - [ - -105.0899239, - 39.5953231 - ], - [ - -105.0896005, - 39.5953332 - ], - [ - -105.0888831, - 39.595317 - ], - [ - -105.088108, - 39.5953159 - ], - [ - -105.0876637, - 39.5953153 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2225, - 808 - ], - "delevation": -10 - }, - { - "delta": [ - 10517, - -161 - ], - "delevation": -60 - }, - { - "delta": [ - 2769, - 112 - ], - "delevation": -10 - }, - { - "delta": [ - 6142, - -180 - ], - "delevation": -30 - }, - { - "delta": [ - 6636, - -12 - ], - "delevation": -20 - }, - { - "delta": [ - 3804, - -7 - ] - } - ], - "laneId": 2, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 3, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911527, - 39.5953113 - ], - [ - -105.0908101, - 39.5953039 - ], - [ - -105.0900791, - 39.5952962 - ], - [ - -105.0896801, - 39.5952874 - ], - [ - -105.0888781, - 39.5952839 - ], - [ - -105.0885678, - 39.5952789 - ], - [ - -105.0880704, - 39.5952849 - ], - [ - -105.0876638, - 39.5952849 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2222, - 515 - ], - "delevation": -10 - }, - { - "delta": [ - 2933, - -82 - ], - "delevation": -10 - }, - { - "delta": [ - 6259, - -85 - ], - "delevation": -40 - }, - { - "delta": [ - 3416, - -98 - ], - "delevation": -20 - }, - { - "delta": [ - 6867, - -39 - ], - "delevation": -30 - }, - { - "delta": [ - 2657, - -55 - ], - "delevation": -10 - }, - { - "delta": [ - 4259, - 67 - ], - "delevation": -10 - }, - { - "delta": [ - 3481, - 0 - ] - } - ], - "laneId": 3, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 1, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911535, - 39.5953745 - ], - [ - -105.0899328, - 39.5953544 - ], - [ - -105.0897165, - 39.5953447 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2215, - 1218 - ] - }, - { - "delta": [ - 10451, - -223 - ], - "delevation": -70 - }, - { - "delta": [ - 1852, - -108 - ], - "delevation": -10 - } - ], - "laneId": 1, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 4, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911537, - 39.5952537 - ], - [ - -105.0903143, - 39.5952555 - ], - [ - -105.0902511, - 39.5952591 - ], - [ - -105.0900995, - 39.5952797 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2213, - -124 - ], - "delevation": -10 - }, - { - "delta": [ - 7187, - 20 - ], - "delevation": -40 - }, - { - "delta": [ - 541, - 40 - ], - "delevation": -10 - }, - { - "delta": [ - 1298, - 229 - ] - } - ], - "laneId": 4, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 6, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911474, - 39.5951732 - ], - [ - -105.0911048, - 39.5951738 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2267, - -1019 - ], - "delevation": -10 - }, - { - "delta": [ - 365, - 7 - ] - } - ], - "laneId": 6, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 5, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911474, - 39.5952053 - ], - [ - -105.0911079, - 39.5952053 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2267, - -662 - ], - "delevation": -10 - }, - { - "delta": [ - 338, - 0 - ] - } - ], - "laneId": 5, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 7, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911443, - 39.5951332 - ], - [ - -105.0911017, - 39.5951356 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2294, - -1463 - ], - "delevation": -10 - }, - { - "delta": [ - 365, - 27 - ] - } - ], - "laneId": 7, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 12, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915234, - 39.5950941 - ], - [ - -105.0915234, - 39.5950602 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -952, - -1898 - ] - }, - { - "delta": [ - 0, - -377 - ] - } - ], - "laneId": 12, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 13, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915804, - 39.5950941 - ], - [ - -105.0915796, - 39.595059 - ], - [ - -105.0915796, - 39.595059 - ], - [ - -105.0915796, - 39.5950596 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1440, - -1898 - ] - }, - { - "delta": [ - 7, - -390 - ] - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - 0, - 7 - ] - } - ], - "laneId": 13, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 10, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913299, - 39.5950922 - ], - [ - -105.09133, - 39.5944158 - ], - [ - -105.0913348, - 39.5939413 - ], - [ - -105.0913368, - 39.592921 - ], - [ - -105.0913348, - 39.5923866 - ], - [ - -105.0913348, - 39.5923866 - ], - [ - -105.0913356, - 39.592386 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 705, - -1919 - ] - }, - { - "delta": [ - -1, - -7515 - ], - "delevation": -40 - }, - { - "delta": [ - -41, - -5272 - ], - "delevation": 10 - }, - { - "delta": [ - -17, - -11337 - ] - }, - { - "delta": [ - 17, - -5938 - ], - "delevation": 10 - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - -7, - -7 - ] - } - ], - "laneId": 10, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 9, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912849, - 39.5950912 - ], - [ - -105.0912838, - 39.5946624 - ], - [ - -105.0912861, - 39.5940862 - ], - [ - -105.0912901, - 39.5933704 - ], - [ - -105.0912882, - 39.5923858 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1090, - -1930 - ], - "delevation": -10 - }, - { - "delta": [ - 9, - -4764 - ], - "delevation": -10 - }, - { - "delta": [ - -20, - -6402 - ], - "delevation": -20 - }, - { - "delta": [ - -34, - -7953 - ], - "delevation": -10 - }, - { - "delta": [ - 16, - -10940 - ], - "delevation": 20 - } - ], - "laneId": 9, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 11, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913713, - 39.5950916 - ], - [ - -105.091375, - 39.5944888 - ], - [ - -105.0913568, - 39.5942534 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 350, - -1925 - ] - }, - { - "delta": [ - -32, - -6698 - ], - "delevation": -30 - }, - { - "delta": [ - 156, - -2616 - ] - } - ], - "laneId": 11, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 8, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912303, - 39.5950889 - ], - [ - -105.0912421, - 39.5949129 - ], - [ - -105.0912427, - 39.5942475 - ], - [ - -105.0912568, - 39.5941003 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1557, - -1956 - ], - "delevation": -10 - }, - { - "delta": [ - -101, - -1956 - ] - }, - { - "delta": [ - -5, - -7393 - ], - "delevation": -40 - }, - { - "delta": [ - -121, - -1636 - ] - } - ], - "laneId": 8, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 15, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916931, - 39.5951733 - ], - [ - -105.0927839, - 39.5951756 - ], - [ - -105.0941732, - 39.5951722 - ], - [ - -105.0952027, - 39.5951734 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2405, - -1018 - ], - "delevation": 10 - }, - { - "delta": [ - -9339, - 26 - ], - "delevation": 30 - }, - { - "delta": [ - -11895, - -38 - ], - "delevation": 50 - }, - { - "delta": [ - -8814, - 13 - ] - } - ], - "laneId": 15, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 16, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916852, - 39.5952059 - ], - [ - -105.0931135, - 39.5952073 - ], - [ - -105.0944406, - 39.595204 - ], - [ - -105.0952041, - 39.5952041 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2337, - -656 - ], - "delevation": 10 - }, - { - "delta": [ - -12229, - 15 - ], - "delevation": 50 - }, - { - "delta": [ - -11362, - -37 - ], - "delevation": 30 - }, - { - "delta": [ - -6537, - 1 - ] - } - ], - "laneId": 16, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 17, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916853, - 39.5952393 - ], - [ - -105.0927239, - 39.5952377 - ], - [ - -105.0941207, - 39.5952375 - ], - [ - -105.0943034, - 39.5952213 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2338, - -284 - ], - "delevation": 10 - }, - { - "delta": [ - -8892, - -18 - ], - "delevation": 30 - }, - { - "delta": [ - -11959, - -2 - ], - "delevation": 50 - }, - { - "delta": [ - -1564, - -180 - ] - } - ], - "laneId": 17, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 14, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916926, - 39.5951407 - ], - [ - -105.0940224, - 39.5951414 - ], - [ - -105.095203, - 39.5951408 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2401, - -1380 - ], - "delevation": 10 - }, - { - "delta": [ - -19947, - 8 - ], - "delevation": 80 - }, - { - "delta": [ - -10108, - -7 - ] - } - ], - "laneId": 14, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 18, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916766, - 39.595308 - ], - [ - -105.0917443, - 39.5953067 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2264, - 479 - ], - "delevation": 20 - }, - { - "delta": [ - -580, - -14 - ] - } - ], - "laneId": 18, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 19, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916758, - 39.5953365 - ], - [ - -105.0917363, - 39.5953365 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2257, - 796 - ], - "delevation": 20 - }, - { - "delta": [ - -518, - 0 - ] - } - ], - "laneId": 19, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 20, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916734, - 39.5953755 - ], - [ - -105.0917299, - 39.5953755 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2236, - 1229 - ], - "delevation": 20 - }, - { - "delta": [ - -484, - 0 - ] - } - ], - "laneId": 20, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 23, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.091519, - 39.5954362 - ], - [ - -105.0914927, - 39.5965421 - ], - [ - -105.091488, - 39.5974092 - ], - [ - -105.0914843, - 39.5981324 - ], - [ - -105.0914843, - 39.5981324 - ], - [ - -105.0914851, - 39.5981349 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -914, - 1903 - ], - "delevation": 20 - }, - { - "delta": [ - 225, - 12288 - ], - "delevation": 30 - }, - { - "delta": [ - 40, - 9634 - ], - "delevation": -20 - }, - { - "delta": [ - 32, - 8035 - ], - "delevation": -30 - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - -7, - 28 - ] - } - ], - "laneId": 23, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 22, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915548, - 39.5954372 - ], - [ - -105.0915441, - 39.59638 - ], - [ - -105.0915337, - 39.5974224 - ], - [ - -105.0915281, - 39.5981345 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1221, - 1914 - ], - "delevation": 20 - }, - { - "delta": [ - 92, - 10475 - ], - "delevation": 30 - }, - { - "delta": [ - 89, - 11582 - ], - "delevation": -20 - }, - { - "delta": [ - 48, - 7912 - ], - "delevation": -30 - } - ], - "laneId": 22, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 21, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916048, - 39.5954391 - ], - [ - -105.0916029, - 39.5957255 - ], - [ - -105.0916004, - 39.5962647 - ], - [ - -105.0915885, - 39.5966976 - ], - [ - -105.0915786, - 39.5977599 - ], - [ - -105.0915764, - 39.5981344 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1649, - 1935 - ], - "delevation": 20 - }, - { - "delta": [ - 16, - 3182 - ], - "delevation": 10 - }, - { - "delta": [ - 21, - 5991 - ], - "delevation": 20 - }, - { - "delta": [ - 102, - 4810 - ] - }, - { - "delta": [ - 85, - 11803 - ], - "delevation": -30 - }, - { - "delta": [ - 19, - 4161 - ], - "delevation": -20 - } - ], - "laneId": 21, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 24, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914747, - 39.5954382 - ], - [ - -105.0914714, - 39.5958506 - ], - [ - -105.0914611, - 39.596192 - ], - [ - -105.0914778, - 39.5963599 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -535, - 1926 - ], - "delevation": 20 - }, - { - "delta": [ - 28, - 4582 - ], - "delevation": 10 - }, - { - "delta": [ - 88, - 3793 - ], - "delevation": 10 - }, - { - "delta": [ - -143, - 1866 - ], - "delevation": 10 - } - ], - "laneId": 24, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 25, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914371, - 39.5954371 - ], - [ - -105.0914355, - 39.5958506 - ], - [ - -105.0914461, - 39.596052 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -213, - 1913 - ], - "delevation": 20 - }, - { - "delta": [ - 14, - 4594 - ], - "delevation": 10 - }, - { - "delta": [ - -91, - 2238 - ], - "delevation": 10 - } - ], - "laneId": 25, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 26, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913276, - 39.5954361 - ], - [ - -105.0913284, - 39.5954678 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 724, - 1902 - ], - "delevation": 10 - }, - { - "delta": [ - -7, - 352 - ], - "delevation": 10 - } - ], - "laneId": 26, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 27, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912831, - 39.5954348 - ], - [ - -105.0912839, - 39.5954647 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1105, - 1888 - ], - "delevation": 10 - }, - { - "delta": [ - -7, - 332 - ], - "delevation": 10 - } - ], - "laneId": 27, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 28, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912264, - 39.5954336 - ], - [ - -105.091228, - 39.5954647 - ], - [ - -105.091228, - 39.5954653 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1591, - 1874 - ], - "delevation": 10 - }, - { - "delta": [ - -14, - 346 - ] - }, - { - "delta": [ - 0, - 7 - ] - } - ], - "laneId": 28, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - } - ] - }, - "connectingLanesFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": "2-19", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911523, - 39.5953376 - ], - [ - -105.0916758, - 39.5953365 - ] - ] - }, - "properties": { - "signalGroupId": 4, - "ingressLaneId": 2, - "egressLaneId": 19 - } - }, - { - "type": "Feature", - "id": "3-18", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911527, - 39.5953113 - ], - [ - -105.0916766, - 39.595308 - ] - ] - }, - "properties": { - "signalGroupId": 4, - "ingressLaneId": 3, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "1-28", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911535, - 39.5953745 - ], - [ - -105.0912264, - 39.5954336 - ] - ] - }, - "properties": { - "ingressLaneId": 1, - "egressLaneId": 28 - } - }, - { - "type": "Feature", - "id": "4-12", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911537, - 39.5952537 - ], - [ - -105.0915234, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 7, - "ingressLaneId": 4, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "10-26", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913299, - 39.5950922 - ], - [ - -105.0913276, - 39.5954361 - ] - ] - }, - "properties": { - "signalGroupId": 6, - "ingressLaneId": 10, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "9-27", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912849, - 39.5950912 - ], - [ - -105.0912831, - 39.5954348 - ] - ] - }, - "properties": { - "signalGroupId": 6, - "ingressLaneId": 9, - "egressLaneId": 27 - } - }, - { - "type": "Feature", - "id": "11-18", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913713, - 39.5950916 - ], - [ - -105.0916766, - 39.595308 - ] - ] - }, - "properties": { - "signalGroupId": 1, - "ingressLaneId": 11, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "8-7", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912303, - 39.5950889 - ], - [ - -105.0911443, - 39.5951332 - ] - ] - }, - "properties": { - "ingressLaneId": 8, - "egressLaneId": 7 - } - }, - { - "type": "Feature", - "id": "15-6", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916931, - 39.5951733 - ], - [ - -105.0911474, - 39.5951732 - ] - ] - }, - "properties": { - "signalGroupId": 8, - "ingressLaneId": 15, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "16-5", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916852, - 39.5952059 - ], - [ - -105.0911474, - 39.5952053 - ] - ] - }, - "properties": { - "signalGroupId": 8, - "ingressLaneId": 16, - "egressLaneId": 5 - } - }, - { - "type": "Feature", - "id": "17-26", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916853, - 39.5952393 - ], - [ - -105.0913276, - 39.5954361 - ] - ] - }, - "properties": { - "signalGroupId": 3, - "ingressLaneId": 17, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "14-13", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916926, - 39.5951407 - ], - [ - -105.0915804, - 39.5950941 - ] - ] - }, - "properties": { - "ingressLaneId": 14, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "23-12", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.091519, - 39.5954362 - ], - [ - -105.0915234, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 2, - "ingressLaneId": 23, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "22-13", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915548, - 39.5954372 - ], - [ - -105.0915804, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 2, - "ingressLaneId": 22, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "21-20", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916048, - 39.5954391 - ], - [ - -105.0916734, - 39.5953755 - ] - ] - }, - "properties": { - "ingressLaneId": 21, - "egressLaneId": 20 - } - }, - { - "type": "Feature", - "id": "24-6", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914747, - 39.5954382 - ], - [ - -105.0911474, - 39.5951732 - ] - ] - }, - "properties": { - "signalGroupId": 5, - "ingressLaneId": 24, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "25-5", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914371, - 39.5954371 - ], - [ - -105.0911474, - 39.5952053 - ] - ] - }, - "properties": { - "signalGroupId": 5, - "ingressLaneId": 25, - "egressLaneId": 5 - } - } - ] - }, - "properties": { - "schemaVersion": 1, - "messageType": "MAP", - "odeReceivedAt": "2025-01-31T23:36:23.542Z", - "originIp": "172.20.0.1", - "intersectionId": 13110, - "msgIssueRevision": 0, - "revision": 0, - "refPoint": { - "latitude": 39.5952649, - "longitude": -105.0914122, - "elevation": 1677 - }, - "cti4501Conformant": false, - "validationMessages": [ - { - "message": "$.payload.data.intersections.intersectionGeometry[0].id.region: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].id", - "schemaPath": "#/$defs/J2735IntersectionReferenceID/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[2].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[2].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[12].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[12].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[16].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[16].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[22].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[22].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].speedLimits: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0]", - "schemaPath": "#/$defs/J2735IntersectionGeometry/required" - } - ], - "laneWidth": 366, - "mapSource": "RSU", - "timeStamp": "2025-01-31T23:36:23.542Z" - } - } \ No newline at end of file + "mapFeatureCollection": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": 10, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34925148645785, + 33.76995371997552 + ], + [ + -84.34997287206494, + 33.769951019972815 + ], + [ + -84.35018009583929, + 33.769923209945006 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1849, + -272 + ], + "dwidth": -50 + }, + { + "delta": [ + -6663, + -30 + ] + }, + { + "delta": [ + -1914, + -309 + ] + } + ], + "laneId": 10, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 3 + } + ] + } + }, + { + "type": "Feature", + "id": 11, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34925148645785, + 33.76992257994438 + ], + [ + -84.34997427927831, + 33.76992266994447 + ], + [ + -84.35024938661185, + 33.76991087993268 + ], + [ + -84.35044589182306, + 33.76987775989956 + ], + [ + -84.35063243636743, + 33.76983104985285 + ], + [ + -84.35080891195743, + 33.769774889796686 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1849, + -618 + ] + }, + { + "delta": [ + -6676, + 1 + ] + }, + { + "delta": [ + -2541, + -131 + ] + }, + { + "delta": [ + -1815, + -368 + ] + }, + { + "delta": [ + -1723, + -519 + ] + }, + { + "delta": [ + -1630, + -624 + ] + } + ], + "laneId": 11, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 12, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 9 + } + ] + } + }, + { + "type": "Feature", + "id": 9, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492353546124, + 33.77002491004671 + ], + [ + -84.34938194877772, + 33.770024370046166 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1700, + 519 + ] + }, + { + "delta": [ + -1354, + -6 + ] + } + ], + "laneId": 9, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 6, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 12, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34911355376596, + 33.7697963998182 + ], + [ + -84.34911485297224, + 33.76969343971524 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -575, + -2020 + ] + }, + { + "delta": [ + -12, + -1144 + ] + } + ], + "laneId": 12, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 13, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34908129007508, + 33.76979693981874 + ], + [ + -84.34907923299846, + 33.76969514971695 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -277, + -2014 + ] + }, + { + "delta": [ + 19, + -1131 + ] + } + ], + "laneId": 13, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 1, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34901069971785, + 33.769804049825844 + ], + [ + -84.34901243199303, + 33.769519919541715 + ], + [ + -84.34899759943595, + 33.76931678933858 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 375, + -1935 + ], + "dwidth": -50 + }, + { + "delta": [ + -16, + -3157 + ] + }, + { + "delta": [ + 137, + -2257 + ] + } + ], + "laneId": 1, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 1 + } + ] + } + }, + { + "type": "Feature", + "id": 2, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.348976378946, + 33.76980845983026 + ], + [ + -84.34897973522935, + 33.76951370953551 + ], + [ + -84.34899727445615, + 33.76925108927289 + ], + [ + -84.34900463657817, + 33.76893275895456 + ], + [ + -84.3490140557287, + 33.76797227799408 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 692, + -1886 + ] + }, + { + "delta": [ + -31, + -3275 + ] + }, + { + "delta": [ + -162, + -2918 + ] + }, + { + "delta": [ + -68, + -3537 + ] + }, + { + "delta": [ + -87, + -10672 + ] + } + ], + "laneId": 2, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 3, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34894205817417, + 33.76981457983638 + ], + [ + -84.34894000109713, + 33.76951541953722 + ], + [ + -84.3489588395263, + 33.769246679268484 + ], + [ + -84.34897226457166, + 33.7689305989524 + ], + [ + -84.3489829829151, + 33.76797011799192 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1009, + -1818 + ] + }, + { + "delta": [ + 19, + -3324 + ] + }, + { + "delta": [ + -174, + -2986 + ] + }, + { + "delta": [ + -124, + -3512 + ] + }, + { + "delta": [ + -99, + -10672 + ] + } + ], + "laneId": 3, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 4, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 4, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34893664480322, + 33.77010744012924 + ], + [ + -84.34893664480322, + 33.770200950222744 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1059, + 1436 + ] + }, + { + "delta": [ + 0, + 1039 + ] + } + ], + "laneId": 4, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 4, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 5, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34897237305151, + 33.77010861013041 + ], + [ + -84.34897172344601, + 33.77020158022338 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 729, + 1449 + ] + }, + { + "delta": [ + 6, + 1033 + ] + } + ], + "laneId": 5, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 4, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 8, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34913174269236, + 33.77012562014742 + ], + [ + -84.3491101974389, + 33.77031948034128 + ], + [ + -84.34907457731616, + 33.77039265041445 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -743, + 1638 + ], + "dwidth": 100 + }, + { + "delta": [ + 199, + 2154 + ] + }, + { + "delta": [ + 329, + 813 + ] + } + ], + "laneId": 8, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 7 + } + ] + } + }, + { + "type": "Feature", + "id": 6, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34906050273062, + 33.770125080146876 + ], + [ + -84.34902823898443, + 33.7704246004464 + ], + [ + -84.34901946927779, + 33.77064888067068 + ], + [ + -84.34902152637486, + 33.770956050977844 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -85, + 1632 + ] + }, + { + "delta": [ + 298, + 3328 + ] + }, + { + "delta": [ + 81, + 2492 + ] + }, + { + "delta": [ + -19, + 3413 + ] + } + ], + "laneId": 6, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 7, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34909742192052, + 33.77012283014463 + ], + [ + -84.34906786486522, + 33.77040498042678 + ], + [ + -84.34905844555284, + 33.770502900524704 + ], + [ + -84.34905097505518, + 33.77095605097785 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -426, + 1607 + ] + }, + { + "delta": [ + 273, + 3135 + ] + }, + { + "delta": [ + 87, + 1088 + ] + }, + { + "delta": [ + 69, + 5035 + ] + } + ], + "laneId": 7, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 12, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 26, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34885501108728, + 33.77008836011016 + ], + [ + -84.34879784581652, + 33.770064960086756 + ], + [ + -84.34878301316509, + 33.770017080038876 + ], + [ + -84.34879243243482, + 33.76995200997381 + ], + [ + -84.34880520798636, + 33.76989692991873 + ], + [ + -84.34882870199401, + 33.76986740988921 + ], + [ + -84.34887103450012, + 33.76985570987751 + ], + [ + -84.34891953823453, + 33.76985030987211 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1228, + 1232 + ] + }, + { + "delta": [ + 585, + -8 + ] + }, + { + "delta": [ + 528, + -260 + ] + }, + { + "delta": [ + 137, + -532 + ] + }, + { + "delta": [ + -87, + -723 + ] + }, + { + "delta": [ + -118, + -612 + ] + }, + { + "delta": [ + -217, + -328 + ] + }, + { + "delta": [ + -391, + -130 + ] + }, + { + "delta": [ + -448, + -60 + ] + } + ], + "laneId": 26, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 25, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 27, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 28, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 29, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 28, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34880661563292, + 33.76941281943461 + ], + [ + -84.34883887911091, + 33.769653209675006 + ], + [ + -84.34883487323161, + 33.76981016983196 + ], + [ + -84.34886984353939, + 33.7698557998776 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 2260, + -6282 + ] + }, + { + "delta": [ + -298, + 2671 + ] + }, + { + "delta": [ + 37, + 1744 + ] + }, + { + "delta": [ + -323, + 507 + ] + } + ], + "laneId": 28, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 27, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34881744237482, + 33.770362050383845 + ], + [ + -84.34883487350739, + 33.77025297027477 + ], + [ + -84.34883487350739, + 33.77015388017568 + ], + [ + -84.34885371207693, + 33.77008818010998 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 2160, + 4265 + ] + }, + { + "delta": [ + -161, + -1212 + ] + }, + { + "delta": [ + 0, + -1101 + ] + }, + { + "delta": [ + -174, + -730 + ] + } + ], + "laneId": 27, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 32, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34914343557362, + 33.76982213984394 + ], + [ + -84.34916443941466, + 33.76982231984412 + ], + [ + -84.34920752976906, + 33.76985012987193 + ], + [ + -84.3492140258045, + 33.76989332991513 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -851, + -1734 + ] + }, + { + "delta": [ + -194, + 2 + ] + }, + { + "delta": [ + -398, + 309 + ] + }, + { + "delta": [ + -60, + 480 + ] + } + ], + "laneId": 32, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 31, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 33, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 34, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 35, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 30, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34903137879489, + 33.769838069859865 + ], + [ + -84.34906299282956, + 33.76983419985599 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 184, + -1557 + ] + }, + { + "delta": [ + -292, + -43 + ] + } + ], + "laneId": 30, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 29, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 31, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 33, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34911896713692, + 33.76936223938404 + ], + [ + -84.34915231326228, + 33.769685519707316 + ], + [ + -84.34915772661475, + 33.76978064980245 + ], + [ + -84.34916259863738, + 33.76982240984421 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -625, + -6844 + ] + }, + { + "delta": [ + -308, + 3592 + ] + }, + { + "delta": [ + -50, + 1057 + ] + }, + { + "delta": [ + -45, + 464 + ] + } + ], + "laneId": 33, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 34, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34992555940892, + 33.76979270981451 + ], + [ + -84.34958007882258, + 33.76979621981802 + ], + [ + -84.34938508961498, + 33.76980287982468 + ], + [ + -84.3492439091894, + 33.76981952984133 + ], + [ + -84.34920828927449, + 33.76984850987031 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -8075, + -2061 + ] + }, + { + "delta": [ + 3191, + 39 + ] + }, + { + "delta": [ + 1801, + 74 + ] + }, + { + "delta": [ + 1304, + 185 + ] + }, + { + "delta": [ + 329, + 322 + ] + } + ], + "laneId": 34, + "laneType": { + "parking": { + "parkingRevocableLane": false, + "parallelParkingInUse": false, + "headInParkingInUse": false, + "doNotParkZone": false, + "parkingForBusUse": false, + "parkingForTaxiUse": false, + "noPublicParkingUse": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 20, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3491024022218, + 33.77054277056457 + ], + [ + -84.34909861283717, + 33.77045835048015 + ], + [ + -84.34910933137172, + 33.77040768042948 + ], + [ + -84.34913693970196, + 33.77036484038664 + ], + [ + -84.34915642792534, + 33.77031696033876 + ], + [ + -84.34916379013895, + 33.77022291024471 + ], + [ + -84.34917526651815, + 33.77014722016902 + ], + [ + -84.3492175991625, + 33.77009601011781 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -472, + 6273 + ] + }, + { + "delta": [ + 35, + -938 + ] + }, + { + "delta": [ + -99, + -563 + ] + }, + { + "delta": [ + -255, + -476 + ] + }, + { + "delta": [ + -180, + -532 + ] + }, + { + "delta": [ + -68, + -1045 + ] + }, + { + "delta": [ + -106, + -841 + ] + }, + { + "delta": [ + -391, + -569 + ] + } + ], + "laneId": 20, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 22, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34968877856343, + 33.770207790229584 + ], + [ + -84.34957065849274, + 33.770199600221396 + ], + [ + -84.34947917228725, + 33.77017899020078 + ], + [ + -84.34935682981701, + 33.770132820154615 + ], + [ + -84.34928147555736, + 33.770106630128424 + ], + [ + -84.34921759768437, + 33.7700961001179 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -5888, + 2551 + ] + }, + { + "delta": [ + 1091, + -91 + ] + }, + { + "delta": [ + 845, + -229 + ] + }, + { + "delta": [ + 1130, + -513 + ] + }, + { + "delta": [ + 696, + -291 + ] + }, + { + "delta": [ + 590, + -117 + ] + } + ], + "laneId": 22, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34921749048802, + 33.7700961001179 + ], + [ + -84.34919399642575, + 33.77009403011583 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1537, + 1091 + ] + }, + { + "delta": [ + 2, + 219 + ] + }, + { + "delta": [ + 217, + -23 + ] + } + ], + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 36, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34921759875567, + 33.769967759989555 + ], + [ + -84.34921759875567, + 33.76999449001629 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1536, + -116 + ] + }, + { + "delta": [ + 0, + 297 + ] + } + ], + "laneId": 36, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 35, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34921749048802, + 33.7700961001179 + ], + [ + -84.34919399642575, + 33.77009403011583 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1537, + 1091 + ] + }, + { + "delta": [ + 2, + 219 + ] + }, + { + "delta": [ + 217, + -23 + ] + } + ], + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34921749048802, + 33.7700961001179 + ], + [ + -84.34919399642575, + 33.77009403011583 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1537, + 1091 + ] + }, + { + "delta": [ + 2, + 219 + ] + }, + { + "delta": [ + 217, + -23 + ] + } + ], + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 24, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34904415435034, + 33.7700907001125 + ], + [ + -84.34899770756658, + 33.77008962011142 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 66, + 1250 + ] + }, + { + "delta": [ + 429, + -12 + ] + } + ], + "laneId": 24, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 25, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 26, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34885501108728, + 33.77008836011016 + ], + [ + -84.34879784581652, + 33.770064960086756 + ], + [ + -84.34878301316509, + 33.770017080038876 + ], + [ + -84.34879243243482, + 33.76995200997381 + ], + [ + -84.34880520798636, + 33.76989692991873 + ], + [ + -84.34882870199401, + 33.76986740988921 + ], + [ + -84.34887103450012, + 33.76985570987751 + ], + [ + -84.34891953823453, + 33.76985030987211 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1228, + 1232 + ] + }, + { + "delta": [ + 585, + -8 + ] + }, + { + "delta": [ + 528, + -260 + ] + }, + { + "delta": [ + 137, + -532 + ] + }, + { + "delta": [ + -87, + -723 + ] + }, + { + "delta": [ + -118, + -612 + ] + }, + { + "delta": [ + -217, + -328 + ] + }, + { + "delta": [ + -391, + -130 + ] + }, + { + "delta": [ + -448, + -60 + ] + } + ], + "laneId": 26, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 25, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 27, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 28, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 29, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 35, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492148920702, + 33.76989314991495 + ], + [ + -84.34921759875299, + 33.76996712998893 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1511, + -945 + ] + }, + { + "delta": [ + -25, + 822 + ] + } + ], + "laneId": 35, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + }, + { + "connectingLane": { + "lane": 36, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + } + ] + } + }, + { + "type": "Feature", + "id": 37, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34921759875567, + 33.76999449001629 + ], + [ + -84.3492162995464, + 33.7700763000981 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1536, + 181 + ] + }, + { + "delta": [ + 12, + 909 + ] + } + ], + "laneId": 37, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": false, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 35, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + }, + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + } + ] + } + }, + { + "type": "Feature", + "id": 23, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34919410472574, + 33.77009403011583 + ], + [ + -84.34904415414763, + 33.7700907001125 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1319, + 1287 + ] + }, + { + "delta": [ + 1385, + -37 + ] + } + ], + "laneId": 23, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + }, + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + } + ] + } + }, + { + "type": "Feature", + "id": 25, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34899770762756, + 33.77008962011142 + ], + [ + -84.3489183475062, + 33.77008908011088 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 495, + 1238 + ] + }, + { + "delta": [ + 733, + -6 + ] + } + ], + "laneId": 25, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + } + ] + } + }, + { + "type": "Feature", + "id": 29, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34891975508584, + 33.769850309872105 + ], + [ + -84.3490313786283, + 33.769838069859865 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1215, + -1421 + ] + }, + { + "delta": [ + -1031, + -136 + ] + } + ], + "laneId": 29, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 30, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + } + ] + } + }, + { + "type": "Feature", + "id": 31, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34906299288126, + 33.769834199856 + ], + [ + -84.34914321890396, + 33.7698206998425 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -108, + -1600 + ] + }, + { + "delta": [ + -741, + -150 + ] + } + ], + "laneId": 31, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 30, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + } + ] + } + } + ] + }, + "connectingLanesFeatureCollection": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "10-5", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34925148645785, + 33.76995371997552 + ], + [ + -84.34897237305151, + 33.77010861013041 + ] + ] + }, + "properties": { + "signalGroupId": 3, + "ingressLaneId": 10, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "11-12", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34925148645785, + 33.76992257994438 + ], + [ + -84.34911355376596, + 33.7697963998182 + ] + ] + }, + "properties": { + "signalGroupId": 9, + "ingressLaneId": 11, + "egressLaneId": 12 + } + }, + { + "type": "Feature", + "id": "1-9", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34901069971785, + 33.769804049825844 + ], + [ + -84.3492353546124, + 33.77002491004671 + ] + ] + }, + "properties": { + "signalGroupId": 1, + "ingressLaneId": 1, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "2-5", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.348976378946, + 33.76980845983026 + ], + [ + -84.34897237305151, + 33.77010861013041 + ] + ] + }, + "properties": { + "signalGroupId": 6, + "ingressLaneId": 2, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "3-4", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34894205817417, + 33.76981457983638 + ], + [ + -84.34893664480322, + 33.77010744012924 + ] + ] + }, + "properties": { + "signalGroupId": 6, + "ingressLaneId": 3, + "egressLaneId": 4 + } + }, + { + "type": "Feature", + "id": "8-9", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34913174269236, + 33.77012562014742 + ], + [ + -84.3492353546124, + 33.77002491004671 + ] + ] + }, + "properties": { + "signalGroupId": 7, + "ingressLaneId": 8, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "6-13", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34906050273062, + 33.770125080146876 + ], + [ + -84.34908129007508, + 33.76979693981874 + ] + ] + }, + "properties": { + "signalGroupId": 2, + "ingressLaneId": 6, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "7-12", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34909742192052, + 33.77012283014463 + ], + [ + -84.34911355376596, + 33.7697963998182 + ] + ] + }, + "properties": { + "signalGroupId": 2, + "ingressLaneId": 7, + "egressLaneId": 12 + } + }, + { + "type": "Feature", + "id": "26-25", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34899770762756, + 33.77008962011142 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 25 + } + }, + { + "type": "Feature", + "id": "26-27", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34881744237482, + 33.770362050383845 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 27 + } + }, + { + "type": "Feature", + "id": "26-28", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34880661563292, + 33.76941281943461 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 28 + } + }, + { + "type": "Feature", + "id": "26-29", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34891975508584, + 33.769850309872105 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 29 + } + }, + { + "type": "Feature", + "id": "28-26", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34880661563292, + 33.76941281943461 + ], + [ + -84.3489183476094, + 33.77008908011088 + ] + ] + }, + "properties": { + "ingressLaneId": 28, + "egressLaneId": 26 + } + }, + { + "type": "Feature", + "id": "27-26", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34881744237482, + 33.770362050383845 + ], + [ + -84.3489183476094, + 33.77008908011088 + ] + ] + }, + "properties": { + "ingressLaneId": 27, + "egressLaneId": 26 + } + }, + { + "type": "Feature", + "id": "32-31", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34914343557362, + 33.76982213984394 + ], + [ + -84.34906299288126, + 33.769834199856 + ] + ] + }, + "properties": { + "ingressLaneId": 32, + "egressLaneId": 31 + } + }, + { + "type": "Feature", + "id": "32-33", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34914343557362, + 33.76982213984394 + ], + [ + -84.34911896713692, + 33.76936223938404 + ] + ] + }, + "properties": { + "ingressLaneId": 32, + "egressLaneId": 33 + } + }, + { + "type": "Feature", + "id": "32-34", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34914343557362, + 33.76982213984394 + ], + [ + -84.34992555940892, + 33.76979270981451 + ] + ] + }, + "properties": { + "ingressLaneId": 32, + "egressLaneId": 34 + } + }, + { + "type": "Feature", + "id": "32-35", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34914343557362, + 33.76982213984394 + ], + [ + -84.3492148920702, + 33.76989314991495 + ] + ] + }, + "properties": { + "ingressLaneId": 32, + "egressLaneId": 35 + } + }, + { + "type": "Feature", + "id": "30-29", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34903137879489, + 33.769838069859865 + ], + [ + -84.34891975508584, + 33.769850309872105 + ] + ] + }, + "properties": { + "ingressLaneId": 30, + "egressLaneId": 29 + } + }, + { + "type": "Feature", + "id": "30-31", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34903137879489, + 33.769838069859865 + ], + [ + -84.34906299288126, + 33.769834199856 + ] + ] + }, + "properties": { + "ingressLaneId": 30, + "egressLaneId": 31 + } + }, + { + "type": "Feature", + "id": "33-32", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34911896713692, + 33.76936223938404 + ], + [ + -84.34914343557362, + 33.76982213984394 + ] + ] + }, + "properties": { + "ingressLaneId": 33, + "egressLaneId": 32 + } + }, + { + "type": "Feature", + "id": "34-32", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34992555940892, + 33.76979270981451 + ], + [ + -84.34914343557362, + 33.76982213984394 + ] + ] + }, + "properties": { + "ingressLaneId": 34, + "egressLaneId": 32 + } + }, + { + "type": "Feature", + "id": "20-21", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3491024022218, + 33.77054277056457 + ], + [ + -84.3492177070231, + 33.77007639009819 + ] + ] + }, + "properties": { + "ingressLaneId": 20, + "egressLaneId": 21 + } + }, + { + "type": "Feature", + "id": "20-22", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3491024022218, + 33.77054277056457 + ], + [ + -84.34968877856343, + 33.770207790229584 + ] + ] + }, + "properties": { + "ingressLaneId": 20, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "22-20", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34968877856343, + 33.770207790229584 + ], + [ + -84.3491024022218, + 33.77054277056457 + ] + ] + }, + "properties": { + "ingressLaneId": 22, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "22-21", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34968877856343, + 33.770207790229584 + ], + [ + -84.3492177070231, + 33.77007639009819 + ] + ] + }, + "properties": { + "ingressLaneId": 22, + "egressLaneId": 21 + } + }, + { + "type": "Feature", + "id": "21-20", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.3491024022218, + 33.77054277056457 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "21-22", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34968877856343, + 33.770207790229584 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "21-23", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34919410472574, + 33.77009403011583 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "21-37", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34921759875567, + 33.76999449001629 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "36-35", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34921759875567, + 33.769967759989555 + ], + [ + -84.3492148920702, + 33.76989314991495 + ] + ] + }, + "properties": { + "ingressLaneId": 36, + "egressLaneId": 35 + } + }, + { + "type": "Feature", + "id": "36-37", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34921759875567, + 33.769967759989555 + ], + [ + -84.34921759875567, + 33.76999449001629 + ] + ] + }, + "properties": { + "ingressLaneId": 36, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "21-20", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.3491024022218, + 33.77054277056457 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "21-22", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34968877856343, + 33.770207790229584 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "21-23", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34919410472574, + 33.77009403011583 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "21-37", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34921759875567, + 33.76999449001629 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "21-20", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.3491024022218, + 33.77054277056457 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "21-22", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34968877856343, + 33.770207790229584 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "21-23", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34919410472574, + 33.77009403011583 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "21-37", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3492177070231, + 33.77007639009819 + ], + [ + -84.34921759875567, + 33.76999449001629 + ] + ] + }, + "properties": { + "ingressLaneId": 21, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "24-23", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34904415435034, + 33.7700907001125 + ], + [ + -84.34919410472574, + 33.77009403011583 + ] + ] + }, + "properties": { + "ingressLaneId": 24, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "24-25", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.34904415435034, + 33.7700907001125 + ], + [ + -84.34899770762756, + 33.77008962011142 + ] + ] + }, + "properties": { + "ingressLaneId": 24, + "egressLaneId": 25 + } + }, + { + "type": "Feature", + "id": "26-25", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34899770762756, + 33.77008962011142 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 25 + } + }, + { + "type": "Feature", + "id": "26-27", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34881744237482, + 33.770362050383845 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 27 + } + }, + { + "type": "Feature", + "id": "26-28", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34880661563292, + 33.76941281943461 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 28 + } + }, + { + "type": "Feature", + "id": "26-29", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -84.3489183476094, + 33.77008908011088 + ], + [ + -84.34891975508584, + 33.769850309872105 + ] + ] + }, + "properties": { + "ingressLaneId": 26, + "egressLaneId": 29 + } + } + ] + }, + "properties": { + "schemaVersion": 2, + "messageType": "MAP", + "odeReceivedAt": "2025-08-01T15:07:54.8Z", + "originIp": "172.18.0.1", + "asn1": "001283A638053000324E2177D41449C5CCC639032D2E02DC0515E1096050A1C000080002A0C76F00473882FCBFC4A0866CB080A05187024150000CB02C50E0000200041063ACB105EC800466137BE883A5A40428ABF2A1A2590080A051870243080024402588E00000050AE5038405028C38456CFF420184470000002970407020281461C27F4388100D22380000014DD604410140A30E14099CA96009A1C000080002A977071047386FF01D5AE11272F080A051870242500004B008D0E000080003155A0510DFC23351BD7893437DE08BDAFF52ACA010140A30E0482C000316019A1C0001000062BF10E61C04C60837A911586F8412435FE75594020281461C090480006100442380000015847B3810140A30E14006078802A11C000000AAD9DA9080A051870A01B024B02150E000020001528CF33024C83863E1A93527968405028C3812124000E480CA8700000109EAF980712AE800E0A39BC5BFB7AAA10140A30E0486C00011603AA1C0001000042656E471C44787E2857C406408B9D58405028C38121900004683400C0D300000716666680724BF80E105F819127B02EA49685C519C024E5C00795F8020388601900D807003A683800C0D3000002251A83BB0DDADA6F1412F6800BDFEC0034683600C0D3000002250E185489D7CD10500076616A44980034684000C0D3000002125689D013E80803966A0713E0300F8084044023341E0060698000000A2E07AC06E3AA201D00F9A10803034C0000088EC78A88376678204F9D842074FD000101A11003035C00000C803AAFE63E3BC09C5E130942D188B90693A100080D0500181A600000C478A38810C230AC173A73408084816987B04F787D6172C2DC29E4E38805402C682C00C0D3000004212014FB8B10DE943D358D8B1A97FC3AE16E872738B100A0054D0540181A600000221FFC4304056D82D97A4C02801600B8094D0900181A6000000220078C0401948808C04A682A00C0D300000110FFE218202B6C16CBD2601400B005C04A682A00C0D300000110FFE218202B6C16CBD2601400B005C04A683000C0D3000000142167103AD7D0402E019341A0060698000038B3333403925FC07082FC0C893D817524B42E28CE01272E003CAFC0101C4300C806C03801D042300688200000886513C2F9F9B0A080350481A084A00D1000000110045A860678D141186A05434105C01A208000022D9D0716B4BED8A054390301C083200D104000014F7E6B076EBFA140C08206840107401A20800002CBF27311FCBBC0A0684103C20083E00D104000013CA0E0048DB6A140F08208040", + "region": 10000, + "intersectionId": 48106, + "msgIssueRevision": 5, + "revision": 5, + "refPoint": { + "latitude": 33.7699782, + "longitude": -84.3490513 + }, + "cti4501Conformant": false, + "validationMessages": [ + { + "message": "CTI-4501 conformance issue: The laneSet 'connectsTo' DF_ConnectsToList is missing" + }, + { + "message": "CTI-4501 conformance issue: The connectsTo 'signalGroup' DE_SignalGroupID is missing" + }, + { + "message": "CTI-4501 conformance issue: The connectsTo 'connectingLane.maneuver' DE_AllowedManeuver is missing" + }, + { + "message": "CTI-4501 conformance issue: The laneSet 'maneuvers' DE_AllowedManeuvers is missing" + }, + { + "message": "CTI-4501 conformance issue: The intersections 'refPoint.elevation' DE_Elevation is missing" + } + ], + "laneWidth": 366, + "speedLimits": [ + { + "type": "VEHICLEMAXSPEED", + "speed": 700 + } + ], + "mapSource": "RSU", + "timeStamp": "2025-08-01T15:07:54.8Z" + } +} \ No newline at end of file diff --git a/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json b/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json deleted file mode 100644 index af91ff7..0000000 --- a/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference-1-hour-later.json +++ /dev/null @@ -1,3443 +0,0 @@ -{ - "mapFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": 2, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911523, - 39.5953376 - ], - [ - -105.0899239, - 39.5953231 - ], - [ - -105.0896005, - 39.5953332 - ], - [ - -105.0888831, - 39.595317 - ], - [ - -105.088108, - 39.5953159 - ], - [ - -105.0876637, - 39.5953153 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2225, - 808 - ], - "delevation": -10 - }, - { - "delta": [ - 10517, - -161 - ], - "delevation": -60 - }, - { - "delta": [ - 2769, - 112 - ], - "delevation": -10 - }, - { - "delta": [ - 6142, - -180 - ], - "delevation": -30 - }, - { - "delta": [ - 6636, - -12 - ], - "delevation": -20 - }, - { - "delta": [ - 3804, - -7 - ] - } - ], - "laneId": 2, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 3, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911527, - 39.5953113 - ], - [ - -105.0908101, - 39.5953039 - ], - [ - -105.0900791, - 39.5952962 - ], - [ - -105.0896801, - 39.5952874 - ], - [ - -105.0888781, - 39.5952839 - ], - [ - -105.0885678, - 39.5952789 - ], - [ - -105.0880704, - 39.5952849 - ], - [ - -105.0876638, - 39.5952849 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2222, - 515 - ], - "delevation": -10 - }, - { - "delta": [ - 2933, - -82 - ], - "delevation": -10 - }, - { - "delta": [ - 6259, - -85 - ], - "delevation": -40 - }, - { - "delta": [ - 3416, - -98 - ], - "delevation": -20 - }, - { - "delta": [ - 6867, - -39 - ], - "delevation": -30 - }, - { - "delta": [ - 2657, - -55 - ], - "delevation": -10 - }, - { - "delta": [ - 4259, - 67 - ], - "delevation": -10 - }, - { - "delta": [ - 3481, - 0 - ] - } - ], - "laneId": 3, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 1, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911535, - 39.5953745 - ], - [ - -105.0899328, - 39.5953544 - ], - [ - -105.0897165, - 39.5953447 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2215, - 1218 - ] - }, - { - "delta": [ - 10451, - -223 - ], - "delevation": -70 - }, - { - "delta": [ - 1852, - -108 - ], - "delevation": -10 - } - ], - "laneId": 1, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 4, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911537, - 39.5952537 - ], - [ - -105.0903143, - 39.5952555 - ], - [ - -105.0902511, - 39.5952591 - ], - [ - -105.0900995, - 39.5952797 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2213, - -124 - ], - "delevation": -10 - }, - { - "delta": [ - 7187, - 20 - ], - "delevation": -40 - }, - { - "delta": [ - 541, - 40 - ], - "delevation": -10 - }, - { - "delta": [ - 1298, - 229 - ] - } - ], - "laneId": 4, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 6, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911474, - 39.5951732 - ], - [ - -105.0911048, - 39.5951738 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2267, - -1019 - ], - "delevation": -10 - }, - { - "delta": [ - 365, - 7 - ] - } - ], - "laneId": 6, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 5, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911474, - 39.5952053 - ], - [ - -105.0911079, - 39.5952053 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2267, - -662 - ], - "delevation": -10 - }, - { - "delta": [ - 338, - 0 - ] - } - ], - "laneId": 5, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 7, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911443, - 39.5951332 - ], - [ - -105.0911017, - 39.5951356 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2294, - -1463 - ], - "delevation": -10 - }, - { - "delta": [ - 365, - 27 - ] - } - ], - "laneId": 7, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 12, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915234, - 39.5950941 - ], - [ - -105.0915234, - 39.5950602 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -952, - -1898 - ] - }, - { - "delta": [ - 0, - -377 - ] - } - ], - "laneId": 12, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 13, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915804, - 39.5950941 - ], - [ - -105.0915796, - 39.595059 - ], - [ - -105.0915796, - 39.595059 - ], - [ - -105.0915796, - 39.5950596 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1440, - -1898 - ] - }, - { - "delta": [ - 7, - -390 - ] - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - 0, - 7 - ] - } - ], - "laneId": 13, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 10, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913299, - 39.5950922 - ], - [ - -105.09133, - 39.5944158 - ], - [ - -105.0913348, - 39.5939413 - ], - [ - -105.0913368, - 39.592921 - ], - [ - -105.0913348, - 39.5923866 - ], - [ - -105.0913348, - 39.5923866 - ], - [ - -105.0913356, - 39.592386 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 705, - -1919 - ] - }, - { - "delta": [ - -1, - -7515 - ], - "delevation": -40 - }, - { - "delta": [ - -41, - -5272 - ], - "delevation": 10 - }, - { - "delta": [ - -17, - -11337 - ] - }, - { - "delta": [ - 17, - -5938 - ], - "delevation": 10 - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - -7, - -7 - ] - } - ], - "laneId": 10, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 9, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912849, - 39.5950912 - ], - [ - -105.0912838, - 39.5946624 - ], - [ - -105.0912861, - 39.5940862 - ], - [ - -105.0912901, - 39.5933704 - ], - [ - -105.0912882, - 39.5923858 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1090, - -1930 - ], - "delevation": -10 - }, - { - "delta": [ - 9, - -4764 - ], - "delevation": -10 - }, - { - "delta": [ - -20, - -6402 - ], - "delevation": -20 - }, - { - "delta": [ - -34, - -7953 - ], - "delevation": -10 - }, - { - "delta": [ - 16, - -10940 - ], - "delevation": 20 - } - ], - "laneId": 9, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 11, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913713, - 39.5950916 - ], - [ - -105.091375, - 39.5944888 - ], - [ - -105.0913568, - 39.5942534 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 350, - -1925 - ] - }, - { - "delta": [ - -32, - -6698 - ], - "delevation": -30 - }, - { - "delta": [ - 156, - -2616 - ] - } - ], - "laneId": 11, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 8, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912303, - 39.5950889 - ], - [ - -105.0912421, - 39.5949129 - ], - [ - -105.0912427, - 39.5942475 - ], - [ - -105.0912568, - 39.5941003 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1557, - -1956 - ], - "delevation": -10 - }, - { - "delta": [ - -101, - -1956 - ] - }, - { - "delta": [ - -5, - -7393 - ], - "delevation": -40 - }, - { - "delta": [ - -121, - -1636 - ] - } - ], - "laneId": 8, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 15, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916931, - 39.5951733 - ], - [ - -105.0927839, - 39.5951756 - ], - [ - -105.0941732, - 39.5951722 - ], - [ - -105.0952027, - 39.5951734 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2405, - -1018 - ], - "delevation": 10 - }, - { - "delta": [ - -9339, - 26 - ], - "delevation": 30 - }, - { - "delta": [ - -11895, - -38 - ], - "delevation": 50 - }, - { - "delta": [ - -8814, - 13 - ] - } - ], - "laneId": 15, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 16, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916852, - 39.5952059 - ], - [ - -105.0931135, - 39.5952073 - ], - [ - -105.0944406, - 39.595204 - ], - [ - -105.0952041, - 39.5952041 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2337, - -656 - ], - "delevation": 10 - }, - { - "delta": [ - -12229, - 15 - ], - "delevation": 50 - }, - { - "delta": [ - -11362, - -37 - ], - "delevation": 30 - }, - { - "delta": [ - -6537, - 1 - ] - } - ], - "laneId": 16, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 17, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916853, - 39.5952393 - ], - [ - -105.0927239, - 39.5952377 - ], - [ - -105.0941207, - 39.5952375 - ], - [ - -105.0943034, - 39.5952213 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2338, - -284 - ], - "delevation": 10 - }, - { - "delta": [ - -8892, - -18 - ], - "delevation": 30 - }, - { - "delta": [ - -11959, - -2 - ], - "delevation": 50 - }, - { - "delta": [ - -1564, - -180 - ] - } - ], - "laneId": 17, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 14, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916926, - 39.5951407 - ], - [ - -105.0940224, - 39.5951414 - ], - [ - -105.095203, - 39.5951408 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2401, - -1380 - ], - "delevation": 10 - }, - { - "delta": [ - -19947, - 8 - ], - "delevation": 80 - }, - { - "delta": [ - -10108, - -7 - ] - } - ], - "laneId": 14, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 18, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916766, - 39.595308 - ], - [ - -105.0917443, - 39.5953067 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2264, - 479 - ], - "delevation": 20 - }, - { - "delta": [ - -580, - -14 - ] - } - ], - "laneId": 18, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 19, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916758, - 39.5953365 - ], - [ - -105.0917363, - 39.5953365 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2257, - 796 - ], - "delevation": 20 - }, - { - "delta": [ - -518, - 0 - ] - } - ], - "laneId": 19, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 20, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916734, - 39.5953755 - ], - [ - -105.0917299, - 39.5953755 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2236, - 1229 - ], - "delevation": 20 - }, - { - "delta": [ - -484, - 0 - ] - } - ], - "laneId": 20, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 23, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.091519, - 39.5954362 - ], - [ - -105.0914927, - 39.5965421 - ], - [ - -105.091488, - 39.5974092 - ], - [ - -105.0914843, - 39.5981324 - ], - [ - -105.0914843, - 39.5981324 - ], - [ - -105.0914851, - 39.5981349 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -914, - 1903 - ], - "delevation": 20 - }, - { - "delta": [ - 225, - 12288 - ], - "delevation": 30 - }, - { - "delta": [ - 40, - 9634 - ], - "delevation": -20 - }, - { - "delta": [ - 32, - 8035 - ], - "delevation": -30 - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - -7, - 28 - ] - } - ], - "laneId": 23, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 22, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915548, - 39.5954372 - ], - [ - -105.0915441, - 39.59638 - ], - [ - -105.0915337, - 39.5974224 - ], - [ - -105.0915281, - 39.5981345 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1221, - 1914 - ], - "delevation": 20 - }, - { - "delta": [ - 92, - 10475 - ], - "delevation": 30 - }, - { - "delta": [ - 89, - 11582 - ], - "delevation": -20 - }, - { - "delta": [ - 48, - 7912 - ], - "delevation": -30 - } - ], - "laneId": 22, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 21, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916048, - 39.5954391 - ], - [ - -105.0916029, - 39.5957255 - ], - [ - -105.0916004, - 39.5962647 - ], - [ - -105.0915885, - 39.5966976 - ], - [ - -105.0915786, - 39.5977599 - ], - [ - -105.0915764, - 39.5981344 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1649, - 1935 - ], - "delevation": 20 - }, - { - "delta": [ - 16, - 3182 - ], - "delevation": 10 - }, - { - "delta": [ - 21, - 5991 - ], - "delevation": 20 - }, - { - "delta": [ - 102, - 4810 - ] - }, - { - "delta": [ - 85, - 11803 - ], - "delevation": -30 - }, - { - "delta": [ - 19, - 4161 - ], - "delevation": -20 - } - ], - "laneId": 21, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 24, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914747, - 39.5954382 - ], - [ - -105.0914714, - 39.5958506 - ], - [ - -105.0914611, - 39.596192 - ], - [ - -105.0914778, - 39.5963599 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -535, - 1926 - ], - "delevation": 20 - }, - { - "delta": [ - 28, - 4582 - ], - "delevation": 10 - }, - { - "delta": [ - 88, - 3793 - ], - "delevation": 10 - }, - { - "delta": [ - -143, - 1866 - ], - "delevation": 10 - } - ], - "laneId": 24, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 25, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914371, - 39.5954371 - ], - [ - -105.0914355, - 39.5958506 - ], - [ - -105.0914461, - 39.596052 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -213, - 1913 - ], - "delevation": 20 - }, - { - "delta": [ - 14, - 4594 - ], - "delevation": 10 - }, - { - "delta": [ - -91, - 2238 - ], - "delevation": 10 - } - ], - "laneId": 25, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 26, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913276, - 39.5954361 - ], - [ - -105.0913284, - 39.5954678 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 724, - 1902 - ], - "delevation": 10 - }, - { - "delta": [ - -7, - 352 - ], - "delevation": 10 - } - ], - "laneId": 26, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 27, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912831, - 39.5954348 - ], - [ - -105.0912839, - 39.5954647 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1105, - 1888 - ], - "delevation": 10 - }, - { - "delta": [ - -7, - 332 - ], - "delevation": 10 - } - ], - "laneId": 27, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 28, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912264, - 39.5954336 - ], - [ - -105.091228, - 39.5954647 - ], - [ - -105.091228, - 39.5954653 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1591, - 1874 - ], - "delevation": 10 - }, - { - "delta": [ - -14, - 346 - ] - }, - { - "delta": [ - 0, - 7 - ] - } - ], - "laneId": 28, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - } - ] - }, - "connectingLanesFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": "2-19", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911523, - 39.5953376 - ], - [ - -105.0916758, - 39.5953365 - ] - ] - }, - "properties": { - "signalGroupId": 4, - "ingressLaneId": 2, - "egressLaneId": 19 - } - }, - { - "type": "Feature", - "id": "3-18", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911527, - 39.5953113 - ], - [ - -105.0916766, - 39.595308 - ] - ] - }, - "properties": { - "signalGroupId": 4, - "ingressLaneId": 3, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "1-28", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911535, - 39.5953745 - ], - [ - -105.0912264, - 39.5954336 - ] - ] - }, - "properties": { - "ingressLaneId": 1, - "egressLaneId": 28 - } - }, - { - "type": "Feature", - "id": "4-12", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911537, - 39.5952537 - ], - [ - -105.0915234, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 7, - "ingressLaneId": 4, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "10-26", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913299, - 39.5950922 - ], - [ - -105.0913276, - 39.5954361 - ] - ] - }, - "properties": { - "signalGroupId": 6, - "ingressLaneId": 10, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "9-27", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912849, - 39.5950912 - ], - [ - -105.0912831, - 39.5954348 - ] - ] - }, - "properties": { - "signalGroupId": 6, - "ingressLaneId": 9, - "egressLaneId": 27 - } - }, - { - "type": "Feature", - "id": "11-18", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913713, - 39.5950916 - ], - [ - -105.0916766, - 39.595308 - ] - ] - }, - "properties": { - "signalGroupId": 1, - "ingressLaneId": 11, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "8-7", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912303, - 39.5950889 - ], - [ - -105.0911443, - 39.5951332 - ] - ] - }, - "properties": { - "ingressLaneId": 8, - "egressLaneId": 7 - } - }, - { - "type": "Feature", - "id": "15-6", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916931, - 39.5951733 - ], - [ - -105.0911474, - 39.5951732 - ] - ] - }, - "properties": { - "signalGroupId": 8, - "ingressLaneId": 15, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "16-5", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916852, - 39.5952059 - ], - [ - -105.0911474, - 39.5952053 - ] - ] - }, - "properties": { - "signalGroupId": 8, - "ingressLaneId": 16, - "egressLaneId": 5 - } - }, - { - "type": "Feature", - "id": "17-26", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916853, - 39.5952393 - ], - [ - -105.0913276, - 39.5954361 - ] - ] - }, - "properties": { - "signalGroupId": 3, - "ingressLaneId": 17, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "14-13", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916926, - 39.5951407 - ], - [ - -105.0915804, - 39.5950941 - ] - ] - }, - "properties": { - "ingressLaneId": 14, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "23-12", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.091519, - 39.5954362 - ], - [ - -105.0915234, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 2, - "ingressLaneId": 23, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "22-13", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915548, - 39.5954372 - ], - [ - -105.0915804, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 2, - "ingressLaneId": 22, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "21-20", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916048, - 39.5954391 - ], - [ - -105.0916734, - 39.5953755 - ] - ] - }, - "properties": { - "ingressLaneId": 21, - "egressLaneId": 20 - } - }, - { - "type": "Feature", - "id": "24-6", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914747, - 39.5954382 - ], - [ - -105.0911474, - 39.5951732 - ] - ] - }, - "properties": { - "signalGroupId": 5, - "ingressLaneId": 24, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "25-5", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914371, - 39.5954371 - ], - [ - -105.0911474, - 39.5952053 - ] - ] - }, - "properties": { - "signalGroupId": 5, - "ingressLaneId": 25, - "egressLaneId": 5 - } - } - ] - }, - "properties": { - "schemaVersion": 1, - "messageType": "MAP", - "odeReceivedAt": "2025-02-01T00:36:23.542Z", - "originIp": "172.20.0.1", - "intersectionId": 12110, - "msgIssueRevision": 0, - "revision": 0, - "refPoint": { - "latitude": 39.5952649, - "longitude": -105.0914122, - "elevation": 1677 - }, - "cti4501Conformant": false, - "validationMessages": [ - { - "message": "$.payload.data.intersections.intersectionGeometry[0].id.region: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].id", - "schemaPath": "#/$defs/J2735IntersectionReferenceID/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[2].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[2].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[12].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[12].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[16].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[16].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[22].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[22].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].speedLimits: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0]", - "schemaPath": "#/$defs/J2735IntersectionGeometry/required" - } - ], - "laneWidth": 366, - "mapSource": "RSU", - "timeStamp": "2025-02-01T00:36:23.542Z" - } - } \ No newline at end of file diff --git a/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference.json b/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference.json index fdf4a97..5e1b7ce 100644 --- a/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference.json +++ b/jpo-deduplicator/src/test/resources/json/processed_map/sample.processed_map-reference.json @@ -1,3443 +1,3119 @@ { "mapFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": 2, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911523, - 39.5953376 - ], - [ - -105.0899239, - 39.5953231 - ], - [ - -105.0896005, - 39.5953332 - ], - [ - -105.0888831, - 39.595317 - ], - [ - -105.088108, - 39.5953159 - ], - [ - -105.0876637, - 39.5953153 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2225, - 808 - ], - "delevation": -10 - }, - { - "delta": [ - 10517, - -161 - ], - "delevation": -60 - }, - { - "delta": [ - 2769, - 112 - ], - "delevation": -10 - }, - { - "delta": [ - 6142, - -180 - ], - "delevation": -30 - }, - { - "delta": [ - 6636, - -12 - ], - "delevation": -20 - }, - { - "delta": [ - 3804, - -7 - ] - } - ], - "laneId": 2, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": 2, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79574771374223, + 40.37685433004563 + ], + [ + -111.79457362498155, + 40.37684929004059 + ], + [ + -111.79437715592712, + 40.37684416003546 + ], + [ + -111.79419817180518, + 40.37682985002115 + ], + [ + -111.79405687479898, + 40.376808429999734 + ], + [ + -111.7939236114442, + 40.37677980997111 + ], + [ + -111.79379306539413, + 40.37674200993331 + ], + [ + -111.79368142200217, + 40.37670420989551 + ], + [ + -111.7935428425045, + 40.376648049839346 + ], + [ + -111.79347420258887, + 40.37661132980263 + ] + ] }, - "signalGroup": 4, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 3, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911527, - 39.5953113 - ], - [ - -105.0908101, - 39.5953039 - ], - [ - -105.0900791, - 39.5952962 - ], - [ - -105.0896801, - 39.5952874 - ], - [ - -105.0888781, - 39.5952839 - ], - [ - -105.0885678, - 39.5952789 - ], - [ - -105.0880704, - 39.5952849 - ], - [ - -105.0876638, - 39.5952849 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2222, - 515 - ], - "delevation": -10 - }, - { - "delta": [ - 2933, - -82 - ], - "delevation": -10 - }, - { - "delta": [ - 6259, - -85 - ], - "delevation": -40 - }, - { - "delta": [ - 3416, - -98 - ], - "delevation": -20 - }, - { - "delta": [ - 6867, - -39 - ], - "delevation": -30 - }, - { - "delta": [ - 2657, - -55 - ], - "delevation": -10 - }, - { - "delta": [ - 4259, - 67 - ], - "delevation": -10 - }, - { - "delta": [ - 3481, - 0 - ] - } - ], - "laneId": 3, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 1460, + 507 + ] + }, + { + "delta": [ + 9938, + -56 + ] + }, + { + "delta": [ + 1663, + -57 + ] + }, + { + "delta": [ + 1515, + -159 + ] + }, + { + "delta": [ + 1196, + -238 + ] + }, + { + "delta": [ + 1128, + -318 + ] + }, + { + "delta": [ + 1105, + -420 + ] + }, + { + "delta": [ + 945, + -420 + ] + }, + { + "delta": [ + 1173, + -624 + ] + }, + { + "delta": [ + 581, + -408 + ] + } + ], + "laneId": 2, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 14, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 3, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79575220311058, + 40.376821570012865 + ], + [ + -111.79457551581227, + 40.37681698000827 + ], + [ + -111.79438247294937, + 40.37681239000368 + ], + [ + -111.79420620616122, + 40.37679915999045 + ], + [ + -111.79406762646826, + 40.37677818996948 + ], + [ + -111.79393849811595, + 40.37675064994194 + ], + [ + -111.7938126777692, + 40.37671437990567 + ], + [ + -111.79370304282185, + 40.37667612986742 + ], + [ + -111.79357048857497, + 40.37662149981279 + ], + [ + -111.79349913144468, + 40.376585769777066 + ] + ] }, - "signalGroup": 4, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 1, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911535, - 39.5953745 - ], - [ - -105.0899328, - 39.5953544 - ], - [ - -105.0897165, - 39.5953447 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2215, - 1218 - ] - }, - { - "delta": [ - 10451, - -223 - ], - "delevation": -70 - }, - { - "delta": [ - 1852, - -108 - ], - "delevation": -10 - } - ], - "laneId": 1, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 1422, + 143 + ] + }, + { + "delta": [ + 9960, + -51 + ] + }, + { + "delta": [ + 1634, + -51 + ] + }, + { + "delta": [ + 1492, + -147 + ] + }, + { + "delta": [ + 1173, + -233 + ] + }, + { + "delta": [ + 1093, + -306 + ] + }, + { + "delta": [ + 1065, + -403 + ] + }, + { + "delta": [ + 928, + -425 + ] + }, + { + "delta": [ + 1122, + -607 + ] + }, + { + "delta": [ + 604, + -397 + ] + } + ], + "laneId": 3, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 1, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79574216110242, + 40.37688637007767 + ], + [ + -111.79457220673274, + 40.37688025007155 + ], + [ + -111.79437514688104, + 40.37686288005418 + ] + ] }, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 4, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911537, - 39.5952537 - ], - [ - -105.0903143, - 39.5952555 - ], - [ - -105.0902511, - 39.5952591 - ], - [ - -105.0900995, - 39.5952797 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2213, - -124 - ], - "delevation": -10 - }, - { - "delta": [ - 7187, - 20 - ], - "delevation": -40 - }, - { - "delta": [ - 541, - 40 - ], - "delevation": -10 - }, - { - "delta": [ - 1298, - 229 - ] - } - ], - "laneId": 4, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 1507, + 863 + ] + }, + { + "delta": [ + 9903, + -68 + ] + }, + { + "delta": [ + 1668, + -193 + ] + } + ], + "laneId": 1, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 18, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 12 + }, + { + "connectingLane": { + "lane": 19, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 12 + } + ] + } + }, + { + "type": "Feature", + "id": 4, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79576094556474, + 40.37678988998119 + ], + [ + -111.79509427455045, + 40.37678682997813 + ], + [ + -111.79497991383585, + 40.37680005999136 + ] + ] }, - "signalGroup": 7, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 6, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911474, - 39.5951732 - ], - [ - -105.0911048, - 39.5951738 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2267, - -1019 - ], - "delevation": -10 - }, - { - "delta": [ - 365, - 7 - ] - } - ], - "laneId": 6, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 5, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911474, - 39.5952053 - ], - [ - -105.0911079, - 39.5952053 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2267, - -662 - ], - "delevation": -10 - }, - { - "delta": [ - 338, - 0 - ] - } - ], - "laneId": 5, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 7, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911443, - 39.5951332 - ], - [ - -105.0911017, - 39.5951356 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 2294, - -1463 - ], - "delevation": -10 - }, - { - "delta": [ - 365, - 27 - ] - } - ], - "laneId": 7, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 12, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915234, - 39.5950941 - ], - [ - -105.0915234, - 39.5950602 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -952, - -1898 - ] - }, - { - "delta": [ - 0, - -377 - ] - } - ], - "laneId": 12, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 13, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915804, - 39.5950941 - ], - [ - -105.0915796, - 39.595059 - ], - [ - -105.0915796, - 39.595059 - ], - [ - -105.0915796, - 39.5950596 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1440, - -1898 - ] - }, - { - "delta": [ - 7, - -390 - ] - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - 0, - 7 - ] - } - ], - "laneId": 13, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 10, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913299, - 39.5950922 - ], - [ - -105.09133, - 39.5944158 - ], - [ - -105.0913348, - 39.5939413 - ], - [ - -105.0913368, - 39.592921 - ], - [ - -105.0913348, - 39.5923866 - ], - [ - -105.0913348, - 39.5923866 - ], - [ - -105.0913356, - 39.592386 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 705, - -1919 - ] - }, - { - "delta": [ - -1, - -7515 - ], - "delevation": -40 - }, - { - "delta": [ - -41, - -5272 - ], - "delevation": 10 - }, - { - "delta": [ - -17, - -11337 - ] - }, - { - "delta": [ - 17, - -5938 - ], - "delevation": 10 - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - -7, - -7 - ] - } - ], - "laneId": 10, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 1348, + -209 + ] + }, + { + "delta": [ + 5643, + -34 + ] + }, + { + "delta": [ + 968, + 147 + ] + } + ], + "laneId": 4, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 5 + } + ] + } + }, + { + "type": "Feature", + "id": 5, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79578315612396, + 40.376754159945456 + ], + [ + -111.79572325854731, + 40.376753619944914 + ] + ] }, - "signalGroup": 6, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 9, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912849, - 39.5950912 - ], - [ - -105.0912838, - 39.5946624 - ], - [ - -105.0912861, - 39.5940862 - ], - [ - -105.0912901, - 39.5933704 - ], - [ - -105.0912882, - 39.5923858 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1090, - -1930 - ], - "delevation": -10 - }, - { - "delta": [ - 9, - -4764 - ], - "delevation": -10 - }, - { - "delta": [ - -20, - -6402 - ], - "delevation": -20 - }, - { - "delta": [ - -34, - -7953 - ], - "delevation": -10 - }, - { - "delta": [ - 16, - -10940 - ], - "delevation": 20 - } - ], - "laneId": 9, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 1160, + -606 + ] + }, + { + "delta": [ + 507, + -6 + ] + } + ], + "laneId": 5, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 6, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.7957885906225, + 40.3767204999118 + ], + [ + -111.79572668467677, + 40.376719959911256 + ] + ] }, - "signalGroup": 6, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 11, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913713, - 39.5950916 - ], - [ - -105.091375, - 39.5944888 - ], - [ - -105.0913568, - 39.5942534 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 350, - -1925 - ] - }, - { - "delta": [ - -32, - -6698 - ], - "delevation": -30 - }, - { - "delta": [ - 156, - -2616 - ] - } - ], - "laneId": 11, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 1114, + -980 + ] + }, + { + "delta": [ + 524, + -6 + ] + } + ], + "laneId": 6, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 7, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79587802356573, + 40.37664390983521 + ], + [ + -111.79588948324114, + 40.37573778892909 + ] + ] }, - "signalGroup": 1, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 8, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912303, - 39.5950889 - ], - [ - -105.0912421, - 39.5949129 - ], - [ - -105.0912427, - 39.5942475 - ], - [ - -105.0912568, - 39.5941003 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1557, - -1956 - ], - "delevation": -10 - }, - { - "delta": [ - -101, - -1956 - ] - }, - { - "delta": [ - -5, - -7393 - ], - "delevation": -40 - }, - { - "delta": [ - -121, - -1636 - ] - } - ], - "laneId": 8, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 357, + -1831 + ] + }, + { + "delta": [ + -97, + -10068 + ] + } + ], + "laneId": 7, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 6, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + }, + { + "connectingLane": { + "lane": 18, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 4 + }, + { + "connectingLane": { + "lane": 19, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 4 + }, + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + } + ] + } + }, + { + "type": "Feature", + "id": 8, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79591925486982, + 40.376643999835295 + ], + [ + -111.79592209025343, + 40.376445459636756 + ], + [ + -111.79590590498636, + 40.37634798953928 + ] + ] }, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 15, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916931, - 39.5951733 - ], - [ - -105.0927839, - 39.5951756 - ], - [ - -105.0941732, - 39.5951722 - ], - [ - -105.0952027, - 39.5951734 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2405, - -1018 - ], - "delevation": 10 - }, - { - "delta": [ - -9339, - 26 - ], - "delevation": 30 - }, - { - "delta": [ - -11895, - -38 - ], - "delevation": 50 - }, - { - "delta": [ - -8814, - 13 - ] - } - ], - "laneId": 15, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + 8, + -1830 + ] + }, + { + "delta": [ + -24, + -2206 + ] + }, + { + "delta": [ + 137, + -1083 + ] + } + ], + "laneId": 8, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 7 + }, + { + "connectingLane": { + "lane": 14, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 7 + } + ] + } + }, + { + "type": "Feature", + "id": 9, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79598246045057, + 40.37665497984628 + ], + [ + -111.79597667154142, + 40.37660880980011 + ] + ] }, - "signalGroup": 8, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 16, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916852, - 39.5952059 - ], - [ - -105.0931135, - 39.5952073 - ], - [ - -105.0944406, - 39.595204 - ], - [ - -105.0952041, - 39.5952041 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2337, - -656 - ], - "delevation": 10 - }, - { - "delta": [ - -12229, - 15 - ], - "delevation": 50 - }, - { - "delta": [ - -11362, - -37 - ], - "delevation": 30 - }, - { - "delta": [ - -6537, - 1 - ] - } - ], - "laneId": 16, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -527, + -1708 + ] + }, + { + "delta": [ + 49, + -513 + ] + } + ], + "laneId": 9, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 4, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 11, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609953845157, + 40.37676036995167 + ], + [ + -111.79741492243544, + 40.37676864995995 + ] + ] }, - "signalGroup": 8, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 17, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916853, - 39.5952393 - ], - [ - -105.0927239, - 39.5952377 - ], - [ - -105.0941207, - 39.5952375 - ], - [ - -105.0943034, - 39.5952213 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2338, - -284 - ], - "delevation": 10 - }, - { - "delta": [ - -8892, - -18 - ], - "delevation": 30 - }, - { - "delta": [ - -11959, - -2 - ], - "delevation": 50 - }, - { - "delta": [ - -1564, - -180 - ] - } - ], - "laneId": 17, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -1518, + -537 + ] + }, + { + "delta": [ + -11134, + 92 + ] + } + ], + "laneId": 11, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 10, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609965659284, + 40.37672877992008 + ], + [ + -111.79741492181886, + 40.37673543992674 + ] + ] }, - "signalGroup": 3, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 14, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916926, - 39.5951407 - ], - [ - -105.0940224, - 39.5951414 - ], - [ - -105.095203, - 39.5951408 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2401, - -1380 - ], - "delevation": 10 - }, - { - "delta": [ - -19947, - 8 - ], - "delevation": 80 - }, - { - "delta": [ - -10108, - -7 - ] - } - ], - "laneId": 14, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -1519, + -888 + ] + }, + { + "delta": [ + -11133, + 74 + ] + } + ], + "laneId": 10, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 6, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 12, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609965659284, + 40.37679204998335 + ], + [ + -111.79671930741368, + 40.37679456998587 + ], + [ + -111.79683036018649, + 40.3767843999757 + ] + ] }, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 18, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916766, - 39.595308 - ], - [ - -105.0917443, - 39.5953067 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2264, - 479 - ], - "delevation": 20 - }, - { - "delta": [ - -580, - -14 - ] - } - ], - "laneId": 18, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 19, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916758, - 39.5953365 - ], - [ - -105.0917363, - 39.5953365 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2257, - 796 - ], - "delevation": 20 - }, - { - "delta": [ - -518, - 0 - ] - } - ], - "laneId": 19, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 20, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916734, - 39.5953755 - ], - [ - -105.0917299, - 39.5953755 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -2236, - 1229 - ], - "delevation": 20 - }, - { - "delta": [ - -484, - 0 - ] - } - ], - "laneId": 20, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 23, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.091519, - 39.5954362 - ], - [ - -105.0914927, - 39.5965421 - ], - [ - -105.091488, - 39.5974092 - ], - [ - -105.0914843, - 39.5981324 - ], - [ - -105.0914843, - 39.5981324 - ], - [ - -105.0914851, - 39.5981349 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -914, - 1903 - ], - "delevation": 20 - }, - { - "delta": [ - 225, - 12288 - ], - "delevation": 30 - }, - { - "delta": [ - 40, - 9634 - ], - "delevation": -20 - }, - { - "delta": [ - 32, - 8035 - ], - "delevation": -30 - }, - { - "delta": [ - 0, - 0 - ] - }, - { - "delta": [ - -7, - 28 - ] - } - ], - "laneId": 23, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -1519, + -185 + ] + }, + { + "delta": [ + -5245, + 28 + ] + }, + { + "delta": [ + -940, + -113 + ] + } + ], + "laneId": 12, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 18, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 1 + }, + { + "connectingLane": { + "lane": 19, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 1 + } + ] + } + }, + { + "type": "Feature", + "id": 13, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79607957257653, + 40.37682472001602 + ], + [ + -111.79614277817231, + 40.37682571001701 + ] + ] }, - "signalGroup": 2, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 22, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915548, - 39.5954372 - ], - [ - -105.0915441, - 39.59638 - ], - [ - -105.0915337, - 39.5974224 - ], - [ - -105.0915281, - 39.5981345 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1221, - 1914 - ], - "delevation": 20 - }, - { - "delta": [ - 92, - 10475 - ], - "delevation": 30 - }, - { - "delta": [ - 89, - 11582 - ], - "delevation": -20 - }, - { - "delta": [ - 48, - 7912 - ], - "delevation": -30 - } - ], - "laneId": 22, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -1349, + 178 + ] + }, + { + "delta": [ + -535, + 11 + ] + } + ], + "laneId": 13, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 6, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 14, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79607957257653, + 40.37685847004977 + ], + [ + -111.79614218749718, + 40.37685901005031 + ] + ] }, - "signalGroup": 2, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 21, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916048, - 39.5954391 - ], - [ - -105.0916029, - 39.5957255 - ], - [ - -105.0916004, - 39.5962647 - ], - [ - -105.0915885, - 39.5966976 - ], - [ - -105.0915786, - 39.5977599 - ], - [ - -105.0915764, - 39.5981344 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -1649, - 1935 - ], - "delevation": 20 - }, - { - "delta": [ - 16, - 3182 - ], - "delevation": 10 - }, - { - "delta": [ - 21, - 5991 - ], - "delevation": 20 - }, - { - "delta": [ - 102, - 4810 - ] - }, - { - "delta": [ - 85, - 11803 - ], - "delevation": -30 - }, - { - "delta": [ - 19, - 4161 - ], - "delevation": -20 - } - ], - "laneId": 21, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -1349, + 553 + ] + }, + { + "delta": [ + -530, + 6 + ] + } + ], + "laneId": 14, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 6, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 15, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79599817323981, + 40.376953870145165 + ], + [ + -111.7959941564279, + 40.37758180077309 + ], + [ + -111.79595375164911, + 40.37773696092825 + ], + [ + -111.79595505122101, + 40.3778544110457 + ] + ] }, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 24, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914747, - 39.5954382 - ], - [ - -105.0914714, - 39.5958506 - ], - [ - -105.0914611, - 39.596192 - ], - [ - -105.0914778, - 39.5963599 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -535, - 1926 - ], - "delevation": 20 - }, - { - "delta": [ - 28, - 4582 - ], - "delevation": 10 - }, - { - "delta": [ - 88, - 3793 - ], - "delevation": 10 - }, - { - "delta": [ - -143, - 1866 - ], - "delevation": 10 - } - ], - "laneId": 24, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -660, + 1613 + ] + }, + { + "delta": [ + 34, + 6977 + ] + }, + { + "delta": [ + 342, + 1724 + ] + }, + { + "delta": [ + -11, + 1305 + ] + } + ], + "laneId": 15, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 7, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 14, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 18 + }, + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 8 + }, + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 18 + } + ] + } + }, + { + "type": "Feature", + "id": 16, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79595623308809, + 40.37695486014616 + ], + [ + -111.79595079857776, + 40.377576940768236 + ], + [ + -111.79593201390126, + 40.37773165092295 + ] + ] }, - "signalGroup": 5, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 25, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914371, - 39.5954371 - ], - [ - -105.0914355, - 39.5958506 - ], - [ - -105.0914461, - 39.596052 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - -213, - 1913 - ], - "delevation": 20 - }, - { - "delta": [ - 14, - 4594 - ], - "delevation": 10 - }, - { - "delta": [ - -91, - 2238 - ], - "delevation": 10 - } - ], - "laneId": 25, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } + "properties": { + "nodes": [ + { + "delta": [ + -305, + 1624 + ] + }, + { + "delta": [ + 46, + 6912 + ] + }, + { + "delta": [ + 159, + 1719 + ] + } + ], + "laneId": 16, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 7, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 6, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 3 + } + ] + } + }, + { + "type": "Feature", + "id": 17, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79591452921892, + 40.37695513014643 + ], + [ + -111.79591382036975, + 40.37757487076617 + ], + [ + -111.79592622534442, + 40.377729940921235 + ] + ] }, - "signalGroup": 5, - "connectionID": 1 - } - ] - } - }, - { - "type": "Feature", - "id": 26, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913276, - 39.5954361 - ], - [ - -105.0913284, - 39.5954678 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 724, - 1902 - ], - "delevation": 10 - }, - { - "delta": [ - -7, - 352 - ], - "delevation": 10 - } - ], - "laneId": 26, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 27, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912831, - 39.5954348 - ], - [ - -105.0912839, - 39.5954647 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1105, - 1888 - ], - "delevation": 10 - }, - { - "delta": [ - -7, - 332 - ], - "delevation": 10 - } - ], - "laneId": 27, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 28, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912264, - 39.5954336 - ], - [ - -105.091228, - 39.5954647 - ], - [ - -105.091228, - 39.5954653 - ] - ] - }, - "properties": { - "nodes": [ - { - "delta": [ - 1591, - 1874 - ], - "delevation": 10 - }, - { - "delta": [ - -14, - 346 - ] - }, - { - "delta": [ - 0, - 7 - ] - } - ], - "laneId": 28, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - } - ] + "properties": { + "nodes": [ + { + "delta": [ + 48, + 1627 + ] + }, + { + "delta": [ + 6, + 6886 + ] + }, + { + "delta": [ + -105, + 1723 + ] + } + ], + "laneId": 17, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 7, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 3 + } + ] + } + }, + { + "type": "Feature", + "id": 18, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79586975367667, + 40.37694478013608 + ], + [ + -111.79586975367667, + 40.376992300183595 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 427, + 1512 + ] + }, + { + "delta": [ + 0, + 528 + ] + } + ], + "laneId": 18, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 8, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 19, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79583076705676, + 40.37694685013815 + ], + [ + -111.79583076705676, + 40.3769959001872 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 757, + 1535 + ] + }, + { + "delta": [ + 0, + 545 + ] + } + ], + "laneId": 19, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 8, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 27, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.7957846919605, + 40.37693083012213 + ], + [ + -111.79576720702049, + 40.37693443012573 + ], + [ + -111.7957705149823, + 40.37692525011655 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1147, + 1357 + ] + }, + { + "delta": [ + 148, + 40 + ] + }, + { + "delta": [ + -28, + -102 + ] + } + ], + "laneId": 27, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 202 + }, + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 204 + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.7958172989517, + 40.376685489876785 + ], + [ + -111.7958162356822, + 40.37667054986184 + ], + [ + -111.79582899491346, + 40.37667306986436 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 871, + -1369 + ] + }, + { + "delta": [ + 9, + -166 + ] + }, + { + "delta": [ + -108, + 28 + ] + } + ], + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 204 + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 206 + } + ] + } + }, + { + "type": "Feature", + "id": 23, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79604637487897, + 40.376672079863376 + ], + [ + -111.7960665769956, + 40.376669019860316 + ], + [ + -111.79606421417505, + 40.37668188987318 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1068, + -1518 + ] + }, + { + "delta": [ + -171, + -34 + ] + }, + { + "delta": [ + 20, + 143 + ] + } + ], + "laneId": 23, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 206 + }, + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 208 + } + ] + } + }, + { + "type": "Feature", + "id": 25, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79605712573476, + 40.37691148010278 + ], + [ + -111.79606385979757, + 40.376922730114025 + ], + [ + -111.79605240007474, + 40.37692174011303 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1159, + 1142 + ] + }, + { + "delta": [ + -57, + 125 + ] + }, + { + "delta": [ + 97, + -11 + ] + } + ], + "laneId": 25, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 202 + }, + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 208 + } + ] + } + }, + { + "type": "Feature", + "id": 20, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.7957722871269, + 40.37692282011412 + ], + [ + -111.79581907115002, + 40.37668683987814 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 1252, + 1268 + ] + }, + { + "delta": [ + -396, + -2622 + ] + } + ], + "laneId": 20, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": true, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 22, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79583312988221, + 40.376672529863825 + ], + [ + -111.79604436605044, + 40.37667306986437 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + 737, + -1513 + ] + }, + { + "delta": [ + -1788, + 6 + ] + } + ], + "laneId": 22, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": true, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 24, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79606315093966, + 40.37668278987409 + ], + [ + -111.79605712574602, + 40.376910490101785 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1210, + -1399 + ] + }, + { + "delta": [ + 51, + 2530 + ] + } + ], + "laneId": 24, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 26, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79604980097587, + 40.3769212001125 + ], + [ + -111.79578882646929, + 40.37693038012168 + ] + ] + }, + "properties": { + "nodes": [ + { + "delta": [ + -1097, + 1250 + ] + }, + { + "delta": [ + 2209, + 102 + ] + } + ], + "laneId": 26, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": true, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] }, "connectingLanesFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": "2-19", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911523, - 39.5953376 - ], - [ - -105.0916758, - 39.5953365 - ] - ] - }, - "properties": { - "signalGroupId": 4, - "ingressLaneId": 2, - "egressLaneId": 19 - } - }, - { - "type": "Feature", - "id": "3-18", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911527, - 39.5953113 - ], - [ - -105.0916766, - 39.595308 - ] - ] - }, - "properties": { - "signalGroupId": 4, - "ingressLaneId": 3, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "1-28", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911535, - 39.5953745 - ], - [ - -105.0912264, - 39.5954336 - ] - ] - }, - "properties": { - "ingressLaneId": 1, - "egressLaneId": 28 - } - }, - { - "type": "Feature", - "id": "4-12", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0911537, - 39.5952537 - ], - [ - -105.0915234, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 7, - "ingressLaneId": 4, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "10-26", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913299, - 39.5950922 - ], - [ - -105.0913276, - 39.5954361 - ] - ] - }, - "properties": { - "signalGroupId": 6, - "ingressLaneId": 10, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "9-27", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912849, - 39.5950912 - ], - [ - -105.0912831, - 39.5954348 - ] - ] - }, - "properties": { - "signalGroupId": 6, - "ingressLaneId": 9, - "egressLaneId": 27 - } - }, - { - "type": "Feature", - "id": "11-18", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0913713, - 39.5950916 - ], - [ - -105.0916766, - 39.595308 - ] - ] - }, - "properties": { - "signalGroupId": 1, - "ingressLaneId": 11, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "8-7", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0912303, - 39.5950889 - ], - [ - -105.0911443, - 39.5951332 - ] - ] - }, - "properties": { - "ingressLaneId": 8, - "egressLaneId": 7 - } - }, - { - "type": "Feature", - "id": "15-6", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916931, - 39.5951733 - ], - [ - -105.0911474, - 39.5951732 - ] - ] - }, - "properties": { - "signalGroupId": 8, - "ingressLaneId": 15, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "16-5", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916852, - 39.5952059 - ], - [ - -105.0911474, - 39.5952053 - ] - ] - }, - "properties": { - "signalGroupId": 8, - "ingressLaneId": 16, - "egressLaneId": 5 - } - }, - { - "type": "Feature", - "id": "17-26", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916853, - 39.5952393 - ], - [ - -105.0913276, - 39.5954361 - ] - ] - }, - "properties": { - "signalGroupId": 3, - "ingressLaneId": 17, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "14-13", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916926, - 39.5951407 - ], - [ - -105.0915804, - 39.5950941 - ] - ] - }, - "properties": { - "ingressLaneId": 14, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "23-12", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.091519, - 39.5954362 - ], - [ - -105.0915234, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 2, - "ingressLaneId": 23, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "22-13", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0915548, - 39.5954372 - ], - [ - -105.0915804, - 39.5950941 - ] - ] - }, - "properties": { - "signalGroupId": 2, - "ingressLaneId": 22, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "21-20", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0916048, - 39.5954391 - ], - [ - -105.0916734, - 39.5953755 - ] - ] - }, - "properties": { - "ingressLaneId": 21, - "egressLaneId": 20 - } - }, - { - "type": "Feature", - "id": "24-6", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914747, - 39.5954382 - ], - [ - -105.0911474, - 39.5951732 - ] - ] - }, - "properties": { - "signalGroupId": 5, - "ingressLaneId": 24, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "25-5", - "geometry": { - "type": "LineString", - "coordinates": [ - [ - -105.0914371, - 39.5954371 - ], - [ - -105.0911474, - 39.5952053 - ] - ] - }, - "properties": { - "signalGroupId": 5, - "ingressLaneId": 25, - "egressLaneId": 5 - } - } - ] + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "2-14", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79574771374223, + 40.37685433004563 + ], + [ + -111.79607957257653, + 40.37685847004977 + ] + ] + }, + "properties": { + "signalGroupId": 2, + "ingressLaneId": 2, + "egressLaneId": 14 + } + }, + { + "type": "Feature", + "id": "3-13", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79575220311058, + 40.376821570012865 + ], + [ + -111.79607957257653, + 40.37682472001602 + ] + ] + }, + "properties": { + "signalGroupId": 2, + "ingressLaneId": 3, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "1-18", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79574216110242, + 40.37688637007767 + ], + [ + -111.79586975367667, + 40.37694478013608 + ] + ] + }, + "properties": { + "signalGroupId": 12, + "ingressLaneId": 1, + "egressLaneId": 18 + } + }, + { + "type": "Feature", + "id": "1-19", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79574216110242, + 40.37688637007767 + ], + [ + -111.79583076705676, + 40.37694685013815 + ] + ] + }, + "properties": { + "signalGroupId": 12, + "ingressLaneId": 1, + "egressLaneId": 19 + } + }, + { + "type": "Feature", + "id": "4-9", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79576094556474, + 40.37678988998119 + ], + [ + -111.79598246045057, + 40.37665497984628 + ] + ] + }, + "properties": { + "signalGroupId": 5, + "ingressLaneId": 4, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "7-6", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79587802356573, + 40.37664390983521 + ], + [ + -111.7957885906225, + 40.3767204999118 + ] + ] + }, + "properties": { + "signalGroupId": 14, + "ingressLaneId": 7, + "egressLaneId": 6 + } + }, + { + "type": "Feature", + "id": "7-18", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79587802356573, + 40.37664390983521 + ], + [ + -111.79586975367667, + 40.37694478013608 + ] + ] + }, + "properties": { + "signalGroupId": 4, + "ingressLaneId": 7, + "egressLaneId": 18 + } + }, + { + "type": "Feature", + "id": "7-19", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79587802356573, + 40.37664390983521 + ], + [ + -111.79583076705676, + 40.37694685013815 + ] + ] + }, + "properties": { + "signalGroupId": 4, + "ingressLaneId": 7, + "egressLaneId": 19 + } + }, + { + "type": "Feature", + "id": "7-5", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79587802356573, + 40.37664390983521 + ], + [ + -111.79578315612396, + 40.376754159945456 + ] + ] + }, + "properties": { + "signalGroupId": 14, + "ingressLaneId": 7, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "8-13", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79591925486982, + 40.376643999835295 + ], + [ + -111.79607957257653, + 40.37682472001602 + ] + ] + }, + "properties": { + "signalGroupId": 7, + "ingressLaneId": 8, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "8-14", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79591925486982, + 40.376643999835295 + ], + [ + -111.79607957257653, + 40.37685847004977 + ] + ] + }, + "properties": { + "signalGroupId": 7, + "ingressLaneId": 8, + "egressLaneId": 14 + } + }, + { + "type": "Feature", + "id": "11-5", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609953845157, + 40.37676036995167 + ], + [ + -111.79578315612396, + 40.376754159945456 + ] + ] + }, + "properties": { + "signalGroupId": 6, + "ingressLaneId": 11, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "10-9", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609965659284, + 40.37672877992008 + ], + [ + -111.79598246045057, + 40.37665497984628 + ] + ] + }, + "properties": { + "signalGroupId": 16, + "ingressLaneId": 10, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "10-6", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609965659284, + 40.37672877992008 + ], + [ + -111.7957885906225, + 40.3767204999118 + ] + ] + }, + "properties": { + "signalGroupId": 6, + "ingressLaneId": 10, + "egressLaneId": 6 + } + }, + { + "type": "Feature", + "id": "12-18", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609965659284, + 40.37679204998335 + ], + [ + -111.79586975367667, + 40.37694478013608 + ] + ] + }, + "properties": { + "signalGroupId": 1, + "ingressLaneId": 12, + "egressLaneId": 18 + } + }, + { + "type": "Feature", + "id": "12-19", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79609965659284, + 40.37679204998335 + ], + [ + -111.79583076705676, + 40.37694685013815 + ] + ] + }, + "properties": { + "signalGroupId": 1, + "ingressLaneId": 12, + "egressLaneId": 19 + } + }, + { + "type": "Feature", + "id": "15-14", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79599817323981, + 40.376953870145165 + ], + [ + -111.79607957257653, + 40.37685847004977 + ] + ] + }, + "properties": { + "signalGroupId": 18, + "ingressLaneId": 15, + "egressLaneId": 14 + } + }, + { + "type": "Feature", + "id": "15-9", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79599817323981, + 40.376953870145165 + ], + [ + -111.79598246045057, + 40.37665497984628 + ] + ] + }, + "properties": { + "signalGroupId": 8, + "ingressLaneId": 15, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "15-13", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79599817323981, + 40.376953870145165 + ], + [ + -111.79607957257653, + 40.37682472001602 + ] + ] + }, + "properties": { + "signalGroupId": 18, + "ingressLaneId": 15, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "16-6", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79595623308809, + 40.37695486014616 + ], + [ + -111.7957885906225, + 40.3767204999118 + ] + ] + }, + "properties": { + "signalGroupId": 3, + "ingressLaneId": 16, + "egressLaneId": 6 + } + }, + { + "type": "Feature", + "id": "17-5", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -111.79591452921892, + 40.37695513014643 + ], + [ + -111.79578315612396, + 40.376754159945456 + ] + ] + }, + "properties": { + "signalGroupId": 3, + "ingressLaneId": 17, + "egressLaneId": 5 + } + } + ] }, "properties": { - "schemaVersion": 1, - "messageType": "MAP", - "odeReceivedAt": "2025-01-31T23:36:23.542Z", - "originIp": "172.20.0.1", - "intersectionId": 12110, - "msgIssueRevision": 0, - "revision": 0, - "refPoint": { - "latitude": 39.5952649, - "longitude": -105.0914122, - "elevation": 1677 - }, - "cti4501Conformant": false, - "validationMessages": [ - { - "message": "$.payload.data.intersections.intersectionGeometry[0].id.region: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].id", - "schemaPath": "#/$defs/J2735IntersectionReferenceID/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[2].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[2].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[4]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[5]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[6]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[7]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[8]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[12].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[12].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[16].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[16].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[17]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[18]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[19]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[22].connectsTo.connectsTo[0].signalGroup: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[22].connectsTo.connectsTo[0]", - "schemaPath": "#/$defs/J2735Connection/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[25]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[26]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27].maneuvers: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27].connectsTo: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0].laneSet.GenericLane[27]", - "schemaPath": "#/$defs/J2735GenericLane/required" - }, - { - "message": "$.payload.data.intersections.intersectionGeometry[0].speedLimits: is missing but it is required", - "jsonPath": "$.payload.data.intersections.intersectionGeometry[0]", - "schemaPath": "#/$defs/J2735IntersectionGeometry/required" - } - ], - "laneWidth": 366, - "mapSource": "RSU", - "timeStamp": "2025-01-31T23:36:23.542Z" + "schemaVersion": 2, + "messageType": "MAP", + "odeReceivedAt": "2025-08-01T15:05:42.572Z", + "originIp": "172.18.0.1", + "asn1": "001282AB780CC3780302071583B3869DD95048EFE5026411504DC3A7720A7D02F120D4DB5EC1728A71DDD462402DC0514F8D16010A0D0001000102DB49FB2D3693FE40B9FDF1C5BD6EC22CAC71216343610B1459703EC52E0B2556403915340243A00008B00C50680008000816C7447969BA1FF345CC4F9A2DD476D164AB8B8B115B385852CDA1F4095C58C4B421CB89CC121B0000458022834000120008B78ED7CB4D5EFF782E8473F148910006244C80030B01050680004000116A23979360B7F783F22498242500014401488680000016442D103FB7E84018886800000162D21607063FA2C07341A00029000052CA1B257F9F58AC348310007244A00011227000089052000E2C08341A00010000450101B437F41D88511278A290D40007487200038804A10D00000025F11540C313FE5816A834000400000884979CAA90500B80905800062C0A541A000290000442291055483804A148490008241A00018B0315068000400011108BA390B8380702151C78A4490000522680002201AC4340000008AEE2C827A6058807310D00000022BBA2909EE80C581EE83400052001095B3934901176822956EBC13FAE8C92438800492130001090D200122C10741A0001000044D9FCB0480BBB00144FF5B824190000CB045D06800040001141872D92006EB984F2FD760905400031012821A0000005357BD01801840404E086800000157AEFF86006210C1B0069A000400008B1EF53414A45007919A148D40065245200330305401A68001000022B672A70412AD0194870522900198916800CE0C170069A0004000088F508480AABBC08528F148B40067246200340306401A68001000022379C76038F3E82617D4523500194918800D000140068A200000B3933D06E742E1000B0034510000055C242E21048060018006882000008D18A247033CF1000D00345100000476F9C43C50C1980", + "intersectionName": "Alpine Hwy & E Main St", + "intersectionId": 6025, + "msgIssueRevision": 0, + "revision": 3, + "refPoint": { + "latitude": 40.3768087, + "longitude": -111.7959202, + "elevation": 1386.0 + }, + "cti4501Conformant": false, + "validationMessages": [ + { + "message": "CTI-4501 conformance issue: The laneSet 'connectsTo' DF_ConnectsToList is missing" + }, + { + "message": "CTI-4501 conformance issue: The intersections 'id.region' DE_RoadRegulatorID is missing" + }, + { + "message": "CTI-4501 conformance issue: The laneSet 'maneuvers' DE_AllowedManeuvers is missing" + } + ], + "laneWidth": 366, + "speedLimits": [ + { + "type": "VEHICLEMAXSPEED", + "speed": 671 + } + ], + "mapSource": "RSU", + "timeStamp": "2025-03-14T14:39:00Z" } - } \ No newline at end of file +} \ No newline at end of file diff --git a/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json b/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json index b8616d4..ac6e0e1 100644 --- a/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json +++ b/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json @@ -1,1829 +1,2880 @@ { - "mapFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": 2, - "geometry": "LINESTRING (-105.0911523 39.5953376, -105.0899239 39.5953231, -105.0896005 39.5953332, -105.0888831 39.595317, -105.088108 39.5953159, -105.0876637 39.5953153)", - "properties": { - "laneId": 2, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 3, - "geometry": "LINESTRING (-105.0911527 39.5953113, -105.0908101 39.5953039, -105.0900791 39.5952962, -105.0896801 39.5952874, -105.0888781 39.5952839, -105.0885678 39.5952789, -105.0880704 39.5952849, -105.0876638 39.5952849)", - "properties": { - "laneId": 3, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 1, - "geometry": "LINESTRING (-105.0911535 39.5953745, -105.0899328 39.5953544, -105.0897165 39.5953447)", - "properties": { - "laneId": 1, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 4, - "geometry": "LINESTRING (-105.0911537 39.5952537, -105.0903143 39.5952555, -105.0902511 39.5952591, -105.0900995 39.5952797)", - "properties": { - "laneId": 4, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 6, - "geometry": "LINESTRING (-105.0911474 39.5951732, -105.0911048 39.5951738)", - "properties": { - "laneId": 6, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 5, - "geometry": "LINESTRING (-105.0911474 39.5952053, -105.0911079 39.5952053)", - "properties": { - "laneId": 5, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 7, - "geometry": "LINESTRING (-105.0911443 39.5951332, -105.0911017 39.5951356)", - "properties": { - "laneId": 7, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 12, - "geometry": "LINESTRING (-105.0915234 39.5950941, -105.0915234 39.5950602)", - "properties": { - "laneId": 12, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 13, - "geometry": "LINESTRING (-105.0915804 39.5950941, -105.0915796 39.595059, -105.0915796 39.595059, -105.0915796 39.5950596)", - "properties": { - "laneId": 13, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 10, - "geometry": "LINESTRING (-105.0913299 39.5950922, -105.09133 39.5944158, -105.0913348 39.5939413, -105.0913368 39.592921, -105.0913348 39.5923866, -105.0913348 39.5923866, -105.0913356 39.592386)", - "properties": { - "laneId": 10, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 9, - "geometry": "LINESTRING (-105.0912849 39.5950912, -105.0912838 39.5946624, -105.0912861 39.5940862, -105.0912901 39.5933704, -105.0912882 39.5923858)", - "properties": { - "laneId": 9, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 11, - "geometry": "LINESTRING (-105.0913713 39.5950916, -105.091375 39.5944888, -105.0913568 39.5942534)", - "properties": { - "laneId": 11, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 8, - "geometry": "LINESTRING (-105.0912303 39.5950889, -105.0912421 39.5949129, -105.0912427 39.5942475, -105.0912568 39.5941003)", - "properties": { - "laneId": 8, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 15, - "geometry": "LINESTRING (-105.0916931 39.5951733, -105.0927839 39.5951756, -105.0941732 39.5951722, -105.0952027 39.5951734)", - "properties": { - "laneId": 15, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 16, - "geometry": "LINESTRING (-105.0916852 39.5952059, -105.0931135 39.5952073, -105.0944406 39.595204, -105.0952041 39.5952041)", - "properties": { - "laneId": 16, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 17, - "geometry": "LINESTRING (-105.0916853 39.5952393, -105.0927239 39.5952377, -105.0941207 39.5952375, -105.0943034 39.5952213)", - "properties": { - "laneId": 17, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 14, - "geometry": "LINESTRING (-105.0916926 39.5951407, -105.0940224 39.5951414, -105.095203 39.5951408)", - "properties": { - "laneId": 14, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 18, - "geometry": "LINESTRING (-105.0916766 39.595308, -105.0917443 39.5953067)", - "properties": { - "laneId": 18, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 19, - "geometry": "LINESTRING (-105.0916758 39.5953365, -105.0917363 39.5953365)", - "properties": { - "laneId": 19, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 20, - "geometry": "LINESTRING (-105.0916734 39.5953755, -105.0917299 39.5953755)", - "properties": { - "laneId": 20, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 23, - "geometry": "LINESTRING (-105.091519 39.5954362, -105.0914927 39.5965421, -105.091488 39.5974092, -105.0914843 39.5981324, -105.0914843 39.5981324, -105.0914851 39.5981349)", - "properties": { - "laneId": 23, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 22, - "geometry": "LINESTRING (-105.0915548 39.5954372, -105.0915441 39.59638, -105.0915337 39.5974224, -105.0915281 39.5981345)", - "properties": { - "laneId": 22, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 21, - "geometry": "LINESTRING (-105.0916048 39.5954391, -105.0916029 39.5957255, -105.0916004 39.5962647, -105.0915885 39.5966976, -105.0915786 39.5977599, -105.0915764 39.5981344)", - "properties": { - "laneId": 21, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 24, - "geometry": "LINESTRING (-105.0914747 39.5954382, -105.0914714 39.5958506, -105.0914611 39.596192, -105.0914778 39.5963599)", - "properties": { - "laneId": 24, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 25, - "geometry": "LINESTRING (-105.0914371 39.5954371, -105.0914355 39.5958506, -105.0914461 39.596052)", - "properties": { - "laneId": 25, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 26, - "geometry": "LINESTRING (-105.0913276 39.5954361, -105.0913284 39.5954678)", - "properties": { - "laneId": 26, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 27, - "geometry": "LINESTRING (-105.0912831 39.5954348, -105.0912839 39.5954647)", - "properties": { - "laneId": 27, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 28, - "geometry": "LINESTRING (-105.0912264 39.5954336, -105.091228 39.5954647, -105.091228 39.5954653)", - "properties": { - "laneId": 28, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - } - ] - }, - "connectingLanesFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": "2-19", - "geometry": "LINESTRING (-105.0911523 39.5953376, -105.0916758 39.5953365)", - "properties": { - "signalGroupId": 4, - "ingressLaneId": 2, - "egressLaneId": 19 - } - }, - { - "type": "Feature", - "id": "3-18", - "geometry": "LINESTRING (-105.0911527 39.5953113, -105.0916766 39.595308)", - "properties": { - "signalGroupId": 4, - "ingressLaneId": 3, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "1-28", - "geometry": "LINESTRING (-105.0911535 39.5953745, -105.0912264 39.5954336)", - "properties": { - "ingressLaneId": 1, - "egressLaneId": 28 - } - }, - { - "type": "Feature", - "id": "4-12", - "geometry": "LINESTRING (-105.0911537 39.5952537, -105.0915234 39.5950941)", - "properties": { - "signalGroupId": 7, - "ingressLaneId": 4, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "10-26", - "geometry": "LINESTRING (-105.0913299 39.5950922, -105.0913276 39.5954361)", - "properties": { - "signalGroupId": 6, - "ingressLaneId": 10, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "9-27", - "geometry": "LINESTRING (-105.0912849 39.5950912, -105.0912831 39.5954348)", - "properties": { - "signalGroupId": 6, - "ingressLaneId": 9, - "egressLaneId": 27 - } - }, - { - "type": "Feature", - "id": "11-18", - "geometry": "LINESTRING (-105.0913713 39.5950916, -105.0916766 39.595308)", - "properties": { - "signalGroupId": 1, - "ingressLaneId": 11, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "8-7", - "geometry": "LINESTRING (-105.0912303 39.5950889, -105.0911443 39.5951332)", - "properties": { - "ingressLaneId": 8, - "egressLaneId": 7 - } - }, - { - "type": "Feature", - "id": "15-6", - "geometry": "LINESTRING (-105.0916931 39.5951733, -105.0911474 39.5951732)", - "properties": { - "signalGroupId": 8, - "ingressLaneId": 15, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "16-5", - "geometry": "LINESTRING (-105.0916852 39.5952059, -105.0911474 39.5952053)", - "properties": { - "signalGroupId": 8, - "ingressLaneId": 16, - "egressLaneId": 5 - } - }, - { - "type": "Feature", - "id": "17-26", - "geometry": "LINESTRING (-105.0916853 39.5952393, -105.0913276 39.5954361)", - "properties": { - "signalGroupId": 3, - "ingressLaneId": 17, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "14-13", - "geometry": "LINESTRING (-105.0916926 39.5951407, -105.0915804 39.5950941)", - "properties": { - "ingressLaneId": 14, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "23-12", - "geometry": "LINESTRING (-105.091519 39.5954362, -105.0915234 39.5950941)", - "properties": { - "signalGroupId": 2, - "ingressLaneId": 23, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "22-13", - "geometry": "LINESTRING (-105.0915548 39.5954372, -105.0915804 39.5950941)", - "properties": { - "signalGroupId": 2, - "ingressLaneId": 22, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "21-20", - "geometry": "LINESTRING (-105.0916048 39.5954391, -105.0916734 39.5953755)", - "properties": { - "ingressLaneId": 21, - "egressLaneId": 20 - } - }, - { - "type": "Feature", - "id": "24-6", - "geometry": "LINESTRING (-105.0914747 39.5954382, -105.0911474 39.5951732)", - "properties": { - "signalGroupId": 5, - "ingressLaneId": 24, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "25-5", - "geometry": "LINESTRING (-105.0914371 39.5954371, -105.0911474 39.5952053)", - "properties": { - "signalGroupId": 5, - "ingressLaneId": 25, - "egressLaneId": 5 - } - } - ] - }, - "properties": { - "schemaVersion": 1, - "messageType": "MAP", - "odeReceivedAt": "2025-01-31T23:50:49.19Z", - "originIp": "172.20.0.1", - "intersectionId": 13110, - "msgIssueRevision": 0, - "revision": 0, - "refPoint": { - "latitude": 39.5952649, - "longitude": -105.0914122, - "elevation": 1677 - }, - "cti4501Conformant": false, - "laneWidth": 366, - "mapSource": "RSU", - "timeStamp": "2025-01-31T23:50:49.19Z" - } - } \ No newline at end of file + "mapFeatureCollection": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": 10, + "geometry": "LINESTRING (-84.34925148645785 33.76995371997552, -84.34997287206494 33.769951019972815, -84.35018009583929 33.769923209945006)", + "properties": { + "laneId": 10, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 3 + } + ] + } + }, + { + "type": "Feature", + "id": 11, + "geometry": "LINESTRING (-84.34925148645785 33.76992257994438, -84.34997427927831 33.76992266994447, -84.35024938661185 33.76991087993268, -84.35044589182306 33.76987775989956, -84.35063243636743 33.76983104985285, -84.35080891195743 33.769774889796686)", + "properties": { + "laneId": 11, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 12, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 9 + } + ] + } + }, + { + "type": "Feature", + "id": 9, + "geometry": "LINESTRING (-84.3492353546124 33.77002491004671, -84.34938194877772 33.770024370046166)", + "properties": { + "laneId": 9, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 6, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 12, + "geometry": "LINESTRING (-84.34911355376596 33.7697963998182, -84.34911485297224 33.76969343971524)", + "properties": { + "laneId": 12, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 13, + "geometry": "LINESTRING (-84.34908129007508 33.76979693981874, -84.34907923299846 33.76969514971695)", + "properties": { + "laneId": 13, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 1, + "geometry": "LINESTRING (-84.34901069971785 33.769804049825844, -84.34901243199303 33.769519919541715, -84.34899759943595 33.76931678933858)", + "properties": { + "laneId": 1, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 1 + } + ] + } + }, + { + "type": "Feature", + "id": 2, + "geometry": "LINESTRING (-84.348976378946 33.76980845983026, -84.34897973522935 33.76951370953551, -84.34899727445615 33.76925108927289, -84.34900463657817 33.76893275895456, -84.3490140557287 33.76797227799408)", + "properties": { + "laneId": 2, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 3, + "geometry": "LINESTRING (-84.34894205817417 33.76981457983638, -84.34894000109713 33.76951541953722, -84.3489588395263 33.769246679268484, -84.34897226457166 33.7689305989524, -84.3489829829151 33.76797011799192)", + "properties": { + "laneId": 3, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 4, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 4, + "geometry": "LINESTRING (-84.34893664480322 33.77010744012924, -84.34893664480322 33.770200950222744)", + "properties": { + "laneId": 4, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 4, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 5, + "geometry": "LINESTRING (-84.34897237305151 33.77010861013041, -84.34897172344601 33.77020158022338)", + "properties": { + "laneId": 5, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 4, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 8, + "geometry": "LINESTRING (-84.34913174269236 33.77012562014742, -84.3491101974389 33.77031948034128, -84.34907457731616 33.77039265041445)", + "properties": { + "laneId": 8, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 7 + } + ] + } + }, + { + "type": "Feature", + "id": 6, + "geometry": "LINESTRING (-84.34906050273062 33.770125080146876, -84.34902823898443 33.7704246004464, -84.34901946927779 33.77064888067068, -84.34902152637486 33.770956050977844)", + "properties": { + "laneId": 6, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 7, + "geometry": "LINESTRING (-84.34909742192052 33.77012283014463, -84.34906786486522 33.77040498042678, -84.34905844555284 33.770502900524704, -84.34905097505518 33.77095605097785)", + "properties": { + "laneId": 7, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 12, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 26, + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34885501108728 33.77008836011016, -84.34879784581652 33.770064960086756, -84.34878301316509 33.770017080038876, -84.34879243243482 33.76995200997381, -84.34880520798636 33.76989692991873, -84.34882870199401 33.76986740988921, -84.34887103450012 33.76985570987751, -84.34891953823453 33.76985030987211)", + "properties": { + "laneId": 26, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 25, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 27, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 28, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 29, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 28, + "geometry": "LINESTRING (-84.34880661563292 33.76941281943461, -84.34883887911091 33.769653209675006, -84.34883487323161 33.76981016983196, -84.34886984353939 33.7698557998776)", + "properties": { + "laneId": 28, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 27, + "geometry": "LINESTRING (-84.34881744237482 33.770362050383845, -84.34883487350739 33.77025297027477, -84.34883487350739 33.77015388017568, -84.34885371207693 33.77008818010998)", + "properties": { + "laneId": 27, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 32, + "geometry": "LINESTRING (-84.34914343557362 33.76982213984394, -84.34916443941466 33.76982231984412, -84.34920752976906 33.76985012987193, -84.3492140258045 33.76989332991513)", + "properties": { + "laneId": 32, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 31, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 33, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 34, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 35, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 30, + "geometry": "LINESTRING (-84.34903137879489 33.769838069859865, -84.34906299282956 33.76983419985599)", + "properties": { + "laneId": 30, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 29, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 31, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 33, + "geometry": "LINESTRING (-84.34911896713692 33.76936223938404, -84.34915231326228 33.769685519707316, -84.34915772661475 33.76978064980245, -84.34916259863738 33.76982240984421)", + "properties": { + "laneId": 33, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 34, + "geometry": "LINESTRING (-84.34992555940892 33.76979270981451, -84.34958007882258 33.76979621981802, -84.34938508961498 33.76980287982468, -84.3492439091894 33.76981952984133, -84.34920828927449 33.76984850987031)", + "properties": { + "laneId": 34, + "laneType": { + "parking": { + "parkingRevocableLane": false, + "parallelParkingInUse": false, + "headInParkingInUse": false, + "doNotParkZone": false, + "parkingForBusUse": false, + "parkingForTaxiUse": false, + "noPublicParkingUse": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 20, + "geometry": "LINESTRING (-84.3491024022218 33.77054277056457, -84.34909861283717 33.77045835048015, -84.34910933137172 33.77040768042948, -84.34913693970196 33.77036484038664, -84.34915642792534 33.77031696033876, -84.34916379013895 33.77022291024471, -84.34917526651815 33.77014722016902, -84.3492175991625 33.77009601011781)", + "properties": { + "laneId": 20, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 22, + "geometry": "LINESTRING (-84.34968877856343 33.770207790229584, -84.34957065849274 33.770199600221396, -84.34947917228725 33.77017899020078, -84.34935682981701 33.770132820154615, -84.34928147555736 33.770106630128424, -84.34921759768437 33.7700961001179)", + "properties": { + "laneId": 22, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34921749048802 33.7700961001179, -84.34919399642575 33.77009403011583)", + "properties": { + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 36, + "geometry": "LINESTRING (-84.34921759875567 33.769967759989555, -84.34921759875567 33.76999449001629)", + "properties": { + "laneId": 36, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 35, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34921749048802 33.7700961001179, -84.34919399642575 33.77009403011583)", + "properties": { + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34921749048802 33.7700961001179, -84.34919399642575 33.77009403011583)", + "properties": { + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 37, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 24, + "geometry": "LINESTRING (-84.34904415435034 33.7700907001125, -84.34899770756658 33.77008962011142)", + "properties": { + "laneId": 24, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 23, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 25, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 26, + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34885501108728 33.77008836011016, -84.34879784581652 33.770064960086756, -84.34878301316509 33.770017080038876, -84.34879243243482 33.76995200997381, -84.34880520798636 33.76989692991873, -84.34882870199401 33.76986740988921, -84.34887103450012 33.76985570987751, -84.34891953823453 33.76985030987211)", + "properties": { + "laneId": 26, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": false, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": true, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 25, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 27, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 28, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "connectingLane": { + "lane": 29, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + } + }, + { + "type": "Feature", + "id": 35, + "geometry": "LINESTRING (-84.3492148920702 33.76989314991495, -84.34921759875299 33.76996712998893)", + "properties": { + "laneId": 35, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + }, + { + "connectingLane": { + "lane": 36, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + } + ] + } + }, + { + "type": "Feature", + "id": 37, + "geometry": "LINESTRING (-84.34921759875567 33.76999449001629, -84.3492162995464 33.7700763000981)", + "properties": { + "laneId": 37, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": false, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 35, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + }, + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 13 + } + ] + } + }, + { + "type": "Feature", + "id": 23, + "geometry": "LINESTRING (-84.34919410472574 33.77009403011583, -84.34904415414763 33.7700907001125)", + "properties": { + "laneId": 23, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 21, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + }, + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + } + ] + } + }, + { + "type": "Feature", + "id": 25, + "geometry": "LINESTRING (-84.34899770762756 33.77008962011142, -84.3489183475062 33.77008908011088)", + "properties": { + "laneId": 25, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + } + ] + } + }, + { + "type": "Feature", + "id": 29, + "geometry": "LINESTRING (-84.34891975508584 33.769850309872105, -84.3490313786283 33.769838069859865)", + "properties": { + "laneId": 29, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 30, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + } + ] + } + }, + { + "type": "Feature", + "id": 31, + "geometry": "LINESTRING (-84.34906299288126 33.769834199856, -84.34914321890396 33.7698206998425)", + "properties": { + "laneId": 31, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 30, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 32, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + } + ] + } + } + ] + }, + "connectingLanesFeatureCollection": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "10-5", + "geometry": "LINESTRING (-84.34925148645785 33.76995371997552, -84.34897237305151 33.77010861013041)", + "properties": { + "signalGroupId": 3, + "ingressLaneId": 10, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "11-12", + "geometry": "LINESTRING (-84.34925148645785 33.76992257994438, -84.34911355376596 33.7697963998182)", + "properties": { + "signalGroupId": 9, + "ingressLaneId": 11, + "egressLaneId": 12 + } + }, + { + "type": "Feature", + "id": "1-9", + "geometry": "LINESTRING (-84.34901069971785 33.769804049825844, -84.3492353546124 33.77002491004671)", + "properties": { + "signalGroupId": 1, + "ingressLaneId": 1, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "2-5", + "geometry": "LINESTRING (-84.348976378946 33.76980845983026, -84.34897237305151 33.77010861013041)", + "properties": { + "signalGroupId": 6, + "ingressLaneId": 2, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "3-4", + "geometry": "LINESTRING (-84.34894205817417 33.76981457983638, -84.34893664480322 33.77010744012924)", + "properties": { + "signalGroupId": 6, + "ingressLaneId": 3, + "egressLaneId": 4 + } + }, + { + "type": "Feature", + "id": "8-9", + "geometry": "LINESTRING (-84.34913174269236 33.77012562014742, -84.3492353546124 33.77002491004671)", + "properties": { + "signalGroupId": 7, + "ingressLaneId": 8, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "6-13", + "geometry": "LINESTRING (-84.34906050273062 33.770125080146876, -84.34908129007508 33.76979693981874)", + "properties": { + "signalGroupId": 2, + "ingressLaneId": 6, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "7-12", + "geometry": "LINESTRING (-84.34909742192052 33.77012283014463, -84.34911355376596 33.7697963998182)", + "properties": { + "signalGroupId": 2, + "ingressLaneId": 7, + "egressLaneId": 12 + } + }, + { + "type": "Feature", + "id": "26-25", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34899770762756 33.77008962011142)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 25 + } + }, + { + "type": "Feature", + "id": "26-27", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34881744237482 33.770362050383845)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 27 + } + }, + { + "type": "Feature", + "id": "26-28", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34880661563292 33.76941281943461)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 28 + } + }, + { + "type": "Feature", + "id": "26-29", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34891975508584 33.769850309872105)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 29 + } + }, + { + "type": "Feature", + "id": "28-26", + "geometry": "LINESTRING (-84.34880661563292 33.76941281943461, -84.3489183476094 33.77008908011088)", + "properties": { + "ingressLaneId": 28, + "egressLaneId": 26 + } + }, + { + "type": "Feature", + "id": "27-26", + "geometry": "LINESTRING (-84.34881744237482 33.770362050383845, -84.3489183476094 33.77008908011088)", + "properties": { + "ingressLaneId": 27, + "egressLaneId": 26 + } + }, + { + "type": "Feature", + "id": "32-31", + "geometry": "LINESTRING (-84.34914343557362 33.76982213984394, -84.34906299288126 33.769834199856)", + "properties": { + "ingressLaneId": 32, + "egressLaneId": 31 + } + }, + { + "type": "Feature", + "id": "32-33", + "geometry": "LINESTRING (-84.34914343557362 33.76982213984394, -84.34911896713692 33.76936223938404)", + "properties": { + "ingressLaneId": 32, + "egressLaneId": 33 + } + }, + { + "type": "Feature", + "id": "32-34", + "geometry": "LINESTRING (-84.34914343557362 33.76982213984394, -84.34992555940892 33.76979270981451)", + "properties": { + "ingressLaneId": 32, + "egressLaneId": 34 + } + }, + { + "type": "Feature", + "id": "32-35", + "geometry": "LINESTRING (-84.34914343557362 33.76982213984394, -84.3492148920702 33.76989314991495)", + "properties": { + "ingressLaneId": 32, + "egressLaneId": 35 + } + }, + { + "type": "Feature", + "id": "30-29", + "geometry": "LINESTRING (-84.34903137879489 33.769838069859865, -84.34891975508584 33.769850309872105)", + "properties": { + "ingressLaneId": 30, + "egressLaneId": 29 + } + }, + { + "type": "Feature", + "id": "30-31", + "geometry": "LINESTRING (-84.34903137879489 33.769838069859865, -84.34906299288126 33.769834199856)", + "properties": { + "ingressLaneId": 30, + "egressLaneId": 31 + } + }, + { + "type": "Feature", + "id": "33-32", + "geometry": "LINESTRING (-84.34911896713692 33.76936223938404, -84.34914343557362 33.76982213984394)", + "properties": { + "ingressLaneId": 33, + "egressLaneId": 32 + } + }, + { + "type": "Feature", + "id": "34-32", + "geometry": "LINESTRING (-84.34992555940892 33.76979270981451, -84.34914343557362 33.76982213984394)", + "properties": { + "ingressLaneId": 34, + "egressLaneId": 32 + } + }, + { + "type": "Feature", + "id": "20-21", + "geometry": "LINESTRING (-84.3491024022218 33.77054277056457, -84.3492177070231 33.77007639009819)", + "properties": { + "ingressLaneId": 20, + "egressLaneId": 21 + } + }, + { + "type": "Feature", + "id": "20-22", + "geometry": "LINESTRING (-84.3491024022218 33.77054277056457, -84.34968877856343 33.770207790229584)", + "properties": { + "ingressLaneId": 20, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "22-20", + "geometry": "LINESTRING (-84.34968877856343 33.770207790229584, -84.3491024022218 33.77054277056457)", + "properties": { + "ingressLaneId": 22, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "22-21", + "geometry": "LINESTRING (-84.34968877856343 33.770207790229584, -84.3492177070231 33.77007639009819)", + "properties": { + "ingressLaneId": 22, + "egressLaneId": 21 + } + }, + { + "type": "Feature", + "id": "21-20", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.3491024022218 33.77054277056457)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "21-22", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34968877856343 33.770207790229584)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "21-23", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34919410472574 33.77009403011583)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "21-37", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34921759875567 33.76999449001629)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "36-35", + "geometry": "LINESTRING (-84.34921759875567 33.769967759989555, -84.3492148920702 33.76989314991495)", + "properties": { + "ingressLaneId": 36, + "egressLaneId": 35 + } + }, + { + "type": "Feature", + "id": "36-37", + "geometry": "LINESTRING (-84.34921759875567 33.769967759989555, -84.34921759875567 33.76999449001629)", + "properties": { + "ingressLaneId": 36, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "21-20", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.3491024022218 33.77054277056457)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "21-22", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34968877856343 33.770207790229584)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "21-23", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34919410472574 33.77009403011583)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "21-37", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34921759875567 33.76999449001629)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "21-20", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.3491024022218 33.77054277056457)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 20 + } + }, + { + "type": "Feature", + "id": "21-22", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34968877856343 33.770207790229584)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 22 + } + }, + { + "type": "Feature", + "id": "21-23", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34919410472574 33.77009403011583)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "21-37", + "geometry": "LINESTRING (-84.3492177070231 33.77007639009819, -84.34921759875567 33.76999449001629)", + "properties": { + "ingressLaneId": 21, + "egressLaneId": 37 + } + }, + { + "type": "Feature", + "id": "24-23", + "geometry": "LINESTRING (-84.34904415435034 33.7700907001125, -84.34919410472574 33.77009403011583)", + "properties": { + "ingressLaneId": 24, + "egressLaneId": 23 + } + }, + { + "type": "Feature", + "id": "24-25", + "geometry": "LINESTRING (-84.34904415435034 33.7700907001125, -84.34899770762756 33.77008962011142)", + "properties": { + "ingressLaneId": 24, + "egressLaneId": 25 + } + }, + { + "type": "Feature", + "id": "26-25", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34899770762756 33.77008962011142)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 25 + } + }, + { + "type": "Feature", + "id": "26-27", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34881744237482 33.770362050383845)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 27 + } + }, + { + "type": "Feature", + "id": "26-28", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34880661563292 33.76941281943461)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 28 + } + }, + { + "type": "Feature", + "id": "26-29", + "geometry": "LINESTRING (-84.3489183476094 33.77008908011088, -84.34891975508584 33.769850309872105)", + "properties": { + "ingressLaneId": 26, + "egressLaneId": 29 + } + } + ] + }, + "properties": { + "schemaVersion": 2, + "messageType": "MAP", + "odeReceivedAt": "2025-08-01T15:07:54.8Z", + "originIp": "172.18.0.1", + "asn1": "001283A638053000324E2177D41449C5CCC639032D2E02DC0515E1096050A1C000080002A0C76F00473882FCBFC4A0866CB080A05187024150000CB02C50E0000200041063ACB105EC800466137BE883A5A40428ABF2A1A2590080A051870243080024402588E00000050AE5038405028C38456CFF420184470000002970407020281461C27F4388100D22380000014DD604410140A30E14099CA96009A1C000080002A977071047386FF01D5AE11272F080A051870242500004B008D0E000080003155A0510DFC23351BD7893437DE08BDAFF52ACA010140A30E0482C000316019A1C0001000062BF10E61C04C60837A911586F8412435FE75594020281461C090480006100442380000015847B3810140A30E14006078802A11C000000AAD9DA9080A051870A01B024B02150E000020001528CF33024C83863E1A93527968405028C3812124000E480CA8700000109EAF980712AE800E0A39BC5BFB7AAA10140A30E0486C00011603AA1C0001000042656E471C44787E2857C406408B9D58405028C38121900004683400C0D300000716666680724BF80E105F819127B02EA49685C519C024E5C00795F8020388601900D807003A683800C0D3000002251A83BB0DDADA6F1412F6800BDFEC0034683600C0D3000002250E185489D7CD10500076616A44980034684000C0D3000002125689D013E80803966A0713E0300F8084044023341E0060698000000A2E07AC06E3AA201D00F9A10803034C0000088EC78A88376678204F9D842074FD000101A11003035C00000C803AAFE63E3BC09C5E130942D188B90693A100080D0500181A600000C478A38810C230AC173A73408084816987B04F787D6172C2DC29E4E38805402C682C00C0D3000004212014FB8B10DE943D358D8B1A97FC3AE16E872738B100A0054D0540181A600000221FFC4304056D82D97A4C02801600B8094D0900181A6000000220078C0401948808C04A682A00C0D300000110FFE218202B6C16CBD2601400B005C04A682A00C0D300000110FFE218202B6C16CBD2601400B005C04A683000C0D3000000142167103AD7D0402E019341A0060698000038B3333403925FC07082FC0C893D817524B42E28CE01272E003CAFC0101C4300C806C03801D042300688200000886513C2F9F9B0A080350481A084A00D1000000110045A860678D141186A05434105C01A208000022D9D0716B4BED8A054390301C083200D104000014F7E6B076EBFA140C08206840107401A20800002CBF27311FCBBC0A0684103C20083E00D104000013CA0E0048DB6A140F08208040", + "region": 10000, + "intersectionId": 48106, + "msgIssueRevision": 5, + "revision": 5, + "refPoint": { + "latitude": 33.7699782, + "longitude": -84.3490513 + }, + "cti4501Conformant": false, + "laneWidth": 366, + "speedLimits": [ + { + "type": "VEHICLEMAXSPEED", + "speed": 700 + } + ], + "mapSource": "RSU", + "timeStamp": "2025-08-01T15:07:54.8Z" + } +} \ No newline at end of file diff --git a/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json b/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json deleted file mode 100644 index 90dad7d..0000000 --- a/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference-1-hour-later.json +++ /dev/null @@ -1,1829 +0,0 @@ -{ - "mapFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": 2, - "geometry": "LINESTRING (-105.0911523 39.5953376, -105.0899239 39.5953231, -105.0896005 39.5953332, -105.0888831 39.595317, -105.088108 39.5953159, -105.0876637 39.5953153)", - "properties": { - "laneId": 2, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 3, - "geometry": "LINESTRING (-105.0911527 39.5953113, -105.0908101 39.5953039, -105.0900791 39.5952962, -105.0896801 39.5952874, -105.0888781 39.5952839, -105.0885678 39.5952789, -105.0880704 39.5952849, -105.0876638 39.5952849)", - "properties": { - "laneId": 3, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 1, - "geometry": "LINESTRING (-105.0911535 39.5953745, -105.0899328 39.5953544, -105.0897165 39.5953447)", - "properties": { - "laneId": 1, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 4, - "geometry": "LINESTRING (-105.0911537 39.5952537, -105.0903143 39.5952555, -105.0902511 39.5952591, -105.0900995 39.5952797)", - "properties": { - "laneId": 4, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 1, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 6, - "geometry": "LINESTRING (-105.0911474 39.5951732, -105.0911048 39.5951738)", - "properties": { - "laneId": 6, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 5, - "geometry": "LINESTRING (-105.0911474 39.5952053, -105.0911079 39.5952053)", - "properties": { - "laneId": 5, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 7, - "geometry": "LINESTRING (-105.0911443 39.5951332, -105.0911017 39.5951356)", - "properties": { - "laneId": 7, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 2, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 12, - "geometry": "LINESTRING (-105.0915234 39.5950941, -105.0915234 39.5950602)", - "properties": { - "laneId": 12, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 13, - "geometry": "LINESTRING (-105.0915804 39.5950941, -105.0915796 39.595059, -105.0915796 39.595059, -105.0915796 39.5950596)", - "properties": { - "laneId": 13, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 4, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 10, - "geometry": "LINESTRING (-105.0913299 39.5950922, -105.09133 39.5944158, -105.0913348 39.5939413, -105.0913368 39.592921, -105.0913348 39.5923866, -105.0913348 39.5923866, -105.0913356 39.592386)", - "properties": { - "laneId": 10, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 9, - "geometry": "LINESTRING (-105.0912849 39.5950912, -105.0912838 39.5946624, -105.0912861 39.5940862, -105.0912901 39.5933704, -105.0912882 39.5923858)", - "properties": { - "laneId": 9, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 11, - "geometry": "LINESTRING (-105.0913713 39.5950916, -105.091375 39.5944888, -105.0913568 39.5942534)", - "properties": { - "laneId": 11, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 8, - "geometry": "LINESTRING (-105.0912303 39.5950889, -105.0912421 39.5949129, -105.0912427 39.5942475, -105.0912568 39.5941003)", - "properties": { - "laneId": 8, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 3, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 15, - "geometry": "LINESTRING (-105.0916931 39.5951733, -105.0927839 39.5951756, -105.0941732 39.5951722, -105.0952027 39.5951734)", - "properties": { - "laneId": 15, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 16, - "geometry": "LINESTRING (-105.0916852 39.5952059, -105.0931135 39.5952073, -105.0944406 39.595204, -105.0952041 39.5952041)", - "properties": { - "laneId": 16, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 17, - "geometry": "LINESTRING (-105.0916853 39.5952393, -105.0927239 39.5952377, -105.0941207 39.5952375, -105.0943034 39.5952213)", - "properties": { - "laneId": 17, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 14, - "geometry": "LINESTRING (-105.0916926 39.5951407, -105.0940224 39.5951414, -105.095203 39.5951408)", - "properties": { - "laneId": 14, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 5, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 18, - "geometry": "LINESTRING (-105.0916766 39.595308, -105.0917443 39.5953067)", - "properties": { - "laneId": 18, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 19, - "geometry": "LINESTRING (-105.0916758 39.5953365, -105.0917363 39.5953365)", - "properties": { - "laneId": 19, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 20, - "geometry": "LINESTRING (-105.0916734 39.5953755, -105.0917299 39.5953755)", - "properties": { - "laneId": 20, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 6, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 23, - "geometry": "LINESTRING (-105.091519 39.5954362, -105.0914927 39.5965421, -105.091488 39.5974092, -105.0914843 39.5981324, -105.0914843 39.5981324, -105.0914851 39.5981349)", - "properties": { - "laneId": 23, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 22, - "geometry": "LINESTRING (-105.0915548 39.5954372, -105.0915441 39.59638, -105.0915337 39.5974224, -105.0915281 39.5981345)", - "properties": { - "laneId": 22, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 21, - "geometry": "LINESTRING (-105.0916048 39.5954391, -105.0916029 39.5957255, -105.0916004 39.5962647, -105.0915885 39.5966976, -105.0915786 39.5977599, -105.0915764 39.5981344)", - "properties": { - "laneId": 21, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 24, - "geometry": "LINESTRING (-105.0914747 39.5954382, -105.0914714 39.5958506, -105.0914611 39.596192, -105.0914778 39.5963599)", - "properties": { - "laneId": 24, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 25, - "geometry": "LINESTRING (-105.0914371 39.5954371, -105.0914355 39.5958506, -105.0914461 39.596052)", - "properties": { - "laneId": 25, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 0, - "ingressApproach": 7, - "ingressPath": true, - "egressPath": 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 - }, - "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 - } - ] - } - }, - { - "type": "Feature", - "id": 26, - "geometry": "LINESTRING (-105.0913276 39.5954361, -105.0913284 39.5954678)", - "properties": { - "laneId": 26, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 27, - "geometry": "LINESTRING (-105.0912831 39.5954348, -105.0912839 39.5954647)", - "properties": { - "laneId": 27, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - }, - { - "type": "Feature", - "id": 28, - "geometry": "LINESTRING (-105.0912264 39.5954336, -105.091228 39.5954647, -105.091228 39.5954653)", - "properties": { - "laneId": 28, - "laneType": { - "vehicle": { - "isVehicleRevocableLane": false, - "isVehicleFlyOverLane": false, - "permissionOnRequest": false, - "hasIRbeaconCoverage": false, - "restrictedToBusUse": false, - "restrictedToTaxiUse": false, - "restrictedFromPublicUse": false, - "hovLaneUseOnly": false - } - }, - "sharedWith": { - "busVehicleTraffic": false, - "trackedVehicleTraffic": false, - "individualMotorizedVehicleTraffic": false, - "taxiVehicleTraffic": false, - "overlappingLaneDescriptionProvided": false, - "cyclistVehicleTraffic": false, - "otherNonMotorizedTrafficTypes": false, - "multipleLanesTreatedAsOneLane": false, - "pedestrianTraffic": false, - "pedestriansTraffic": false - }, - "egressApproach": 8, - "ingressApproach": 0, - "ingressPath": false, - "egressPath": true - } - } - ] - }, - "connectingLanesFeatureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": "2-19", - "geometry": "LINESTRING (-105.0911523 39.5953376, -105.0916758 39.5953365)", - "properties": { - "signalGroupId": 4, - "ingressLaneId": 2, - "egressLaneId": 19 - } - }, - { - "type": "Feature", - "id": "3-18", - "geometry": "LINESTRING (-105.0911527 39.5953113, -105.0916766 39.595308)", - "properties": { - "signalGroupId": 4, - "ingressLaneId": 3, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "1-28", - "geometry": "LINESTRING (-105.0911535 39.5953745, -105.0912264 39.5954336)", - "properties": { - "ingressLaneId": 1, - "egressLaneId": 28 - } - }, - { - "type": "Feature", - "id": "4-12", - "geometry": "LINESTRING (-105.0911537 39.5952537, -105.0915234 39.5950941)", - "properties": { - "signalGroupId": 7, - "ingressLaneId": 4, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "10-26", - "geometry": "LINESTRING (-105.0913299 39.5950922, -105.0913276 39.5954361)", - "properties": { - "signalGroupId": 6, - "ingressLaneId": 10, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "9-27", - "geometry": "LINESTRING (-105.0912849 39.5950912, -105.0912831 39.5954348)", - "properties": { - "signalGroupId": 6, - "ingressLaneId": 9, - "egressLaneId": 27 - } - }, - { - "type": "Feature", - "id": "11-18", - "geometry": "LINESTRING (-105.0913713 39.5950916, -105.0916766 39.595308)", - "properties": { - "signalGroupId": 1, - "ingressLaneId": 11, - "egressLaneId": 18 - } - }, - { - "type": "Feature", - "id": "8-7", - "geometry": "LINESTRING (-105.0912303 39.5950889, -105.0911443 39.5951332)", - "properties": { - "ingressLaneId": 8, - "egressLaneId": 7 - } - }, - { - "type": "Feature", - "id": "15-6", - "geometry": "LINESTRING (-105.0916931 39.5951733, -105.0911474 39.5951732)", - "properties": { - "signalGroupId": 8, - "ingressLaneId": 15, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "16-5", - "geometry": "LINESTRING (-105.0916852 39.5952059, -105.0911474 39.5952053)", - "properties": { - "signalGroupId": 8, - "ingressLaneId": 16, - "egressLaneId": 5 - } - }, - { - "type": "Feature", - "id": "17-26", - "geometry": "LINESTRING (-105.0916853 39.5952393, -105.0913276 39.5954361)", - "properties": { - "signalGroupId": 3, - "ingressLaneId": 17, - "egressLaneId": 26 - } - }, - { - "type": "Feature", - "id": "14-13", - "geometry": "LINESTRING (-105.0916926 39.5951407, -105.0915804 39.5950941)", - "properties": { - "ingressLaneId": 14, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "23-12", - "geometry": "LINESTRING (-105.091519 39.5954362, -105.0915234 39.5950941)", - "properties": { - "signalGroupId": 2, - "ingressLaneId": 23, - "egressLaneId": 12 - } - }, - { - "type": "Feature", - "id": "22-13", - "geometry": "LINESTRING (-105.0915548 39.5954372, -105.0915804 39.5950941)", - "properties": { - "signalGroupId": 2, - "ingressLaneId": 22, - "egressLaneId": 13 - } - }, - { - "type": "Feature", - "id": "21-20", - "geometry": "LINESTRING (-105.0916048 39.5954391, -105.0916734 39.5953755)", - "properties": { - "ingressLaneId": 21, - "egressLaneId": 20 - } - }, - { - "type": "Feature", - "id": "24-6", - "geometry": "LINESTRING (-105.0914747 39.5954382, -105.0911474 39.5951732)", - "properties": { - "signalGroupId": 5, - "ingressLaneId": 24, - "egressLaneId": 6 - } - }, - { - "type": "Feature", - "id": "25-5", - "geometry": "LINESTRING (-105.0914371 39.5954371, -105.0911474 39.5952053)", - "properties": { - "signalGroupId": 5, - "ingressLaneId": 25, - "egressLaneId": 5 - } - } - ] - }, - "properties": { - "schemaVersion": 1, - "messageType": "MAP", - "odeReceivedAt": "2025-02-01T00:50:49.19Z", - "originIp": "172.20.0.1", - "intersectionId": 12110, - "msgIssueRevision": 0, - "revision": 0, - "refPoint": { - "latitude": 39.5952649, - "longitude": -105.0914122, - "elevation": 1677 - }, - "cti4501Conformant": false, - "laneWidth": 366, - "mapSource": "RSU", - "timeStamp": "2025-02-01T00:50:49.19Z" - } - } \ No newline at end of file diff --git a/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json b/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json index f781ea3..11b0fe5 100644 --- a/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json +++ b/jpo-deduplicator/src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-reference.json @@ -1 +1,1874 @@ -{"mapFeatureCollection":{"type":"FeatureCollection","features":[{"type":"Feature","id":2,"geometry":"LINESTRING (-105.0911523 39.5953376, -105.0899239 39.5953231, -105.0896005 39.5953332, -105.0888831 39.595317, -105.088108 39.5953159, -105.0876637 39.5953153)","properties":{"laneId":2,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":1,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":3,"geometry":"LINESTRING (-105.0911527 39.5953113, -105.0908101 39.5953039, -105.0900791 39.5952962, -105.0896801 39.5952874, -105.0888781 39.5952839, -105.0885678 39.5952789, -105.0880704 39.5952849, -105.0876638 39.5952849)","properties":{"laneId":3,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":1,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":1,"geometry":"LINESTRING (-105.0911535 39.5953745, -105.0899328 39.5953544, -105.0897165 39.5953447)","properties":{"laneId":1,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":1,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":4,"geometry":"LINESTRING (-105.0911537 39.5952537, -105.0903143 39.5952555, -105.0902511 39.5952591, -105.0900995 39.5952797)","properties":{"laneId":4,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":1,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":6,"geometry":"LINESTRING (-105.0911474 39.5951732, -105.0911048 39.5951738)","properties":{"laneId":6,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":2,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":5,"geometry":"LINESTRING (-105.0911474 39.5952053, -105.0911079 39.5952053)","properties":{"laneId":5,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":2,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":7,"geometry":"LINESTRING (-105.0911443 39.5951332, -105.0911017 39.5951356)","properties":{"laneId":7,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":2,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":12,"geometry":"LINESTRING (-105.0915234 39.5950941, -105.0915234 39.5950602)","properties":{"laneId":12,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":4,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":13,"geometry":"LINESTRING (-105.0915804 39.5950941, -105.0915796 39.595059, -105.0915796 39.595059, -105.0915796 39.5950596)","properties":{"laneId":13,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":4,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":10,"geometry":"LINESTRING (-105.0913299 39.5950922, -105.09133 39.5944158, -105.0913348 39.5939413, -105.0913368 39.592921, -105.0913348 39.5923866, -105.0913348 39.5923866, -105.0913356 39.592386)","properties":{"laneId":10,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":3,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":9,"geometry":"LINESTRING (-105.0912849 39.5950912, -105.0912838 39.5946624, -105.0912861 39.5940862, -105.0912901 39.5933704, -105.0912882 39.5923858)","properties":{"laneId":9,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":3,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":11,"geometry":"LINESTRING (-105.0913713 39.5950916, -105.091375 39.5944888, -105.0913568 39.5942534)","properties":{"laneId":11,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":3,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":8,"geometry":"LINESTRING (-105.0912303 39.5950889, -105.0912421 39.5949129, -105.0912427 39.5942475, -105.0912568 39.5941003)","properties":{"laneId":8,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":3,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":15,"geometry":"LINESTRING (-105.0916931 39.5951733, -105.0927839 39.5951756, -105.0941732 39.5951722, -105.0952027 39.5951734)","properties":{"laneId":15,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":5,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":16,"geometry":"LINESTRING (-105.0916852 39.5952059, -105.0931135 39.5952073, -105.0944406 39.595204, -105.0952041 39.5952041)","properties":{"laneId":16,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":5,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":17,"geometry":"LINESTRING (-105.0916853 39.5952393, -105.0927239 39.5952377, -105.0941207 39.5952375, -105.0943034 39.5952213)","properties":{"laneId":17,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":5,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":14,"geometry":"LINESTRING (-105.0916926 39.5951407, -105.0940224 39.5951414, -105.095203 39.5951408)","properties":{"laneId":14,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":5,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":18,"geometry":"LINESTRING (-105.0916766 39.595308, -105.0917443 39.5953067)","properties":{"laneId":18,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":6,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":19,"geometry":"LINESTRING (-105.0916758 39.5953365, -105.0917363 39.5953365)","properties":{"laneId":19,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":6,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":20,"geometry":"LINESTRING (-105.0916734 39.5953755, -105.0917299 39.5953755)","properties":{"laneId":20,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":6,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":23,"geometry":"LINESTRING (-105.091519 39.5954362, -105.0914927 39.5965421, -105.091488 39.5974092, -105.0914843 39.5981324, -105.0914843 39.5981324, -105.0914851 39.5981349)","properties":{"laneId":23,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":7,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":22,"geometry":"LINESTRING (-105.0915548 39.5954372, -105.0915441 39.59638, -105.0915337 39.5974224, -105.0915281 39.5981345)","properties":{"laneId":22,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":7,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":21,"geometry":"LINESTRING (-105.0916048 39.5954391, -105.0916029 39.5957255, -105.0916004 39.5962647, -105.0915885 39.5966976, -105.0915786 39.5977599, -105.0915764 39.5981344)","properties":{"laneId":21,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":7,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":24,"geometry":"LINESTRING (-105.0914747 39.5954382, -105.0914714 39.5958506, -105.0914611 39.596192, -105.0914778 39.5963599)","properties":{"laneId":24,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":7,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":25,"geometry":"LINESTRING (-105.0914371 39.5954371, -105.0914355 39.5958506, -105.0914461 39.596052)","properties":{"laneId":25,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":0,"ingressApproach":7,"ingressPath":true,"egressPath":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},"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}]}},{"type":"Feature","id":26,"geometry":"LINESTRING (-105.0913276 39.5954361, -105.0913284 39.5954678)","properties":{"laneId":26,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":8,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":27,"geometry":"LINESTRING (-105.0912831 39.5954348, -105.0912839 39.5954647)","properties":{"laneId":27,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":8,"ingressApproach":0,"ingressPath":false,"egressPath":true}},{"type":"Feature","id":28,"geometry":"LINESTRING (-105.0912264 39.5954336, -105.091228 39.5954647, -105.091228 39.5954653)","properties":{"laneId":28,"laneType":{"vehicle":{"isVehicleRevocableLane":false,"isVehicleFlyOverLane":false,"permissionOnRequest":false,"hasIRbeaconCoverage":false,"restrictedToBusUse":false,"restrictedToTaxiUse":false,"restrictedFromPublicUse":false,"hovLaneUseOnly":false}},"sharedWith":{"busVehicleTraffic":false,"trackedVehicleTraffic":false,"individualMotorizedVehicleTraffic":false,"taxiVehicleTraffic":false,"overlappingLaneDescriptionProvided":false,"cyclistVehicleTraffic":false,"otherNonMotorizedTrafficTypes":false,"multipleLanesTreatedAsOneLane":false,"pedestrianTraffic":false,"pedestriansTraffic":false},"egressApproach":8,"ingressApproach":0,"ingressPath":false,"egressPath":true}}]},"connectingLanesFeatureCollection":{"type":"FeatureCollection","features":[{"type":"Feature","id":"2-19","geometry":"LINESTRING (-105.0911523 39.5953376, -105.0916758 39.5953365)","properties":{"signalGroupId":4,"ingressLaneId":2,"egressLaneId":19}},{"type":"Feature","id":"3-18","geometry":"LINESTRING (-105.0911527 39.5953113, -105.0916766 39.595308)","properties":{"signalGroupId":4,"ingressLaneId":3,"egressLaneId":18}},{"type":"Feature","id":"1-28","geometry":"LINESTRING (-105.0911535 39.5953745, -105.0912264 39.5954336)","properties":{"ingressLaneId":1,"egressLaneId":28}},{"type":"Feature","id":"4-12","geometry":"LINESTRING (-105.0911537 39.5952537, -105.0915234 39.5950941)","properties":{"signalGroupId":7,"ingressLaneId":4,"egressLaneId":12}},{"type":"Feature","id":"10-26","geometry":"LINESTRING (-105.0913299 39.5950922, -105.0913276 39.5954361)","properties":{"signalGroupId":6,"ingressLaneId":10,"egressLaneId":26}},{"type":"Feature","id":"9-27","geometry":"LINESTRING (-105.0912849 39.5950912, -105.0912831 39.5954348)","properties":{"signalGroupId":6,"ingressLaneId":9,"egressLaneId":27}},{"type":"Feature","id":"11-18","geometry":"LINESTRING (-105.0913713 39.5950916, -105.0916766 39.595308)","properties":{"signalGroupId":1,"ingressLaneId":11,"egressLaneId":18}},{"type":"Feature","id":"8-7","geometry":"LINESTRING (-105.0912303 39.5950889, -105.0911443 39.5951332)","properties":{"ingressLaneId":8,"egressLaneId":7}},{"type":"Feature","id":"15-6","geometry":"LINESTRING (-105.0916931 39.5951733, -105.0911474 39.5951732)","properties":{"signalGroupId":8,"ingressLaneId":15,"egressLaneId":6}},{"type":"Feature","id":"16-5","geometry":"LINESTRING (-105.0916852 39.5952059, -105.0911474 39.5952053)","properties":{"signalGroupId":8,"ingressLaneId":16,"egressLaneId":5}},{"type":"Feature","id":"17-26","geometry":"LINESTRING (-105.0916853 39.5952393, -105.0913276 39.5954361)","properties":{"signalGroupId":3,"ingressLaneId":17,"egressLaneId":26}},{"type":"Feature","id":"14-13","geometry":"LINESTRING (-105.0916926 39.5951407, -105.0915804 39.5950941)","properties":{"ingressLaneId":14,"egressLaneId":13}},{"type":"Feature","id":"23-12","geometry":"LINESTRING (-105.091519 39.5954362, -105.0915234 39.5950941)","properties":{"signalGroupId":2,"ingressLaneId":23,"egressLaneId":12}},{"type":"Feature","id":"22-13","geometry":"LINESTRING (-105.0915548 39.5954372, -105.0915804 39.5950941)","properties":{"signalGroupId":2,"ingressLaneId":22,"egressLaneId":13}},{"type":"Feature","id":"21-20","geometry":"LINESTRING (-105.0916048 39.5954391, -105.0916734 39.5953755)","properties":{"ingressLaneId":21,"egressLaneId":20}},{"type":"Feature","id":"24-6","geometry":"LINESTRING (-105.0914747 39.5954382, -105.0911474 39.5951732)","properties":{"signalGroupId":5,"ingressLaneId":24,"egressLaneId":6}},{"type":"Feature","id":"25-5","geometry":"LINESTRING (-105.0914371 39.5954371, -105.0911474 39.5952053)","properties":{"signalGroupId":5,"ingressLaneId":25,"egressLaneId":5}}]},"properties":{"schemaVersion":1,"messageType":"MAP","odeReceivedAt":"2025-01-31T23:50:49.19Z","originIp":"172.20.0.1","intersectionId":12110,"msgIssueRevision":0,"revision":0,"refPoint":{"latitude":39.5952649,"longitude":-105.0914122,"elevation":1677.0},"cti4501Conformant":false,"laneWidth":366,"mapSource":"RSU","timeStamp":"2025-01-31T23:50:49.19Z"}} \ No newline at end of file +{ + "mapFeatureCollection": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": 2, + "geometry": "LINESTRING (-111.79574771374223 40.37685433004563, -111.79457362498155 40.37684929004059, -111.79437715592712 40.37684416003546, -111.79419817180518 40.37682985002115, -111.79405687479898 40.376808429999734, -111.7939236114442 40.37677980997111, -111.79379306539413 40.37674200993331, -111.79368142200217 40.37670420989551, -111.7935428425045 40.376648049839346, -111.79347420258887 40.37661132980263)", + "properties": { + "laneId": 2, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 14, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 3, + "geometry": "LINESTRING (-111.79575220311058 40.376821570012865, -111.79457551581227 40.37681698000827, -111.79438247294937 40.37681239000368, -111.79420620616122 40.37679915999045, -111.79406762646826 40.37677818996948, -111.79393849811595 40.37675064994194, -111.7938126777692 40.37671437990567, -111.79370304282185 40.37667612986742, -111.79357048857497 40.37662149981279, -111.79349913144468 40.376585769777066)", + "properties": { + "laneId": 3, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 2 + } + ] + } + }, + { + "type": "Feature", + "id": 1, + "geometry": "LINESTRING (-111.79574216110242 40.37688637007767, -111.79457220673274 40.37688025007155, -111.79437514688104 40.37686288005418)", + "properties": { + "laneId": 1, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 18, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 12 + }, + { + "connectingLane": { + "lane": 19, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 12 + } + ] + } + }, + { + "type": "Feature", + "id": 4, + "geometry": "LINESTRING (-111.79576094556474 40.37678988998119, -111.79509427455045 40.37678682997813, -111.79497991383585 40.37680005999136)", + "properties": { + "laneId": 4, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 1, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 5 + } + ] + } + }, + { + "type": "Feature", + "id": 5, + "geometry": "LINESTRING (-111.79578315612396 40.376754159945456, -111.79572325854731 40.376753619944914)", + "properties": { + "laneId": 5, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 6, + "geometry": "LINESTRING (-111.7957885906225 40.3767204999118, -111.79572668467677 40.376719959911256)", + "properties": { + "laneId": 6, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 2, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 7, + "geometry": "LINESTRING (-111.79587802356573 40.37664390983521, -111.79588948324114 40.37573778892909)", + "properties": { + "laneId": 7, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 6, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + }, + { + "connectingLane": { + "lane": 18, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 4 + }, + { + "connectingLane": { + "lane": 19, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 4 + }, + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 14 + } + ] + } + }, + { + "type": "Feature", + "id": 8, + "geometry": "LINESTRING (-111.79591925486982 40.376643999835295, -111.79592209025343 40.376445459636756, -111.79590590498636 40.37634798953928)", + "properties": { + "laneId": 8, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 3, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 7 + }, + { + "connectingLane": { + "lane": 14, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 7 + } + ] + } + }, + { + "type": "Feature", + "id": 9, + "geometry": "LINESTRING (-111.79598246045057 40.37665497984628, -111.79597667154142 40.37660880980011)", + "properties": { + "laneId": 9, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 4, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 11, + "geometry": "LINESTRING (-111.79609953845157 40.37676036995167, -111.79741492243544 40.37676864995995)", + "properties": { + "laneId": 11, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 10, + "geometry": "LINESTRING (-111.79609965659284 40.37672877992008, -111.79741492181886 40.37673543992674)", + "properties": { + "laneId": 10, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 16 + }, + { + "connectingLane": { + "lane": 6, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 6 + } + ] + } + }, + { + "type": "Feature", + "id": 12, + "geometry": "LINESTRING (-111.79609965659284 40.37679204998335, -111.79671930741368 40.37679456998587, -111.79683036018649 40.3767843999757)", + "properties": { + "laneId": 12, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 5, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 18, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 1 + }, + { + "connectingLane": { + "lane": 19, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 1 + } + ] + } + }, + { + "type": "Feature", + "id": 13, + "geometry": "LINESTRING (-111.79607957257653 40.37682472001602, -111.79614277817231 40.37682571001701)", + "properties": { + "laneId": 13, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 6, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 14, + "geometry": "LINESTRING (-111.79607957257653 40.37685847004977, -111.79614218749718 40.37685901005031)", + "properties": { + "laneId": 14, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 6, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 15, + "geometry": "LINESTRING (-111.79599817323981 40.376953870145165, -111.7959941564279 40.37758180077309, -111.79595375164911 40.37773696092825, -111.79595505122101 40.3778544110457)", + "properties": { + "laneId": 15, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 7, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": true, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 14, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 18 + }, + { + "connectingLane": { + "lane": 9, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 8 + }, + { + "connectingLane": { + "lane": 13, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": true, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 18 + } + ] + } + }, + { + "type": "Feature", + "id": 16, + "geometry": "LINESTRING (-111.79595623308809 40.37695486014616, -111.79595079857776 40.377576940768236, -111.79593201390126 40.37773165092295)", + "properties": { + "laneId": 16, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 7, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 6, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 3 + } + ] + } + }, + { + "type": "Feature", + "id": 17, + "geometry": "LINESTRING (-111.79591452921892 40.37695513014643, -111.79591382036975 40.37757487076617, -111.79592622534442 40.377729940921235)", + "properties": { + "laneId": 17, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 0, + "ingressApproach": 7, + "ingressPath": true, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 5, + "maneuver": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": true, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 3 + } + ] + } + }, + { + "type": "Feature", + "id": 18, + "geometry": "LINESTRING (-111.79586975367667 40.37694478013608, -111.79586975367667 40.376992300183595)", + "properties": { + "laneId": 18, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 8, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 19, + "geometry": "LINESTRING (-111.79583076705676 40.37694685013815, -111.79583076705676 40.3769959001872)", + "properties": { + "laneId": 19, + "laneType": { + "vehicle": { + "isVehicleRevocableLane": false, + "isVehicleFlyOverLane": false, + "hovLaneUseOnly": false, + "restrictedToBusUse": false, + "restrictedToTaxiUse": false, + "restrictedFromPublicUse": false, + "hasIRbeaconCoverage": false, + "permissionOnRequest": false + } + }, + "egressApproach": 8, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": true, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 27, + "geometry": "LINESTRING (-111.7957846919605 40.37693083012213, -111.79576720702049 40.37693443012573, -111.7957705149823 40.37692525011655)", + "properties": { + "laneId": 27, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 202 + }, + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 204 + } + ] + } + }, + { + "type": "Feature", + "id": 21, + "geometry": "LINESTRING (-111.7958172989517 40.376685489876785, -111.7958162356822 40.37667054986184, -111.79582899491346 40.37667306986436)", + "properties": { + "laneId": 21, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 20, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 204 + }, + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 206 + } + ] + } + }, + { + "type": "Feature", + "id": 23, + "geometry": "LINESTRING (-111.79604637487897 40.376672079863376, -111.7960665769956 40.376669019860316, -111.79606421417505 40.37668188987318)", + "properties": { + "laneId": 23, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 22, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 206 + }, + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 208 + } + ] + } + }, + { + "type": "Feature", + "id": 25, + "geometry": "LINESTRING (-111.79605712573476 40.37691148010278, -111.79606385979757 40.376922730114025, -111.79605240007474 40.37692174011303)", + "properties": { + "laneId": 25, + "laneType": { + "sidewalk": { + "sidewalk-RevocableLane": false, + "bicyleUseAllowed": true, + "isSidewalkFlyOverLane": false, + "walkBikes": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + }, + "connectsTo": [ + { + "connectingLane": { + "lane": 26, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 202 + }, + { + "connectingLane": { + "lane": 24, + "maneuver": { + "maneuverStraightAllowed": true, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + }, + "signalGroup": 208 + } + ] + } + }, + { + "type": "Feature", + "id": 20, + "geometry": "LINESTRING (-111.7957722871269 40.37692282011412, -111.79581907115002 40.37668683987814)", + "properties": { + "laneId": 20, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": true, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 22, + "geometry": "LINESTRING (-111.79583312988221 40.376672529863825, -111.79604436605044 40.37667306986437)", + "properties": { + "laneId": 22, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": true, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 24, + "geometry": "LINESTRING (-111.79606315093966 40.37668278987409, -111.79605712574602 40.376910490101785)", + "properties": { + "laneId": 24, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": false, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + }, + { + "type": "Feature", + "id": 26, + "geometry": "LINESTRING (-111.79604980097587 40.3769212001125, -111.79578882646929 40.37693038012168)", + "properties": { + "laneId": 26, + "laneType": { + "crosswalk": { + "crosswalkRevocableLane": false, + "bicyleUseAllowed": true, + "isXwalkFlyOverLane": false, + "fixedCycleTime": false, + "biDirectionalCycleTimes": false, + "hasPushToWalkButton": true, + "audioSupport": false, + "rfSignalRequestPresent": false, + "unsignalizedSegmentsPresent": false + } + }, + "egressApproach": 0, + "ingressApproach": 0, + "ingressPath": false, + "egressPath": false, + "maneuvers": { + "maneuverStraightAllowed": false, + "maneuverLeftAllowed": false, + "maneuverRightAllowed": false, + "maneuverUTurnAllowed": false, + "maneuverLeftTurnOnRedAllowed": false, + "maneuverRightTurnOnRedAllowed": false, + "maneuverLaneChangeAllowed": false, + "maneuverNoStoppingAllowed": false, + "yieldAllwaysRequired": false, + "goWithHalt": false, + "caution": false, + "reserved1": false + } + } + } + ] + }, + "connectingLanesFeatureCollection": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "2-14", + "geometry": "LINESTRING (-111.79574771374223 40.37685433004563, -111.79607957257653 40.37685847004977)", + "properties": { + "signalGroupId": 2, + "ingressLaneId": 2, + "egressLaneId": 14 + } + }, + { + "type": "Feature", + "id": "3-13", + "geometry": "LINESTRING (-111.79575220311058 40.376821570012865, -111.79607957257653 40.37682472001602)", + "properties": { + "signalGroupId": 2, + "ingressLaneId": 3, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "1-18", + "geometry": "LINESTRING (-111.79574216110242 40.37688637007767, -111.79586975367667 40.37694478013608)", + "properties": { + "signalGroupId": 12, + "ingressLaneId": 1, + "egressLaneId": 18 + } + }, + { + "type": "Feature", + "id": "1-19", + "geometry": "LINESTRING (-111.79574216110242 40.37688637007767, -111.79583076705676 40.37694685013815)", + "properties": { + "signalGroupId": 12, + "ingressLaneId": 1, + "egressLaneId": 19 + } + }, + { + "type": "Feature", + "id": "4-9", + "geometry": "LINESTRING (-111.79576094556474 40.37678988998119, -111.79598246045057 40.37665497984628)", + "properties": { + "signalGroupId": 5, + "ingressLaneId": 4, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "7-6", + "geometry": "LINESTRING (-111.79587802356573 40.37664390983521, -111.7957885906225 40.3767204999118)", + "properties": { + "signalGroupId": 14, + "ingressLaneId": 7, + "egressLaneId": 6 + } + }, + { + "type": "Feature", + "id": "7-18", + "geometry": "LINESTRING (-111.79587802356573 40.37664390983521, -111.79586975367667 40.37694478013608)", + "properties": { + "signalGroupId": 4, + "ingressLaneId": 7, + "egressLaneId": 18 + } + }, + { + "type": "Feature", + "id": "7-19", + "geometry": "LINESTRING (-111.79587802356573 40.37664390983521, -111.79583076705676 40.37694685013815)", + "properties": { + "signalGroupId": 4, + "ingressLaneId": 7, + "egressLaneId": 19 + } + }, + { + "type": "Feature", + "id": "7-5", + "geometry": "LINESTRING (-111.79587802356573 40.37664390983521, -111.79578315612396 40.376754159945456)", + "properties": { + "signalGroupId": 14, + "ingressLaneId": 7, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "8-13", + "geometry": "LINESTRING (-111.79591925486982 40.376643999835295, -111.79607957257653 40.37682472001602)", + "properties": { + "signalGroupId": 7, + "ingressLaneId": 8, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "8-14", + "geometry": "LINESTRING (-111.79591925486982 40.376643999835295, -111.79607957257653 40.37685847004977)", + "properties": { + "signalGroupId": 7, + "ingressLaneId": 8, + "egressLaneId": 14 + } + }, + { + "type": "Feature", + "id": "11-5", + "geometry": "LINESTRING (-111.79609953845157 40.37676036995167, -111.79578315612396 40.376754159945456)", + "properties": { + "signalGroupId": 6, + "ingressLaneId": 11, + "egressLaneId": 5 + } + }, + { + "type": "Feature", + "id": "10-9", + "geometry": "LINESTRING (-111.79609965659284 40.37672877992008, -111.79598246045057 40.37665497984628)", + "properties": { + "signalGroupId": 16, + "ingressLaneId": 10, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "10-6", + "geometry": "LINESTRING (-111.79609965659284 40.37672877992008, -111.7957885906225 40.3767204999118)", + "properties": { + "signalGroupId": 6, + "ingressLaneId": 10, + "egressLaneId": 6 + } + }, + { + "type": "Feature", + "id": "12-18", + "geometry": "LINESTRING (-111.79609965659284 40.37679204998335, -111.79586975367667 40.37694478013608)", + "properties": { + "signalGroupId": 1, + "ingressLaneId": 12, + "egressLaneId": 18 + } + }, + { + "type": "Feature", + "id": "12-19", + "geometry": "LINESTRING (-111.79609965659284 40.37679204998335, -111.79583076705676 40.37694685013815)", + "properties": { + "signalGroupId": 1, + "ingressLaneId": 12, + "egressLaneId": 19 + } + }, + { + "type": "Feature", + "id": "15-14", + "geometry": "LINESTRING (-111.79599817323981 40.376953870145165, -111.79607957257653 40.37685847004977)", + "properties": { + "signalGroupId": 18, + "ingressLaneId": 15, + "egressLaneId": 14 + } + }, + { + "type": "Feature", + "id": "15-9", + "geometry": "LINESTRING (-111.79599817323981 40.376953870145165, -111.79598246045057 40.37665497984628)", + "properties": { + "signalGroupId": 8, + "ingressLaneId": 15, + "egressLaneId": 9 + } + }, + { + "type": "Feature", + "id": "15-13", + "geometry": "LINESTRING (-111.79599817323981 40.376953870145165, -111.79607957257653 40.37682472001602)", + "properties": { + "signalGroupId": 18, + "ingressLaneId": 15, + "egressLaneId": 13 + } + }, + { + "type": "Feature", + "id": "16-6", + "geometry": "LINESTRING (-111.79595623308809 40.37695486014616, -111.7957885906225 40.3767204999118)", + "properties": { + "signalGroupId": 3, + "ingressLaneId": 16, + "egressLaneId": 6 + } + }, + { + "type": "Feature", + "id": "17-5", + "geometry": "LINESTRING (-111.79591452921892 40.37695513014643, -111.79578315612396 40.376754159945456)", + "properties": { + "signalGroupId": 3, + "ingressLaneId": 17, + "egressLaneId": 5 + } + } + ] + }, + "properties": { + "schemaVersion": 2, + "messageType": "MAP", + "odeReceivedAt": "2025-08-01T15:05:42.572Z", + "originIp": "172.18.0.1", + "asn1": "001282AB780CC3780302071583B3869DD95048EFE5026411504DC3A7720A7D02F120D4DB5EC1728A71DDD462402DC0514F8D16010A0D0001000102DB49FB2D3693FE40B9FDF1C5BD6EC22CAC71216343610B1459703EC52E0B2556403915340243A00008B00C50680008000816C7447969BA1FF345CC4F9A2DD476D164AB8B8B115B385852CDA1F4095C58C4B421CB89CC121B0000458022834000120008B78ED7CB4D5EFF782E8473F148910006244C80030B01050680004000116A23979360B7F783F22498242500014401488680000016442D103FB7E84018886800000162D21607063FA2C07341A00029000052CA1B257F9F58AC348310007244A00011227000089052000E2C08341A00010000450101B437F41D88511278A290D40007487200038804A10D00000025F11540C313FE5816A834000400000884979CAA90500B80905800062C0A541A000290000442291055483804A148490008241A00018B0315068000400011108BA390B8380702151C78A4490000522680002201AC4340000008AEE2C827A6058807310D00000022BBA2909EE80C581EE83400052001095B3934901176822956EBC13FAE8C92438800492130001090D200122C10741A0001000044D9FCB0480BBB00144FF5B824190000CB045D06800040001141872D92006EB984F2FD760905400031012821A0000005357BD01801840404E086800000157AEFF86006210C1B0069A000400008B1EF53414A45007919A148D40065245200330305401A68001000022B672A70412AD0194870522900198916800CE0C170069A0004000088F508480AABBC08528F148B40067246200340306401A68001000022379C76038F3E82617D4523500194918800D000140068A200000B3933D06E742E1000B0034510000055C242E21048060018006882000008D18A247033CF1000D00345100000476F9C43C50C1980", + "intersectionName": "Alpine Hwy & E Main St", + "intersectionId": 6025, + "msgIssueRevision": 0, + "revision": 3, + "refPoint": { + "latitude": 40.3768087, + "longitude": -111.7959202, + "elevation": 1386.0 + }, + "cti4501Conformant": false, + "laneWidth": 366, + "speedLimits": [ + { + "type": "VEHICLEMAXSPEED", + "speed": 671 + } + ], + "mapSource": "RSU", + "timeStamp": "2025-03-14T14:39:00Z" + } +} \ No newline at end of file From 9df2ee986e6ba5d4236543495253c6a9406d4371 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 1 Aug 2025 12:45:25 -0600 Subject: [PATCH 11/24] Update release notes and application.yaml --- docs/Release_notes.md | 1 + jpo-deduplicator/src/main/resources/application.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/Release_notes.md b/docs/Release_notes.md index f99986b..98819b7 100644 --- a/docs/Release_notes.md +++ b/docs/Release_notes.md @@ -17,6 +17,7 @@ The first release of the jpo-deduplicator package. This package focuses on remov - OdeMapJson - OdeBsmJson - OdeTimJson + - OdeRawEncodedTim This release also makes additional changes to the submodule components as follows diff --git a/jpo-deduplicator/src/main/resources/application.yaml b/jpo-deduplicator/src/main/resources/application.yaml index 366a30d..6143bd0 100644 --- a/jpo-deduplicator/src/main/resources/application.yaml +++ b/jpo-deduplicator/src/main/resources/application.yaml @@ -43,7 +43,7 @@ kafkaTopicDeduplicatedOdeBsmJson: topic.DeduplicatedOdeBsmJson enableOdeBsmDeduplication: ${ENABLE_ODE_BSM_DEDUPLICATION:true} odeBsmMaximumTimeDelta: 10000 # Milliseconds odeBsmMaximumPositionDelta: 1 # Meter -odeBsmAlwaysIncludeAtSpeed: 20 # Meter / Second +odeBsmAlwaysIncludeAtSpeed: 1 # x 0.02 Meter / Second (J2735 defined) # Processed Map Configuration kafkaTopicProcessedSpat: topic.ProcessedSpat From 98a7bcc5f58858fc93208b1d78af518bd4c21220 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 1 Aug 2025 15:13:37 -0600 Subject: [PATCH 12/24] Add new deduplication documentation as well as modify duplication rules for OdeMapJson and OdeTimJson --- README.md | 35 ++++++++++++++++++- .../processors/OdeMapJsonProcessor.java | 15 ++++---- .../processors/OdeTimJsonProcessor.java | 11 ++++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1b961bd..6750f6f 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,46 @@ The JPO-Deduplicator is a Kafka Java spring-boot application designed to reduce The following topics currently support deduplication. +- topic.OdeMapJson -> topic.DeduplicatedOdeMapJson - topic.ProcessedMap -> topic.DeduplicatedProcessedMap - topic.ProcessedMapWKT -> topic.DeduplicatedProcessedMapWKT -- topic.OdeMapJson -> topic.DeduplicatedOdeMapJson - topic.OdeTimJson -> topic.DeduplicatedOdeTimJson - topic.OdeBsmJson -> topic.DeduplicatedOdeBsmJson +- topic.ProcessedBsm -> topic.DeduplicatedProcessedBsm - topic.ProcessedSpat -> topic.DeduplicatedProcessedSpat +## Topic Deduplication Rules + +The processes that determine which messages are duplicates are unique and customized for each message type. The following is a detailed explanation on each message type's criteria for when messages are deduplicated. All of the criteria must be met for a single message type. + +### OdeMapJson +- Two messages within a 1 hour time window +- Two messages have the same intersection ID + +### ProcessedMap and ProcessedMapWKT +- Two messages within a 1 hour time window +- Two messages have the same hash values after factoring out the odeReceivedAt and timeStamp fields + +### OdeTimJson +- Two messages within a 1 hour time window +- Two messages have the same packet ID + +### OdeBsmJson +- Two messages within the defined time threshold defined by the `odeBsmMaximumTimeDelta` value in application.yaml +- The new message's speed is identical to the previous message's speed +- The new message's speed is below the speed threshold defined by the `odeBsmAlwaysIncludeAtSpeed` value in application.yaml +- The position delta between the messages is not suitably large defined by the `odeBsmMaximumPositionDelta` value in application.yaml or position information is null + +### ProcessedBsm +- Two messages within the defined time threshold defined by the `odeBsmMaximumTimeDelta` value in application.yaml +- The new speed is below the speed threshold defined by the `odeBsmAlwaysIncludeAtSpeed` value in application.yaml +- The position delta between the messages is not suitably large defined by the `odeBsmMaximumPositionDelta` value in application.yaml or position information is null + +### ProcessedSpat +- Two messages within 1 minute time window +- Signal states are identical +- Signal light phases are identical + ## Release Notes The current version and release history of the JPO Deduplicator: [Release Notes]() 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 cc631d3..b749daa 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 @@ -66,24 +66,21 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData return false; } + // Check if the Map intersection IDs are the same MapDataMessageFrame oldMap = (MapDataMessageFrame) lastMessage.getPayload().getData(); + int oldMapIntersectionId = (int) oldMap.getValue().getIntersections().get(0).getId().getId().getValue(); MapDataMessageFrame newMap = (MapDataMessageFrame) newMessage.getPayload().getData(); + int newMapIntersectionId = (int) newMap.getValue().getIntersections().get(0).getId().getId().getValue(); - // Compare map data for equality - if (oldMap == null || newMap == null || oldMap.getValue() == null || newMap.getValue() == null) { + if (oldMapIntersectionId != newMapIntersectionId) { 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); } + // Treat maps as duplicates if they have the same intersection ID and + // are within the 1 hour time window 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 f036903..4e69d3d 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 @@ -7,6 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformationMessageFrame; import us.dot.its.jpo.deduplicator.DeduplicatorProperties; import us.dot.its.jpo.ode.model.OdeMessageFrameData; import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata; @@ -64,6 +65,16 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData logger.warn("One or both TIM messages have null payload or data, treating as non-duplicate"); return false; } + + // Check if the TIM packet IDs are the same + TravelerInformationMessageFrame oldTim = (TravelerInformationMessageFrame) lastMessage.getPayload().getData(); + TravelerInformationMessageFrame newTim = (TravelerInformationMessageFrame) newMessage.getPayload().getData(); + String oldTimPacketId = oldTim.getValue().getPacketID().getValue(); + String newTimPacketId = newTim.getValue().getPacketID().getValue(); + + if (!oldTimPacketId.equals(newTimPacketId)) { + return false; + } } catch(Exception e){ logger.warn("Caught General Exception" + e); } From 221b2262c19dd5035c0dabf8712c4fb071b6b19d Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 1 Aug 2025 16:05:33 -0600 Subject: [PATCH 13/24] Address comments --- README.md | 1 + .../deduplicator/processors/OdeBsmJsonProcessor.java | 8 ++++++-- .../deduplicator/processors/OdeTimJsonProcessor.java | 5 +++++ jpo-deduplicator/src/main/resources/application.yaml | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6750f6f..acc9953 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ The processes that determine which messages are duplicates are unique and custom ### OdeTimJson - Two messages within a 1 hour time window - Two messages have the same packet ID +- Two message have the same msgCnt value ### OdeBsmJson - Two messages within the defined time threshold defined by the `odeBsmMaximumTimeDelta` value in application.yaml 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 55b5245..22f7619 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 @@ -87,8 +87,12 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData // 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 (newSpeedAvailable) { + // Convert to m/s (J2735 speed is in 0.02 m/s increments * 0 - 8190) + double newSpeed = newCore.getSpeed().getValue() * 0.02; + if (newSpeed > props.getOdeBsmAlwaysIncludeAtSpeed()) { + return false; + } } // If the new core and the old core have different null conditions 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 4e69d3d..1d1b4de 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 @@ -75,6 +75,11 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData if (!oldTimPacketId.equals(newTimPacketId)) { return false; } + + // Check if the message count of the new TIM is identical to the old TIM + if (newTim.getValue().getMsgCnt().getValue() != oldTim.getValue().getMsgCnt().getValue()) { + return false; + } } catch(Exception e){ logger.warn("Caught General Exception" + e); } diff --git a/jpo-deduplicator/src/main/resources/application.yaml b/jpo-deduplicator/src/main/resources/application.yaml index 6143bd0..3efd86e 100644 --- a/jpo-deduplicator/src/main/resources/application.yaml +++ b/jpo-deduplicator/src/main/resources/application.yaml @@ -43,7 +43,7 @@ kafkaTopicDeduplicatedOdeBsmJson: topic.DeduplicatedOdeBsmJson enableOdeBsmDeduplication: ${ENABLE_ODE_BSM_DEDUPLICATION:true} odeBsmMaximumTimeDelta: 10000 # Milliseconds odeBsmMaximumPositionDelta: 1 # Meter -odeBsmAlwaysIncludeAtSpeed: 1 # x 0.02 Meter / Second (J2735 defined) +odeBsmAlwaysIncludeAtSpeed: 1 # Meter / Second # Processed Map Configuration kafkaTopicProcessedSpat: topic.ProcessedSpat From 319b117f2781ecc2dfac995df1ac4733f1d6ad09 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Tue, 5 Aug 2025 02:38:37 -0600 Subject: [PATCH 14/24] Removed redundant logic for TIM dedup processing --- .../processors/OdeTimJsonProcessor.java | 16 ---------------- 1 file changed, 16 deletions(-) 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 1d1b4de..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 @@ -7,7 +7,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformationMessageFrame; import us.dot.its.jpo.deduplicator.DeduplicatorProperties; import us.dot.its.jpo.ode.model.OdeMessageFrameData; import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata; @@ -65,21 +64,6 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData logger.warn("One or both TIM messages have null payload or data, treating as non-duplicate"); return false; } - - // Check if the TIM packet IDs are the same - TravelerInformationMessageFrame oldTim = (TravelerInformationMessageFrame) lastMessage.getPayload().getData(); - TravelerInformationMessageFrame newTim = (TravelerInformationMessageFrame) newMessage.getPayload().getData(); - String oldTimPacketId = oldTim.getValue().getPacketID().getValue(); - String newTimPacketId = newTim.getValue().getPacketID().getValue(); - - if (!oldTimPacketId.equals(newTimPacketId)) { - return false; - } - - // Check if the message count of the new TIM is identical to the old TIM - if (newTim.getValue().getMsgCnt().getValue() != oldTim.getValue().getMsgCnt().getValue()) { - return false; - } } catch(Exception e){ logger.warn("Caught General Exception" + e); } From 5d70433b8927f3e7b573314d5b3bb1b848ddf7db Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Tue, 5 Aug 2025 02:44:21 -0600 Subject: [PATCH 15/24] Remove redundant OdeMapJson dedup logic that was added --- .../deduplicator/processors/OdeMapJsonProcessor.java | 11 ----------- 1 file changed, 11 deletions(-) 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 b749daa..9c53614 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 @@ -10,7 +10,6 @@ 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 { @@ -65,16 +64,6 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData logger.warn("One or both Map messages have null payload or data, treating as non-duplicate"); return false; } - - // Check if the Map intersection IDs are the same - MapDataMessageFrame oldMap = (MapDataMessageFrame) lastMessage.getPayload().getData(); - int oldMapIntersectionId = (int) oldMap.getValue().getIntersections().get(0).getId().getId().getValue(); - MapDataMessageFrame newMap = (MapDataMessageFrame) newMessage.getPayload().getData(); - int newMapIntersectionId = (int) newMap.getValue().getIntersections().get(0).getId().getId().getValue(); - - if (oldMapIntersectionId != newMapIntersectionId) { - return false; - } } catch (Exception e) { logger.warn("Caught General Exception while checking Map duplicates: " + e.getMessage(), e); } From 267aaf354df8ff353afcc89bfff063c970988052 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Wed, 6 Aug 2025 14:40:50 -0600 Subject: [PATCH 16/24] Remove the conflictmonitor.version from the pom --- jpo-deduplicator/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/jpo-deduplicator/pom.xml b/jpo-deduplicator/pom.xml index 0e2d79c..ff77160 100644 --- a/jpo-deduplicator/pom.xml +++ b/jpo-deduplicator/pom.xml @@ -34,7 +34,6 @@ java 5.0.2 3.0.2 - 1.5.0 @@ -59,10 +58,6 @@ - org.springframework.boot spring-boot-devtools From ad2ed6eb766e035e1dc83144fc5fc388b801388f Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Wed, 6 Aug 2025 17:07:12 -0600 Subject: [PATCH 17/24] Address some of the pull request comments --- .../deduplicator/DeduplicatorProperties.java | 9 +---- .../processors/OdeBsmJsonProcessor.java | 36 ++++-------------- .../processors/OdeMapJsonProcessor.java | 36 ++++-------------- .../processors/OdeTimJsonProcessor.java | 38 ++++--------------- .../jpo/deduplicator/utils/OdeJsonUtils.java | 35 +++++++++++++++++ 5 files changed, 60 insertions(+), 94 deletions(-) create mode 100644 jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/OdeJsonUtils.java 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 ff41acc..d16c50e 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 @@ -129,7 +129,6 @@ void initialize() { logger.info("groupId: {}", buildProperties.getGroup()); logger.info("artifactId: {}", buildProperties.getArtifact()); logger.info("version: {}", version); - // OdeMsgMetadata.setStaticSchemaVersion(OUTPUT_SCHEMA_VERSION); String hostname; try { @@ -191,8 +190,6 @@ 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); // Decrease default commit interval. Default for 'at least once' mode of 30000ms // is too slow. @@ -207,16 +204,12 @@ public Properties createStreamProperties(String name) { } else if (SystemUtils.IS_OS_WINDOWS) { streamProps.put(StreamsConfig.STATE_DIR_CONFIG, "C:/temp/ode"); } - // streamProps.put(StreamsConfig.STATE_DIR_CONFIG, "/var/lib/")\ // Increase max.block.ms and delivery.timeout.ms for streams final int FIVE_MINUTES_MS = 5 * 60 * 1000; streamProps.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, FIVE_MINUTES_MS); streamProps.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, FIVE_MINUTES_MS); - // Disable batching - // streamProps.put(ProducerConfig.BATCH_SIZE_CONFIG, 0); - streamProps.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "zstd"); streamProps.put(ProducerConfig.LINGER_MS_CONFIG, getKafkaLingerMs()); @@ -419,7 +412,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); + logger.warn("Something went wrong retrieving the environment variable " + variableName); } return value; } 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 22f7619..9ccc1e1 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 @@ -2,22 +2,20 @@ 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.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; +import us.dot.its.jpo.deduplicator.utils.OdeJsonUtils; public class OdeBsmJsonProcessor extends DeduplicationProcessor { - DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; DeduplicatorProperties props; private static final Logger logger = LoggerFactory.getLogger(OdeBsmJsonProcessor.class); @@ -29,25 +27,7 @@ public OdeBsmJsonProcessor(String storeName, DeduplicatorProperties props) { @Override 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: " + (message != null && message.getMetadata() != null - ? ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt() - : "null"), e); - return Instant.ofEpochMilli(0); - } + return OdeJsonUtils.getOdeMessageFrameMessageTime(message); } @Override @@ -62,12 +42,12 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData 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 BSM messages have null payload or data, treating as non-duplicate"); - return false; + // Check for null conditions - treat as non-duplicate if one is null and the other is not + boolean lastMessageIsNull = (lastMessage == null || lastMessage.getPayload() == null || lastMessage.getPayload().getData() == null); + boolean newMessageIsNull = (newMessage == null || newMessage.getPayload() == null || newMessage.getPayload().getData() == null); + if ((lastMessageIsNull && !newMessageIsNull) || (!lastMessageIsNull && newMessageIsNull)) { + logger.warn("One TIM message has a null payload or data, treating as non-duplicate"); + return true; } BSMcoreData oldCore = ((BasicSafetyMessageMessageFrame) lastMessage.getPayload().getData()).getValue() 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 9c53614..88c2864 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 @@ -2,18 +2,16 @@ 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.deduplicator.utils.OdeJsonUtils; import us.dot.its.jpo.ode.model.OdeMessageFrameData; -import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata; public class OdeMapJsonProcessor extends DeduplicationProcessor { - DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; DeduplicatorProperties props; private static final Logger logger = LoggerFactory.getLogger(OdeMapJsonProcessor.class); @@ -25,25 +23,7 @@ public OdeMapJsonProcessor(String storeName, DeduplicatorProperties 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); - } + return OdeJsonUtils.getOdeMessageFrameMessageTime(message); } @Override @@ -57,12 +37,12 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData 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; + // Check for null conditions - treat as non-duplicate if one is null and the other is not + boolean lastMessageIsNull = (lastMessage == null || lastMessage.getPayload() == null || lastMessage.getPayload().getData() == null); + boolean newMessageIsNull = (newMessage == null || newMessage.getPayload() == null || newMessage.getPayload().getData() == null); + if ((lastMessageIsNull && !newMessageIsNull) || (!lastMessageIsNull && newMessageIsNull)) { + logger.warn("One TIM message has a null payload or data, treating as non-duplicate"); + return true; } } catch (Exception e) { logger.warn("Caught General Exception while checking Map duplicates: " + e.getMessage(), e); 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 f036903..e3a4314 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 @@ -2,19 +2,16 @@ 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.deduplicator.utils.OdeJsonUtils; import us.dot.its.jpo.ode.model.OdeMessageFrameData; -import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata; public class OdeTimJsonProcessor extends DeduplicationProcessor{ - DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; - private static final Logger logger = LoggerFactory.getLogger(OdeTimJsonProcessor.class); DeduplicatorProperties props; @@ -23,28 +20,9 @@ public OdeTimJsonProcessor(DeduplicatorProperties props){ this.storeName = props.getKafkaStateStoreOdeTimJsonName(); } - @Override public Instant getMessageTime(OdeMessageFrameData message) { - try { - 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); - } + return OdeJsonUtils.getOdeMessageFrameMessageTime(message); } @Override @@ -57,12 +35,12 @@ public boolean isDuplicate(OdeMessageFrameData lastMessage, OdeMessageFrameData 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; + // Check for null conditions - treat as non-duplicate if one is null and the other is not + boolean lastMessageIsNull = (lastMessage == null || lastMessage.getPayload() == null || lastMessage.getPayload().getData() == null); + boolean newMessageIsNull = (newMessage == null || newMessage.getPayload() == null || newMessage.getPayload().getData() == null); + if ((lastMessageIsNull && !newMessageIsNull) || (!lastMessageIsNull && newMessageIsNull)) { + logger.warn("One TIM message has a null payload or data, treating as non-duplicate"); + return true; } } catch(Exception e){ logger.warn("Caught General Exception" + e); diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/OdeJsonUtils.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/OdeJsonUtils.java new file mode 100644 index 0000000..d614e9c --- /dev/null +++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/utils/OdeJsonUtils.java @@ -0,0 +1,35 @@ +package us.dot.its.jpo.deduplicator.utils; + +import java.time.Instant; +import java.time.format.DateTimeFormatter; + +import lombok.extern.slf4j.Slf4j; +import us.dot.its.jpo.ode.model.OdeMessageFrameData; +import us.dot.its.jpo.ode.model.OdeMessageFrameMetadata; + +@Slf4j +public class OdeJsonUtils { + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; + + public static Instant getOdeMessageFrameMessageTime(OdeMessageFrameData message) { + try { + if (message == null || message.getMetadata() == null) { + log.warn("The MessageFrame message or metadata is null, using epoch time"); + return Instant.ofEpochMilli(0); + } + + String time = ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt(); + if (time == null || time.isEmpty()) { + log.warn("The MessageFrame message has null or empty odeReceivedAt time, using epoch time"); + return Instant.ofEpochMilli(0); + } + + return Instant.from(formatter.parse(time)); + } catch (Exception e) { + log.warn("Failed to Parse Time: " + (message != null && message.getMetadata() != null + ? ((OdeMessageFrameMetadata) message.getMetadata()).getOdeReceivedAt() + : "null"), e); + return Instant.ofEpochMilli(0); + } + } +} From de8e803c564b4b0986dc381fa146ae9d81b87c50 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Thu, 7 Aug 2025 17:27:59 -0600 Subject: [PATCH 18/24] Address additional pull request comments --- .../processors/ProcessedMapProcessor.java | 2 +- .../processors/ProcessedMapWktProcessor.java | 2 +- .../serialization/JsonSerdes.java | 12 ---------- .../topologies/BsmDeduplicatorTopology.java | 24 ------------------- .../ProcessedMapDeduplicatorTopologyTest.java | 4 ++-- ...ocessedMapWktDeduplicatorTopologyTest.java | 4 ++-- 6 files changed, 6 insertions(+), 42 deletions(-) diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java index 5e69542..23c7d72 100644 --- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java +++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java @@ -27,7 +27,7 @@ public ProcessedMapProcessor(DeduplicatorProperties props){ @Override public Instant getMessageTime(ProcessedMap message) { try { - return message.getProperties().getTimeStamp().toInstant(); + return message.getProperties().getOdeReceivedAt().toInstant(); } catch (Exception e) { return Instant.ofEpochMilli(0); } diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java index e69814b..6a23b0e 100644 --- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java +++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapWktProcessor.java @@ -25,7 +25,7 @@ public ProcessedMapWktProcessor(DeduplicatorProperties props){ @Override public Instant getMessageTime(ProcessedMap message) { try { - return message.getProperties().getTimeStamp().toInstant(); + return message.getProperties().getOdeReceivedAt().toInstant(); } catch (Exception e) { return Instant.ofEpochMilli(0); } 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 4a8407d..787fef5 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 @@ -4,8 +4,6 @@ import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.common.serialization.Serdes; -import com.fasterxml.jackson.databind.JsonNode; - 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; @@ -44,17 +42,7 @@ public static Serde OdeMessageFrame(DeduplicatorProperties new SafeJsonDeserializer<>(OdeMessageFrameData.class)); } - public static Serde JSON(DeduplicatorProperties props) { - return Serdes.serdeFrom( - new JsonSerializer(), - new JsonDeserializer<>(JsonNode.class)); - } - 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 b6639dd..b87afb9 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 @@ -9,7 +9,6 @@ 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.BasicSafetyMessage.BasicSafetyMessageMessageFrame; import org.apache.kafka.streams.kstream.*; import org.apache.kafka.streams.state.Stores; @@ -18,7 +17,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; -import java.time.Instant; import java.time.format.DateTimeFormatter; import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeBsmJsonProcessorSupplier; @@ -54,28 +52,6 @@ public void start() { streams.start(); } - 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(); 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 936c658..739824f 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 @@ -77,9 +77,9 @@ public void setup() throws IOException { // Message 1 but 1 hour later ProcessedMap processedMap1HourLater = objectMapper.readValue(processedMapReference, typeReference); - ZonedDateTime originalZdt = processedMap1HourLater.getProperties().getTimeStamp(); + ZonedDateTime originalZdt = processedMap1HourLater.getProperties().getOdeReceivedAt(); Instant newInstant = originalZdt.toInstant().plusSeconds(3601); - processedMap1HourLater.getProperties().setTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); + processedMap1HourLater.getProperties().setOdeReceivedAt(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); inputProcessedMap3 = processedMap1HourLater.toString(); // A different Message entirely 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 ac49555..8ea83d8 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 @@ -75,9 +75,9 @@ public void setup() throws IOException { // Message 1 but 1 hour later ProcessedMap processedMapWkt1HourLater = objectMapper.readValue(processedMapWktReference, typeReference); - ZonedDateTime originalZdt = processedMapWkt1HourLater.getProperties().getTimeStamp(); + ZonedDateTime originalZdt = processedMapWkt1HourLater.getProperties().getOdeReceivedAt(); Instant newInstant = originalZdt.toInstant().plusSeconds(3601); - processedMapWkt1HourLater.getProperties().setTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); + processedMapWkt1HourLater.getProperties().setOdeReceivedAt(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); inputProcessedMapWkt3 = processedMapWkt1HourLater.toString(); // A different Message entirely From 41d50572369cf48861c74b025d29de3037b0e0f8 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Thu, 7 Aug 2025 17:46:59 -0600 Subject: [PATCH 19/24] Discard messages with 'unknown' keys for MessageFrame topologies --- .../topologies/BsmDeduplicatorTopology.java | 16 +++++++--- .../topologies/MapDeduplicatorTopology.java | 16 +++++++--- .../topologies/TimDeduplicatorTopology.java | 32 +++++++++++++++---- 3 files changed, 50 insertions(+), 14 deletions(-) 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 b87afb9..d063268 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 @@ -65,23 +65,31 @@ public Topology buildTopology() { 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"); + logger.warn("Received BSM message with null payload or data, discarding message"); 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"); + logger.warn("Received BSM message with null message frame data, discarding message"); return "unknown"; } return mf.getValue().getCoreData().getId().getValue(); } catch (Exception e) { - logger.error("Error extracting key from BSM message: " + e.getMessage(), e); + logger.error("Error extracting key from BSM message: " + e.getMessage() + ", discarding message", e); return "unknown"; } - }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame())); + }) + .filter((key, value) -> { + if ("unknown".equals(key)) { + logger.debug("Discarding BSM message with unknown key"); + return false; + } + return true; + }) + .repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame())); KStream deduplicatedStream = bsmRekeyedStream.process( new OdeBsmJsonProcessorSupplier(props.getKafkaStateStoreOdeBsmJsonName(), props), 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 11205fa..10923e0 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 @@ -68,14 +68,14 @@ public Topology buildTopology() { 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"); + logger.warn("Received Map message with null payload or data, discarding message"); return "unknown"; } 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"); + logger.warn("Received Map message with null message frame data, discarding message"); return "unknown"; } @@ -84,10 +84,18 @@ public Topology buildTopology() { 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); + logger.error("Error extracting key from Map message: " + e.getMessage() + ", discarding message", e); return "unknown"; } - }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame())); + }) + .filter((key, value) -> { + if ("unknown".equals(key)) { + logger.debug("Discarding Map message with unknown key"); + return false; + } + return true; + }) + .repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame())); KStream deduplicatedStream = mapRekeyedStream.process( new OdeMapJsonProcessorSupplier(props.getKafkaStateStoreOdeMapJsonName(), props), 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 e8cd33f..6478941 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 @@ -21,6 +21,7 @@ import java.time.format.DateTimeFormatter; import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformation; +import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformationMessageFrame; 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; @@ -72,17 +73,36 @@ public Topology buildTopology() { KStream timRekeyedStream = inputStream.selectKey((key, value) -> { try { - TravelerInformation travellerInformation = (TravelerInformation) value.getPayload().getData().getValue(); + if (value == null || value.getPayload() == null || value.getPayload().getData() == null) { + logger.warn("Received TIM message with null payload or data, discarding message"); + return "unknown"; + } + + TravelerInformationMessageFrame mf = (TravelerInformationMessageFrame) value.getPayload().getData(); + if (mf == null || mf.getValue() == null || mf.getValue().getPacketID() == null || + mf.getValue().getMsgCnt() == null) { + logger.warn("Received TIM message with null message frame data, discarding message"); + return "unknown"; + } + String rsuIP = value.getMetadata().getOriginIp(); - String packetId = travellerInformation.getPacketID().getValue(); - int msgCnt = (int) travellerInformation.getMsgCnt().getValue(); + String packetId = mf.getValue().getPacketID().getValue(); + int msgCnt = (int) mf.getValue().getMsgCnt().getValue(); String newKey = rsuIP + "_" + packetId + "_" + msgCnt; return newKey; } catch (Exception e) { - logger.error(e.toString()); - return ""; + logger.error("Error extracting key from TIM message: " + e.getMessage() + ", discarding message", e); + return "unknown"; + } + }) + .filter((key, value) -> { + if ("unknown".equals(key)) { + logger.debug("Discarding Map message with unknown key"); + return false; } - }).repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame())); + return true; + }) + .repartition(Repartitioned.with(Serdes.String(), JsonSerdes.OdeMessageFrame())); KStream deduplicatedStream = timRekeyedStream.process(new OdeTimJsonProcessorSupplier(props), props.getKafkaStateStoreOdeTimJsonName()); From 04931611c21d9c38c5a11e50a38548e5d4cb5cb1 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 8 Aug 2025 00:00:02 -0600 Subject: [PATCH 20/24] Add moy to the OdeMapJson dedup tests --- .../topologies/TimDeduplicatorTopology.java | 1 - .../MapDeduplicatorTopologyTest.java | 26 ++++++++++++++----- .../ode_map/sample.ode-map-reference.json | 1 + 3 files changed, 21 insertions(+), 7 deletions(-) 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 6478941..38f7618 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 @@ -20,7 +20,6 @@ import java.time.format.DateTimeFormatter; -import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformation; import us.dot.its.jpo.asn.j2735.r2024.TravelerInformation.TravelerInformationMessageFrame; import us.dot.its.jpo.deduplicator.DeduplicatorProperties; import us.dot.its.jpo.deduplicator.deduplicator.processors.suppliers.OdeTimJsonProcessorSupplier; 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 d78f5d1..e357cbb 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 @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; +import us.dot.its.jpo.asn.j2735.r2024.Common.MinuteOfTheYear; +import us.dot.its.jpo.asn.j2735.r2024.MapData.MapDataMessageFrame; import us.dot.its.jpo.deduplicator.DeduplicatorProperties; import us.dot.its.jpo.deduplicator.deduplicator.topologies.MapDeduplicatorTopology; import us.dot.its.jpo.geojsonconverter.DateJsonMapper; @@ -40,9 +42,9 @@ public class MapDeduplicatorTopologyTest { String inputMap1 = ""; String inputMap2 = ""; + String inputMap3 = ""; String inputMap4 = ""; String inputMap5 = ""; - String inputMap3 = ""; @Autowired DeduplicatorProperties props; @@ -69,6 +71,13 @@ public void setup() throws IOException { Instant instant = Instant.parse(originalTime); Instant newInstant = instant.plus(5, ChronoUnit.MINUTES); map5MinutesLater.getMetadata().setOdeReceivedAt(newInstant.toString()); + // ASN1 modified to show that this message is a deduplicated irrelevant to it + map5MinutesLater.getMetadata().setAsn1(map5MinutesLater.getMetadata().getAsn1() + "1"); + + MapDataMessageFrame mf = (MapDataMessageFrame) map5MinutesLater.getPayload().getData(); + MinuteOfTheYear newMoy = new MinuteOfTheYear(mf.getValue().getTimeStamp().getValue() + 5); + mf.getValue().setTimeStamp(newMoy); + map5MinutesLater.getPayload().setData(mf); inputMap3 = map5MinutesLater.toJson(); // A different Message entirely - should be kept @@ -84,6 +93,11 @@ public void setup() throws IOException { instant = Instant.parse(originalTime); newInstant = instant.plus(61, ChronoUnit.HOURS); map1HourLater.getMetadata().setOdeReceivedAt(newInstant.toString()); + + mf = (MapDataMessageFrame) map1HourLater.getPayload().getData(); + newMoy = new MinuteOfTheYear(mf.getValue().getTimeStamp().getValue() + 60); + mf.getValue().setTimeStamp(newMoy); + map1HourLater.getPayload().setData(mf); inputMap5 = map1HourLater.toJson(); } @@ -126,9 +140,9 @@ public void testTopology() { inputOdeMapData.pipeInput(null, inputMap1); inputOdeMapData.pipeInput(null, inputMap2); + inputOdeMapData.pipeInput(null, inputMap3); inputOdeMapData.pipeInput(null, inputMap4); inputOdeMapData.pipeInput(null, inputMap5); - inputOdeMapData.pipeInput(null, inputMap3); List> mapDeduplicationResults = outputOdeMapData .readKeyValuesToList(); @@ -137,12 +151,12 @@ public void testTopology() { assertEquals(3, mapDeduplicationResults.size()); OdeMessageFrameData map1 = objectMapper.readValue(inputMap1, OdeMessageFrameData.class); - OdeMessageFrameData map3 = objectMapper.readValue(inputMap4, OdeMessageFrameData.class); - OdeMessageFrameData map4 = objectMapper.readValue(inputMap5, OdeMessageFrameData.class); + OdeMessageFrameData map4 = objectMapper.readValue(inputMap4, OdeMessageFrameData.class); + OdeMessageFrameData map5 = 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())); + assertThat(mapDeduplicationResults.get(1).value.toJson(), jsonEquals(map4.toJson())); + assertThat(mapDeduplicationResults.get(2).value.toJson(), jsonEquals(map5.toJson())); } catch (JsonMappingException e) { e.printStackTrace(); 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 0ec484d..cd0ca02 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 @@ -32,6 +32,7 @@ "messageId": 18, "value": { "MapData": { + "timeStamp": 282063, "msgIssueRevision": 0, "layerType": "intersectionData", "layerID": 0, From de33f60b0d8cf2b3d92b72ffb41f95ca995bb422 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 8 Aug 2025 01:04:06 -0600 Subject: [PATCH 21/24] Handle ASN1 and update timestamp and odereceivedat in processed message types --- .../processors/ProcessedMapProcessor.java | 11 +-- .../processors/ProcessedMapWktProcessor.java | 3 + .../ProcessedBsmDeduplicatorTopologyTest.java | 67 ++++++++++++------- .../ProcessedMapDeduplicatorTopologyTest.java | 39 ++++++++--- ...ocessedMapWktDeduplicatorTopologyTest.java | 38 ++++++++--- ...ProcessedSpatDeduplicatorTopologyTest.java | 46 ++++++++----- 6 files changed, 139 insertions(+), 65 deletions(-) diff --git a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java index 23c7d72..28f80e0 100644 --- a/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java +++ b/jpo-deduplicator/src/main/java/us/dot/its/jpo/deduplicator/deduplicator/processors/ProcessedMapProcessor.java @@ -35,16 +35,18 @@ public Instant getMessageTime(ProcessedMap message) { @Override public boolean isDuplicate(ProcessedMap lastMessage, ProcessedMap newMessage) { - try{ + try { Instant newValueTime = getMessageTime(newMessage); Instant oldValueTime = getMessageTime(lastMessage); - - if(newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)){ + + if (newValueTime.minus(Duration.ofHours(1)).isAfter(oldValueTime)) { return false; - }else{ + } else { + String newAsn1 = newMessage.getProperties().getAsn1(); ZonedDateTime newValueTimestamp = newMessage.getProperties().getTimeStamp(); ZonedDateTime newValueOdeReceivedAt = newMessage.getProperties().getOdeReceivedAt(); + newMessage.getProperties().setAsn1(lastMessage.getProperties().getAsn1()); newMessage.getProperties().setTimeStamp(lastMessage.getProperties().getTimeStamp()); newMessage.getProperties().setOdeReceivedAt(lastMessage.getProperties().getOdeReceivedAt()); @@ -52,6 +54,7 @@ public boolean isDuplicate(ProcessedMap lastMessage, ProcessedMap
  • lastMessage, ProcessedMap lastMessage, ProcessedMap processedBsmModifyAsn1 = objectMapper.readValue(processedBsmReferenceData.toString(), + new TypeReference>() { + }); + processedBsmModifyAsn1.getProperties().setAsn1("modified"); + inputProcessedBsm3 = processedBsmModifyAsn1.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); + ZonedDateTime originalTimeStampZdt = processedBsmIncreaseTime.getProperties().getTimeStamp(); + Instant newTimeStampInstant = originalTimeStampZdt.toInstant().plusSeconds(15); processedBsmIncreaseTime.getProperties() - .setTimeStamp(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); - inputProcessedBsm3 = processedBsmIncreaseTime.toString(); + .setTimeStamp(ZonedDateTime.ofInstant(newTimeStampInstant, originalTimeStampZdt.getZone())); + + // Convert OdeReceivedAt to Instant, add 15 seconds, then convert back + String originalOdeReceivedAt = processedBsmIncreaseTime.getProperties().getOdeReceivedAt(); + Instant originalOdeReceivedAtInstant = Instant.parse(originalOdeReceivedAt); + Instant newOdeReceivedAtInstant = originalOdeReceivedAtInstant.plusSeconds(15); + processedBsmIncreaseTime.getProperties().setOdeReceivedAt(newOdeReceivedAtInstant.toString()); + + inputProcessedBsm4 = 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(); + inputProcessedBsm5 = 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(); + inputProcessedBsm6 = processedBsmPositionChanged.toString(); // Vehicle Position was removed. Should be Forwarded ProcessedBsm processedBsmPositionRemoved = new ProcessedBsm(null, null, processedBsmReferenceData.getProperties()); - inputProcessedBsm6 = processedBsmPositionRemoved.toString(); + inputProcessedBsm7 = processedBsmPositionRemoved.toString(); // Vehicle Position was added back in. Should be Forwarded ProcessedBsm processedBsmPositionAddedBack = objectMapper.readValue(processedBsmReferenceData.toString(), new TypeReference>() { }); - inputProcessedBsm7 = processedBsmPositionAddedBack.toString(); + inputProcessedBsm8 = 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(); + inputProcessedBsm9 = processedBsmSpeedMissing.toString(); } @Test @@ -180,6 +198,7 @@ public void testTopology() { inputProcessedBsmData.pipeInput(key, inputProcessedBsm6); inputProcessedBsmData.pipeInput(key, inputProcessedBsm7); inputProcessedBsmData.pipeInput(key, inputProcessedBsm8); + inputProcessedBsmData.pipeInput(key, inputProcessedBsm9); List>> processedBsmDeduplicationResults = outputProcessedBsmData .readKeyValuesToList(); @@ -190,9 +209,6 @@ public void testTopology() { ProcessedBsm processedBsm1 = objectMapper.readValue(inputProcessedBsm1, new TypeReference>() { }); - ProcessedBsm processedBsm3 = objectMapper.readValue(inputProcessedBsm3, - new TypeReference>() { - }); ProcessedBsm processedBsm4 = objectMapper.readValue(inputProcessedBsm4, new TypeReference>() { }); @@ -208,14 +224,17 @@ public void testTopology() { ProcessedBsm processedBsm8 = objectMapper.readValue(inputProcessedBsm8, new TypeReference>() { }); + ProcessedBsm processedBsm9 = objectMapper.readValue(inputProcessedBsm9, + 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())); + assertThat(processedBsmDeduplicationResults.get(1).value.toString(), jsonEquals(processedBsm4.toString())); + assertThat(processedBsmDeduplicationResults.get(2).value.toString(), jsonEquals(processedBsm5.toString())); + assertThat(processedBsmDeduplicationResults.get(3).value.toString(), jsonEquals(processedBsm6.toString())); + assertThat(processedBsmDeduplicationResults.get(4).value.toString(), jsonEquals(processedBsm7.toString())); + assertThat(processedBsmDeduplicationResults.get(5).value.toString(), jsonEquals(processedBsm8.toString())); + assertThat(processedBsmDeduplicationResults.get(6).value.toString(), jsonEquals(processedBsm9.toString())); } catch (JsonMappingException e) { e.printStackTrace(); 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 739824f..7c4399a 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 @@ -49,12 +49,15 @@ public class ProcessedMapDeduplicatorTopologyTest { // Duplicate of Number 1 String inputProcessedMap2 = ""; - // A different Message entirely + // Verify ASN1 field has no bearing on deduplication String inputProcessedMap3 = ""; - // Message 1 but 1 hour later + // A different Message entirely String inputProcessedMap4 = ""; + // Message 1 but 1 hour later + String inputProcessedMap5 = ""; + String key = "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}"; @Autowired @@ -75,18 +78,31 @@ public void setup() throws IOException { // Duplicate of Number 1 inputProcessedMap2 = processedMapReferenceData.toString(); + // Verify ASN1 field has no bearing on deduplication - should be dropped + ProcessedMap processedMapModifyAsn1 = objectMapper.readValue(processedMapReference, typeReference); + processedMapModifyAsn1.getProperties().setAsn1("modified"); + inputProcessedMap3 = processedMapModifyAsn1.toString(); + // Message 1 but 1 hour later ProcessedMap processedMap1HourLater = objectMapper.readValue(processedMapReference, typeReference); - ZonedDateTime originalZdt = processedMap1HourLater.getProperties().getOdeReceivedAt(); - Instant newInstant = originalZdt.toInstant().plusSeconds(3601); - processedMap1HourLater.getProperties().setOdeReceivedAt(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); - inputProcessedMap3 = processedMap1HourLater.toString(); + // Convert ZonedDateTime to Instant, add 1 hour, then convert back + ZonedDateTime originalTimeStampZdt = processedMap1HourLater.getProperties().getTimeStamp(); + Instant newTimeStampInstant = originalTimeStampZdt.toInstant().plusSeconds(3601); + processedMap1HourLater.getProperties() + .setTimeStamp(ZonedDateTime.ofInstant(newTimeStampInstant, originalTimeStampZdt.getZone())); + + // Convert OdeReceivedAt to Instant, add 1 hour, then convert back + ZonedDateTime originalOdeReceivedAtZdt = processedMap1HourLater.getProperties().getOdeReceivedAt(); + Instant newOdeReceivedAtInstant = originalOdeReceivedAtZdt.toInstant().plusSeconds(3601); + processedMap1HourLater.getProperties().setOdeReceivedAt(ZonedDateTime.ofInstant(newOdeReceivedAtInstant, originalOdeReceivedAtZdt.getZone())); + + inputProcessedMap4 = processedMap1HourLater.toString(); // A different Message entirely String differentProcessedMapReference = new String(Files .readAllBytes(Paths.get("src/test/resources/json/processed_map/sample.processed_map-different.json"))); ProcessedMap processedMapDifferentData = objectMapper.readValue(differentProcessedMapReference, typeReference); - inputProcessedMap4 = processedMapDifferentData.toString(); + inputProcessedMap5 = processedMapDifferentData.toString(); } @Test @@ -132,6 +148,7 @@ public void testTopology() { inputProcessedMapData.pipeInput(key, inputProcessedMap2); inputProcessedMapData.pipeInput(key, inputProcessedMap3); inputProcessedMapData.pipeInput(key, inputProcessedMap4); + inputProcessedMapData.pipeInput(key, inputProcessedMap5); List>> mapDeduplicatorResults = outputProcessedMapData .readKeyValuesToList(); @@ -141,16 +158,16 @@ public void testTopology() { ProcessedMap map1 = objectMapper.readValue(inputProcessedMap1, typeReference); - ProcessedMap map3 = objectMapper.readValue(inputProcessedMap3, - typeReference); ProcessedMap map4 = objectMapper.readValue(inputProcessedMap4, typeReference); + ProcessedMap map5 = objectMapper.readValue(inputProcessedMap5, + 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(1).value.getProperties().getOdeReceivedAt()); + assertEquals(map5.getProperties().getOdeReceivedAt(), mapDeduplicatorResults.get(2).value.getProperties().getOdeReceivedAt()); } catch (JsonMappingException e) { 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 8ea83d8..c53d17e 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 @@ -47,12 +47,15 @@ public class ProcessedMapWktDeduplicatorTopologyTest { // Duplicate of Number 1 String inputProcessedMapWkt2 = ""; - // A different Message entirely + // Verify ASN1 field has no bearing on deduplication String inputProcessedMapWkt3 = ""; - // Message 1 but 1 hour later + // A different Message entirely String inputProcessedMapWkt4 = ""; + // Message 1 but 1 hour later + String inputProcessedMapWkt5 = ""; + String key = "{\"rsuId\":\"10.11.81.12\",\"intersectionId\":12109,\"region\":-1}"; @Autowired @@ -73,18 +76,30 @@ public void setup() throws IOException { // Duplicate of Number 1 inputProcessedMapWkt2 = processedMapWktReferenceData.toString(); + // Verify ASN1 field has no bearing on deduplication - should be dropped + ProcessedMap processedMapWktModifyAsn1 = objectMapper.readValue(processedMapWktReference, typeReference); + processedMapWktModifyAsn1.getProperties().setAsn1("modified"); + inputProcessedMapWkt3 = processedMapWktModifyAsn1.toString(); + // Message 1 but 1 hour later ProcessedMap processedMapWkt1HourLater = objectMapper.readValue(processedMapWktReference, typeReference); - ZonedDateTime originalZdt = processedMapWkt1HourLater.getProperties().getOdeReceivedAt(); - Instant newInstant = originalZdt.toInstant().plusSeconds(3601); - processedMapWkt1HourLater.getProperties().setOdeReceivedAt(ZonedDateTime.ofInstant(newInstant, originalZdt.getZone())); - inputProcessedMapWkt3 = processedMapWkt1HourLater.toString(); + // Convert ZonedDateTime to Instant, add 1 hour, then convert back + ZonedDateTime originalTimeStampZdt = processedMapWkt1HourLater.getProperties().getTimeStamp(); + Instant newTimeStampInstant = originalTimeStampZdt.toInstant().plusSeconds(3601); + processedMapWkt1HourLater.getProperties() + .setTimeStamp(ZonedDateTime.ofInstant(newTimeStampInstant, originalTimeStampZdt.getZone())); + + // Convert OdeReceivedAt to Instant, add 1 hour, then convert back + ZonedDateTime originalOdeReceivedAtZdt = processedMapWkt1HourLater.getProperties().getOdeReceivedAt(); + Instant newOdeReceivedAtInstant = originalOdeReceivedAtZdt.toInstant().plusSeconds(3601); + processedMapWkt1HourLater.getProperties().setOdeReceivedAt(ZonedDateTime.ofInstant(newOdeReceivedAtInstant, originalOdeReceivedAtZdt.getZone())); + inputProcessedMapWkt4 = processedMapWkt1HourLater.toString(); // A different Message entirely String differentProcessedMapWktReference = new String(Files .readAllBytes(Paths.get("src/test/resources/json/processed_map_wkt/sample.processed_map_wkt-different.json"))); ProcessedMap processedMapWktDifferentData = objectMapper.readValue(differentProcessedMapWktReference, typeReference); - inputProcessedMapWkt4 = processedMapWktDifferentData.toString(); + inputProcessedMapWkt5 = processedMapWktDifferentData.toString(); } @Test @@ -130,6 +145,7 @@ public void testTopology() { inputProcessedMapData.pipeInput(key, inputProcessedMapWkt2); inputProcessedMapData.pipeInput(key, inputProcessedMapWkt3); inputProcessedMapData.pipeInput(key, inputProcessedMapWkt4); + inputProcessedMapData.pipeInput(key, inputProcessedMapWkt5); List>> processedMapWktDeduplicatorResults = outputProcessedMapData .readKeyValuesToList(); @@ -139,14 +155,14 @@ public void testTopology() { ProcessedMap processedMapWkt1 = objectMapper.readValue(inputProcessedMapWkt1, typeReference); - ProcessedMap processedMapWkt3 = objectMapper.readValue(inputProcessedMapWkt3, - typeReference); ProcessedMap processedMapWkt4 = objectMapper.readValue(inputProcessedMapWkt4, typeReference); + ProcessedMap processedMapWkt5 = objectMapper.readValue(inputProcessedMapWkt5, + typeReference); assertThat(processedMapWktDeduplicatorResults.get(0).value.toString(), jsonEquals(processedMapWkt1.toString())); - assertThat(processedMapWktDeduplicatorResults.get(1).value.toString(), jsonEquals(processedMapWkt3.toString())); - assertThat(processedMapWktDeduplicatorResults.get(2).value.toString(), jsonEquals(processedMapWkt4.toString())); + assertThat(processedMapWktDeduplicatorResults.get(1).value.toString(), jsonEquals(processedMapWkt4.toString())); + assertThat(processedMapWktDeduplicatorResults.get(2).value.toString(), jsonEquals(processedMapWkt5.toString())); } catch (JsonMappingException 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 e076104..9b82095 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 @@ -46,18 +46,21 @@ public class ProcessedSpatDeduplicatorTopologyTest { // Same as Processed SPaT 1 String inputProcessedSpat2; - // Time change of +1 minute + // Verify ASN1 field has no bearing on deduplication String inputProcessedSpat3; - // With a signal group removed + // Time change of +1 minute String inputProcessedSpat4; - // With a signal group's id changed + // With a signal group removed String inputProcessedSpat5; - // With a change of the light state of a signal group + // With a signal group's id changed String inputProcessedSpat6; + // With a change of the light state of a signal group + String inputProcessedSpat7; + String key = "{\"rsuId\": \"10.164.6.16\", \"intersectionId\": 6311,\"region\": -1}"; @Autowired @@ -81,28 +84,40 @@ public void setup() throws IOException { // Duplicate of Number 1, should be dropped inputProcessedSpat2 = processedSpatReferenceData.toString(); + // Verify ASN1 field has no bearing on deduplication - should be dropped + ProcessedSpat processedSpatModifyAsn1 = objectMapper.readValue(processedSpatReferenceData.toString(), + ProcessedSpat.class); + processedSpatModifyAsn1.setAsn1("modified"); + inputProcessedSpat3 = processedSpatModifyAsn1.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 + // 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(); + + // Convert OdeReceivedAt to Instant, add 61 seconds, then convert back + String originalOdeReceivedAt = processedSpatIncreaseTime.getOdeReceivedAt(); + Instant originalOdeReceivedAtInstant = Instant.parse(originalOdeReceivedAt); + Instant newOdeReceivedAtInstant = originalOdeReceivedAtInstant.plusSeconds(61); + processedSpatIncreaseTime.setOdeReceivedAt(newOdeReceivedAtInstant.toString()); + + inputProcessedSpat4 = processedSpatIncreaseTime.toString(); // Signal group removed ProcessedSpat processedSpatSignalGroupRemoved = objectMapper.readValue(processedSpatReferenceData.toString(), ProcessedSpat.class); processedSpatSignalGroupRemoved.getStates().remove(0); - inputProcessedSpat4 = processedSpatSignalGroupRemoved.toString(); + inputProcessedSpat5 = processedSpatSignalGroupRemoved.toString(); // Signal group ID changed ProcessedSpat processedSpatSignalGroupIdChanged = objectMapper.readValue( processedSpatSignalGroupRemoved.toString(), ProcessedSpat.class); processedSpatSignalGroupIdChanged.getStates().get(0).setSignalGroup(500); - inputProcessedSpat5 = processedSpatSignalGroupIdChanged.toString(); + inputProcessedSpat6 = processedSpatSignalGroupIdChanged.toString(); // Signal group light state changed ProcessedSpat processedSpatSignalGroupLightStateChanged = objectMapper.readValue( @@ -110,7 +125,7 @@ public void setup() throws IOException { ProcessedSpat.class); processedSpatSignalGroupLightStateChanged.getStates().get(0).getStateTimeSpeed().get(0) .setEventState(ProcessedMovementPhaseState.PROTECTED_CLEARANCE); - inputProcessedSpat6 = processedSpatSignalGroupLightStateChanged.toString(); + inputProcessedSpat7 = processedSpatSignalGroupLightStateChanged.toString(); } @Test @@ -156,6 +171,7 @@ public void testTopology() { inputProcessedSpatData.pipeInput(key, inputProcessedSpat4); inputProcessedSpatData.pipeInput(key, inputProcessedSpat5); inputProcessedSpatData.pipeInput(key, inputProcessedSpat6); + inputProcessedSpatData.pipeInput(key, inputProcessedSpat7); List> processedSpatDeduplicatorResults = outputProcessedSpatData .readKeyValuesToList(); @@ -164,16 +180,16 @@ public void testTopology() { 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); + ProcessedSpat processedSpat7 = objectMapper.readValue(inputProcessedSpat7, 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())); + assertThat(processedSpatDeduplicatorResults.get(1).value.toString(), jsonEquals(processedSpat4.toString())); + assertThat(processedSpatDeduplicatorResults.get(2).value.toString(), jsonEquals(processedSpat5.toString())); + assertThat(processedSpatDeduplicatorResults.get(3).value.toString(), jsonEquals(processedSpat6.toString())); + assertThat(processedSpatDeduplicatorResults.get(4).value.toString(), jsonEquals(processedSpat7.toString())); } catch (JsonMappingException e) { e.printStackTrace(); From ed849bcedc83b77949d67473a3ee1c56e1b34a1a Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 8 Aug 2025 01:06:29 -0600 Subject: [PATCH 22/24] Update gitmodules to include the latest version of the jpo-utils --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 532f96c..3a6e292 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "jpo-utils"] path = jpo-utils - url = https://github.com/usdot-jpo-ode/jpo-utils.git + url = https://github.com/CDOT-CV/jpo-utils.git From a1a590321fb1195f054bb42a8ff5ff4f29d60829 Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 8 Aug 2025 01:14:38 -0600 Subject: [PATCH 23/24] Update jpo-utils for the removal of unused mongo collections/topics --- jpo-utils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jpo-utils b/jpo-utils index 56deaf7..281b032 160000 --- a/jpo-utils +++ b/jpo-utils @@ -1 +1 @@ -Subproject commit 56deaf72ec7463fba6606080337c657d58e12845 +Subproject commit 281b032a7dc65102bf544e4220f940b97e9992f3 From 9321ba567c1fdda0d7c6e5a70c093c16fdce829c Mon Sep 17 00:00:00 2001 From: Drew Johnston Date: Fri, 8 Aug 2025 01:16:45 -0600 Subject: [PATCH 24/24] Remove env vars related to OdeRawEncodedTIMJson --- docker-compose.yml | 1 - sample.env | 1 - 2 files changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index fe8fded..ba2c085 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,6 @@ services: ENABLE_PROCESSED_MAP_WKT_DEDUPLICATION: ${ENABLE_PROCESSED_MAP_WKT_DEDUPLICATION} ENABLE_ODE_MAP_DEDUPLICATION: ${ENABLE_ODE_MAP_DEDUPLICATION} ENABLE_ODE_TIM_DEDUPLICATION: ${ENABLE_ODE_TIM_DEDUPLICATION} - ENABLE_ODE_RAW_ENCODED_TIM_DEDUPLICATION: ${ENABLE_ODE_RAW_ENCODED_TIM_DEDUPLICATION} ENABLE_PROCESSED_SPAT_DEDUPLICATION: ${ENABLE_PROCESSED_SPAT_DEDUPLICATION} ENABLE_ODE_BSM_DEDUPLICATION: ${ENABLE_ODE_BSM_DEDUPLICATION} ENABLE_PROCESSED_BSM_DEDUPLICATION: ${ENABLE_PROCESSED_BSM_DEDUPLICATION} diff --git a/sample.env b/sample.env index e7a3f4d..efa2ad7 100644 --- a/sample.env +++ b/sample.env @@ -50,7 +50,6 @@ ENABLE_PROCESSED_MAP_DEDUPLICATION=true ENABLE_PROCESSED_MAP_WKT_DEDUPLICATION=true ENABLE_ODE_MAP_DEDUPLICATION=true ENABLE_ODE_TIM_DEDUPLICATION=true -ENABLE_ODE_RAW_ENCODED_TIM_DEDUPLICATION=true ENABLE_PROCESSED_SPAT_DEDUPLICATION=true ENABLE_ODE_BSM_DEDUPLICATION=true ENABLE_PROCESSED_BSM_DEDUPLICATION=true