Samuel-Tyler / fast_ber

A C++11 ASN.1 BER Encoding and Decoding Library
Boost Software License 1.0
84 stars 11 forks source link

Automatic tags not working #40

Open Thiesius opened 2 years ago

Thiesius commented 2 years ago

Using ETSI CAM 1.4.1 the Automatic tags are not respected (context_specific class is not used) and the message fails to validate against ASN1 Playground

Please note that I have no real understanding of ASN.1 and BER encoding. So my fixes might seem naive. Anyways:

I have managed in somewhat uneducated way fix the encoder with generating context_specific id when the tagging_mode is automatic and the component in collection / choice is a SequenceType or ChoiceType. This "fix" somehow broke encoded_size as the returned value is 204 and real message size is actually 210. This encoding might also work only for my use case as I haven't tested anything else. However the generated bytes are same as the message from ASN1 Playground.

I also fixed the decoder in similar way as the encoder. "create_collection_decode_functions" for optional types is another sort of hack by collecting all ids from all components and generating that huge "if" statement for them. I only tested that on decoding the message I previously encoded.

Samuel-Tyler commented 2 years ago

Could you post the ASN.1 snippit with the problem?

Thiesius commented 2 years ago

ASN.1 descriptions: https://forge.etsi.org/rep/ITS/asn1/cdd_ts102894_2/blob/master/ITS-Container.asn https://forge.etsi.org/rep/ITS/asn1/cam_en302637_2/blob/master/CAM-PDU-Descriptions.asn

I used sample from ASN.1 Playground as a baseline:

value1 CAM ::= {
  header {
    protocolVersion 1,
    messageID cam,
    stationID 1234567
  },
  cam {
    generationDeltaTime 11409,
    camParameters {
      basicContainer {
        stationType passengerCar,
        referencePosition {
          latitude 40487111,
          longitude 79494789,
          positionConfidenceEllipse {
            semiMajorConfidence 500,
            semiMinorConfidence 400,
            semiMajorOrientation wgs84North
          },
          altitude {
            altitudeValue 2000,
            altitudeConfidence alt-000-02
          }
        }
      },
      highFrequencyContainer basicVehicleContainerHighFrequency : {
        heading {
          headingValue wgs84North,
          headingConfidence equalOrWithinZeroPointOneDegree
        },
        speed {
          speedValue 2000,
          speedConfidence equalOrWithinOneCentimeterPerSec
        },
        driveDirection forward,
        vehicleLength {
          vehicleLengthValue 35,
          vehicleLengthConfidenceIndication noTrailerPresent
        },
        vehicleWidth 20,
        longitudinalAcceleration {
          longitudinalAccelerationValue 10,
          longitudinalAccelerationConfidence pointOneMeterPerSecSquared
        },
        curvature {
          curvatureValue straight,
          curvatureConfidence onePerMeter-0-00002
        },
        curvatureCalculationMode yawRateUsed,
        yawRate {
          yawRateValue straight,
          yawRateConfidence degSec-000-01
        },
        accelerationControl '0100000'B,
        steeringWheelAngle {
          steeringWheelAngleValue 30,
          steeringWheelAngleConfidence equalOrWithinOnePointFiveDegree
        },
        lateralAcceleration {
          lateralAccelerationValue -2,
          lateralAccelerationConfidence pointOneMeterPerSecSquared
        },
        verticalAcceleration {
          verticalAccelerationValue pointOneMeterPerSecSquaredUp,
          verticalAccelerationConfidence pointOneMeterPerSecSquared
        }
      },
      specialVehicleContainer publicTransportContainer : {
        embarkationStatus FALSE,
        ptActivation {
          ptActivationType undefinedCodingType,
          ptActivationData '001122334455'H
        }
      }
    }
  }
}

