From 1eb71a21c067154a031e3c602e16d38f34938a6f Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Sun, 22 Dec 2024 10:22:32 +0100 Subject: [PATCH] Added name and model support --- Messages.py | 209 +++++++++++++++++++++++++------------------------ Participant.py | 7 +- SiteServer.py | 13 ++- Thing.py | 28 +++++-- 4 files changed, 143 insertions(+), 114 deletions(-) diff --git a/Messages.py b/Messages.py index bc0e76e..6a88dfc 100644 --- a/Messages.py +++ b/Messages.py @@ -1,7 +1,6 @@ # from .Participant import Participant from . import LowLevelMessages -from .Spherical import Spherical -from .Quaternion import Quaternion +from .Thing import Thing class IMessage: id = 0x00 @@ -10,10 +9,10 @@ class IMessage: return 0 def SendTo(self, participant): - bufferSize = self.Serialize([participant.buffer]) - if bufferSize == 0: + buffer_size = self.Serialize([participant.buffer]) + if buffer_size == 0: return False - return participant.SendBuffer(bufferSize) + return participant.SendBuffer(buffer_size) def Publish(self, participant): bufferSize = self.Serialize([participant.buffer]) @@ -25,20 +24,20 @@ class ClientMsg(IMessage): id = 0xA0 length = 2 - def __init__(self, networkId): - if isinstance(networkId, int): - self.networkId = networkId - elif isinstance(networkId, bytes): - self.networkId = networkId[1] + def __init__(self, network_id): + if isinstance(network_id, int): + self.network_id = network_id + elif isinstance(network_id, bytes): + self.network_id = network_id[1] def Serialize(self, buffer_ref): - if self.networkId is None: + if self.network_id is None: return 0 buffer: bytearray = buffer_ref[0] - buffer[0:2] = [ + buffer[0:ClientMsg.length] = [ ClientMsg.id, - self.networkId + self.network_id ] return ClientMsg.length @@ -46,21 +45,21 @@ class NetworkIdMsg(IMessage): id = 0xA1 length = 2 - def __init__(self, networkId): - self.networkId = None - if isinstance(networkId, int): - self.networkId = networkId - elif isinstance(networkId, bytes): - self.networkId = networkId[1] + def __init__(self, network_id): + self.network_id = None + if isinstance(network_id, int): + self.network_id = network_id + elif isinstance(network_id, bytes): + self.network_id = network_id[1] def Serialize(self, buffer_ref): - if self.networkId is None: + if self.network_id is None: return 0 buffer: bytearray = buffer_ref[0] - buffer[0:2] = [ + buffer[0:NetworkIdMsg.length] = [ NetworkIdMsg.id, - self.networkId + self.network_id ] return NetworkIdMsg.length @@ -68,106 +67,112 @@ class ThingMsg(IMessage): id = 0x80 length = 5 - def __init__(self, networkId, thing): - self.networkId = networkId - self.thingId = thing.id - self.thingType = thing.type - self.parentId = None + def __init__(self, network_id, thing): + self.network_id = network_id + self.thing = thing def Serialize(self, buffer_ref): - if self.networkId is None or self.thingId is None: + if self.network_id is None or self.thing is None: return 0 buffer: bytearray = buffer_ref[0] - buffer[0:5] = [ + buffer[0:ThingMsg.length] = [ ThingMsg.id, - self.networkId, - self.thingId, - 0x00, - 0x00 + self.network_id, + self.thing.id, + self.thing.type, + self.thing.parent_id ] return ThingMsg.length +class NameMsg(IMessage): + id = 0x91 + length = 4 + + 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] + + encoded_name = self.thing.name.encode('utf-8') + name_length = len(encoded_name) + full_length = NameMsg.length + name_length + if name_length == 0 or full_length > len(buffer): + return 0 + + buffer[0:NameMsg.length] = [ + NameMsg.id, + self.network_id, + self.thing.id, + name_length + ] + # Append the name string + buffer[NameMsg.length:full_length] = encoded_name + return full_length class ModelUrlMsg(IMessage): id = 0x90 length = 6 - def __init__(self, networkId, thingId, url): - self.networkId = networkId - self.thingId = thingId - self.url = url + def __init__(self, network_id, thing): + self.network_id = network_id + self.thing = thing - def Serialize(self, buffer): - buffer[0:ModelUrlMsg.length] = [ - ModelUrlMsg.id, - self.networkId, - self.thingId, - 0x3D, # Dummy float16 value 1 - 0x00, - len(self.url) - ] - # Append the url string - fullLength = ModelUrlMsg.length + len(self.url) - buffer[ModelUrlMsg.length:fullLength] = \ - [ord(c) for c in self.url] - return fullLength - # ix = 0 - # buffer[ix] = ModelUrlMsg.id - # ix+=1 - # buffer[ix] = self.networkId - # ix+=1 - # buffer[ix] = self.thingId - # ix+=1 - # buffer[ix] = 0x3D # Dummy float16 value 1 - # ix+=1 - # buffer[ix] = 0x00 - # ix+=1 - # buffer[ix] = len(self.url) - # ix+=1 - # for c in self.url: - # buffer[ix] = ord(c) - # ix+=1 - # return ix - -class PoseMsg(IMessage): - id = 0x10 - length = 4 + 4 + 4 - - Position = 0x01 - Orientation = 0x02 - LinearVelocity = 0x04 - AngularVelocity = 0x08 - - def __init__(self, networkId, thing, poseType): - self.networkId = networkId - self.thingId = thing.id - - poseType = 0x0F # unity server currently requires position and orientation - self.poseType = poseType - self.position = Spherical.zero - self.orientation = Quaternion.identity - self.linearVelocity = thing.linearVelocity - self.angularVelocity = thing.angularVelocity - def Serialize(self, buffer_ref): - if (self.networkId is None) or (self.thingId is None): + if self.network_id is None or self.thing is None: return 0 buffer: bytearray = buffer_ref[0] - buffer[0:4] = [ + + 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 + + def __init__(self, network_id, thing, poseType): + 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:PoseMsg.length] = [ PoseMsg.id, - self.networkId, - self.thingId, - self.poseType + self.network_id, + self.thing.id, + self.thing.pose_updated ] ix = [4] - if self.poseType & PoseMsg.Position: - LowLevelMessages.SendSpherical(buffer, ix, self.position) - if self.poseType & PoseMsg.Orientation: - LowLevelMessages.SendQuat32(buffer, ix, self.orientation) - if self.poseType & PoseMsg.LinearVelocity: - LowLevelMessages.SendSpherical(buffer, ix, self.linearVelocity) - if self.poseType & PoseMsg.AngularVelocity: - LowLevelMessages.SendSpherical(buffer, ix, self.angularVelocity) + if self.thing.pose_updated & Thing.Position: + LowLevelMessages.SendSpherical(buffer, ix, self.thing.position) + if self.thing.pose_updated & Thing.Orientation: + LowLevelMessages.SendQuat32(buffer, ix, self.thing.orientation) + if self.thing.pose_updated & Thing.LinearVelocity: + LowLevelMessages.SendSpherical(buffer, ix, self.thing.linearVelocity) + if self.thing.pose_updated & Thing.AngularVelocity: + LowLevelMessages.SendSpherical(buffer, ix, self.thing.angularVelocity) return ix[0] diff --git a/Participant.py b/Participant.py index 9e11df4..64b8a09 100644 --- a/Participant.py +++ b/Participant.py @@ -11,9 +11,10 @@ class Participant: self.port = port self.udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udpSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - self.networkId = 0 - #self.udpSocket.bind(("0.0.0.0", 7681)) + # self.udpSocket.bind(("0.0.0.0", 7681)) self.buffer = bytearray(256) + + self.network_id = 0 self.nextPublishMe = 0 def SendBuffer(self, bufferSize): @@ -37,7 +38,7 @@ class Participant: return True def PublishMe(self): - msg = Messages.ClientMsg(self.networkId) + msg = Messages.ClientMsg(self.network_id) msg.Publish(self) def Update(self, currentTime): diff --git a/SiteServer.py b/SiteServer.py index 1211e9f..8c810f2 100644 --- a/SiteServer.py +++ b/SiteServer.py @@ -17,7 +17,12 @@ class SiteServer(Participant): return super().Update(currentTime) - def ProcessNetworkIdMsg(self, msg): - self.networkId = msg.networkId - msg = Messages.ThingMsg(self.networkId, next(iter(Thing.allThings))) - msg.SendTo(self) \ No newline at end of file + def ProcessNetworkIdMsg(self, thing_msg): + self.network_id = thing_msg.network_id + thing = next(iter(Thing.allThings)) + thing_msg = Messages.ThingMsg(self.network_id, thing) + thing_msg.SendTo(self) + name_msg = Messages.NameMsg(self.network_id, thing) + name_msg.SendTo(self) + model_msg = Messages.ModelUrlMsg(self.network_id, thing) + model_msg.SendTo(self) diff --git a/Thing.py b/Thing.py index 1346703..13b4b6b 100644 --- a/Thing.py +++ b/Thing.py @@ -1,12 +1,30 @@ +from .Spherical import Spherical +from .Quaternion import Quaternion + class Thing: allThings = set() - def __init__(self): - self.networkId = None - self.id = None - self.type = None + Position = 0x01 + Orientation = 0x02 + LinearVelocity = 0x04 + AngularVelocity = 0x08 + + def __init__(self): + self.networkId = 0 + self.id = 0 + self.type = 0 + self.parent_id = 0 + + self.name = None + self.model_url = None + + self.position = Spherical.zero + self.orientation = Quaternion.identity + self.linearVelocity = Spherical.zero + self.angularVelocity = Spherical.zero + + self.pose_updated = 0x00 # the bits indicate which fields have been updated - self.modelUrl = None Thing.Add(self) def update(self, currentTime):