CAM/DENM C++ Sample Code Using OSS ASN.1 Tools


This sample is provided as part of the OSS ASN.1 Tools trial and commercial shipments. The source code and related files are listed below for reference.

The sample demonstrates how to use the OSS ASN.1 Tools to work with messages for the CAM and DENM standards (ETSI EN 302 637-2 and ETSI EN 302 637-3).

It runs on Linux on x86-64 as an example and illustrates how to create, encode, decode, and print CAM and DENM messages using the OSS ASN.1 Tools API.

A makefile is included for building and running the test program using the OSS ASN.1/C++ runtime.

To explore more samples (LTE RRC, 5G RRC, S1AP, X2AP), visit the main Sample Code page.

Overview

This sample shows how to:

  • Initialize the OSS ASN.1/C++ runtime for the CAM and DENM schemas.
  • Create CAM and DENM messages.
  • Encode CAM and DENM messages.
  • Decode encoded messages.
  • Print decoded message contents.
  • Build and run the sample test program with a makefile on Linux.

Files in This Sample

The files listed below are included in the OSS ASN.1 Tools trial and commercial shipments and are used by this sample program:

File Description
README.TXT Instructions and sample overview.
CAM.asn ASN.1 specification from ETSI EN 302 637-2 V1.4.1 (2019-04).
DENM.asn ASN.1 specification from ETSI EN 302 637-3 V1.3.1 (2019-04).
ITS-Container.asn ASN.1 specification from ETSI TS 102 894-2 V1.3.1 (2018-08).
camdenm.dir Additional ASN.1 compiler directives.
tcamdenm.cpp Simple C++ program that demonstrates creating, encoding, decoding, and printing CAM and DENM messages.
makefile Makefile that builds and runs the sample test.
makefile.rtoed Makefile that builds and runs the sample test using RTOED.
gui/ ASN.1 Studio project for viewing/compiling schema and generating sample data.

Build and Run Instructions

(Installation instructions for the OSS ASN.1 Tools are included in all trial and commercial shipments.)

To build and run this sample, install a trial or licensed version of the OSS ASN.1 Tools for C++.

1. Generate C++ source and header files (runtime-only shipments)

If your shipment is runtime-only, generate the .cpp and .h files by running:

make cross

This creates a samples/cross directory with:

  • the required .asn files
  • scripts to run the OSS ASN.1/C++ compiler (asn1cpl.sh or asn1cpl.bat)
2. Build and run the sample
make

This command compiles the sample C++ source, links it with the OSS ASN.1 static library, and executes the test. To use another type of library in the shipment (such as a shared library), set the A makefile variable, for example:

make A=so
3. Clean up generated files
make clean
4. Other Platforms

Note: The C++ source code in this sample is platform-independent. Linux commands are shown as an example, but equivalent samples and build instructions are available for Windows, macOS, and other platforms. For help with platform-specific instructions, please contact OSS Support.

Code Listing: tcamdenm.cpp

The following listing shows the main C++ source file for this sample test program, tcamdenm.cpp. It demonstrates how to create, encode, decode, and print CAM and DENM messages using the OSS ASN.1 Tools API.

Show tcamdenm.cpp source code
/*****************************************************************************/
/*  Copyright (C) ###RELEASE_YEAR### OSS Nokalva, Inc.  All rights reserved. */
/*****************************************************************************/
/* THIS FILE IS PROPRIETARY MATERIAL OF OSS NOKALVA, INC.                    */
/* AND MAY BE USED ONLY BY DIRECT LICENSEES OF OSS NOKALVA, INC.             */
/* THIS FILE MAY NOT BE DISTRIBUTED.                                         */
/* THIS COPYRIGHT STATEMENT MAY NOT BE REMOVED.                              */
/* THIS SAMPLE PROGRAM IS PROVIDED AS IS. THE SAMPLE PROGRAM AND ANY RESULTS */
/* OBTAINED FROM IT ARE PROVIDED WITHOUT ANY WARRANTIES OR REPRESENTATIONS,  */
/* EXPRESS, IMPLIED OR STATUTORY.                                            */
/*****************************************************************************/


/*
 * Demonstrates CAM and DENM PDUs creating, encoding, decoding
 * and further processing.
 */

#include "camdenm.h"

#define currentVersion		1

