diff --git a/docker-compose.yml b/docker-compose.yml
index 91551538e..7ca7edcc1 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -91,184 +91,3 @@ services:
options:
max-size: "10m"
max-file: "5"
-
- aem:
- build: ./asn1_codec
- image: jpoode_acm:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- ACM_CONFIG_FILE: aem.properties
- ACM_LOG_TO_CONSOLE: ${AEM_LOG_TO_CONSOLE}
- ACM_LOG_TO_FILE: ${AEM_LOG_TO_FILE}
- ACM_LOG_LEVEL: ${AEM_LOG_LEVEL}
- depends_on:
- - kafka
- volumes:
- - ${DOCKER_SHARED_VOLUME}:/asn1_codec_share
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- ppm_bsm:
- build:
- context: ./jpo-cvdp
- dockerfile: Dockerfile
- image: jpoode_ppm:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- PPM_CONFIG_FILE: ppmBsm.properties
- PPM_LOG_TO_CONSOLE: ${PPM_BSM_LOG_TO_CONSOLE}
- PPM_LOG_TO_FILE: ${PPM_BSM_LOG_TO_FILE}
- PPM_LOG_LEVEL: ${PPM_BSM_LOG_LEVEL}
- volumes:
- - ${DOCKER_SHARED_VOLUME}:/ppm_data
- depends_on:
- - kafka
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- ppm_tim:
- build:
- context: ./jpo-cvdp
- dockerfile: Dockerfile
- image: jpoode_ppm:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- PPM_CONFIG_FILE: ppmTim.properties
- PPM_LOG_TO_CONSOLE: ${PPM_TIM_LOG_TO_CONSOLE}
- PPM_LOG_TO_FILE: ${PPM_TIM_LOG_TO_FILE}
- PPM_LOG_LEVEL: ${PPM_TIM_LOG_LEVEL}
- volumes:
- - ${DOCKER_SHARED_VOLUME}:/ppm_data
- depends_on:
- - kafka
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- cvpep_bsm_depositor:
- build: ./jpo-s3-deposit
- image: jpoode_s3dep:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- DEPOSIT_BUCKET_NAME: ${CVPEP_BSM_BUCKET_NAME}
- DEPOSIT_KEY_NAME: ${CVPEP_BSM_DEPOSIT_KEY}
- DEPOSIT_TOPIC: ${CVPEP_BSM_TOPIC}
- K_AWS_ACCESS_KEY_ID: ${CVPEP_BSM_K_AWS_ACCESS_KEY_ID}
- K_AWS_SECRET_ACCESS_SECRET: ${CVPEP_BSM_K_AWS_SECRET_ACCESS_SECRET}
- K_AWS_SESSION_TOKEN: ${CVPEP_BSM_K_AWS_SESSION_TOKEN}
- K_AWS_EXPIRATION: ${CVPEP_BSM_K_AWS_EXPIRATION}
- API_ENDPOINT: ${CVPEP_BSM_API_ENDPOINT}
- HEADER_ACCEPT: ${CVPEP_BSM_HEADER_ACCEPT}
- HEADER_X_API_KEY: ${CVPEP_BSM_HEADER_X_API_KEY}
- DEPOSIT_GROUP: ${CVPEP_BSM_GROUP}
- depends_on:
- - kafka
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- rde_bsm_depositor:
- build: ./jpo-s3-deposit
- image: jpoode_s3dep:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- DEPOSIT_BUCKET_NAME: ${RDE_BSM_BUCKET_NAME}
- DEPOSIT_KEY_NAME: ${RDE_BSM_DEPOSIT_KEY}
- DEPOSIT_TOPIC: ${RDE_BSM_TOPIC}
- K_AWS_ACCESS_KEY_ID: ${RDE_BSM_K_AWS_ACCESS_KEY_ID}
- K_AWS_SECRET_ACCESS_SECRET: ${RDE_BSM_K_AWS_SECRET_ACCESS_SECRET}
- K_AWS_SESSION_TOKEN: ${RDE_BSM_K_AWS_SESSION_TOKEN}
- K_AWS_EXPIRATION: ${RDE_BSM_K_AWS_EXPIRATION}
- API_ENDPOINT: ${RDE_BSM_API_ENDPOINT}
- HEADER_ACCEPT: ${RDE_BSM_HEADER_ACCEPT}
- HEADER_X_API_KEY: ${RDE_BSM_HEADER_X_API_KEY}
- DEPOSIT_GROUP: ${RDE_BSM_GROUP}
- depends_on:
- - kafka
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- cvpep_tim_depositor:
- build: ./jpo-s3-deposit
- image: jpoode_s3dep:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- DEPOSIT_BUCKET_NAME: ${CVPEP_TIM_BUCKET_NAME}
- DEPOSIT_KEY_NAME: ${CVPEP_TIM_DEPOSIT_KEY}
- DEPOSIT_TOPIC: ${CVPEP_TIM_TOPIC}
- K_AWS_ACCESS_KEY_ID: ${CVPEP_BSM_K_AWS_ACCESS_KEY_ID}
- K_AWS_SECRET_ACCESS_SECRET: ${CVPEP_BSM_K_AWS_SECRET_ACCESS_SECRET}
- K_AWS_SESSION_TOKEN: ${CVPEP_BSM_K_AWS_SESSION_TOKEN}
- K_AWS_EXPIRATION: ${CVPEP_BSM_K_AWS_EXPIRATION}
- API_ENDPOINT: ${CVPEP_BSM_API_ENDPOINT}
- HEADER_ACCEPT: ${CVPEP_BSM_HEADER_ACCEPT}
- HEADER_X_API_KEY: ${CVPEP_BSM_HEADER_X_API_KEY}
- DEPOSIT_GROUP: ${CVPEP_TIM_GROUP}
- depends_on:
- - kafka
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- rde_tim_depositor:
- build: ./jpo-s3-deposit
- image: jpoode_s3dep:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- DEPOSIT_BUCKET_NAME: ${RDE_TIM_BUCKET_NAME}
- DEPOSIT_KEY_NAME: ${RDE_TIM_DEPOSIT_KEY}
- DEPOSIT_TOPIC: ${RDE_TIM_TOPIC}
- K_AWS_ACCESS_KEY_ID: ${CVPEP_BSM_K_AWS_ACCESS_KEY_ID}
- K_AWS_SECRET_ACCESS_SECRET: ${RDE_TIM_K_AWS_SECRET_ACCESS_SECRET}
- K_AWS_SESSION_TOKEN: ${RDE_TIM_K_AWS_SESSION_TOKEN}
- K_AWS_EXPIRATION: ${RDE_TIM_K_AWS_EXPIRATION}
- API_ENDPOINT: ${RDE_TIM_API_ENDPOINT}
- HEADER_ACCEPT: ${RDE_TIM_HEADER_ACCEPT}
- HEADER_X_API_KEY: ${RDE_TIM_HEADER_X_API_KEY}
- DEPOSIT_GROUP: ${RDE_TIM_GROUP}
- depends_on:
- - kafka
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- sdw_depositor:
- build: ./jpo-sdw-depositor
- image: jpoode_sdwdep:latest
- environment:
- DOCKER_HOST_IP: ${DOCKER_HOST_IP}
- #SDW_GROUP_ID: ${SDW_GROUP_ID}
- #SDW_KAFKA_PORT: ${SDW_KAFKA_PORT}
- #SDW_SUBSCRIPTION_TOPICS: ${SDW_SUBSCRIPTION_TOPICS}
- #SDW_DESTINATION_URL: ${SDW_DESTINATION_URL}
- SDW_API_KEY: ${SDW_API_KEY}
- depends_on:
- - kafka
- - zookeeper
- - ode
- logging:
- options:
- max-size: "10m"
- max-file: "5"
-
- sec:
- build: ./jpo-security-svcs
- image: jpoode_sec:latest
- ports:
- - "8090:8090"
- environment:
- SEC_CRYPTO_SERVICE_BASE_URI: ${SEC_CRYPTO_SERVICE_BASE_URI}
- logging:
- options:
- max-size: "10m"
- max-file: "5"
diff --git a/docs/Release_notes.md b/docs/Release_notes.md
index 03a80d469..8611f4026 100644
--- a/docs/Release_notes.md
+++ b/docs/Release_notes.md
@@ -1,6 +1,20 @@
JPO-ODE Release Notes
----------------------------
+Version 2.0.2, released April 2024
+----------------------------------------
+### **Summary**
+The updates for the jpo-ode 2.0.2 release includes an update to the dataflow for the UDP and log ingestion endpoints. This update allows for the UDP and log ingestion endpoints to handle and strip unsigned IEEE 1609.2 and 1609.3 headers. Signed IEEE 1609.2 security headers are maintained in the encoded Kafka topic prior to being decoded.
+
+Enhancements in this release:
+- Support IEEE 1609.2 and 1609.3 header ingestion
+- Strips unsigned IEEE 1609.2 headers
+- Strips IEEE 1609.2 headers
+- Maintains signed IEEE 1609.3 headers before eventually stripping them before decoding to the J2735 payload
+
+Known Issues:
+- No known issues at this time.
+
Version 2.0.1, released March 2024
----------------------------------------
### **Summary**
diff --git a/docs/data-flow-diagrams/ODE Data Flow Overview.drawio b/docs/data-flow-diagrams/ODE Data Flow Overview.drawio
index 3804b4e44..37725264d 100644
--- a/docs/data-flow-diagrams/ODE Data Flow Overview.drawio
+++ b/docs/data-flow-diagrams/ODE Data Flow Overview.drawio
@@ -1 +1,329 @@
-7V1Zd6LKFv41WeveB1wyw6PRmKFj5nSS85KFUCoJUjZgYvrXn0IGkdohGJmipx9sLZEU+9vDV7t2VR3w3eni2NFmkwE2kHXAtY3FAd874DheaPPkP7/lI2jh2ko7aBk7phG0sauGW/MvChujy+amgdy1Cz2MLc+crTfq2LaR7q21aY6D39cvG2Fr/a/OtDGiGm51zaJbH0zDmwStCiev2k+QOZ5Ef5mV1OCbqRZdHD6JO9EM/J5o4o8O+K6DsRe8my66yPKlF8nl4fTjwTp/lY7Prt0/2v3hr7uL30xws/4mP4kfwUG29+1bjxeLf26OR78nRudMVm/vrp/ca0YO7+16H5HAkEHkF37EjjfBY2xr1tGq9dDBc9tA/m3b5NPqmnOMZ6SRJY0vyPM+QmXQ5h4mTRNvaoXfooXpPYY/998/+e9bYvipt0h81fsIP+SUQfQ8eO7o4QMp8xfzxl1YryfM9WHnSPpzcTdhuFAVNWeMvCwBheD7UkkoVCjiY4SnyHM+yAUOsjTPfFvXOi1U3nF83Qog8ibECMYLvUu9X/88H78Oj6VH3H3Tr68GDCvUgVdNspfkumSf1e03zZqHf6nj2mwP6cRpGj3N027w3ENO60V70yiU1jF4n5geup1pSzG9E8+7Lu+RaVldbGFn+Vve0JAy0km76zn4FSW+kXQFDUcbI/SGHA8tMkUafSsGvwi9P8OpoT28r3wpG9nIJOFHpfb2KIBKEXvjH2IB4EOIOS2AVYu2gPCnV9gkDxLDrHCtFNBCGsCgr+HvUhjGHfk+rCJtXN0Bafhfpzf4P4U4CcUz/+3MwTpy3a8taqjpr+OlFlzOPcu00SeWJiLFECBLU7ghL0klWhpx7e00BCJta1xJtvb8+2Ti4ONr9kJ4P3n2TuULS4083o82NTVvsOHqCjZZ3V4PNl0SafQBUXif4iLnzdSJitpEVS1rx+IOw4spa5BFOvJwfJWRh1XqMAciWOcjJsv+hwRb9j+u6PLy0/Z8GX54PqcdiY0yo6jbIGlzTu3Z3KNBtSwyOEUbm8toNOJ00FwMaSiJpQYPTk3Hbzln8FAKMBdwqFILT4tHlvFo8inxTdEjy0zOlrSUrPFEUywFjDiRpRDWtCOmQrGsKg3l6WTwenM0unt+7N27C9W45Sa/AZbVNA4lACrd6+ryK9/Bf0+RZQyelcm1oDBCo1RaoFW6b1rofmZhzdhV4iSmFRwiTvFYoxLiJMr1EqcVV3pao0qVECdRyUmcpNoyjZn9ThjPDdIR+bsOae1amusit1CrGSk6goPCUBEFcXNstuFPqgJYTaWD71oy8wUrfyScL5W/8DzXVrofdTup+9o7aTiyl8le8i4chdMW8G1KVKP281wqZihyzjRvEaQIhkBsPCuKMkZfZ3H5Zmk3R2n3iunvoG/n05MYEi/Q2i1VyYiima0EBFf4Be+YX0kzUVbmWlzdaQkgi9c0xyLnjZpKbck255f2+KIK/Rt+dIJ14Wyw6N0AjOUnSBZ8lGZxcZnmI2cutnfMXTCcnHLUfDsnCS+NhrBR7N7Lsass5HREqlKXvbw8PnaOTz38z1H/4VEenlr9vs0I9YLGHmw0U1NtNVRuoGHJ1pa0hoM5DXTjQk5eGyq+0mz5047jaB+JC2Z+BYebuHOqFIQR1RRtk+RUYSH1i/Rcrch+8QtBSf2C59spZQj6XWiNSQRFIozemdMemmHX9LCzqxlhWaCqe8CccFkjINhypTpcdMG2reSt41KkRvFJha62uroaUIDsYpUV104PSvOPSUtLB0TqsT5R5SFnmWrcRaqfLiuFQRBFGoQiqP7Z4fjl7HQ0NQVmbC46DH99eMrw9ZTCN4Ppq9HSjIQnA6XENStTH/U7lcvs4ulUs42BZhOL2bVwLlLhPK6DSxqPUmU4r6U0rmgbyJ3PL74sezsjoBP6t72HmNfuTpUb26ZSym2uVWUBD+wTd2GqVs2d62Gbpfz0oM6PAOFM7Y4uyyFjOjkdBOJJ3NqW5rA/bXVaZi7z6zDQbtYsgUpX7KwsYYeigMxRBEgSgBndiicK6IKFn6f7sUrnUP7aMsHZPQdWkB3tyQoywDBEaGRQVm6DZ9xz9emoy5x07In98Px6/Veqp4ztO8sAGjISjw3rayLWrGrruONw/NmdFQSQnQl57ayIAGSyc3d2N2afbubGXU+4Hvfcp3pG4E1YbgOttwElVNtuAtn9To3a9yJSUQN5Vq40C585t50AhFiIZuia689d7lT+XU1PwMoS4MCg5bVFODBOeRxq538GLnv2NlUu7KfOH4mh+ds0kPjBciMgYpBE9OQiyfJ8JXfIu7G3jMZRTfa7SXrOtf2g09IpmIhovHU8NMsc2+S9TqSLiOgPfQGaumZ1wi+mpmEEjhK55l9tuLyVj0s4iU7uKx4eiD3/XsQ3uoGbZClIbewb4Rr+YVNpAMcp4XhBA1RLBQHMlwUwnapfAWz62BooQnLk4OkmSOYVd37EIVNeD5flOUc+TS4g6FgAOrEs6Oj54hR0o3i6sk9eNd3z3+4ZbGqaFQpwbroNzGqWhhw9s5xCbuU+iUvDe2t0Ck+PnSFGUqnZ0asEpjEJITFxiaFfGnB1eXbpGyF2pho9xNpt5OIU92qVAV+zzdHEHobt7PbyYl9hY/h0sTcHMdBKcWM/paD/AZesoFrDTZTrD3LALi+ZwGm2sedek1ElagJRgpY8l4UjWEVC08yb23t6wB1lRDwiMfQX+7c8nCHHJJ3w5b1qv1o1fj02X6Bo99rNJ1Y2IRrUXnssX23yA1xtTvPEX+iDlvy7ObW0pZZb2hBZh3GqKW0W2PYiaSqlipNSYxWYBxeg2uZ4WFW4MGkCEKUtfLmsiVT6M8fRF0yQQOiQCzhhtlh9GaU6fmmjV418e4dnph7dkvQwuGtwDYVZiRn2bB2gMc/UvNyYpwIQK6gtVVVlUWoHLwptSlAtHMvKrbbME/4YvZSkDQCtKEYdLntHfkxb1rUEq7bz6sQqyLAb60WOspe69KLVXvsnrBMVILqpUux513KcckspSRnoEFeMLtzOh1NszMlPc6pAjdMKjXAbnOy7DZGXRCV4ASpIILfh60ZbUOT4ZXtF6Z3hB+Pt/mr8MnJd5vF0dHRuAbtNF6MooZ9oHxPZz6rwFzmmOWpSCF6u10GAuJcVLELOsBnuJU5tNQNzFgQdQDxgCwVgDm2bRw9fKSTGAWzg08aHZ4QzVAexr8snwM+lJUM+k5MULngBEm3QoIVl+ZaiJqhWWUyLLoCkNdo2Ov6pIuST7ntCU19X5PXh96ZKmoXul3UHCTGKGVnmLbd65/hWKvMm860ECZajE1+iWwYVGNTG79SNVSW+cfF7xoNpn7JCpF80Tr7sW0RNcjrKZmSLilTXHD411B/JdwrJgVQ+ryDwLXV7P5BV6bNWWfP4KQOeoIU2xnYqiRS2xikkrkE5JLp8hsufQiqtAo39YctgwIcAismyUpXVF5Nl9TqZOHXn8QKw3Vr6QidQP5lnLyt/Cm7iXMtu59/XfXAdW97a/2hf5eqVP6vbCeXHo5G/xXNQSmRaQM1e5Pv1+TDH6GYYAHU+/CoXYmjO6yW5jektq11bbXG9kVu2lhobxHThl6JWGBjg9ZEADf9xxpF7eSTXKOPgalmS991DS+B68riEvOB68u1wrm3Ls6xuJ5zgqZ/li4u90lWzBp4PLcRE1V98n+YHEzwdznMkhlPc4Ejsdvv9Sukvw6n5+S9pbIkloVDPrkbVrsIAH1ymrSaLqDbEaGo+0em7+wTW5xwBmLO8UUNgptMBN7f3pKGHLP84g4+f5f3o8Q/DcnkzsWX6Pjod9wEw72ZkyspDh6cKUmK4EuhA9ShFLLyAkaHnF2z8HzAMK9JmUykwHA3MHpqMmt5wlJUlKKFTLTR0ocb+2QyFDA/nmStFhq/lNKmCiRQH5JmzuEv1TOpmdH+4MJ+7l/IrPtelR8F8mUZZ750TPfiwzSKxUbdzj/Bd4kd+2sge2FmhEdyWpysL9jBQyxKFjgpu3FptPKANY/8itcymOVR1qIDOs55E2JaZlShlVu4JDFnBpob9d5c/3fyUgFQKNqz6+PyMgHTKVuJTOrbdhv9ZQk3WgRCT1by5g3Z2s39qHfMns+NlnQALHqeUfR5L6GhrJIpZZ0B9eVYUVxdPzOp1QudJF8J1j0Tpl6rkUHDs4iZDQjtFVpQKi0RAbLKnGxpqBlxOM6htuJTV6+QJF4FqB6e3EnXm+kS7C9yQrsbdnNKaDpC/0io+QOlnp2gaqugABQOvq+0sl6xeJxSdePmRZerLPcuw7RcA7qW736QmtjSPTy+rXu5JG22GGazk3Y0t5dLHvbIb7OlXhCMCi9npkuSCvE7K+r/nhsAuA7Tz87LHCrwO2Mns4X2xDr5SUYO1XqJSp6yrDKb1yzo4pK8uWUOrLz/1zXERsYXnxte++hOPmlfGGVPb9AF/bBvYBYMD0+ZCWb43e7Lop+ht3nrQoMiiLr2tcmRZv6zlbWPf93KeQjrJLoQGVVQSM0soCZd0jsd900J3ODjqzED61Xxome7ET+x060tnluDaqKNlJZ7ep4GDNmUsgtKDeNDTTTNtue8wEQhNN5s071QCPsBhdIpQ3dQTzPnpIL5CiI7nO46QIKWnbIFt3qrFh94IeoUPPVOw4/hIdMkDtGKrIIT8/Zmxv9h9FaHI004GJIj4V/wL
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/data-flow-diagrams/ODE Data Flow Overview.drawio.png b/docs/data-flow-diagrams/ODE Data Flow Overview.drawio.png
index 2de1e2ed0..915576aaf 100644
Binary files a/docs/data-flow-diagrams/ODE Data Flow Overview.drawio.png and b/docs/data-flow-diagrams/ODE Data Flow Overview.drawio.png differ
diff --git a/docs/data-flow-diagrams/README.md b/docs/data-flow-diagrams/README.md
index 1b65f513c..6be5d3549 100644
--- a/docs/data-flow-diagrams/README.md
+++ b/docs/data-flow-diagrams/README.md
@@ -38,18 +38,19 @@ The purpose of these diagrams is to show:
### Overview Data Flow 3 (Offloaded Files)
1. Messages are offloaded onto a directory referenced by the FileUploadController class.
1. The FileUploadController class indirectly invokes the LogFileToAsn1CodecPublisher class, which handles the offloaded messages.
-1. If the message is a DriverAlert, the LogFileToAsn1CodecPublisher class pushes it to the OdeDriverAlertJson topic.
-1. If the message is a BSM, SPAT, TIM or MAP, the LogFileToAsn1CodecPublisher class pushes it to the Asn1DecoderInput topic.
-1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from that topic and pushes decoded messages to the Asn1DecoderOutput topic.
-1. The Asn1DecodeDataRouter class pulls from the Asn1DecodeOutput topic and deposits messages into the Pojo Messages group of topics and the Json Messages group of topics.
-1. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the Json Messages group of topics and pushes filtered messages to the Filtered Json Messages group of topics.
-1. The [GeoJSON Converter](https://github.com/usdot-jpo-ode/jpo-geojsonconverter) pulls from the Json Messages group of topics, converts the messages and pushes them to the Processed Spat/Map group of topics.
-1. The [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) pulls from the Processed Map/Spat group of topics and pushes to the [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) Output Topics group.
+1. If the message is a DriverAlert, the LogFileToAsn1CodecPublisher class pushes it to the OdeDriverAlertJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+1. If the message is a BSM, SPAT, TIM or MAP, the LogFileToAsn1CodecPublisher class pushes it to the corresponding OdeRawEncoded JSON topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+2. If the message is a BSM, SPAT, TIM or MAP, the Asn1CodecMessageServiceController pulls from the OdeRawEncoded JSON topics and processes the data with the corresponding Asn1Decode JSON class. This class then writes to the Asn1DecoderInput topic.
+3. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from that topic and pushes decoded messages to the Asn1DecoderOutput topic.
+4. The Asn1DecodeDataRouter class pulls from the Asn1DecodeOutput topic and deposits messages into the Pojo Messages group of topics and the Json Messages group of topics.
+5. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the Json Messages group of topics and pushes filtered messages to the Filtered Json Messages group of topics.
+6. The [GeoJSON Converter](https://github.com/usdot-jpo-ode/jpo-geojsonconverter) pulls from the Json Messages group of topics, converts the messages and pushes them to the Processed Spat/Map group of topics.
+7. The [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) pulls from the Processed Map/Spat group of topics and pushes to the [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) Output Topics group.
### BSM Data Flow 1 (Receiver Classes)
-1. The BSM comes in through the BsmReceiver class and is pushed to the OdeRawEncodedBSMJson topic.
+1. The BSM comes in through the BsmReceiver class and is pushed to the OdeRawEncodedBSMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
1. The Asn1CodecMessageServiceController pulls from the OdeRawEncodedBSMJson topic and pushes the BSM to the Asn1DecodeBSMJSON class.
-1. The Asn1DecodeBSMJSON class pushes the BSM to the Asn1DecoderInput topic.
+1. The Asn1DecodeBSMJSON class pushes the BSM to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic and pushes the decoded BSM to the Asn1DecoderOutput topic.
1. The AsnCodecRouterServiceController pulls from the Asn1DecoderOutput topic and passes the BSM to the Asn1DecodedDataRouter class.
1. The Asn1DecodedDataRouter pushes the BSM to the OdeBsmRxPojo, OdeBsmTxPojo, OdeBsmPojo and OdeBsmDuringEventPojo topics.
@@ -59,12 +60,14 @@ The purpose of these diagrams is to show:
### BSM Data Flow 2 (Offloaded Files)
1. The BSM is offloaded onto a directory referenced by the FileUploadController class.
1. The FileUploadController class indirectly invokes the LogFileToAsn1CodecPublisher class, which handles the offloaded message.
-1. The LogFileToAsn1CodecPublisher class pushes the BSM to the Asn1DecoderInput topic.
-1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic and pushes the decoded BSM to the Asn1DecoderOutput topic.
-1. The AsnCodecRouterServiceController pulls from the Asn1DecoderOutput topic and passes the BSM to the Asn1DecodedDataRouter class.
-1. The Asn1DecodedDataRouter pushes the BSM to the OdeBsmRxPojo, OdeBsmTxPojo, OdeBsmPojo and OdeBsmDuringEventPojo topics.
-1. The ToJsonServiceController class pulls from OdeBsmPojo and pushes the BSM in JSON form to the OdeBsmJson topic.
-1. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeBsmJson topic and pushes the filtered BSM to the FilteredOdeBsmJson topic.
+1. The LogFileToAsn1CodecPublisher class pushes the BSM to the RawEncodedBSMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+1. The Asn1CodecMessageServiceController pulls from the OdeRawEncodedBSMJson topic and pushes the BSM to the Asn1DecodeBSMJSON class.
+1. The Asn1DecodeBSMJSON class pushes the BSM to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
+3. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic and pushes the decoded BSM to the Asn1DecoderOutput topic.
+4. The AsnCodecRouterServiceController pulls from the Asn1DecoderOutput topic and passes the BSM to the Asn1DecodedDataRouter class.
+5. The Asn1DecodedDataRouter pushes the BSM to the OdeBsmRxPojo, OdeBsmTxPojo, OdeBsmPojo and OdeBsmDuringEventPojo topics.
+6. The ToJsonServiceController class pulls from OdeBsmPojo and pushes the BSM in JSON form to the OdeBsmJson topic.
+7. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeBsmJson topic and pushes the filtered BSM to the FilteredOdeBsmJson topic.
### TIM Data Flow 1 (Tim Depositor Controller)
1. The TIM comes in through the TimDepositorController class and is pushed to the J2735TimBroadcastJson, OdeTimBroadcastJson, OdeTimBroadcastPojo and Asn1EncoderInput topics.
@@ -78,9 +81,9 @@ The purpose of these diagrams is to show:
1. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeTimJson topic, filters the TIM and pushes it to the FilteredOdeTimJson topic.
### TIM Data Flow 2 (Receiver Classes)
-1. The TIM comes in through the TimReceiver class and is pushed to the OdeRawEncodedTIMJson topic.
+1. The TIM comes in through the TimReceiver class and is pushed to the OdeRawEncodedTIMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
1. The AsnCodecMessageServiceController pulls from the OdeRawEncodedTIMJson topic and passes the TIM to the Asn1DecodeTIMJSON class.
-1. The Asn1DecodeTIMJSON class pushes the TIM to the Asn1DecoderInput topic.
+1. The Asn1DecodeTIMJSON class pushes the TIM to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the TIM, and pushes it to the Asn1DecoderOutput topic.
1. The Asn1DecodedDataRouter pulls from the Asn1DecoderOutput topic and pushes the TIM to the OdeTimJson, OdeTimRxJson and OdeDNMsgJson topics.
1. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeTimJson topic, filters the TIM and pushes it to the FilteredOdeTimJson topic.
@@ -88,15 +91,17 @@ The purpose of these diagrams is to show:
### TIM Data Flow 3 (Offloaded Files)
1. The TIM is offloaded onto a directory referenced by the FileUploadController class.
1. The FileUploadController class indirectly invokes the LogFileToAsn1CodecPublisher class, which handles the offloaded message.
-1. The LogFileToAsn1CodecPublisher class pushes the TIM to the Asn1DecoderInput topic.
-1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the TIM, and pushes it to the Asn1DecoderOutput topic.
-1. The Asn1DecodedDataRouter pulls from the Asn1DecoderOutput topic and pushes the TIM to the OdeTimJson, OdeTimRxJson and OdeDNMsgJson topics.
-1. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeTimJson topic, filters the TIM and pushes it to the FilteredOdeTimJson topic.
+1. The LogFileToAsn1CodecPublisher class pushes the TIM to the RawEncodedTIMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+1. The AsnCodecMessageServiceController pulls from the OdeRawEncodedTIMJson topic and passes the TIM to the Asn1DecodeTIMJSON class.
+1. The Asn1DecodeTIMJSON class pushes the TIM to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
+2. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the TIM, and pushes it to the Asn1DecoderOutput topic.
+3. The Asn1DecodedDataRouter pulls from the Asn1DecoderOutput topic and pushes the TIM to the OdeTimJson, OdeTimRxJson and OdeDNMsgJson topics.
+4. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeTimJson topic, filters the TIM and pushes it to the FilteredOdeTimJson topic.
### SPAT Data Flow 1 (Receiver Classes)
-1. The SPAT comes in through the SpatReceiver class and is pushed to the OdeRawEncodedSPATJson topic.
+1. The SPAT comes in through the SpatReceiver class and is pushed to the OdeRawEncodedSPATJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedSPATJson topic and passes the SRM to the Asn1DecodeSPATJSON class.
-1. The Asn1DecodeSPATJSON class pushes the SPAT to the Asn1DecoderInput topic.
+1. The Asn1DecodeSPATJSON class pushes the SPAT to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the SPAT, and pushes it to the Asn1DecoderOutput topic.
1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the SPAT to the Asn1DecodedDataRouter class.
1. The Asn1DecodedDataRouter pushes the SPAT to the OdeSpatPojo, OdeSpatRxPojo, OdeDNMsgJson, OdeSpatRxJson, OdeSpatTxPojo and OdeSpatJson topics.
@@ -107,18 +112,20 @@ The purpose of these diagrams is to show:
### SPAT Data Flow 2 (Offloaded Files)
1. The SPAT is offloaded onto a directory referenced by the FileUploadController class.
1. The FileUploadController class indirectly invokes the LogFileToAsn1CodecPublisher class, which handles the offloaded message.
-1. The LogFileToAsn1CodecPublisher class pushes the SPAT to the Asn1DecoderInput topic.
-1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the SPAT, and pushes it to the Asn1DecoderOutput topic.
-1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the SPAT to the Asn1DecodedDataRouter class.
-1. The Asn1DecodedDataRouter pushes the SPAT to the OdeSpatPojo, OdeSpatRxPojo, OdeDNMsgJson, OdeSpatRxJson, OdeSpatTxPojo and OdeSpatJson topics.
-1. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeSpatJson topic, filters the SPAT, and pushes it to the FilteredOdeSpatJson topic.
-1. The [GeoJSON Converter](https://github.com/usdot-jpo-ode/jpo-geojsonconverter) pulls from the OdeSpatJson topic, converts the SPAT and pushes it to the ProcessedOdeSpatJson topic.
-1. The [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) pulls from the ProcessedOdeSpatJson topic and pushes to the [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) Output Topics group.
+1. The LogFileToAsn1CodecPublisher class pushes the SPAT to the OdeRawEncodedSPATJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedSPATJson topic and passes the SRM to the Asn1DecodeSPATJSON class.
+1. The Asn1DecodeSPATJSON class pushes the SPAT to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
+2. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the SPAT, and pushes it to the Asn1DecoderOutput topic.
+3. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the SPAT to the Asn1DecodedDataRouter class.
+4. The Asn1DecodedDataRouter pushes the SPAT to the OdeSpatPojo, OdeSpatRxPojo, OdeDNMsgJson, OdeSpatRxJson, OdeSpatTxPojo and OdeSpatJson topics.
+5. The [PPM](https://github.com/usdot-jpo-ode/jpo-cvdp) pulls from the OdeSpatJson topic, filters the SPAT, and pushes it to the FilteredOdeSpatJson topic.
+6. The [GeoJSON Converter](https://github.com/usdot-jpo-ode/jpo-geojsonconverter) pulls from the OdeSpatJson topic, converts the SPAT and pushes it to the ProcessedOdeSpatJson topic.
+7. The [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) pulls from the ProcessedOdeSpatJson topic and pushes to the [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) Output Topics group.
### MAP Data Flow 1 (Receiver Classes)
-1. The MAP comes in through the MapReceiver class and is pushed to the OdeRawEncodedMAPJson topic.
+1. The MAP comes in through the MapReceiver class and is pushed to the OdeRawEncodedMAPJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedMAPJson topic and passes the MAP to the Asn1DecodeMAPJSON class.
-1. The Asn1DecodeMAPJSON class pushes the MAP to the Asn1DecoderInput topic.
+1. The Asn1DecodeMAPJSON class pushes the MAP to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the MAP, and pushes it to the Asn1DecoderOutput topic.
1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the MAP to the Asn1DecodedDataRouter class.
1. The Asn1DecodedDataRouter class pushes the MAP to the OdeMapTxPojo and OdeMapJson topics.
@@ -128,32 +135,34 @@ The purpose of these diagrams is to show:
### MAP Data Flow 2 (Offloaded Files)
1. The MAP is offloaded onto a directory referenced by the FileUploadController class.
1. The FileUploadController class indirectly invokes the LogFileToAsn1CodecPublisher class, which handles the offloaded message.
-1. The LogFileToAsn1CodecPublisher class pushes the MAP to the Asn1DecoderInput topic.
-1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the MAP, and pushes it to the Asn1DecoderOutput topic.
-1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the MAP to the Asn1DecodedDataRouter class.
-1. The Asn1DecodedDataRouter class pushes the MAP to the OdeMapTxPojo and OdeMapJson topics.
-1. The [GeoJSON Converter](https://github.com/usdot-jpo-ode/jpo-geojsonconverter) pulls from the OdeMapJson topic, converts the MAP and pushes it to the ProcessedOdeMapJson topic.
-1. The [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) pulls from the ProcessedOdeMapJson topic and pushes to the [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) Output Topics group.
+1. The LogFileToAsn1CodecPublisher class pushes the MAP to the OdeRawEncodedMAPJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedMAPJson topic and passes the MAP to the Asn1DecodeMAPJSON class.
+1. The Asn1DecodeMAPJSON class pushes the MAP to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
+2. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the MAP, and pushes it to the Asn1DecoderOutput topic.
+3. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the MAP to the Asn1DecodedDataRouter class.
+4. The Asn1DecodedDataRouter class pushes the MAP to the OdeMapTxPojo and OdeMapJson topics.
+5. The [GeoJSON Converter](https://github.com/usdot-jpo-ode/jpo-geojsonconverter) pulls from the OdeMapJson topic, converts the MAP and pushes it to the ProcessedOdeMapJson topic.
+6. The [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) pulls from the ProcessedOdeMapJson topic and pushes to the [Conflict Monitor](https://github.com/usdot-jpo-ode/jpo-conflictmonitor) Output Topics group.
### SRM Data Flow
-1. The SRM comes in through the SrmReceiver class and is pushed to the OdeRawEncodedSRMJson topic.
+1. The SRM comes in through the SrmReceiver class and is pushed to the OdeRawEncodedSRMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedSRMJson topic and passes the SRM to the Asn1DecodeSRMJSON class.
-1. The Asn1DecodeSRMJSON class pushes the SRM to the Asn1DecoderInput topic.
+1. The Asn1DecodeSRMJSON class pushes the SRM to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the SRM, and pushes it to the Asn1DecoderOutput topic.
1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the SRM to the Asn1DecodedDataRouter class.
1. The Asn1DecodedDataRouter class pushes the SRM to the OdeSrmTxPojo and OdeSrmJson topics.
### SSM Data Flow
-1. The SSM comes in through the SsmReceiver class and is pushed to the OdeRawEncodedSSMJson topic.
+1. The SSM comes in through the SsmReceiver class and is pushed to the OdeRawEncodedSSMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedSSMJson topic and passes the SSM to the Asn1DecodeSSMJSON class.
-1. The Asn1DecodeSSMJSON class pushes the SSM to the Asn1DecoderInput topic.
+1. The Asn1DecodeSSMJSON class pushes the SSM to the Asn1DecoderInput topic. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the SSM, and pushes it to the Asn1DecoderOutput topic.
1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the SSM to the Asn1DecodedDataRouter class.
1. The Asn1DecodedDataRouter class pushes the SSM to the OdeSsmTxPojo and OdeSsmJson topics.
### PSM Data Flow
-1. The PSM comes in through the PsmReceiver class and is pushed to the OdeRawEncodedPSMJson topic.
-1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedPSMJson topic and passes the PSM to the Asn1DecodePSMJSON class.
+1. The PSM comes in through the PsmReceiver class and is pushed to the OdeRawEncodedPSMJson topic. Any IEEE 1609.3 or unsigned IEEE 1609.2 headers are stripped at this point.
+1. The AsnCodecMessageServiceController class pulls from the OdeRawEncodedPSMJson topic and passes the PSM to the Asn1DecodePSMJSON class. Any remaining signed IEEE 1609.2 headers are removed at this point.
1. The Asn1DecodePSMJSON class pushes the PSM to the Asn1DecoderInput topic.
1. The [ACM](https://github.com/usdot-jpo-ode/asn1_codec) pulls from the Asn1DecoderInput topic, decodes the PSM, and pushes it to the Asn1DecoderOutput topic.
1. The AsnCodecRouterServiceController class pulls from the Asn1DecoderOutput topic and passes the PSM to the Asn1DecodedDataRouter class.
diff --git a/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio b/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio
index 356a937ac..e230ea639 100644
--- a/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio
+++ b/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio
@@ -1 +1,186 @@
-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
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio.png b/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio.png
index d4bd75e53..2b51b350e 100644
Binary files a/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio.png and b/docs/data-flow-diagrams/bsm/BSM Data Flow.drawio.png differ
diff --git a/docs/data-flow-diagrams/map/MAP Data Flow.drawio b/docs/data-flow-diagrams/map/MAP Data Flow.drawio
index 0c847407f..a4e70d1a2 100644
--- a/docs/data-flow-diagrams/map/MAP Data Flow.drawio
+++ b/docs/data-flow-diagrams/map/MAP Data Flow.drawio
@@ -1 +1,160 @@
-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
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/data-flow-diagrams/map/MAP Data Flow.drawio.png b/docs/data-flow-diagrams/map/MAP Data Flow.drawio.png
index 8b524d078..1803fc557 100644
Binary files a/docs/data-flow-diagrams/map/MAP Data Flow.drawio.png and b/docs/data-flow-diagrams/map/MAP Data Flow.drawio.png differ
diff --git a/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio b/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio
index 4736b6615..9cdf02de0 100644
--- a/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio
+++ b/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio
@@ -1 +1,220 @@
-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
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio.png b/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio.png
index 9f30799d4..8741be56f 100644
Binary files a/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio.png and b/docs/data-flow-diagrams/spat/SPAT Data Flow.drawio.png differ
diff --git a/docs/data-flow-diagrams/tim/TIM Data Flow.drawio b/docs/data-flow-diagrams/tim/TIM Data Flow.drawio
index 97257f8be..15e7443ac 100644
--- a/docs/data-flow-diagrams/tim/TIM Data Flow.drawio
+++ b/docs/data-flow-diagrams/tim/TIM Data Flow.drawio
@@ -1 +1,315 @@
-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
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/data-flow-diagrams/tim/TIM Data Flow.drawio.png b/docs/data-flow-diagrams/tim/TIM Data Flow.drawio.png
index 0b87dcddd..529846eb3 100644
Binary files a/docs/data-flow-diagrams/tim/TIM Data Flow.drawio.png and b/docs/data-flow-diagrams/tim/TIM Data Flow.drawio.png differ
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/OdeProperties.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/OdeProperties.java
index 98c57adf7..b32674343 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/OdeProperties.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/OdeProperties.java
@@ -119,6 +119,7 @@ public class OdeProperties implements EnvironmentAware {
private Set kafkaTopicsDisabledSet = new HashSet<>();
// BSM
+ private final String BSM_START_FLAG = "0014";
private String kafkaTopicOdeBsmPojo = "topic.OdeBsmPojo";
private String kafkaTopicOdeBsmJson = "topic.OdeBsmJson";
private String kafkaTopicOdeBsmRxPojo = "topic.OdeBsmRxPojo";
@@ -130,6 +131,7 @@ public class OdeProperties implements EnvironmentAware {
private int bsmBufferSize = 500;
// TIM
+ private final String TIM_START_FLAG = "001f";
private String kafkaTopicOdeTimJson = "topic.OdeTimJson";
private String kafkaTopicOdeDNMsgJson = "topic.OdeDNMsgJson";
private String kafkaTopicOdeTimRxJson = "topic.OdeTimRxJson";
@@ -142,6 +144,7 @@ public class OdeProperties implements EnvironmentAware {
private int timBufferSize = 500;
//SPAT
+ private final String SPAT_START_FLAG = "0013";
private String kafkaTopicOdeSpatTxPojo = "topic.OdeSpatTxPojo";
private String kafkaTopicOdeSpatPojo = "topic.OdeSpatPojo";
private String kafkaTopicOdeSpatJson = "topic.OdeSpatJson";
@@ -150,9 +153,10 @@ public class OdeProperties implements EnvironmentAware {
private String kafkaTopicFilteredOdeSpatJson = "topic.FilteredOdeSpatJson";
private String kafkaTopicOdeRawEncodedSPATJson = "topic.OdeRawEncodedSPATJson";
private int spatReceiverPort = 44910;
- private int spatBufferSize = 1000;
+ private int spatBufferSize = 500;
//SSM
+ private final String SSM_START_FLAG = "001e";
private String kafkaTopicOdeSsmPojo = "topic.OdeSsmPojo";
private String kafkaTopicOdeSsmJson = "topic.OdeSsmJson";
private String kafkaTopicOdeRawEncodedSSMJson = "topic.OdeRawEncodedSSMJson";
@@ -160,6 +164,7 @@ public class OdeProperties implements EnvironmentAware {
private int ssmBufferSize = 500;
//SRM
+ private final String SRM_START_FLAG = "001d";
private String kafkaTopicOdeSrmTxPojo = "topic.OdeSrmTxPojo";
private String kafkaTopicOdeSrmJson = "topic.OdeSrmJson";
private String kafkaTopicOdeRawEncodedSRMJson = "topic.OdeRawEncodedSRMJson";
@@ -167,6 +172,7 @@ public class OdeProperties implements EnvironmentAware {
private int srmBufferSize = 500;
//MAP
+ private final String MAP_START_FLAG = "0012";
private String kafkaTopicOdeRawEncodedMAPJson = "topic.OdeRawEncodedMAPJson";
private String kafkaTopicOdeMapTxPojo = "topic.OdeMapTxPojo";
private String kafkaTopicOdeMapJson = "topic.OdeMapJson";
@@ -174,6 +180,7 @@ public class OdeProperties implements EnvironmentAware {
private int mapBufferSize = 2048;
// PSM
+ private final String PSM_START_FLAG = "0020";
private String kafkaTopicOdeRawEncodedPSMJson = "topic.OdeRawEncodedPSMJson";
private String kafkaTopicOdePsmTxPojo = "topic.OdePsmTxPojo";
private String kafkaTopicOdePsmJson = "topic.OdePsmJson";
@@ -385,6 +392,10 @@ public void setVerboseJson(Boolean verboseJson) {
this.verboseJson = verboseJson;
}
+ public String getBsmStartFlag() {
+ return BSM_START_FLAG;
+ }
+
public int getBsmReceiverPort() {
return bsmReceiverPort;
}
@@ -401,6 +412,10 @@ public void setBsmBufferSize(int bsmBufferSize) {
this.bsmBufferSize = bsmBufferSize;
}
+ public String getTimStartFlag() {
+ return TIM_START_FLAG;
+ }
+
public int getTimReceiverPort() {
return timReceiverPort;
}
@@ -417,6 +432,10 @@ public void setTimBufferSize(int timBufferSize) {
this.timBufferSize = timBufferSize;
}
+ public String getSsmStartFlag() {
+ return SSM_START_FLAG;
+ }
+
public int getSsmReceiverPort() {
return ssmReceiverPort;
}
@@ -433,6 +452,10 @@ public void setSsmBufferSize(int ssmBufferSize) {
this.ssmBufferSize = ssmBufferSize;
}
+ public String getSrmStartFlag() {
+ return SRM_START_FLAG;
+ }
+
public int getSrmReceiverPort() {
return srmReceiverPort;
}
@@ -449,6 +472,10 @@ public void setSrmBufferSize(int srmBufferSize) {
this.srmBufferSize = srmBufferSize;
}
+ public String getSpatStartFlag() {
+ return SPAT_START_FLAG;
+ }
+
public int getSpatReceiverPort() {
return spatReceiverPort;
}
@@ -465,6 +492,10 @@ public void setSpatBufferSize(int spatBufferSize) {
this.spatBufferSize = spatBufferSize;
}
+ public String getMapStartFlag() {
+ return MAP_START_FLAG;
+ }
+
public int getMapReceiverPort() {
return mapReceiverPort;
}
@@ -481,6 +512,10 @@ public void setMapBufferSize(int mapBufferSize) {
this.mapBufferSize = mapBufferSize;
}
+ public String getPsmStartFlag() {
+ return PSM_START_FLAG;
+ }
+
public int getPsmReceiverPort() {
return psmReceiverPort;
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisher.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisher.java
index 2b229ec7d..82d550f32 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisher.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisher.java
@@ -35,8 +35,6 @@
import us.dot.its.jpo.ode.importer.parser.LogFileParser;
import us.dot.its.jpo.ode.importer.parser.RxMsgFileParser;
import us.dot.its.jpo.ode.importer.parser.SpatLogFileParser;
-import us.dot.its.jpo.ode.model.Asn1Encoding;
-import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
import us.dot.its.jpo.ode.model.OdeBsmMetadata;
@@ -156,76 +154,67 @@ public boolean isSpatRecord() {
private void publishList(XmlUtils xmlUtils, List dataList) throws JsonProcessingException {
serialId.setBundleSize(dataList.size());
+
for (OdeData odeData : dataList) {
OdeLogMetadata msgMetadata = (OdeLogMetadata) odeData.getMetadata();
OdeMsgPayload msgPayload = (OdeMsgPayload) odeData.getPayload();
msgMetadata.setSerialId(serialId);
if (isDriverAlertRecord()) {
- logger.debug("Publishing a driverAlert.");
-
publisher.publish(JsonUtils.toJson(odeData, false),
publisher.getOdeProperties().getKafkaTopicDriverAlertJson());
+ } else if (isBsmRecord()) {
+ publisher.publish(JsonUtils.toJson(odeData, false),
+ publisher.getOdeProperties().getKafkaTopicOdeRawEncodedBSMJson());
+ } else if (isSpatRecord()) {
+ publisher.publish(JsonUtils.toJson(odeData, false),
+ publisher.getOdeProperties().getKafkaTopicOdeRawEncodedSPATJson());
} else {
- if (isBsmRecord()) {
- logger.debug("Publishing a BSM");
- } else if (isSpatRecord()) {
- logger.debug("Publishing a Spat");
- } else {
- logger.debug("Publishing a TIM or MAP");
- }
-
- if (!(isSpatRecord() && msgMetadata instanceof OdeSpatMetadata
- && !((OdeSpatMetadata) msgMetadata).getIsCertPresent())) {
- if (checkHeader(msgPayload) == "Ieee1609Dot2Data") {
- Asn1Encoding msgEncoding = new Asn1Encoding("root", "Ieee1609Dot2Data", EncodingRule.COER);
- msgMetadata.addEncoding(msgEncoding);
- }
+ // Determine the message type (MAP or TIM are the current other options)
+ String messageType = determineMessageType(msgPayload);
+ if (messageType == "MAP") {
+ publisher.publish(JsonUtils.toJson(odeData, false),
+ publisher.getOdeProperties().getKafkaTopicOdeRawEncodedMAPJson());
+ } else if (messageType == "TIM") {
+ publisher.publish(JsonUtils.toJson(odeData, false),
+ publisher.getOdeProperties().getKafkaTopicOdeRawEncodedTIMJson());
}
-
- Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame",
- EncodingRule.UPER);
- msgMetadata.addEncoding(unsecuredDataEncoding);
-
- publisher.publish(xmlUtils.toXml(odeData),
- publisher.getOdeProperties().getKafkaTopicAsn1DecoderInput());
}
+
serialId.increment();
}
}
-
/**
- * Checks the header of the OdeMsgPayload and determines the encoding rule to be used in the Asn1DecoderInput XML.
- * The payload is checked for various message start flags. It will add the encoding rule to the Asn1DecoderInput XML
- * to tell the ASN1 codec to extract data from the header into the output message.
+ * Determines the message type based off the most likely start flag
*
- * @param payload The OdeMsgPayload to check the header of.
- * @return The encoding rule to be used in the Asn1DecoderInput XML.
+ * @param payload The OdeMsgPayload to check the content of.
*/
- public String checkHeader(OdeMsgPayload payload) {
- JSONObject payloadJson;
- String header = null;
+ public String determineMessageType(OdeMsgPayload payload) {
+ String messageType = "";
try {
- payloadJson = JsonUtils.toJSONObject(payload.getData().toJson());
- String hexPacket = payloadJson.getString("bytes");
-
- for (String key : msgStartFlags.keySet()) {
- String startFlag = msgStartFlags.get(key);
- int startIndex = hexPacket.toLowerCase().indexOf(startFlag);
- logger.debug("Start index for " + key + "(" + startFlag + ")" + " is: " + startIndex);
- if (startIndex <= 20 && startIndex != 0 && startIndex != -1) {
- logger.debug("Message has supported Ieee1609Dot2Data header, adding encoding rule to Asn1DecoderInput XML");
- header = "Ieee1609Dot2Data";
- break;
+ JSONObject payloadJson = JsonUtils.toJSONObject(payload.getData().toJson());
+ String hexString = payloadJson.getString("bytes").toLowerCase();
+
+ HashMap flagIndexes = new HashMap();
+ flagIndexes.put("MAP", hexString.indexOf(msgStartFlags.get("MAP")));
+ flagIndexes.put("TIM", hexString.indexOf(msgStartFlags.get("TIM")));
+
+ int lowestIndex = Integer.MAX_VALUE;
+ for (String key : flagIndexes.keySet()) {
+ if (flagIndexes.get(key) == -1) {
+ logger.debug("This message is not of type " + key);
+ continue;
+ }
+ if (flagIndexes.get(key) < lowestIndex) {
+ messageType = key;
+ lowestIndex = flagIndexes.get(key);
}
- logger.debug("Payload JSON: " + payloadJson);
}
} catch (JsonUtilsException e) {
logger.error("JsonUtilsException while checking message header. Stacktrace: " + e.toString());
-
}
- return header;
+ return messageType;
}
// This method will check if the next character is a newline character (0x0A in hex or 10 in converted decimal)
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/importer/parser/PayloadParser.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/importer/parser/PayloadParser.java
index 2436c3025..c3467aced 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/importer/parser/PayloadParser.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/importer/parser/PayloadParser.java
@@ -33,12 +33,6 @@ public class PayloadParser extends LogFileParser {
private static Logger logger = LoggerFactory.getLogger(PayloadParser.class);
private static HashMap msgStartFlags = new HashMap();
- // Maximum header size for 1609 payload headers
- private static final int HEADER_SIZE_1609 = 20;
-
- // Maximum header size for WSMP payload headers
- private static final int HEADER_SIZE_WSMP = 35;
-
public static final int PAYLOAD_LENGTH = 2;
protected short payloadLength;
@@ -63,7 +57,6 @@ public ParserStatus parseFile(BufferedInputStream bis, String fileName) throws F
if (status != ParserStatus.COMPLETE)
return status;
short length = CodecUtils.bytesToShort(readBuffer, 0, PAYLOAD_LENGTH, ByteOrder.LITTLE_ENDIAN);
- logger.debug("Payload length is: " + length);
setPayloadLength(length);
}
@@ -72,7 +65,7 @@ public ParserStatus parseFile(BufferedInputStream bis, String fileName) throws F
status = parseStep(bis, getPayloadLength());
if (status != ParserStatus.COMPLETE)
return status;
- setPayload(removeHeader(Arrays.copyOf(readBuffer, getPayloadLength())));
+ setPayload(stripDot3Header(Arrays.copyOf(readBuffer, getPayloadLength())));
}
resetStep();
@@ -104,43 +97,41 @@ public LogFileParser setPayload(byte[] payload) {
return this;
}
- @Override
- public void writeTo(OutputStream os) throws IOException {
- os.write(CodecUtils.shortToBytes(payloadLength, ByteOrder.LITTLE_ENDIAN));
- os.write(payload, 0, payloadLength);
- }
+ @Override
+ public void writeTo(OutputStream os) throws IOException {
+ os.write(CodecUtils.shortToBytes(payloadLength, ByteOrder.LITTLE_ENDIAN));
+ os.write(payload, 0, payloadLength);
+ }
- // Removes the 1609.2 header but will keep the 1609.1 header
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
+ /* Strips the 1609.3 and unsigned 1609.2 headers if they are present.
+ Will return the payload with a signed 1609.2 header if it is present.
+ Otherwise, returns just the payload. */
+ public byte[] stripDot3Header(byte[] packet) {
+ String hexString = HexUtils.toHexString(packet);
String hexPacketParsed = "";
- for (String key : msgStartFlags.keySet()) {
- String startFlag = msgStartFlags.get(key);
- int startIndex = hexPacket.toLowerCase().indexOf(startFlag);
- if (hexPacketParsed.equals("")) {
- logger.debug("Start index for: " + key + " is: " + startIndex);
- if (startIndex == -1) {
- logger.debug("Message does not have header for: " + key);
- continue;
- } else if (startIndex <= HEADER_SIZE_1609) {
- logger.debug("Message has supported header. startIndex: " + startIndex + " msgFlag: " + startFlag);
- hexPacketParsed = hexPacket;
- // If the header type is WSMP, the header will be stripped from the payload.
- } else if (startIndex > HEADER_SIZE_1609 && startIndex < HEADER_SIZE_WSMP) {
- int trueStartIndex = HEADER_SIZE_1609
- + hexPacket.substring(HEADER_SIZE_1609, hexPacket.length()).indexOf(startFlag);
- logger.debug("Found payload start at: " + trueStartIndex);
- hexPacketParsed = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
- }
+
+ for (String start_flag : msgStartFlags.values()) {
+ int payloadStartIndex = hexString.indexOf(start_flag);
+ if (payloadStartIndex == -1)
+ continue;
+
+ String headers = hexString.substring(0, payloadStartIndex);
+ String payload = hexString.substring(payloadStartIndex, hexString.length());
+ // Look for the index of the start flag of a signed 1609.2 header, if one exists
+ int signedDot2StartIndex = headers.indexOf("038100");
+ if (signedDot2StartIndex == -1)
+ hexPacketParsed = payload;
+ else
+ hexPacketParsed = headers.substring(signedDot2StartIndex, headers.length()) + payload;
+ break;
}
+
if (hexPacketParsed.equals("")) {
- hexPacketParsed = hexPacket;
- logger.debug("Could not identify a Header in the following packet: " + hexPacketParsed);
- } else {
- logger.debug("Payload hex: " + hexPacketParsed);
+ hexPacketParsed = hexString;
+ logger.debug("Packet is not a BSM, TIM or Map message: " + hexPacketParsed);
}
+
return HexUtils.fromHexString(hexPacketParsed);
}
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/AbstractAsn1DecodeMessageJSON.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/AbstractAsn1DecodeMessageJSON.java
index 1fe61439d..d47db451d 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/AbstractAsn1DecodeMessageJSON.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/AbstractAsn1DecodeMessageJSON.java
@@ -14,14 +14,25 @@ public abstract class AbstractAsn1DecodeMessageJSON extends AbstractSubscriberPr
private Logger logger = LoggerFactory.getLogger(this.getClass());
protected StringPublisher codecPublisher;
+ protected String payload_start_flag;
public AbstractAsn1DecodeMessageJSON() {
super();
}
- public AbstractAsn1DecodeMessageJSON(StringPublisher codecPublisher) {
+ public AbstractAsn1DecodeMessageJSON(StringPublisher codecPublisher, String payload_start_flag) {
super();
this.codecPublisher = codecPublisher;
+ this.payload_start_flag = payload_start_flag;
+ }
+
+ // Strips the IEEE 1609.2 security header (if it exists) and returns the payload
+ protected String stripDot2Header(String hexString) {
+ hexString = hexString.toLowerCase();
+ int startIndex = hexString.indexOf(payload_start_flag);
+ if (startIndex == -1)
+ return "BAD DATA";
+ return hexString.substring(startIndex, hexString.length());
}
protected void publishEncodedMessageToAsn1Decoder(OdeData odeData) {
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSON.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSON.java
index 9abf490ca..33565a56e 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSON.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSON.java
@@ -1,12 +1,12 @@
package us.dot.its.jpo.ode.services.asn1.message;
-import java.util.Set;
-
-import org.json.JSONArray;
+import org.apache.tomcat.util.buf.HexUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.coder.StringPublisher;
import us.dot.its.jpo.ode.model.Asn1Encoding;
@@ -14,94 +14,42 @@
import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
import us.dot.its.jpo.ode.model.OdeBsmMetadata;
-import us.dot.its.jpo.ode.model.OdeBsmMetadata.BsmSource;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
-import us.dot.its.jpo.ode.model.OdeLogMsgMetadataLocation;
-import us.dot.its.jpo.ode.model.OdeMsgPayload;
-import us.dot.its.jpo.ode.model.ReceivedMessageDetails;
-import us.dot.its.jpo.ode.model.RxSource;
-/***
- * Encoded message Processor
- */
public class Asn1DecodeBSMJSON extends AbstractAsn1DecodeMessageJSON {
- private static final String BSMContentType = "BsmMessageContent";
-
private Logger logger = LoggerFactory.getLogger(this.getClass());
-
+ private ObjectMapper objectMapper = new ObjectMapper();
public Asn1DecodeBSMJSON(OdeProperties odeProps) {
- super(new StringPublisher(odeProps));
+ super(new StringPublisher(odeProps), odeProps.getBsmStartFlag());
}
@Override
- protected Object process(String consumedData) {
-
- OdeData odeData = null;
- OdeMsgPayload payload = null;
-
+ protected OdeAsn1Data process(String consumedData) {
+ OdeAsn1Data messageToPublish = null;
try {
- logger.info("Processing BSM data");
- logger.debug("BSM data: {}", consumedData);
- JSONObject rawJSONObject = new JSONObject(consumedData);
- Set> keys = rawJSONObject.keySet();
- for (Object key : keys)
- {
- //Send encoded BSM content to Codec service to decode BSM
- if (key != null && key.toString().equals(BSMContentType)) {
- /**process consumed data { "BsmMessageContent": [{ "metadata": { "utctimestamp:"2020-11-30T23:45:24.913657Z" }, "payload":"001480CF4B950C400022D2666E923D1EA6D4E28957BD55FFFFF001C758FD7E67D07F7FFF8000000002020218E1C1004A40196FBC042210115C030EF1408801021D4074CE7E1848101C5C0806E8E1A50101A84056EE8A1AB4102B840A9ADA21B9010259C08DEE1C1C560FFDDBFC070C0222210018BFCE309623120FFE9BFBB10C8238A0FFDC3F987114241610009BFB7113024780FFAC3F95F13A26800FED93FDD51202C5E0FE17BF9B31202FBAFFFEC87FC011650090019C70808440C83207873800000000001095084081C903447E31C12FC0"}]}
- */
- OdeBsmMetadata metadata = null;
-
- JSONArray rawBSMJsonContentArray = rawJSONObject.getJSONArray(BSMContentType);
- for (int i = 0; i < rawBSMJsonContentArray.length(); i++) {
- JSONObject rawBSMJsonContent = (JSONObject) rawBSMJsonContentArray.get(i);
- String encodedPayload = rawBSMJsonContent.get("payload").toString();
- JSONObject rawmetadata = (JSONObject) rawBSMJsonContent.get("metadata");
- logger.debug("RAW BSM: {}", encodedPayload);
- // construct payload
- payload = new OdeAsn1Payload(new OdeHexByteArray(encodedPayload));
-
- // construct metadata
- metadata = new OdeBsmMetadata(payload);
- metadata.setOdeReceivedAt(rawmetadata.getString("utctimestamp"));
- metadata.setRecordType(RecordType.bsmTx);
- metadata.setSecurityResultCode(SecurityResultCode.success);
- if (rawmetadata.has("originRsu"))
- metadata.setOriginIp(rawmetadata.getString("originRsu"));
+ JSONObject rawBsmJsonObject = new JSONObject(consumedData);
- // construct metadata: receivedMessageDetails
- ReceivedMessageDetails receivedMessageDetails = new ReceivedMessageDetails();
- receivedMessageDetails.setRxSource(RxSource.RV);
+ String jsonStringMetadata = rawBsmJsonObject.get("metadata").toString();
+ OdeBsmMetadata metadata = objectMapper.readValue(jsonStringMetadata, OdeBsmMetadata.class);
- // construct metadata: locationData
- OdeLogMsgMetadataLocation locationData = new OdeLogMsgMetadataLocation();
- receivedMessageDetails.setLocationData(locationData);
+ Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame", EncodingRule.UPER);
+ metadata.addEncoding(unsecuredDataEncoding);
- metadata.setReceivedMessageDetails(receivedMessageDetails);
- metadata.setBsmSource(BsmSource.RV);
+ String payloadHexString = ((JSONObject)((JSONObject) rawBsmJsonObject.get("payload")).get("data")).getString("bytes");
+ payloadHexString = super.stripDot2Header(payloadHexString);
- Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame",
- EncodingRule.UPER);
- metadata.addEncoding(unsecuredDataEncoding);
+ if (payloadHexString.equals("BAD DATA")) {
+ logger.error("NON-BSM DATA ENCOUNTERED IN THE ASN1DECODEBSMJSON CLASS");
+ return null;
+ }
- // construct odeData
- odeData = new OdeAsn1Data(metadata, payload);
+ OdeAsn1Payload payload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
- publishEncodedMessageToAsn1Decoder(odeData);
- }
-
- }
- else {
- logger.error("Error received invalid key from consumed message");
- }
- }
+ messageToPublish = new OdeAsn1Data(metadata, payload);
+ publishEncodedMessageToAsn1Decoder(messageToPublish);
} catch (Exception e) {
logger.error("Error publishing to Asn1DecoderInput: {}", e.getMessage());
}
- return null;
+ return messageToPublish;
}
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSON.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSON.java
index 8e03d223b..1e70ae76d 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSON.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSON.java
@@ -1,97 +1,56 @@
package us.dot.its.jpo.ode.services.asn1.message;
-import java.util.Set;
-
-import org.json.JSONArray;
+import org.apache.tomcat.util.buf.HexUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.coder.StringPublisher;
import us.dot.its.jpo.ode.model.Asn1Encoding;
import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
import us.dot.its.jpo.ode.model.OdeMapMetadata;
-import us.dot.its.jpo.ode.model.OdeMapMetadata.MapSource;
-import us.dot.its.jpo.ode.model.OdeMsgPayload;
-/***
- * Encoded message Processor
- */
public class Asn1DecodeMAPJSON extends AbstractAsn1DecodeMessageJSON {
- private static final String MAPContentType = "MapMessageContent";
-
private Logger logger = LoggerFactory.getLogger(this.getClass());
+ private ObjectMapper objectMapper = new ObjectMapper();
public Asn1DecodeMAPJSON(OdeProperties odeProps) {
- super(new StringPublisher(odeProps));
+ super(new StringPublisher(odeProps), odeProps.getMapStartFlag());
}
@Override
- protected Object process(String consumedData) {
-
- OdeData odeData = null;
- OdeMsgPayload payload = null;
-
+ protected OdeAsn1Data process(String consumedData) {
+ OdeAsn1Data messageToPublish = null;
try {
- logger.info("Processing MAP data");
- logger.debug("MAP data: {}", consumedData);
- JSONObject rawJSONObject = new JSONObject(consumedData);
- Set> keys = rawJSONObject.keySet();
- for (Object key : keys)
- {
- //Send encoded MAP content to Codec service to decode MAP
- if (key != null && key.toString().equals(MAPContentType)) {
- /**process consumed data { "MapMessageContent": [{ "metadata": { "utctimestamp:"2020-11-30T23:45:24.913657Z" }, "payload":"00121E38041180000138044CD8EA0F3D3FC4A600000100000000030AE0C0615C18"}]}
- */
- OdeMapMetadata metadata = null;
-
- JSONArray rawMAPJsonContentArray = rawJSONObject.getJSONArray(MAPContentType);
- for (int i = 0; i < rawMAPJsonContentArray.length(); i++) {
- JSONObject rawMAPJsonContent = (JSONObject) rawMAPJsonContentArray.get(i);
- String encodedPayload = rawMAPJsonContent.get("payload").toString();
- JSONObject rawmetadata = (JSONObject) rawMAPJsonContent.get("metadata");
- logger.debug("RAW MAP: {}", encodedPayload);
- // construct payload
- payload = new OdeAsn1Payload(new OdeHexByteArray(encodedPayload));
-
- // construct metadata
- metadata = new OdeMapMetadata(payload);
- metadata.setOdeReceivedAt(rawmetadata.getString("utctimestamp"));
- metadata.setOriginIp(rawmetadata.getString("originRsu"));
- metadata.setRecordType(RecordType.mapTx);
- metadata.setSecurityResultCode(SecurityResultCode.success);
+ JSONObject rawMapJsonObject = new JSONObject(consumedData);
- if (rawmetadata.getString("source").equals("RSU"))
- metadata.setMapSource(MapSource.RSU);
- else
- metadata.setMapSource(MapSource.V2X);
+ String jsonStringMetadata = rawMapJsonObject.get("metadata").toString();
+ OdeMapMetadata metadata = objectMapper.readValue(jsonStringMetadata, OdeMapMetadata.class);
- Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame",
- EncodingRule.UPER);
- metadata.addEncoding(unsecuredDataEncoding);
+ Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame", EncodingRule.UPER);
+ metadata.addEncoding(unsecuredDataEncoding);
- // construct odeData
- odeData = new OdeAsn1Data(metadata, payload);
+ String payloadHexString = ((JSONObject)((JSONObject) rawMapJsonObject.get("payload")).get("data")).getString("bytes");
+ payloadHexString = super.stripDot2Header(payloadHexString);
- publishEncodedMessageToAsn1Decoder(odeData);
- }
-
- }
- else {
- logger.error("Error received invalid key from consumed message");
- }
+ if (payloadHexString.equals("BAD DATA")) {
+ logger.error("NON-MAP DATA ENCOUNTERED IN THE ASN1DECODEMAPJSON CLASS");
+ return null;
}
+
+ OdeAsn1Payload payload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+
+ messageToPublish = new OdeAsn1Data(metadata, payload);
+ publishEncodedMessageToAsn1Decoder(messageToPublish);
} catch (Exception e) {
logger.error("Error publishing to Asn1DecoderInput: {}", e.getMessage());
}
- return null;
+ return messageToPublish;
}
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSON.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSON.java
index 59b519c2e..a766228b9 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSON.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSON.java
@@ -1,95 +1,55 @@
package us.dot.its.jpo.ode.services.asn1.message;
-import java.util.Set;
-
-import org.json.JSONArray;
+import org.apache.tomcat.util.buf.HexUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.coder.StringPublisher;
import us.dot.its.jpo.ode.model.Asn1Encoding;
import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
import us.dot.its.jpo.ode.model.OdePsmMetadata;
-import us.dot.its.jpo.ode.model.OdePsmMetadata.PsmSource;
-import us.dot.its.jpo.ode.model.OdeMsgPayload;
-/***
- * Encoded message Processor
- */
public class Asn1DecodePSMJSON extends AbstractAsn1DecodeMessageJSON {
- private static final String PSMContentType = "PsmMessageContent";
-
private Logger logger = LoggerFactory.getLogger(this.getClass());
-
+ private ObjectMapper objectMapper = new ObjectMapper();
public Asn1DecodePSMJSON(OdeProperties odeProps) {
- super(new StringPublisher(odeProps));
+ super(new StringPublisher(odeProps), odeProps.getPsmStartFlag());
}
@Override
- protected Object process(String consumedData) {
-
- OdeData odeData = null;
- OdeMsgPayload payload = null;
-
+ protected OdeAsn1Data process(String consumedData) {
+ OdeAsn1Data messageToPublish = null;
try {
- logger.info("Processing PSM data");
- logger.debug("PSM data: {}", consumedData);
- JSONObject rawJSONObject = new JSONObject(consumedData);
- Set> keys = rawJSONObject.keySet();
- for (Object key : keys)
- {
- //Send encoded PSM content to Codec service to decode PSM
- if (key != null && key.toString().equals(PSMContentType)) {
- OdePsmMetadata metadata = null;
-
- JSONArray rawPSMJsonContentArray = rawJSONObject.getJSONArray(PSMContentType);
- for (int i = 0; i < rawPSMJsonContentArray.length(); i++) {
- JSONObject rawPSMJsonContent = (JSONObject) rawPSMJsonContentArray.get(i);
- String encodedPayload = rawPSMJsonContent.get("payload").toString();
- JSONObject rawmetadata = (JSONObject) rawPSMJsonContent.get("metadata");
- logger.debug("RAW PSM: {}", encodedPayload);
- // construct payload
- payload = new OdeAsn1Payload(new OdeHexByteArray(encodedPayload));
-
- // construct metadata
- metadata = new OdePsmMetadata(payload);
- metadata.setOdeReceivedAt(rawmetadata.getString("utctimestamp"));
- metadata.setOriginIp(rawmetadata.getString("originRsu"));
- metadata.setRecordType(RecordType.psmTx);
- metadata.setSecurityResultCode(SecurityResultCode.success);
+ JSONObject rawPsmJsonObject = new JSONObject(consumedData);
- if (rawmetadata.getString("source").equals("RSU"))
- metadata.setPsmSource(PsmSource.RSU);
- else
- metadata.setPsmSource(PsmSource.V2X);
+ String jsonStringMetadata = rawPsmJsonObject.get("metadata").toString();
+ OdePsmMetadata metadata = objectMapper.readValue(jsonStringMetadata, OdePsmMetadata.class);
- Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame",
- EncodingRule.UPER);
- metadata.addEncoding(unsecuredDataEncoding);
+ Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame", EncodingRule.UPER);
+ metadata.addEncoding(unsecuredDataEncoding);
- // construct odeData
- odeData = new OdeAsn1Data(metadata, payload);
+ String payloadHexString = ((JSONObject)((JSONObject) rawPsmJsonObject.get("payload")).get("data")).getString("bytes");
+ payloadHexString = super.stripDot2Header(payloadHexString);
- publishEncodedMessageToAsn1Decoder(odeData);
- }
-
- }
- else {
- logger.error("Error received invalid key from consumed message");
- }
+ if (payloadHexString.equals("BAD DATA")) {
+ logger.error("NON-PSM DATA ENCOUNTERED IN THE ASN1DECODEPSMJSON CLASS");
+ return null;
}
+
+ OdeAsn1Payload payload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+
+ messageToPublish = new OdeAsn1Data(metadata, payload);
+ publishEncodedMessageToAsn1Decoder(messageToPublish);
} catch (Exception e) {
logger.error("Error publishing to Asn1DecoderInput: {}", e.getMessage());
}
- return null;
+ return messageToPublish;
}
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSON.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSON.java
index cdb4f2421..305665044 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSON.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSON.java
@@ -1,107 +1,57 @@
package us.dot.its.jpo.ode.services.asn1.message;
-import java.util.Set;
-
-import org.json.JSONArray;
+import org.apache.tomcat.util.buf.HexUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.coder.StringPublisher;
import us.dot.its.jpo.ode.model.Asn1Encoding;
import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
-import us.dot.its.jpo.ode.model.OdeLogMsgMetadataLocation;
-import us.dot.its.jpo.ode.model.OdeMsgPayload;
import us.dot.its.jpo.ode.model.OdeSpatMetadata;
-import us.dot.its.jpo.ode.model.OdeSpatMetadata.SpatSource;
-import us.dot.its.jpo.ode.model.ReceivedMessageDetails;
-import us.dot.its.jpo.ode.model.RxSource;
-/***
- * Encoded message Processor
- */
public class Asn1DecodeSPATJSON extends AbstractAsn1DecodeMessageJSON {
- private static final String SPATContentType = "SpatMessageContent";
-
private Logger logger = LoggerFactory.getLogger(this.getClass());
+ private ObjectMapper objectMapper = new ObjectMapper();
public Asn1DecodeSPATJSON(OdeProperties odeProps) {
- super(new StringPublisher(odeProps));
+ super(new StringPublisher(odeProps), odeProps.getSpatStartFlag());
}
@Override
- protected Object process(String consumedData) {
-
- OdeData odeData = null;
- OdeMsgPayload payload = null;
-
+ protected OdeAsn1Data process(String consumedData) {
+ OdeAsn1Data messageToPublish = null;
try {
- logger.info("Processing SPAT data");
- logger.debug("SPAT data: {}", consumedData);
- JSONObject rawJSONObject = new JSONObject(consumedData);
- Set> keys = rawJSONObject.keySet();
- for (Object key : keys) {
-
- if (key != null && key.toString().equals(SPATContentType)) {
- /**
- * process consumed data { "SpatMessageContent": [{ "metadata": { "utctimestamp:
- * "2020-11-30T23:45:24.913657Z" }
- * "payload":"00131A604A380583702005837800080008100000040583705043002580"}]}
- */
-
- OdeSpatMetadata metadata = null;
- JSONArray rawSPATJsonContentArray = rawJSONObject.getJSONArray(SPATContentType);
- for (int i = 0; i < rawSPATJsonContentArray.length(); i++) {
- JSONObject rawSPATJsonContent = (JSONObject) rawSPATJsonContentArray.get(i);
- String encodedPayload = rawSPATJsonContent.get("payload").toString();
- JSONObject rawmetadata = (JSONObject) rawSPATJsonContent.get("metadata");
- logger.debug("RAW SPAT: {}", encodedPayload);
- // construct payload
- payload = new OdeAsn1Payload(new OdeHexByteArray(encodedPayload));
+ JSONObject rawSpatJsonObject = new JSONObject(consumedData);
- // construct metadata
- metadata = new OdeSpatMetadata(payload);
- metadata.setOdeReceivedAt(rawmetadata.getString("utctimestamp"));
- metadata.setOriginIp(rawmetadata.getString("originRsu"));
- metadata.setRecordType(RecordType.spatTx);
- metadata.setSecurityResultCode(SecurityResultCode.success);
+ String jsonStringMetadata = rawSpatJsonObject.get("metadata").toString();
+ OdeSpatMetadata metadata = objectMapper.readValue(jsonStringMetadata, OdeSpatMetadata.class);
- // construct metadata: receivedMessageDetails
- ReceivedMessageDetails receivedMessageDetails = new ReceivedMessageDetails();
- receivedMessageDetails.setRxSource(RxSource.NA);
+ Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame", EncodingRule.UPER);
+ metadata.addEncoding(unsecuredDataEncoding);
- // construct metadata: locationData
- OdeLogMsgMetadataLocation locationData = new OdeLogMsgMetadataLocation();
- receivedMessageDetails.setLocationData(locationData);
+ String payloadHexString = ((JSONObject) ((JSONObject) rawSpatJsonObject.get("payload")).get("data"))
+ .getString("bytes");
+ payloadHexString = super.stripDot2Header(payloadHexString);
- metadata.setReceivedMessageDetails(receivedMessageDetails);
- metadata.setSpatSource(SpatSource.V2X);
-
- Asn1Encoding unsecuredDataEncoding = new Asn1Encoding("unsecuredData", "MessageFrame",
- EncodingRule.UPER);
- metadata.addEncoding(unsecuredDataEncoding);
+ if (payloadHexString.equals("BAD DATA")) {
+ logger.error("NON-SPAT DATA ENCOUNTERED IN THE ASN1DECODESPATJSON CLASS");
+ return null;
+ }
- // construct odeData
- odeData = new OdeAsn1Data(metadata, payload);
+ OdeAsn1Payload payload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
- publishEncodedMessageToAsn1Decoder(odeData);
- }
- }
- else {
- logger.error("Error received invalid key from consumed message");
- }
- }
+ messageToPublish = new OdeAsn1Data(metadata, payload);
+ publishEncodedMessageToAsn1Decoder(messageToPublish);
} catch (Exception e) {
logger.error("Error publishing to Asn1DecoderInput: {}", e.getMessage());
}
- return null;
+ return messageToPublish;
}
-
+
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSON.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSON.java
index 6667dfc56..6924deb7d 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSON.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSON.java
@@ -1,93 +1,56 @@
package us.dot.its.jpo.ode.services.asn1.message;
-import java.util.Set;
-
-import org.json.JSONArray;
+import org.apache.tomcat.util.buf.HexUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.coder.StringPublisher;
import us.dot.its.jpo.ode.model.Asn1Encoding;
import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
-import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
-import us.dot.its.jpo.ode.model.OdeSrmMetadata.SrmSource;
import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
-import us.dot.its.jpo.ode.model.OdeMsgPayload;
import us.dot.its.jpo.ode.model.OdeSrmMetadata;
public class Asn1DecodeSRMJSON extends AbstractAsn1DecodeMessageJSON {
- private static final String SRMContentType = "SrmMessageContent";
-
private Logger logger = LoggerFactory.getLogger(this.getClass());
-
+ private ObjectMapper objectMapper = new ObjectMapper();
public Asn1DecodeSRMJSON(OdeProperties odeProps) {
- super(new StringPublisher(odeProps));
+ super(new StringPublisher(odeProps), odeProps.getSrmStartFlag());
}
@Override
- protected Object process(String consumedData) {
+ protected OdeAsn1Data process(String consumedData) {
+ OdeAsn1Data messageToPublish = null;
+ try {
+ JSONObject rawSrmJsonObject = new JSONObject(consumedData);
- OdeData odeData = null;
- OdeMsgPayload payload = null;
+ String jsonStringMetadata = rawSrmJsonObject.get("metadata").toString();
+ OdeSrmMetadata metadata = objectMapper.readValue(jsonStringMetadata, OdeSrmMetadata.class);
- try {
- logger.info("Processing SRM data");
- logger.debug("SRM data: {}", consumedData);
- JSONObject rawJSONObject = new JSONObject(consumedData);
- Set> keys = rawJSONObject.keySet();
- for (Object key : keys)
- {
- if (key != null && key.toString().equals(SRMContentType)) {
- /**process consumed data
- * {"SrmMessageContent":[{"metadata":{"utctimestamp":
- * "2020-11-30T23:45:24.913657Z", "originRsu":"172.250.250.77"},
- * "payload":"001d2130000010090bd341080d00855c6c0c6899853000a534f7c24cb29897694759b7c0"}]}
- */
- OdeSrmMetadata metadata = null;
-
- JSONArray rawSRMJsonContentArray = rawJSONObject.getJSONArray(SRMContentType);
- for(int i=0;i keys = rawJSONObject.keySet();
- for (Object key : keys)
- {
- if (key != null && key.toString().equals(SSMContentType)) {
- /**process consumed data
- * {"SsmMessageContent":[{"metadata":{"utctimestamp":
- * "2020-11-30T23:45:24.913657Z", "originRsu":"172.250.250.77"},
- * "payload":"001e120000000005e9c04071a26614c06000040ba0"}]}
- */
- OdeSsmMetadata metadata = null;
-
- JSONArray rawSSMJsonContentArray = rawJSONObject.getJSONArray(SSMContentType);
- for(int i=0;i keys = rawJSONObject.keySet();
- for (Object key : keys)
- {
- if (key != null && key.toString().equals(TIMContentType)) {
- /**process consumed data
- * {"TimMessageContent":[{"metadata":{"utctimestamp":"2020-11-30T23:45:24.913657Z", "originRsu":"172.250.250.77"},"payload":"001f5520100000000000564fb69082709b898aac59717eadfffe4fca1bf0a9d828407e137131558b2e2fd581f46ffff00118b2e3b3ee6e2702c18b2e34f4e6e269ec18b2e285426e2580598b2e23b6e6e254c80420005c48"}]}
- */
- OdeTimMetadata metadata = null;
-
- JSONArray rawTIMJsonContentArray = rawJSONObject.getJSONArray(TIMContentType);
- for(int i=0;i {
-
- @Override
- public int compare(J2735Bsm x, J2735Bsm y) {
- // TODO - determine message arrival time
- // for now we are using the BSM's time offset property
-
- int xt = x.getCoreData().getSecMark();
- int yt = y.getCoreData().getSecMark();
-
- return Integer.compare(xt, yt);
- }
-
-}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/bsm/BsmReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/bsm/BsmReceiver.java
index a61cfff3a..6088c0c28 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/bsm/BsmReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/bsm/BsmReceiver.java
@@ -4,27 +4,31 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import us.dot.its.jpo.ode.coder.StringPublisher;
import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeBsmMetadata;
+import us.dot.its.jpo.ode.model.OdeBsmMetadata.BsmSource;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeLogMsgMetadataLocation;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.ReceivedMessageDetails;
+import us.dot.its.jpo.ode.model.RxSource;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class BsmReceiver extends AbstractUdpReceiverPublisher {
private static Logger logger = LoggerFactory.getLogger(BsmReceiver.class);
- private static final String BSM_START_FLAG = "0014"; // these bytes indicate
- // start of BSM payload
- private static final int HEADER_MINIMUM_SIZE = 20; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher bsmPublisher;
@Autowired
@@ -43,7 +47,7 @@ public BsmReceiver(OdeProperties odeProps, int port, int bufferSize) {
@Override
public void run() {
- logger.debug("UDP Receiver Service started.");
+ logger.debug("BSM UDP Receiver Service started.");
byte[] buffer = new byte[bufferSize];
@@ -51,7 +55,7 @@ public void run() {
do {
try {
- logger.debug("Waiting for UDP packets...");
+ logger.debug("Waiting for UDP BSM packets...");
socket.receive(packet);
if (packet.getLength() > 0) {
senderIp = packet.getAddress().getHostAddress();
@@ -59,65 +63,51 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
-
- // Add header data for the decoding process
- ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
- String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
-
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
-
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getBsmStartFlag()) == -1)
+ continue;
+ logger.debug("Full BSM packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getBsmStartFlag());
+ logger.debug("Stripped BSM packet: {}", payloadHexString);
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("BsmMessageContent", messageList);
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload bsmPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdeBsmMetadata bsmMetadata = new OdeBsmMetadata(bsmPayload);
- logger.debug("BSM JSON Object: {}", jsonObject.toString());
+ // Set BSM Metadata values that can be assumed from the UDP endpoint
+ ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
+ String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ bsmMetadata.setOdeReceivedAt(timestamp);
+
+ ReceivedMessageDetails receivedMessageDetails = new ReceivedMessageDetails();
+ OdeLogMsgMetadataLocation locationData = new OdeLogMsgMetadataLocation(
+ "unavailable",
+ "unavailable",
+ "unavailable",
+ "unavailable",
+ "unavailable");
+ receivedMessageDetails.setRxSource(RxSource.RSU);
+ receivedMessageDetails.setLocationData(locationData);
+ bsmMetadata.setReceivedMessageDetails(receivedMessageDetails);
+
+ bsmMetadata.setOriginIp(senderIp);
+ bsmMetadata.setBsmSource(BsmSource.EV);
+ bsmMetadata.setRecordType(RecordType.bsmTx);
+ bsmMetadata.setRecordGeneratedBy(GeneratedBy.OBU);
+ bsmMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- this.bsmPublisher.publish(jsonObject.toString(), this.bsmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedBSMJson());
+ bsmPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(bsmMetadata, bsmPayload), false),
+ bsmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedBSMJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "0014",
- * message is raw BSM. Otherwise, headers are >= 20 bytes, so look past that
- * for start of payload BSM.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
-
- int startIndex = hexPacket.indexOf(BSM_START_FLAG);
- if (startIndex == 0) {
- logger.debug("Message is raw BSM with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no BSM start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the BSM
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(BSM_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/map/MapReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/map/MapReceiver.java
index d72089eb8..c39efc181 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/map/MapReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/map/MapReceiver.java
@@ -4,8 +4,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
@@ -13,17 +11,20 @@
import org.springframework.beans.factory.annotation.Autowired;
import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeMapMetadata.MapSource;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.OdeMapMetadata;
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class MapReceiver extends AbstractUdpReceiverPublisher {
private static Logger logger = LoggerFactory.getLogger(MapReceiver.class);
- private static final String MAP_START_FLAG = "0012"; // these bytes indicate
- // start of MAP payload
- private static final int HEADER_MINIMUM_SIZE = 20; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher mapPublisher;
@Autowired
@@ -42,7 +43,7 @@ public MapReceiver(OdeProperties odeProps, int port, int bufferSize) {
@Override
public void run() {
- logger.debug("MAP UDP Receiver Service started.");
+ logger.debug("Map UDP Receiver Service started.");
byte[] buffer = new byte[bufferSize];
@@ -50,7 +51,7 @@ public void run() {
do {
try {
- logger.debug("Waiting for UDP MAP packets...");
+ logger.debug("Waiting for UDP Map packets...");
socket.receive(packet);
if (packet.getLength() > 0) {
senderIp = packet.getAddress().getHostAddress();
@@ -58,67 +59,40 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
+
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getMapStartFlag()) == -1)
+ continue;
+ logger.debug("Full Map packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getMapStartFlag());
+ logger.debug("Stripped Map packet: {}", payloadHexString);
+
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload mapPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdeMapMetadata mapMetadata = new OdeMapMetadata(mapPayload);
// Add header data for the decoding process
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ mapMetadata.setOdeReceivedAt(timestamp);
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
- metadataObject.put("source", "RSU");
-
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
-
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
-
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("MapMessageContent", messageList);
-
- logger.debug("MAP JSON Object: {}", jsonObject.toString());
+ mapMetadata.setOriginIp(senderIp);
+ mapMetadata.setMapSource(MapSource.RSU);
+ mapMetadata.setRecordType(RecordType.mapTx);
+ mapMetadata.setRecordGeneratedBy(GeneratedBy.RSU);
+ mapMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- this.mapPublisher.publish(jsonObject.toString(),
- this.mapPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedMAPJson());
+ mapPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(mapMetadata, mapPayload), false),
+ mapPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedMAPJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "0013", message
- * is raw SPAT. Otherwise, headers are >= 20 bytes, so look past that for start
- * of payload SPAT.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
-
- int startIndex = hexPacket.indexOf(MAP_START_FLAG);
- if (startIndex == 0) {
- logger.debug("Message is raw MAP with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no MAP start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the MAP
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(MAP_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/psm/PsmReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/psm/PsmReceiver.java
index 4cea6ae6a..dfdcf557d 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/psm/PsmReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/psm/PsmReceiver.java
@@ -4,8 +4,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
@@ -13,17 +11,20 @@
import org.springframework.beans.factory.annotation.Autowired;
import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.OdePsmMetadata.PsmSource;
+import us.dot.its.jpo.ode.model.OdePsmMetadata;
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class PsmReceiver extends AbstractUdpReceiverPublisher {
private static Logger logger = LoggerFactory.getLogger(PsmReceiver.class);
- private static final String PSM_START_FLAG = "0020"; // these bytes indicate
- // start of PSM payload
- private static final int HEADER_MINIMUM_SIZE = 6; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher psmPublisher;
@Autowired
@@ -58,69 +59,40 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
+
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getPsmStartFlag()) == -1)
+ continue;
+ logger.debug("Full PSM packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getPsmStartFlag());
+ logger.debug("Stripped PSM packet: {}", payloadHexString);
+
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload psmPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdePsmMetadata psmMetadata = new OdePsmMetadata(psmPayload);
// Add header data for the decoding process
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ psmMetadata.setOdeReceivedAt(timestamp);
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
- metadataObject.put("source", "RSU");
-
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
-
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
-
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("PsmMessageContent", messageList);
-
- logger.debug("PSM JSON Object: {}", jsonObject.toString());
+ psmMetadata.setOriginIp(senderIp);
+ psmMetadata.setPsmSource(PsmSource.RSU);
+ psmMetadata.setRecordType(RecordType.psmTx);
+ psmMetadata.setRecordGeneratedBy(GeneratedBy.UNKNOWN);
+ psmMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- this.psmPublisher.publish(jsonObject.toString(),
- this.psmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedPSMJson());
+ psmPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(psmMetadata, psmPayload), false),
+ psmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedPSMJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "0013", message
- * is raw SPAT. Otherwise, headers are >= 20 bytes, so look past that for start
- * of payload SPAT.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
- logger.debug("PSM packet: {}", hexPacket);
-
- int startIndex = hexPacket.indexOf(PSM_START_FLAG);
- if (startIndex == 0) {
- logger.debug("Message is raw PSM with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no PSM start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the PSM
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(PSM_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
- logger.debug("PSM packet substring: {}", hexPacket);
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/spat/SpatReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/spat/SpatReceiver.java
index c57c28188..b03a7d50b 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/spat/SpatReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/spat/SpatReceiver.java
@@ -4,8 +4,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
@@ -13,18 +11,20 @@
import org.springframework.beans.factory.annotation.Autowired;
import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.OdeSpatMetadata;
+import us.dot.its.jpo.ode.model.OdeSpatMetadata.SpatSource;
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class SpatReceiver extends AbstractUdpReceiverPublisher {
-
private static Logger logger = LoggerFactory.getLogger(SpatReceiver.class);
- private static final String SPAT_START_FLAG = "0013"; // these bytes indicate
- // start of SPAT payload
- private static final int HEADER_MINIMUM_SIZE = 20; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher spatPublisher;
@Autowired
@@ -43,7 +43,7 @@ public SpatReceiver(OdeProperties odeProps, int port, int bufferSize) {
@Override
public void run() {
- logger.debug("SPAT UDP Receiver Service started.");
+ logger.debug("SPaT UDP Receiver Service started.");
byte[] buffer = new byte[bufferSize];
@@ -51,7 +51,7 @@ public void run() {
do {
try {
- logger.debug("Waiting for UDP SPAT packets...");
+ logger.debug("Waiting for UDP SPaT packets...");
socket.receive(packet);
if (packet.getLength() > 0) {
senderIp = packet.getAddress().getHostAddress();
@@ -59,65 +59,40 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
-
- // Add header data for the decoding process
- ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
- String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
-
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getSpatStartFlag()) == -1)
+ continue;
+ logger.debug("Full SPaT packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getSpatStartFlag());
+ logger.debug("Stripped SPaT packet: {}", payloadHexString);
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload spatPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdeSpatMetadata spatMetadata = new OdeSpatMetadata(spatPayload);
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("SpatMessageContent", messageList);
+ // Add header data for the decoding process
+ ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
+ String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ spatMetadata.setOdeReceivedAt(timestamp);
- logger.debug("SPAT JSON Object: {}", jsonObject.toString());
+ spatMetadata.setOriginIp(senderIp);
+ spatMetadata.setSpatSource(SpatSource.RSU);
+ spatMetadata.setRecordType(RecordType.spatTx);
+ spatMetadata.setRecordGeneratedBy(GeneratedBy.RSU);
+ spatMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- this.spatPublisher.publish(jsonObject.toString(), this.spatPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedSPATJson());
+ spatPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(spatMetadata, spatPayload), false),
+ spatPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedSPATJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "0013",
- * message is raw SPAT. Otherwise, headers are >= 20 bytes, so look past that
- * for start of payload SPAT.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
-
- int startIndex = hexPacket.indexOf(SPAT_START_FLAG);
- if (startIndex == 0) {
- logger.debug("Message is raw SPAT with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no SPAT start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the SPAT
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(SPAT_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/srm/SrmReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/srm/SrmReceiver.java
index cd57c7172..22917447e 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/srm/SrmReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/srm/SrmReceiver.java
@@ -4,8 +4,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
@@ -13,18 +11,20 @@
import org.springframework.beans.factory.annotation.Autowired;
import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.OdeSrmMetadata;
+import us.dot.its.jpo.ode.model.OdeSrmMetadata.SrmSource;
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class SrmReceiver extends AbstractUdpReceiverPublisher {
-
private static Logger logger = LoggerFactory.getLogger(SrmReceiver.class);
- private static final String SRM_START_FLAG = "001d"; // these bytes indicate
- // start of SRM payload
- private static final int HEADER_MINIMUM_SIZE = 20; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher srmPublisher;
@Autowired
@@ -59,66 +59,40 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
+
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getSrmStartFlag()) == -1)
+ continue;
+ logger.debug("Full SRM packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getSrmStartFlag());
+ logger.debug("Stripped SRM packet: {}", payloadHexString);
+
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload srmPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdeSrmMetadata srmMetadata = new OdeSrmMetadata(srmPayload);
// Add header data for the decoding process
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ srmMetadata.setOdeReceivedAt(timestamp);
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
- metadataObject.put("source", "RSU");
-
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
-
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
-
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("SrmMessageContent", messageList);
-
- logger.debug("SRM JSON Object: {}", jsonObject.toString());
+ srmMetadata.setOriginIp(senderIp);
+ srmMetadata.setSrmSource(SrmSource.RSU);
+ srmMetadata.setRecordType(RecordType.srmTx);
+ srmMetadata.setRecordGeneratedBy(GeneratedBy.OBU);
+ srmMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- this.srmPublisher.publish(jsonObject.toString(), this.srmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedSRMJson());
+ srmPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(srmMetadata, srmPayload), false),
+ srmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedSRMJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "001d",
- * message is raw SRM. Otherwise, headers are >= 20 bytes, so look past that
- * for start of payload SRM.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
-
- int startIndex = hexPacket.indexOf(SRM_START_FLAG);
- if (startIndex == 0) {
- logger.debug("Message is raw SRM with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no SRM start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the SRM
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(SRM_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/ssm/SsmReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/ssm/SsmReceiver.java
index 05169b12a..c5a7774a8 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/ssm/SsmReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/ssm/SsmReceiver.java
@@ -4,8 +4,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
@@ -13,18 +11,20 @@
import org.springframework.beans.factory.annotation.Autowired;
import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.OdeSsmMetadata;
+import us.dot.its.jpo.ode.model.OdeSsmMetadata.SsmSource;
import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class SsmReceiver extends AbstractUdpReceiverPublisher {
-
private static Logger logger = LoggerFactory.getLogger(SsmReceiver.class);
- private static final String SSM_START_FLAG = "001e"; // these bytes indicate
- // start of SSM payload
- private static final int HEADER_MINIMUM_SIZE = 20; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher ssmPublisher;
@Autowired
@@ -59,66 +59,40 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
-
- // Add header data for the decoding process
- ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
- String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
-
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
- metadataObject.put("source", "RSU");
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getSsmStartFlag()) == -1)
+ continue;
+ logger.debug("Full SSM packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getSsmStartFlag());
+ logger.debug("Stripped SSM packet: {}", payloadHexString);
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload ssmPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdeSsmMetadata ssmMetadata = new OdeSsmMetadata(ssmPayload);
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("SsmMessageContent", messageList);
+ // Add header data for the decoding process
+ ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
+ String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ ssmMetadata.setOdeReceivedAt(timestamp);
- logger.debug("SSM JSON Object: {}", jsonObject.toString());
+ ssmMetadata.setOriginIp(senderIp);
+ ssmMetadata.setSsmSource(SsmSource.RSU);
+ ssmMetadata.setRecordType(RecordType.ssmTx);
+ ssmMetadata.setRecordGeneratedBy(GeneratedBy.RSU);
+ ssmMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- this.ssmPublisher.publish(jsonObject.toString(), this.ssmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedSSMJson());
+ ssmPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(ssmMetadata, ssmPayload), false),
+ ssmPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedSSMJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "001e",
- * message is raw SSM. Otherwise, headers are >= 20 bytes, so look past that
- * for start of payload SSM.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
-
- int startIndex = hexPacket.indexOf(SSM_START_FLAG);
- if (startIndex == 0) {
- logger.debug("Message is raw SSM with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no SSM start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the SSM
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(SSM_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/tim/TimReceiver.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/tim/TimReceiver.java
index 7bc086bca..a6b190336 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/tim/TimReceiver.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/udp/tim/TimReceiver.java
@@ -1,14 +1,9 @@
package us.dot.its.jpo.ode.udp.tim;
-import java.io.IOException;
import java.net.DatagramPacket;
-import java.util.concurrent.atomic.AtomicInteger;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
@@ -16,21 +11,19 @@
import org.springframework.beans.factory.annotation.Autowired;
import us.dot.its.jpo.ode.coder.StringPublisher;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
+import us.dot.its.jpo.ode.model.OdeLogMetadata.SecurityResultCode;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy;
+import us.dot.its.jpo.ode.model.OdeTimMetadata;
import us.dot.its.jpo.ode.OdeProperties;
-import us.dot.its.jpo.ode.coder.MessagePublisher;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.SerialId;
import us.dot.its.jpo.ode.udp.AbstractUdpReceiverPublisher;
+import us.dot.its.jpo.ode.util.JsonUtils;
public class TimReceiver extends AbstractUdpReceiverPublisher {
-
private static Logger logger = LoggerFactory.getLogger(TimReceiver.class);
- private static final String TIM_START_FLAG = "001f"; // these bytes indicate
- // start of TIM payload
- private static final int HEADER_MINIMUM_SIZE = 20; // WSMP headers are at
- // least 20 bytes long
-
private StringPublisher timPublisher;
@Autowired
@@ -48,7 +41,6 @@ public TimReceiver(OdeProperties odeProps, int port, int bufferSize) {
@Override
public void run() {
-
logger.debug("TIM UDP Receiver Service started.");
byte[] buffer = new byte[bufferSize];
@@ -65,69 +57,39 @@ public void run() {
logger.debug("Packet received from {}:{}", senderIp, senderPort);
// extract the actualPacket from the buffer
- byte[] payload = removeHeader(packet.getData());
+ byte[] payload = packet.getData();
if (payload == null)
continue;
- String payloadHexString = HexUtils.toHexString(payload);
- logger.debug("Packet: {}", payloadHexString);
-
- logger.debug("Creating Decoded TIM JSON Object...");
+
+ // convert bytes to hex string and verify identity
+ String payloadHexString = HexUtils.toHexString(payload).toLowerCase();
+ if (payloadHexString.indexOf(odeProperties.getTimStartFlag()) == -1)
+ continue;
+ logger.debug("Full TIM packet: {}", payloadHexString);
+ payloadHexString = super.stripDot3Header(payloadHexString, odeProperties.getTimStartFlag());
+ logger.debug("Stripped TIM packet: {}", payloadHexString);
+
+ // Create OdeMsgPayload and OdeLogMetadata objects and populate them
+ OdeAsn1Payload timPayload = new OdeAsn1Payload(HexUtils.fromHexString(payloadHexString));
+ OdeTimMetadata timMetadata = new OdeTimMetadata(timPayload);
// Add header data for the decoding process
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
String timestamp = utc.format(DateTimeFormatter.ISO_INSTANT);
+ timMetadata.setOdeReceivedAt(timestamp);
- JSONObject metadataObject = new JSONObject();
- metadataObject.put("utctimestamp", timestamp);
- metadataObject.put("originRsu", senderIp);
-
- JSONObject messageObject = new JSONObject();
- messageObject.put("metadata", metadataObject);
- messageObject.put("payload", payloadHexString);
-
- JSONArray messageList = new JSONArray();
- messageList.put(messageObject);
-
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("TimMessageContent", messageList);
-
- logger.debug("TIM JSON Object: {}", jsonObject.toString());
+ timMetadata.setOriginIp(senderIp);
+ timMetadata.setRecordType(RecordType.timMsg);
+ timMetadata.setRecordGeneratedBy(GeneratedBy.RSU);
+ timMetadata.setSecurityResultCode(SecurityResultCode.success);
// Submit JSON to the OdeRawEncodedMessageJson Kafka Topic
- logger.debug("Publishing JSON TIM...");
-
- this.timPublisher.publish(jsonObject.toString(), this.timPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedTIMJson());
+ timPublisher.publish(JsonUtils.toJson(new OdeAsn1Data(timMetadata, timPayload), false),
+ timPublisher.getOdeProperties().getKafkaTopicOdeRawEncodedTIMJson());
}
} catch (Exception e) {
logger.error("Error receiving packet", e);
}
} while (!isStopped());
}
-
- /**
- * Attempts to strip WSMP header bytes. If message starts with "001F",
- * message is raw TIM. Otherwise, headers are >= 20 bytes, so look past that
- * for start of payload TIM.
- *
- * @param packet
- */
- public byte[] removeHeader(byte[] packet) {
- String hexPacket = HexUtils.toHexString(packet);
-
- int startIndex = hexPacket.indexOf(TIM_START_FLAG);
- if (startIndex == 0) {
- logger.info("Message is raw TIM with no headers.");
- } else if (startIndex == -1) {
- logger.error("Message contains no TIM start flag.");
- return null;
- } else {
- // We likely found a message with a header, look past the first 20
- // bytes for the start of the TIM
- int trueStartIndex = HEADER_MINIMUM_SIZE
- + hexPacket.substring(HEADER_MINIMUM_SIZE, hexPacket.length()).indexOf(TIM_START_FLAG);
- hexPacket = hexPacket.substring(trueStartIndex, hexPacket.length());
- }
-
- return HexUtils.fromHexString(hexPacket);
- }
}
diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/upload/FileUploadController.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/upload/FileUploadController.java
index 1f1bf852f..7ad63c352 100644
--- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/upload/FileUploadController.java
+++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/upload/FileUploadController.java
@@ -51,7 +51,7 @@ public class FileUploadController {
@Autowired
public FileUploadController(
- StorageService storageService, OdeProperties odeProperties,
+ StorageService storageService, OdeProperties odeProperties,
SimpMessagingTemplate template) {
super();
this.storageService = storageService;
@@ -59,7 +59,7 @@ public FileUploadController(
ExecutorService threadPool = Executors.newCachedThreadPool();
Path logPath = Paths.get(odeProperties.getUploadLocationRoot(),
- odeProperties.getUploadLocationObuLog());
+ odeProperties.getUploadLocationObuLog());
logger.debug("UPLOADER - BSM log file upload directory: {}", logPath);
Path failurePath = Paths.get(odeProperties.getUploadLocationRoot(), "failed");
logger.debug("UPLOADER - Failure directory: {}", failurePath);
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisherTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisherTest.java
index 8f71c68c8..33fc23641 100644
--- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisherTest.java
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/coder/stream/LogFileToAsn1CodecPublisherTest.java
@@ -24,6 +24,7 @@
import java.io.ByteArrayInputStream;
import java.util.List;
+import org.apache.tomcat.util.buf.HexUtils;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -37,10 +38,12 @@
import us.dot.its.jpo.ode.importer.ImporterDirectoryWatcher.ImporterFileType;
import us.dot.its.jpo.ode.importer.parser.FileParser.ParserStatus;
import us.dot.its.jpo.ode.importer.parser.LogFileParser;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
import us.dot.its.jpo.ode.model.OdeData;
import us.dot.its.jpo.ode.model.OdeLogMetadata.RecordType;
import us.dot.its.jpo.ode.model.OdeMsgMetadata;
import us.dot.its.jpo.ode.util.DateTimeUtils;
+import us.dot.its.jpo.ode.util.JsonUtils.JsonUtilsException;
public class LogFileToAsn1CodecPublisherTest {
@@ -179,11 +182,11 @@ public void testPublishBsmTxLogFile() throws Exception {
List dataList = testLogFileToAsn1CodecPublisher.publish(bis, filename, ImporterFileType.LOG_FILE);
for (OdeData data : dataList) {
- assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getOdeReceivedAt()),
+ assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getRecordGeneratedAt()),
DateTimeUtils.nowZDT()) > 0);
data.getMetadata().setOdeReceivedAt("2019-03-05T20:31:17.579Z");
data.getMetadata().getSerialId().setStreamId("c7bbb42e-1e39-442d-98ac-62740ca50f92");
- var expected = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"bsmTx.gz\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"NA\"},\"encodings\":[{\"elementName\":\"root\",\"elementType\":\"Ieee1609Dot2Data\",\"encodingRule\":\"COER\"},{\"elementName\":\"unsecuredData\",\"elementType\":\"MessageFrame\",\"encodingRule\":\"UPER\"}],\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"038100140380\"}}}";
+ var expected = "{\"metadata\":{\"bsmSource\":\"EV\",\"logFileName\":\"bsmTx.gz\",\"recordType\":\"bsmTx\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"NA\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"00140380\"}}}";
assertEquals(expected, data.toJson());
}
}
@@ -212,7 +215,7 @@ public void testPublishDistressNotificationLogFile() throws Exception {
List dataList = testLogFileToAsn1CodecPublisher.publish(bis, filename, ImporterFileType.LOG_FILE);
for (OdeData data : dataList) {
- assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getOdeReceivedAt()),
+ assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getRecordGeneratedAt()),
DateTimeUtils.nowZDT()) > 0);
data.getMetadata().setOdeReceivedAt("2019-03-05T20:31:17.579Z");
data.getMetadata().getSerialId().setStreamId("c7bbb42e-1e39-442d-98ac-62740ca50f92");
@@ -244,7 +247,7 @@ public void testPublishDriverAlertLogFile() throws Exception {
List dataList = testLogFileToAsn1CodecPublisher.publish(bis, filename, ImporterFileType.LOG_FILE);
for (OdeData data : dataList) {
- assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getOdeReceivedAt()),
+ assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getRecordGeneratedAt()),
DateTimeUtils.nowZDT()) > 0);
data.getMetadata().setOdeReceivedAt("2019-03-05T20:31:17.579Z");
data.getMetadata().getSerialId().setStreamId("c7bbb42e-1e39-442d-98ac-62740ca50f92");
@@ -263,7 +266,7 @@ public void testPublishRxMsgTIMLogFile() throws Exception {
(byte) 0x67, (byte) 0x06, (byte) 0x00, (byte) 0x00, // 2.3 elevation
(byte) 0x04, (byte) 0x00, // 2.3 speed
(byte) 0x09, (byte) 0x27, // 2.4 heading
- (byte) 0xa9, (byte) 0x2c, (byte) 0xe2, (byte) 0x5a, // 3. utcTimeInSec
+ (byte) 0xa9, (byte) 0x2c, (byte) 0xe2, (byte) 0x5a, // 2. utcTimeInSec
(byte) 0x8f, (byte) 0x01, // 4. mSec
(byte) 0x00, // 5. securityResultCode
(byte) 0x06, (byte) 0x00, // 6.0 payloadLength
@@ -278,11 +281,11 @@ public void testPublishRxMsgTIMLogFile() throws Exception {
List dataList = testLogFileToAsn1CodecPublisher.publish(bis, filename, ImporterFileType.LOG_FILE);
for (OdeData data : dataList) {
- assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getOdeReceivedAt()),
+ assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getRecordGeneratedAt()),
DateTimeUtils.nowZDT()) > 0);
data.getMetadata().setOdeReceivedAt("2019-03-05T20:31:17.579Z");
data.getMetadata().getSerialId().setStreamId("c7bbb42e-1e39-442d-98ac-62740ca50f92");
- var expected = "{\"metadata\":{\"logFileName\":\"rxMsg.gz\",\"recordType\":\"rxMsg\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"SAT\"},\"encodings\":[{\"elementName\":\"root\",\"elementType\":\"Ieee1609Dot2Data\",\"encodingRule\":\"COER\"},{\"elementName\":\"unsecuredData\",\"elementType\":\"MessageFrame\",\"encodingRule\":\"UPER\"}],\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"TMC_VIA_SAT\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"038100140380\"}}}";
+ var expected = "{\"metadata\":{\"logFileName\":\"rxMsg.gz\",\"recordType\":\"rxMsg\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"SAT\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"TMC_VIA_SAT\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"00140380\"}}}";
assertEquals(expected, data.toJson());
}
}
@@ -312,11 +315,11 @@ public void testPublishRxMsgBSMLogFile() throws Exception {
List dataList = testLogFileToAsn1CodecPublisher.publish(bis, filename, ImporterFileType.LOG_FILE);
for (OdeData data : dataList) {
- assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getOdeReceivedAt()),
+ assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getRecordGeneratedAt()),
DateTimeUtils.nowZDT()) > 0);
data.getMetadata().setOdeReceivedAt("2019-03-05T20:31:17.579Z");
data.getMetadata().getSerialId().setStreamId("c7bbb42e-1e39-442d-98ac-62740ca50f92");
- var expected = "{\"metadata\":{\"bsmSource\":\"RV\",\"logFileName\":\"rxMsg.gz\",\"recordType\":\"rxMsg\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"RV\"},\"encodings\":[{\"elementName\":\"root\",\"elementType\":\"Ieee1609Dot2Data\",\"encodingRule\":\"COER\"},{\"elementName\":\"unsecuredData\",\"elementType\":\"MessageFrame\",\"encodingRule\":\"UPER\"}],\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"118100140380\"}}}";
+ var expected = "{\"metadata\":{\"bsmSource\":\"RV\",\"logFileName\":\"rxMsg.gz\",\"recordType\":\"rxMsg\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"RV\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"00140380\"}}}";
assertEquals(expected, data.toJson());
}
}
@@ -367,13 +370,23 @@ public void testPublishRxMsgBSMLogFileNewLine() throws Exception {
List dataList = testLogFileToAsn1CodecPublisher.publish(bis, filename, ImporterFileType.LOG_FILE);
for (OdeData data : dataList) {
- assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getOdeReceivedAt()),
+ assertTrue(DateTimeUtils.difference(DateTimeUtils.isoDateTime(data.getMetadata().getRecordGeneratedAt()),
DateTimeUtils.nowZDT()) > 0);
data.getMetadata().setOdeReceivedAt("2019-03-05T20:31:17.579Z");
data.getMetadata().getSerialId().setStreamId("c7bbb42e-1e39-442d-98ac-62740ca50f92");
- var expected = "{\"metadata\":{\"bsmSource\":\"RV\",\"logFileName\":\"rxMsg.gz\",\"recordType\":\"rxMsg\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"RV\"},\"encodings\":[{\"elementName\":\"root\",\"elementType\":\"Ieee1609Dot2Data\",\"encodingRule\":\"COER\"},{\"elementName\":\"unsecuredData\",\"elementType\":\"MessageFrame\",\"encodingRule\":\"UPER\"}],\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"118100140380\"}}}";
+ var expected = "{\"metadata\":{\"bsmSource\":\"RV\",\"logFileName\":\"rxMsg.gz\",\"recordType\":\"rxMsg\",\"securityResultCode\":\"success\",\"receivedMessageDetails\":{\"locationData\":{\"latitude\":\"42.4506735\",\"longitude\":\"-83.2790108\",\"elevation\":\"163.9\",\"speed\":\"0.08\",\"heading\":\"124.9125\"},\"rxSource\":\"RV\"},\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c7bbb42e-1e39-442d-98ac-62740ca50f92\",\"bundleSize\":1,\"bundleId\":1,\"recordId\":0,\"serialNumber\":1},\"odeReceivedAt\":\"2019-03-05T20:31:17.579Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedAt\":\"2018-04-26T19:46:49.399Z\",\"recordGeneratedBy\":\"OBU\",\"sanitized\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"00140380\"}}}";
assertEquals(expected, data.toJson());
}
}
+ @Test
+ public void testDetermineMessageType() throws JsonUtilsException {
+ String mapHexString = "0012839338023000205E96094D40DF4C2CA626C8516E02DC3C2010640000000289E01C009F603F42E88039900000000A41107B027D80FD0A4200C6400000002973021C09F603DE0C16029200000080002A8A008D027D98FEE805404FB0E1085F60588200028096021200000080002AA0007D027D98FE9802E04FB1200C214456228000A02B1240005022C03240000020000D56B40BC04FB35FF655E2C09F623FB81C835FEC0DB240A0A2BFF4AEBF82C660000804B0089000000800025670034013ECD7FB9578E027D9AFF883C4E050515FFA567A41635000040258024800000400012B8F81F409F663FAC094013ECD7FC83DDB02829AFFA480BC04FB02C6E0000804B09C5000000200035EA98A9604F60DA6C7C113D505C35FFE941D409F65C05034C050500C9880004409BC800000006D2BD3CEC813C40CDE062C1FD400000200008791EA3DB3CF380A009F666F05005813D80FFE0A0588C00040092106A00000000BC75CAC009F66DB54C04A813D80A100801241ED40000000078EBAE3B6DA7A008809E2050904008811F100000000BC72389009F60ECA8002049C400000002F1B2CA3027D93A71FA813EC204BC400000002F1B2B34027B0397608880CD10000000039B8E1A51036820505080D51000000003A7461ED1036760505080DD1000000003B2F62311006260505160BCA00000080002B785E2A80A0A6C028DE728145037F1F9E456488000202B2540001022C1894000001000057058C5B81414D806DBCD4028A18F4DF23A050502C8D0000404B05A5000000800035B6471BC05053602431F380A2864087BDB0141458064AB0D6C00053FC013EC0B0680006012C15940000020000D6C06C6581414D807FB972028A1901D78DC050536020EC1800A0A6C039D639813D80B0780006012C1494000002000096AB8C6581414D8062BE32028A1B01417E04050A360172D77009E2058440003009409C200000040006B3486A480A0A1CAB7134C8117DCC02879B018FAE2C050F3601CED54809E21012720000000067FBAD0007E7E84045C80000000100661580958004041C8000000019F3658401CDFA2C0D64000002000144016C02C36DDFFF0282984ACC1EE05052C36F0AC02828669D82DA8F821480A0A10F140002C8E0001004B03190000008000519FD190C43B2E0066108B08401428C342A0CE02828258A0604A6BE959AEE0E6050502C920001004B02D90000008000459FA164404FB30A8580A00A14619C306701414C32CE10E02829659081F814141029030164B0000802E8000802000035FDB1D84C09EC6C003BA14814140B0540003012C187400040080011B13F6EDB804F115FA6DFC10AFC94FC6A57EE07DCE2BFA7BED3B5FFCD72E80A1E018C900008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ OdeAsn1Payload mapPayload = new OdeAsn1Payload(HexUtils.fromHexString(mapHexString));
+ assertEquals(testLogFileToAsn1CodecPublisher.determineMessageType(mapPayload), "MAP");
+
+ String timHexString = "001F79201000000000012AA366D080729B8987D859717EE22001FFFE4FD0011589D828007E537130FB0B2E2FDC440001F46FFFF002B8B2E46E926E27CE6813D862CB90EDC9B89E11CE2CB8E98F9B89BCC4050518B2E365B66E26AE3B8B2E291A66E2591D8141462CB873969B89396C62CB86AFE9B89208E00000131560018300023E43A6A1351800023E4700EFC51881010100030180C620FB90CAAD3B9C5082080E1DDC905E10168E396921000325A0D73B83279C83010180034801090001260001808001838005008001F0408001828005008001304000041020407E800320409780050080012040000320409900018780032040958005000001E0408183E7139D7B70987019B526B8A950052F5C011D3C4B992143E885C71F95DA6071658082346CC03A50D66801F65288C30AB39673D0494536C559047E457AD291C99C20A7FB1244363E993EE3EE98C78742609340541DA01545A0F7339C26A527903576D30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ OdeAsn1Payload timPayload = new OdeAsn1Payload(HexUtils.fromHexString(timHexString));
+ assertEquals(testLogFileToAsn1CodecPublisher.determineMessageType(timPayload), "TIM");
+ }
}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSONTest.java
new file mode 100644
index 000000000..3552ecaca
--- /dev/null
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeBSMJSONTest.java
@@ -0,0 +1,46 @@
+package us.dot.its.jpo.ode.services.asn1.message;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.json.JSONException;
+import org.junit.jupiter.api.Test;
+
+import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeBsmMetadata;
+import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
+
+public class Asn1DecodeBSMJSONTest {
+ private final String json = "{\"metadata\":{\"bsmSource\":\"EV\",\"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.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"be071349-9bb6-4b66-b1c7-8df1f9e0cb74\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T16:46:45.297174600Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"originIp\":\"192.168.0.1\"},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"03810040038081B1001480AD4644A9EA5442BC26E97C7496576E052569B214000070007050FD7D0FA1007FFF8000681250020214C1C0FF64BFFA0FB84F720FF71BFF9500DFFFC0FF564006D001FFFC0FF5BBFE5B031FFFC0FF573FF73075FFFC0FF973FFB708FFFFC0FFEFC00B50B5FFFC0FFF0401150BBFFFC0FFDF4015D0C1FFFC0FFB9C01690C7FFFC0FFC0401550C9FFFC0FFBAC014F0C9FFFC0FFBBC01530CBFFFC0FFBB400B30E7FFFC100383FFCD0E3FFFCFFFEC800400120000243450D45B978805B073A8672E91E9D80824A65C65F85E35B61502149263F000FE804E6B84AF66507D51690DE76F30D1468A68F8986B58E6AECB2C5FC4766C223F0B977E87678DDF714FE123C483622CC7500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
+
+ @Test
+ public void testConstructor() {
+ OdeProperties properties = new OdeProperties();
+ properties.setKafkaBrokers("localhost:9092");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedBSMJson(), "topic.OdeRawEncodedBSMJson");
+ }
+
+ @Test
+ public void testProcess() throws XmlUtilsException, JSONException {
+ OdeProperties properties = new OdeProperties();
+ properties.setKafkaBrokers("localhost:9092");
+ Asn1DecodeBSMJSON testDecodeBsmJson = new Asn1DecodeBSMJSON(properties);
+
+ OdeAsn1Data resultOdeObj = testDecodeBsmJson.process(json);
+
+ // Validate the metadata
+ OdeBsmMetadata jsonMetadataObj = (OdeBsmMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getBsmSource(), OdeBsmMetadata.BsmSource.EV);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"001480AD4644A9EA5442BC26E97C7496576E052569B214000070007050FD7D0FA1007FFF8000681250020214C1C0FF64BFFA0FB84F720FF71BFF9500DFFFC0FF564006D001FFFC0FF5BBFE5B031FFFC0FF573FF73075FFFC0FF973FFB708FFFFC0FFEFC00B50B5FFFC0FFF0401150BBFFFC0FFDF4015D0C1FFFC0FFB9C01690C7FFFC0FFC0401550C9FFFC0FFBAC014F0C9FFFC0FFBBC01530CBFFFC0FFBB400B30E7FFFC100383FFCD0E3FFFCFFFEC800400120000243450D45B978805B073A8672E91E9D80824A65C65F85E35B61502149263F000FE804E6B84AF66507D51690DE76F30D1468A68F8986B58E6AECB2C5FC4766C223F0B977E87678DDF714FE123C483622CC7500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
+ }
+}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSONTest.java
index 2b9311fc3..54dc107df 100644
--- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSONTest.java
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeMAPJSONTest.java
@@ -3,49 +3,44 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.json.JSONException;
-import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
import us.dot.its.jpo.ode.model.OdeMapMetadata;
import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
public class Asn1DecodeMAPJSONTest {
-
- private final String json = "{\"MapMessageContent\": [{ \"metadata\": { \"utctimestamp:\"2020-11-30T23:45:24.913657Z\" }, \"payload\":\"00121E38041180000138044CD8EA0F3D3FC4A600000100000000030AE0C0615C18\"}]}";
- private JSONObject jsonObj = new JSONObject();
+ private final String json = "{\"metadata\":{\"recordType\":\"mapTx\",\"securityResultCode\":\"success\",\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"b91c5c0f-1c42-457e-b7c5-54505c942667\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T19:04:47.440601200Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"RSU\",\"sanitized\":false,\"mapSource\":\"RSU\",\"originIp\":\"192.168.0.1\"},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"03810040038081B10012839338023000205E96094D40DF4C2CA626C8516E02DC3C2010640000000289E01C009F603F42E88039900000000A41107B027D80FD0A4200C6400000002973021C09F603DE0C16029200000080002A8A008D027D98FEE805404FB0E1085F60588200028096021200000080002AA0007D027D98FE9802E04FB1200C214456228000A02B1240005022C03240000020000D56B40BC04FB35FF655E2C09F623FB81C835FEC0DB240A0A2BFF4AEBF82C660000804B0089000000800025670034013ECD7FB9578E027D9AFF883C4E050515FFA567A41635000040258024800000400012B8F81F409F663FAC094013ECD7FC83DDB02829AFFA480BC04FB02C6E0000804B09C5000000200035EA98A9604F60DA6C7C113D505C35FFE941D409F65C05034C050500C9880004409BC800000006D2BD3CEC813C40CDE062C1FD400000200008791EA3DB3CF380A009F666F05005813D80FFE0A0588C00040092106A00000000BC75CAC009F66DB54C04A813D80A100801241ED40000000078EBAE3B6DA7A008809E2050904008811F100000000BC72389009F60ECA8002049C400000002F1B2CA3027D93A71FA813EC204BC400000002F1B2B34027B0397608880CD10000000039B8E1A51036820505080D51000000003A7461ED1036760505080DD1000000003B2F62311006260505160BCA00000080002B785E2A80A0A6C028DE728145037F1F9E456488000202B2540001022C1894000001000057058C5B81414D806DBCD4028A18F4DF23A050502C8D0000404B05A5000000800035B6471BC05053602431F380A2864087BDB0141458064AB0D6C00053FC013EC0B0680006012C15940000020000D6C06C6581414D807FB972028A1901D78DC050536020EC1800A0A6C039D639813D80B0780006012C1494000002000096AB8C6581414D8062BE32028A1B01417E04050A360172D77009E2058440003009409C200000040006B3486A480A0A1CAB7134C8117DCC02879B018FAE2C050F3601CED54809E21012720000000067FBAD0007E7E84045C80000000100661580958004041C8000000019F3658401CDFA2C0D64000002000144016C02C36DDFFF0282984ACC1EE05052C36F0AC02828669D82DA8F821480A0A10F140002C8E0001004B03190000008000519FD190C43B2E0066108B08401428C342A0CE02828258A0604A6BE959AEE0E6050502C920001004B02D90000008000459FA164404FB30A8580A00A14619C306701414C32CE10E02829659081F814141029030164B0000802E8000802000035FDB1D84C09EC6C003BA14814140B0540003012C187400040080011B13F6EDB804F115FA6DFC10AFC94FC6A57EE07DCE2BFA7BED3B5FFCD72E80A1E018C900008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
@Test
public void testConstructor() {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
- assertEquals(properties.getKafkaTopicOdeBsmPojo(), "topic.OdeBsmPojo");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedMAPJson(), "topic.OdeRawEncodedMAPJson");
}
@Test
- public void testProcessMapJson() throws XmlUtilsException, JSONException {
+ public void testProcess() throws XmlUtilsException, JSONException {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
Asn1DecodeMAPJSON testDecodeMapJson = new Asn1DecodeMAPJSON(properties);
- assertEquals(testDecodeMapJson.process(json), null);
-
- // metadata
- OdeData obj = new OdeData();
- OdeMapMetadata jsonMetadataObj = new OdeMapMetadata();
- jsonMetadataObj.setOdeReceivedAt("2020-11-30T23:45:24.913657Z");
- jsonObj.put("metadata", jsonMetadataObj);
-
- // payload
- String encodedPayload = "00121E38041180000138044CD8EA0F3D3FC4A600000100000000030AE0C0615C18";
- obj.setMetadata(jsonMetadataObj);
- obj.setPayload(new OdeAsn1Payload(new OdeHexByteArray(encodedPayload)));
-
- assertEquals("{\"bytes\":\"00121E38041180000138044CD8EA0F3D3FC4A600000100000000030AE0C0615C18\"}",
- obj.getPayload().getData().toJson());
-
+
+ OdeAsn1Data resultOdeObj = testDecodeMapJson.process(json);
+
+ // Validate the metadata
+ OdeMapMetadata jsonMetadataObj = (OdeMapMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getMapSource(), OdeMapMetadata.MapSource.RSU);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"0012839338023000205E96094D40DF4C2CA626C8516E02DC3C2010640000000289E01C009F603F42E88039900000000A41107B027D80FD0A4200C6400000002973021C09F603DE0C16029200000080002A8A008D027D98FEE805404FB0E1085F60588200028096021200000080002AA0007D027D98FE9802E04FB1200C214456228000A02B1240005022C03240000020000D56B40BC04FB35FF655E2C09F623FB81C835FEC0DB240A0A2BFF4AEBF82C660000804B0089000000800025670034013ECD7FB9578E027D9AFF883C4E050515FFA567A41635000040258024800000400012B8F81F409F663FAC094013ECD7FC83DDB02829AFFA480BC04FB02C6E0000804B09C5000000200035EA98A9604F60DA6C7C113D505C35FFE941D409F65C05034C050500C9880004409BC800000006D2BD3CEC813C40CDE062C1FD400000200008791EA3DB3CF380A009F666F05005813D80FFE0A0588C00040092106A00000000BC75CAC009F66DB54C04A813D80A100801241ED40000000078EBAE3B6DA7A008809E2050904008811F100000000BC72389009F60ECA8002049C400000002F1B2CA3027D93A71FA813EC204BC400000002F1B2B34027B0397608880CD10000000039B8E1A51036820505080D51000000003A7461ED1036760505080DD1000000003B2F62311006260505160BCA00000080002B785E2A80A0A6C028DE728145037F1F9E456488000202B2540001022C1894000001000057058C5B81414D806DBCD4028A18F4DF23A050502C8D0000404B05A5000000800035B6471BC05053602431F380A2864087BDB0141458064AB0D6C00053FC013EC0B0680006012C15940000020000D6C06C6581414D807FB972028A1901D78DC050536020EC1800A0A6C039D639813D80B0780006012C1494000002000096AB8C6581414D8062BE32028A1B01417E04050A360172D77009E2058440003009409C200000040006B3486A480A0A1CAB7134C8117DCC02879B018FAE2C050F3601CED54809E21012720000000067FBAD0007E7E84045C80000000100661580958004041C8000000019F3658401CDFA2C0D64000002000144016C02C36DDFFF0282984ACC1EE05052C36F0AC02828669D82DA8F821480A0A10F140002C8E0001004B03190000008000519FD190C43B2E0066108B08401428C342A0CE02828258A0604A6BE959AEE0E6050502C920001004B02D90000008000459FA164404FB30A8580A00A14619C306701414C32CE10E02829659081F814141029030164B0000802E8000802000035FDB1D84C09EC6C003BA14814140B0540003012C187400040080011B13F6EDB804F115FA6DFC10AFC94FC6A57EE07DCE2BFA7BED3B5FFCD72E80A1E018C900008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
}
-
}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSONTest.java
index e70868742..07372aa98 100644
--- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSONTest.java
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodePSMJSONTest.java
@@ -3,49 +3,44 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.json.JSONException;
-import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
import us.dot.its.jpo.ode.model.OdePsmMetadata;
import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
public class Asn1DecodePSMJSONTest {
-
- private final String json = "{\"PsmMessageContent\": [{ \"metadata\": { \"utctimestamp:\"2020-11-30T23:45:24.913657Z\" }, \"payload\":\"011d0000201a0000024ea0dc91de75f84da102c23f042dc41414ffff0006ba1000270000000111f7ca7986010000\"}]}";
- private JSONObject jsonObj = new JSONObject();
+ private final String json = "{\"metadata\":{\"recordType\":\"psmTx\",\"securityResultCode\":\"success\",\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"fa3dfe1b-80cd-45cb-ae2c-c604a214fe56\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T19:16:35.212860500Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"UNKNOWN\",\"sanitized\":false,\"psmSource\":\"RSU\",\"originIp\":\"192.168.0.1\"},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"00201A0000021BD86891DE75F84DA101C13F042E2214141FFF00022C2000270000000163B2CC798601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
@Test
public void testConstructor() {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
- assertEquals(properties.getKafkaTopicOdePsmJson(), "topic.OdePsmJson");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedPSMJson(), "topic.OdeRawEncodedPSMJson");
}
@Test
- public void testProcessPsmJson() throws XmlUtilsException, JSONException {
+ public void testProcess() throws XmlUtilsException, JSONException {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
Asn1DecodePSMJSON testDecodePsmJson = new Asn1DecodePSMJSON(properties);
- assertEquals(testDecodePsmJson.process(json), null);
-
- // metadata
- OdeData obj = new OdeData();
- OdePsmMetadata jsonMetadataObj = new OdePsmMetadata();
- jsonMetadataObj.setOdeReceivedAt("2020-11-30T23:45:24.913657Z");
- jsonObj.put("metadata", jsonMetadataObj);
-
- // payload
- String encodedPayload = "011d0000201a0000024ea0dc91de75f84da102c23f042dc41414ffff0006ba1000270000000111f7ca7986010000";
- obj.setMetadata(jsonMetadataObj);
- obj.setPayload(new OdeAsn1Payload(new OdeHexByteArray(encodedPayload)));
-
- assertEquals("{\"bytes\":\"011d0000201a0000024ea0dc91de75f84da102c23f042dc41414ffff0006ba1000270000000111f7ca7986010000\"}",
- obj.getPayload().getData().toJson());
-
+
+ OdeAsn1Data resultOdeObj = testDecodePsmJson.process(json);
+
+ // Validate the metadata
+ OdePsmMetadata jsonMetadataObj = (OdePsmMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getPsmSource(), OdePsmMetadata.PsmSource.RSU);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"00201A0000021BD86891DE75F84DA101C13F042E2214141FFF00022C2000270000000163B2CC798601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
}
-
}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSONTest.java
new file mode 100644
index 000000000..6098d70a5
--- /dev/null
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSPATJSONTest.java
@@ -0,0 +1,46 @@
+package us.dot.its.jpo.ode.services.asn1.message;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.json.JSONException;
+import org.junit.jupiter.api.Test;
+
+import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeSpatMetadata;
+import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
+
+public class Asn1DecodeSPATJSONTest {
+ private final String json = "{\"metadata\":{\"recordType\":\"spatTx\",\"securityResultCode\":\"success\",\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"5ec410a3-bec6-4724-9601-1e08778e1dfc\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T19:43:22.604870100Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"RSU\",\"sanitized\":false,\"spatSource\":\"RSU\",\"originIp\":\"192.168.0.1\",\"isCertPresent\":false},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"0381004003807C00134700081132000000E437070010434257925790010232119A11CE800C10D095E495E400808684AF24AF20050434257925790030232119A11CE801C10D095E495E401008684AF24AF20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
+
+ @Test
+ public void testConstructor() {
+ OdeProperties properties = new OdeProperties();
+ properties.setKafkaBrokers("localhost:9092");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedSPATJson(), "topic.OdeRawEncodedSPATJson");
+ }
+
+ @Test
+ public void testProcess() throws XmlUtilsException, JSONException {
+ OdeProperties properties = new OdeProperties();
+ properties.setKafkaBrokers("localhost:9092");
+ Asn1DecodeSPATJSON testDecodeSpatJson = new Asn1DecodeSPATJSON(properties);
+
+ OdeAsn1Data resultOdeObj = testDecodeSpatJson.process(json);
+
+ // Validate the metadata
+ OdeSpatMetadata jsonMetadataObj = (OdeSpatMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getSpatSource(), OdeSpatMetadata.SpatSource.RSU);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"00134700081132000000E437070010434257925790010232119A11CE800C10D095E495E400808684AF24AF20050434257925790030232119A11CE801C10D095E495E401008684AF24AF20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
+ }
+}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSONTest.java
index b51505b10..d675e865f 100644
--- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSONTest.java
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSRMJSONTest.java
@@ -3,48 +3,44 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.json.JSONException;
-import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
import us.dot.its.jpo.ode.model.OdeSrmMetadata;
import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
public class Asn1DecodeSRMJSONTest {
-
- private final String json = "{\"SrmMessageContent\": [{ \"metadata\": { \"utctimestamp\":\"2020-11-30T23:45:24.913657Z\", \"originRsu\":\"172.0.0.24\", \"source\":\"RSU\" }, \"payload\":\"001d2130000010090bd341080d00855c6c0c6899853000a534f7c24cb29897694759b7c0\"}]}";
- private JSONObject jsonObj = new JSONObject();
+ private final String json = "{\"metadata\":{\"recordType\":\"srmTx\",\"securityResultCode\":\"success\",\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"190cbd65-d1e2-488a-ba42-b7d3f03a5c69\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T19:24:04.113614500Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"OBU\",\"sanitized\":false,\"originIp\":\"192.168.0.1\",\"srmSource\":\"RSU\"},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"0381004003807C001D2130000010090BD341080D00855C6C0C6899853000A534F7C24CB29897694759B7C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
@Test
public void testConstructor() {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
- assertEquals(properties.getKafkaTopicOdeSrmTxPojo(), "topic.OdeSrmTxPojo");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedSRMJson(), "topic.OdeRawEncodedSRMJson");
}
@Test
- public void testProcessSrmJson() throws XmlUtilsException, JSONException {
+ public void testProcess() throws XmlUtilsException, JSONException {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
Asn1DecodeSRMJSON testDecodeSrmJson = new Asn1DecodeSRMJSON(properties);
- assertEquals(testDecodeSrmJson.process(json), null);
-
- // metadata
- OdeData obj = new OdeData();
- OdeSrmMetadata jsonMetadataObj = new OdeSrmMetadata();
- jsonMetadataObj.setOdeReceivedAt("2020-11-30T23:45:24.913657Z");
- jsonObj.put("metadata", jsonMetadataObj);
-
- // payload
- String encodedPayload = "001d2130000010090bd341080d00855c6c0c6899853000a534f7c24cb29897694759b7c0";
- obj.setMetadata(jsonMetadataObj);
- obj.setPayload(new OdeAsn1Payload(new OdeHexByteArray(encodedPayload)));
-
- assertEquals("{\"bytes\":\"001d2130000010090bd341080d00855c6c0c6899853000a534f7c24cb29897694759b7c0\"}",
- obj.getPayload().getData().toJson());
-
+
+ OdeAsn1Data resultOdeObj = testDecodeSrmJson.process(json);
+
+ // Validate the metadata
+ OdeSrmMetadata jsonMetadataObj = (OdeSrmMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getSrmSource(), OdeSrmMetadata.SrmSource.RSU);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"001D2130000010090BD341080D00855C6C0C6899853000A534F7C24CB29897694759B7C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
}
}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSSMJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSSMJSONTest.java
index 2a1e5ed94..03f7d21ed 100644
--- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSSMJSONTest.java
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeSSMJSONTest.java
@@ -3,48 +3,44 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.json.JSONException;
-import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
import us.dot.its.jpo.ode.model.OdeAsn1Payload;
-import us.dot.its.jpo.ode.model.OdeData;
-import us.dot.its.jpo.ode.model.OdeHexByteArray;
import us.dot.its.jpo.ode.model.OdeSsmMetadata;
import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
public class Asn1DecodeSSMJSONTest {
-
- private final String json = "{\"SsmMessageContent\": [{ \"metadata\": { \"utctimestamp\":\"2020-11-30T23:45:24.913657Z\", \"originRsu\":\"172.0.0.24\", \"source\":\"RSU\" }, \"payload\":\"001e120000000005e9c04071a26614c06000040ba0\"}]}";
- private JSONObject jsonObj = new JSONObject();
+ private final String json = "{\"metadata\":{\"recordType\":\"ssmTx\",\"securityResultCode\":\"success\",\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"c4e4e92d-dccc-45f5-813f-7d36795529a0\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T19:31:02.907835400Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"RSU\",\"sanitized\":false,\"originIp\":\"192.168.0.1\",\"ssmSource\":\"RSU\"},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"0381004003807C001E120000000005E9C04071A26614C06000040BA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
@Test
public void testConstructor() {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
- assertEquals(properties.getKafkaTopicOdeSsmPojo(), "topic.OdeSsmPojo");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedSSMJson(), "topic.OdeRawEncodedSSMJson");
}
@Test
- public void testProcessSsmJson() throws XmlUtilsException, JSONException {
+ public void testProcess() throws XmlUtilsException, JSONException {
OdeProperties properties = new OdeProperties();
properties.setKafkaBrokers("localhost:9092");
Asn1DecodeSSMJSON testDecodeSsmJson = new Asn1DecodeSSMJSON(properties);
- assertEquals(testDecodeSsmJson.process(json), null);
-
- // metadata
- OdeData obj = new OdeData();
- OdeSsmMetadata jsonMetadataObj = new OdeSsmMetadata();
- jsonMetadataObj.setOdeReceivedAt("2020-11-30T23:45:24.913657Z");
- jsonObj.put("metadata", jsonMetadataObj);
-
- // payload
- String encodedPayload = "001e120000000005e9c04071a26614c06000040ba0";
- obj.setMetadata(jsonMetadataObj);
- obj.setPayload(new OdeAsn1Payload(new OdeHexByteArray(encodedPayload)));
-
- assertEquals("{\"bytes\":\"001e120000000005e9c04071a26614c06000040ba0\"}",
- obj.getPayload().getData().toJson());
-
+
+ OdeAsn1Data resultOdeObj = testDecodeSsmJson.process(json);
+
+ // Validate the metadata
+ OdeSsmMetadata jsonMetadataObj = (OdeSsmMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getSsmSource(), OdeSsmMetadata.SsmSource.RSU);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"001E120000000005E9C04071A26614C06000040BA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
}
}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeTIMJSONTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeTIMJSONTest.java
new file mode 100644
index 000000000..8bf04a0a0
--- /dev/null
+++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/services/asn1/message/Asn1DecodeTIMJSONTest.java
@@ -0,0 +1,47 @@
+package us.dot.its.jpo.ode.services.asn1.message;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.json.JSONException;
+import org.junit.jupiter.api.Test;
+
+import us.dot.its.jpo.ode.OdeProperties;
+import us.dot.its.jpo.ode.model.Asn1Encoding.EncodingRule;
+import us.dot.its.jpo.ode.model.OdeAsn1Data;
+import us.dot.its.jpo.ode.model.OdeAsn1Payload;
+import us.dot.its.jpo.ode.model.OdeMsgMetadata;
+import us.dot.its.jpo.ode.model.OdeTimMetadata;
+import us.dot.its.jpo.ode.util.XmlUtils.XmlUtilsException;
+
+public class Asn1DecodeTIMJSONTest {
+ private final String json = "{\"metadata\":{\"recordType\":\"timMsg\",\"securityResultCode\":\"success\",\"payloadType\":\"us.dot.its.jpo.ode.model.OdeAsn1Payload\",\"serialId\":{\"streamId\":\"9952caf6-81bd-490d-ad95-47dee31c3ba8\",\"bundleSize\":1,\"bundleId\":0,\"recordId\":0,\"serialNumber\":0},\"odeReceivedAt\":\"2024-03-15T19:38:48.578500100Z\",\"schemaVersion\":6,\"maxDurationTime\":0,\"recordGeneratedBy\":\"RSU\",\"sanitized\":false,\"originIp\":\"192.168.0.1\"},\"payload\":{\"dataType\":\"us.dot.its.jpo.ode.model.OdeHexByteArray\",\"data\":{\"bytes\":\"0381004003807C001F79201000000000012AA366D080729B8987D859717EE22001FFFE4FD0011589D828007E537130FB0B2E2FDC440001F46FFFF002B8B2E46E926E27CE6813D862CB90EDC9B89E11CE2CB8E98F9B89BCC4050518B2E365B66E26AE3B8B2E291A66E2591D8141462CB873969B89396C62CB86AFE9B89208E00000131560018300023E43A6A1351800023E4700EFC51881010100030180C620FB90CAAD3B9C5082080E1DDC905E10168E396921000325A0D73B83279C83010180034801090001260001808001838005008001F0408001828005008001304000041020407E800320409780050080012040000320409900018780032040958005000001E0408183E7139D7B70987019B526B8A950052F5C011D3C4B992143E885C71F95DA6071658082346CC03A50D66801F65288C30AB39673D0494536C559047E457AD291C99C20A7FB1244363E993EE3EE98C78742609340541DA01545A0F7339C26A527903576D30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}}";
+
+ @Test
+ public void testConstructor() {
+ OdeProperties properties = new OdeProperties();
+ properties.setKafkaBrokers("localhost:9092");
+ assertEquals(properties.getKafkaTopicOdeRawEncodedTIMJson(), "topic.OdeRawEncodedTIMJson");
+ }
+
+ @Test
+ public void testProcess() throws XmlUtilsException, JSONException {
+ OdeProperties properties = new OdeProperties();
+ properties.setKafkaBrokers("localhost:9092");
+ Asn1DecodeTIMJSON testDecodeTimJson = new Asn1DecodeTIMJSON(properties);
+
+ OdeAsn1Data resultOdeObj = testDecodeTimJson.process(json);
+
+ // Validate the metadata
+ OdeTimMetadata jsonMetadataObj = (OdeTimMetadata) resultOdeObj.getMetadata();
+ assertEquals(jsonMetadataObj.getRecordGeneratedBy(), OdeMsgMetadata.GeneratedBy.RSU);
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementName(), "unsecuredData");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getElementType(), "MessageFrame");
+ assertEquals(jsonMetadataObj.getEncodings().get(0).getEncodingRule(), EncodingRule.UPER);
+
+ // Validate the payload
+ String expectedPayload = "{\"bytes\":\"001F79201000000000012AA366D080729B8987D859717EE22001FFFE4FD0011589D828007E537130FB0B2E2FDC440001F46FFFF002B8B2E46E926E27CE6813D862CB90EDC9B89E11CE2CB8E98F9B89BCC4050518B2E365B66E26AE3B8B2E291A66E2591D8141462CB873969B89396C62CB86AFE9B89208E00000131560018300023E43A6A1351800023E4700EFC51881010100030180C620FB90CAAD3B9C5082080E1DDC905E10168E396921000325A0D73B83279C83010180034801090001260001808001838005008001F0408001828005008001304000041020407E800320409780050080012040000320409900018780032040958005000001E0408183E7139D7B70987019B526B8A950052F5C011D3C4B992143E885C71F95DA6071658082346CC03A50D66801F65288C30AB39673D0494536C559047E457AD291C99C20A7FB1244363E993EE3EE98C78742609340541DA01545A0F7339C26A527903576D30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
+ OdeAsn1Payload jsonPayloadObj = (OdeAsn1Payload) resultOdeObj.getPayload();
+ assertEquals(jsonPayloadObj.getDataType(), "us.dot.its.jpo.ode.model.OdeHexByteArray");
+ assertEquals(jsonPayloadObj.getData().toString(), expectedPayload);
+ }
+}
diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/udp/bsm/BsmComparatorTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/udp/bsm/BsmComparatorTest.java
deleted file mode 100644
index 35decb55d..000000000
--- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/udp/bsm/BsmComparatorTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * Copyright 2018 572682
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- ******************************************************************************/
-package us.dot.its.jpo.ode.udp.bsm;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.jupiter.api.Test;
-
-import us.dot.its.jpo.ode.plugin.j2735.J2735Bsm;
-import us.dot.its.jpo.ode.plugin.j2735.J2735BsmCoreData;
-import us.dot.its.jpo.ode.udp.bsm.BsmComparator;
-
-public class BsmComparatorTest {
-
- @Test
- public void shouldReturnXLessThanY() {
- J2735BsmCoreData testDataX = new J2735BsmCoreData();
- testDataX.setSecMark(5);
- J2735BsmCoreData testDataY = new J2735BsmCoreData();
- testDataY.setSecMark(6);
-
- J2735Bsm bsmX = new J2735Bsm();
- bsmX.setCoreData(testDataX);
-
- J2735Bsm bsmY = new J2735Bsm();
- bsmY.setCoreData(testDataY);
-
- BsmComparator testBsmComparator = new BsmComparator();
- assertEquals(-1, testBsmComparator.compare(bsmX, bsmY));
- }
-
- @Test
- public void shouldReturnYLessThanX() {
- J2735BsmCoreData testDataX = new J2735BsmCoreData();
- testDataX.setSecMark(6);
- J2735BsmCoreData testDataY = new J2735BsmCoreData();
- testDataY.setSecMark(5);
-
- J2735Bsm bsmX = new J2735Bsm();
- bsmX.setCoreData(testDataX);
-
- J2735Bsm bsmY = new J2735Bsm();
- bsmY.setCoreData(testDataY);
-
- BsmComparator testBsmComparator = new BsmComparator();
- assertEquals(1, testBsmComparator.compare(bsmX, bsmY));
- }
-
- @Test
- public void shouldReturnXEqualsY() {
- J2735BsmCoreData testDataX = new J2735BsmCoreData();
- testDataX.setSecMark(5);
- J2735BsmCoreData testDataY = new J2735BsmCoreData();
- testDataY.setSecMark(5);
-
- J2735Bsm bsmX = new J2735Bsm();
- bsmX.setCoreData(testDataX);
-
- J2735Bsm bsmY = new J2735Bsm();
- bsmY.setCoreData(testDataY);
-
- BsmComparator testBsmComparator = new BsmComparator();
- assertEquals(0, testBsmComparator.compare(bsmX, bsmY));
- }
-
-}
diff --git a/pom.xml b/pom.xml
index 1acd37a92..18acbf54a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -116,7 +116,7 @@
org.sonarsource.scanner.maven
sonar-maven-plugin
- 3.10.0.2594
+ 3.11.0.3922
org.springframework.boot
@@ -126,8 +126,7 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 21
+ 21
true
-Xlint:deprecation
@@ -137,9 +136,9 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.0.0-M5
+ 3.2.5
- -javaagent:${user.home}/.m2/repository/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar
+ -javaagent:${user.home}/.m2/repository/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar -Xshare:off
${loader.path}
@@ -150,14 +149,14 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.1.2
+ 3.2.5
org.apache.maven.plugins
maven-release-plugin
- 2.5.3
+ 3.0.1