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)
 |