Compare commits

...

2 Commits

Author SHA1 Message Date
4726e443b4 Unit test fixes 2025-04-28 18:13:22 +02:00
2fe73b39be Aligned participant documentation 2025-04-28 18:13:12 +02:00
8 changed files with 48 additions and 39 deletions

View File

@ -11,10 +11,14 @@ class ParticipantMsg(IMessage):
## The length of the message ## The length of the message
length: int = 2 length: int = 2
def __init__(self, data = None): def __init__(self, arg1):
"""! Create a new message for sending """! Create a new message for sending
""" """
self.network_id = data if isinstance(arg1, bytes):
buffer = arg1
self.network_id = buffer[1]
else:
self.network_id = arg1
def Serialize(self, buffer_ref): def Serialize(self, buffer_ref):
"""! Serialize the message into a byte array. """! Serialize the message into a byte array.

View File

@ -8,6 +8,8 @@ class Participant:
""" """
def __init__(self, ip_address, port): def __init__(self, ip_address, port):
"""! Create a new participant with the given communcation info """! Create a new participant with the given communcation info
@param ip_address The IP address of the participant
@param port The UDP port of the participant
""" """
## The Ip Address of a participant. When the participant is local, this contains 0.0.0.0 ## The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
@ -15,16 +17,27 @@ class Participant:
## The port number for UDP communication with the participant. This is 0 for isolated participants. ## The port number for UDP communication with the participant. This is 0 for isolated participants.
self.port = port self.port = port
## The network ID of the participant ## he network Id to identify the participant.
self.network_id =0 self.network_id =0
## The things managed by this participant ## The things managed by this participant
self.things = set() self.things = set()
def Get(self, thing_id):
"""! Get the thing with the given properties
@param thing_id The ID of the thing
@return The thing if found, None in other cases
"""
for thing in self.things:
if thing is not None and thing.id == thing_id:
return thing
return None
def Add(self, thing, check_id = True): def Add(self, thing, check_id = True):
"""! Add a new thing for this participant. """! Add a new thing for this participant.
@param thing The thing to add @param thing The thing to add
@param check_id When true, the thing ID of the thing is checked. If it is 0, a new thing Id will be assigned. @param check_id If true, the thing.id is regenerated if it is zero
""" """
if check_id and thing.id == 0: if check_id and thing.id == 0:
thing.id = len(self.things) + 1 thing.id = len(self.things) + 1
@ -34,25 +47,16 @@ class Participant:
if found_thing == None: if found_thing == None:
self.things.add(thing) self.things.add(thing)
def Get(self, thing_id):
"""! Find a thing managed by this participant
@param thing_id The ID of the thing
@return The thing if found or nullptr when no thing has been found
"""
for thing in self.things:
if thing is not None and thing.id == thing_id:
return thing
return None
def Remove(self, thing): def Remove(self, thing):
"""! Remove a thig for this participant """! Remove a thing for this participant
@param thing The thing to remove @param thing The thing to remove
""" """
self.things.remove(thing) self.things.remove(thing)
## Update all things def Update(self, currentTimeMs=0):
def Update(self, currentTimeMs): """! Update all things for this participant
@param The current time in milliseconds (optional)
"""
for thing in list(self.things): for thing in list(self.things):
if thing is not None: if thing is not None:
thing.Update(currentTimeMs) thing.Update(currentTimeMs)

View File