static CAM * create_CAM_value()
{
    CAM *cam_msg = new CAM();

    ItsPduHeader header(currentVersion, messageID_cam, 1234567);
    cam_msg->set_header(header);

    PosConfidenceEllipse positionConfidenceEllipse(500, 400, wgs84North);
    Altitude altitude(2000, alt_000_02);
    ReferencePosition referencePosition(40487111, 79494789, positionConfidenceEllipse, altitude);
    BasicContainer basicContainer(passengerCar, referencePosition);

    Heading heading(wgs84North, equalOrWithinZeroPointOneDegree);
    Speed speed(2000, 1);
    VehicleLength length(35, noTrailerPresent);
    LongitudinalAcceleration longitudinalAcceleration(10, pointOneMeterPerSecSquared);
    Curvature curvature(CurvatureValue_straight, onePerMeter_0_00002);
    YawRate yawrate(YawRateValue_straight, degSec_000_01);
    unsigned char accCtl_val = 0x80 >> gasPedalEngaged;
    OssBitString accCtl(7, &accCtl_val);
    SteeringWheelAngle steeringWheelAngle(30, equalOrWithinOnePointFiveDegree);
    LateralAcceleration lAcc(-2, pointOneMeterPerSecSquared);
    VerticalAcceleration vAcc(pointOneMeterPerSecSquaredUp, pointOneMeterPerSecSquared);
    CenDsrcTollingZone cenDsrcTollingZone;

    HighFrequencyContainer highFrequencyContainer;
    BasicVehicleContainerHighFrequency basicVehicleContainerHighFrequency(heading, speed, forward, length,
						20, longitudinalAcceleration, curvature, yawRateUsed, yawrate);

    basicVehicleContainerHighFrequency.set_accelerationControl(accCtl);
    basicVehicleContainerHighFrequency.set_steeringWheelAngle(steeringWheelAngle);
    basicVehicleContainerHighFrequency.set_lateralAcceleration(lAcc);
    basicVehicleContainerHighFrequency.set_verticalAcceleration(vAcc);

    highFrequencyContainer.set_basicVehicleContainerHighFrequency(basicVehicleContainerHighFrequency);

    LowFrequencyContainer lowFrequencyContainer;
    unsigned char lights_val = (0x80 >> lowBeamHeadlightsOn) |
				 (0x80 >> leftTurnSignalOn) |
				 (0x80 >> daytimeRunningLightsOn);
    OssBitString lights(8, &lights_val);
    DeltaReferencePosition pathPosition(10000, 5000, DeltaAltitude_unavailable);
    PathPoint pathPoint(pathPosition, 1000);
    PathHistory pathHistory;
    pathHistory.prepend(pathPoint);

    BasicVehicleContainerLowFrequency basicVehicleContainerLowFrequency(VehicleRole_default, lights, pathHistory);
    lowFrequencyContainer.set_basicVehicleContainerLowFrequency(basicVehicleContainerLowFrequency);

    SpecialVehicleContainer specialVehicleContainer;
    char _static_value6[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};

    OssString ptActivationData(6, _static_value6);
    PtActivation ptActivation(undefinedCodingType, ptActivationData);
    PublicTransportContainer publicTransportContainer(FALSE, ptActivation);
    specialVehicleContainer.set_publicTransportContainer(publicTransportContainer);

    CamParameters camParameters(basicContainer, highFrequencyContainer, lowFrequencyContainer, specialVehicleContainer);
    CoopAwareness cam(11409, camParameters);
    cam_msg->set_cam(cam);

    return cam_msg;
}

static const char *get_messageID(unsigned short id)
{
    static char value[16];

    switch (id) {
	case messageID_denm: return "denm";
	case messageID_cam:  return "cam";
	case poi:            return "poi";
	case spatem:         return "spatem";
	case mapem:          return "mapem";
	case ivim:           return "ivim";
	case ev_rsr:         return "ev-rsr";
	case tistpgtransaction: return "tistpgtransaction";
	case srem:   	     return "srem";
	case ssem:           return "ssem";
	case evcsn:          return "evcsn";
	case saem:           return "saem";
	case rtcmem:         return "rtcmem";
	default:
	    sprintf(value, "%d", id);
    }
    return value;
}

