Skip to content

Java: CAM v1.1.3 refactoring and new CAM v2.3.0#489

Merged
mathieu1fb merged 31 commits intoOrange-OpenSource:masterfrom
mathieu1fb:cam-refactoring
Mar 10, 2026
Merged

Java: CAM v1.1.3 refactoring and new CAM v2.3.0#489
mathieu1fb merged 31 commits intoOrange-OpenSource:masterfrom
mathieu1fb:cam-refactoring

Conversation

@mathieu1fb
Copy link
Copy Markdown
Collaborator

@mathieu1fb mathieu1fb commented Mar 9, 2026

What's new

  • CAM v2.3.0 support has been added
  • CAM v1.1.3 has been refactored completely for compatibility, so that both versions can be handled in parallel

Close #485
Close #486


What to do

After reviewing code changes:

  1. Clone the its-client project on your IDE.
  2. Ensure that you have Gradle to be able to build the java/iot3 modules (core, mobility and examples).
  3. Find the Iot3MobilityExample class in the examples module, and set appropriate values for the following fields:
private static final String EXAMPLE_UUID = "uuid";
private static final String EXAMPLE_CONTEXT = "context";
// MQTT parameters
private static final String EXAMPLE_MQTT_HOST = "mqtt_host";
private static final int EXAMPLE_MQTT_PORT = 1883;
private static final String EXAMPLE_MQTT_USERNAME = "mqtt_username";
private static final String EXAMPLE_MQTT_PASSWORD = "mqtt_password";
private static final boolean EXAMPLE_MQTT_USE_TLS = true; // set to true
  1. In the same class, remove the telemetry and LwM2M parameters from the IoT3Mobility builder as they won't be used:
.telemetryParams(EXAMPLE_OTL_SCHEME,
                        EXAMPLE_OTL_HOST,
                        EXAMPLE_OTL_PORT,
                        EXAMPLE_OTL_ENDPOINT,
                        EXAMPLE_OTL_USERNAME,
                        EXAMPLE_OTL_PASSWORD)
.lwm2mParams(
                        EXAMPLE_LWM2M_CONFIG,
                        EXAMPLE_LWM2M_DEVICE,
                        lwm2mConnectivityStatistics)
  1. Run Iot3MobilityExample for a few seconds.
  2. Stop it.
  3. Modify the CamVersion.V1_1_3 parameter in the ioT3Mobility.sendPosition(...) method by CamVersion.V2_3_0.
  4. Run Iot3MobilityExample for a few seconds.
  5. Stop it.

Expected results

  1. During the first run, you should see CAMs v1.1.3 being received and processed (i.e. turned into RoadUser objects).
Raw message received: {"type":"cam","origin":"self","version":"1.1.3","source_uuid":"ora_test_123","timestamp":1773072528767,"message":{"protocol_version":2,"station_id":78486518,"generation_delta_time":64895,"basic_container":{"station_type":5,"reference_position":{"latitude":486252180,"longitude":22434480,"altitude":0}},"high_frequency_container":{"heading":0,"speed":0,"longitudinal_acceleration":0,"yaw_rate":0}}}

Raw CAM v1.1.3: CamEnvelope113[type=cam, origin=self, version=1.1.3, sourceUuid=ora_test_123, timestamp=1773072528767, message=CamMessage113[protocolVersion=2, stationId=78486518, generationDeltaTime=64895, basicContainer=BasicContainer[stationType=5, referencePosition=ReferencePosition[latitude=486252180, longitude=22434480, altitude=0], confidence=null], highFrequencyContainer=HighFrequencyContainer[heading=0, speed=0, driveDirection=null, vehicleLength=null, vehicleWidth=null, curvature=null, curvatureCalculationMode=null, longitudinalAcceleration=0, yawRate=0, accelerationControl=null, lanePosition=null, lateralAcceleration=null, verticalAcceleration=null, confidence=null], lowFrequencyContainer=null]]
New Road User: ora_test_123_78486518
Road User position: lat/lng: (48.625218,2.243448)
  1. During the second run, you should see the exact same with CAMs v2.3.0.
Raw message received: {"message_type":"cam","message_format":"json/raw","source_uuid":"ora_test_123","timestamp":1773070072412,"version":"2.3.0","message":{"protocol_version":2,"station_id":24793671,"generation_delta_time":33372,"basic_container":{"station_type":5,"reference_position":{"latitude":486252180,"longitude":22434480,"position_confidence_ellipse":{"semi_major":10,"semi_minor":10,"semi_major_orientation":0},"altitude":{"value":0,"confidence":15}}},"high_frequency_container":{"basic_vehicle_container_high_frequency":{"heading":{"value":0,"confidence":127},"speed":{"value":0,"confidence":127},"drive_direction":2,"vehicle_length":{"value":1023,"confidence":4},"vehicle_width":62,"longitudinal_acceleration":{"value":0,"confidence":102},"curvature":{"value":1023,"confidence":7},"curvature_calculation_mode":2,"yaw_rate":{"value":0,"confidence":8}}}}}

