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 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; // LibItsCommon import from LibItsCommon_Functions all; // LibItsBtp import from LibItsBtp_TypesAndValues all; import from LibItsBtp_Templates all; // LibItsCam import from LibItsCam_Templates all; // LibItsDenm import from LibItsDenm_Templates all; // LibItsMapemSpatemm import from LibItsMapemSpatem_Templates all; // LibItsMapemSpatemm import from LibItsIvim_Templates all; // LibItsMapemSpatemm import from LibItsSremSsem_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; // AtsRSUsSimulator import from ItsRSUsSimulator_TypesAndValues all; import from ItsRSUsSimulator_TestSystem all; import from ItsRSUsSimulator_Templates 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 f_initialiseSecuredMode(); //Initialze the Config module //cfPort.send(CfInitialize:{}); // Initialisations f_setup_rsu(vc_rsu_id); } // End of function f_cf01Up function f_cf01Down() runs on ItsRSUsSimulator { vc_rsuMessagesValueList := {}; f_uninitialiseSecuredMode(); // Unmap unmap(self:acPort, system:acPort); //unmap(self:cfPort, system:cfPort); unmap(self:geoNetworkingPort, system:geoNetworkingPort); // Disconnect f_disconnect4SelfOrClientSync(); } // 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) octetstring 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) SSEM v_ssem := omit; var integer v_counter; vc_longPosVectorRsu := PICS_RSU_PARAMS[p_rsu_id].longPosVector; // 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; } // 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( -, { 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) and (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[p_rsu_id][PX_ETSI_ZONE_ID - 1]); v_counter := v_counter + 1) { var DenmEventsParmsPerZone v_denmEventsParmsPerZone := PICS_DENM_EVENTS_RSU[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[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[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 { vc_denm := false; } // 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 == 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 := 'AAAAAAAA'O; // TODO Use a PICS } // 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, v_ssem ); 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; } } // 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 false; } // End of function f_process_cf_event function f_prepare_beacon( out template (value) Payload p_payload ) runs on ItsRSUsSimulator { p_payload := valueof( f_adaptPayload( vc_rsuMessagesValueList[vc_rsu_id].beacon, 0, -, e_any ) ); } // End of function f_prepare_beacon function f_prepare_cam( out template (value) Payload 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 ) ); } // End of function f_prepare_cam function f_prepare_denm( out template (value) Payload 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); } // End of function f_prepare_denm function f_prepare_mapem( out template (value) Payload 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) Payload 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) Payload 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_evcsn( out template (value) Payload 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) Payload { var template (value) Payload v_payload; if(p_nextHeader == e_any) { v_payload := { decodedPayload := omit, rawPayload := 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 := { decodedPayload := { btpPacket := m_btpAWithPorts( p_destPort, p_srcPort, { decodedPayload := omit, rawPayload := p_finalPayload } ) }, rawPayload := ''O }; return v_payload; } if(p_nextHeader == e_btpB) { v_payload := { decodedPayload := { btpPacket := m_btpBWithPorts( p_destPort, p_srcPort, { decodedPayload := omit, rawPayload := p_finalPayload } ) }, rawPayload := ''O }; 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) Payload 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) Payload 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) ), m_defaultLifetime, c_hopLimit1 )); } else { v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template m_geoNwBroadcastPacket_payload( // TODO modifes 'template (value) GnNonSecuredPacket m_geoNwBroadcastPacket' to set the field vc_longPosVectorRsu, f_incLocalSeqNumber(), f_geoArea2GeoBroadcastArea(vc_geoArea), -, -, valueof(p_payload) ), m_defaultLifetime, c_hopLimit1 )); } f_sendGeoNetMessage(valueof(m_geoNwReq_linkLayerBroadcast(v_geoNetworkingPdu, p_its_aid))); } // End of function f_send function f_processSrem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { log("SREM=", p_geoNetworkingPdu); if (ispresent(p_geoNetworkingPdu.gnPacket.packet.payload.decodedPayload)) { if (ispresent(p_geoNetworkingPdu.gnPacket.packet.payload.decodedPayload.btpPacket.payload.decodedPayload)) { if (ischosen(p_geoNetworkingPdu.gnPacket.packet.payload.decodedPayload.btpPacket.payload.decodedPayload.sremPacket)) { var SignalRequestMessage v_signalRequestMessage := p_geoNetworkingPdu.gnPacket.packet.payload.decodedPayload.btpPacket.payload.decodedPayload.sremPacket.srm; var template (value) Payload v_payload; log(v_signalRequestMessage); // Build response // TODO v_ssem.ssm.status v_payload := valueof( f_adaptPayload( bit2oct( encvalue( valueof( m_ssem( v_signalRequestMessage )))), PICS_SSEM_BTP_DESTINATION_PORT, PICS_SSEM_BTP_SOURCE_PORT ) ); // Send SSEM f_send(v_payload, PICS_SSEM_ITS_AID); } // else, ignore message } // else, ignore message } // else, ignore message } // End of function f_processSrem 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; } } // End of module ItsRSUsSimulator_Functions