Skip to content

Documentation for Distcandidateselector Module

DistanceCandidateSelector

Bases: CandidateSelector

Selects candidate nodes based on their physical proximity.

This selector uses geolocation data to filter candidates within a maximum distance threshold. It listens for GPS updates and maintains a mapping of node identifiers to their distances and coordinates.

Attributes:

Name Type Description
MAX_DISTANCE_THRESHOLD int

Maximum distance (in meters) allowed for a node to be considered a valid candidate.

candidates list

List of candidate nodes to be evaluated.

candidates_lock Locker

Async lock for managing concurrent access to the candidate list.

nodes_distances dict

Maps node IDs to a tuple containing the distance and GPS coordinates.

nodes_distances_lock Locker

Async lock for the distance mapping.

_verbose bool

Flag to enable verbose logging for debugging.

Methods:

Name Description
set_config

Subscribes to GPS events for distance updates.

add_candidate

Adds a new candidate to the list.

select_candidates

Returns candidates within the allowed distance.

remove_candidates

Clears the candidate list.

any_candidate

Returns True if there is at least one candidate.

Inherits from

CandidateSelector: Base class interface for candidate selection logic.

Source code in nebula/core/situationalawareness/discovery/candidateselection/distcandidateselector.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class DistanceCandidateSelector(CandidateSelector):
    """
    Selects candidate nodes based on their physical proximity.

    This selector uses geolocation data to filter candidates within a 
    maximum distance threshold. It listens for GPS updates and maintains 
    a mapping of node identifiers to their distances and coordinates.

    Attributes:
        MAX_DISTANCE_THRESHOLD (int): Maximum distance (in meters) allowed 
            for a node to be considered a valid candidate.
        candidates (list): List of candidate nodes to be evaluated.
        candidates_lock (Locker): Async lock for managing concurrent access 
            to the candidate list.
        nodes_distances (dict): Maps node IDs to a tuple containing the 
            distance and GPS coordinates.
        nodes_distances_lock (Locker): Async lock for the distance mapping.
        _verbose (bool): Flag to enable verbose logging for debugging.

    Methods:
        set_config(config): Subscribes to GPS events for distance updates.
        add_candidate(candidate): Adds a new candidate to the list.
        select_candidates(): Returns candidates within the allowed distance.
        remove_candidates(): Clears the candidate list.
        any_candidate(): Returns True if there is at least one candidate.

    Inherits from:
        CandidateSelector: Base class interface for candidate selection logic.
    """
    # INFO: This value may change according to the needs of the federation
    MAX_DISTANCE_THRESHOLD = 200

    def __init__(self):
        self.candidates = []
        self.candidates_lock = Locker(name="candidates_lock", async_lock=True)
        self.nodes_distances: dict[str, tuple[float, tuple[float, float]]] = None
        self.nodes_distances_lock = Locker("nodes_distances_lock", async_lock=True)
        self._verbose = False

    async def set_config(self, config):
        await EventManager.get_instance().subscribe_addonevent(GPSEvent, self._udpate_distances)

    async def _udpate_distances(self, gpsevent: GPSEvent):
        async with self.nodes_distances_lock:
            distances = await gpsevent.get_event_data()
            self.nodes_distances = distances

    async def add_candidate(self, candidate):
        async with self.candidates_lock:
            self.candidates.append(candidate)

    async def select_candidates(self):
        async with self.candidates_lock:
            async with self.nodes_distances_lock:
                nodes_available = [
                    candidate
                    for candidate in self.candidates
                    if candidate[0] in self.nodes_distances
                    and self.nodes_distances[candidate[0]][0] < self.MAX_DISTANCE_THRESHOLD
                ]
                if self._verbose:
                    logging.info(f"Nodes availables: {nodes_available}")
        return (nodes_available, [])

    async def remove_candidates(self):
        async with self.candidates_lock:
            self.candidates = []

    async def any_candidate(self):
        async with self.candidates_lock:
            any = True if len(self.candidates) > 0 else False
        return any