diff --git a/Messages.py b/Messages.py index 5f7f934..4aff96f 100644 --- a/Messages.py +++ b/Messages.py @@ -30,60 +30,6 @@ class InvestigateMsg(): self.network_id = buffer[1] self.thing_id = buffer[2] -class ThingMsg(IMessage): - id = 0x80 - length = 5 - - def __init__(self, network_id, thing): - self.network_id = network_id - self.thing = thing - - def Serialize(self, buffer_ref): - if self.network_id is None or self.thing is None: - return 0 - - buffer: bytearray = buffer_ref[0] - buffer[0:ThingMsg.length] = [ - ThingMsg.id, - self.network_id, - self.thing.id, - self.thing.type, - self.thing.parent_id - ] - return ThingMsg.length - -class ModelUrlMsg(IMessage): - id = 0x90 - length = 6 - - def __init__(self, network_id, thing): - self.network_id = network_id - self.thing = thing - - def Serialize(self, buffer_ref): - if self.network_id is None or self.thing is None or self.thing.model_url is None: - return 0 - - buffer: bytearray = buffer_ref[0] - - encoded_url = self.thing.model_url.encode('utf-8') - url_length = len(encoded_url) - full_length = ModelUrlMsg.length + url_length - if url_length == 0 or full_length > len(buffer): - return 0 - - buffer[0:ModelUrlMsg.length] = [ - ModelUrlMsg.id, - self.network_id, - self.thing.id, - 0x3D, # Dummy float16 value 1 - 0x00, # this field will disappear - url_length - ] - # Append the url string - buffer[ModelUrlMsg.length:full_length] = encoded_url - return full_length - class PoseMsg(IMessage): id = 0x10 length = 4 diff --git a/ModelUrlMsg.py b/ModelUrlMsg.py new file mode 100644 index 0000000..863c1a2 --- /dev/null +++ b/ModelUrlMsg.py @@ -0,0 +1,43 @@ +from Messages import IMessage + +class ModelUrlMsg(IMessage): + id = 0x90 + length = 4 + + def __init__(self, data, thing = None): + if isinstance(data, bytes): + self.network_id = data[1] + self.thing_id = data[2] + # model url length is not needed here + self.url = data[ModelUrlMsg.length:].decode("utf-8") + else: + self.network_id = data + if thing is not None: + self.thing_id = thing.id + self.url = thing.model_url + else: + self.thing_id = None + self.url = None + + def Serialize(self, buffer_ref): + if self.network_id is None or self.thing_id is None or self.url is None: + return 0 + + buffer: bytearray = buffer_ref[0] + + encoded_url = self.url.encode('utf-8') + url_length = len(encoded_url) + full_length = ModelUrlMsg.length + url_length + if url_length == 0 or full_length > len(buffer): + return 0 + + buffer[0:ModelUrlMsg.length] = [ + ModelUrlMsg.id, + self.network_id, + self.thing_id, + url_length + ] + # Append the url string + buffer[ModelUrlMsg.length:full_length] = encoded_url + return full_length + diff --git a/NameMsg.py b/NameMsg.py index 3b08006..b799196 100644 --- a/NameMsg.py +++ b/NameMsg.py @@ -4,23 +4,28 @@ class NameMsg(IMessage): id = 0x91 length = 4 - def __init__(self, network_id, thing=None): - if isinstance(network_id, bytes): - self.network_id = network_id[1] - self.thing_id = network_id[2] - name_length = network_id[3] - self.name = network_id[NameMsg.length:].decode("utf-8") + def __init__(self, data, thing = None): + if isinstance(data, bytes): + self.network_id = data[1] + self.thing_id = data[2] + # name_length is not needed here + self.name = data[NameMsg.length:].decode("utf-8") else: - self.network_id = network_id - self.thing = thing + self.network_id = data + if thing is not None: + self.thing_id = thing.id + self.name = thing.name + else: + self.thing_id = None + self.name = None def Serialize(self, buffer_ref): - if self.network_id is None or self.thing is None or self.thing.name is None: + if self.network_id is None or self.thing_id is None or self.name is None: return 0 buffer: bytearray = buffer_ref[0] - encoded_name = self.thing.name.encode('utf-8') + encoded_name = self.name.encode('utf-8') name_length = len(encoded_name) full_length = NameMsg.length + name_length if name_length == 0 or full_length > len(buffer): @@ -29,7 +34,7 @@ class NameMsg(IMessage): buffer[0:NameMsg.length] = [ NameMsg.id, self.network_id, - self.thing.id, + self.thing_id, name_length ] # Append the name string diff --git a/Participant.py b/Participant.py index d4eb7c2..b0f4cf5 100644 --- a/Participant.py +++ b/Participant.py @@ -3,7 +3,9 @@ import threading from ClientMsg import ClientMsg from NetworkIdMsg import NetworkIdMsg +from ThingMsg import ThingMsg from NameMsg import NameMsg +from ModelUrlMsg import ModelUrlMsg from Thing import Thing ## A participant is device which can communicate with other participants @@ -43,6 +45,21 @@ class Participant: self.others.append(remote_participant) return remote_participant + def Update(self, currentTime): + if (currentTime > self.nextPublishMe): + self.Publish(ClientMsg(self.network_id)) + print(f'Sent ClientMsg {self.network_id}') + self.nextPublishMe = currentTime + Participant.publishInterval + + Thing.UpdateAll(currentTime) + +#region Send + + def SendThingInfo(self, thing): + self.Send(ThingMsg(self.network_id, thing)) + self.Send(NameMsg(self.network_id, thing)) + self.Send(ModelUrlMsg(self.network_id, thing)) + def Send(self, msg): buffer_size = msg.Serialize([self.buffer]) if buffer_size <= 0: @@ -59,33 +76,10 @@ class Participant: self.udp_socket.sendto(self.buffer[:buffer_size], ('', 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) +#endregion - 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') - - def ProcessNetworkIdMsg(self, msg: NetworkIdMsg): - self.network_id = msg.network_id - print(f'receive network id {msg.network_id}') - for thing in Thing.allThings: - self.Send(NameMsg(self.network_id, thing)) - - def ProcessInvestigateMsg(self, data: bytearray): - pass - - def ProcessNameMsg(self, msg: NameMsg): - print(f'received name {msg.name}') +#region Receive def Receiver(self): while True: @@ -106,11 +100,43 @@ class Participant: self.ProcessClientMsg(ClientMsg(data)) case NetworkIdMsg.id: self.ProcessNetworkIdMsg(NetworkIdMsg(data)) + # case InvestigateMsg.id: + # self.ProcessInvestigateMsg(InvestigateMsg(data)) + case ThingMsg.id: + self.ProcessThingMsg(ThingMsg(data)) case NameMsg.id: self.ProcessNameMsg(NameMsg(data)) - # case Messages.InvestigateMsg.id: - # msg = Messages.InvestigateMsg(data) - # self.ProcessInvestigateMsg(msg) + case ModelUrlMsg.id: + self.ProcessModelUrlMsg(ModelUrlMsg(data)) # case Messages.BinaryMsg.id: # msg = Messages.BinaryMsg(data) # msg.thing.ProcessBinary(msg.data) + + 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'############################ Client') + + def ProcessNetworkIdMsg(self, msg: NetworkIdMsg): + if self.network_id != msg.network_id: + self.network_id = msg.network_id + print(f'receive network id {msg.network_id}') + for thing in Thing.allThings: + self.SendThingInfo(thing) + # self.Send(NameMsg(self.network_id, thing)) + + def ProcessInvestigateMsg(self, data: bytearray): + pass + + def ProcessThingMsg(self, msg: ThingMsg): + print(f'received thing {msg.thing_id}') + + def ProcessNameMsg(self, msg: NameMsg): + print(f'received name {msg.name}') + + def ProcessModelUrlMsg(self, msg: ModelUrlMsg): + print(f'received model url: {msg.url}') + +#endregion \ No newline at end of file diff --git a/ThingMsg.py b/ThingMsg.py new file mode 100644 index 0000000..8c0ddcf --- /dev/null +++ b/ThingMsg.py @@ -0,0 +1,36 @@ +from Messages import IMessage + +class ThingMsg(IMessage): + id = 0x80 + length = 5 + + def __init__(self, data, thing=None): + if isinstance(data, bytes): + self.network_id = data[1] + self.thing_id = data[2] + self.thing_type = data[3] + self.parent_id = data[4] + else: + self.network_id = data + if thing is not None: + self.thing_id = thing.id + self.thing_type = thing.type + self.parent_id = thing.parent_id + else: + self.thing_id = None + self.thing_type = None + self.parent_id = None + + def Serialize(self, buffer_ref): + if self.network_id is None or self.thing_id is None: + return 0 + + buffer: bytearray = buffer_ref[0] + buffer[0:ThingMsg.length] = [ + ThingMsg.id, + self.network_id, + self.thing_id, + self.thing_type, + self.parent_id + ] + return ThingMsg.length \ No newline at end of file diff --git a/test/__pycache__/thing_test.cpython-312.pyc b/test/__pycache__/thing_test.cpython-312.pyc index 529efc2..98a11fc 100644 Binary files a/test/__pycache__/thing_test.cpython-312.pyc and b/test/__pycache__/thing_test.cpython-312.pyc differ diff --git a/test/thing_test.py b/test/thing_test.py index 77feae2..ba5efc3 100644 --- a/test/thing_test.py +++ b/test/thing_test.py @@ -22,27 +22,13 @@ class ThingTest(unittest.TestCase): participant = Participant("127.0.0.1") thing = Thing() thing.name = "First thing" + thing.model_url = "https://passer.life/extras/ant.jpg" milliseconds = time.time() * 1000 start_time = milliseconds - while milliseconds < start_time + 5000: + while milliseconds < start_time + 6000: milliseconds = time.time() * 1000 participant.Update(milliseconds) - def test_something(self): - self.assertEqual(1 + 1, 2) - - def test_another_thing(self): - self.assertTrue(isinstance("hello", str)) - - def test_yet_another_thing(self): - self.assertFalse(3 > 5) - - def test_more_tests(self): - self.assertIn(3, [1, 2, 3, 4]) - - def test_even_more_tests(self): - self.assertIsNone(None) - if __name__ == '__main__': unittest.main() \ No newline at end of file