Skip to content
LibItsGeoNetworking_Functions.ttcn 79.7 KiB
Newer Older
berge's avatar
berge committed
/**
 *  @author     ETSI / STF405 / STF449
berge's avatar
berge committed
 *  @version    $URL$
 *              $Id$
 *  @desc       Module containing functions for GeoNetworking
berge's avatar
berge committed
 *
 */
module LibItsGeoNetworking_Functions {
    
berge's avatar
berge committed
    // Libcommon
    import from LibCommon_BasicTypesAndValues all;
    import from LibCommon_DataStrings all;
    import from LibCommon_VerdictControl {type FncRetCode;}
    import from LibCommon_Sync all;
berge's avatar
berge committed
    import from LibCommon_Time all;
berge's avatar
berge committed
    // LibIts
fischer's avatar
fischer committed
    import from LibItsCommon_Functions all;
reinaortega's avatar
reinaortega committed
    import from LibItsCommon_TestSystem all;
tepelmann's avatar
tepelmann committed
    import from LibItsCommon_TypesAndValues all;
reinaortega's avatar
reinaortega committed
    import from LibItsGeoNetworking_Functions all;
    import from LibItsGeoNetworking_TestSystem all;
berge's avatar
berge committed
    import from LibItsGeoNetworking_TypesAndValues all;
berge's avatar
berge committed
    import from LibItsGeoNetworking_Templates all;
fischer's avatar
fischer committed
    import from LibItsGeoNetworking_Pixits all;
    import from LibItsGeoNetworking_Pics all;
    import from LibItsExternal_TypesAndValues {type MacAddress};
tepelmann's avatar
tepelmann committed
    
tepelmann's avatar
tepelmann committed
    group utFuntions {
tepelmann's avatar
tepelmann committed
        
reinaortega's avatar
reinaortega committed
        /**
         * @desc    Requests to bring the IUT in an initial state
         * @param   p_init The initialisation to trigger.
         */
        function f_utInitializeIut(template (value) UtInitialize p_init) runs on ItsBaseGeoNetworking {
tepelmann's avatar
tepelmann committed
            
reinaortega's avatar
reinaortega committed
            utPort.send(p_init);
            tc_wait.start;
            alt {
                [] utPort.receive(UtResult:true) {
                    tc_wait.stop;
                    log("*** f_utInitializeIut: INFO: IUT initialized ***");
                }
                [] utPort.receive {
                    tc_wait.stop;
                    log("*** f_utInitializeIut: INFO: IUT could not be initialized ***");
                    f_selfOrClientSyncAndVerdict("error", e_error);
                }
                [] tc_wait.timeout {
                    log("*** f_utInitializeIut: INFO: IUT could not be initialized in time ***");
                    f_selfOrClientSyncAndVerdict("error", e_timeout);
                }
                [else] { // Shortcut defaults
tepelmann's avatar
tepelmann committed
                    repeat;
reinaortega's avatar
reinaortega committed
                }
            }
tepelmann's avatar
tepelmann committed
        
tepelmann's avatar
tepelmann committed
         * @desc    Requests to change the position of the IUT
         */
        function f_utChangePosition() runs on ItsBaseGeoNetworking {
        	
        	utPort.send(m_changePosition);
            tc_wait.start;
            alt {
                [] utPort.receive(UtResult:true) {
                    tc_wait.stop;
                    log("*** f_utInitializeIut: INFO: IUT initialized ***");
                }
                [] utPort.receive {
                    tc_wait.stop;
                    log("*** f_utInitializeIut: INFO: IUT could not be initialized ***");
                    f_selfOrClientSyncAndVerdict("error", e_error);
                }
                [] tc_wait.timeout {
                    log("*** f_utInitializeIut: INFO: IUT could not be initialized in time ***");
                    f_selfOrClientSyncAndVerdict("error", e_timeout);
                }
                [else] { // Shortcut defaults
tepelmann's avatar
tepelmann committed
                    repeat;
reinaortega's avatar
reinaortega committed
        }
        
        /**
         * @desc    Triggers event from the application layer
         * @param   p_event The event to trigger.
         */
        function f_utTriggerEvent(template (value) UtGnTrigger p_event) runs on ItsGeoNetworking {
reinaortega's avatar
reinaortega committed
            
            utPort.send(p_event);
reinaortega's avatar
reinaortega committed
            alt {
                [] utPort.receive(UtResult:true) {
                    tc_wait.stop;
                }
                [] utPort.receive {
                    tc_wait.stop;
                }
                [] tc_wait.timeout {
                }
                [else] { // Shortcut defaults
tepelmann's avatar
tepelmann committed
                    repeat;
reinaortega's avatar
reinaortega committed
                }
            }
        }
        
        /**
         * @desc Checks that the event was indicated at the application layer
         * @param p_event The event to check.
         * @param   p_discard The event should not appear. Default value: FALSE.
         */
        function f_utCheckEvent(template (value) UtGnTrigger p_event, boolean p_discard) runs on ItsGeoNetworking {
reinaortega's avatar
reinaortega committed
            
            utPort.send(p_event);
reinaortega's avatar
reinaortega committed
            tc_wait.start;
            alt {
                [] utPort.receive(UtResult:true) {
                    tc_wait.stop;
                    if (p_discard == false) {
                        log("*** f_utCheckEvent: INFO: Event correctly indicated at application layer ***");
                    }
                    else {
                        log("*** f_utCheckEvent: ERROR: Event indicated at application layer where it should be discarded ***");
                        f_selfOrClientSyncAndVerdict("error", e_error);
                    }
                }
                [] utPort.receive(UtResult:false) {
                    tc_wait.stop;
                    if (p_discard == false) {
                        log("*** f_utCheckEvent: ERROR: Event not correctly indicated at application layer ***");
                        f_selfOrClientSyncAndVerdict("error", e_error);
                    }
                    else {
                        log("*** f_utCheckEvent: INFO: Event not indicated at application layer***");
                    }
                }
                [] tc_wait.timeout {
                    log("*** f_utCheckEvent: ERROR: Timeout while waiting for event check result ***");
tepelmann's avatar
tepelmann committed
                    f_selfOrClientSyncAndVerdict("error", e_timeout);
reinaortega's avatar
reinaortega committed
                }
                [else] { // Shortcut defaults
tepelmann's avatar
tepelmann committed
                    repeat;
reinaortega's avatar
reinaortega committed
    } // End of group utFunctions
    group geoConfigurationFunctions {
        
        /**
         * @desc This configuration features:
         *       - one ITS node (IUT)
         *       - two ITS nodes (nodeA, nodeB)
         *       - Area1 which only includes NodeB and IUT
tepelmann's avatar
tepelmann committed
         *       - Area2 which only includes NodeB
tepelmann's avatar
tepelmann committed
         *         NodeB being close to the area center
reinaortega's avatar
reinaortega committed
        function f_cf01Up() runs on ItsGeoNetworking {
            // Variables
            var PositionTable v_positionTable := {};
            var GeoAreaTable v_areaTable := {};
            var LongPosVector v_longPosVectorIut, v_longPosVectorNodeA, v_longPosVectorNodeB, v_longPosVectorNodeD;
            map(self:acPort, system:acPort);
            map(self:utPort, system:utPort);
            map(self:geoNetworkingPort, system:geoNetworkingPort);
            // Connect
            f_connect4SelfOrClientSync();
tepelmann's avatar
tepelmann committed
            activate(a_cf01Down());
            //Initialze the IUT
            f_initialState();
            
            //Get positions
            v_longPosVectorIut := f_getIutLongPosVector();
            v_longPosVectorNodeA := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeA, c_latitudeFactorNodeA);
            v_longPosVectorNodeB := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeB, c_latitudeFactorNodeB);
            v_longPosVectorNodeD := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeD, c_latitudeFactorNodeD);
            // Propagate GN addresses
            v_longPosVectorNodeA.gnAddr := f_getTsGnLocalAddress(c_compNodeA);
            v_longPosVectorNodeB.gnAddr := f_getTsGnLocalAddress(c_compNodeB);
tepelmann's avatar
tepelmann committed
            // Position table
            f_addPosition(v_positionTable, c_compIut, v_longPosVectorIut);
            f_addPosition(v_positionTable, c_compNodeA, v_longPosVectorNodeA);
            f_addPosition(v_positionTable, c_compNodeB, v_longPosVectorNodeB);
berge's avatar
berge committed
            f_addPosition(v_positionTable, c_compNodeD, v_longPosVectorNodeD);
            // Area table
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area1,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeD, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area2,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeB, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
            f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeB);
        } // end f_cf01Up
berge's avatar
berge committed
        /**
         * @desc Deletes configuration cf01
reinaortega's avatar
reinaortega committed
        function f_cf01Down() runs on ItsGeoNetworking {
            unmap(self:acPort, system:acPort);
            unmap(self:utPort, system:utPort);
            unmap(self:geoNetworkingPort, system:geoNetworkingPort);
            
            // Disconnect
            f_disconnect4SelfOrClientSync();
            
        } // end f_cf01Down
        
        /**
         * @desc This configuration features:
         *       - one ITS node (IUT)
         *       - one ITS node (NodeB)
berge's avatar
berge committed
         *       - one ITS node (NodeD)
         *       - Area1 which only includes NodeB, NodeD and IUT
tepelmann's avatar
tepelmann committed
         *       - Area2 which only includes NodeB and NodeD
         *         NodeB being close to the area center
         *
         * @param p_nodeB   Component for NodeB
         * @param p_nodeD   Component for NodeD
reinaortega's avatar
reinaortega committed
        function f_cf02Up(out ItsGeoNetworking p_nodeB, out ItsGeoNetworking p_nodeD) runs on ItsMtc {
            
            // Variables
            var PositionTable v_positionTable := {};
            var GeoAreaTable v_areaTable := {};
            var LongPosVector v_longPosVectorIut, v_longPosVectorNodeA, v_longPosVectorNodeB, v_longPosVectorNodeC, v_longPosVectorNodeD;
reinaortega's avatar
reinaortega committed
            p_nodeB := ItsGeoNetworking.create(c_compNodeB) alive;
            p_nodeD := ItsGeoNetworking.create(c_compNodeD) alive;
tepelmann's avatar
tepelmann committed
            
            // Map
berge's avatar
berge committed
            map(self:acPort, system:acPort);
tepelmann's avatar
tepelmann committed
            map(self:utPort, system:utPort);
            map(p_nodeB:acPort, system:acPort);
            map(p_nodeD:acPort, system:acPort);
            map(p_nodeB:utPort, system:utPort);
            map(p_nodeD:utPort, system:utPort);
            map(p_nodeB:geoNetworkingPort, system:geoNetworkingPort);
berge's avatar
berge committed
            map(p_nodeD:geoNetworkingPort, system:geoNetworkingPort);
tepelmann's avatar
tepelmann committed
            // Connect
            connect(p_nodeB:syncPort, self:syncPort);
berge's avatar
berge committed
            connect(p_nodeD:syncPort, self:syncPort);
tepelmann's avatar
tepelmann committed
            connect(self:syncPort, mtc:syncPort);
            activate(a_cf02Down(p_nodeB, p_nodeD));
            
            //Initialze the IUT
            f_initialState();
            
            //Get positions
            v_longPosVectorIut := f_getIutLongPosVector();
            v_longPosVectorNodeA := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeA, c_latitudeFactorNodeA);
            v_longPosVectorNodeB := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeB, c_latitudeFactorNodeB);
            v_longPosVectorNodeD := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeD, c_latitudeFactorNodeD);
            // Propagate GN addresses
            v_longPosVectorNodeA.gnAddr := f_getTsGnLocalAddress(c_compNodeA);
            v_longPosVectorNodeB.gnAddr := f_getTsGnLocalAddress(c_compNodeB);
            v_longPosVectorNodeD.gnAddr := f_getTsGnLocalAddress(c_compNodeD);
            // Position table
            f_addPosition(v_positionTable, c_compIut, v_longPosVectorIut);
            f_addPosition(v_positionTable, c_compNodeA, v_longPosVectorNodeA);
            f_addPosition(v_positionTable, c_compNodeB, v_longPosVectorNodeB);
            f_addPosition(v_positionTable, c_compNodeD, v_longPosVectorNodeD);
            // Area table
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area1,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeD, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area2,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeB, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
            
            p_nodeB.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeB));
            p_nodeD.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeD));
            p_nodeB.done;
berge's avatar
berge committed
            p_nodeD.done;
        
        } // end f_cf02Up
berge's avatar
berge committed
        /**
         * @desc Deletes configuration cf02
         * @param p_nodeB   Component for NodeB
         * @param p_nodeD   Component for NodeD
reinaortega's avatar
reinaortega committed
        function f_cf02Down(in ItsGeoNetworking p_nodeB, in ItsGeoNetworking p_nodeD) runs on ItsMtc {
tepelmann's avatar
tepelmann committed
            unmap(self:acPort, system:acPort);
tepelmann's avatar
tepelmann committed
            unmap(self:utPort, system:utPort);
            unmap(p_nodeB:acPort, system:acPort);
            unmap(p_nodeD:acPort, system:acPort);
            unmap(p_nodeB:utPort, system:utPort);
            unmap(p_nodeD:utPort, system:utPort);
            unmap(p_nodeB:geoNetworkingPort, system:geoNetworkingPort);
berge's avatar
berge committed
            unmap(p_nodeD:geoNetworkingPort, system:geoNetworkingPort);
            disconnect(p_nodeB:syncPort, self:syncPort);
berge's avatar
berge committed
            disconnect(p_nodeD:syncPort, self:syncPort);
tepelmann's avatar
tepelmann committed
            disconnect(self:syncPort, mtc:syncPort);
        
        } // end f_cf02Down
        
        /**
         * @desc This configuration features:
         *       - one ITS node (IUT)
         *       - one ITS node (NodeA)
         *       - one ITS node in direction of NodeA (NodeB)
tepelmann's avatar
tepelmann committed
         *       - one ITS node not in direction of NodeA (NodeC)
         *       - Area1 which only includes NodeB and IUT
tepelmann's avatar
tepelmann committed
         *       - Area2 which only includes NodeB
         *         NodeB being close to the area center
         * @param p_nodeB   Component for NodeB
         * @param p_nodeC   Component for NodeC
reinaortega's avatar
reinaortega committed
        function f_cf03Up(out ItsGeoNetworking p_nodeB, out ItsGeoNetworking p_nodeC) runs on ItsMtc {
            // Variables
            var PositionTable v_positionTable := {};
            var GeoAreaTable v_areaTable := {};
            var LongPosVector v_longPosVectorIut, v_longPosVectorNodeA, v_longPosVectorNodeB, v_longPosVectorNodeC, v_longPosVectorNodeD;
            // Create
reinaortega's avatar
reinaortega committed
            p_nodeB := ItsGeoNetworking.create(c_compNodeB) alive;
            p_nodeC := ItsGeoNetworking.create(c_compNodeC) alive;
tepelmann's avatar
tepelmann committed
            map(self:acPort, system:acPort);
tepelmann's avatar
tepelmann committed
            map(self:utPort, system:utPort);
            map(p_nodeB:acPort, system:acPort);
            map(p_nodeC:acPort, system:acPort);
            map(p_nodeB:utPort, system:utPort);
            map(p_nodeC:utPort, system:utPort);
            map(p_nodeB:geoNetworkingPort, system:geoNetworkingPort);
            map(p_nodeC:geoNetworkingPort, system:geoNetworkingPort);
            
            // Connect
            connect(p_nodeB:syncPort, self:syncPort);
            connect(p_nodeC:syncPort, self:syncPort);
tepelmann's avatar
tepelmann committed
            connect(self:syncPort, mtc:syncPort);
            
            activate(a_cf03Down(p_nodeB, p_nodeC));
            
            //Initialze the IUT
            f_initialState();
            
            //Get positions
            v_longPosVectorIut := f_getIutLongPosVector();
            v_longPosVectorNodeA := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeA, c_latitudeFactorNodeA);
            v_longPosVectorNodeB := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeB, c_latitudeFactorNodeB);
            v_longPosVectorNodeC := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeC, c_latitudeFactorNodeC);
            v_longPosVectorNodeD := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeD, c_latitudeFactorNodeD);
            // Propagate GN addresses
            v_longPosVectorNodeA.gnAddr := f_getTsGnLocalAddress(c_compNodeA);
            v_longPosVectorNodeB.gnAddr := f_getTsGnLocalAddress(c_compNodeB);
            v_longPosVectorNodeC.gnAddr := f_getTsGnLocalAddress(c_compNodeC);
            // Position table
            f_addPosition(v_positionTable, c_compIut, v_longPosVectorIut);
            f_addPosition(v_positionTable, c_compNodeA, v_longPosVectorNodeA);
            f_addPosition(v_positionTable, c_compNodeB, v_longPosVectorNodeB);
            f_addPosition(v_positionTable, c_compNodeC, v_longPosVectorNodeC);
            
            // Area table
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area1,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeD, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area2,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeB, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
            
            p_nodeB.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeB));
            p_nodeC.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeC));
            p_nodeB.done;
            p_nodeC.done;
        } // end f_cf03Up
        /**
         * @desc Deletes configuration cf03
         * @param p_nodeB   Component for NodeB
         * @param p_nodeC   Component for NodeC
reinaortega's avatar
reinaortega committed
        function f_cf03Down(in ItsGeoNetworking p_nodeB, in ItsGeoNetworking p_nodeC) runs on ItsMtc {
tepelmann's avatar
tepelmann committed
            unmap(self:acPort, system:acPort);
berge's avatar
berge committed
            unmap(self:utPort, system:utPort);
            unmap(p_nodeB:acPort, system:acPort);
            unmap(p_nodeC:acPort, system:acPort);
            unmap(p_nodeB:utPort, system:utPort);
            unmap(p_nodeC:utPort, system:utPort);
            unmap(p_nodeB:geoNetworkingPort, system:geoNetworkingPort);
            unmap(p_nodeC:geoNetworkingPort, system:geoNetworkingPort);
            
            disconnect(p_nodeB:syncPort, self:syncPort);
            disconnect(p_nodeC:syncPort, self:syncPort);
tepelmann's avatar
tepelmann committed
            disconnect(self:syncPort, mtc:syncPort);
        
        } // end f_cf03Down
        /**
         * @desc This configuration features:
         *       - one ITS node (IUT)
         *       - one ITS node (NodeA)
tepelmann's avatar
tepelmann committed
         *       - one ITS node in direction of NodeA and having
         *         shortest distance to NodeA (NodeB)
         *       - one ITS node in direction of NodeA (NodeD)
         *       - one ITS node not in direction of NodeA (NodeC)
         *       - Area1 which only includes NodeB, NodeD and IUT
tepelmann's avatar
tepelmann committed
         *       - Area2 which only includes NodeA, NodeB and NodeD
         *         NodeB being close to the area center
         * @param p_nodeB   Component for NodeB
         * @param p_nodeC   Component for NodeC
tepelmann's avatar
tepelmann committed
         * @param p_nodeD   Component for NodeD
reinaortega's avatar
reinaortega committed
        function f_cf04Up(out ItsGeoNetworking p_nodeB, out ItsGeoNetworking p_nodeC, out ItsGeoNetworking p_nodeD) runs on ItsMtc {
            // Variables
            var PositionTable v_positionTable := {};
            var GeoAreaTable v_areaTable := {};
            var LongPosVector v_longPosVectorIut, v_longPosVectorNodeA, v_longPosVectorNodeB, v_longPosVectorNodeC, v_longPosVectorNodeD;
            // Create
reinaortega's avatar
reinaortega committed
            p_nodeB := ItsGeoNetworking.create(c_compNodeB) alive;
            p_nodeC := ItsGeoNetworking.create(c_compNodeC) alive;
            p_nodeD := ItsGeoNetworking.create(c_compNodeD) alive;
tepelmann's avatar
tepelmann committed
            map(self:acPort, system:acPort);
tepelmann's avatar
tepelmann committed
            map(self:utPort, system:utPort);
            map(p_nodeB:acPort, system:acPort);
            map(p_nodeC:acPort, system:acPort);
            map(p_nodeD:acPort, system:acPort);
            map(p_nodeB:utPort, system:utPort);
            map(p_nodeC:utPort, system:utPort);
            map(p_nodeD:utPort, system:utPort);
            map(p_nodeB:geoNetworkingPort, system:geoNetworkingPort);
            map(p_nodeC:geoNetworkingPort, system:geoNetworkingPort);
            map(p_nodeD:geoNetworkingPort, system:geoNetworkingPort);
            
            // Connect
            connect(p_nodeB:syncPort, self:syncPort);
            connect(p_nodeC:syncPort, self:syncPort);
            connect(p_nodeD:syncPort, self:syncPort);
tepelmann's avatar
tepelmann committed
            connect(self:syncPort, mtc:syncPort);
            activate(a_cf04Down(p_nodeB, p_nodeC, p_nodeD));
            //Initialze the IUT
            f_initialState();
            
            //Get positions
            v_longPosVectorIut := f_getIutLongPosVector();
            v_longPosVectorNodeA := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeA, c_latitudeFactorNodeA);
            v_longPosVectorNodeB := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeB, c_latitudeFactorNodeB);
            v_longPosVectorNodeC := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeC, c_latitudeFactorNodeC);
            v_longPosVectorNodeD := f_computePosition(v_longPosVectorIut, c_longitudeFactorNodeD, c_latitudeFactorNodeD);
            // Propagate GN addresses
            v_longPosVectorNodeA.gnAddr := f_getTsGnLocalAddress(c_compNodeA);
            v_longPosVectorNodeB.gnAddr := f_getTsGnLocalAddress(c_compNodeB);
            v_longPosVectorNodeC.gnAddr := f_getTsGnLocalAddress(c_compNodeC);
            v_longPosVectorNodeD.gnAddr := f_getTsGnLocalAddress(c_compNodeD);
            // Position table
            f_addPosition(v_positionTable, c_compIut, v_longPosVectorIut);
            f_addPosition(v_positionTable, c_compNodeA, v_longPosVectorNodeA);
            f_addPosition(v_positionTable, c_compNodeB, v_longPosVectorNodeB);
            f_addPosition(v_positionTable, c_compNodeC, v_longPosVectorNodeC);
            f_addPosition(v_positionTable, c_compNodeD, v_longPosVectorNodeD);
            // Area table
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area1,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeD, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
tepelmann's avatar
tepelmann committed
            f_addArea(v_areaTable, c_area2,
berge's avatar
berge committed
                f_computeCircularArea(v_longPosVectorNodeB, float2int(1.1 * f_distance(v_longPosVectorNodeB, v_longPosVectorNodeD))));
tepelmann's avatar
tepelmann committed
            
            p_nodeB.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeB));
            p_nodeC.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeC));
            p_nodeD.start(f_initialiseComponent(v_positionTable, v_areaTable, c_compNodeD));
            p_nodeB.done;
            p_nodeC.done;
            p_nodeD.done;
tepelmann's avatar
tepelmann committed
            
        } // end f_cf04Up
        /**
         * @desc Deletes configuration cf04
         * @param p_nodeB   Component for NodeB
         * @param p_nodeC   Component for NodeC
tepelmann's avatar
tepelmann committed
         * @param p_nodeD   Component for NodeD
reinaortega's avatar
reinaortega committed
        function f_cf04Down(in ItsGeoNetworking p_nodeB, in ItsGeoNetworking p_nodeC, in ItsGeoNetworking p_nodeD) runs on ItsMtc {
tepelmann's avatar
tepelmann committed
            unmap(self:acPort, system:acPort);
berge's avatar
berge committed
            unmap(self:utPort, system:utPort);
            unmap(p_nodeB:acPort, system:acPort);
            unmap(p_nodeC:acPort, system:acPort);
            unmap(p_nodeD:acPort, system:acPort);
            unmap(p_nodeB:utPort, system:utPort);
            unmap(p_nodeC:utPort, system:utPort);
            unmap(p_nodeD:utPort, system:utPort);
            unmap(p_nodeB:geoNetworkingPort, system:geoNetworkingPort);
            unmap(p_nodeC:geoNetworkingPort, system:geoNetworkingPort);
            unmap(p_nodeD:geoNetworkingPort, system:geoNetworkingPort);
            
            disconnect(p_nodeB:syncPort, self:syncPort);
            disconnect(p_nodeC:syncPort, self:syncPort);
            disconnect(p_nodeD:syncPort, self:syncPort);
tepelmann's avatar
tepelmann committed
            disconnect(self:syncPort, mtc:syncPort);
        
        } // end f_cf04Down
        
        /**
         * @desc    Behavior function for initializing component's variables and tables
         * @param   p_positionTable Table containing position vectors of all nodes
         * @param   p_areaTable     Table containing all defined geoAreas
         * @param   p_componentName Name of the component
        function f_initialiseComponent(
            in PositionTable p_positionTable,
            in GeoAreaTable p_areaTable,
tepelmann's avatar
tepelmann committed
            in charstring p_componentName)
reinaortega's avatar
reinaortega committed
        runs on ItsGeoNetworking {
            
            vc_positionTable := p_positionTable;
            vc_areaTable := p_areaTable;
tepelmann's avatar
tepelmann committed
            vc_componentName := p_componentName;
            
        } // end f_initialiseComponent
        
tepelmann's avatar
tepelmann committed
         * @desc    Makes the simulated ITS node behave as a neighbour of IUT
reinaortega's avatar
reinaortega committed
        function f_startBeingNeighbour() runs on ItsGeoNetworking {
berge's avatar
berge committed
            
            vc_neighbourDefault := activate(a_neighbourDefault());
            f_acTriggerEvent(m_startBeaconing(m_beaconHeader(f_getPosition(vc_componentName)).beaconHeader));
            f_sleepIgnoreDef(PX_NEIGHBOUR_DISCOVERY_DELAY);
berge's avatar
berge committed
        } // end f_startBeingNeighbour
tepelmann's avatar
tepelmann committed
         * @desc    Makes the simulated ITS node behave as not being a neighbour of IUT
tepelmann's avatar
tepelmann committed
         */
tepelmann's avatar
tepelmann committed
        function f_stopBeingNeighbour() runs on ItsGeoNetworking {
berge's avatar
berge committed
            
            f_acTriggerEvent(m_stopBeaconing);
tepelmann's avatar
tepelmann committed
            deactivate(vc_neighbourDefault);
berge's avatar
berge committed
            
        } // end f_stopBeingNeighbour
        
    } // end geoConfigurationFunctions
    
    group geoPositionFunctions {
        
        /**
         * @desc    Add a position vector in position table
         * @param   p_positionTable Position table to be updated
         * @param   p_positionKey   Reference key of the added position vector
         * @param   p_positionValue Added position vector
        function f_addPosition(
berge's avatar
berge committed
            inout PositionTable p_positionTable,
            in charstring p_positionKey,
            in LongPosVector p_positionValue
        ) {
berge's avatar
berge committed
            p_positionTable[lengthof(p_positionTable)] := {
                key := p_positionKey,
                position := p_positionValue
            };
tepelmann's avatar
tepelmann committed
         * @desc    Get the position vector corresponding to a key
         * @param   p_positionKey   Reference key of the searched position vector
         * @return  LongPosVector - The searched position vector
        function f_getPosition(
            in charstring p_positionKey
tepelmann's avatar
tepelmann committed
        ) runs on ItsGeoNetworking
        return LongPosVector {
            
            var integer i := 0;
            
            for (i:=0; i<lengthof(vc_positionTable); i:=i+1) {
                if (vc_positionTable[i].key == p_positionKey) {
                    v_return := vc_positionTable[i].position;
                }
            }
            if((v_return != null) and (v_return.timestamp == 0)) {
                v_return.timestamp := f_computeGnTimestamp();
        /**
         * @desc    Compute a position based on reference point and distance factors
         * @param   p_refPosition       Reference point
tepelmann's avatar
tepelmann committed
         * @param   p_longitudeFactor   Number of PX_DISTANCE_UNIT applied for computing longitude
         * @param   p_latitudeFactor    Number of PX_DISTANCE_UNIT applied for computing latitude
         * @return  LongPosVector - Computed position
         * @see     PX_DISTANCE_UNIT
        function f_computePosition(
tepelmann's avatar
tepelmann committed
            in LongPosVector p_refPosition,
            in integer p_longitudeFactor,
            in integer p_latitudeFactor
        ) return LongPosVector {
            var LongPosVector v_return := p_refPosition;
berge's avatar
berge committed
            v_return.latitude := v_return.latitude + p_latitudeFactor * PX_DISTANCE_UNIT;
            v_return.longitude := v_return.longitude + p_longitudeFactor * PX_DISTANCE_UNIT;
berge's avatar
berge committed
            v_return.timestamp := f_computeGnTimestamp();
            return v_return;
        }
        
        /**
         * @desc    Add a geoArea in geoArea table
         * @param   p_geoAreaTable  GeoArea table to be updated
         * @param   p_areaKey       Reference key of the added geoArea
         * @param   p_geoArea       Added geoArea
         */
        function f_addArea(
            inout GeoAreaTable p_geoAreaTable,
            in charstring p_areaKey,
            in GeoArea p_geoArea
        ) {
            p_geoAreaTable[lengthof(p_geoAreaTable)] := {
                key := p_areaKey,
                geoArea := p_geoArea
            };
        }
tepelmann's avatar
tepelmann committed
         * @desc    Get the geoArea corresponding to a key
         * @param   p_areaName   Reference key of the searched geoArea
         * @return  GeoArea - The serached geoArea
tepelmann's avatar
tepelmann committed
         */
berge's avatar
berge committed
        function f_getArea(
            in charstring p_areaName
tepelmann's avatar
tepelmann committed
        ) runs on ItsGeoNetworking
        return GeoArea {
            var GeoArea v_return;
            var integer i := 0;
            
berge's avatar
berge committed
            for (i:=0; i<lengthof(vc_areaTable); i:=i+1) {
                if (vc_areaTable[i].key == p_areaName) {
                    v_return := vc_areaTable[i].geoArea;
berge's avatar
berge committed
            
            return v_return;
        }
        
tepelmann's avatar
tepelmann committed
         * @desc    Get the geoBroadcastArea corresponding to a key
         * @param   p_areaName   Reference key of the searched geoBroadcastArea
         * @return  GeoBroadcastArea - The serached geoBroadcastArea
tepelmann's avatar
tepelmann committed
         */
        function f_getGeoBroadcastArea(in charstring p_areaName) runs on ItsGeoNetworking
        return GeoBroadcastArea {
            return f_geoArea2GeoBroadcastArea(f_getArea(p_areaName));
tepelmann's avatar
tepelmann committed
         * @desc    Get the GeoAnycastArea corresponding to a key
         * @param   p_areaName   Reference key of the searched GeoAnycastArea
         * @return  GeoAnycastArea - The serached GeoAnycastArea
tepelmann's avatar
tepelmann committed
         */
        function f_getGeoAnycastArea(in charstring p_areaName) runs on ItsGeoNetworking
            return f_geoArea2GeoAnycastArea(f_getArea(p_areaName));
        /**
         * @desc    Convert GeoArea type to GeoBroadcastArea
         * @param   p_area  GeoArea to be converted
         * @return  GeoBroadcastArea
tepelmann's avatar
tepelmann committed
        function f_geoArea2GeoBroadcastArea(GeoArea p_area)
        return GeoBroadcastArea {
            var GeoBroadcastArea v_broadcastArea;
            if (p_area.shape == e_geoCircle) {
                v_broadcastArea.geoBroadcastSubType := e_geoBroadcastCircle;
            }
            else if (p_area.shape == e_geoRect) {
                v_broadcastArea.geoBroadcastSubType := e_geoBroadcastRect;
            }
            else if (p_area.shape == e_geoElip) {
                v_broadcastArea.geoBroadcastSubType := e_geoBroadcastElip;
            }
            else {
                v_broadcastArea.geoBroadcastSubType := e_reserved;
            }
            
            v_broadcastArea.geoBroadcastArea := p_area.area;
            
            return v_broadcastArea;
berge's avatar
berge committed
        }
        /**
         * @desc    Convert GeoArea type to GeoAnycastArea
         * @param   p_area  GeoArea to be converted
         * @return  GeoAnycastArea
tepelmann's avatar
tepelmann committed
         */
        function f_geoArea2GeoAnycastArea(GeoArea p_area)
        return GeoAnycastArea {
            var GeoAnycastArea v_anycastArea;
            
            if (p_area.shape == e_geoCircle) {
                v_anycastArea.geoAnycastSubType := e_geoAnycastCircle;
            }
            else if (p_area.shape == e_geoRect) {
                v_anycastArea.geoAnycastSubType := e_geoAnycastRect;
            }
            else if (p_area.shape == e_geoElip) {
                v_anycastArea.geoAnycastSubType := e_geoAnycastElip;
            }
            else {
                v_anycastArea.geoAnycastSubType := e_reserved;
            }
            
            v_anycastArea.geoAnycastArea := p_area.area;
            
            return v_anycastArea;
        }
        
        /**
         * @desc    Compute a square geoArea
         * @param   p_centerLongPosVector   Center point of the square area
         * @param   p_distanceA             Width of the square area in meters
         * @return  GeoArea - Computed geoArea
        function f_computeSquareArea(
tepelmann's avatar
tepelmann committed
            in LongPosVector p_centerLongPosVector,
            in UInt16 p_distanceA
        ) return GeoArea {
            var GeoArea v_geoArea;
            
            v_geoArea := {
                shape := e_geoRect,
                area := {
                    geoAreaPosLatitude := p_centerLongPosVector.latitude,
                    geoAreaPosLongitude := p_centerLongPosVector.longitude,
                    distanceA := p_distanceA,
                    distanceB := p_distanceA,
tepelmann's avatar
tepelmann committed
                    angle := 0
tepelmann's avatar
tepelmann committed
            return v_geoArea;
berge's avatar
berge committed
        /**
         * @desc    Compute a circular geoArea
         * @param   p_centerLongPosVector   Center point of the square area
         * @param   p_distanceA             Radius of the square area in meters
         * @return  GeoArea - Computed geoArea
         */
        function f_computeCircularArea(
tepelmann's avatar
tepelmann committed
            in LongPosVector p_centerLongPosVector,
berge's avatar
berge committed
            in UInt16 p_distanceA
        ) return GeoArea {
                
            var GeoArea v_geoArea;
            
            v_geoArea := {
                shape := e_geoCircle,
                area := {
                    geoAreaPosLatitude := p_centerLongPosVector.latitude,
                    geoAreaPosLongitude := p_centerLongPosVector.longitude,
                    distanceA := p_distanceA,
                    distanceB := 0,
tepelmann's avatar
tepelmann committed
                    angle := 0
tepelmann's avatar
tepelmann committed
            return v_geoArea;
        }
tepelmann's avatar
tepelmann committed
        /**
         * @desc    Compute radius of an circular area
         * @param   p_squareMeters  Square meters of an circular area
         * @return  Computed radius in meters
         * @see     fx_computeRadiusFromCircularArea
         */
        function f_radiusFromCircularArea(
            in float p_squareMeters
        ) return float {
         
            log("*** f_distance: INFO: calling fx_computeRadiusFromCircularArea() ***");
            return fx_computeRadiusFromCircularArea(p_squareMeters);
        }
        
        /**
         * @desc    Compute distance between two points
         * @param   p_pointA    First point
         * @param   p_pointB    Second point
         * @return  Computed distance in meters
         * @see     fx_computeDistance
        function f_distance(
            in LongPosVector p_pointA,
            in LongPosVector p_pointB
        ) return float {
         
            log("*** f_distance: INFO: calling fx_computeDistance() ***");
tepelmann's avatar
tepelmann committed
            return fx_computeDistance(p_pointA.latitude, p_pointA.longitude, p_pointB.latitude, p_pointB.longitude);
tepelmann's avatar
tepelmann committed
    } // end geoPositionFunctions
berge's avatar
berge committed
    group geoAltsteps {
berge's avatar
berge committed
        /**
         * @desc The base default.
         */
reinaortega's avatar
reinaortega committed
        altstep a_default() runs on ItsGeoNetworking {
            var LongPosVector v_longPosVectorIut;
            
            [] a_receiveLsRequest(
                ?, ?, v_longPosVectorIut
tepelmann's avatar
tepelmann committed
               ) {
            [] geoNetworkingPort.receive {
berge's avatar
berge committed
                log("*** a_default: ERROR: Received an unexpected message ***");
                f_selfOrClientSyncAndVerdict("error", e_error);
            }
            [] tc_wait.timeout {
berge's avatar
berge committed
                log("*** a_default: ERROR: Timeout while awaiting reaction of the IUT prior to Upper Tester action ***");
                f_selfOrClientSyncAndVerdict("error", e_timeout);
            }
            [] tc_ac.timeout {
berge's avatar
berge committed
                log("*** a_default: ERROR: Timeout while awaiting the reception of a message ***");
                f_selfOrClientSyncAndVerdict("error", e_timeout);
berge's avatar
berge committed
            [] a_shutdown() {
                log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
tepelmann's avatar
tepelmann committed
                stop;
berge's avatar
berge committed
            }
tepelmann's avatar
tepelmann committed
         * @desc    Neighbour default altstep (answers to LS Requests)
reinaortega's avatar
reinaortega committed
        altstep a_neighbourDefault() runs on ItsGeoNetworking {
            [] a_receiveLsRequestAndReply(
tepelmann's avatar
tepelmann committed
                ?, f_getPosition(vc_componentName).gnAddr.mid,
                f_getPosition(vc_componentName),
                f_getPosition(vc_componentName)
tepelmann's avatar
tepelmann committed
               ) {
                repeat;
tepelmann's avatar
tepelmann committed
            }
            [vc_componentName == c_compNodeB] a_receiveLsRequestAndReply(
tepelmann's avatar
tepelmann committed
                ?, f_getPosition(c_compNodeA).gnAddr.mid,
                f_getPosition(c_compNodeA),
                f_getPosition(vc_componentName)
tepelmann's avatar
tepelmann committed
               ) {
tepelmann's avatar
tepelmann committed
            }
tepelmann's avatar
tepelmann committed
        
        /**
         * @desc Default handling cf01 de-initialisation.
         */
        altstep a_cf01Down() runs on ItsGeoNetworking {
            [] a_shutdown() {
                f_poDefault();
                f_cf01Down();
                log("*** a_cf01Down: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
tepelmann's avatar
tepelmann committed
                stop;
tepelmann's avatar
tepelmann committed
            }
        }
        
        /**
         * @desc Default handling cf02 de-initialisation.
         */
        altstep a_cf02Down(in ItsGeoNetworking p_nodeB, in ItsGeoNetworking p_nodeD) runs on ItsMtc {
            [] a_shutdown() {
                f_cf02Down(p_nodeB, p_nodeD);
                log("*** a_cf02Down: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
                stop;
            }
        }
        
        /**
         * @desc Default handling cf03 de-initialisation.
         */
        altstep a_cf03Down(in ItsGeoNetworking p_nodeB, in ItsGeoNetworking p_nodeC) runs on ItsMtc {
            [] a_shutdown() {
                f_cf03Down(p_nodeB, p_nodeC);
                log("*** a_cf03Down: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
                stop;
            }
        }
        
        /**
         * @desc Default handling cf04 de-initialisation.
         */
        altstep a_cf04Down(in ItsGeoNetworking p_nodeB, in ItsGeoNetworking p_nodeC, in ItsGeoNetworking p_nodeD) runs on ItsMtc {
            [] a_shutdown() {
                f_cf04Down(p_nodeB, p_nodeC, p_nodeD);
                log("*** a_cf04Down: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
                stop;
            }
        }
berge's avatar
berge committed
        
        group geoGeoUnicastAltsteps {
            
            /**
             * @desc    Receive GeoUnicast packet
tepelmann's avatar
tepelmann committed
             * @param   p_sourceLongPosVec          Expected source position vector
             * @param   p_destinationShortPosVec    Expected destination position vector
             * @param   p_seqNumber                 Expected sequence number
berge's avatar
berge committed
             */
berge's avatar
berge committed
            altstep a_receiveGeoUnicast(
                in template (present) ShortPosVector p_destinationShortPosVec,
                in template (present) UInt16 p_seqNumber
reinaortega's avatar
reinaortega committed
            ) runs on ItsGeoNetworking {
berge's avatar
berge committed
                
tepelmann's avatar
tepelmann committed
                [] geoNetworkingPort.receive(mw_geoNwInd(mw_geoNwPdu(mw_geoNwUnicastPacket(
berge's avatar
berge committed
                    p_destinationShortPosVec,
                    p_seqNumber)))) {
tepelmann's avatar
tepelmann committed
                }
tepelmann's avatar
tepelmann committed
            }
berge's avatar
berge committed
            
            /**
             * @desc    Receive GeoUnicast packet for specific destination
             * @param   p_destinationShortPosVec    Expected destination position vector
berge's avatar
berge committed
             */
reinaortega's avatar
reinaortega committed
            altstep a_receiveGeoUnicastWithDestination(in template (present) ShortPosVector p_destinationShortPosVec) runs on ItsGeoNetworking {
berge's avatar
berge committed
                
tepelmann's avatar
tepelmann committed
                [] a_receiveGeoUnicast(p_destinationShortPosVec, ?) {}
tepelmann's avatar
tepelmann committed
            }
berge's avatar
berge committed
            
            /**
             * @desc Receive any GeoUnicast packet
             */
reinaortega's avatar
reinaortega committed
            altstep a_receiveAnyGeoUnicast() runs on ItsGeoNetworking {
berge's avatar
berge committed
                
tepelmann's avatar
tepelmann committed
                [] a_receiveGeoUnicast(?, ?) {}
tepelmann's avatar
tepelmann committed
            }
berge's avatar
berge committed
            
        } // end geoGeoUnicastAltsteps
        
berge's avatar
berge committed
        group geoGeoBroadcastAltsteps {
            
            /**
             * @desc Receive GeoBroadcast packet
             * @param   p_srcLongPosVec     Expected source position vector
             * @param   p_seqNumber         Expected sequence number
berge's avatar
berge committed
             */
            altstep a_receiveGeoBroadcast(
tepelmann's avatar
tepelmann committed
                in template (present) LongPosVector p_srcLongPosVec,
berge's avatar
berge committed
                in template (present) UInt16 p_seqNumber
reinaortega's avatar
reinaortega committed
            ) runs on ItsGeoNetworking {
tepelmann's avatar
tepelmann committed
                [] geoNetworkingPort.receive(mw_geoNwInd(mw_geoNwPdu(mw_geoNwBroadcastPacket(
berge's avatar
berge committed
                        p_srcLongPosVec,
                        p_seqNumber
                    )))) {
                }
            }
berge's avatar
berge committed
            
            /**
             * @desc Receive GeoBroadcast packet with specific Area and HopLimit
             * @param   p_srcLongPosVec     Expected source position vector
             * @param   p_seqNumber         Expected sequence number
             * @param   p_broadcastArea     Expected geoBroadcastArea
             * @param   p_routerHopLimit    Expected router hop limit
             * @param   p_maxHopLimit       Expected max hop limit (Default: ?)
berge's avatar
berge committed
             */
            altstep a_receiveGeoBroadcastWithAreaWithHopLimit(
tepelmann's avatar
tepelmann committed
                in template (present) LongPosVector p_srcLongPosVec,