CAM/DENM Java 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 Unix shell script (run.sh) is included for running the test program using the OSS ASN.1/Java 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/Java runtime for the CAM and DENM schemas.
  • Create CAM and DENM messages.
  • Encode CAM and DENM messages.
  • Decode encoded messages.
  • Print decoded message contents.
  • Run the sample test program using the provided run.sh script.

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.java Simple Java program that demonstrates creating, encoding, decoding, and printing CAM and DENM messages.
camdenm.cmd ASN.1 compiler command file used to ASN.1-compile the CAM and DENM protocol specifications.
run.sh Unix shell script that runs the test.
gui/ ASN.1 Studio project for viewing/compiling schema and generating sample data.
sample.out Expected output from this test.

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 Java.

1. Verify environment variables

Before running the test, ensure the following are set appropriately:

  • OSS_ASN1_JAVA
  • CLASSPATH
  • PATH
2. Run the sample
./run.sh
3. Clean up generated files
./run.sh cleanup
4. Other Platforms

Note: The Java 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.java

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

Show Tcamdenm.java 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.                                            */
/*****************************************************************************/

import camdenm.Camdenm;
import camdenm.cam_pdu_descriptions.BasicContainer;
import camdenm.cam_pdu_descriptions.BasicVehicleContainerHighFrequency;
import camdenm.cam_pdu_descriptions.BasicVehicleContainerLowFrequency;
import camdenm.cam_pdu_descriptions.CAM;
import camdenm.cam_pdu_descriptions.CamParameters;
import camdenm.cam_pdu_descriptions.CoopAwareness;
import camdenm.cam_pdu_descriptions.GenerationDeltaTime;
import camdenm.cam_pdu_descriptions.HighFrequencyContainer;
import camdenm.cam_pdu_descriptions.LowFrequencyContainer;
import camdenm.cam_pdu_descriptions.PublicTransportContainer;
import camdenm.cam_pdu_descriptions.SpecialVehicleContainer;

import camdenm.denm_pdu_descriptions.AlacarteContainer;
import camdenm.denm_pdu_descriptions.DENM;
import camdenm.denm_pdu_descriptions.DecentralizedEnvironmentalNotificationMessage;
import camdenm.denm_pdu_descriptions.ImpactReductionContainer;
import camdenm.denm_pdu_descriptions.LocationContainer;
import camdenm.denm_pdu_descriptions.ManagementContainer;
import camdenm.denm_pdu_descriptions.RoadWorksContainerExtended;
import camdenm.denm_pdu_descriptions.SituationContainer;
import camdenm.denm_pdu_descriptions.StationaryVehicleContainer;
import camdenm.denm_pdu_descriptions.Termination;

import camdenm.its_container.ItsPduHeader.MessageID;
import camdenm.its_container.*;

import com.oss.asn1.PERUnalignedCoder;

import com.oss.util.HexTool;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/*
 * Demonstrates work with data for CAM and DENM protocols.
 */
public class Tcamdenm {
    /*
     * Demonstrates CAM and DENM PDUs creating, encoding, decoding
     * and further processing.
     */
    public static void main(String[] args) throws java.io.FileNotFoundException, Exception
    {
	// Initialize the project
	try {
	    Camdenm.initialize();
	} catch (Exception e) {
	    System.out.println("Initialization exception: " + e);
	    System.exit(1);
	}

        // Instantiate the coder
	PERUnalignedCoder coder = Camdenm.getPERUnalignedCoder();

        // Part 1. Create, encode and decode the CAM message

        System.out.printf("\nCreating the CAM PDU value... ");
        CAM cam = createCAMValue();
        System.out.printf("Done\n");
        System.out.printf("\nPrinting the value in the ASN.1 value notation...\n");
        System.out.println(cam);
        // Encode the value
        byte[] cam_encoding = null;
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            System.out.printf("\nEncoding the created CAM value... ");
            coder.encode(cam, baos);
            cam_encoding = baos.toByteArray();
            System.out.printf("Done\n");
            System.out.printf("\nEncoded CAM message:\n");
            HexTool.printHex(cam_encoding);
        } catch (Exception e) {
	    System.out.println("Encoding of CAM message has failed: " + e);
	    System.exit(1);
        }
        // Decode the sample CAM message
        CAM cam_decoded = null;
        try (ByteArrayInputStream bais = new ByteArrayInputStream(cam_encoding)) {
            System.out.printf("\nDecoding the encoded CAM message... ");
            cam_decoded = (CAM)coder.decode(bais, new CAM());
            System.out.printf("Done\n");
        } catch (Exception e) {
	    System.out.println("Decoding of CAM message has failed: " + e);
	    System.exit(2);
        }
        System.out.printf("\nComparing the decoded message with the original PDU value... ");
        if (cam.equals(cam_decoded))
            System.out.printf("Succeeded\n");
        else
            System.out.printf("Failed\n");