static const char *get_stationType(StationType stype)
{
    static char value[16];

    switch (stype) {
        case unknown:         return "unknown";
        case pedestrian:      return "pedestrian";
        case cyclist:         return "cyclist";
        case moped:           return "moped";
        case motorcycle:      return "motorcycle";
        case passengerCar:    return "passengerCar";
        case bus:             return "bus";
        case lightTruck:      return "lightTruck";
        case heavyTruck:      return "heavyTruck";
        case trailer:         return "trailer";
        case specialVehicles: return "specialVehicles";
        case tram:            return "tram";
	case roadSideUnit:    return "roadSideUnit";
	default:
	    sprintf(value, "%d", stype);
    }
    return value;
}

static void print_Position(Latitude latitude, Longitude longitude,
			    AltitudeValue altitudeValue)
{
    const char *_valueName = NULL;

    printf("(");
    switch (latitude) {
    case Latitude_oneMicrodegreeNorth:
	_valueName = "oneMicrodegreeNorth";
	break;
    case Latitude_oneMicrodegreeSouth:
	_valueName = "oneMicrodegreeSouth";
	break;
    case Latitude_unavailable:
	_valueName = "unavailable";
	break;
    default:
	printf("%d.%06d", latitude / 1000000, abs(latitude % 1000000));
    }
    if (_valueName)
	printf("%s", _valueName);

    _valueName = NULL;
    printf(", ");
    switch (longitude) {
    case Longitude_oneMicrodegreeEast:
	_valueName = "oneMicrodegreeEast";
	break;
    case Longitude_oneMicrodegreeWest:
	_valueName = "oneMicrodegreeWest";
	break;
    case Longitude_unavailable:
	_valueName = "unavailable";
	break;
    default:
	printf("%d.%06d", longitude / 1000000, abs(longitude % 1000000));
    }
    if (_valueName)
	printf("%s", _valueName);

    _valueName = NULL;
    printf("), alt ");
    switch (altitudeValue) {
    case referenceEllipsoidSurface:
	_valueName = "referenceEllipsoidSurface";
	break;
    case AltitudeValue_oneCentimeter:
	_valueName = "oneCentimeter";
	break;
    case AltitudeValue_unavailable:
	_valueName = "unavailable";
	break;
    default:
	printf("%d.%02d m", altitudeValue / 100, abs(altitudeValue % 100));
    }
    if (_valueName)
	printf("%s", _valueName);
    printf("\n");
}

static const char *get_SpeedValue(SpeedValue val)
{
    static char value[16];

    switch (val) {
	case standstill:		return "standstill";
	case oneCentimeterPerSec:	return "oneCentimeterPerSec";
	case SpeedValue_unavailable:	return "unavailable";
	default:
	    sprintf(value, "%d", val);
    }
    return value;
}

static void print_some_CAM_fields(const CAM *cam)
{
    printf("messageID: %s\n", get_messageID(cam->get_header().get_messageID()));
    printf("stationID: %u\n", cam->get_header().get_stationID());
    printf("generationDeltaTime: %d\n", cam->get_cam().get_generationDeltaTime());
    const BasicContainer & basicContainer = cam->get_cam().get_camParameters().get_basicContainer();
    printf("stationType: %s\n", get_stationType(basicContainer.get_stationType()));
    printf("referencePosition: ");
    const ReferencePosition & referencePosition = basicContainer.get_referencePosition();
    print_Position(referencePosition.get_latitude(),
			referencePosition.get_longitude(),
			referencePosition.get_altitude().get_altitudeValue());
    HighFrequencyContainer highFrequencyContainer =
		cam->get_cam().get_camParameters().get_highFrequencyContainer();
    BasicVehicleContainerHighFrequency *basicVehicleContainerHighFrequency =
		highFrequencyContainer.get_basicVehicleContainerHighFrequency();
    if (basicVehicleContainerHighFrequency) {
	Speed speed = basicVehicleContainerHighFrequency->get_speed();
	printf("speedValue: %s\n", get_SpeedValue(speed.get_speedValue()));
    }
}

