using Participant.Send

This commit is contained in:
Pascal Serrarens 2025-06-05 10:13:13 +02:00
parent 0c74320271
commit 26f8a238bc
2 changed files with 51 additions and 44 deletions

View File

@ -13,9 +13,9 @@ class Participant:
# region Init # region Init
local_participant = None local_participant: 'Participant' = None
def __init__(self, ip_address: str = None, port: int = None) -> None: def __init__(self, ip_address: str = None, port: int = None, local_participant: 'Participant' = None) -> None:
"""! 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 ip_address The IP address of the participant
@param port The UDP port of the participant @param port The UDP port of the participant
@ -26,6 +26,10 @@ 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: int = port self.port: int = port
self.udp_socket = None
if local_participant is not None:
self.udp_socket = local_participant.udp_socket
## he network Id to identify the participant. ## he network Id to identify the participant.
self.network_id: int = 0 self.network_id: int = 0
@ -130,7 +134,7 @@ class Participant:
return participant return participant
return None return None
def AddParticipant(arg1: Union[str, 'Participant'], port: Optional[int] = None) -> 'Participant': def AddParticipant(arg1: Union[str, 'Participant'], port: Optional[int] = None, local_participant: 'Participant' = None) -> 'Participant':
"""! Add a participant """! Add a participant
@param arg1 Either: @param arg1 Either:
- str: The IP address of the participant - str: The IP address of the participant
@ -139,14 +143,14 @@ class Participant:
""" """
if port is not None: if port is not None:
ip_address = str(arg1) ip_address = str(arg1)
participant = Participant(ip_address, port) participant = Participant(ip_address, port, local_participant)
participant.network_id = len(Participant.participants) + 1 participant.network_id = len(Participant.participants) + 1
Participant.AddParticipant(participant) Participant.AddParticipant(participant)
return participant return participant
else: else:
participant: Participant = arg1 participant: Participant = arg1
foundParticipant = Participant.GetParticipant(participant.network_id, participant.port) foundParticipant = Participant.GetParticipant(participant.network_id, participant.port)
if foundParticipant is not None: if foundParticipant is None:
Participant.participants.add(participant) Participant.participants.add(participant)
return participant return participant

View File

@ -43,6 +43,7 @@ class ParticipantUDP(Participant):
name = "Participant" name = "Participant"
#region Init #region Init
def __init__(self, def __init__(self,
port: int = 7681, port: int = 7681,
ip_address: Optional[str] = None, ip_address: Optional[str] = None,
@ -64,46 +65,47 @@ class ParticipantUDP(Participant):
## The interval in milliseconds for publishing (broadcasting) data on the local network ## The interval in milliseconds for publishing (broadcasting) data on the local network
self.publishInterval = 3000 # 3 seconds self.publishInterval = 3000 # 3 seconds
if port != 0:
self.is_isolated = False
if ip_address is not None:
self.remote_site = Participant(ip_address, port)
Participant.AddParticipant(self)
Participant.ReplaceLocalParticipant(self)
self.buffer: bytearray = bytearray(256) self.buffer: bytearray = bytearray(256)
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", local_port)) self.udp_socket.bind(("0.0.0.0", local_port))
if port != 0:
self.is_isolated = False
if ip_address is not None:
self.remote_site = Participant(ip_address, port, self)
self.thread = threading.Thread(target = self.Receiver) self.thread = threading.Thread(target = self.Receiver)
self.thread.daemon = True self.thread.daemon = True
self.thread.start() self.thread.start()
@staticmethod Participant.AddParticipant(self)
def Isolated() -> 'ParticipantUDP': Participant.ReplaceLocalParticipant(self)
if ParticipantUDP.isolated_participant == None:
ParticipantUDP.isolated_participant = ParticipantUDP(0) # @staticmethod
return ParticipantUDP.isolated_participant # def Isolated() -> 'ParticipantUDP':
# if ParticipantUDP.isolated_participant == None:
# ParticipantUDP.isolated_participant = ParticipantUDP(0)
# return ParticipantUDP.isolated_participant
#endregion Init #endregion Init
isolated_participant = None # isolated_participant = None
#region Update #region Update
def Update(self): def Update(self):
currentTimeMs = int(time.time() * 1000) currentTimeMs = int(time.time() * 1000)
# Send periodic ParticipantMsg
if self.is_isolated == False: if self.is_isolated == False:
if self.publishInterval > 0 and currentTimeMs > self.nextPublishMe: if self.publishInterval > 0 and currentTimeMs > self.nextPublishMe:
msg = ParticipantMsg(self.network_id) msg = ParticipantMsg(self.network_id)
if self.remote_site == None: if self.remote_site == None:
self.Publish(msg) self.Publish(msg)
else: else:
self.Send(self.remote_site, msg) self.remote_site.Send(msg)
self.nextPublishMe = currentTimeMs + self.publishInterval self.nextPublishMe = currentTimeMs + self.publishInterval
@ -116,21 +118,22 @@ class ParticipantUDP(Participant):
# if thing.hierarchyChanged and not (self.isIsolated or self.network_id == ): # if thing.hierarchyChanged and not (self.isIsolated or self.network_id == ):
# thingMsg = ThingMsg(self.network_id, thing) # thingMsg = ThingMsg(self.network_id, thing)
# self.Send(self.remote_site, thingMsg) # self.Send(self.remote_site, thingMsg)
if thing.owner is not None: # if thing.owner is not None:
poseMsg = PoseMsg(thing.owner.network_id, thing) # poseMsg = PoseMsg(thing.owner.network_id, thing)
if self.remote_site is not None: # if self.remote_site is not None:
self.Send(self.remote_site, poseMsg) # self.remote_site.Send(poseMsg)
thing.Update(False) thing.Update(False)
if not(self.is_isolated or self.network_id == 0): if not(self.is_isolated or self.network_id == 0):
if thing.terminate: if thing.terminate:
destroyMsg = DestroyMsg.Create(self.network_id, thing) destroyMsg = DestroyMsg.Create(self.network_id, thing)
self.Send(self.remote_site, destroyMsg) self.remote_site.Send(destroyMsg)
else: # else:
if self.remote_site is not None and thing.owner is not None: # this is very inefficient
# Send to remote site # if self.remote_site is not None and thing.owner is not None:
self.Send(self.remote_site, PoseMsg(thing.owner.network_id, thing)) # # Send to remote site
self.Send(self.remote_site, BinaryMsg(thing.owner.network_id, thing)) # self.Send(self.remote_site, PoseMsg(thing.owner.network_id, thing))
# self.Send(self.remote_site, BinaryMsg(thing.owner.network_id, thing))
if thing.terminate: if thing.terminate:
self.Remove(thing) self.Remove(thing)
@ -139,11 +142,11 @@ class ParticipantUDP(Participant):
#region Send #region Send
def SendThingInfo(self, owner: Participant, thing: 'Thing', recursively: bool = False): def SendThingInfo(self, owner: Participant, thing: 'Thing', recursively: bool = False):
self.Send(owner, ThingMsg(self.network_id, thing)) owner.Send(ThingMsg(self.network_id, thing))
self.Send(owner, NameMsg(self.network_id, thing)) owner.Send(NameMsg(self.network_id, thing))
self.Send(owner, ModelUrlMsg(self.network_id, thing)) owner.Send(ModelUrlMsg(self.network_id, thing))
self.Send(owner, PoseMsg(self.network_id, thing, True)) owner.Send(PoseMsg(self.network_id, thing, True))
self.Send(owner, BinaryMsg(self.network_id, thing)) owner.Send(BinaryMsg(self.network_id, thing))
if recursively: if recursively:
for child in thing.children: for child in thing.children:
@ -156,14 +159,14 @@ class ParticipantUDP(Participant):
self.Publish(PoseMsg(self.network_id, thing)) self.Publish(PoseMsg(self.network_id, thing))
self.Publish(BinaryMsg(self.network_id, thing)) self.Publish(BinaryMsg(self.network_id, thing))
def Send(self, owner: Participant, msg: IMessage): # def Send(self, owner: Participant, msg: IMessage):
buffer_size = msg.Serialize([self.buffer]) # buffer_size = msg.Serialize([self.buffer])
if buffer_size <= 0: # if buffer_size <= 0:
return True # return True
# print(f'{self.name} send {self.buffer[0]} to {owner.ip_address} {owner.port}') # # print(f'{self.name} send {self.buffer[0]} to {owner.ip_address} {owner.port}')
self.udp_socket.sendto(self.buffer[:buffer_size], (owner.ip_address, owner.port)) # self.udp_socket.sendto(self.buffer[:buffer_size], (owner.ip_address, owner.port))
return True # return True
def Publish(self, msg: IMessage): def Publish(self, msg: IMessage):
buffer_size = msg.Serialize([self.buffer]) buffer_size = msg.Serialize([self.buffer])
@ -188,7 +191,7 @@ class ParticipantUDP(Participant):
remote_participant = Participant.GetParticipant(remote_ip_address, remote_port) remote_participant = Participant.GetParticipant(remote_ip_address, remote_port)
if remote_participant is None: if remote_participant is None:
# print(f'new participant') # print(f'new participant')
remote_participant = Participant.AddParticipant(remote_ip_address, remote_port) remote_participant = Participant.AddParticipant(remote_ip_address, remote_port, self)
self.ReceiveData(data, remote_participant) self.ReceiveData(data, remote_participant)
except ConnectionError: except ConnectionError:
self.network_id = 0 self.network_id = 0