@ -33,12 +33,12 @@ class ParticipantUDP(Participant):
name = "Participant" name = "Participant"
isolated_participant = None isolated_participant = None
def __init__(self, port=7681, ip_address=None, local_port=0): def __init__(self, port=7681, ip_address=None, local_port=7681):
super().__init__(ip_address = "127.0.0.1", port = port) super().__init__(ip_address = "127.0.0.1", port = local_port)
if local_port == 0: # if local_port == 0:
local_port = port # local_port = port
self.local_port = local_port # self.local_port = local_port
## True if the participant is running isolated. ## True if the participant is running isolated.
# Isolated participants do not communicate with other participants # Isolated participants do not communicate with other participants
@ -48,7 +48,7 @@ class ParticipantUDP(Participant):
## The other participants communicating with this participant ## The other participants communicating with this participant
self.others = [] self.others = []
if self.port != 0: if port != 0:
self.is_isolated = False self.is_isolated = False
if ip_address is not None: if ip_address is not None:
self.remote_site = Participant(ip_address, port) self.remote_site = Participant(ip_address, port)
@ -59,7 +59,7 @@ class ParticipantUDP(Participant):
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
self.udp_socket.bind(("0.0.0.0", self.local_port)) self.udp_socket.bind(("0.0.0.0", self.port))
self.thread = threading.Thread(target = self.Receiver) self.thread = threading.Thread(target = self.Receiver)
self.thread.daemon = True self.thread.daemon = True

View File

@ -23,7 +23,8 @@ class SiteServer(ParticipantUDP):
def ProcessParticipantMsg(self, sender, msg): def ProcessParticipantMsg(self, sender, msg):
print(f'{self.name} received Participant ') print(f'{self.name} received Participant ')
self.Send(sender, NetworkIdMsg()) if msg.network_id != sender.network_id:
self.Send(sender, sender.network_id)
def ProcessNetworkId(self, msg): def ProcessNetworkId(self, msg):
pass pass

View File

@ -39,7 +39,7 @@ class Thing:
owner = parent.owner owner = parent.owner
self.SetParent(parent) self.SetParent(parent)
elif owner == None: elif owner == None:
from ParticipantUDP import ParticipantUDP from RoboidControl.ParticipantUDP import ParticipantUDP
owner = ParticipantUDP.Isolated() owner = ParticipantUDP.Isolated()
self.children = [] self.children = []

View File

@ -1,5 +1,5 @@
from Thing import Thing from RoboidControl.Thing import Thing
from Messages import LowLevelMessages from RoboidControl.Messages import LowLevelMessages
class TemperatureSensor(Thing): class TemperatureSensor(Thing):
def __init__(self, thing_id): def __init__(self, thing_id):

View File

@ -4,11 +4,11 @@ from pathlib import Path
sys.path.append(str(Path(__file__).resolve().parent.parent)) sys.path.append(str(Path(__file__).resolve().parent.parent))
import time import time
from Participants.SiteServer import SiteServer from RoboidControl.Participants.SiteServer import SiteServer
from ParticipantUDP import ParticipantUDP from RoboidControl.ParticipantUDP import ParticipantUDP
from Thing import * from RoboidControl.Thing import *
from Things.DifferentialDrive import DifferentialDrive from RoboidControl.Things.DifferentialDrive import DifferentialDrive
from Things.TouchSensor import TouchSensor from RoboidControl.Things.TouchSensor import TouchSensor
# Start a site server # Start a site server
site = SiteServer(port=7691) site = SiteServer(port=7691)

View File

@ -3,13 +3,13 @@ import sys
from pathlib import Path from pathlib import Path
# Add the project root to sys.path # Add the project root to sys.path
sys.path.append(str(Path(__file__).resolve().parent.parent)) sys.path.append(str(Path(__file__).resolve().parent))
import unittest import unittest
from Thing import Thing from RoboidControl.Thing import Thing
from ParticipantUDP import ParticipantUDP from RoboidControl.ParticipantUDP import ParticipantUDP
from Participants.SiteServer import SiteServer from RoboidControl.Participants.SiteServer import SiteServer
class ThingTest(unittest.TestCase): class ThingTest(unittest.TestCase):
@ -33,7 +33,7 @@ class ThingTest(unittest.TestCase):
def test_site_participant(self): def test_site_participant(self):
site = SiteServer(port=7681) site = SiteServer(port=7681)
participant = ParticipantUDP(port=7681, ip_address="127.0.0.1", local_port=7682) participant = ParticipantUDP(ip_address="127.0.0.1", port=7681, local_port=7682)
milliseconds = time.time() * 1000 milliseconds = time.time() * 1000
start_time = milliseconds start_time = milliseconds