static DENM *create_DENM_value()
{
    DENM *denm_msg = new DENM;

    ItsPduHeader header(currentVersion, messageID_denm, 1234567);
    denm_msg->set_header(header);

    DecentralizedEnvironmentalNotificationMessage denm;
    ActionID actionID(20, 30);

    PosConfidenceEllipse positionConfidenceEllipse(500, 400, 10);
    Altitude altitude(2000, alt_000_02);
    ReferencePosition eventPosition(40487111, -79494789, positionConfidenceEllipse, altitude);

    ManagementContainer management;
    management.set_actionID(actionID);
    management.set_detectionTime(45000000000ULL);
    management.set_referenceTime(oneMillisecAfterUTCStartOf2004);
    management.set_eventPosition(eventPosition);
    management.set_validityDuration(600);
    management.set_transmissionInterval(oneMilliSecond);

    denm.set_management(management);

    CauseCode causeCode(roadworks, 0);
    SituationContainer situation(lowest, causeCode);
    denm.set_situation(situation);

    Speed eventSpeed(standstill, equalOrWithinOneCentimeterPerSec);
    Heading eventPositionHeading(wgs84North, equalOrWithinOneDegree);
    LocationContainer location;
    location.set_eventSpeed(eventSpeed);
    location.set_eventPositionHeading(eventPositionHeading);
    location.set_roadType(urban_NoStructuralSeparationToOppositeLanes);

    Traces traces;
    DeltaReferencePosition pathPosition(20, 20, DeltaAltitude_unavailable);
    PathPoint pathPoint(pathPosition, tenMilliSecondsInPast);

    DeltaReferencePosition pathPosition2(22, 22, DeltaAltitude_unavailable);
    PathPoint pathPoint2(pathPosition2);

    PathHistory pathHistory;
    pathHistory.prepend(pathPoint2);
    pathHistory.prepend(pathPoint);

    traces.prepend(pathHistory);
    location.set_traces(traces);
    denm.set_location(location);

    AlacarteContainer alacarte;
    PositionOfPillars positionOfPillars;
    positionOfPillars.prepend(PosPillar_tenCentimeters);
    unsigned char occupants[3];
    occupants[0] = (0x80 >> row1LeftOccupied) |
			(0x80 >> row1RightOccupied) |
			(0x80 >> row1MidOccupied) |
			(0x80 >> row1NotDetectable) |
			(0x80 >> row1NotPresent) |
			(0x80 >> row2LeftOccupied) |
			(0x80 >> row2RightOccupied);
    occupants[1] = 0x80 >> (row3NotPresent % 8);
    occupants[2] = 0x80 >> (row4NotPresent % 8);
    PositionOfOccupants positionOfOccupants(20, occupants);
    ImpactReductionContainer impactReduction(HeightLonCarr_oneCentimeter, HeightLonCarr_oneCentimeter,
						PosLonCarr_oneCentimeter, PosLonCarr_oneCentimeter,
						positionOfPillars, PosCentMass_unavailable,
						WheelBaseVehicle_tenCentimeters, point4Meters,
						PosFrontAx_tenCentimeters, positionOfOccupants,
						20, response);

    unsigned char lightBarVal = (0x80 >> lightBarActivated) | (0x80 >> sirenActivated);
    OssBitString lightBarSirenInUse(2, &lightBarVal);

    ClosedLanes closedLanes;
    closedLanes.set_outerhardShoulderStatus(availableForStopping);
    unsigned char drivingLaneVal = (0x80 >> 0) | (0x80 >> 1);
    DrivingLaneStatus drivingLaneStatus(3, &drivingLaneVal);
    closedLanes.set_drivingLaneStatus(drivingLaneStatus);

    RestrictedTypes restriction;
    restriction.prepend(unknown);
    CauseCode incidentIndication(reserved, 0);

    PosConfidenceEllipse itineraryPositionConfidenceEllipse(SemiAxisLength_oneCentimeter,
						SemiAxisLength_oneCentimeter, wgs84North);
    Altitude itineraryAltitude(200, alt_000_02);
    ReferencePosition itineraryPathPosition(20, 20,
					itineraryPositionConfidenceEllipse, itineraryAltitude);
    ItineraryPath recommendedPath;
    recommendedPath.prepend(itineraryPathPosition);
    RoadWorksContainerExtended roadWorks;
    roadWorks.set_lightBarSirenInUse(lightBarSirenInUse);
    roadWorks.set_closedLanes(closedLanes);
    roadWorks.set_restriction(restriction);
    roadWorks.set_speedLimit(20);
    roadWorks.set_incidentIndication(incidentIndication);
    roadWorks.set_recommendedPath(recommendedPath);

    StationaryVehicleContainer stationaryVehicle;
    stationaryVehicle.set_stationarySince(equalOrGreater15Minutes);
    stationaryVehicle.set_numberOfOccupants(30);
    CauseCode stationaryCause(roadworks, 0);
    stationaryVehicle.set_stationaryCause(stationaryCause);
    unsigned char energyStorVal = 0x80 >> gasoline;
    OssBitString energyStorageType(6, &energyStorVal);
    stationaryVehicle.set_energyStorageType(energyStorageType);

    VehicleIdentification vehicleIdentification("WVW", "ZZZ1JZ");
    stationaryVehicle.set_vehicleIdentification(vehicleIdentification);

    alacarte.set_impactReduction(impactReduction);
    alacarte.set_externalTemperature(oneDegreeCelsius);
    alacarte.set_positioningSolution(noPositioningSolution);
    alacarte.set_roadWorks(roadWorks);
    alacarte.set_stationaryVehicle(stationaryVehicle);

    denm.set_alacarte(alacarte);
    denm_msg->set_denm(denm);

    return denm_msg;
}

