105 lines
3.7 KiB
Python
105 lines
3.7 KiB
Python
import socket
|
|
import Messages
|
|
import threading
|
|
|
|
from ClientMsg import ClientMsg
|
|
from NetworkIdMsg import NetworkIdMsg
|
|
from Thing import Thing
|
|
|
|
## A participant is device which can communicate with other participants
|
|
#
|
|
## Currently only UDP communication is supported
|
|
class Participant:
|
|
publishInterval = 3000 # 3 seconds
|
|
|
|
def __init__(self, ipAddress = "0.0.0.0", port=7681, remote=False):
|
|
self.buffer = bytearray(256)
|
|
self.ipAddress = ipAddress
|
|
self.port = port
|
|
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
self.buffer = bytearray(256)
|
|
|
|
if remote == False:
|
|
self.udp_socket.bind(("0.0.0.0", 7681))
|
|
self.network_id = 0
|
|
self.nextPublishMe = 0
|
|
self.others = []
|
|
|
|
self.thread = threading.Thread(target = self.Receiver)
|
|
self.thread.daemon = True
|
|
self.thread.start()
|
|
|
|
def GetParticipant(self, ip_address, port):
|
|
found_participants = (item for item in self.others
|
|
if item.ipAddress == ip_address and item.port == port)
|
|
participant = next(found_participants, None)
|
|
return participant
|
|
|
|
def AddParticipant(self, ip_address, port):
|
|
remote_participant = Participant(ip_address, port, remote=True)
|
|
self.others.append(remote_participant)
|
|
remote_participant.network_id = len(self.others)
|
|
return remote_participant
|
|
|
|
def Send(self, msg):
|
|
buffer_size = msg.Serialize([self.buffer])
|
|
if buffer_size <= 0:
|
|
return True
|
|
|
|
self.udp_socket.sendto(self.buffer[:buffer_size], (self.ipAddress, self.port))
|
|
return True
|
|
|
|
def Publish(self, msg):
|
|
buffer_size = msg.Serialize([self.buffer])
|
|
if buffer_size <= 0:
|
|
return True
|
|
|
|
self.udp_socket.sendto(self.buffer[:buffer_size], ('<broadcast>', self.port))
|
|
return True
|
|
|
|
def Update(self, currentTime):
|
|
if (currentTime > self.nextPublishMe):
|
|
self.Publish(ClientMsg(self.network_id))
|
|
print(f'Sent ClientMsg')
|
|
self.nextPublishMe = currentTime + Participant.publishInterval
|
|
|
|
Thing.UpdateAll(currentTime)
|
|
|
|
def ProcessClientMsg(self, msg: ClientMsg):
|
|
if msg.network_id == 0:
|
|
self.Send(NetworkIdMsg(self.network_id))
|
|
print(f'############################ New Client -> {self.network_id}')
|
|
else:
|
|
print(f'############################ New Client')
|
|
|
|
pass
|
|
def ProcessNetworkIdMsg(self, msg: NetworkIdMsg):
|
|
self.network_id = msg.network_id
|
|
print(f'receive network id {msg.network_id}')
|
|
pass
|
|
def ProcessInvestigateMsg(self, data: bytearray):
|
|
pass
|
|
|
|
def Receiver(self):
|
|
while True:
|
|
data, addr = self.udp_socket.recvfrom(1024)
|
|
remote_participant = self.GetParticipant(addr[0], addr[1])
|
|
if remote_participant is None:
|
|
remote_participant = self.AddParticipant(addr[0], addr[1])
|
|
remote_participant.ReceiveData(data)
|
|
|
|
def ReceiveData(self, data):
|
|
msgId = data[0]
|
|
match msgId:
|
|
case ClientMsg.id:
|
|
self.ProcessClientMsg(ClientMsg(data))
|
|
case NetworkIdMsg.id:
|
|
self.ProcessNetworkIdMsg(NetworkIdMsg(data))
|
|
case Messages.InvestigateMsg.id:
|
|
msg = Messages.InvestigateMsg(data)
|
|
self.ProcessInvestigateMsg(msg)
|
|
case Messages.BinaryMsg.id:
|
|
msg = Messages.BinaryMsg(data)
|
|
msg.thing.ProcessBinary(msg.data)
|