        System.out.printf("\nPartial custom printing of the decoded CAM PDU:\n\n");
        printSelectedCAMFields(cam_decoded);

        // Part 2. Create, encode and decode the DENM message

        System.out.printf("\nCreating the DENM PDU value... ");
        DENM denm = createDENMValue();
        System.out.printf("Done\n");
        System.out.printf("\nPrinting the value in the ASN.1 value notation...\n");
        System.out.println(denm);
        // Encode the value
        byte[] denm_encoding = null;
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            System.out.printf("\nEncoding the created DENM value... ");
            coder.encode(denm, baos);
            denm_encoding = baos.toByteArray();
            System.out.printf("Done\n");
            System.out.printf("\nEncoded DENM message:\n");
            HexTool.printHex(denm_encoding);
        } catch (Exception e) {
	    System.out.println("Encoding of DENM message has failed: " + e);
	    System.exit(1);
        }
        // Decode the sample DENM message
        DENM denm_decoded = null;
        try (ByteArrayInputStream bais = new ByteArrayInputStream(denm_encoding)) {
            System.out.printf("\nDecoding the encoded DENM message... ");
            denm_decoded = (DENM)coder.decode(bais, new DENM());
            System.out.printf("Done\n");
        } catch (Exception e) {
	    System.out.println("Decoding of DENM message has failed: " + e);
	    System.exit(2);
        }
        System.out.printf("\nComparing the decoded message with the original PDU value... ");
        if (denm.equals(denm_decoded))
            System.out.printf("Succeeded\n");
        else
            System.out.printf("Failed\n");

        System.out.printf("\nPartial custom printing of the decoded DENM PDU:\n\n");
        printSelectedDENMFields(denm_decoded);
    }

    // Creates the mock CAM PDU.
    private static CAM createCAMValue() {
        // Construct the ItsPduHeader
        ItsPduHeader itsPduHeader = new ItsPduHeader(
            1,
            ItsPduHeader.MessageID.cam,
            new StationID(1234567));
        // Begin the construction of the CoopAwareness
        CoopAwareness cam;
        {
            // Construct the GenerationDeltaTime
            GenerationDeltaTime generationDeltaTime = new GenerationDeltaTime(11409);
            // Begin the construction of the CamParameters
            CamParameters camParameters;
            {
                BasicContainer basicContainer;
                // Begin the construction of the BasicContainer
                {
                    ReferencePosition referencePosition;
                    // Begin the construction of the ReferencePosition
                    {
                        PosConfidenceEllipse posConfidenceEllipse =
                            new PosConfidenceEllipse(
                                new SemiAxisLength(500),
                                new SemiAxisLength(400),
                                HeadingValue.wgs84North);
                        Altitude altitude = new Altitude(
                            new AltitudeValue(2000),
                            AltitudeConfidence.alt_000_02);
                        referencePosition = new ReferencePosition(
                            new Latitude(40487111),
                            new Longitude(79494789),
                            posConfidenceEllipse,
                            altitude);
                    } // Done with the construction of the ReferencePosition
                    basicContainer = new BasicContainer(
                        StationType.passengerCar,
                        referencePosition);
                } // Done with the construction of the BasicContainer
                HighFrequencyContainer highFrequencyContainer;
                // Begin the construction of the HighFrequencyContainer
                {
                    BasicVehicleContainerHighFrequency basicVehicleContainerHighFrequency;
                    // Begin the construction of the BasicVehicleContainerHighFrequency
                    {
                        basicVehicleContainerHighFrequency = new BasicVehicleContainerHighFrequency(
                            new Heading(
                                HeadingValue.wgs84North,
                                HeadingConfidence.equalOrWithinZeroPointOneDegree),
                            new Speed(
                                new SpeedValue(2000),
                                SpeedConfidence.equalOrWithinOneCentimeterPerSec),
                            DriveDirection.forward,
                            new VehicleLength(
                                new VehicleLengthValue(35),
                                VehicleLengthConfidenceIndication.noTrailerPresent),
                            new VehicleWidth(20),
                            new LongitudinalAcceleration(
                                new LongitudinalAccelerationValue(10),
                                AccelerationConfidence.pointOneMeterPerSecSquared),
                            new Curvature(
                                CurvatureValue.straight,
                                CurvatureConfidence.onePerMeter_0_00002),
                            CurvatureCalculationMode.yawRateUsed,
                            new YawRate(
                                YawRateValue.straight,
                                YawRateConfidence.degSec_000_01));
                        // Set particular optional components
                        // Acceleration control
                        AccelerationControl accelerationControl =
                            new AccelerationControl(new byte[1], 7);
                        accelerationControl.setBit(AccelerationControl.gasPedalEngaged);
                        basicVehicleContainerHighFrequency.accelerationControl = accelerationControl;
                        // SteeringWheelAngle
                        SteeringWheelAngle steeringWheelAngle = new SteeringWheelAngle(
                                new SteeringWheelAngleValue(30),
                                SteeringWheelAngleConfidence.equalOrWithinOnePointFiveDegree);
                        basicVehicleContainerHighFrequency.steeringWheelAngle = steeringWheelAngle;
                        // LateralAcceleration
                        LateralAcceleration lateralAcceleration = new LateralAcceleration(
                            new LateralAccelerationValue(-2),
                            AccelerationConfidence.pointOneMeterPerSecSquared);
                        basicVehicleContainerHighFrequency.lateralAcceleration = lateralAcceleration;
                        // VerticalAcceleration
                        VerticalAcceleration verticalAcceleration = new VerticalAcceleration(
                            VerticalAccelerationValue.pointOneMeterPerSecSquaredUp,
                            AccelerationConfidence.pointOneMeterPerSecSquared);
                        basicVehicleContainerHighFrequency.verticalAcceleration = verticalAcceleration;
                    } // Done with the construction of the BasicVehicleContainerHighFrequency
                    // Setup the HighFrequencyContainer (CHOICE) using the
                    // appropriate createHighFrequencyContainerWithXXX()
                    // factory method.
                    highFrequencyContainer =
                        HighFrequencyContainer.createHighFrequencyContainerWithBasicVehicleContainerHighFrequency(
                                basicVehicleContainerHighFrequency);
                } // Done with the construction of the HighFrequencyContainer
                // Begin the construction of the LowFrequencyContainer
                LowFrequencyContainer lowFrequencyContainer;
                {
                    lowFrequencyContainer = new LowFrequencyContainer();
                    BasicVehicleContainerLowFrequency basicVehicleContainerLowFrequency;
                    // Begin the construction of the BasicVehicleContainerLowFrequency
                    {
                        // Create the PathHistory list of one element
                        PathHistory pathHistory = new PathHistory();
                        pathHistory.add(new PathPoint(
                            new DeltaReferencePosition(
                                new DeltaLatitude(10000),
                                new DeltaLongitude(5000),
                                DeltaAltitude.unavailable),
                            new PathDeltaTime(1000)));
                        ExteriorLights exteriorLightts = new ExteriorLights(new byte[1], 8);
                        exteriorLightts.setBit(ExteriorLights.lowBeamHeadlightsOn);
                        exteriorLightts.setBit(ExteriorLights.leftTurnSignalOn);
                        exteriorLightts.setBit(ExteriorLights.daytimeRunningLightsOn);
                        basicVehicleContainerLowFrequency = new BasicVehicleContainerLowFrequency(
                            VehicleRole._default,
                            exteriorLightts,
                            pathHistory);
                    } // Done with the construction of the BasicVehicleContainerLowFrequency
                    // Alternative method to initialize the CHOICE (BasicVehicleContainerLowFrequency)
                    // is to invoke its setXXX() instance method for the corresponding alternative
                    lowFrequencyContainer.setBasicVehicleContainerLowFrequency(
                        basicVehicleContainerLowFrequency);
                } // Done with the construction of the LowFrequencyContainer
                // Begin the construction of the SpecialVehicleContainer
                SpecialVehicleContainer specialVehicleContainer;
                {
                    PublicTransportContainer publicTransportContainer =
                        new PublicTransportContainer(
                            new EmbarkationStatus(false),
                            new PtActivation(
                                PtActivationType.undefinedCodingType,
                                new PtActivationData(new byte[]{
                                    0x00, 0x11, 0x22, 0x33, 0x44, 0x55
                                })));
                    specialVehicleContainer =
                        SpecialVehicleContainer.createSpecialVehicleContainerWithPublicTransportContainer(
                            publicTransportContainer);
                } // Done with the construction of the SpecialVehicleContainer
                camParameters = new CamParameters(basicContainer,
                    highFrequencyContainer, lowFrequencyContainer, specialVehicleContainer);
            } // Done with the construction of the CamParameters
            cam = new CoopAwareness(generationDeltaTime, camParameters);
        } // Done with the construction of CoopAwareness
        // Create the CAM PDU and return it to the caller
        return new CAM(itsPduHeader, cam);
    }

    // Prints particular components of CAM PDU
    private static void printSelectedCAMFields(CAM pdu) {
        ItsPduHeader itsPduHeader = pdu.getHeader();
        System.out.printf("messageID: %s\n",
            messageIdToSTring(itsPduHeader.messageID));
        System.out.printf("stationID: %d\n", itsPduHeader.stationID.longValue());

        CoopAwareness cam = pdu.cam;
        GenerationDeltaTime generationDeltaTime = cam.getGenerationDeltaTime();

        System.out.printf("generationDeltaTime: ");
        if (generationDeltaTime.equals(GenerationDeltaTime.oneMilliSec))
            System.out.printf("oneMilliSec\n");
        else
            System.out.printf("%d\n", generationDeltaTime.longValue());

        BasicContainer basicContainer = cam.camParameters.basicContainer;
        System.out.printf("stationType: %s\n",
            stationTypeToString(basicContainer.stationType));

        System.out.printf("referencePosition: %s\n",
            positionToString(basicContainer.referencePosition));

        HighFrequencyContainer highFrequencyContainer =
            cam.camParameters.highFrequencyContainer;
        if (highFrequencyContainer.hasBasicVehicleContainerHighFrequency()) {
            BasicVehicleContainerHighFrequency basicVehicleContainerHighFrequency =
                highFrequencyContainer.getBasicVehicleContainerHighFrequency();
            System.out.printf("speedValue: %s\n",
                speedValueToString(basicVehicleContainerHighFrequency.speed.speedValue));
        } else {
            System.out.printf("printing of emptyRSUContainerHighFrequency is not supported\n");
        }
    }

    // Creates the mock DENM PDU
    private static DENM createDENMValue() {
        // Construct the ItsPduHeader
        ItsPduHeader itsPduHeader = new ItsPduHeader(
            1,
            MessageID.denm,
            new StationID(1234567));

        DecentralizedEnvironmentalNotificationMessage denm;
        // Begin the construction of the DecentralizedEnvironmentalNotificationMessage
        {
            ManagementContainer management;
            // Begin the construction of the ManagementContainer
            {
                ReferencePosition eventPosition = new ReferencePosition(
                    new Latitude(40487111),
                    new Longitude(-79494789),
                    new PosConfidenceEllipse(
                        new SemiAxisLength(500),
                        new SemiAxisLength(400),
                        new HeadingValue(10)),
                    new Altitude(
                        new AltitudeValue(2000),
                        AltitudeConfidence.alt_000_02));
                management = new ManagementContainer(
                    new ActionID(
                        new StationID(20),
                        new SequenceNumber(30)),
                    new TimestampIts(45000000000L),
                    TimestampIts.oneMillisecAfterUTCStartOf2004,
                    Termination.isCancellation,
                    eventPosition,
                    RelevanceDistance.lessThan100m,
                    RelevanceTrafficDirection.upstreamTraffic,
                    ValidityDuration.oneSecondAfterDetection,
                    TransmissionInterval.tenSeconds,
                    StationType.passengerCar);
                // Set the particular optional fields
                management.validityDuration = new ValidityDuration(600);
                management.transmissionInterval = TransmissionInterval.oneMilliSecond;
            } // Done with the construction of the ManagementContainer
            SituationContainer situation;
            // Begin the construction of the SituationContainer
            {
                situation = new SituationContainer(
                    InformationQuality.lowest,
                    new CauseCode(
                        CauseCodeType.roadworks,
                        new SubCauseCodeType(0)));
            } // Done with the construction of the SituationContainer
            LocationContainer location;
            // Begin the construction of the LocationContainer
            {
                Traces traces;
                // Begin the construction of the Traces
                {
                    // Create a PathHistory list of two elements
                    PathHistory pathHistory = new PathHistory();
                    pathHistory.add(new PathPoint(
                        new DeltaReferencePosition(
                            new DeltaLatitude(20),
                            new DeltaLongitude(20),
                            DeltaAltitude.unavailable),
                        PathDeltaTime.tenMilliSecondsInPast));
                    pathHistory.add(new PathPoint(
                        new DeltaReferencePosition(
                            new DeltaLatitude(22),
                            new DeltaLongitude(22),
                            DeltaAltitude.unavailable)));
                    traces = new Traces();
                    traces.add(pathHistory);
                } // Done with the construction of the Traces
                location = new LocationContainer(traces);
                // Set the particular optional fields
                location.roadType = RoadType.urban_NoStructuralSeparationToOppositeLanes;
                location.eventSpeed = new Speed(
                    SpeedValue.standstill,
                    SpeedConfidence.equalOrWithinOneCentimeterPerSec);
                location.eventPositionHeading = new Heading(
                    HeadingValue.wgs84North,
                    HeadingConfidence.equalOrWithinOneDegree);
            } // Done with the construction of the LocationContainer
            AlacarteContainer alacarte;
            // Begin the construction of the AlacarteContainer
            {
                alacarte = new AlacarteContainer();
                // Create a PositionOfPillars list of one element
                PositionOfPillars posOfPillars = new PositionOfPillars();
                posOfPillars.add(PosPillar.tenCentimeters);
                // Create the positionOfOccupants bit mask
                PositionOfOccupants positionOfOccupants =
                    new PositionOfOccupants(new byte[3], 20);
                positionOfOccupants.setBit(PositionOfOccupants.row1LeftOccupied);
                positionOfOccupants.setBit(PositionOfOccupants.row1RightOccupied);
                positionOfOccupants.setBit(PositionOfOccupants.row1MidOccupied);
                positionOfOccupants.setBit(PositionOfOccupants.row1NotDetectable);
                positionOfOccupants.setBit(PositionOfOccupants.row1NotPresent);
                positionOfOccupants.setBit(PositionOfOccupants.row2LeftOccupied);
                positionOfOccupants.setBit(PositionOfOccupants.row2RightOccupied);
                positionOfOccupants.setBit(PositionOfOccupants.row3NotPresent);
                positionOfOccupants.setBit(PositionOfOccupants.row4NotPresent);
                alacarte.impactReduction = new ImpactReductionContainer(
                    HeightLonCarr.oneCentimeter,
                    HeightLonCarr.oneCentimeter,
                    PosLonCarr.oneCentimeter,
                    PosLonCarr.oneCentimeter,
                    posOfPillars,
                    PosCentMass.unavailable,
                    WheelBaseVehicle.tenCentimeters,
                    TurningRadius.point4Meters,
                    PosFrontAx.tenCentimeters,
                    positionOfOccupants,
                    new VehicleMass(20),
                    RequestResponseIndication.response);
                alacarte.externalTemperature = Temperature.oneDegreeCelsius;
                alacarte.roadWorks = new RoadWorksContainerExtended();
                LightBarSirenInUse lightBarSirensInUse =
                    new LightBarSirenInUse(new byte[1], 2);
                lightBarSirensInUse.setBit(LightBarSirenInUse.lightBarActivated);
                lightBarSirensInUse.setBit(LightBarSirenInUse.sirenActivated);
                alacarte.roadWorks.lightBarSirenInUse = lightBarSirensInUse;
                DrivingLaneStatus drivingLaneStatus =
                    new DrivingLaneStatus(new byte[1], 3);
                drivingLaneStatus.setBit(0);
                drivingLaneStatus.setBit(1);
                alacarte.roadWorks.closedLanes = new ClosedLanes();
                alacarte.roadWorks.closedLanes.outerhardShoulderStatus =
                    HardShoulderStatus.availableForStopping;
                alacarte.roadWorks.closedLanes.drivingLaneStatus =
                    drivingLaneStatus;
                // Create a RestrictedTypes list of one element
                alacarte.roadWorks.restriction = new RestrictedTypes();
                alacarte.roadWorks.restriction.add(StationType.unknown);
                alacarte.roadWorks.speedLimit = new SpeedLimit(20);
                alacarte.roadWorks.incidentIndication = new CauseCode(
                    CauseCodeType.reserved, new SubCauseCodeType(0));
                // Create a ItineraryPath list of one element
                alacarte.roadWorks.recommendedPath = new ItineraryPath();
                alacarte.roadWorks.recommendedPath.add(
                    new ReferencePosition(
                        new Latitude(20),
                        new Longitude(20),
                        new PosConfidenceEllipse(
                            SemiAxisLength.oneCentimeter,
                            SemiAxisLength.oneCentimeter,
                            HeadingValue.wgs84North),
                        new Altitude(
                            new AltitudeValue(200),
                            AltitudeConfidence.alt_000_02)));
                alacarte.positioningSolution =
                    PositioningSolutionType.noPositioningSolution;
                alacarte.stationaryVehicle = new StationaryVehicleContainer();
                alacarte.stationaryVehicle.stationarySince =
                    StationarySince.equalOrGreater15Minutes;
                alacarte.stationaryVehicle.stationaryCause =
                    new CauseCode(CauseCodeType.roadworks,
                    new SubCauseCodeType(0));
                alacarte.stationaryVehicle.numberOfOccupants = new NumberOfOccupants(30);
                alacarte.stationaryVehicle.vehicleIdentification =
                    new VehicleIdentification(
                        new WMInumber("WVW"),
                        new VDS("ZZZ1JZ"));
                EnergyStorageType energyStorageType = new EnergyStorageType(
                    new byte[1], 7);
                energyStorageType.setBit(EnergyStorageType.gasoline);
                alacarte.stationaryVehicle.energyStorageType =
                    energyStorageType;
            } // Done with the construction of the AlacarteContainer
            denm = new DecentralizedEnvironmentalNotificationMessage(
                management,
                situation,
                location,
                alacarte);
        } // Done with the construction of the DecentralizedEnvironmentalNotificationMessage
        // Create the DENM PDU and return it to the caller
        return new DENM(itsPduHeader, denm);
    }

    private static void printSelectedDENMFields(DENM pdu) {
        ItsPduHeader itsPduHeader = pdu.getHeader();
        System.out.printf("messageID: %s\n",
            messageIdToSTring(itsPduHeader.messageID));
        System.out.printf("stationID: %d\n", itsPduHeader.stationID.longValue());

        ManagementContainer managementContainer = pdu.denm.management;
        System.out.printf("eventPosition: %s\n",
            positionToString(managementContainer.eventPosition));
        if (pdu.denm.hasSituation()) {
            System.out.printf("causeCode: %s\n",
                causeCodeToString(pdu.denm.situation.eventType.causeCode));
        } else {
            System.out.printf("causeCode omitted.\n");
        }
    }

    // Formats the value of the MessageID
    private static String messageIdToSTring(ItsPduHeader.MessageID messageID) {
//                messageID INTEGER{ denm(1), cam(2), poi(3), spatem(4), mapem(5), ivim(6), ev-rsr(7),
//        tistpgtransaction(8), srem(9), ssem(10), evcsn(11), saem(12), rtcmem(13) } (0..255), 

        if (MessageID.denm.equals(messageID))
            return "denm";
        else if (MessageID.cam.equals(messageID))
            return "cam";
        else if (MessageID.poi.equals(messageID))
            return "poi";
        else if (MessageID.spatem.equals(messageID))
            return "spatem";
        else if (MessageID.mapem.equals(messageID))
            return "mapem";
        else if (MessageID.ivim.equals(messageID))
            return "ivim";
        else if (MessageID.ev_rsr.equals(messageID))
            return "ex-rsr";
        else if (MessageID.tistpgtransaction.equals(messageID))
            return "tistpgtransaction";
        else if (MessageID.srem.equals(messageID))
            return "srem";
        else if (MessageID.ssem.equals(messageID))
            return "ssem";
        else if (MessageID.evcsn.equals(messageID))
            return "evcsn";
        else if (MessageID.saem.equals(messageID))
            return "saem";
        else if (MessageID.rtcmem.equals(messageID))
            return "rtcmem";
        else
            return "" + messageID.intValue();
    }

    // Formats the value of the StationType
    private static String stationTypeToString(StationType stationType) {
         if (StationType.bus.equals(stationType))
            return "bus";
        else if (StationType.cyclist.equals(stationType))
            return "cyclist";
        else if (StationType.heavyTruck.equals(stationType))
            return "heavyTruck";
        else if (StationType.lightTruck.equals(stationType))
            return "lightTruck";
        else if (StationType.moped.equals(stationType))
            return "moped";
        else if (StationType.motorcycle.equals(stationType))
            return "motorcycle";
        else if (StationType.passengerCar.equals(stationType))
            return "passengerCar";
        else if (StationType.pedestrian.equals(stationType))
            return "pedestrian";
        else if (StationType.roadSideUnit.equals(stationType))
            return "roadSideUnit";
        else if (StationType.specialVehicles.equals(stationType))
            return "specialVehicles";
        else if (StationType.trailer.equals(stationType))
            return "trailer";
        else if (StationType.tram.equals(stationType))
            return "tram";
        else if (StationType.unknown.equals(stationType))
            return "unknown";
        else
            return "" + stationType.intValue();
    }

    // Formats the value of ReferencePosition
    private static String positionToString(ReferencePosition referencePosition) {
        StringBuilder sb = new StringBuilder();

        sb.append('(');
        // Latitude
        Latitude latitude = referencePosition.latitude;
        if (Latitude.oneMicrodegreeNorth.equals(latitude))
            sb.append("oneMicrodegreeNorth");
        else if (Latitude.oneMicrodegreeSouth.equals(latitude))
            sb.append("oneMicrodegreeSouth");
        else if (Latitude.unavailable.equals(latitude))
            sb.append("unavailable");
        else {
            long v = latitude.longValue();
            sb.append(String.format("%d.%06d",
                v / 1000000, Math.abs(v % 1000000)));
        }
        sb.append(", ");
        // Longitude
        Longitude longitude = referencePosition.longitude;
        if (Longitude.oneMicrodegreeEast.equals(longitude))
            sb.append("oneMicrodegreeEast");
        else if (Longitude.oneMicrodegreeWest.equals(longitude))
            sb.append("oneMicrodegreeWest");
        else if (Longitude.unavailable.equals(longitude))
            sb.append("unavailable");
        else {
            long v = longitude.longValue();
            sb.append(String.format("%d.%06d",
                v / 1000000, Math.abs(v % 1000000)));
        }
        sb.append("), alt ");
        // Altitude
        AltitudeValue altitude = referencePosition.altitude.altitudeValue;
        if (AltitudeValue.referenceEllipsoidSurface.equals(altitude))
            sb.append("referenceEllipsoidSurface");
        else if (AltitudeValue.oneCentimeter.equals(altitude))
            sb.append("oneCentimeter");
        else if (AltitudeValue.unavailable.equals(altitude))
            sb.append("unavailable");
        else {
            long v = altitude.longValue();
            sb.append(String.format("%d.%02d",
                v / 100, Math.abs(v % 100)));
        }
        sb.append(" m");
        return sb.toString();
    }

    // Formats the value of the SpeedValue
    private static String speedValueToString(SpeedValue speedValue) {
        if (SpeedValue.oneCentimeterPerSec.equals(speedValue))
            return "oneCentimeterPerSec";
        else if (SpeedValue.standstill.equals(speedValue))
            return "standstill";
        else if (SpeedValue.unavailable.equals(speedValue))
            return "unavailable";
        else
            return "" + speedValue.intValue();
    }

    // Formats the value of the CauseCode
    private static String causeCodeToString(CauseCodeType causeCode) {
        if (CauseCodeType.accident.equals(causeCode))
            return "accident";
        else if (CauseCodeType.adverseWeatherCondition_Adhesion.equals(causeCode))
            return "adverseWeatherCondition_Adhesion";
        else if (CauseCodeType.adverseWeatherCondition_ExtremeWeatherCondition.equals(causeCode))
            return "adverseWeatherCondition_ExtremeWeatherCondition";
        else if (CauseCodeType.adverseWeatherCondition_Precipitation.equals(causeCode))
            return "adverseWeatherCondition_Precipitation";
        else if (CauseCodeType.adverseWeatherCondition_Visibility.equals(causeCode))
            return "adverseWeatherCondition_Visibility";
        else if (CauseCodeType.collisionRisk.equals(causeCode))
            return "collisionRisk";
        else if (CauseCodeType.dangerousEndOfQueue.equals(causeCode))
            return "dangerousEndOfQueue";
        else if (CauseCodeType.dangerousSituation.equals(causeCode))
            return "dangerousSituation";
        else if (CauseCodeType.emergencyVehicleApproaching.equals(causeCode))
            return "emergencyVehicleApproaching";
        else if (CauseCodeType.hazardousLocation_AnimalOnTheRoad.equals(causeCode))
            return "hazardousLocation_AnimalOnTheRoad";
        else if (CauseCodeType.hazardousLocation_DangerousCurve.equals(causeCode))
            return "hazardousLocation_DangerousCurve";
        else if (CauseCodeType.hazardousLocation_ObstacleOnTheRoad.equals(causeCode))
            return "hazardousLocation_ObstacleOnTheRoad";
        else if (CauseCodeType.hazardousLocation_SurfaceCondition.equals(causeCode))
            return "hazardousLocation_SurfaceCondition";
        else if (CauseCodeType.humanPresenceOnTheRoad.equals(causeCode))
            return "humanPresenceOnTheRoad";
        else if (CauseCodeType.humanProblem.equals(causeCode))
            return "humanProblem";
        else if (CauseCodeType.postCrash.equals(causeCode))
            return "postCrash";
        else if (CauseCodeType.rescueAndRecoveryWorkInProgress.equals(causeCode))
            return "rescueAndRecoveryWorkInProgress";
        else if (CauseCodeType.reserved.equals(causeCode))
            return "reserved";
        else if (CauseCodeType.roadworks.equals(causeCode))
            return "roadworks";
        else if (CauseCodeType.signalViolation.equals(causeCode))
            return "signalViolation";
        else if (CauseCodeType.slowVehicle.equals(causeCode))
            return "slowVehicle";
        else if (CauseCodeType.stationaryVehicle.equals(causeCode))
            return "stationaryVehicle";
        else if (CauseCodeType.trafficCondition.equals(causeCode))
            return "trafficCondition";
        else if (CauseCodeType.vehicleBreakdown.equals(causeCode))
            return "vehicleBreakdown";
        else if (CauseCodeType.wrongWayDriving.equals(causeCode))
            return "wrongWayDriving";
        else
            return "" + causeCode.intValue();
    }
}

Expected Output (Excerpt)

This is the expected output when running the sample:

Creating the CAM PDU value... Done
Encoding the created CAM value... Done
Decoding the encoded CAM message... Done
Comparing the decoded message with the original PDU value... Succeeded

Partial custom printing of the decoded CAM PDU:

messageID: cam
stationID: 1234567
generationDeltaTime: 11409
stationType: passengerCar
referencePosition: (40.487111, 79.494789), alt 20.00 m
speedValue: 2000

Creating the DENM PDU value... Done
Encoding the created DENM value... Done
Decoding the encoded DENM message... Done
Comparing the decoded message with the original PDU value... Succeeded

Partial custom printing of the decoded DENM PDU:

messageID: denm
stationID: 1234567
eventPosition: (40.487111, -79.494789), alt 20.00 m
causeCode: roadworks

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 a shell script. When exporting cam_denm.a1sproj, specify Tcamdenm as the "Class or .jar name to execute".

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