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.network_id = buffer[1]
self.thing_id = buffer[2] 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): class PoseMsg(IMessage):
id = 0x10 id = 0x10
length = 4 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 id = 0x91
length = 4 length = 4
def __init__(self, network_id, thing=None): def __init__(self, data, thing = None):
if isinstance(network_id, bytes): if isinstance(data, bytes):
self.network_id = network_id[1] self.network_id = data[1]
self.thing_id = network_id[2] self.thing_id = data[2]
name_length = network_id[3] # name_length is not needed here
self.name = network_id[NameMsg.length:].decode("utf-8") self.name = data[NameMsg.length:].decode("utf-8")
else: else:
self.network_id = network_id self.network_id = data
self.thing = thing 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): 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 return 0
buffer: bytearray = buffer_ref[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) name_length = len(encoded_name)
full_length = NameMsg.length + name_length full_length = NameMsg.length + name_length
if name_length == 0 or full_length > len(buffer): if name_length == 0 or full_length > len(buffer):
@ -29,7 +34,7 @@ class NameMsg(IMessage):
buffer[0:NameMsg.length] = [ buffer[0:NameMsg.length] = [
NameMsg.id, NameMsg.id,
self.network_id, self.network_id,
self.thing.id, self.thing_id,
name_length name_length
] ]
# Append the name string # Append the name string

View File

@ -3,7 +3,9 @@ import threading
from ClientMsg import ClientMsg from ClientMsg import ClientMsg
from NetworkIdMsg import NetworkIdMsg from NetworkIdMsg import NetworkIdMsg
from ThingMsg import ThingMsg
from NameMsg import NameMsg from NameMsg import NameMsg
from ModelUrlMsg import ModelUrlMsg
from Thing import Thing from Thing import Thing
## A participant is device which can communicate with other participants ## A participant is device which can communicate with other participants
@ -43,6 +45,21 @@ class Participant:
self.others.append(remote_participant) self.others.append(remote_participant)
return 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): def Send(self, msg):
buffer_size = msg.Serialize([self.buffer]) buffer_size = msg.Serialize([self.buffer])
if buffer_size <= 0: if buffer_size <= 0:
@ -59,33 +76,10 @@ class Participant:
self.udp_socket.sendto(self.buffer[:buffer_size], ('<broadcast>', self.port)) self.udp_socket.sendto(self.buffer[:buffer_size], ('<broadcast>', self.port))
return True 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): #region Receive
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}')
def Receiver(self): def Receiver(self):
while True: while True:
@ -106,11 +100,43 @@ class Participant:
self.ProcessClientMsg(ClientMsg(data)) self.ProcessClientMsg(ClientMsg(data))
case NetworkIdMsg.id: case NetworkIdMsg.id:
self.ProcessNetworkIdMsg(NetworkIdMsg(data)) self.ProcessNetworkIdMsg(NetworkIdMsg(data))
# case InvestigateMsg.id:
# self.ProcessInvestigateMsg(InvestigateMsg(data))
case ThingMsg.id:
self.ProcessThingMsg(ThingMsg(data))
case NameMsg.id: case NameMsg.id:
self.ProcessNameMsg(NameMsg(data)) self.ProcessNameMsg(NameMsg(data))
# case Messages.InvestigateMsg.id: case ModelUrlMsg.id:
# msg = Messages.InvestigateMsg(data) self.ProcessModelUrlMsg(ModelUrlMsg(data))
# self.ProcessInvestigateMsg(msg)
# case Messages.BinaryMsg.id: # case Messages.BinaryMsg.id:
# msg = Messages.BinaryMsg(data) # msg = Messages.BinaryMsg(data)
# msg.thing.ProcessBinary(msg.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") participant = Participant("127.0.0.1")
thing = Thing() thing = Thing()
thing.name = "First thing" thing.name = "First thing"
thing.model_url = "https://passer.life/extras/ant.jpg"
milliseconds = time.time() * 1000 milliseconds = time.time() * 1000
start_time = milliseconds start_time = milliseconds
while milliseconds < start_time + 5000: while milliseconds < start_time + 6000:
milliseconds = time.time() * 1000 milliseconds = time.time() * 1000
participant.Update(milliseconds) 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__': if __name__ == '__main__':
unittest.main() unittest.main()