Skip to content

Introduction

gradysim.protocol

Use this module to create protocols. What GrADyS-SIM NextGen calls protocols is the logic that powers network nodes. Each network node has a protocol instance that is responsible for the node's behavior. Protocols define how a node reacts to its environment and enable it to interact with it.

Protocols are environment agnostic, meaning they are not coupled to a specific environment. This allows for the same protocol to be used in different environments. For example, a protocol that defines how a node reacts to its environment can be used in different simulation environments and even in a real-world environment.

Protocols are created by subclassing the IProtocol interface. The IProtocol interface defines the methods that a protocol must implement. These methods are reactive in nature, meaning they are called to react to events that occur in the environment. For example, a protocol may implement a method that is called when a node receives a message from another node. The protocol can then react to the message by sending a message back to the sender or by sending a message to another node.

The protocol interface also guides how the protocol can affect its environment, through a IProvider instance that is injected into the protocol when it is instantiated. The IProvider instance provides the protocol with the necessary tools to interact with the environment. It enables the protocol to send messages to other nodes, schedule timers, and more.

Messages are sent using the CommunicationCommand class. It instructs the node's communication module to perform some communication action, generally sending a message to another node. The node's communication module is not known by the protocol and shouldn't be its concern. The protocol only needs to know how to send messages and the IProvider instance provides it with the necessary tools to do so.

The protocol can affect its node's mobility by sending MobilityCommand via the IProvider instance. The MobilityCommand class instructs the node's mobility module to perform some mobility action, generally moving the node to a new location. The node's mobility module is not known by the protocol and shouldn't be its concern. The protocol only needs to know how to move the node and the IProvider instance provides it with the necessary tools to do so.

The protocol can also schedule timers using the IProvider instance. Timers are scheduled using the schedule_timer() method. The method takes a timer and a timestamp as arguments. These timers can be cancelled using the cancel_timer() method.

gradysim.protocol.interface.IProtocol

Bases: ABC

Subclass this interface to define a protocol. All abstract methods must be implemented, they can be empty in case no action is necessary. These methods define how a node reacts to its environment. You should use them to implement the logic that powers your node. Following this interface you will need to implement your protocol's logic in a event-based fashion.

The IProvider interface accessible through the provider attribute provides the protocol with the necessary tools to interact with the environment.

Protocols that follow this interface can run in any of the execution-modes supported by GrADyS-SIM NextGen.

Source code in gradysim/protocol/interface.py
class IProtocol(ABC):
    """
    Subclass this interface to define a protocol. All abstract methods must be implemented, they can be empty in case
    no action is necessary. These methods define how a node reacts to its environment. You should use them to implement
    the logic that powers your node. Following this interface you will need to implement your protocol's logic in a
    event-based fashion.

    The IProvider interface accessible through the `provider` attribute provides the protocol with the necessary tools
    to interact with the environment.

    Protocols that follow this interface can run in any of the [execution-modes][] supported by GrADyS-SIM NextGen.
    """

    provider: IProvider
    """
    IProvider instance that will provide protocol
    with necessary tools to interact with the environment.
    """

    @classmethod
    def instantiate(cls, provider: IProvider) -> 'IProtocol':
        """
        Called when the protocol is instantiated before the simulator starts. The protocol's __init__() method is not
        called, instead this method is used to initialize the protocol.

        Args:
            provider: the IProvider instance that will provide the protocol
                with necessary tools to interact with the environment

        Returns:
            the instantiated protocol
        """
        protocol = cls()
        protocol.provider = provider
        return protocol

    @abstractmethod
    def initialize(self) -> None:
        """
        This is the first function called when the simulator begins. The initialize()
        methods for each network node are called in arbitrary order so don't rely on other
        protocols having already been initialized.
        """
        pass

    @abstractmethod
    def handle_timer(self, timer: str) -> None:
        """
        Called when a timer fires. The timer is identified by a string. This is the same string that was passed to the
        provider's schedule_timer() method when the timer was scheduled.

        Args:
            timer: the timer that fired
        """
        pass

    @abstractmethod
    def handle_packet(self, message: str) -> None:
        """
        Called when a packet is received from another node. The packet contains a message which can be an identifier,
        some serialized data, or anything else that can be represented as a string.

        Args:
            message: the message contained in the packet
        """
        pass

    @abstractmethod
    def handle_telemetry(self, telemetry: Telemetry) -> None:
        """
        Regularly called by the mobility module with information about the state of the node's mobility. Use this data
        if your protocol should react to the node's mobility.

        Args:
            telemetry: the telemetry data
        """
        pass

    @abstractmethod
    def finish(self) -> None:
        """
        Called when the simulator finishes. The finish() method of every node in the simulator is called in arbitrary
        order.
        """
        pass

