1#include <vanetza/asn1/its/CAM.h>
2#include <vanetza/asn1/its/r2/CAM.h>
3#include <vanetza/facilities/detail/macros.ipp>
6ASSERT_EQUAL_TYPE(AltitudeConfidence_t);
7ASSERT_EQUAL_ENUM(AltitudeConfidence_alt_000_01);
8ASSERT_EQUAL_ENUM(AltitudeConfidence_alt_200_00);
9ASSERT_EQUAL_ENUM(AltitudeConfidence_outOfRange);
10ASSERT_EQUAL_ENUM(AltitudeConfidence_unavailable);
12ASSERT_EQUAL_TYPE(AltitudeValue_t);
13ASSERT_EQUAL_ENUM(AltitudeValue_unavailable);
15ASSERT_EQUAL_TYPE(DeltaAltitude_t);
16ASSERT_EQUAL_ENUM(DeltaAltitude_unavailable);
18ASSERT_EQUAL_TYPE(DeltaLatitude_t);
19ASSERT_EQUAL_ENUM(DeltaLatitude_unavailable);
21ASSERT_EQUAL_TYPE(DeltaLongitude_t);
22ASSERT_EQUAL_ENUM(DeltaLongitude_unavailable);
24ASSERT_EQUAL_TYPE(Latitude_t);
25ASSERT_EQUAL_ENUM(Latitude_unavailable);
27ASSERT_EQUAL_TYPE(Longitude_t);
28ASSERT_EQUAL_ENUM(Longitude_unavailable);
30ASSERT_EQUAL_TYPE(PathDeltaTime_t);
37bool check_service_specific_permissions(
const ASN1_PREFIXED(CamParameters_t)& params, security::CamPermissions ssp)
39 using security::CamPermission;
40 using security::CamPermissions;
42 CamPermissions required_permissions;
44 if (params.highFrequencyContainer.present == ASN1_PREFIXED(HighFrequencyContainer_PR_rsuContainerHighFrequency)) {
45 const ASN1_PREFIXED(RSUContainerHighFrequency_t)& rsu = params.highFrequencyContainer.choice.rsuContainerHighFrequency;
46 if (rsu.protectedCommunicationZonesRSU) {
47 required_permissions.add(CamPermission::CEN_DSRC_Tolling_Zone);
51 if (
const ASN1_PREFIXED(SpecialVehicleContainer_t)* special = params.specialVehicleContainer) {
52 const ASN1_PREFIXED(EmergencyContainer_t)* emergency =
nullptr;
53 const ASN1_PREFIXED(SafetyCarContainer_t)* safety =
nullptr;
54 const ASN1_PREFIXED(RoadWorksContainerBasic_t)* roadworks =
nullptr;
56 switch (special->present) {
57 case ASN1_PREFIXED(SpecialVehicleContainer_PR_publicTransportContainer):
58 required_permissions.add(CamPermission::Public_Transport);
60 case ASN1_PREFIXED(SpecialVehicleContainer_PR_specialTransportContainer):
61 required_permissions.add(CamPermission::Special_Transport);
63 case ASN1_PREFIXED(SpecialVehicleContainer_PR_dangerousGoodsContainer):
64 required_permissions.add(CamPermission::Dangerous_Goods);
66 case ASN1_PREFIXED(SpecialVehicleContainer_PR_roadWorksContainerBasic):
67 required_permissions.add(CamPermission::Roadwork);
68 roadworks = &special->choice.roadWorksContainerBasic;
70 case ASN1_PREFIXED(SpecialVehicleContainer_PR_rescueContainer):
71 required_permissions.add(CamPermission::Rescue);
73 case ASN1_PREFIXED(SpecialVehicleContainer_PR_emergencyContainer):
74 required_permissions.add(CamPermission::Emergency);
75 emergency = &special->choice.emergencyContainer;
77 case ASN1_PREFIXED(SpecialVehicleContainer_PR_safetyCarContainer):
78 required_permissions.add(CamPermission::Safety_Car);
79 safety = &special->choice.safetyCarContainer;
85 if (emergency && emergency->emergencyPriority && emergency->emergencyPriority->size == 1) {
87 assert(emergency->emergencyPriority->buf);
88 uint8_t bits = *emergency->emergencyPriority->buf;
89 if (bits & (1 << (7 - ASN1_PREFIXED(EmergencyPriority_requestForRightOfWay)))) {
90 required_permissions.add(CamPermission::Request_For_Right_Of_Way);
92 if (bits & (1 << (7 - ASN1_PREFIXED(EmergencyPriority_requestForFreeCrossingAtATrafficLight)))) {
93 required_permissions.add(CamPermission::Request_For_Free_Crossing_At_Traffic_Light);
97 if (roadworks && roadworks->closedLanes) {
98 required_permissions.add(CamPermission::Closed_Lanes);
101 if (safety && safety->trafficRule) {
102 switch (*safety->trafficRule) {
103 case ASN1_PREFIXED(TrafficRule_noPassing):
104 required_permissions.add(CamPermission::No_Passing);
106 case ASN1_PREFIXED(TrafficRule_noPassingForTrucks):
107 required_permissions.add(CamPermission::No_Passing_For_Trucks);
114 if (safety && safety->speedLimit) {
115 required_permissions.add(CamPermission::Speed_Limit);
119 return ssp.has(required_permissions);
122void print_indented(std::ostream& os,
const ASN1_PREFIXED(CAM_t)* message,
const std::string& indent,
unsigned level)
124 auto prefix = [&](
const char* field) -> std::ostream& {
125 for (
unsigned i = 0; i < level; ++i) {
132 const ASN1_PREFIXED(ItsPduHeader_t)& header = message->header;
133 prefix(
"ITS PDU Header") <<
"\n";
135 prefix(
"Protocol Version") << header.protocolVersion <<
"\n";
137 prefix(
"Message ID") << header.messageID <<
"\n";
138 prefix(
"Station ID") << header.stationID <<
"\n";
140 prefix(
"Message ID") << header.messageId <<
"\n";
141 prefix(
"Station ID") << header.stationId <<
"\n";
146 const ASN1_PREFIXED(CoopAwareness_t)& cam = message->cam;
148 const ASN1_PREFIXED(CamPayload_t)& cam = message->cam;
150 prefix(
"CoopAwareness") <<
"\n";
152 prefix(
"Generation Delta Time") << cam.generationDeltaTime <<
"\n";
154 prefix(
"Basic Container") <<
"\n";
156 const ASN1_PREFIXED(BasicContainer_t)& basic = cam.camParameters.basicContainer;
157 prefix(
"Station Type") << basic.stationType <<
"\n";
158 prefix(
"Reference Position") <<
"\n";
160 prefix(
"Longitude") << basic.referencePosition.longitude <<
"\n";
161 prefix(
"Latitude") << basic.referencePosition.latitude <<
"\n";
163 prefix(
"Semi Major Orientation") << basic.referencePosition.positionConfidenceEllipse.semiMajorOrientation <<
"\n";
164 prefix(
"Semi Major Confidence") << basic.referencePosition.positionConfidenceEllipse.semiMajorConfidence <<
"\n";
165 prefix(
"Semi Minor Confidence") << basic.referencePosition.positionConfidenceEllipse.semiMinorConfidence <<
"\n";
167 prefix(
"Semi Major Axis Orientation") << basic.referencePosition.positionConfidenceEllipse.semiMajorAxisOrientation <<
"\n";
168 prefix(
"Semi Major Axis Length") << basic.referencePosition.positionConfidenceEllipse.semiMajorAxisLength <<
"\n";
169 prefix(
"Semi Minor Axis Length") << basic.referencePosition.positionConfidenceEllipse.semiMinorAxisLength <<
"\n";
172 prefix(
"Altitude [Confidence]") << basic.referencePosition.altitude.altitudeValue
173 <<
" [" << basic.referencePosition.altitude.altitudeConfidence <<
"]\n";
177 if (cam.camParameters.highFrequencyContainer.present == ASN1_PREFIXED(HighFrequencyContainer_PR_basicVehicleContainerHighFrequency)) {
178 prefix(
"High Frequency Container [Basic Vehicle]") <<
"\n";
180 const ASN1_PREFIXED(BasicVehicleContainerHighFrequency)& bvc =
181 cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency;
182 prefix(
"Heading [Confidence]") << bvc.heading.headingValue
183 <<
" [" << bvc.heading.headingConfidence <<
"]\n";
184 prefix(
"Speed [Confidence]") << bvc.speed.speedValue
185 <<
" [" << bvc.speed.speedConfidence <<
"]\n";
186 prefix(
"Drive Direction") << bvc.driveDirection <<
"\n";
188 prefix(
"Longitudinal Acceleration [Confidence]") << bvc.longitudinalAcceleration.longitudinalAccelerationValue
189 <<
" [" << bvc.longitudinalAcceleration.longitudinalAccelerationConfidence <<
"]\n";
191 prefix(
"Longitudinal Acceleration [Confidence]") << bvc.longitudinalAcceleration.value
192 <<
" [" << bvc.longitudinalAcceleration.confidence <<
"]\n";
194 prefix(
"Vehicle Length [Confidence Indication]") << bvc.vehicleLength.vehicleLengthValue
195 <<
" [" << bvc.vehicleLength.vehicleLengthConfidenceIndication <<
"]\n";
196 prefix(
"Vehicle Width") << bvc.vehicleWidth <<
"\n";
197 prefix(
"Curvature [Confidence]") << bvc.curvature.curvatureValue
198 <<
" [" << bvc.curvature.curvatureConfidence <<
"]\n";
199 prefix(
"Curvature Calculation Mode") << bvc.curvatureCalculationMode <<
"\n";
200 prefix(
"Yaw Rate [Confidence]") << bvc.yawRate.yawRateValue
201 <<
" [" << bvc.yawRate.yawRateConfidence <<
"]\n";
203 }
else if (cam.camParameters.highFrequencyContainer.present == ASN1_PREFIXED(HighFrequencyContainer_PR_rsuContainerHighFrequency)) {
204 prefix(
"High Frequency Container [RSU]") <<
"\n";
205 const ASN1_PREFIXED(RSUContainerHighFrequency_t)& rsu = cam.camParameters.highFrequencyContainer.choice.rsuContainerHighFrequency;
206 if (
nullptr != rsu.protectedCommunicationZonesRSU &&
nullptr != rsu.protectedCommunicationZonesRSU->list.array) {
208 int size = rsu.protectedCommunicationZonesRSU->list.count;
209 for (
int i = 0; i < size; i++)
211 prefix(
"Protected Zone") <<
"\n";
213 prefix(
"Type") << rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneType <<
"\n";
214 if (rsu.protectedCommunicationZonesRSU->list.array[i]->expiryTime
215 &&
nullptr != rsu.protectedCommunicationZonesRSU->list.array[i]->expiryTime->buf
216 && rsu.protectedCommunicationZonesRSU->list.array[i]->expiryTime->size > 0)
217 prefix(
"Expiry Time") << (unsigned) rsu.protectedCommunicationZonesRSU->list.array[i]->expiryTime->buf[0] <<
"\n";
218 prefix(
"Latitude") << rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneLatitude <<
"\n";
219 prefix(
"Longitude") << rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneLongitude <<
"\n";
220 if (
nullptr != rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneRadius)
221 prefix(
"Radius") << *(rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneRadius) <<
"\n";
222 if (
nullptr != rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneRadius)
224 prefix(
"ID") << *(rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneID) <<
"\n";
226 prefix(
"ID") << *(rsu.protectedCommunicationZonesRSU->list.array[i]->protectedZoneId) <<
"\n";
233 prefix(
"High Frequency Container") <<
"empty\n";
236 if (
nullptr != cam.camParameters.lowFrequencyContainer) {
237 if (cam.camParameters.lowFrequencyContainer->present == ASN1_PREFIXED(LowFrequencyContainer_PR_basicVehicleContainerLowFrequency)) {
238 prefix(
"Low Frequency Container") <<
"\n";
239 const ASN1_PREFIXED(BasicVehicleContainerLowFrequency_t)& lfc =
240 cam.camParameters.lowFrequencyContainer->choice.basicVehicleContainerLowFrequency;
242 prefix(
"Vehicle Role") << (lfc.vehicleRole) <<
"\n";
244 if (
nullptr != lfc.exteriorLights.buf && lfc.exteriorLights.size > 0)
245 prefix(
"Exterior Lights") << unsigned(*(lfc.exteriorLights.buf)) <<
"\n";
246 if (
nullptr != lfc.pathHistory.list.array) {
247 int size = lfc.pathHistory.list.count;
248 for (
int i = 0; i < size; i++)
250 prefix(
"Path history point") <<
"\n";
252 prefix(
"Latitude") << (lfc.pathHistory.list.array[i]->pathPosition.deltaLatitude) <<
"\n";
253 prefix(
"Longitude") << (lfc.pathHistory.list.array[i]->pathPosition.deltaLongitude) <<
"\n";
254 prefix(
"Altitude") << (lfc.pathHistory.list.array[i]->pathPosition.deltaAltitude) <<
"\n";
255 if (lfc.pathHistory.list.array[i]->pathDeltaTime)
256 prefix(
"Delta time") << *(lfc.pathHistory.list.array[i]->pathDeltaTime) <<
"\n";
263 prefix(
"Low Frequency Container") <<
"present but empty" <<
"\n";
266 prefix(
"Low Frequency Container") <<
"not present" <<
"\n";
268 if (
nullptr != cam.camParameters.specialVehicleContainer) {
269 if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_publicTransportContainer)) {
270 prefix(
"Special Vehicle Container [Public Transport]") <<
"\n";
271 ASN1_PREFIXED(PublicTransportContainer_t)& ptc = cam.camParameters.specialVehicleContainer->choice.publicTransportContainer;
273 prefix(
"Embarkation Status") << ptc.embarkationStatus <<
"\n";
274 if (ptc.ptActivation) {
275 prefix(
"PT Activation Type") << ptc.ptActivation->ptActivationType <<
"\n";
276 if (0 != ptc.ptActivation->ptActivationData.size) {
277 int size = ptc.ptActivation->ptActivationData.size;
278 for (
int i = 0; i < ptc.ptActivation->ptActivationData.size; i++)
279 prefix(
"PT Activation Data") << (unsigned) ptc.ptActivation->ptActivationData.buf[i] <<
"\n";
283 }
else if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_specialTransportContainer)) {
284 prefix(
"Special Vehicle Container [Special Transport]") <<
"\n";
285 ASN1_PREFIXED(SpecialTransportContainer_t)& stc = cam.camParameters.specialVehicleContainer->choice.specialTransportContainer;
287 if (
nullptr != stc.specialTransportType.buf && stc.specialTransportType.size > 0)
288 prefix(
"Type") << (unsigned) stc.specialTransportType.buf[0] <<
"\n";
289 if (
nullptr != stc.lightBarSirenInUse.buf && stc.lightBarSirenInUse.size > 0)
290 prefix(
"Light Bar Siren in Use") << (unsigned) stc.lightBarSirenInUse.buf[0] <<
"\n";
292 }
else if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_dangerousGoodsContainer)) {
293 prefix(
"Special Vehicle Container [Dangerous Goods]") <<
"\n";
294 ASN1_PREFIXED(DangerousGoodsContainer_t)& dgc = cam.camParameters.specialVehicleContainer->choice.dangerousGoodsContainer;
296 prefix(
"Dangerous Goods Basic Type") << (unsigned)dgc.dangerousGoodsBasic <<
"\n";
298 }
else if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_roadWorksContainerBasic)) {
299 prefix(
"Special Vehicle Container [Road Works]") <<
"\n";
300 ASN1_PREFIXED(RoadWorksContainerBasic_t)& rwc = cam.camParameters.specialVehicleContainer->choice.roadWorksContainerBasic;
302 if (
nullptr != rwc.roadworksSubCauseCode)
303 prefix(
"Sub Cause Code") << *(rwc.roadworksSubCauseCode) <<
"\n";
304 if (
nullptr != rwc.lightBarSirenInUse.buf && rwc.lightBarSirenInUse.size > 0)
305 prefix(
"Light Bar Siren in Use") << (unsigned) rwc.lightBarSirenInUse.buf[0] <<
"\n";
306 if (
nullptr != rwc.closedLanes) {
307 if (rwc.closedLanes->innerhardShoulderStatus)
308 prefix(
"Inner Hard Shoulder Status") << *(rwc.closedLanes->innerhardShoulderStatus) <<
"\n";
309 if (rwc.closedLanes->outerhardShoulderStatus)
310 prefix(
"Outer Hard Shoulder Status") << *(rwc.closedLanes->outerhardShoulderStatus) <<
"\n";
311 if (rwc.closedLanes->drivingLaneStatus &&
nullptr != rwc.closedLanes->drivingLaneStatus->buf
312 && rwc.closedLanes->drivingLaneStatus->size > 0)
313 prefix(
"Driving Lane Status") << (unsigned) rwc.closedLanes->drivingLaneStatus->buf[0] <<
"\n";
316 }
else if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_rescueContainer)) {
317 prefix(
"Special Vehicle Container [Rescue]") <<
"\n";
318 ASN1_PREFIXED(RescueContainer_t)& rc = cam.camParameters.specialVehicleContainer->choice.rescueContainer;
320 if (
nullptr != rc.lightBarSirenInUse.buf && rc.lightBarSirenInUse.size > 0)
321 prefix(
"Light Bar Siren in Use") << (unsigned) rc.lightBarSirenInUse.buf[0] <<
"\n";
323 }
else if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_emergencyContainer)) {
324 prefix(
"Special Vehicle Container [Emergency]") <<
"\n";
325 ASN1_PREFIXED(EmergencyContainer_t)& ec = cam.camParameters.specialVehicleContainer->choice.emergencyContainer;
327 if (
nullptr != ec.lightBarSirenInUse.buf && ec.lightBarSirenInUse.size > 0)
328 prefix(
"Light Bar Siren in Use") << (unsigned) ec.lightBarSirenInUse.buf[0] <<
"\n";
329 if (
nullptr != ec.incidentIndication) {
331 prefix(
"Incident Indication Cause Code") << ec.incidentIndication->causeCode <<
"\n";
332 prefix(
"Incident Indication Sub Cause Code") << ec.incidentIndication->subCauseCode <<
"\n";
334 prefix(
"Incident Indication Cause Code V2") << ec.incidentIndication->ccAndScc.present <<
"\n";
335 prefix(
"Incident Indication Sub Cause Code V2") << ec.incidentIndication->ccAndScc.choice.reserved0 <<
"\n";
338 if (
nullptr != ec.emergencyPriority &&
nullptr != ec.emergencyPriority->buf
339 && ec.emergencyPriority->size > 0) {
340 prefix(
"Emergency Priority") << (unsigned) ec.emergencyPriority->buf[0] <<
"\n";
343 }
else if (cam.camParameters.specialVehicleContainer->present == ASN1_PREFIXED(SpecialVehicleContainer_PR_safetyCarContainer)) {
344 prefix(
"Special Vehicle Container [Safety Car]") <<
"\n";
345 ASN1_PREFIXED(SafetyCarContainer_t)& sc = cam.camParameters.specialVehicleContainer->choice.safetyCarContainer;
347 if (
nullptr != sc.lightBarSirenInUse.buf && sc.lightBarSirenInUse.size > 0)
348 prefix(
"Light Bar Siren in Use") << (unsigned) sc.lightBarSirenInUse.buf[0] <<
"\n";
349 if (
nullptr != sc.incidentIndication) {
351 prefix(
"Incident Indication Cause Code") << sc.incidentIndication->causeCode <<
"\n";
352 prefix(
"Incident Indication Sub Cause Code") << sc.incidentIndication->subCauseCode <<
"\n";
354 prefix(
"Incident Indication Cause Code V2") << sc.incidentIndication->ccAndScc.present <<
"\n";
355 prefix(
"Incident Indication Sub Cause Code V2") << sc.incidentIndication->ccAndScc.choice.reserved0 <<
"\n";
358 if (
nullptr != sc.trafficRule) {
359 prefix(
"Traffic Rule") << *(sc.trafficRule) <<
"\n";
361 if (
nullptr != sc.speedLimit) {
362 prefix(
"Speed Limit") << *(sc.speedLimit) <<
"\n";
367 prefix(
"Special Vehicle Container") << (
"present but empty") <<
"\n";
370 prefix(
"Special Vehicle Container") <<
"not present" <<
"\n";