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.
This sample shows how to:
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. |
(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.
Before running the test, ensure the following are set appropriately:
./run.sh
./run.sh cleanup
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.
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.
/*****************************************************************************/
/* 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();
}
}
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
-- 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
}
The gui/ subdirectory contains an ASN.1 Studio project for this sample. With ASN.1 Studio you can:
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.
If you have questions about using this sample, contact OSS Nokalva Support.