Added thing and model msg support

This commit is contained in:
Pascal Serrarens 2024-12-31 16:16:42 +01:00
parent 85f66fa50f
commit 1b4f401e64
7 changed files with 151 additions and 109 deletions

View File

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

43
ModelUrlMsg.py Normal file
View File

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

View File

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

View File

@ -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], ('<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)
#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

36
ThingMsg.py Normal file
View File

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

View File

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