static const char *get_CauseCode(CauseCodeType _causeCode)
{
    static	char	str[16];

    switch (_causeCode) {
	case reserved: return "reserved";
	case trafficCondition: return "trafficCondition";
	case accident: return "accident";
	case roadworks: return "roadworks";
	case adverseWeatherCondition_Adhesion: return "adverseWeatherCondition-Adhesion";
	case hazardousLocation_SurfaceCondition: return "hazardousLocation-SurfaceCondition";
	case hazardousLocation_ObstacleOnTheRoad: return "hazardousLocation-ObstacleOnTheRoad";
	case hazardousLocation_AnimalOnTheRoad: return "hazardousLocation-AnimalOnTheRoad";
	case humanPresenceOnTheRoad: return "humanPresenceOnTheRoad";
	case wrongWayDriving: return "wrongWayDriving";
	case rescueAndRecoveryWorkInProgress: return "rescueAndRecoveryWorkInProgress";
	case adverseWeatherCondition_ExtremeWeatherCondition: return "adverseWeatherCondition-ExtremeWeatherCondition";
	case adverseWeatherCondition_Visibility: return "adverseWeatherCondition-Visibility";
	case adverseWeatherCondition_Precipitation: return "adverseWeatherCondition-Precipitation";
	case slowVehicle: return "slowVehicle";
	case dangerousEndOfQueue: return "dangerousEndOfQueue";
	case vehicleBreakdown: return "vehicleBreakdown";
	case postCrash: return "postCrash";
	case humanProblem: return "humanProblem";
	case CauseCodeType_stationaryVehicle: return "stationaryVehicle";
	case emergencyVehicleApproaching: return "emergencyVehicleApproaching";
	case hazardousLocation_DangerousCurve: return "hazardousLocation-DangerousCurve";
	case collisionRisk: return "collisionRisk";
	case signalViolation: return "signalViolation";
	case dangerousSituation: return "dangerousSituation";
	default:
    	    sprintf(str, "%u", _causeCode);
    }
    return str;
}

static void print_some_DENM_fields(const DENM *denm)
{
    printf("messageID: %s\n", get_messageID(denm->get_header().get_messageID()));
    printf("stationID: %u\n", denm->get_header().get_stationID());

    const ManagementContainer & managementContainer = denm->get_denm().get_management();
    printf("eventPosition: ");
    const ReferencePosition & referencePosition = managementContainer.get_eventPosition();
    print_Position(referencePosition.get_latitude(),
			referencePosition.get_longitude(),
			referencePosition.get_altitude().get_altitudeValue());

    const SituationContainer * situation =  denm->get_denm().get_situation();
    if (situation) {
	printf("causeCode: %s\n", get_CauseCode(situation->get_eventType().get_causeCode()));
    } else {
	printf("causeCode omitted.\n");
    }
}

/*
 * Main application routine
 */
