ItsRSUsSimulator_Functions.ttcn 21.9 KB
Newer Older
garciay's avatar
garciay committed
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 SREM_PDU_Descriptions language "ASN.1:1997" all;
    import from SSEM_PDU_Descriptions language "ASN.1:1997" all;
garciay's avatar
garciay committed
    import from DSRC language "ASN.1:1997" all;
garciay's avatar
garciay committed
    
    // LibItsCommon
    import from LibItsCommon_Functions all;
    
    // LibItsBtp
    import from LibItsBtp_TypesAndValues all;
    import from LibItsBtp_Templates all;
    
    // LibItsDenm
    import from LibItsDenm_Templates all;
    
garciay's avatar
garciay committed
    // LibItsMapemSpatemm
    import from LibItsMapemSpatem_Templates all;
    
    // LibItsMapemSpatemm
    import from LibItsIvim_Templates all;
    
    // LibItsMapemSpatemm
    import from LibItsSremSsem_Templates all;
    
garciay's avatar
garciay committed
    // 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;
    
    // 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 rsuConfigurationFunctions {
garciay's avatar
garciay committed
        
        /**
         * @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);
garciay's avatar
garciay committed
            map(self:geoNetworkingPort, system:geoNetworkingPort);
            
            // Connect
            f_connect4SelfOrClientSync();
            activate(a_cf01Down());
            
            // Initialise secured mode
            f_initialiseSecuredMode();
            
            //Initialze the Config module
            cfPort.send(CfInitialize:{});
garciay's avatar
garciay committed
            
            // Initialisations
            f_setup_rsu(vc_rsu_id);
             
garciay's avatar
garciay committed
        } // End of function f_cf01Up
        
        function f_cf01Down() runs on ItsRSUsSimulator {
            
            vc_rsuMessagesValueList := {};
            
garciay's avatar
garciay committed
            f_uninitialiseSecuredMode();
            
            // Unmap
            unmap(self:acPort, system:acPort);
            unmap(self:cfPort, system:cfPort);
garciay's avatar
garciay committed
            unmap(self:geoNetworkingPort, system:geoNetworkingPort);
            
            // Disconnect
            f_disconnect4SelfOrClientSync();
            
        } // End of function f_cf01Down
        
    } // End of group rsuConfigurationFunctions
    
    function f_setup_rsu(
                         in integer p_rsu_id
    ) runs on ItsRSUsSimulator { 
        
        // Local variables
        var template (value) DenmParmContainers v_denmParmContainers;
        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) SSEM v_ssem := omit;
        var integer v_counter;
        
        vc_longPosVectorRsu := PICS_RSU_PARAMS[p_rsu_id].longPosVector;
        // MAPEM
garciay's avatar
garciay committed
        if (PICS_GENERATE_MAPEM 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?
        }
        // SPATEM
garciay's avatar
garciay committed
        if (PICS_GENERATE_SPATEM and (lengthof(PICS_SPATEM_PARMS_RSUs[p_rsu_id]) != 0)) {
            // Reset counter
            vc_currentPhaseStartTime := 36001;
            vc_endPhaseStartTime := 0;
            vc_spatemStatesId := 0;
garciay's avatar
garciay committed
            // 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
        }
        // IVIM
garciay's avatar
garciay committed
        if (PICS_GENERATE_IVIM 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_
                        ),
garciay's avatar
garciay committed
                        PICS_IVIM_PARMS_RSUs[p_rsu_id].iviContainers
            ));
            // Update ivi status
            v_ivim.ivi.mandatory.validFrom := f_getCurrentTime();
        }
        // DENM
        if (PICS_GENERATE_DENM) {
            // 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
                );
                v_denms[v_counter] := valueof(
                    m_denmPdu(
                        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
        }
        // CAM
        if (PICS_GENERATE_CAM) {
            // Build the list of the CAM events
            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
            );
        } 
        // Build the messages value list for this RSU
        vc_rsuMessagesValueList[p_rsu_id] := 
            m_rsuProfile(
                v_cam, 
                v_denms,
                v_mapem,
                v_spatems,
                v_ivim,
                v_ssem
        );
        if (PICS_RSU_PARAMS[p_rsu_id].geoShape == e_geoCircle) {
            vc_geoArea := f_computeCircularArea(vc_longPosVectorRsu, PICS_RSU_PARAMS[p_rsu_id].geoParms.radius);
        } 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].cam)) {
            if (ispresent(vc_rsuMessagesValueList[vc_rsu_id].denms)) {
            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
garciay's avatar
garciay committed
    
    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
garciay's avatar
garciay committed
        p_payload := valueof(
            f_adaptPayload(
                bit2oct(
                    encvalue(
                        valueof(
                            vc_rsuMessagesValueList[vc_rsu_id].cam
garciay's avatar
garciay committed
                ))),
                PICS_CAM_BTP_DESTINATION_PORT,
                PICS_CAM_BTP_SOURCE_PORT
            )
        );
    } // End of function f_prepare_cam
garciay's avatar
garciay committed
    
    function f_prepare_denm(
                            out template (value) Payload p_payload
    ) runs on ItsRSUsSimulator {
        
        // Update dynamic parms
        vc_rsuMessagesValueList[vc_rsu_id].denms[vc_denmEventCounter].denm.management.referenceTime  := f_getCurrentTime();
garciay's avatar
garciay committed
        p_payload := valueof(
            f_adaptPayload(
                bit2oct(
                    encvalue(
                        valueof(vc_rsuMessagesValueList[vc_rsu_id].denms[vc_denmEventCounter]
garciay's avatar
garciay committed
                ))),
                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
garciay's avatar
garciay committed
    
    function f_prepare_mapem(
                             out template (value) Payload p_payload
    ) runs on ItsRSUsSimulator {
        
garciay's avatar
garciay committed
        p_payload := valueof(
            f_adaptPayload(
                bit2oct(
                    encvalue(
                        valueof(
                            vc_rsuMessagesValueList[vc_rsu_id].mapem
garciay's avatar
garciay committed
                ))),
                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;
    }
    
garciay's avatar
garciay committed
    function f_prepare_spatem(
                              in template (value) SPATEM p_spatem,
garciay's avatar
garciay committed
                              out template (value) Payload p_payload
    ) runs on ItsRSUsSimulator {
        var template (value) SPATEM v_spatem := p_spatem; // Make a copy
        var TimeMark v_currentTimeMark := f_getCurrentTimeMark();
        if (vc_currentPhaseStartTime == 36001) {
		    vc_currentPhaseStartTime := v_currentTimeMark;
		    vc_endPhaseStartTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, vc_repitition_duration[vc_spatemStatesId]);
        }
        if (v_currentTimeMark >= vc_endPhaseStartTime) {
            vc_spatemStatesId := (vc_spatemStatesId + 1) mod vc_spatemStatesNum; // Change state
		    vc_currentPhaseStartTime := v_currentTimeMark;
		    vc_endPhaseStartTime := f_computeEndPhaseStartTime(vc_currentPhaseStartTime, vc_repitition_duration[vc_spatemStatesId]);
        }
        log("vc_currentPhaseStartTime = ", vc_currentPhaseStartTime);
        log("vc_endPhaseStartTime = ", vc_endPhaseStartTime);
        log("v_currentTimeMark = ", v_currentTimeMark);
        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 (value) MovementList v_states := vc_states[vc_signalGroupParmId][v_intersection];
            select (vc_spatemStatesId) {
                case (0) {
                    v_spatem.spat.intersections[v_intersection].states[0] := v_states[0];
                    v_spatem.spat.intersections[v_intersection].states[1] := v_states[1];
                    v_spatem.spat.intersections[v_intersection].states[2] := v_states[2];
                }
                case (1) {
                    v_spatem.spat.intersections[v_intersection].states[0] := v_states[1];
                    v_spatem.spat.intersections[v_intersection].states[1] := v_states[2];
                    v_spatem.spat.intersections[v_intersection].states[2] := v_states[0];
                }
                case (2) {
                    v_spatem.spat.intersections[v_intersection].states[0] := v_states[2];
                    v_spatem.spat.intersections[v_intersection].states[1] := v_states[0];
                    v_spatem.spat.intersections[v_intersection].states[2] := v_states[1];
                }
                case else {
                }
            } // End of 'select' statement
            // Update 'minEndTime' field
            v_spatem.spat.intersections[v_intersection].states[0].state_time_speed[0].timing.minEndTime := vc_currentPhaseStartTime;
            v_spatem.spat.intersections[v_intersection].states[1].state_time_speed[0].timing.minEndTime := vc_currentPhaseStartTime + vc_repitition_duration[(vc_spatemStatesId + 1) mod vc_spatemStatesNum];
            v_spatem.spat.intersections[v_intersection].states[2].state_time_speed[0].timing.minEndTime := vc_currentPhaseStartTime + vc_repitition_duration[(vc_spatemStatesId + 2) mod vc_spatemStatesNum];
        } // End of 'for' statement
        
        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
garciay's avatar
garciay committed
    
    function f_prepare_ivim(
                            out template (value) Payload p_payload
garciay's avatar
garciay committed
    ) 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
garciay's avatar
garciay committed
    
    function f_adaptPayload(
                            in template (value) octetstring p_finalPayload,
                            in template (value) BtpPortId  p_destPort,
                            in template (value) BtpPortId  p_srcPort := 0
    ) return template (value) Payload {
        var template (value) Payload v_payload;
        
        if(PX_GN_UPPER_LAYER == e_any) {
            v_payload := { decodedPayload := omit, rawPayload := p_finalPayload};
            return v_payload;
        }
        
        if(PX_GN_UPPER_LAYER == e_ipv6) {
            log("*** " & testcasename() & ": INCONC: Layer IPv6 not supported ***");
            setverdict(inconc);
            stop;
        }
        
        if(PX_GN_UPPER_LAYER == e_btpA) {
            v_payload := { 
                decodedPayload := { 
                    btpPacket := m_btpAWithPorts(
                        p_destPort,
                        p_srcPort,
                        { 
                            decodedPayload := omit, 
                            rawPayload := p_finalPayload 
                        }
                    )
                },
                rawPayload := ''O
            };
            return v_payload;
        }
        
        if(PX_GN_UPPER_LAYER == 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
garciay's avatar
garciay committed
    
    function f_send(
                    in template (value) Payload p_payload,
                    in UInt32 p_its_aid
garciay's avatar
garciay committed
    ) runs on ItsRSUsSimulator {
        var GeoNetworkingPdu v_geoNetworkingPdu;
        
        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_defaultHopLimit
        ));
        f_sendGeoNetMessage(valueof(m_geoNwReq_linkLayerBroadcast(v_geoNetworkingPdu, p_its_aid)));
    } // End of function f_send
garciay's avatar
garciay committed
    
    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
garciay's avatar
garciay committed
    
    function f_incLocalSeqNumber() runs on ItsRSUsSimulator return UInt16 {
        vc_localSeqNumber := (vc_localSeqNumber + 1) mod 65536;
        return vc_localSeqNumber;
    }
    
garciay's avatar
garciay committed
    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;
    }
    
garciay's avatar
garciay committed
    function f_getDenmSequenceNumber() runs on ItsRSUsSimulator return SequenceNumber {
garciay's avatar
garciay committed
        return vc_sequenceNumber;
garciay's avatar
garciay committed
    }
    
} // End of module ItsRSUsSimulator_Functions