provider: IProvider instance-attribute

IProvider instance that will provide protocol with necessary tools to interact with the environment.

finish() abstractmethod

Called when the simulator finishes. The finish() method of every node in the simulator is called in arbitrary order.

Source code in gradysim/protocol/interface.py
@abstractmethod
def finish(self) -> None:
    """
    Called when the simulator finishes. The finish() method of every node in the simulator is called in arbitrary
    order.
    """
    pass

handle_packet(message) abstractmethod

Called when a packet is received from another node. The packet contains a message which can be an identifier, some serialized data, or anything else that can be represented as a string.

Parameters:

Name Type Description Default
message str

the message contained in the packet

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def handle_packet(self, message: str) -> None:
    """
    Called when a packet is received from another node. The packet contains a message which can be an identifier,
    some serialized data, or anything else that can be represented as a string.

    Args:
        message: the message contained in the packet
    """
    pass

handle_telemetry(telemetry) abstractmethod

Regularly called by the mobility module with information about the state of the node's mobility. Use this data if your protocol should react to the node's mobility.

Parameters:

Name Type Description Default
telemetry Telemetry

the telemetry data

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def handle_telemetry(self, telemetry: Telemetry) -> None:
    """
    Regularly called by the mobility module with information about the state of the node's mobility. Use this data
    if your protocol should react to the node's mobility.

    Args:
        telemetry: the telemetry data
    """
    pass

handle_timer(timer) abstractmethod

Called when a timer fires. The timer is identified by a string. This is the same string that was passed to the provider's schedule_timer() method when the timer was scheduled.

Parameters:

Name Type Description Default
timer str

the timer that fired

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def handle_timer(self, timer: str) -> None:
    """
    Called when a timer fires. The timer is identified by a string. This is the same string that was passed to the
    provider's schedule_timer() method when the timer was scheduled.

    Args:
        timer: the timer that fired
    """
    pass

initialize() abstractmethod

This is the first function called when the simulator begins. The initialize() methods for each network node are called in arbitrary order so don't rely on other protocols having already been initialized.

Source code in gradysim/protocol/interface.py
@abstractmethod
def initialize(self) -> None:
    """
    This is the first function called when the simulator begins. The initialize()
    methods for each network node are called in arbitrary order so don't rely on other
    protocols having already been initialized.
    """
    pass

instantiate(provider) classmethod

Called when the protocol is instantiated before the simulator starts. The protocol's init() method is not called, instead this method is used to initialize the protocol.

Parameters:

Name Type Description Default
provider IProvider

the IProvider instance that will provide the protocol with necessary tools to interact with the environment

required

Returns:

Type Description
IProtocol

the instantiated protocol

Source code in gradysim/protocol/interface.py
@classmethod
def instantiate(cls, provider: IProvider) -> 'IProtocol':
    """
    Called when the protocol is instantiated before the simulator starts. The protocol's __init__() method is not
    called, instead this method is used to initialize the protocol.

    Args:
        provider: the IProvider instance that will provide the protocol
            with necessary tools to interact with the environment

    Returns:
        the instantiated protocol
    """
    protocol = cls()
    protocol.provider = provider
    return protocol

gradysim.protocol.interface.IProvider

Bases: ABC

Interface that all protocols use to interact with their environment. The IProvider instance provides the protocol with the necessary tools to interact with the environment. It enables the protocol to send messages to other nodes, schedule timers, and more.