int main()
{
    int retcode;
    CAM *cam = NULL;
    DENM *denm = NULL;

    try {
	ITS_Container_Control ctl;
        CAM_PDU cam_pdu;
	CAM_PDU cam_pdu2;
	EncodedBuffer encodedData;  /* encoded data */

	/* Set the encoding rules and encoding/decoding flags */
	ctl.setEncodingRules(OSS_PER_UNALIGNED);
	ctl.setEncodingFlags(AUTOMATIC_ENCDEC | STRICT_PER_ENCODING_OF_DEFAULT_VALUES);
	ctl.setDecodingFlags(AUTOMATIC_ENCDEC);
	ctl.setDebugFlags(PRINT_ERROR_MESSAGES | PRINT_DECODING_DETAILS |
		PRINT_ENCODING_DETAILS);

	/* ==== Part 1. Create, encode and decode CAM message ==== */
	printf("\nCreating a CAM PDU value... ");

	cam = create_CAM_value();

	printf("Done\n");

	/*
	 * Set the data to the coding container.
	 */
	cam_pdu.set_data(*cam);

	/*
	 * Print the input to the encoder.
	 */
	printf("\nPrinting the created value with CAM_PDU::print() ...\n");
	cam_pdu.print(ctl);

	/*
	 * Perform the encoding.
	 */
	printf("\nEncoding the created CAM value... ");
	cam_pdu.encode(ctl, encodedData);
	printf("Done\n");

	/*
	 * Print encoded message.
	 */
	printf("\nEncoded CAM message:\n");
	encodedData.print_hex(ctl);

	/*
	 * Decode previously encoded message.
	 */
	printf("\nDecoding the encoded CAM message... ");
	cam_pdu2.decode(ctl, encodedData);
	printf("Done\n");

	/*
	 * Check to see that the PDU was decoded properly by comparing it
	 * with the value generated by the ASN.1 compiler from the value
	 * notation present in the ASN.1 syntax.
	 */
	printf("\nComparing the decoded message with the original PDU value... ");
	if (cam_pdu.equals(ctl, cam_pdu2))
	    printf("Succeeded\n");
	else
	    printf("Failed\n");

	printf("\nPartial custom printing of the decoded CAM PDU:\n\n");
	print_some_CAM_fields(cam_pdu2.get_data());

	/*
	 * Release memory for buffer re-use
	 */
	asn1Free(encodedData.release_data());

	/* Free the decoded input message */
	cam_pdu2.free_data(ctl);


	/* ==== Part 2. Create, encode and decode DENM message ==== */
        DENM_PDU denm_pdu;
        DENM_PDU denm_pdu2;

	printf("\nCreating a DENM PDU value... ");

	denm = create_DENM_value();

	printf("Done\n");

	/*
	 * Set the data to the coding container.
	 */
	denm_pdu.set_data(*denm);

	/*
	 * Print the input to the encoder.
	 */
	printf("\nPrinting the created value with DENM_PDU::print() ...\n");
	denm_pdu.print(ctl);

	/*
	 * Perform the encoding.
	 */
	printf("\nEncoding the created DENM value... ");
	denm_pdu.encode(ctl, encodedData);
	printf("Done\n");

	/*
	 * Print encoded message.
	 */
	printf("\nEncoded DENM message:\n");
	encodedData.print_hex(ctl);

	/*
	 * Decode previously encoded message.
	 */
	printf("\nDecoding the encoded DENM message... ");
	denm_pdu2.decode(ctl, encodedData);
	printf("Done\n");

	/*
	 * Check to see that the PDU was decoded properly by comparing it
	 * with the value generated by the ASN.1 compiler from the value
	 * notation present in the ASN.1 syntax.
	 */
	printf("\nComparing the decoded message with the original PDU value... ");
	if (denm_pdu.equals(ctl, denm_pdu2))
	    printf("Succeeded\n");
	else
	    printf("Failed\n");

	printf("\nPartial custom printing of the decoded DENM PDU:\n\n");
	print_some_DENM_fields(denm_pdu2.get_data());

	retcode = 0;
	/* Free the decoded input message */
	denm_pdu2.free_data(ctl);
    } catch (ASN1RuntimeException &exc) {
        retcode = exc.get_code();
	printf("An error occurred: code = %d.\n", retcode);
    } catch (...) {
	printf("An unexpected exception occurred.\n");
	retcode =  -1;
    }

    delete cam;
    delete denm;

    return retcode;
}

Expected Output (Excerpt)

This is the expected output when running the sample:

Created CAM message
Encoding successful
Decoding successful
... printed CAM message ...

Created DENM message
Encoding successful
Decoding successful
... printed DENM message ...

ASN.1 Schema Excerpt (CAM.asn)

Show excerpt from CAM.asn
-- Excerpt from ETSI EN 302 637-2 V1.4.1 (2019-04)

