From 1b4f401e64411a689b821b9dcdb58b28d0918882 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 31 Dec 2024 16:16:42 +0100 Subject: [PATCH] Added thing and model msg support --- Messages.py | 54 ------------- ModelUrlMsg.py | 43 ++++++++++ NameMsg.py | 27 ++++--- Participant.py | 82 +++++++++++++------- ThingMsg.py | 36 +++++++++ test/__pycache__/thing_test.cpython-312.pyc | Bin 2842 -> 1823 bytes test/thing_test.py | 18 +---- 7 files changed, 151 insertions(+), 109 deletions(-) create mode 100644 ModelUrlMsg.py create mode 100644 ThingMsg.py 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 529efc281d148d9bc01a519f2ffe3cd91e28a09a..98a11fc52943161c27af47e7d5913401a2c899ca 100644 GIT binary patch delta 449 zcmZ9Hze~eF6vyw9OMj%b?I3LwtEtkVNE;AwD7K?xadPNV0*P&;t>JP7Eusz`6dWw4 z6kMF0`)4@0sH8f&2kj&XzSBYQ!Ta3zy?5`uyPNcFB5^-6qav_ll{G_Tn0Q>&AQ~YX z)v<-@l7$DTE?W|i9LfbU)-l7_8DC4M7zaE}Dj7>Yk{YrYB8)|UPc&?#`4vv_0MADL z=hme135~$Ter(I39@AON={EbzEyi50Y#6TTc{VMzon70o4;VE)!|bxsp4+4`=yKc) zLWK||psCpGldjpZ{b*<3vfGUwZPU0YB?VFdPXXw{Xd0BCU^cHQtJvjzB^!R8ubwFv zNj_4x!{Ya~g2G>-`3+ct=mOvlQIY@Yr6HjN!r-3RGeGY|Rf-=PfNI=PmvEe)tJ$3_ z6n)Y$oi5cu{tfwzY{FA}ZM#bIP{80`1rW#>;|WSmQ0xt5UeU^wXt;P8c}nFTQn@LD NAXw*L>Kqa8`3822WK{qF literal 2842 zcmbtW>uVfU6u);Ko7v6e(b~M4m~NUrTx@rnQmsWT)W)h{*NEwtMHq&iF`4b`?0RQX z*>wXIB5t8zr5}>2VCbio^bhb)5d5@lLc%nH_y8Bbgr=YR$#Z6A-)*6IL(YAjd+s^s z_q%8I*PfmTf%eJ2_S}?6$e%c=HJE#CcL};>q7jXnB<1%sMPbgFT$W356xVo@&+;jr z5{|q_G+~KoqE0eWV56y9T##a6H|*UrtJ_YxW)STP@Q-2a9)i_n;?(yvs&V)DH4c>sS)@)7EFrZ}7CEPu zSdu|IZLOxK2}RIbcS@0aV1U(7*B{(XKN+|hT2-4-F(3A8Y6`!M!uK@n!$v&wN};x z;~VyCj1-d$t5dQ2g28Mj>cPp7+)M@$6PpQWsac)%;9ft9Js=wNVM8!=dp(qWQXu}r zZTQ!B2Jo-}0^lEv~jAGq077Pkftmc{FlzuGwPKe1*ba9a!3__jQ(q51;W zC6cLEFjxp0)G}JDWKe+N!6vH+Gge*Ih6m%k`}u-u-lc3WtlDTH+MEkJm({(fJ91Iq ziQ+*#eU)rU@}@Lgk%m_WR_TUxu+wRzljrn1FnE^Jjbf-#2gCGQEsPqGgK%7NUN_BL zjCUh`K(lN?cO!;vSWqXdwC?h@!&nq-G>5m>gIcw6&b-bPKg6*%xLbB7(E#G^g^5r2 z$H?mGd*>evpV*M5IwP&aa}3TrD^mQ_T%LvxOZ`It5b?<>rl^Xwt%1`8)daYru+|*L zpch6#ca#=qi_x}FIy8=;p?x5lQQNcf@vVUk=|E>R=!=Kj^P`!A-xIf63CAZ{3=YSH zD#pm*qd~ldDkccRlYG=ZusUM%%W)QpwO66-j&j`C!W(RS);>5r*LrTK-;ZrbM>-?H zD7;881JA^z6%mR*SLDD^JDIaOf!OB(peMtHqlJ39B&~Ie& wv2cV&Z%CW{6P5mn#{?!jGn5E&xp5dZ)H 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