Raw CAM v2.3.0: CamEnvelope230[messageType=cam, messageFormat=json/raw, sourceUuid=ora_test_123, timestamp=1773070072412, version=2.3.0, message=CamStructuredData[protocolVersion=2, stationId=24793671, generationDeltaTime=33372, basicContainer=BasicContainer[stationType=5, referencePosition=ReferencePosition[latitude=486252180, longitude=22434480, positionConfidenceEllipse=PositionConfidenceEllipse[semiMajor=10, semiMinor=10, semiMajorOrientation=0], altitude=Altitude[value=0, confidence=15]]], highFrequencyContainer=BasicVehicleContainerHighFrequency[heading=Heading[value=0, confidence=127], speed=Speed[value=0, confidence=127], driveDirection=2, vehicleLength=VehicleLength[value=1023, confidence=4], vehicleWidth=62, longitudinalAcceleration=AccelerationComponent[value=0, confidence=102], curvature=Curvature[value=1023, confidence=7], curvatureCalculationMode=2, yawRate=YawRate[value=0, confidence=8], accelerationControl=null, lanePosition=null, steeringWheelAngle=null, lateralAcceleration=null, verticalAcceleration=null, performanceClass=null, cenDsrcTollingZone=null], lowFrequencyContainer=null, specialVehicleContainer=null]]
New Road User: ora_test_123_24793671
Road User position: lat/lng: (48.625218,2.243448)

Note: it is normal if source_uuid, station_id and timestamps differ in your test.

This new implementation should be faster and is clearly versioned.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…nversion

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…e simple methods

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…2.3.0 implementations

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…3 and v2.3.0 implementations

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
The user shouldn't have to set message type and version, so we set them.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…ckage

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…ehicleContainer

The SpecialVehicleContainer is actually not part of the JSON schema for this CAM version, and was anyway empty.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
… CamWriter113

This container was not part of the CAM v1.1.3 spec and has been removed.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…CamValidator230

This field was wrongly expected to be mandatory.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…(...) method

Note that handling both CAM versions in the same class makes imports messy since many 1.1.3 and 2.3.0 classes have the same name. Maybe we should add a version suffix to each class.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Max value was erroneously set to 01-01-2028 in the JSON schema, which will break soon.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
@mathieu1fb mathieu1fb added this to the Sprint 19 milestone Mar 9, 2026
@mathieu1fb mathieu1fb requested a review from fredOG-2A1 March 9, 2026 16:12
@mathieu1fb mathieu1fb self-assigned this Mar 9, 2026
@mathieu1fb mathieu1fb added the Java label Mar 9, 2026
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
… Java SDK

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Copy link
Copy Markdown
Member

@fredOG-2A1 fredOG-2A1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have tested with your recommandations.
It works as expected:
Raw message received: {"type":"cam","origin":"self","version":"1.1.3","source_uuid":"uuid","timestamp":1773139624269,"message":...}}
Raw CAM v1.1.3: CamEnvelope113[type=cam, origin=self, version=1.1.3, sourceUuid=uuid, timestamp=1773140392318, message=CamMessage113[protocolVersion=2, stationId=95569549, generationDeltaTime=33150, basicContainer=BasicContainer[...], highFrequencyContainer=HighFrequencyContainer[...], lowFrequencyContainer=null]]

Raw message received: {"message_type":"cam","message_format":"json/raw","source_uuid":"uuid","timestamp":1773140102589,"version":"2.3.0","message":...}}}
Raw CAM v2.3.0: CamEnvelope230[messageType=cam, messageFormat=json/raw, sourceUuid=uuid, timestamp=1773140597331, version=2.3.0, message=CamStructuredData[protocolVersion=2, stationId=28036714, generationDeltaTime=41555, basicContainer=BasicContainer[...], highFrequencyContainer=BasicVehicleContainerHighFrequency[...]]

Huge work!

Just a thought, what about using static vars to avoid this kink of writings:
"source_uuid" or others. Replacing by SOURCE_UUID that contains 'source_uuid' ensure that no mispelling could occure.
Just a suggestion.

@mathieu1fb
Copy link
Copy Markdown
Collaborator Author

Have tested with your recommandations. It works as expected: Raw message received: {"type":"cam","origin":"self","version":"1.1.3","source_uuid":"uuid","timestamp":1773139624269,"message":...}} Raw CAM v1.1.3: CamEnvelope113[type=cam, origin=self, version=1.1.3, sourceUuid=uuid, timestamp=1773140392318, message=CamMessage113[protocolVersion=2, stationId=95569549, generationDeltaTime=33150, basicContainer=BasicContainer[...], highFrequencyContainer=HighFrequencyContainer[...], lowFrequencyContainer=null]]

Raw message received: {"message_type":"cam","message_format":"json/raw","source_uuid":"uuid","timestamp":1773140102589,"version":"2.3.0","message":...}}} Raw CAM v2.3.0: CamEnvelope230[messageType=cam, messageFormat=json/raw, sourceUuid=uuid, timestamp=1773140597331, version=2.3.0, message=CamStructuredData[protocolVersion=2, stationId=28036714, generationDeltaTime=41555, basicContainer=BasicContainer[...], highFrequencyContainer=BasicVehicleContainerHighFrequency[...]]

Huge work!

Just a thought, what about using static vars to avoid this kink of writings: "source_uuid" or others. Replacing by SOURCE_UUID that contains 'source_uuid' ensure that no mispelling could occure. Just a suggestion.

Thank you for the review! I have indeed considered using some sort of dictionary for all the JSON fields, but have not done so. I might do it in a future version.

@mathieu1fb mathieu1fb merged commit 6f62840 into Orange-OpenSource:master Mar 10, 2026
115 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor CAM v1.1.3 Add support for CAM v2.3.0

2 participants