CAM-PDU-Descriptions {itu-t (0) identified-organization (4) etsi (0) itsDomain (5) 
 wg1 (1) en (302637) cam (2) version (2)}
DEFINITIONS AUTOMATIC TAGS ::=
BEGIN

    IMPORTS
        ItsPduHeader, CauseCode, ReferencePosition, AccelerationControl, Curvature,
        CurvatureCalculationMode, Heading, LanePosition, EmergencyPriority, EmbarkationStatus, Speed,
        DriveDirection, LongitudinalAcceleration, LateralAcceleration, VerticalAcceleration, StationType,
        ExteriorLights, DangerousGoodsBasic, SpecialTransportType, LightBarSirenInUse, VehicleRole,
        VehicleLength, VehicleWidth, PathHistory, RoadworksSubCauseCode, ClosedLanes, TrafficRule,
        SpeedLimit, SteeringWheelAngle, PerformanceClass, YawRate, ProtectedCommunicationZone, PtActivation,
        Latitude, Longitude, ProtectedCommunicationZonesRSU, CenDsrcTollingZone 
    FROM ITS-Container {itu-t (0) identified-organization (4) etsi (0) 
        itsDomain (5) wg1 (1) ts (102894) cdd (2) version (2)};

    -- The root data frame for cooperative awareness messages
    CAM ::= SEQUENCE {
        header ItsPduHeader,
        cam CoopAwareness
    }

    CoopAwareness ::= SEQUENCE {
        generationDeltaTime GenerationDeltaTime,
        camParameters CamParameters
    }

    CamParameters ::= SEQUENCE {
        basicContainer BasicContainer,
        highFrequencyContainer HighFrequencyContainer,
        lowFrequencyContainer LowFrequencyContainer OPTIONAL,
        specialVehicleContainer SpecialVehicleContainer OPTIONAL,
        ...
    }

    HighFrequencyContainer ::= CHOICE {
        basicVehicleContainerHighFrequency BasicVehicleContainerHighFrequency,
        rsuContainerHighFrequency RSUContainerHighFrequency,
        ...
    }

    LowFrequencyContainer ::= CHOICE {
        basicVehicleContainerLowFrequency BasicVehicleContainerLowFrequency,
        ...
    }

    SpecialVehicleContainer ::= CHOICE {
        publicTransportContainer PublicTransportContainer,
        specialTransportContainer SpecialTransportContainer,
        dangerousGoodsContainer DangerousGoodsContainer,
        roadWorksContainerBasic RoadWorksContainerBasic,
        rescueContainer RescueContainer,
        emergencyContainer EmergencyContainer,
        safetyCarContainer SafetyCarContainer,
        ...
    }

    BasicContainer ::= SEQUENCE {
        stationType StationType,
        referencePosition ReferencePosition,
        ... 
    }

    BasicVehicleContainerHighFrequency ::= SEQUENCE {
        heading Heading,
        speed Speed,
        driveDirection DriveDirection,
        vehicleLength VehicleLength,
        vehicleWidth VehicleWidth,
        longitudinalAcceleration LongitudinalAcceleration,
        curvature Curvature,
        curvatureCalculationMode CurvatureCalculationMode,
        yawRate YawRate,
        accelerationControl AccelerationControl OPTIONAL,
        lanePosition LanePosition OPTIONAL,
        steeringWheelAngle SteeringWheelAngle OPTIONAL,
        lateralAcceleration LateralAcceleration OPTIONAL,
        verticalAcceleration VerticalAcceleration OPTIONAL,
        performanceClass PerformanceClass OPTIONAL,
        cenDsrcTollingZone CenDsrcTollingZone OPTIONAL
    }

Using ASN.1 Studio (Optional)

The gui/ subdirectory contains an ASN.1 Studio project for this sample. With ASN.1 Studio you can:

  • Open the CAM and DENM ASN.1 modules.
  • Generate code from the ASN.1 schema.
  • Create and edit sample encoded CAM and DENM messages.
  • Export projects to gmake makefiles.

Related Samples

Disclaimer

This sample is provided solely for illustration purposes, for example to demonstrate usage of the OSS ASN.1 Tools API with CAM and DENM messages. It does not represent a complete application. To build and run this sample, you must use a trial or licensed version of the appropriate OSS ASN.1 Tools. The copyright and license statements included in each source file remain fully applicable.

Need Help?

If you have questions about using this sample, contact OSS Nokalva Support.

See Also