Source code in gradysim/protocol/interface.py
class IProvider(ABC):
    """
    Interface that all protocols use to interact with their environment. The IProvider instance provides the protocol
    with the necessary tools to interact with the environment. It enables the protocol to send messages to other nodes,
    schedule timers, and more.
    """

    @abstractmethod
    def send_communication_command(self, command: CommunicationCommand) -> None:
        """
        Sends a communication command to the node's communication module

        Args:
            command: the communication command to send
        """
        pass

    @abstractmethod
    def send_mobility_command(self, command: MobilityCommand) -> None:
        """
        Sends a mobility command to the node's mobility module

        Args:
            command: the mobility command to send
        """
        pass

    @abstractmethod
    def schedule_timer(self, timer: str, timestamp: float) -> None:
        """
        Schedules a timer that should fire at a specified timestamp

        Args:
            timer: the timer to schedule. Use this string to identify the timer when it fires, associate it with some
                serialized data, or anything else that can be represented as a string.
            timestamp: the timestamp in simulation seconds at which the timer should fire.
        """
        pass

    @abstractmethod
    def cancel_timer(self, timer: str) -> None:
        """
        Cancels a timer that was previously scheduled. If a timer with the given identifier is not scheduled,
        this method does nothing. If multiple timers with the same identifier are scheduled, all of them are canceled.

        Args:
            timer: identifier of the timer to cancel
        """
        pass

    @abstractmethod
    def current_time(self) -> float:
        """
        Returns the current simulator time in seconds

        Returns:
            the current simulator time in seconds
        """
        pass

    @abstractmethod
    def get_id(self) -> int:
        """
        Returns the node's unique identifier in the simulation

        Returns:
            the node's unique identifier in the simulation
        """
        pass

    # TODO: Document this
    tracked_variables: Dict[str, Any]

cancel_timer(timer) abstractmethod

Cancels a timer that was previously scheduled. If a timer with the given identifier is not scheduled, this method does nothing. If multiple timers with the same identifier are scheduled, all of them are canceled.

Parameters:

Name Type Description Default
timer str

identifier of the timer to cancel

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def cancel_timer(self, timer: str) -> None:
    """
    Cancels a timer that was previously scheduled. If a timer with the given identifier is not scheduled,
    this method does nothing. If multiple timers with the same identifier are scheduled, all of them are canceled.

    Args:
        timer: identifier of the timer to cancel
    """
    pass

current_time() abstractmethod

Returns the current simulator time in seconds

Returns:

Type Description
float

the current simulator time in seconds

Source code in gradysim/protocol/interface.py
@abstractmethod
def current_time(self) -> float:
    """
    Returns the current simulator time in seconds

    Returns:
        the current simulator time in seconds
    """
    pass

get_id() abstractmethod

Returns the node's unique identifier in the simulation

Returns:

Type Description
int

the node's unique identifier in the simulation

Source code in gradysim/protocol/interface.py
@abstractmethod
def get_id(self) -> int:
    """
    Returns the node's unique identifier in the simulation

    Returns:
        the node's unique identifier in the simulation
    """
    pass

schedule_timer(timer, timestamp) abstractmethod

Schedules a timer that should fire at a specified timestamp

Parameters:

Name Type Description Default
timer str

the timer to schedule. Use this string to identify the timer when it fires, associate it with some serialized data, or anything else that can be represented as a string.

required
timestamp float

the timestamp in simulation seconds at which the timer should fire.

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def schedule_timer(self, timer: str, timestamp: float) -> None:
    """
    Schedules a timer that should fire at a specified timestamp

    Args:
        timer: the timer to schedule. Use this string to identify the timer when it fires, associate it with some
            serialized data, or anything else that can be represented as a string.
        timestamp: the timestamp in simulation seconds at which the timer should fire.
    """
    pass

send_communication_command(command) abstractmethod

Sends a communication command to the node's communication module

Parameters:

Name Type Description Default
command CommunicationCommand

the communication command to send

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def send_communication_command(self, command: CommunicationCommand) -> None:
    """
    Sends a communication command to the node's communication module

    Args:
        command: the communication command to send
    """
    pass

send_mobility_command(command) abstractmethod

Sends a mobility command to the node's mobility module

Parameters:

Name Type Description Default
command MobilityCommand

the mobility command to send

required
Source code in gradysim/protocol/interface.py
@abstractmethod
def send_mobility_command(self, command: MobilityCommand) -> None:
    """
    Sends a mobility command to the node's mobility module

    Args:
        command: the mobility command to send
    """
    pass