diff --git a/.gitignore b/.gitignore index 03368199..d5bc1c2f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,7 @@ settings.json asn1c_combined/compile.out asn1c_combined/converter-example asn1c_combined/converter-example.mk -asn1c_combined/libasncodec.a \ No newline at end of file +asn1c_combined/libasncodec.a + +.idea/ +cmake-build-*/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 41c6e910..c6ee9a31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1) project(ACM) # need to set these prior to setting any targets. -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_VERBOSE_MAKEFILE ON) diff --git a/asn1c_combined/generate-files.sh b/asn1c_combined/generate-files.sh index dc98409e..a3188e41 100644 --- a/asn1c_combined/generate-files.sh +++ b/asn1c_combined/generate-files.sh @@ -36,9 +36,6 @@ if [ "$year" == "2024" ]; then patch --binary --backup --forward --reject-file="-" \ ./j2735-asn-files/2024/J3217-TollUsageMsg-2024-rel-v1.1.asn \ ./j2735-asn-files/2024/asn-edits/TollUsageMessage.patch - patch --binary --backup --forward --reject-file="-" \ - ./j2735-asn-files/2024/J2735-Common-2024-rel-v1.1.2.asn \ - ./j2735-asn-files/2024/asn-edits/Common.patch # Verify that the patches were applied correctly if ! grep -q RwmSnapShot ./j2735-asn-files/2024/J2945-3-RoadWeatherMessage-2024-rel-v2.1.asn; then @@ -56,10 +53,6 @@ if [ "$year" == "2024" ]; then exit 1 fi - if grep -q " eventJackKnife " ./j2735-asn-files/2024/J2735-Common-2024-rel-v1.1.2.asn; then - echo "The patch for the Common ASN file was not applied correctly." - exit 1 - fi fi diff --git a/asn1c_combined/generated-files/2024.tar.gz b/asn1c_combined/generated-files/2024.tar.gz index a5b95616..abd116c6 100644 Binary files a/asn1c_combined/generated-files/2024.tar.gz and b/asn1c_combined/generated-files/2024.tar.gz differ diff --git a/asn1c_combined/j2735-asn-files/2024/asn-edits/Common.patch b/asn1c_combined/j2735-asn-files/2024/asn-edits/Common.patch deleted file mode 100644 index 8be2d142..00000000 --- a/asn1c_combined/j2735-asn-files/2024/asn-edits/Common.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- J2735-Common-2024-rel-v1.1.2.asn 2024-05-16 14:48:14.000000000 -0600 -+++ J2735-Common-2024-rel-v1.1.2.asn.EDITED 2025-01-17 16:10:23.262921200 -0700 -@@ -1874,11 +1874,11 @@ - eventWipersChanged (9), - eventFlatTire (10), - eventDisabledVehicle (11), -- The DisabledVehicle DF may also be sent -- eventAirBagDeployment (12), -- eventJackKnife (13) -- Applies to vehicles with trailer(s) -- } (SIZE (13, ..., 14)) -+ eventAirBagDeployment (12) -+ } (SIZE (13, ...)) - -- To extend: Append event flags to the list, - -- and update extension marker, e.g., (Size (13, ..., 14..16)) -+-- EDITED: reverted to previous definition without 'eventJackKnife' - - VehicleHeight ::= INTEGER (0..127) - -- the height of the vehicle diff --git a/asn1c_combined/j2735-asn-files/2024/overrides/VehicleEventFlags.c b/asn1c_combined/j2735-asn-files/2024/overrides/VehicleEventFlags.c new file mode 100644 index 00000000..b033b602 --- /dev/null +++ b/asn1c_combined/j2735-asn-files/2024/overrides/VehicleEventFlags.c @@ -0,0 +1,95 @@ +/* + * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) + * From ASN.1 module "Common" + * found in "./j2735-asn-files/2024/J2735-Common-2024-rel-v1.1.2.asn" + * `asn1c -fcompound-names -gen-OER -fincludes-quoted -no-gen-JER -pdu=all -D ./generated-files/2024` + */ + +#include "VehicleEventFlags.h" + +int +VehicleEventFlags_constraint(const asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + size_t size; + + if(!sptr) { + ASN__CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if(st->size > 0) { + /* Size in bits */ + size = 8 * st->size - (st->bits_unused & 0x07); + } else { + size = 0; + } + + /* + * NOT edited. Keep the size constraint including extension in this check. + */ + if((size >= 13UL && size <= 14UL)) { + /* Constraint check succeeded */ + return 0; + } else { + ASN__CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +/* + * This type is implemented using BIT_STRING, + * so here we adjust the DEF accordingly. + */ +#if !defined(ASN_DISABLE_OER_SUPPORT) +static asn_oer_constraints_t asn_OER_type_VehicleEventFlags_constr_1 CC_NOTUSED = { + { 0, 0 }, + -1 /* (SIZE(0..MAX)) */}; +#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */ + +/* + * EDITED PER size constraint + * originally: (SIZE(13..14,...)) + * changed to: (SIZE(13,...)) + */ +#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) +asn_per_constraints_t asn_PER_type_VehicleEventFlags_constr_1 CC_NOTUSED = { + { APC_UNCONSTRAINED, -1, -1, 0, 0 }, + { APC_CONSTRAINED | APC_EXTENSIBLE, 0, 0, 13, 13 }, + 0, 0 /* No PER value map */ +}; +#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */ + +static const ber_tlv_tag_t asn_DEF_VehicleEventFlags_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_VehicleEventFlags = { + "VehicleEventFlags", + "VehicleEventFlags", + &asn_OP_BIT_STRING, + asn_DEF_VehicleEventFlags_tags_1, + sizeof(asn_DEF_VehicleEventFlags_tags_1) + /sizeof(asn_DEF_VehicleEventFlags_tags_1[0]), /* 1 */ + asn_DEF_VehicleEventFlags_tags_1, /* Same as above */ + sizeof(asn_DEF_VehicleEventFlags_tags_1) + /sizeof(asn_DEF_VehicleEventFlags_tags_1[0]), /* 1 */ + { +#if !defined(ASN_DISABLE_OER_SUPPORT) + &asn_OER_type_VehicleEventFlags_constr_1, +#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */ +#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) + &asn_PER_type_VehicleEventFlags_constr_1, +#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */ +#if !defined(ASN_DISABLE_JER_SUPPORT) + 0, +#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */ + VehicleEventFlags_constraint + }, + 0, 0, /* Defined elsewhere */ + &asn_SPC_BIT_STRING_specs /* Additional specs */ +}; + diff --git a/data/InputData.decoding.bsm.with.VehicleEventFlags.eventJackKnife.xml b/data/InputData.decoding.bsm.with.VehicleEventFlags.eventJackKnife.xml new file mode 100644 index 00000000..eba53435 --- /dev/null +++ b/data/InputData.decoding.bsm.with.VehicleEventFlags.eventJackKnife.xml @@ -0,0 +1 @@ +RVbsmTxsuccessRVunsecuredDataMessageFrameUPERus.dot.its.jpo.ode.model.OdeAsn1Payloadbee2fd4f-f2e4-4a91-a35c-dabf83f22dec10002023-02-21T21:08:03.588646Z60false10.10.10.10us.dot.its.jpo.ode.model.OdeHexByteArray0014515767567EDDDFA3E68037E116658105B0DA9414000070F402B0FD630FA1007F82800000000000A9D0E00040C227738206DF900A482429E82C7DF900F4C268B282DE5F7015602B18982B1DED82000D50F680 \ No newline at end of file diff --git a/src/tests.cpp b/src/tests.cpp index 2a5b71ca..ce20db35 100644 --- a/src/tests.cpp +++ b/src/tests.cpp @@ -4,6 +4,7 @@ #include "acm.hpp" #include "utilities.hpp" + bool loadTestCases( const std::string& case_file, StrVector& case_data ) { std::string line; @@ -26,6 +27,7 @@ bool loadTestCases( const std::string& case_file, StrVector& case_data ) { } pugi::xpath_query ode_payload_query("OdeAsn1Data/payload/data"); +pugi::xpath_query bsm_vehicle_event_flags_query("MessageFrame/value/BasicSafetyMessage/partII/BSMpartIIExtension/partII-Value/VehicleSafetyExtensions/events"); pugi::xml_document output_doc; pugi::xml_parse_result parse_result; pugi::xml_node payload_node; @@ -222,8 +224,8 @@ TEST_CASE("Decode BSM", "[decoding]") { CHECK(payload_node); } -TEST_CASE("Decode BSM with VehicleEventFlags", "[decoding]") { - std::cout << "=== Decode BSM with VehicleEventFlags ===" << std::endl; +TEST_CASE("Decode BSM with VehicleEventFlags (hard braking event)", "[decoding]") { + std::cout << "=== Decode BSM with VehicleEventFlags (hard braking event) ===" << std::endl; // prepare asn1_codec.setup_logger_for_testing(); @@ -234,4 +236,157 @@ TEST_CASE("Decode BSM with VehicleEventFlags", "[decoding]") { CHECK(parse_result); payload_node = ode_payload_query.evaluate_node(output_doc).node(); CHECK(payload_node); -} \ No newline at end of file + pugi::xml_node event_flags_node = bsm_vehicle_event_flags_query.evaluate_node(payload_node).node(); + CHECK(event_flags_node); + std::string bitstring(event_flags_node.text().get()); + std::cout << "VehicleEventFlags: " << bitstring << std::endl; + std::string expected_bitstring("0000000100000"); + CHECK(bitstring == expected_bitstring); +} + +TEST_CASE("Decode BSM with VehicleEventFlags (jackknife event)", "[decoding]") { + std::cout << "=== Decode BSM with VehicleEventFlags (jackknife event) ===" << std::endl; + + // prepare + asn1_codec.setup_logger_for_testing(); + + std::stringstream out9; + CHECK(asn1_codec.file_test("data/InputData.decoding.bsm.with.VehicleEventFlags.eventJackKnife.xml", out9, false) == EXIT_SUCCESS); + parse_result = output_doc.load(out9, pugi::parse_default | pugi::parse_declaration | pugi::parse_doctype | pugi::parse_trim_pcdata); + CHECK(parse_result); + payload_node = ode_payload_query.evaluate_node(output_doc).node(); + CHECK(payload_node); + pugi::xml_node event_flags_node = bsm_vehicle_event_flags_query.evaluate_node(payload_node).node(); + CHECK(event_flags_node); + std::string bitstring(event_flags_node.text().get()); + std::cout << "VehicleEventFlags: " << bitstring << std::endl; + std::string expected_bitstring("00000000000001"); + CHECK(bitstring == expected_bitstring); +} + +/* + * Utilities for VehicleEventFlags tests + */ + +void print_bits(const void * buf, const ssize_t num_bytes) { + std::cout << "uper: "; + for (int i = 0; i < num_bytes; i++) { + uint8_t abyte = *((uint8_t *)buf + i); + std::cout << std::bitset<8>(abyte) << " "; + } + std::cout << std::endl; +} + +void test_encode_VehicleEventFlags_to_uper(const uint16_t bitstring, const uint8_t *expected_uper, const ssize_t expected_byte_len) { + std::cout << "bitstring: " << std::bitset<16>(bitstring) << std::endl; + const uint8_t buf[] = { static_cast(bitstring >> 8), static_cast(bitstring & 0xFF) }; + const size_t size = sizeof(buf); + uint8_t *ptr_buf = (uint8_t *)&buf; + const int bits_unused = __builtin_ctz(bitstring); + asn_struct_ctx_t asn_ctx = {}; + VehicleEventFlags_t vef = {ptr_buf, size, bits_unused, asn_ctx}; + VehicleEventFlags_t* ptr_vef = &vef; + asn_TYPE_descriptor_t *vef_type = &asn_DEF_VehicleEventFlags; + asn_encode_to_new_buffer_result_t res + = asn_encode_to_new_buffer(0, ATS_UNALIGNED_BASIC_PER, vef_type, ptr_vef); + if (res.buffer) { + printf("Successfully encoded %ld bytes to uper\n", res.result.encoded); + print_bits(res.buffer, res.result.encoded); + } else { + FAIL("Error encoding vef"); + return; + } + if (res.result.encoded != expected_byte_len) { + fprintf(stderr, "Error, expected %ld bytes but got %ld", expected_byte_len, res.result.encoded); + FAIL("Wrong number of bytes"); + } + if (memcmp(expected_uper, (uint8_t *)res.buffer, res.result.encoded) != 0) { + FAIL("Error, Uper doesn't match expected"); + } + free(res.buffer); +} + +void test_decode_VehicleEventFlags_from_uper(const uint8_t * uper, const ssize_t uper_len, const uint16_t expected_bitstring, + const int expect_constraint_to_fail) { + print_bits(uper, uper_len); + VehicleEventFlags_t * ptr_vef = 0; + asn_dec_rval_t rval + = asn_decode(0, ATS_UNALIGNED_BASIC_PER, &asn_DEF_VehicleEventFlags, (void **)&ptr_vef, uper, uper_len); + if (rval.code != RC_OK) { + FAIL("Error decoding"); + return; + } + printf("Successfully decoded %ld bytes\n", rval.consumed); + printf("bitstring size: %ld, bits_unused: %d\n", ptr_vef->size, ptr_vef->bits_unused); + + if (ptr_vef->size != 2) { + FAIL("Error, expected bitstring to be 2 bytes"); + } + uint16_t actual_bitstring = (ptr_vef->buf[0] << 8) | ptr_vef->buf[1]; + std::cout << "bitstring: " << std::bitset<16>(actual_bitstring) << std::endl; + if (actual_bitstring != expected_bitstring) { + std::cout << "Error, expected bitstring: " << std::bitset<16>(expected_bitstring) + << " but got: " << std::bitset<16>(actual_bitstring) << std::endl; + FAIL("Bitstring mismatch"); + } + + // Check constraints + char errbuf[128]; + size_t errlen = sizeof(errbuf); + int cons_ret = asn_check_constraints(&asn_DEF_VehicleEventFlags, ptr_vef, errbuf, &errlen); + if (cons_ret && !expect_constraint_to_fail) { + fprintf(stderr, "Constraint check failed: %s\n", errbuf); + FAIL("Unexpected constraint check fail"); + } + + ASN_STRUCT_FREE(asn_DEF_VehicleEventFlags, ptr_vef); +} + +/* + * Data for VehicleEventFlags tests + */ +constexpr uint16_t bitstring_root = (0x8000 >> VehicleEventFlags_eventHazardLights) + | (0x8000 >> VehicleEventFlags_eventAirBagDeployment); +constexpr uint8_t uper_root[2] = { 0b01000000, 0b00000100 }; + +constexpr uint16_t bitstring_with_ext = (0x8000 >> VehicleEventFlags_eventHazardLights) + | (0x8000 >> VehicleEventFlags_eventAirBagDeployment) + | (0x8000 >> VehicleEventFlags_eventJackKnife); + +constexpr uint8_t uper_with_ext[3] = { 0b10000111, 0b01000000, 0b00000110 }; + +constexpr uint16_t bitstring_15bits = (0x8000 >> VehicleEventFlags_eventHazardLights) + | (0x8000 >> VehicleEventFlags_eventAirBagDeployment) + | (0x8000 >> VehicleEventFlags_eventJackKnife) + | (0x8000 >> 14); +constexpr uint8_t uper_15bits[3] = {0b10000111, 0b11000000, 0b00000111 }; + +TEST_CASE("Encode VehicleEventFlags root, from struct to UPER, 13 bits", "[encoding]") { + std::cout << "=== Encode VehicleEventFlags root, from struct to UPER, 13 bits ===" << std::endl; + test_encode_VehicleEventFlags_to_uper(bitstring_root, uper_root, 2); +} + +TEST_CASE("Encode VehicleEventFlags with 2024 extension, from struct to UPER, 14 bits", "[encoding]") { + std::cout << "=== Encode VehicleEventFlags with 2024 extension to UPER, 14 bits ===" << std::endl; + test_encode_VehicleEventFlags_to_uper(bitstring_with_ext, uper_with_ext, 3); +} + +TEST_CASE("Encode VehicleEventFlags with unknown future extension, from struct to UPER, 15 bits", "[encoding]") { + std::cout << "=== Encode VehicleEventFlags with unknown future extension, from struct to UPER, 15 bits ===" << std::endl; + test_encode_VehicleEventFlags_to_uper(bitstring_15bits, uper_15bits, 3); +} + +TEST_CASE("Decode VehicleEventFlags root, from UPER to struct, 13 bits", "[decoding]") { + std::cout << "=== Decode VehicleEventFlags root, from UPER to struct, 13 bits ===" << std::endl; + test_decode_VehicleEventFlags_from_uper(uper_root, 2, bitstring_root, 0); +} + +TEST_CASE("Decode VehicleEventFlags with 2024 extension, from UPER to struct, 14 bits", "[decoding]") { + std::cout << "=== Decode VehicleEventFlags with 2024 extension, from UPER to struct, 14 bits ===" << std::endl; + test_decode_VehicleEventFlags_from_uper(uper_with_ext, 3, bitstring_with_ext, 0); +} + +TEST_CASE("Decode VehicleEventFlags with unknown future extension, from UPER to struct, 15 bits", "[decoding]") { + std::cout << "=== Decode VehicleEventFlags with unknown future extension, from UPER to struct, 15 bits ===" << std::endl; + test_decode_VehicleEventFlags_from_uper(uper_15bits, 3, bitstring_15bits, 1); +}