module ItsRSUsSimulator_Functions { // LibCommon import from LibCommon_BasicTypesAndValues all; import from LibCommon_DataStrings all; import from LibCommon_VerdictControl all; import from LibCommon_Sync all; import from LibCommon_Time all; // LibIts import from ITS_Container language "ASN.1:1997" all; import from CAM_PDU_Descriptions language "ASN.1:1997" all; import from DENM_PDU_Descriptions language "ASN.1:1997" all; import from MAPEM_PDU_Descriptions language "ASN.1:1997" all; import from SPATEM_PDU_Descriptions language "ASN.1:1997" all; import from IVIM_PDU_Descriptions language "ASN.1:1997" all; //import from EVCSN_PDU_Descriptions language "ASN.1:1997" all; import from RTCMEM_PDU_Descriptions language "ASN.1:1997" all; import from SREM_PDU_Descriptions language "ASN.1:1997" all; import from SSEM_PDU_Descriptions language "ASN.1:1997" all; import from DSRC language "ASN.1:1997" all; import from IEEE1609dot2BaseTypes language "ASN.1:1997" all; import from IEEE1609dot2 language "ASN.1:1997" all; import from EtsiTs102941BaseTypes language "ASN.1:1997" all; import from EtsiTs102941TypesEnrolment language "ASN.1:1997" all; import from EtsiTs102941TypesAuthorization language "ASN.1:1997" all; import from EtsiTs102941TypesAuthorizationValidation language "ASN.1:1997" all; import from EtsiTs102941MessagesCa language "ASN.1:1997" all; import from EtsiTs103097Module language "ASN.1:1997" all; // LibItsCommon import from LibItsCommon_Templates all; import from LibItsCommon_Functions all; import from LibItsCommon_ASN1_ISDSRC_NamedNumbers all; // LibItsBtp import from LibItsBtp_TypesAndValues all; import from LibItsBtp_Templates all; // LibItsCam import from LibItsCam_TypesAndValues all; import from LibItsCam_Templates all; // LibItsDenm import from LibItsDenm_TypesAndValues all; import from LibItsDenm_Templates all; // LibItsMapemSpatemm import from LibItsIvim_TypesAndValues all; import from LibItsIvim_Templates all; import from LibItsMapemSpatem_TypesAndValues all; import from LibItsMapemSpatem_Templates all; // LibItsSremSsem import from LibItsSremSsem_TypesAndValues all; import from LibItsSremSsem_Templates all; import from LibItsSremSsem_Pixits all; // LibItsRtcmem import from LibItsRtcmem_TypesAndValues all; import from LibItsRtcmem_Templates all; // LibItsGeoNetworking import from LibItsGeoNetworking_TestSystem all; import from LibItsGeoNetworking_Functions all; import from LibItsGeoNetworking_Templates all; import from LibItsGeoNetworking_TypesAndValues all; import from LibItsGeoNetworking_Pixits all; // LibItsSecurity import from LibItsSecurity_TypesAndValues all; import from LibItsSecurity_Functions all; import from LibItsSecurity_Templates all; // LibItsHttp import from LibItsHttp_TypesAndValues all; import from LibItsHttp_Templates all; import from LibItsHttp_BinaryTemplates all; import from LibItsHttp_Functions all; import from LibItsHttp_TestSystem all; // LibItsPki import from LibItsPki_TypesAndValues all; import from LibItsPki_Templates all; import from LibItsPki_Functions all; import from LibItsPki_TestSystem all; import from LibItsPki_Pics all; import from LibItsPki_Pixits all; // AtsRSUsSimulator import from ItsRSUsSimulator_TypesAndValues all; import from ItsRSUsSimulator_TestSystem all; import from ItsRSUsSimulator_Templates all; import from ItsRSUsSimulator_PicsInitConsts all; import from ItsRSUsSimulator_Pics all; import from ItsRSUsSimulator_Pixits all; group externalFunctions { /** * @desc External function to compute a position using a reference position, a distance and an orientation * @param p_refLongPosVector Vehicle reference position * @param p_cenLongPosVector Collision point position * @param p_rotation Rotation angle in 1/10 of degrees (from North) * @param p_latitude Computed position's latitude * @param p_longitude Computed position's longitude * @remark See http://www.movable-type.co.uk/scripts/latlong.html */ external function fx_computePositionFromRotation( in Int32 p_refLatitude, in Int32 p_refLongitude, in Int32 p_cenLatitude, in Int32 p_cenLongitude, in Int32 p_rotation, out Int32 p_latitude, out Int32 p_longitude ); } // End of group externalFunctions group rsuConfigurationFunctions { /** * @desc This configuration features: * - one ITS node (IUT) * - two ITS nodes (nodeA, nodeB) * - Area1 which only includes NodeB and IUT * - Area2 which only includes NodeB * NodeB being close to the area center */ function f_cf01Up() runs on ItsRSUsSimulator { // Local variables // Map map(self:acPort, system:acPort); map(self:cfPort, system:cfPort); map(self:geoNetworkingPort, system:geoNetworkingPort); // Connect f_connect4SelfOrClientSync(); activate(a_cf01Down()); // Initialise secured mode LibItsGeoNetworking_Functions.f_initialiseSecuredMode(); //Initialze the Config module //cfPort.send(CfInitialize:{}); // Initialisations f_setup_rsu(vc_rsu_id); if (vc_pki == true) { // TODO LibItsPki_Function.f_cf01(); } } // End of function f_cf01Up function f_cf01Down() runs on ItsRSUsSimulator { vc_rsuMessagesValueList := {}; LibItsGeoNetworking_Functions.f_uninitialiseSecuredMode(); // Unmap unmap(self:acPort, system:acPort); unmap(self:cfPort, system:cfPort); unmap(self:geoNetworkingPort, system:geoNetworkingPort); // Disconnect f_disconnect4SelfOrClientSync(); deactivate; } // End of function f_cf01Down /** * @desc Default handling cf01 de-initialisation. */ altstep a_cf01Down() runs on ItsRSUsSimulator { [] a_shutdown() { f_poDefault(); f_cf01Down(); log("*** a_cf01Down: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***"); stop; } } // End of altstep a_cf01Down } // End of group rsuConfigurationFunctions group usecase6 { function f_initialiseVehicleSimulatorComponent( in ItsRSUsSimulator p_component, in integer p_vehicleIndex, out template (omit) CAM p_cam ) runs on ItsRSUsSimulator { p_cam := m_camMsg_vehicle( f_getTsStationId() + p_vehicleIndex, f_getCurrentTime() mod 65536, // Shall be updated in function f_prepare_vehicle_cam m_rsuPosition( 0, // Shall be computed 0 // Shall be computed ) ); map(p_component:geoNetworkingPort, system:geoNetworkingPort); } // End of function f_initialiseVehicleSimulatorComponent function f_uninitialiseVehicleSimulatorComponent( in ItsRSUsSimulator p_component ) runs on ItsRSUsSimulator { p_component.done; unmap(p_component:geoNetworkingPort, system:geoNetworkingPort); } // End of function f_uninitialiseVehicleSimulatorComponent } // End of group usecase6 function f_setup_rsu( in integer p_rsu_id ) runs on ItsRSUsSimulator { // Local variables var template (value) DenmParmContainers v_denmParmContainers; var template (omit) GeoNetworkingPdu v_beacon := omit; var template (omit) DENMs v_denms := omit; var template (omit) CAM v_cam := omit; var template (omit) MAPEM v_mapem := omit; var template (omit) SPATEMs v_spatems := omit; var template (omit) IVIM v_ivim := omit; //var template (omit) EvcsnPdu v_evcsn := omit; var template (omit) RTCMEM v_rtcmem := omit; var integer v_counter; log(">>> f_setup_rsu: ", vc_cam); log(">>> f_setup_rsu: ", vc_denm); log(">>> f_setup_rsu: ", vc_rtcmem); log(">>> f_setup_rsu: ", p_rsu_id); log(">>> f_setup_rsu: ", PX_ETSI_USE_CASE_ID); vc_longPosVectorRsu := PICS_RSU_PARAMS[p_rsu_id].longPosVector; log("f_setup_rsu: vc_longPosVectorRsu=", vc_longPosVectorRsu); // MAPEM, only if PX_ETSI_USE_CASE_ID is set to 3 if ((vc_mapem == true) and (PX_ETSI_USE_CASE_ID == 3) and ispresent(PICS_MAPEM_PARMS_RSUs[p_rsu_id].intersections)) { // Build the list of the MAPEM events v_mapem := m_mapemParm( PICS_RSU_PARAMS[vc_rsu_id].stationID, m_mapem( f_getMsgIssueRevision(), PICS_MAPEM_PARMS_RSUs[p_rsu_id].intersections, PICS_MAPEM_PARMS_RSUs[p_rsu_id].roadSegments )); // Update revision fields v_mapem.map_.intersections[0].revision := f_incMsgIssueRevision(); // TODO Add more? } else { vc_mapem := false; } // SPATEM, only if PX_ETSI_USE_CASE_ID is set to 3 if ((vc_spatem == true) and (PX_ETSI_USE_CASE_ID == 3) and (lengthof(PICS_SPATEM_PARMS_RSUs[p_rsu_id]) != 0)) { // Reset counter vc_currentPhaseStartTime := 36001; vc_endPhaseStartTime := 0; vc_spatemStatesId := 0; // Build the list of the SPATEM events for (v_counter := 0; v_counter < lengthof(PICS_SPATEM_PARMS_RSUs[p_rsu_id]); v_counter := v_counter + 1) { v_spatems[v_counter] := m_spatemParm( PICS_RSU_PARAMS[p_rsu_id].stationID, m_spatem( PICS_SPATEM_PARMS_RSUs[p_rsu_id][v_counter].intersections, "SignalGroupID #" & int2str(PICS_SPATEM_PARMS_RSUs[p_rsu_id][v_counter].signalGroupID) )); for (var integer v_intersection := 0; v_intersection < lengthof(v_spatems[v_counter].spat.intersections); v_intersection := v_intersection + 1) { vc_states[v_counter][v_intersection] := v_spatems[v_counter].spat.intersections[v_intersection].states; } // End of 'for' statement // TODO Build SPATEM with dynamic values } // End of 'for' statement // TODO Build SPATEM with dynamic values } else { vc_spatem := false; } // IVIM, only if PX_ETSI_USE_CASE_ID is set to 5 if ((vc_ivim == true) and (PX_ETSI_USE_CASE_ID == 5) and ispresent(PICS_IVIM_PARMS_RSUs[p_rsu_id].provider)) { // Build the list of the IVIM events v_ivim := m_ivimParm( PICS_RSU_PARAMS[p_rsu_id].stationID, m_ivimStructure( m_iviManagementContainer( PICS_IVIM_PARMS_RSUs[p_rsu_id].provider, PICS_IVIM_PARMS_RSUs[p_rsu_id].iviIdentificationNumber, 0//IviStatus_new_ ), PICS_IVIM_PARMS_RSUs[p_rsu_id].iviContainers )); // Update ivi status v_ivim.ivi.mandatory.validFrom := f_getCurrentTime(); v_ivim.ivi.mandatory.validTo := valueof(v_ivim.ivi.mandatory.validFrom) + 43200000; // 12hours } else { vc_ivim := false; } // RTCMEM if (vc_rtcmem == true) { // Build the list of the RTCMEM events v_rtcmem := m_rtcmemParm( PICS_RSU_PARAMS[p_rsu_id].stationID, m_defaultRtcmem( 123, -, { '01010101'O, '03030303'O } ) ); } else { vc_rtcmem := false; } /* // EVCSN, only if PX_ETSI_USE_CASE_ID is set to 8 */ /* if ((vc_evcsn == true) and (PX_ETSI_USE_CASE_ID == 8)) { */ /* // Build the list of the EVCSN events */ /* v_evcsn := */ /* m_evcsnParm( */ /* PICS_RSU_PARAMS[p_rsu_id].stationID, */ /* m_evcsn( */ /* m_itsPOIHeader( */ /* -, */ /* 0, // To be updated at run time */ /* - */ /* ), */ /* m_itsEVCSNData( */ /* -, */ /* { c_PICS_ITS_CHARGING } */ /* ) */ /* )); */ /* // Update poi status */ /* } else { */ /* vc_evcsn := false; */ /* } */ // DENM, only if PX_ETSI_USE_CASE_ID is set to 1 if (vc_denm == true) { if (PX_ETSI_USE_CASE_ID == 1) { // Build the list of the DENM events for the specified RSU (PX_RSU_ID) and the given zone (PX_ETSI_ZONE_ID) for (v_counter := 0; v_counter < lengthof(PICS_DENM_EVENTS_RSU_UC1[p_rsu_id][PX_ETSI_ZONE_ID - 1]); v_counter := v_counter + 1) { var DenmEventsParmsPerZone v_denmEventsParmsPerZone := PICS_DENM_EVENTS_RSU_UC1[p_rsu_id][PX_ETSI_ZONE_ID - 1]; v_denmParmContainers := m_denmParmContainers( PICS_RSU_PARAMS[p_rsu_id].stationID, f_incDenmSequenceNumber(), PICS_DENM_REPETITION_INTERVAL, v_denmEventsParmsPerZone[v_counter].eventPosition, v_denmEventsParmsPerZone[v_counter].causeCodeType, v_denmEventsParmsPerZone[v_counter].eventHistory, v_denmEventsParmsPerZone[v_counter].traces, PICS_DENM_VALIDITY_DURATION, PICS_DENM_RELEVANCE_DISTANCE, PICS_DENM_RELEVANCE_TRAFFIC_DIRECTION ); v_denms[v_counter] := valueof( m_denmPdu_rsu( PICS_RSU_PARAMS[p_rsu_id].stationID, m_denm( v_denmParmContainers.managementContainer, v_denmParmContainers.situationContainer, v_denmParmContainers.locationContainer ))); if (ispresent(v_denmEventsParmsPerZone[v_counter].roadWorksContainerExtended)) { v_denms[v_counter].denm.alacarte := m_alacarte(v_denmEventsParmsPerZone[v_counter].roadWorksContainerExtended); } } // End of 'for' statement // Update referenceDenms field, all except the current one for (v_counter := 0; v_counter < lengthof(PICS_DENM_EVENTS_RSU_UC1[p_rsu_id][PX_ETSI_ZONE_ID - 1]); v_counter := v_counter + 1) { if (ispresent(v_denms[v_counter].denm.alacarte.roadWorks)) { var integer v_referenceDenms := 0; for (var integer v_counter1 := 0; v_counter1 < lengthof(PICS_DENM_EVENTS_RSU_UC1[p_rsu_id][PX_ETSI_ZONE_ID - 1]); v_counter1 := v_counter1 + 1) { if (v_counter1 == v_counter) { continue; } v_denms[v_counter].denm.alacarte.roadWorks.referenceDenms[v_referenceDenms] := v_denms[v_counter1].denm.management.actionID; v_referenceDenms := v_referenceDenms + 1; } // End of 'for' statement } } // End of 'for' statement } else if (PX_ETSI_USE_CASE_ID == 2) { // Use case for Accident // Build the list of the DENM events for the specified RSU (PX_RSU_ID) and the given zone (PX_ETSI_ZONE_ID) for (v_counter := 0; v_counter < lengthof(PICS_DENM_PARAMS_UC2); v_counter := v_counter + 1) { v_denmParmContainers := m_denmParmContainers( PICS_RSU_PARAMS[p_rsu_id].stationID, f_incDenmSequenceNumber(), PICS_DENM_REPETITION_INTERVAL, PICS_DENM_PARAMS_UC2[v_counter].eventPosition, PICS_DENM_PARAMS_UC2[v_counter].causeCodeType, omit, omit, PICS_DENM_VALIDITY_DURATION, PICS_DENM_RELEVANCE_DISTANCE, PICS_DENM_RELEVANCE_TRAFFIC_DIRECTION ); log("f_setup_rsu: v_denmParmContainers=", v_denmParmContainers); v_denms[v_counter] := valueof( m_denmPdu_rsu( PICS_RSU_PARAMS[p_rsu_id].stationID, m_denm( v_denmParmContainers.managementContainer, v_denmParmContainers.situationContainer, omit ))); } // End of 'for' statement } else { vc_denm := false; } log("f_setup_rsu: v_denms=", v_denms); } // CAM if (vc_cam == true) { // Build the list of the CAM events if (PX_ETSI_USE_CASE_ID == 7) { vc_longPosVectorRsu := PICS_UC7_LPV.longPosVector; v_cam := m_camParm( PICS_UC7_LPV.stationID, PICS_UC7_LPV.stationType, PICS_UC7_LPV.vehicleRole, m_rsuPosition( PICS_UC7_LPV.longPosVector.latitude, PICS_UC7_LPV.longPosVector.longitude ), PICS_UC7_LPV.pathHistory, { rsuContainerHighFrequency := { protectedCommunicationZonesRSU := omit } } ); } else if (PX_ETSI_USE_CASE_ID == 6) { // FIXME To be removed only for test v_cam := m_camMsg_vehicle( PICS_RSU_PARAMS[p_rsu_id].stationID, f_getCurrentTime() mod 65536, // Shall be updated in function f_prepare_vehicle_cam m_rsuPosition( vc_longPosVectorRsu.latitude, vc_longPosVectorRsu.longitude ) ); } else if (PX_ETSI_USE_CASE_ID == 9) { v_cam := m_camParm( PICS_RSU_PARAMS[p_rsu_id].stationID, -, -, m_rsuPosition( vc_longPosVectorRsu.latitude, vc_longPosVectorRsu.longitude ), PICS_RSU_PARAMS[p_rsu_id].pathHistory, m_highFrequencyContainer_rsuContainerHighFrequency( m_rSUContainerHighFrequency( PICS_UC9_PCZ ))); } else { v_cam := m_camParm( PICS_RSU_PARAMS[p_rsu_id].stationID, -, -, m_rsuPosition( vc_longPosVectorRsu.latitude, vc_longPosVectorRsu.longitude ), PICS_RSU_PARAMS[p_rsu_id].pathHistory, { rsuContainerHighFrequency := { protectedCommunicationZonesRSU := omit } } ); } } if (vc_beacon == true) { // Build the list of the Beacon events v_beacon := valueof(m_geoNwPdu( m_geoNwBeaconPacket( vc_longPosVectorRsu ), m_defaultLifetime, 1 ) ); v_beacon.gnPacket.packet.commonHeader.flags := f_isMobile(); f_acTriggerEvent(m_startPassBeaconing(m_beaconHeader(m_longPosVector(PX_TS_NODE_B_LOCAL_GN_ADDR, 0)).beaconHeader)); } // Build the messages value list for this RSU vc_rsuMessagesValueList[p_rsu_id] := m_rsuProfile( v_beacon, v_cam, v_denms, v_mapem, v_spatems, v_ivim // v_evcsn, ); if (PICS_RSU_PARAMS[p_rsu_id].geoShape == e_geoCircle) { vc_geoArea := { shape := e_geoCircle, area := { geoAreaPosLatitude := vc_longPosVectorRsu.latitude, geoAreaPosLongitude := vc_longPosVectorRsu.longitude, distanceA := PICS_RSU_PARAMS[p_rsu_id].geoParms.radius, distanceB := PICS_RSU_PARAMS[p_rsu_id].geoParms.radius, angle := 0 } } } else { log("*** " & testcasename() & ": INCONC: Wrong PICS_RSU_GEOAREA_FORM event initialisation ***"); setverdict(inconc); stop; } log("<<< f_setup_rsu: ", vc_rsuMessagesValueList[p_rsu_id]); } // End of function f_setup_rsu function f_process_cf_event( in CfEvent p_cfEvent ) runs on ItsRSUsSimulator return boolean { var template (value) CfResult v_result := true; // Terminate simulation if (p_cfEvent == "stop") { if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].beacon)) { tc_beacon.stop; } if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].cam)) { tc_cam.stop; } if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].denms)) { tc_denm.stop; } if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].mapem)) { tc_mapem.stop; } if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].spatems)) { tc_spatem.stop; } if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].ivim)) { tc_ivim.stop; } } else { v_result := false; } cfPort.send(v_result); return true; } // End of function f_process_cf_event function f_prepare_cam( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { vc_rsuMessagesValueList[vc_rsu_id].cam.cam.generationDeltaTime := f_getCurrentTime() mod 65536; // See ETSI EN 302 637-2 V1.3.0 - Clause B.3 generationDelatTime p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( vc_rsuMessagesValueList[vc_rsu_id].cam ))), PICS_CAM_BTP_DESTINATION_PORT, PICS_CAM_BTP_SOURCE_PORT ) ); //log("f_prepare_cam: ", p_payload); } // End of function f_prepare_cam function f_prepare_denm( out template (value) GnRawPayload p_payload, in boolean p_cancellation := false ) runs on ItsRSUsSimulator { // Update dynamic parms vc_rsuMessagesValueList[vc_rsu_id].denms[vc_denmEventCounter].denm.management.referenceTime := f_getCurrentTime(); if (p_cancellation == true) { vc_rsuMessagesValueList[vc_rsu_id].denms[vc_denmEventCounter].denm.management.termination := isCancellation; } p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof(vc_rsuMessagesValueList[vc_rsu_id].denms[vc_denmEventCounter] ))), PICS_DENM_BTP_DESTINATION_PORT, PICS_DENM_BTP_SOURCE_PORT ) ); vc_denmEventCounter := (vc_denmEventCounter + 1) mod lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); //log("f_prepare_denm: ", p_payload); } // End of function f_prepare_denm function f_prepare_mapem( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( vc_rsuMessagesValueList[vc_rsu_id].mapem ))), PICS_MAPEM_BTP_DESTINATION_PORT, PICS_MAPEM_BTP_SOURCE_PORT ) ); } // End of function f_prepare_mapem function f_computeEndPhaseStartTime( in TimeMark p_timeMark, in UInt32 p_inc ) return TimeMark { var UInt32 v_endPhaseStartTime := p_timeMark + p_inc; return v_endPhaseStartTime mod 36000; } function f_prepare_spatem( in template (value) SPATEM p_spatem, out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { var template (omit) SPATEM v_spatem := p_spatem; // Make a copy var TimeMark v_currentTimeMark := f_getCurrentTimeMark(); if (vc_currentPhaseStartTime == 36001) { // First call vc_currentPhaseStartTime := v_currentTimeMark; select (vc_spatemStatesId) { case (0) { vc_endPhaseStartTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_30); } case (1) { vc_endPhaseStartTime := f_computeEndPhaseStartTime(v_currentTimeMark, PICS_SPATEM_REPITITION_DURATION_STATE_30); } case (2) { vc_endPhaseStartTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_30); } } // End of 'select' statement } if (v_currentTimeMark >= vc_endPhaseStartTime) { var float t := (int2float(v_currentTimeMark - vc_endPhaseStartTime) / int2float(v_currentTimeMark)); log("t = ", t); if (t < 1.0) { // Change state vc_spatemStatesId := (vc_spatemStatesId + 1) mod vc_spatemStatesNum; vc_currentPhaseStartTime := v_currentTimeMark; vc_endPhaseStartTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_30); } } log("vc_currentPhaseStartTime = ", vc_currentPhaseStartTime); log("v_currentTimeMark = ", v_currentTimeMark); log("vc_endPhaseStartTime = ", vc_endPhaseStartTime); log("vc_spatemStatesId = ", vc_spatemStatesId); // Rebuild SPATEM message for (var integer v_intersection := 0; v_intersection < lengthof(v_spatem.spat.intersections); v_intersection := v_intersection + 1) { var template (omit) MovementList v_states := vc_states[vc_signalGroupParmId][v_intersection]; v_spatem.spat.intersections[v_intersection].states := { v_states[vc_spatemStatesId] }; v_spatem.spat.intersections[v_intersection].moy := f_getMinuteOfTheYear(); v_spatem.spat.intersections[v_intersection].timeStamp := f_getDSecond(); v_spatem.spat.intersections[v_intersection].revision := (valueof(v_spatem.spat.intersections[v_intersection].revision) + 1) mod 128; select (vc_spatemStatesId) { case (0) { // permissive_Movement_Allowed v_spatem.spat.intersections[v_intersection].states[1] := v_states[1]; // permissive-clearance //v_spatem.spat.intersections[v_intersection].states[2] := v_states[2]; // Update startTime & minEndTime v_spatem.spat.intersections[v_intersection].states[0].state_time_speed[0].timing.minEndTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_30); v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.startTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_30); v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.minEndTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_40); } case (1) { // permissive-clearance v_spatem.spat.intersections[v_intersection].states[1] := v_states[2]; // stop-And-Remain //v_spatem.spat.intersections[v_intersection].states[2] := v_states[0]; // Update startTime & minEndTime v_spatem.spat.intersections[v_intersection].states[0].state_time_speed[0].timing.minEndTime := f_computeEndPhaseStartTime(v_currentTimeMark, PICS_SPATEM_REPITITION_DURATION_STATE_10); v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.startTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_10); v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.minEndTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_30); } case (2) { // stop-And-Remain v_spatem.spat.intersections[v_intersection].states[1] := v_states[0]; // permissive_Movement_Allowed //v_spatem.spat.intersections[v_intersection].states[2] := v_states[1]; // Update startTime & minEndTime v_spatem.spat.intersections[v_intersection].states[0].state_time_speed[0].timing.minEndTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_20); v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.startTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_20); v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.minEndTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, PICS_SPATEM_REPITITION_DURATION_STATE_50); } case else { } } // End of 'select' statement } // End of 'for' statement log("v_spatem.spat.intersections = ", v_spatem.spat.intersections); p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( v_spatem ))), PICS_SPATEM_BTP_DESTINATION_PORT, PICS_SPATEM_BTP_SOURCE_PORT ) ); } // End of function f_prepare_spatem function f_prepare_ivim( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( vc_rsuMessagesValueList[vc_rsu_id].ivim ))), PICS_IVIM_BTP_DESTINATION_PORT, PICS_IVIM_BTP_SOURCE_PORT ) ); } // End of function f_prepare_ivim function f_prepare_rtcmem( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( vc_rsuMessagesValueList[vc_rsu_id].rtcmem ))), PICS_RTCMEM_BTP_DESTINATION_PORT, PICS_RTCMEM_BTP_SOURCE_PORT ) ); } // End of function f_prepare_rtcmem function f_prepare_srem( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { log("f_prepare_srem: vc_sremEventCounter = ", vc_sremEventCounter); p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( vc_rsuMessagesValueList[vc_rsu_id].srems[vc_sremEventCounter] ))), PICS_SREM_BTP_DESTINATION_PORT, PICS_SREM_BTP_SOURCE_PORT ) ); if (valueof(vc_rsuMessagesValueList[vc_rsu_id].srems[vc_sremEventCounter].srm.requests[0].request.requestType) == priorityCancellation) { log("f_prepare_srem: Remove item: ", vc_rsuMessagesValueList[vc_rsu_id].srems); if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems) == 1) { log("f_prepare_srem: Remove last item"); vc_rsuMessagesValueList[vc_rsu_id].srems := {}; vc_sremEventCounter := 0; vc_srem := false; } else { if (vc_sremEventCounter == 0) { vc_rsuMessagesValueList[vc_rsu_id].srems := substr(vc_rsuMessagesValueList[vc_rsu_id].srems, 1, lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems) - 1); } else { var SREMs v_l; v_l := substr(vc_rsuMessagesValueList[vc_rsu_id].srems, 0, vc_sremEventCounter) & substr(vc_rsuMessagesValueList[vc_rsu_id].srems, vc_sremEventCounter + 1, lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems) - vc_sremEventCounter - 1); vc_rsuMessagesValueList[vc_rsu_id].srems := v_l; } log("f_prepare_srem: After removing: ", vc_rsuMessagesValueList[vc_rsu_id].srems); vc_sremEventCounter := (vc_sremEventCounter + 1) mod lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems); } } else { vc_sremEventCounter := (vc_sremEventCounter + 1) mod lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems); } } // End of function f_prepare_srem function f_prepare_ssem( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { log("f_prepare_ssem: vc_ssemEventCounter = ", vc_ssemEventCounter); p_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( vc_rsuMessagesValueList[vc_rsu_id].ssems[vc_ssemEventCounter] ))), PICS_SSEM_BTP_DESTINATION_PORT, PICS_SSEM_BTP_SOURCE_PORT ) ); vc_ssemEventCounter := (vc_ssemEventCounter + 1) mod lengthof(vc_rsuMessagesValueList[vc_rsu_id].ssems); } // End of function f_prepare_ssem /* function f_prepare_evcsn( */ /* out template (value) GnRawPayload p_payload */ /* ) runs on ItsRSUsSimulator { */ /* vc_rsuMessagesValueList[vc_rsu_id].evcsn.evcsn.poiHeader.timeStamp := f_getCurrentTime(); // Check if it is ITS or UTC time */ /* log("vc_rsuMessagesValueList[vc_rsu_id].evcsn", valueof(vc_rsuMessagesValueList[vc_rsu_id].evcsn)); */ /* p_payload := valueof( */ /* f_adaptPayload( */ /* bit2oct( */ /* encvalue( */ /* valueof( */ /* vc_rsuMessagesValueList[vc_rsu_id].evcsn */ /* ))), */ /* PICS_EVCSN_BTP_DESTINATION_PORT, */ /* PICS_EVCSN_BTP_SOURCE_PORT */ /* ) */ /* ); */ /* } // End of function f_prepare_evcsn */ function f_adaptPayload( in template (value) octetstring p_finalPayload, in template (value) BtpPortId p_destPort, in template (value) BtpPortId p_srcPort := 0, in NextHeader p_nextHeader := PX_GN_UPPER_LAYER ) return template (value) GnRawPayload { var template (value) GnRawPayload v_payload := ''O; if(p_nextHeader == e_any) { v_payload := p_finalPayload; return v_payload; } if(p_nextHeader == e_ipv6) { log("*** " & testcasename() & ": INCONC: Layer IPv6 not supported ***"); setverdict(inconc); stop; } if(p_nextHeader == e_btpA) { v_payload := int2oct(valueof(p_destPort), 2) & int2oct(valueof(p_srcPort), 2) & valueof(p_finalPayload); return v_payload; } if(p_nextHeader == e_btpB) { v_payload := int2oct(valueof(p_destPort), 2) & int2oct(valueof(p_srcPort), 2) & valueof(p_finalPayload); return v_payload; } return v_payload; } // End of function f_adaptPayload function f_isInApproach( in ThreeDLocation p_detectionPoint, in ThreeDLocation p_location, in float p_dist := 150.0 ) return boolean { var float v_dist := fx_computeDistance(p_detectionPoint.latitude, p_detectionPoint.longitude, p_location.latitude, p_location.longitude); log("v_dist = ", v_dist); return v_dist <= p_dist; } function f_mirror_and_send_vehicle_cam( in template (value) CAM p_camSimu, in CAM p_camVehicle, in ThreeDLocation p_location ) runs on ItsRSUsSimulator { // Local variables var ReferencePosition v_newPosition := p_camVehicle.cam.camParameters.basicContainer.referencePosition; var template (value) GnRawPayload v_payload; // Apply 90° rotation if (PICS_USE_LPV == true) { fx_computePositionFromRotation( p_location.latitude, p_location.longitude, PICS_UC6_COLLISION_POINT_Z2.latitude, // Z1 PICS_UC6_COLLISION_POINT_Z2.longitude, // Z1 900, v_newPosition.latitude, v_newPosition.longitude ); log("Rotation: (", p_location.latitude, ", ", p_location.longitude, ") --> (", v_newPosition.latitude, ", ", v_newPosition.longitude, ")"); } else { fx_computePositionFromRotation( p_camVehicle.cam.camParameters.basicContainer.referencePosition.latitude, p_camVehicle.cam.camParameters.basicContainer.referencePosition.longitude, PICS_UC6_COLLISION_POINT_Z2.latitude, // Z1 PICS_UC6_COLLISION_POINT_Z2.longitude, // Z1 2450, v_newPosition.latitude, v_newPosition.longitude ); log("Rotation: (", p_camVehicle.cam.camParameters.basicContainer.referencePosition.latitude, ", ", p_camVehicle.cam.camParameters.basicContainer.referencePosition.longitude, ") --> (", v_newPosition.latitude, ", ", v_newPosition.longitude, ")"); } /*v_newPosition.latitude := ; v_newPosition.longitude := ;*/ // Update CAM p_camSimu.cam.generationDeltaTime := f_getCurrentTime() mod 65536; // See ETSI EN 302 637-2 V1.3.0 - Clause B.3 generationDelatTime p_camSimu.cam.camParameters.basicContainer.referencePosition := v_newPosition; p_camSimu.cam.camParameters.highFrequencyContainer := p_camVehicle.cam.camParameters.highFrequencyContainer; v_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( p_camSimu ))), PICS_CAM_BTP_DESTINATION_PORT, PICS_CAM_BTP_SOURCE_PORT ) ); // Update GN vc_longPosVectorRsu := PICS_UC6_VEHICLE_TEMPLATE_POSITION; vc_longPosVectorRsu.latitude := valueof(p_camSimu.cam.camParameters.basicContainer.referencePosition.latitude); vc_longPosVectorRsu.longitude := valueof(p_camSimu.cam.camParameters.basicContainer.referencePosition.longitude); vc_geoArea := PICS_UC6_VEHICLE_TEMPLATE_GEOAREA; vc_geoArea.area.geoAreaPosLatitude := valueof(p_camSimu.cam.camParameters.basicContainer.referencePosition.latitude); vc_geoArea.area.geoAreaPosLongitude := valueof(p_camSimu.cam.camParameters.basicContainer.referencePosition.longitude); // And send it f_send(v_payload, PICS_CAM_ITS_AID); } // End of function f_mirror_and_send_vehicle_cam function f_send( in template (value) GnRawPayload p_payload, in UInt32 p_its_aid ) runs on ItsRSUsSimulator { var GeoNetworkingPdu v_geoNetworkingPdu; vc_longPosVectorRsu.timestamp_ := f_computeGnTimestamp(); if (p_its_aid == 36) { // CAM v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwShbPacket_payload( vc_longPosVectorRsu, valueof(p_payload) ), Lifetime:{ multiplier := c_defaultLifetime, ltBase := e_100s }, c_hopLimit1 )); } else if (p_its_aid == 37) { // DENM v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwTsbPacket_payload( f_incLocalSeqNumber(), vc_longPosVectorRsu, -, -, valueof(p_payload) ), Lifetime:{ multiplier := c_defaultLifetime, ltBase := e_100s }, c_hopLimit1 )); } else if ((p_its_aid == 137) or (p_its_aid == 138)) { // MAPEM/SPATEM v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwBroadcastPacket_payload( vc_longPosVectorRsu, f_incLocalSeqNumber(), f_geoArea2GeoBroadcastArea(vc_geoArea), -, -, valueof(p_payload) ), Lifetime:{ multiplier := c_defaultLifetime, ltBase := e_100s }, c_hopLimit1 )); } else if (p_its_aid == 139) { // IVIM v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwBroadcastPacket_payload( vc_longPosVectorRsu, f_incLocalSeqNumber(), f_geoArea2GeoBroadcastArea(vc_geoArea), -, -, valueof(p_payload) ), Lifetime:{ multiplier := c_defaultLifetime, ltBase := e_100s }, c_hopLimit1 )); } else if (p_its_aid == 140) { // SxEM v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwBroadcastPacket_payload( vc_longPosVectorRsu, f_incLocalSeqNumber(), f_geoArea2GeoBroadcastArea(vc_geoArea), -, -, valueof(p_payload) ), Lifetime:{ multiplier := c_defaultLifetime, ltBase := e_100s }, c_hopLimit1 )); } else if (p_its_aid == 140) { // RTCMEM v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwBroadcastPacket_payload( vc_longPosVectorRsu, f_incLocalSeqNumber(), f_geoArea2GeoBroadcastArea(vc_geoArea), -, -, valueof(p_payload) ), Lifetime:{ multiplier := c_defaultLifetime, ltBase := e_100s }, c_hopLimit1 )); } else { // Beacon v_geoNetworkingPdu := valueof(vc_rsuMessagesValueList[vc_rsu_id].beacon); } f_sendGeoNetMessage(valueof(m_geoNwReq_linkLayerBroadcast(v_geoNetworkingPdu, p_its_aid))); } // End of function f_send function f_processBeacon( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processBeacon: Beacon=", p_geoNetworkingPdu); if (PICS_SEND_BEACON_INDICATION) { var UtGnEventInd v_utGnEventInd; var integer v_result; // Extract BEACON message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Send UtGnEventInd log("f_processBeacon: v_payload=", v_payload); v_utGnEventInd.rawPayload := v_payload; cfPort.send(v_utGnEventInd); } } function f_processCam( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processCam: CAM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_CAM_INDICATION) { var UtCamEventInd v_utCamEventInd; var integer v_result; // Extract CAM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtCamEventInd log("f_processCam: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utCamEventInd.camMsg) == 0) { cfPort.send(v_utCamEventInd); } } } function f_processDenm( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processDenm: DENM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_DENM_INDICATION) { var UtDenmEventInd v_utDenmEventInd; var integer v_result; // Extract DENM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtDenmEventInd log("f_processDenm: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utDenmEventInd.denMsg) == 0) { cfPort.send(v_utDenmEventInd); } } } function f_processIvim( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processIvim: IVIM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_IVIM_INDICATION) { var UtIvimEventInd v_utIvimEventInd; var integer v_result; // Extract IVIM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtIvimEventInd log("f_processIvim: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utIvimEventInd.iviMsg) == 0) { cfPort.send(v_utIvimEventInd); } } } function f_processMapem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processMapem: MAPEM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_MAPEM_INDICATION) { var UtMapemEventInd v_utMapemEventInd; var integer v_result; // Extract MAPEM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtMapemEventInd log("f_processMapem: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utMapemEventInd.mapeMsg) == 0) { cfPort.send(v_utMapemEventInd); } } } function f_processSpatem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processSpatem: SPATEM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_SPATEM_INDICATION) { var UtSpatemEventInd v_utSpatemEventInd; var integer v_result; // Extract SPATEM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtSpatemEventInd log("f_processSpatem: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utSpatemEventInd.spateMsg) == 0) { cfPort.send(v_utSpatemEventInd); } } } function f_processSrem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processSrem: SREM=", p_geoNetworkingPdu); if (ispresent(p_geoNetworkingPdu.gnPacket.packet.payload)) { var integer v_result; var bitstring v_bs; var BtpPacket v_btp; var SREM v_srem; var SSEM v_ssem; // Extract SREM payload v_bs := oct2bit(p_geoNetworkingPdu.gnPacket.packet.payload); v_result := decvalue(v_bs, v_btp); // FIXME Check p_geoNetworkingPdu.gnPacket.commonHeader.nextHeader v_bs := oct2bit(valueof(v_btp.payload)); v_result := decvalue(v_bs, v_srem); log("f_processSrem: SignalRequestMessage: ", v_srem.srm); if (v_srem.srm.requests[0].request.requestType == priorityCancellation) { // FIXME Remove it from the list of the SSEMs vc_rsuMessagesValueList[vc_rsu_id].ssems := {}; } else { // FIXME Find it into the list of the SSEMs v_ssem := valueof( m_ssemPdu( m_ssem( v_srem.srm ) ) ); v_ssem.ssm.sequenceNumber := v_srem.srm.sequenceNumber + 1; if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].ssems)) { vc_rsuMessagesValueList[vc_rsu_id].ssems[lengthof(vc_rsuMessagesValueList[vc_rsu_id].ssems)] := v_ssem; } else { vc_rsuMessagesValueList[vc_rsu_id].ssems := { v_ssem }; } log("f_processSrem: v_ssem=", v_ssem); } } // else, ignore message if (PICS_SEND_SREM_INDICATION) { var UtSremEventInd v_utSremEventInd; var integer v_result; // Extract SREM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtSremEventInd log("f_processSrem: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utSremEventInd.sreMsg) == 0) { cfPort.send(v_utSremEventInd); } } // else, ignore message } // End of function f_processSrem function f_processSsem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processSsem: SSEM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_SSEM_INDICATION) { var UtSsemEventInd v_utSsemEventInd; var integer v_result; // Extract SSEM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtSsemEventInd log("f_processSsem: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utSsemEventInd.sseMsg) == 0) { cfPort.send(v_utSsemEventInd); } } // else, ignore message } // End of function f_processSsem function f_processRtcmem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; log("f_processRtcmem: RTCMEM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_RTCMEM_INDICATION) { var UtRtcmemEventInd v_utRtcmemEventInd; var integer v_result; // Extract RTCMEM message var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); // Send UtRtcmemEventInd log("f_processRtcmem: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utRtcmemEventInd.rtcmemMsg) == 0) { cfPort.send(v_utRtcmemEventInd); } } } function f_incLocalSeqNumber() runs on ItsRSUsSimulator return UInt16 { vc_localSeqNumber := (vc_localSeqNumber + 1) mod 65536; return vc_localSeqNumber; } function f_incMsgIssueRevision() runs on ItsRSUsSimulator return MsgCount { vc_msgIssueRevision := (vc_msgIssueRevision + 1) mod 128; // See MsgCount declaration return vc_msgIssueRevision; } function f_getMsgIssueRevision() runs on ItsRSUsSimulator return MsgCount { return vc_msgIssueRevision; } function f_incDenmSequenceNumber() runs on ItsRSUsSimulator return SequenceNumber { vc_sequenceNumber := (vc_sequenceNumber + 1) mod 65536; // See SequenceNumber declaration return vc_sequenceNumber; } function f_getDenmSequenceNumber() runs on ItsRSUsSimulator return SequenceNumber { return vc_sequenceNumber; } function f_payload_template( in integer p_dest_port, in integer p_src_port ) return template (present) octetstring { //log(">>> f_payload_template: ", p_dest_port, " - ", p_src_port); var template (value) Oct2 v_t1 := int2oct(p_dest_port, 2); var template (value) Oct2 v_t2 := int2oct(p_src_port, 2); var template (present) octetstring v_t3 := ? /*? length (5 .. 65535)*/; var template (present) octetstring v_out := valueof(v_t1) & valueof(v_t2) & v_t3; //log("<<< f_payload_template: v_out=", v_out); return v_out } altstep a_process_cf_ut_command() runs on ItsRSUsSimulator { var UtGnInitialize v_utGnInitialize; var UtCamInitialize v_utCamInitialize; var UtDenmInitialize v_utDenmInitialize; var UtIvimInitialize v_utIvimInitialize; var UtMapemSpatemInitialize v_utMapemSpatemInitialize; var UtMapemSpatemTrigger v_utMapemSpatemTrigger; var UtSremInitialize v_utSremInitialize; var UtRtcmemInitialize v_utRtcmemInitialize; var UtPkiInitialize v_utPkiInitialize; var UtGnTrigger v_utGnTrigger; var UtCamTrigger v_utCamTrigger; var UtDenmTrigger v_utDenmTrigger; var UtIvimTrigger v_utIvimTrigger; var UtSremTrigger v_utSremTrigger; var UtRtcmemTrigger v_utRtcmemTrigger; var UtDenmUpdate v_utDenmUpdate; var UtIvimUpdate v_utIvimUpdate; var UtSremUpdate v_utSremUpdate; var UtRtcmemUpdate v_utRtcmemUpdate; var UtDenmTermination v_utDenmTermination; var UtIvimTermination v_utIvimTermination; var UtSremCancelation v_utSremCancelation; var UtRtcmemTermination v_utRtcmemTermination; var UtPkiTrigger v_utPkiTrigger; [] cfPort.receive(UtGnInitialize:?) -> value v_utGnInitialize { var GeoNetworkingPdu v_geoNwPdu; log("a_process_cf_ut_command: v_utGnInitialize = ", v_utGnInitialize); v_geoNwPdu :=valueof( m_geoNwPdu( m_geoNwBeaconPacket( vc_longPosVectorRsu ), m_defaultLifetime, 1 ) ); v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnInitializeResult := true } ); repeat; } [] cfPort.receive(UtGnTrigger:?) -> value v_utGnTrigger { log("a_process_cf_ut_command: v_utGnTrigger = ", v_utGnTrigger); if (ischosen(v_utGnTrigger.geoUnicast)) { var GnNonSecuredPacket v_geoNwUnicastPacket := valueof( m_geoNwUnicastPacket_with_payload( vc_longPosVectorRsu, f_getIutShortPosVector(), f_incLocalSeqNumber(), c_defaultHopLimit, v_utGnTrigger.geoUnicast.trafficClass, v_utGnTrigger.geoUnicast.payload )); var GeoNetworkingPdu v_geoNwPdu := valueof( m_geoNwPdu( v_geoNwUnicastPacket, m_lifetimeBase1s(v_utGnTrigger.geoUnicast.lifetime / 1000), c_defaultHopLimit ) ); v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); v_geoNwPdu.gnPacket.packet.extendedHeader.geoUnicastHeader.dstPosVector.gnAddr := v_utGnTrigger.geoUnicast.gnAddress; vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnTriggerResult := true } ); } else if (ischosen(v_utGnTrigger.geoBroadcast)) { var GeoBroadcastArea v_broadcastArea; var GnNonSecuredPacket v_geoNwBroadcastPacket; var GeoNetworkingPdu v_geoNwPdu; if (v_utGnTrigger.geoBroadcast.shape == e_geoCircle) { v_broadcastArea.geoBroadcastSubType := e_geoBroadcastCircle; } else if (v_utGnTrigger.geoBroadcast.shape == e_geoRect) { v_broadcastArea.geoBroadcastSubType := e_geoBroadcastRect; } else if (v_utGnTrigger.geoBroadcast.shape == e_geoElip) { v_broadcastArea.geoBroadcastSubType := e_geoBroadcastElip; } else { v_broadcastArea.geoBroadcastSubType := e_reserved; } v_broadcastArea.geoBroadcastArea := v_utGnTrigger.geoBroadcast.area; v_geoNwBroadcastPacket := valueof( m_geoNwBroadcastPacket_payload( vc_longPosVectorRsu, f_incLocalSeqNumber(), v_broadcastArea, c_defaultHopLimit, v_utGnTrigger.geoBroadcast.trafficClass, v_utGnTrigger.geoBroadcast.payload )); v_geoNwBroadcastPacket.commonHeader.flags := f_isMobile(); v_geoNwPdu := valueof( m_geoNwPdu( v_geoNwBroadcastPacket, m_lifetimeBase1s(v_utGnTrigger.geoBroadcast.lifetime / 1000), c_defaultHopLimit )); v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnTriggerResult := true } ); } else if (ischosen(v_utGnTrigger.geoAnycast)) { var GeoAnycastArea v_anycastArea; var GnNonSecuredPacket v_geoNwAnycastPacket; var GeoNetworkingPdu v_geoNwPdu; if (v_utGnTrigger.geoAnycast.shape == e_geoCircle) { v_anycastArea.geoAnycastSubType := e_geoAnycastCircle; } else if (v_utGnTrigger.geoAnycast.shape == e_geoRect) { v_anycastArea.geoAnycastSubType := e_geoAnycastRect; } else if (v_utGnTrigger.geoAnycast.shape == e_geoElip) { v_anycastArea.geoAnycastSubType := e_geoAnycastElip; } else { v_anycastArea.geoAnycastSubType := e_reserved; } v_anycastArea.geoAnycastArea := v_utGnTrigger.geoAnycast.area; v_geoNwAnycastPacket := valueof( m_geoNwAnycastPacket_payload( vc_longPosVectorRsu, f_incLocalSeqNumber(), v_anycastArea, c_defaultHopLimit, v_utGnTrigger.geoAnycast.trafficClass, v_utGnTrigger.geoAnycast.payload )); v_geoNwPdu := valueof( m_geoNwPdu( v_geoNwAnycastPacket, m_lifetimeBase1s(v_utGnTrigger.geoAnycast.lifetime / 1000), c_defaultHopLimit )); v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnTriggerResult := true } ); } else if (ischosen(v_utGnTrigger.shb)) { var GnNonSecuredPacket v_geoShbPacket; var GeoNetworkingPdu v_geoNwPdu; v_geoShbPacket := valueof( m_geoNwShbPacket_payload( vc_longPosVectorRsu, v_utGnTrigger.shb.payload )); v_geoShbPacket.commonHeader.maxHopLimit := 1; v_geoShbPacket.commonHeader.trafficClass.scf := v_utGnTrigger.shb.trafficClass.scf; v_geoShbPacket.commonHeader.trafficClass.channelOffload := v_utGnTrigger.shb.trafficClass.channelOffload; v_geoShbPacket.commonHeader.trafficClass.tcId := v_utGnTrigger.shb.trafficClass.tcId; v_geoNwPdu := valueof( m_geoNwPdu( v_geoShbPacket, m_defaultLifetime, 1 )); v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnTriggerResult := true } ); } else if (ischosen(v_utGnTrigger.tsb)) { var GnNonSecuredPacket v_geoTsbPacket; var GeoNetworkingPdu v_geoNwPdu; v_geoTsbPacket := valueof( m_geoNwTsbPacket_payload( f_incLocalSeqNumber(), vc_longPosVectorRsu, -, -, v_utGnTrigger.tsb.payload )); v_geoTsbPacket.commonHeader.trafficClass.scf := v_utGnTrigger.tsb.trafficClass.scf; v_geoTsbPacket.commonHeader.trafficClass.channelOffload := v_utGnTrigger.tsb.trafficClass.channelOffload; v_geoTsbPacket.commonHeader.trafficClass.tcId := v_utGnTrigger.tsb.trafficClass.tcId; v_geoNwPdu := valueof( m_geoNwPdu( v_geoTsbPacket, m_defaultLifetime, c_defaultHopLimit )); v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnTriggerResult := true } ); } else { cfPort.send(UtGnResults: { utGnTriggerResult := false } ); } repeat; } [vc_cam == true] cfPort.receive(UtCamInitialize:?) -> value v_utCamInitialize { log("a_process_cf_ut_command: v_utCamInitialize = ", v_utCamInitialize); if (oct2int(v_utCamInitialize.hashedId8) != 0) { var charstring v_certificate_id; var EtsiTs103097Certificate v_certificate; log("a_process_cf_ut_command: Looking for certificate ", v_utCamInitialize.hashedId8); f_getCertificateFromDigest(v_utCamInitialize.hashedId8, v_certificate, v_certificate_id); log("a_process_cf_ut_command (pki): Change certificate to ", v_certificate_id); f_acTriggerSecEvent(m_acEnableSecurity(v_certificate_id)); } vc_cam_timer_value := 1.0; // Reset CAM timer vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.curvature.curvatureValue := 0; vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.heading.headingValue := 0; vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.lowFrequencyContainer.basicVehicleContainerLowFrequency.vehicleRole := default_; vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.specialVehicleContainer := omit; cfPort.send(UtCamResults: { utCamInitializeResult := true } ); repeat; } [vc_cam == true] cfPort.receive(UtCamTrigger: { changeSpeed := ? }) -> value v_utCamTrigger { log("a_process_cf_ut_command: v_utCamTrigger = ", v_utCamTrigger); cfPort.send(UtCamResults: { utCamTriggerResult := true } ); vc_cam_timer_value := vc_cam_timer_value / 2.0; repeat; } [vc_cam == true] cfPort.receive(UtCamTrigger: { changeCurvature := ? }) -> value v_utCamTrigger { log("a_process_cf_ut_command: v_utCamTrigger = ", v_utCamTrigger); if (ischosen(vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency)) { cfPort.send(UtCamResults: { utCamTriggerResult := true } ); vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.curvature.curvatureValue := v_utCamTrigger.changeCurvature; } else { cfPort.send(UtCamResults: { utCamTriggerResult := false } ); } repeat; } [vc_cam == true] cfPort.receive(UtCamTrigger: { changeHeading := ? }) -> value v_utCamTrigger { log("a_process_cf_ut_command: v_utCamTrigger = ", v_utCamTrigger); if (ischosen(vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency)) { cfPort.send(UtCamResults: { utCamTriggerResult := true } ); vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.heading.headingValue := valueof(vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.heading.headingValue) + v_utCamTrigger.changeHeading; } else { cfPort.send(UtCamResults: { utCamTriggerResult := false } ); } repeat; } [vc_cam == true] cfPort.receive(UtCamTrigger: { setVehicleRole := ? }) -> value v_utCamTrigger { log("a_process_cf_ut_command: v_utCamTrigger = ", v_utCamTrigger); vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.lowFrequencyContainer.basicVehicleContainerLowFrequency.vehicleRole := v_utCamTrigger.setVehicleRole; vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.specialVehicleContainer := { publicTransportContainer := { embarkationStatus := true, ptActivation := omit } }; cfPort.send(UtCamResults: { utCamTriggerResult := true } ); repeat; } [] cfPort.receive(UtDenmInitialize:?) -> value v_utDenmInitialize { log("a_process_cf_ut_command: v_utDenmInitialize = ", v_utDenmInitialize); vc_rsuMessagesValueList[vc_rsu_id].denms := {}; vc_denmEventCounter := 0; vc_denm := true; cfPort.send(UtDenmResults: { utDenmInitializeResult := true } ); repeat; } [vc_denm == true] cfPort.receive(UtDenmTrigger:?) -> value v_utDenmTrigger { var template (value) DenmParmContainers v_denmParmContainers; var DenmEventsParmsPerZone v_denmEventsParmsPerZone := PICS_DENM_EVENTS_RSU_UC1[vc_rsu_id][PX_ETSI_ZONE_ID - 1]; var integer seq_number := f_incDenmSequenceNumber(); log("a_process_cf_ut_command: v_utDenmTrigger: ", v_utDenmTrigger); v_denmParmContainers := m_denmParmContainers( PICS_RSU_PARAMS[vc_rsu_id].stationID, seq_number, v_utDenmTrigger.repetitionInterval, v_denmEventsParmsPerZone[0].eventPosition, v_utDenmTrigger.situation.eventType.causeCode, v_denmEventsParmsPerZone[0].eventHistory, v_denmEventsParmsPerZone[0].traces, v_utDenmTrigger.validityDuration, v_utDenmTrigger.relevanceDistance, v_utDenmTrigger.relevanceTrafficDirection ); v_denmParmContainers.managementContainer.detectionTime := v_utDenmTrigger.detectionTime; vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms)] := valueof( m_denmPdu_rsu( PICS_RSU_PARAMS[vc_rsu_id].stationID, m_denm( v_denmParmContainers.managementContainer, v_denmParmContainers.situationContainer, v_denmParmContainers.locationContainer ))); log("a_process_cf_ut_command: utDenmTrigger: denm=[" & int2char(lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1) & "]=", vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1]); //denm={ { header := { protocolVersion := 2, messageID := 1, stationID := 1111101 }, denm := { management := { actionID := { originatingStationID := 1111101, sequenceNumber := 1 }, detectionTime := 510819417810, referenceTime := 510819420809, termination := omit, eventPosition := { latitude := 367467556, longitude := -45552381, positionConfidenceEllipse := { semiMajorConfidence := 100, semiMinorConfidence := 100, semiMajorOrientation := 0 }, altitude := { altitudeValue := 0, altitudeConfidence := alt_000_01 (0) } }, relevanceDistance := lessThan50m (0), relevanceTrafficDirection := upstreamTraffic (1), validityDuration := 2, transmissionInterval := omit, stationType := 15 }, situation := { informationQuality := 0, eventType := { causeCode := 91, subCauseCode := 0 }, linkedCause := omit, eventHistory := { { eventPosition := { deltaLatitude := 135, deltaLongitude := -147, deltaAltitude := 0 }, eventDeltaTime := omit, informationQuality := 0 }, { eventPosition := { deltaLatitude := -68, deltaLongitude := 74, deltaAltitude := 0 }, eventDeltaTime := omit, informationQuality := 0 } } }, location := { eventSpeed := omit, eventPositionHeading := omit, traces := { { { pathPosition := { deltaLatitude := -1086, deltaLongitude := 2551, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -450, deltaLongitude := 1010, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -460, deltaLongitude := 1000, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -440, deltaLongitude := 1000, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -440, deltaLongitude := 990, deltaAltitude := 0 }, pathDeltaTime := omit } } }, roadType := omit }, alacarte := omit } } } if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) == 1) { tc_denm.start; } cfPort.send(UtDenmResults: { utDenmTriggerResult := { result := true, actionId := vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1].denm.management.actionID } } ); repeat; } [vc_denm == true] cfPort.receive(UtDenmUpdate:?) -> value v_utDenmUpdate { var integer v_i := 0; var boolean v_found := false; log("a_process_cf_ut_command: v_utDenmUpdate = ", v_utDenmUpdate); for (v_i := 0; v_i < lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); v_i := v_i + 1) { if (v_utDenmUpdate.actionId.sequenceNumber == valueof(vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.actionID.sequenceNumber)) { v_found := true; break; } } // End of 'for' statement if (v_found == true) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.detectionTime := v_utDenmUpdate.detectionTime; if (ispresent(v_utDenmUpdate.validityDuration)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.validityDuration := v_utDenmUpdate.validityDuration; } if (ispresent(v_utDenmUpdate.situation)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.situation := v_utDenmUpdate.situation; } if (ispresent(v_utDenmUpdate.relevanceDistance)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.relevanceDistance := v_utDenmUpdate.relevanceDistance; } if (ispresent(v_utDenmUpdate.relevanceTrafficDirection)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.relevanceTrafficDirection := v_utDenmUpdate.relevanceTrafficDirection; } if (ispresent(v_utDenmUpdate.transmissionInterval)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.transmissionInterval := v_utDenmUpdate.transmissionInterval; } if (ispresent(v_utDenmUpdate.transmissionInterval)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.transmissionInterval := v_utDenmUpdate.transmissionInterval; } if (ispresent(v_utDenmUpdate.alacarte)) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.alacarte := v_utDenmUpdate.alacarte; } } cfPort.send(UtDenmResults: { utDenmUpdateResult := { result := true, actionId := vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.actionID } } ); repeat; } [vc_denm == true] cfPort.receive(UtDenmTermination:?) -> value v_utDenmTermination { var integer v_i := 0; var boolean v_found := false; log("a_process_cf_ut_command: v_utDenmTermination: ", v_utDenmTermination); for (v_i := 0; v_i < lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); v_i := v_i + 1) { if (v_utDenmTermination.actionId.sequenceNumber == valueof(vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.actionID.sequenceNumber)) { v_found := true; break; } } // End of 'for' statement if (v_found == true) { log("a_process_cf_ut_command: v_utDenmTermination: v_i=", v_i); log("a_process_cf_ut_command: v_utDenmTermination: l=", lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms)); if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) > 1) { //Shift elements for (var integer v_j := v_i + 1; v_i < lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); v_i := v_i + 1) { vc_rsuMessagesValueList[vc_rsu_id].denms[v_i] := vc_rsuMessagesValueList[vc_rsu_id].denms[v_j]; v_j := v_j + 1; } // End of 'for' statement vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1] := {} } else { vc_rsuMessagesValueList[vc_rsu_id].denms := {}; vc_denmEventCounter := 0; } log("v_utDenmTermination: New l=", lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms)); if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) == 0) { tc_denm.stop; f_sleep(1.0); vc_denm := false; } cfPort.send(UtDenmResults: { utDenmTerminationResult := true } ); } repeat; } [] cfPort.receive(UtIvimInitialize:?) -> value v_utIvimInitialize { log("a_process_cf_ut_command: v_utIvimInitialize = ", v_utIvimInitialize); if (oct2int(v_utIvimInitialize.hashedId8) != 0) { var charstring v_certificate_id; var EtsiTs103097Certificate v_certificate; log("a_process_cf_ut_command: Looking for certificate ", v_utIvimInitialize.hashedId8); f_getCertificateFromDigest(v_utIvimInitialize.hashedId8, v_certificate, v_certificate_id); log("a_process_cf_ut_command (pki): Change certificate to ", v_certificate_id); f_acTriggerSecEvent(m_acEnableSecurity(v_certificate_id)); } if (vc_ivim == false) { vc_rsuMessagesValueList[vc_rsu_id].ivim := m_ivimParm( PICS_RSU_PARAMS[vc_rsu_id].stationID, m_ivimStructure( m_iviManagementContainer( PICS_IVIM_PARMS_RSUs[vc_rsu_id].provider, PICS_IVIM_PARMS_RSUs[vc_rsu_id].iviIdentificationNumber, 0//IviStatus_new_ ), PICS_IVIM_PARMS_RSUs[vc_rsu_id].iviContainers )); // Update ivi status vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validFrom := f_getCurrentTime(); vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validTo := valueof(vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validFrom) + 43200000; // 12hours } vc_ivim := true; cfPort.send(UtIvimResults: { utIvimInitializeResult := true } ); repeat; } [vc_ivim == true] cfPort.receive(UtIvimTrigger:?) -> value v_utIvimTrigger { log("a_process_cf_ut_command: v_utIvimTrigger: ", v_utIvimTrigger); vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.iviIdentificationNumber := 10; if (ispresent(v_utIvimTrigger.validTo)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validTo := v_utIvimTrigger.validTo; } if (ispresent(v_utIvimTrigger.validFrom)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validFrom := v_utIvimTrigger.validFrom; } if (ispresent(v_utIvimTrigger.zoneIds)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_ := { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0] }; vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts := { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts[0] }; vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts[0].zoneId := v_utIvimTrigger.zoneIds[0]; for (var integer v_idx := 1; v_idx < lengthof(v_utIvimTrigger.zoneIds); v_idx := v_idx + 1) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts[v_idx] := vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts[v_idx - 1]; vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts[v_idx].zoneId := v_utIvimTrigger.zoneIds[v_idx]; } // End of 'for' statement } if (ispresent(v_utIvimTrigger.laneNumber)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.optional_[0].glc.parts[0].laneNumber := v_utIvimTrigger.laneNumber; } cfPort.send(UtIvimResults: { utIvimTriggerResult := { result:= true, iviIdentificationNumber := 10 } } ); tc_ivim.start; repeat; } [vc_ivim == true] cfPort.receive(UtIvimUpdate:?) -> value v_utIvimUpdate { if (ispresent(v_utIvimUpdate.validTo)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validTo := v_utIvimUpdate.validTo; } if (ispresent(v_utIvimUpdate.validFrom)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.validFrom := v_utIvimUpdate.validFrom; } if (ispresent(v_utIvimUpdate.timeStamp)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.timeStamp := v_utIvimUpdate.validFrom; } if (ispresent(v_utIvimUpdate.connectedIviStructures)) { vc_rsuMessagesValueList[vc_rsu_id].ivim.ivi.mandatory.connectedIviStructures := v_utIvimUpdate.connectedIviStructures } cfPort.send(UtIvimResults: { utIvimUpdateResult := { result:= true, iviIdentificationNumber := 10 } } ); repeat; } [vc_ivim == true] cfPort.receive(UtIvimTermination:?) -> value v_utIvimTermination { log("a_process_cf_ut_command: v_utIvimTermination: ", v_utIvimTermination); tc_ivim.stop; vc_ivim := false; cfPort.send(UtIvimResults: { utIvimTerminationResult := true } ); repeat; } [] cfPort.receive(UtMapemSpatemInitialize:?) -> value v_utMapemSpatemInitialize { log("a_process_cf_ut_command: v_utMapemSpatemInitialize = ", v_utMapemSpatemInitialize); if (oct2int(v_utMapemSpatemInitialize.hashedId8) != 0) { var charstring v_certificate_id; var EtsiTs103097Certificate v_certificate; log("a_process_cf_ut_command: Looking for certificate ", v_utMapemSpatemInitialize.hashedId8); f_getCertificateFromDigest(v_utMapemSpatemInitialize.hashedId8, v_certificate, v_certificate_id); log("a_process_cf_ut_command (pki): Change certificate to ", v_certificate_id); f_acTriggerSecEvent(m_acEnableSecurity(v_certificate_id)); } if (vc_mapem == false) { vc_rsuMessagesValueList[vc_rsu_id].mapem := m_mapemParm( PICS_RSU_PARAMS[vc_rsu_id].stationID, m_mapem( f_getMsgIssueRevision(), c_PICS_ConfTest_ProfileId_0.intersections, omit )); // Update revision fields vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].revision := f_incMsgIssueRevision(); // TODO Add more? } log("a_process_cf_ut_command: MAPEM=", vc_rsuMessagesValueList[vc_rsu_id].mapem); vc_mapem := true; tc_mapem.start; cfPort.send(UtMapemSpatemResults: { utMapemSpatemInitializeResult := true } ); repeat; } [vc_mapem == true] cfPort.receive(UtMapemSpatemTrigger:?) -> value v_utMapemSpatemTrigger { log("a_process_cf_ut_command: v_utMapemSpatemTrigger: ", v_utMapemSpatemTrigger); if (v_utMapemSpatemTrigger.event == mapemNewContent) { // TODO To be reviewd /*vc_rsuMessagesValueList[vc_rsu_id].mapem := m_mapemParm( PICS_RSU_PARAMS[vc_rsu_id].stationID, m_mapem( f_getMsgIssueRevision(), c_PICS_ConfTest_ProfileId_0.intersections, omit ));*/ } if (v_utMapemSpatemTrigger.intersectionID != valueof(vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].id.id)) { // TODO } if ( not(ispresent(vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].speedLimits)) or (v_utMapemSpatemTrigger.regulatorySpeedLimit != valueof(vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].speedLimits[0])) ) { // Update field and increment revision vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].speedLimits[0] := v_utMapemSpatemTrigger.regulatorySpeedLimit; vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].revision := valueof(vc_rsuMessagesValueList[vc_rsu_id].mapem.map_.intersections[0].revision) + 1; } cfPort.send(UtMapemSpatemResults: { utMapemSpatemTriggerResult := true } ); tc_mapem.start; repeat; } [] cfPort.receive(UtRtcmemInitialize:?) -> value v_utRtcmemInitialize { log("a_process_cf_ut_command: v_utRtcmemInitialize = ", v_utRtcmemInitialize); if (oct2int(v_utRtcmemInitialize.hashedId8) != 0) { var charstring v_certificate_id; var EtsiTs103097Certificate v_certificate; log("a_process_cf_ut_command: Looking for certificate ", v_utRtcmemInitialize.hashedId8); f_getCertificateFromDigest(v_utRtcmemInitialize.hashedId8, v_certificate, v_certificate_id); log("a_process_cf_ut_command (pki): Change certificate to ", v_certificate_id); f_acTriggerSecEvent(m_acEnableSecurity(v_certificate_id)); } vc_rsuMessagesValueList[vc_rsu_id].rtcmem := valueof( m_rtcmemPdu( m_defaultRtcmem( 123, -, { '00000000'O, '01010101'O } ))); vc_rtcmem := true; cfPort.send(UtRtcmemResults: { utRtcmemInitializeResult := true } ); repeat; } [vc_rtcmem == true] cfPort.receive(UtRtcmemTrigger:?) -> value v_utRtcmemTrigger { log("a_process_cf_ut_command: v_utRtcmemTrigger: ", v_utRtcmemTrigger); vc_rsuMessagesValueList[vc_rsu_id].rtcmem.rtcmc.msgCnt := v_utRtcmemTrigger.msgCnt; vc_rsuMessagesValueList[vc_rsu_id].rtcmem.rtcmc.rev := v_utRtcmemTrigger.rev; vc_rsuMessagesValueList[vc_rsu_id].rtcmem.rtcmc.msgs := v_utRtcmemTrigger.msgs; // TODO Add optional part cfPort.send(UtRtcmemResults: { utRtcmemTriggerResult := true } ); tc_rtcmem.start; repeat; } [vc_rtcmem == true] cfPort.receive(UtRtcmemUpdate:?) -> value v_utRtcmemUpdate { vc_rsuMessagesValueList[vc_rsu_id].rtcmem.rtcmc.msgs := v_utRtcmemUpdate.msgs; cfPort.send(UtRtcmemResults: { utRtcmemUpdateResult := true } ); repeat; } [vc_rtcmem == true] cfPort.receive(UtRtcmemTermination:?) -> value v_utRtcmemTermination { log("a_process_cf_ut_command: v_utRtcmemTermination: ", v_utRtcmemTermination); tc_rtcmem.stop; vc_rtcmem := false; cfPort.send(UtRtcmemResults: { utRtcmemTerminationResult := true } ); repeat; } [] cfPort.receive(UtSremInitialize:?) -> value v_utSremInitialize { log("a_process_cf_ut_command: v_utSremInitialize = ", v_utSremInitialize); if (oct2int(v_utSremInitialize.hashedId8) != 0) { var charstring v_certificate_id; var EtsiTs103097Certificate v_certificate; log("a_process_cf_ut_command: Looking for certificate ", v_utSremInitialize.hashedId8); f_getCertificateFromDigest(v_utSremInitialize.hashedId8, v_certificate, v_certificate_id); log("a_process_cf_ut_command (pki): Change certificate to ", v_certificate_id); f_acTriggerSecEvent(m_acEnableSecurity(v_certificate_id)); } // Reset SxEM lists & counters vc_sremEventCounter := 0; vc_rsuMessagesValueList[vc_rsu_id].srems := {}; vc_ssemEventCounter := 0; vc_rsuMessagesValueList[vc_rsu_id].ssems := {}; vc_srem := true; cfPort.send(UtSremResults: { utSremInitializeResult := true } ); repeat; } [vc_srem == true] cfPort.receive(UtSremTrigger:?) -> value v_utSremTrigger { var integer v_idx := lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems); log("a_process_cf_ut_command: v_utSremTrigger: ", v_utSremTrigger); vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx] := valueof( m_sremPdu( m_srem( m_requestorDescription( m_vehicleID( f_getIutStationId() ), m_requestorType( basicVehicle ), m_requestor_position( LibItsSremSsem_Templates.m_position3D( vc_longPosVectorRsu.latitude, vc_longPosVectorRsu.longitude ) ) ), { m_signalRequestPackage( m_signalRequest( LibItsSremSsem_Templates.m_intersectionReferenceID( PX_INTERSECTION_ID ), PX_REQUEST_ID + lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems), priorityRequest, { lane := 1 } ) ) } ) ) ); vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.type_.role := valueof(v_utSremTrigger.basicVehicleRole); if (valueof(vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.type_.role) == publicTransport) { vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitStatus := LibItsCommon_ASN1_ISDSRC_NamedNumbers.TransitVehicleStatus_atStopLine_; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitOccupancy := occupancyMed; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitSchedule := 35; } else { vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitStatus := omit; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitOccupancy := omit; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitSchedule := omit; } vc_sremEventCounter := v_idx; if (v_idx == 0) { tc_srem.start; } cfPort.send(UtSremResults: { utSremTriggerResult := true } ); repeat; } [vc_srem == true] cfPort.receive(UtSremUpdate:?) -> value v_utSremUpdate { var integer v_idx; log("a_process_cf_ut_command: v_utSremUpdate: ", v_utSremUpdate); for (v_idx := 0; v_idx < lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems); v_idx := v_idx + 1) { if (valueof(vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requests[0].request.requestID) == valueof(v_utSremUpdate.requestID)) { break; } } // End of 'for' statement if (v_idx == lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems)) { log("a_process_cf_ut_command: v_utSremUpdate: Failed to find the requestID ", v_utSremUpdate.requestID); cfPort.send(UtSremResults: { utSremUpdateResult := false } ); } else { vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.type_.role := valueof(v_utSremUpdate.basicVehicleRole); vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.sequenceNumber := valueof(vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.sequenceNumber) + 1; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requests[0].request.requestType := priorityRequestUpdate; if (valueof(vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.type_.role) == publicTransport) { vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitStatus := LibItsCommon_ASN1_ISDSRC_NamedNumbers.TransitVehicleStatus_atStopLine_; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitOccupancy := occupancyMed; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitSchedule := 35; } else { vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitStatus := omit; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitOccupancy := omit; vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requestor.transitSchedule := omit; } cfPort.send(UtSremResults: { utSremUpdateResult := true } ); } repeat; } [vc_srem == true] cfPort.receive(UtSremCancelation:?) -> value v_utSremCancelation { var integer v_idx; log("a_process_cf_ut_command: v_utSremCancelation: ", v_utSremCancelation); log("a_process_cf_ut_command: v_utSremCancelation: vc_rsuMessagesValueList[vc_rsu_id].srems: ", vc_rsuMessagesValueList[vc_rsu_id].srems); for (v_idx := 0; v_idx < lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems); v_idx := v_idx + 1) { if (valueof(vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requests[0].request.requestID) == valueof(v_utSremCancelation.requestID)) { break; } } // End of 'for' statement if (v_idx == lengthof(vc_rsuMessagesValueList[vc_rsu_id].srems)) { log("a_process_cf_ut_command: v_utSremCancelation: Failed to find the requestID ", v_utSremCancelation.requestID); cfPort.send(UtSremResults: { utSremUpdateResult := false } ); } else { vc_rsuMessagesValueList[vc_rsu_id].srems[v_idx].srm.requests[0].request.requestType := priorityCancellation; vc_sremEventCounter := v_idx; log("a_process_cf_ut_command: v_utSremCancelation: Cancelling item # ", vc_sremEventCounter); cfPort.send(UtSremResults: { utSremCancelationResult := true } ); } repeat; } [vc_pki == true] cfPort.receive(UtPkiInitialize:?) -> value v_utPkiInitialize { log("a_process_cf_ut_command: v_utPkiInitialize = ", v_utPkiInitialize); if (oct2int(v_utPkiInitialize.hashedId8) != 0) { var charstring v_certificate_id; var EtsiTs103097Certificate v_certificate; log("a_process_cf_ut_command: Looking for certificate ", v_utPkiInitialize.hashedId8); f_getCertificateFromDigest(v_utPkiInitialize.hashedId8, v_certificate, v_certificate_id); log("a_process_cf_ut_command (pki): Change certificate to ", v_certificate_id); f_acTriggerSecEvent(m_acEnableSecurity(v_certificate_id)); vc_security_state := 0; // 0: initial vc_reenrolment := false; vc_ec_counter := 0; vc_ec_certificates := {}; vc_at_counter := 0; vc_at_certificates := {}; tc_cam.stop; } cfPort.send(UtPkiResults: { utPkiInitializeResult := true } ); repeat; } [vc_pki == true] cfPort.receive(UtPkiTrigger: { triggerEnrolmentRequest := ? }) -> value v_utPkiTrigger { var ItsPkiHttpRsuSimulator v_pki; var EcData v_ec_data; log("a_process_cf_ut_command: v_utPkiTrigger=", v_utPkiTrigger); cfPort.send(UtPkiResults: { utPkiTriggerResult := true } ); v_pki := ItsPkiHttpRsuSimulator.create("TriggeredEc") alive; connect(v_pki:resultPort, self:resultPort); v_pki.start(f_trigger_enrolment_request_await_response()); tc_wait.start; alt { [] resultPort.receive(EcData:?) -> value v_ec_data { tc_wait.stop; vc_ec_certificates[vc_ec_counter] := v_ec_data; vc_ec_counter := vc_ec_counter + 1; vc_reenrolment := true; vc_security_state := 1; // 1:enrolled setverdict(pass); } [] tc_wait.timeout { log("a_process_cf_ut_command: Failed to retrieve EcData"); vc_reenrolment := false; vc_security_state := 0; // 0: initial } } // End of 'alt' statement disconnect(v_pki:resultPort, self:resultPort); v_pki.done; v_pki.kill; repeat; } [vc_pki == true] cfPort.receive(UtPkiTrigger: { triggerAuthorizationRequest := ? }) -> value v_utPkiTrigger { var ItsPkiHttpRsuSimulator v_pki; var AtData v_at_data; cfPort.send(UtPkiResults: { utPkiTriggerResult := true } ); v_pki := ItsPkiHttpRsuSimulator.create("TriggeredAt") alive; connect(v_pki:resultPort, self:resultPort); v_pki.start(f_trigger_authorization_request_await_response( vc_ec_counter, vc_ec_certificates )); tc_wait.start; alt { [] resultPort.receive(AtData:?) -> value v_at_data { tc_wait.stop; vc_at_certificates[vc_at_counter] := v_at_data; vc_at_counter := vc_at_counter + 1; vc_security_state := 2; // 2: authorization setverdict(pass); } [] tc_wait.timeout { log("a_process_cf_ut_command: Failed to retrieve AtData"); vc_security_state := 1; // 1: enrolled } } // End of 'alt' statement disconnect(v_pki:resultPort, self:resultPort); v_pki.done; v_pki.kill; if (vc_security_state == 2) { var octetstring v_cert := bit2oct(encvalue(vc_at_certificates[0].certificate)); var Oct32 v_wholeHash := f_hashWithSha256(v_cert); var HashedId8 v_hashedId8_sha256 := f_hashedId8FromSha256(v_wholeHash); var charstring v_cert_id; var HashedId8 v_hashedId8; var HashedId8 v_issuer; var octetstring v_public_key_x := ''O; var octetstring v_public_key_y := ''O; var octetstring v_public_key_compressed; var integer v_verify_compressed_mode; var template (omit) octetstring v_public_enc_key_x := omit; var template (omit) octetstring v_public_enc_key_y := omit; var template (omit) octetstring v_public_enc_compressed_key := omit; var template (omit) integer v_public_enc_key_compressed_mode := omit; log("a_process_cf_ut_command: triggerAuthorizationRequest: vc_at_counter=", vc_at_counter); log("a_process_cf_ut_command: triggerAuthorizationRequest: vc_at_certificates=", vc_at_certificates); // Prepare to store the new certificate if (ischosen(vc_at_certificates[0].certificate.issuer.sha256AndDigest)) { v_hashedId8 := v_hashedId8_sha256; v_issuer := vc_at_certificates[0].certificate.issuer.sha256AndDigest; } else if (ischosen(vc_at_certificates[0].certificate.issuer.sha384AndDigest)) { v_hashedId8 := f_hashedId8FromSha384(f_hashWithSha384(v_cert)); v_issuer := vc_at_certificates[0].certificate.issuer.sha384AndDigest; } else { log("a_process_cf_ut_command: Wrong certificate format, self_ not expected as issuer, back to initial"); vc_security_state := 0; // 0: initial vc_reenrolment := false; vc_ec_counter := 0; vc_ec_certificates := {}; vc_at_counter := 0; vc_at_certificates := {}; repeat; } v_cert_id := hex2str(oct2hex(v_hashedId8)); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_cert_id =", v_cert_id); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_cert =", v_cert); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_wholeHash =", v_wholeHash); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_hashedId8_sha256 =", v_hashedId8_sha256); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_hashedId8 =", v_hashedId8); // Extract verification keys if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) { if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) { v_public_key_compressed := vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0; v_verify_compressed_mode := 0; } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1)) { v_public_key_compressed := vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1; v_verify_compressed_mode := 1; } else { // TODO } if (lengthof(v_public_key_x) == 0) { v_public_key_x := v_public_key_compressed; // Key X-Coordinate fx_get_uncompressed_key_nistp256(vc_at_certificates[0].private_key, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate } } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1)) { if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) { v_public_key_compressed := vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0; v_verify_compressed_mode := 0; } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1)) { v_public_key_compressed := vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1; v_verify_compressed_mode := 1; } else { // TODO } if (lengthof(v_public_key_x) == 0) { v_public_key_x := v_public_key_compressed; // Key X-Coordinate fx_get_uncompressed_key_brainpoolp256r1(vc_at_certificates[0].private_key, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate } } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1)) { if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_0)) { v_public_key_compressed := vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_0; v_verify_compressed_mode := 0; } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_1)) { v_public_key_compressed := vc_at_certificates[0].certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_1; v_verify_compressed_mode := 1; } else { // TODO } if (lengthof(v_public_key_x) == 0) { v_public_key_x := v_public_key_compressed; // Key X-Coordinate fx_get_uncompressed_key_brainpoolp384r1(vc_at_certificates[0].private_key, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate } } else { log("a_process_cf_ut_command: Wrong certificate format, invalid verification key, back to initial"); vc_security_state := 0; // 0: initial vc_reenrolment := false; vc_ec_counter := 0; vc_ec_certificates := {}; vc_at_counter := 0; vc_at_certificates := {}; repeat; } log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_key_x =", v_public_key_x); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_key_y =", v_public_key_y); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_key_compressed =", v_public_key_compressed); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_verify_compressed_mode=", v_verify_compressed_mode); // Extract encryption key if (ispresent(vc_at_certificates[0].certificate.toBeSigned.encryptionKey)) { if (ischosen(vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256)) { if (ischosen(vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0)) { v_public_enc_compressed_key := vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0; v_public_enc_key_compressed_mode := 0; } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1)) { v_public_enc_compressed_key := vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1; v_public_enc_key_compressed_mode := 1; } else { // TODO } if (not(ispresent(v_public_enc_key_x))) { var octetstring v_key; v_public_enc_key_x := v_public_enc_compressed_key; // Key X-Coordinate fx_get_uncompressed_key_nistp256(vc_at_certificates[0].private_enc_key, valueof(v_public_enc_compressed_key), valueof(v_public_enc_key_compressed_mode), v_key); // Key Y-Coordinate v_public_enc_key_y := v_key; } } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1)) { if (ischosen(vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0)) { v_public_enc_compressed_key := vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0; v_public_enc_key_compressed_mode := 0; } else if (ischosen(vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1)) { v_public_enc_compressed_key := vc_at_certificates[0].certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1; v_public_enc_key_compressed_mode := 1; } else { // TODO } if (not(ispresent(v_public_enc_key_x))) { var octetstring v_key; v_public_enc_key_x := v_public_enc_compressed_key; // Key X-Coordinate fx_get_uncompressed_key_brainpoolp256r1(vc_at_certificates[0].private_enc_key, valueof(v_public_enc_compressed_key), valueof(v_public_enc_key_compressed_mode), v_key); // Key Y-Coordinate v_public_enc_key_y := v_key; } } else { log("a_process_cf_ut_command: Wrong certificate format, invalid verification key, back to initial"); vc_security_state := 0; // 0: initial vc_reenrolment := false; vc_ec_counter := 0; vc_ec_certificates := {}; vc_at_counter := 0; vc_at_certificates := {}; repeat; } } log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_enc_key_x =", v_public_enc_key_x); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_enc_key_y =", v_public_enc_key_y); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_enc_compressed_key =", v_public_enc_compressed_key); log("a_process_cf_ut_command: Prepare to store new AT certificate: v_public_enc_key_compressed_mode=", v_public_enc_key_compressed_mode); // Store the certificate log("a_process_cf_ut_command: Store new AT certificate"); if (fx_store_certificate(v_cert_id, v_cert, vc_at_certificates[0].private_key, v_public_key_x, v_public_key_y, v_public_key_compressed, v_verify_compressed_mode, v_wholeHash, v_hashedId8_sha256, v_hashedId8, v_issuer, vc_at_certificates[0].private_enc_key, v_public_enc_key_x, v_public_enc_key_y, v_public_enc_compressed_key, v_public_enc_key_compressed_mode) == false) { log("a_process_cf_ut_command: Failed to store certificate, back to initial"); vc_security_state := 0; // 0: initial vc_reenrolment := false; vc_ec_counter := 0; vc_ec_certificates := {}; vc_at_counter := 0; vc_at_certificates := {}; repeat; } // Update the Test System log("a_process_cf_ut_command (pki): Change certificate to ", v_cert_id); f_acTriggerSecEvent(m_acEnableSecurity(v_cert_id)); // Enrolled & Authorized, start CAM emission tc_cam.start(vc_cam_timer_value); } repeat; } [] cfPort.receive { // Ignore it log("*** " & testcasename() & ": INFO: Unexpected CF message received ***"); repeat; } } // End of 'altstep' statement function f_trigger_enrolment_request_await_response() runs on ItsPkiHttpRsuSimulator { // Local variables var Oct32 v_private_key; var Oct32 v_compressed_public_key; var integer v_compressed_mode; var Oct32 v_request_hash; var Oct16 v_encrypted_sym_key; var Oct16 v_aes_sym_key; var Oct16 v_authentication_vector; var Oct12 v_nonce; var octetstring v_salt; var Ieee1609Dot2Data v_ieee1609dot2_signed_and_encrypted_data; var Headers v_headers; var HttpMessage v_response; var EtsiTs102941Data v_etsi_ts_102941_data; timer v_t := 5.0; log(">>> f_trigger_enrolment_request_await_response"); f_cfHttpUp(PICS_IUT_EA_CERTIFICATE_ID, PICS_IUT_AA_CERTIFICATE_ID); f_http_build_inner_ec_request(v_private_key, v_compressed_public_key, v_compressed_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, v_salt, v_ieee1609dot2_signed_and_encrypted_data, v_request_hash); f_init_default_headers_list(-, "inner_ec_request", v_headers); httpPort.send( m_http_request( m_http_request_post( PICS_HTTP_POST_URI, v_headers, m_http_message_body_binary( m_binary_body_ieee1609dot2_data( v_ieee1609dot2_signed_and_encrypted_data ))))); // Wait for the resposne v_t.start; alt { [] httpPort.receive( mw_http_response( mw_http_response_ok( mw_http_message_body_binary( mw_binary_body_ieee1609dot2_data( mw_enrolmentResponseMessage( mw_encryptedData( -, mw_SymmetricCiphertext_aes128ccm ))))))) -> value v_response { v_t.stop; log("f_trigger_enrolment_request_await_response: v_response=", v_response); if (f_verify_pki_response_message(v_private_key, v_aes_sym_key, v_authentication_vector, vc_eaWholeHash, v_response.response.body.binary_body.ieee1609dot2_data, false, -, v_etsi_ts_102941_data) == false) { log("f_trigger_enrolment_request_await_response: Failed to verify PKI message ***"); } else { log("f_trigger_enrolment_request_await_response: v_etsi_ts_102941_data=", v_etsi_ts_102941_data); // Verify the received EC certificate log("f_trigger_enrolment_request_await_response: match ", match(v_etsi_ts_102941_data.content, mw_enrolmentResponse(mw_innerEcResponse_ok(substr(v_request_hash, 0, 16), mw_etsiTs103097Certificate(-, mw_toBeSignedCertificate_ec, -)))), " ***"); // TODO In TITAN, this is the only way to get the unmatching in log if (match(v_etsi_ts_102941_data.content, mw_enrolmentResponse(mw_innerEcResponse_ok(substr(v_request_hash, 0, 16), mw_etsiTs103097Certificate(-, mw_toBeSignedCertificate_ec, -))))) { var InnerEcResponse v_inner_ec_response := v_etsi_ts_102941_data.content.enrolmentResponse; if (f_verify_ec_certificate(v_etsi_ts_102941_data.content.enrolmentResponse.certificate, vc_eaCertificate, vc_eaHashedId8, v_compressed_public_key, v_compressed_mode)) { var EcData v_ec_data; log("f_trigger_enrolment_request_await_response: p_inner_ec_response= ", v_inner_ec_response); // Send the new certificate for storing v_ec_data.private_key := v_private_key; v_ec_data.aes_sym_key := v_aes_sym_key; v_ec_data.certificate := v_inner_ec_response.certificate; log("f_trigger_enrolment_request_await_response: send v_ec_data=", v_ec_data); resultPort.send(v_ec_data); } else { log("f_trigger_enrolment_request_await_response: Cannot verify EC certificate signature ***"); } } else { log("f_trigger_enrolment_request_await_response: Unexpected message received ***"); } } } [] v_t.timeout { log("*** " & testcasename() & ": INCONC: Expected message not received ***"); } } // End of 'alt' statement f_cfHttpDown(); log("<<< f_trigger_enrolment_request_await_response"); } function f_trigger_authorization_request_await_response( in integer p_ec_counter, in SequenceOfEcData p_ec_certificates ) runs on ItsPkiHttpRsuSimulator { // Local variables var Oct32 v_private_key_at; var Oct32 v_public_compressed_key_at; var integer p_compressed_mode_at; var Oct32 v_private_enc_key_at; var Oct32 v_public_compressed_enc_key_at; var integer v_compressed_enc_mode_at; var Oct16 v_encrypted_sym_key; var Oct16 v_aes_sym_key; var HashedId8 v_aes_sym_key_hashed_id8; var Oct16 v_authentication_vector; var Oct12 v_nonce; var octetstring v_salt; var Ieee1609Dot2Data v_ieee1609dot2_signed_and_encrypted_data; var Oct32 v_request_hash; var bitstring v_encoded_value; var Ieee1609Dot2Data v_authorization_response; var Headers v_headers; var HttpMessage v_response; var EtsiTs102941Data v_etsi_ts_102941_data; var FncRetCode v_result; timer v_t := 5.0; f_cfHttpUp(PICS_IUT_EA_CERTIFICATE_ID, PICS_IUT_AA_CERTIFICATE_ID); f_http_build_authorization_request( p_ec_certificates[p_ec_counter - 1].certificate, p_ec_certificates[p_ec_counter - 1].private_key, v_private_key_at, v_public_compressed_key_at, p_compressed_mode_at, v_private_enc_key_at, v_public_compressed_enc_key_at, v_compressed_enc_mode_at, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, v_salt, v_ieee1609dot2_signed_and_encrypted_data, v_request_hash); log("f_trigger_authorization_request_await_response: v_ieee1609dot2_signed_and_encrypted_data=", v_ieee1609dot2_signed_and_encrypted_data); v_aes_sym_key_hashed_id8 := f_hashedId8FromSha256(f_hashWithSha256('80'O & v_aes_sym_key)); // Used to match the response f_init_default_headers_list(-, "inner_at_request", v_headers); httpPort.send( m_http_request( m_http_request_post( PICS_HTTP_POST_URI_AT, v_headers, m_http_message_body_binary( m_binary_body_ieee1609dot2_data( v_ieee1609dot2_signed_and_encrypted_data ))))); // Wait for the resposne v_t.start; alt { [] httpPort.receive( mw_http_response( mw_http_response_ok( mw_http_message_body_binary( mw_binary_body_ieee1609dot2_data( mw_enrolmentResponseMessage( mw_encryptedData( -, mw_SymmetricCiphertext_aes128ccm ))))))) -> value v_response { v_t.stop; log("f_trigger_authorization_request_await_response: v_response=", v_response); if (f_verify_pki_response_message(v_private_key_at, v_aes_sym_key, v_authentication_vector, v_request_hash, v_response.response.body.binary_body.ieee1609dot2_data, false, -, v_etsi_ts_102941_data) == false) { log("f_trigger_authorization_request_await_response: Failed to verify PKI message"); } else { log("f_trigger_authorization_request_await_response: v_etsi_ts_102941_data=", v_etsi_ts_102941_data); // Verify the received AT certificate log(match(v_etsi_ts_102941_data.content, mw_authorizationResponse(mw_innerAtResponse_ok(substr(v_request_hash, 0, 16), mw_etsiTs103097Certificate(-, mw_toBeSignedCertificate_at, -))))); // TODO In TITAN, this is the only way to get the unmatching in log if (match(v_etsi_ts_102941_data.content, mw_authorizationResponse(mw_innerAtResponse_ok(substr(v_request_hash, 0, 16), mw_etsiTs103097Certificate(-, mw_toBeSignedCertificate_at, -)))) == true) { var InnerAtResponse v_inner_at_response := v_etsi_ts_102941_data.content.authorizationResponse; var AtData v_at_data; log("f_trigger_enrolment_request_await_response: p_inner_at_response= ", v_inner_at_response); // Send the new certificate for storing v_at_data.private_key := v_private_key_at; v_at_data.private_enc_key := v_private_enc_key_at; v_at_data.aes_sym_key := v_aes_sym_key; v_at_data.certificate := v_inner_at_response.certificate; log("f_trigger_enrolment_request_await_response: send v_at_data=", v_at_data); resultPort.send(v_at_data); // TODO Provide the new certificate to the Test System // TODO Start CAM emission } else { log("f_trigger_authorization_request_await_response: Cannot verify AT certificate signature ***"); } } } [] v_t.timeout { log("*** " & testcasename() & ": INCONC: Expected message not received ***"); } } // End of 'alt' statement f_cfHttpDown(); log("<<< f_trigger_authorization_request_await_response"); } } // End of module ItsRSUsSimulator_Functions