Message on above rewritten in code I used to test it.

        fast_ber::CAM_PDU_Descriptions::CAM msg{};
        msg.header.messageID = 2;
        msg.header.protocolVersion = 1;
        msg.header.stationID = 1234567;

        msg.cam.generationDeltaTime = 11409;
        auto& bc = msg.cam.camParameters.basicContainer;
        bc.stationType = 5;
        bc.referencePosition.latitude = 40487111;
        bc.referencePosition.longitude = 79494789;
        bc.referencePosition.positionConfidenceEllipse.semiMajorConfidence = 500;
        bc.referencePosition.positionConfidenceEllipse.semiMinorConfidence = 400;
        bc.referencePosition.positionConfidenceEllipse.semiMajorOrientation = 0;
        bc.referencePosition.altitude.altitudeValue = 2000;
        bc.referencePosition.altitude.altitudeConfidence = fast_ber::ITS_Container::AltitudeConfidenceValues::alt_000_02;

        fast_ber::CAM_PDU_Descriptions::BasicVehicleContainerHighFrequency basicVehContHF{};
        basicVehContHF.heading.headingValue = 0;
        basicVehContHF.heading.headingConfidence = 1;
        basicVehContHF.speed.speedValue = 2000;
        basicVehContHF.speed.speedConfidence = 1;
        basicVehContHF.driveDirection = fast_ber::ITS_Container::DriveDirectionValues::forward;
        basicVehContHF.vehicleLength.vehicleLengthValue = 35;
        basicVehContHF.vehicleLength.vehicleLengthConfidenceIndication = fast_ber::ITS_Container::VehicleLengthConfidenceIndicationValues::noTrailerPresent;
        basicVehContHF.vehicleWidth = 20;
        basicVehContHF.longitudinalAcceleration.longitudinalAccelerationValue = 10;
        basicVehContHF.longitudinalAcceleration.longitudinalAccelerationConfidence = 1;
        basicVehContHF.curvature.curvatureValue = 0;
        basicVehContHF.curvature.curvatureConfidence = fast_ber::ITS_Container::CurvatureConfidenceValues::onePerMeter_0_00002;
        basicVehContHF.curvatureCalculationMode = fast_ber::ITS_Container::CurvatureCalculationModeValues::yawRateUsed;
        basicVehContHF.yawRate.yawRateValue = 0;
        basicVehContHF.yawRate.yawRateConfidence = fast_ber::ITS_Container::YawRateConfidenceValues::degSec_000_01;
        std::array<uint8_t, 2> accelControl = {0x01, 0x40};
        basicVehContHF.accelerationControl =  std::span(accelControl);
        fast_ber::ITS_Container::SteeringWheelAngle steeringWheelAngle{};
        steeringWheelAngle.steeringWheelAngleValue = 30;
        steeringWheelAngle.steeringWheelAngleConfidence = 1;
        basicVehContHF.steeringWheelAngle = steeringWheelAngle;
        fast_ber::ITS_Container::LateralAcceleration latAcc{};
        latAcc.lateralAccelerationValue = -2;
        latAcc.lateralAccelerationConfidence = 1;
        basicVehContHF.lateralAcceleration = latAcc;
        fast_ber::ITS_Container::VerticalAcceleration vertiAcc{};
        vertiAcc.verticalAccelerationValue = 1;
        vertiAcc.verticalAccelerationConfidence = 1;
        basicVehContHF.verticalAcceleration = vertiAcc;

        fast_ber::CAM_PDU_Descriptions::BasicVehicleContainerLowFrequency basicVehContLF{};
        basicVehContLF.vehicleRole = fast_ber::ITS_Container::VehicleRoleValues::default_;
        std::array<uint8_t, 2> exterLights = {0x00, 0xA8};
        basicVehContLF.exteriorLights = std::span(exterLights);
        fast_ber::ITS_Container::PathPoint pp{};
        pp.pathDeltaTime = 1000;
        pp.pathPosition.deltaLatitude = 10000;
        pp.pathPosition.deltaLongitude = 5000;
        pp.pathPosition.deltaAltitude = 12800;
        basicVehContLF.pathHistory.emplace_back(std::move(pp));

        fast_ber::CAM_PDU_Descriptions::PublicTransportContainer pubTransportCont{};
        pubTransportCont.embarkationStatus = false;
        fast_ber::ITS_Container::PtActivation ptAct{};
        std::array<uint8_t, 6> testData = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
        ptAct.ptActivationData = std::span(testData);
        ptAct.ptActivationType = 0;
        pubTransportCont.ptActivation = std::move(ptAct);

        msg.cam.camParameters.highFrequencyContainer = std::move(basicVehContHF);
        msg.cam.camParameters.lowFrequencyContainer = std::move(basicVehContLF);
        msg.cam.camParameters.specialVehicleContainer = std::move(pubTransportCont);

My blanket fix I did yesterday (prepare the bucket :D ): https://github.com/Roboauto/fast_ber/commit/089d3a2dfb3c8b14da066791f578fbec86dcf6c6

I used https://lapo.it/asn1js/ to compare the results

Samuel-Tyler commented 2 years ago

Thanks I will take a look