Added explicit typing
This commit is contained in:
parent
f8c6037538
commit
97eafeccfc
@ -1,30 +1,31 @@
|
|||||||
#from Thing import Thing
|
from Thing import Thing
|
||||||
|
from Messages import IMessage
|
||||||
|
|
||||||
class BinaryMsg():
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
class BinaryMsg(IMessage):
|
||||||
id = 0xB1
|
id = 0xB1
|
||||||
length = 4
|
length = 4
|
||||||
|
|
||||||
def __init__(self, data, thing = None):
|
def __init__(self, arg1: Union[bytes, int], thing: Optional[Thing] = None):
|
||||||
if isinstance(data, bytes):
|
if thing is None:
|
||||||
|
data = bytes(arg1)
|
||||||
self.thing_id = data[2]
|
self.thing_id = data[2]
|
||||||
self.data_length = data[3]
|
self.data_length = data[3]
|
||||||
self.data = data[4:]
|
self.data = data[4:]
|
||||||
else:
|
else:
|
||||||
self.network_id = data
|
self.network_id = int(arg1)
|
||||||
self.thing_id = thing.id
|
self.thing_id = thing.id
|
||||||
self.thing = thing
|
self.thing = thing
|
||||||
|
|
||||||
def Serialize(self, buffer_ref):
|
def Serialize(self, buffer_ref: list[bytearray]):
|
||||||
if self.thing_id is None:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
buffer: bytearray = buffer_ref[0]
|
buffer: bytearray = buffer_ref[0]
|
||||||
ix = self.length
|
ix = self.length
|
||||||
self.data_length = self.thing.GenerateBinary(buffer, {ix})
|
self.data_length = self.thing.GenerateBinary(buffer, {ix})
|
||||||
if ix <= self.length:
|
if ix <= self.length:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
print(f'Send BinaryMsg [{self.network_id}/{self.thing_id}] {self.thing_type} {self.parent_id}')
|
print(f'Send BinaryMsg [{self.network_id}/{self.thing_id}] {self.data_length}')
|
||||||
|
|
||||||
buffer[0] = self.id
|
buffer[0] = self.id
|
||||||
buffer[1] = self.network_id
|
buffer[1] = self.network_id
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#import Messages.LowLevelMessages as LowLevelMessages
|
#import Messages.LowLevelMessages as LowLevelMessages
|
||||||
|
# from ParticipantUDP import ParticipantUDP
|
||||||
|
|
||||||
class IMessage:
|
class IMessage:
|
||||||
id = 0x00
|
id = 0x00
|
||||||
@ -6,84 +7,17 @@ class IMessage:
|
|||||||
## Serialize the message into the given buffer
|
## Serialize the message into the given buffer
|
||||||
#
|
#
|
||||||
## @returns: the length of the message
|
## @returns: the length of the message
|
||||||
def Serialize(buffer):
|
def Serialize(self, buffer_ref: list[bytearray]) -> int:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def SendTo(self, participant):
|
# def SendTo(self, participant: ParticipantUDP) -> bool:
|
||||||
buffer_size = self.Serialize([participant.buffer])
|
# buffer_size = self.Serialize([participant.buffer])
|
||||||
if buffer_size == 0:
|
# if buffer_size == 0:
|
||||||
return False
|
# return False
|
||||||
return participant.SendBuffer(buffer_size)
|
# return participant.SendBuffer(buffer_size)
|
||||||
|
|
||||||
def Publish(self, participant):
|
# def Publish(self, participant: Participant) -> bool:
|
||||||
bufferSize = self.Serialize([participant.buffer])
|
# bufferSize = self.Serialize([participant.buffer])
|
||||||
if bufferSize == 0:
|
# if bufferSize == 0:
|
||||||
return False
|
# return False
|
||||||
return participant.PublishBuffer(bufferSize)
|
# return participant.PublishBuffer(bufferSize)
|
||||||
|
|
||||||
# class InvestigateMsg():
|
|
||||||
# id = 0x81
|
|
||||||
# length = 3
|
|
||||||
|
|
||||||
# def __init__(self, buffer):
|
|
||||||
# self.thing_id = buffer[2]
|
|
||||||
|
|
||||||
# class PoseMsg(IMessage):
|
|
||||||
# """! Message to communicate the pose of the thing
|
|
||||||
|
|
||||||
# The pose is in local space relative to the parent.
|
|
||||||
# If there is not parent (the thing is a root thing), the pose will be in world space.
|
|
||||||
# """
|
|
||||||
# ## The message ID
|
|
||||||
# id = 0x10
|
|
||||||
# ## The length of the message
|
|
||||||
# length = 4
|
|
||||||
|
|
||||||
# def __init__(self, thing):
|
|
||||||
# self.thing = thing
|
|
||||||
|
|
||||||
# def Serialize(self, buffer_ref):
|
|
||||||
# if self.thing is None:
|
|
||||||
# return 0
|
|
||||||
|
|
||||||
# buffer: bytearray = buffer_ref[0]
|
|
||||||
# buffer[0:PoseMsg.length] = [
|
|
||||||
# PoseMsg.id,
|
|
||||||
# 0, # Network id
|
|
||||||
# self.thing.id,
|
|
||||||
# self.thing.pose_updated
|
|
||||||
# ]
|
|
||||||
# ix = [4]
|
|
||||||
# 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]
|
|
||||||
|
|
||||||
# class BinaryMsg():
|
|
||||||
# id = 0xB1
|
|
||||||
|
|
||||||
# def __init__(self, buffer):
|
|
||||||
# self.thing_id = buffer[2]
|
|
||||||
# self.thing = Thing.Get(self.thing_id)
|
|
||||||
# self.data = buffer[3:]
|
|
||||||
|
|
||||||
# def SendTo(participant, thing, data: bytearray):
|
|
||||||
# length = 3
|
|
||||||
|
|
||||||
# if thing is None or data is None:
|
|
||||||
# return False
|
|
||||||
|
|
||||||
# participant.buffer[0:length] = [
|
|
||||||
# BinaryMsg.id,
|
|
||||||
# 0, # network_id,
|
|
||||||
# thing.id
|
|
||||||
# ]
|
|
||||||
# full_length = length + len(data)
|
|
||||||
# participant.buffer[length:full_length] = data
|
|
||||||
# participant.SendBuffer(full_length)
|
|
||||||
# return True
|
|
@ -1,25 +1,25 @@
|
|||||||
from RoboidControl.Messages.Messages import IMessage
|
from RoboidControl.Messages.Messages import IMessage
|
||||||
|
from Thing import Thing
|
||||||
|
|
||||||
|
from typing import Union, Optional
|
||||||
|
|
||||||
class ModelUrlMsg(IMessage):
|
class ModelUrlMsg(IMessage):
|
||||||
id = 0x90
|
id = 0x90
|
||||||
length = 4
|
length = 4
|
||||||
|
|
||||||
thing_id = None
|
def __init__(self, arg1: Union[bytes, int], thing: Optional[Thing] = None):
|
||||||
url = None
|
if thing is None:
|
||||||
|
data = bytes(arg1)
|
||||||
def __init__(self, data, thing = None):
|
|
||||||
if isinstance(data, bytes):
|
|
||||||
self.thing_id = data[2]
|
self.thing_id = data[2]
|
||||||
# model url length is not needed here
|
# model url length is not needed here
|
||||||
self.url = data[ModelUrlMsg.length:].decode("utf-8")
|
self.url = data[ModelUrlMsg.length:].decode("utf-8")
|
||||||
else:
|
else:
|
||||||
if thing is not None:
|
self.network_id: int = int(arg1)
|
||||||
self.network_id = data
|
self.thing_id: int = thing.id
|
||||||
self.thing_id = thing.id
|
self.url: Optional[str] = thing.model_url
|
||||||
self.url = thing.model_url
|
|
||||||
|
|
||||||
def Serialize(self, buffer_ref):
|
def Serialize(self, buffer_ref: list[bytearray]):
|
||||||
if self.thing_id is None or self.url is None:
|
if self.url is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
buffer: bytearray = buffer_ref[0]
|
buffer: bytearray = buffer_ref[0]
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
from RoboidControl.Messages.Messages import IMessage
|
from RoboidControl.Messages.Messages import IMessage
|
||||||
|
from Thing import Thing
|
||||||
|
|
||||||
|
from typing import Union, Optional
|
||||||
|
|
||||||
class NameMsg(IMessage):
|
class NameMsg(IMessage):
|
||||||
id = 0x91
|
id = 0x91
|
||||||
length = 4
|
length = 4
|
||||||
|
|
||||||
thing_id = None
|
def __init__(self, arg1: Union[bytes, int], thing: Optional[Thing] = None):
|
||||||
name = None
|
if thing is None:
|
||||||
|
data = bytes(arg1)
|
||||||
def __init__(self, data, thing = None):
|
|
||||||
if isinstance(data, bytes):
|
|
||||||
self.thing_id = data[2]
|
self.thing_id = data[2]
|
||||||
# name_length is not needed here
|
# name_length is not needed here
|
||||||
self.name = data[NameMsg.length:].decode("utf-8")
|
self.name = data[NameMsg.length:].decode("utf-8")
|
||||||
else:
|
else:
|
||||||
if thing is not None:
|
self.network_id: int = int(arg1)
|
||||||
self.network_id = data
|
self.thing_id: int = thing.id
|
||||||
self.thing_id = thing.id
|
self.name: Optional[str] = thing.name
|
||||||
self.name = thing.name
|
|
||||||
|
|
||||||
def Serialize(self, buffer_ref):
|
def Serialize(self, buffer_ref: list[bytearray]):
|
||||||
if self.thing_id is None or self.name is None:
|
if self.name is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
buffer: bytearray = buffer_ref[0]
|
buffer: bytearray = buffer_ref[0]
|
||||||
|
@ -1,27 +1,31 @@
|
|||||||
from RoboidControl.Messages.Messages import IMessage
|
from RoboidControl.Messages.Messages import IMessage
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
## A network id message invites another participant to a site
|
## A network id message invites another participant to a site
|
||||||
#
|
#
|
||||||
## This can be sent in response to a ClientMsg
|
## This can be sent in response to a ClientMsg
|
||||||
class NetworkIdMsg(IMessage):
|
class NetworkIdMsg(IMessage):
|
||||||
id = 0xA1
|
id: int = 0xA1
|
||||||
length = 2
|
length: int = 2
|
||||||
|
|
||||||
## Create a network id message
|
## Create a network id message
|
||||||
def __init__(self, arg1 = None):
|
def __init__(self, arg1: Union[bytes, int]):
|
||||||
|
self.network_id: int = 0
|
||||||
if isinstance(arg1, bytes):
|
if isinstance(arg1, bytes):
|
||||||
buffer = arg1
|
buffer = bytearray(arg1)
|
||||||
self.network_id = buffer[1]
|
self.network_id = buffer[1]
|
||||||
else:
|
else:
|
||||||
self.network_id = arg1
|
self.network_id = int(arg1)
|
||||||
|
|
||||||
## Serialize the message into the given buffer
|
## Serialize the message into the given buffer
|
||||||
#
|
#
|
||||||
## @param buffer_ref A reference to the buffer to use. This should be a list with the buffer as its first and only element
|
## @param buffer_ref A reference to the buffer to use. This should be a list with the buffer as its first and only element
|
||||||
## @returns the length of the message
|
## @returns the length of the message
|
||||||
def Serialize(self, buffer_ref):
|
def Serialize(self, buffer_ref: list[bytearray]) -> int:
|
||||||
buffer: bytearray = buffer_ref[0]
|
buffer: bytearray = buffer_ref[0]
|
||||||
buffer[0:NetworkIdMsg.length] = [
|
last:int = NetworkIdMsg.length
|
||||||
|
buffer[0:last] = [
|
||||||
NetworkIdMsg.id,
|
NetworkIdMsg.id,
|
||||||
self.network_id
|
self.network_id
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import RoboidControl.Messages.LowLevelMessages as LowLevelMessages
|
import RoboidControl.Messages.LowLevelMessages as LowLevelMessages
|
||||||
#from Thing import Thing
|
#from Thing import Thing
|
||||||
|
|
||||||
class PoseMsg():
|
class PoseMsg(IMessage):
|
||||||
id = 0x10
|
id = 0x10
|
||||||
length = 4
|
length = 4
|
||||||
|
|
||||||
|
@ -1,33 +1,29 @@
|
|||||||
from RoboidControl.Messages.Messages import IMessage
|
from RoboidControl.Messages.Messages import IMessage
|
||||||
|
from Thing import Thing
|
||||||
|
|
||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
class ThingMsg(IMessage):
|
class ThingMsg(IMessage):
|
||||||
id = 0x80
|
id = 0x80
|
||||||
length = 5
|
length = 5
|
||||||
|
|
||||||
thing_id = None
|
def __init__(self, arg1: Union[bytes, int], thing: Optional[Thing]=None):
|
||||||
thing_type = None
|
if thing is None:
|
||||||
parent_id = None
|
buffer = bytes(arg1)
|
||||||
|
self.network_id: int = buffer[1]
|
||||||
def __init__(self, arg1, thing=None):
|
self.thing_id: int = buffer[2]
|
||||||
if isinstance(arg1, bytes):
|
self.thing_type: int = buffer[3]
|
||||||
buffer = arg1
|
self.parent_id: int = buffer[4]
|
||||||
self.network_id = buffer[1]
|
|
||||||
self.thing_id = buffer[2]
|
|
||||||
self.thing_type = buffer[3]
|
|
||||||
self.parent_id = buffer[4]
|
|
||||||
else:
|
else:
|
||||||
if thing is not None:
|
self.network_id = int(arg1)
|
||||||
self.network_id = arg1
|
self.thing_id = thing.id
|
||||||
self.thing_id = thing.id
|
self.thing_type = thing.type
|
||||||
self.thing_type = thing.type
|
if thing.parent is not None:
|
||||||
if thing.parent is not None:
|
self.parent_id = thing.parent.id
|
||||||
self.parent_id = thing.parent.id
|
else:
|
||||||
else:
|
self.parent_id = 0
|
||||||
self.parent_id = 0
|
|
||||||
|
|
||||||
def Serialize(self, buffer_ref):
|
def Serialize(self, buffer_ref: list[bytearray]):
|
||||||
if self.thing_id is None:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
print(f'Send ThingMsg [{self.network_id}/{self.thing_id}] {self.thing_type} {self.parent_id}')
|
print(f'Send ThingMsg [{self.network_id}/{self.thing_id}] {self.thing_type} {self.parent_id}')
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
from Thing import Thing
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
class Participant:
|
class Participant:
|
||||||
"""! A participant is a device which manages things.
|
"""! A participant is a device which manages things.
|
||||||
|
|
||||||
@ -6,35 +10,35 @@ class Participant:
|
|||||||
It also maintains the communcation information to contact the participant.
|
It also maintains the communcation information to contact the participant.
|
||||||
It is used as a basis for the local participant, but also as a reference to remote participants.
|
It is used as a basis for the local participant, but also as a reference to remote participants.
|
||||||
"""
|
"""
|
||||||
def __init__(self, ip_address, port):
|
def __init__(self, ip_address: str, port: int) -> None:
|
||||||
"""! Create a new participant with the given communcation info
|
"""! Create a new participant with the given communcation info
|
||||||
@param ip_address The IP address of the participant
|
@param ip_address The IP address of the participant
|
||||||
@param port The UDP port of the participant
|
@param port The UDP port of the participant
|
||||||
"""
|
"""
|
||||||
|
|
||||||
## The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
|
## The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
|
||||||
self.ip_address = ip_address
|
self.ip_address: str = ip_address
|
||||||
## The port number for UDP communication with the participant. This is 0 for isolated participants.
|
## The port number for UDP communication with the participant. This is 0 for isolated participants.
|
||||||
self.port = port
|
self.port: int = port
|
||||||
|
|
||||||
## he network Id to identify the participant.
|
## he network Id to identify the participant.
|
||||||
self.network_id =0
|
self.network_id: int = 0
|
||||||
|
|
||||||
## The things managed by this participant
|
## The things managed by this participant
|
||||||
self.things = set()
|
self.things: set[Thing] = set()
|
||||||
|
|
||||||
def Get(self, thing_id):
|
def Get(self, thing_id: int) -> Optional[Thing]:
|
||||||
"""! Get the thing with the given properties
|
"""! Get the thing with the given properties
|
||||||
|
|
||||||
@param thing_id The ID of the thing
|
@param thing_id The ID of the thing
|
||||||
@return The thing if found, None in other cases
|
@return The thing if found, None in other cases
|
||||||
"""
|
"""
|
||||||
for thing in self.things:
|
for thing in self.things:
|
||||||
if thing is not None and thing.id == thing_id:
|
if thing.id == thing_id:
|
||||||
return thing
|
return thing
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def Add(self, thing, check_id = True):
|
def Add(self, thing: Thing, check_id: bool = True):
|
||||||
"""! Add a new thing for this participant.
|
"""! Add a new thing for this participant.
|
||||||
@param thing The thing to add
|
@param thing The thing to add
|
||||||
@param check_id If true, the thing.id is regenerated if it is zero
|
@param check_id If true, the thing.id is regenerated if it is zero
|
||||||
@ -47,16 +51,15 @@ class Participant:
|
|||||||
if found_thing == None:
|
if found_thing == None:
|
||||||
self.things.add(thing)
|
self.things.add(thing)
|
||||||
|
|
||||||
def Remove(self, thing):
|
def Remove(self, thing: Thing) -> None:
|
||||||
"""! Remove a thing for this participant
|
"""! Remove a thing for this participant
|
||||||
@param thing The thing to remove
|
@param thing The thing to remove
|
||||||
"""
|
"""
|
||||||
self.things.remove(thing)
|
self.things.remove(thing)
|
||||||
|
|
||||||
def Update(self, currentTimeMs=0):
|
def Update(self, currentTimeMs: int = 0) -> None:
|
||||||
"""! Update all things for this participant
|
"""! Update all things for this participant
|
||||||
@param The current time in milliseconds (optional)
|
@param The current time in milliseconds (optional)
|
||||||
"""
|
"""
|
||||||
for thing in list(self.things):
|
for thing in list(self.things):
|
||||||
if thing is not None:
|
thing.Update(currentTimeMs)
|
||||||
thing.Update(currentTimeMs)
|
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import socket
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
|
|
||||||
from RoboidControl.Participant import Participant
|
from RoboidControl.Participant import Participant
|
||||||
from RoboidControl.Thing import Thing
|
from RoboidControl.Thing import Thing
|
||||||
from RoboidControl.Messages.ParticipantMsg import ParticipantMsg
|
from RoboidControl.Messages.ParticipantMsg import ParticipantMsg
|
||||||
@ -9,13 +5,19 @@ from RoboidControl.Messages.NetworkIdMsg import NetworkIdMsg
|
|||||||
from RoboidControl.Messages.ThingMsg import ThingMsg
|
from RoboidControl.Messages.ThingMsg import ThingMsg
|
||||||
from RoboidControl.Messages.NameMsg import NameMsg
|
from RoboidControl.Messages.NameMsg import NameMsg
|
||||||
from RoboidControl.Messages.ModelUrlMsg import ModelUrlMsg
|
from RoboidControl.Messages.ModelUrlMsg import ModelUrlMsg
|
||||||
|
from RoboidControl.Messages.Messages import IMessage
|
||||||
from RoboidControl.Messages import *
|
from RoboidControl.Messages import *
|
||||||
|
|
||||||
import sys
|
import socket
|
||||||
micropython = 'micropython' in sys.modules
|
import threading
|
||||||
|
import time
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
if micropython:
|
# import sys
|
||||||
from MicroPython.uPythonParticipant import Bla
|
# micropython = 'micropython' in sys.modules
|
||||||
|
|
||||||
|
# if micropython:
|
||||||
|
# from MicroPython.uPythonParticipant import uPythonParticipant
|
||||||
|
|
||||||
class ParticipantUDP(Participant):
|
class ParticipantUDP(Participant):
|
||||||
"""! A local participant is the local device which can communicate with other participants.
|
"""! A local participant is the local device which can communicate with other participants.
|
||||||
@ -26,14 +28,18 @@ class ParticipantUDP(Participant):
|
|||||||
Currently, only UDP communication is supported
|
Currently, only UDP communication is supported
|
||||||
"""
|
"""
|
||||||
|
|
||||||
buffer = None
|
#buffer = None
|
||||||
nextPublishMe = 0
|
nextPublishMe = 0
|
||||||
others = None
|
#others = None
|
||||||
thread = None
|
#thread = None
|
||||||
name = "Participant"
|
name = "Participant"
|
||||||
isolated_participant = None
|
isolated_participant = None
|
||||||
|
|
||||||
def __init__(self, port=7681, ip_address=None, local_port=7681):
|
def __init__(self,
|
||||||
|
port: int = 7681,
|
||||||
|
ip_address: Optional[str] = None,
|
||||||
|
local_port: int = 7681
|
||||||
|
) -> None:
|
||||||
super().__init__(ip_address = "127.0.0.1", port = local_port)
|
super().__init__(ip_address = "127.0.0.1", port = local_port)
|
||||||
|
|
||||||
# if local_port == 0:
|
# if local_port == 0:
|
||||||
@ -42,11 +48,11 @@ class ParticipantUDP(Participant):
|
|||||||
|
|
||||||
## True if the participant is running isolated.
|
## True if the participant is running isolated.
|
||||||
# Isolated participants do not communicate with other participants
|
# Isolated participants do not communicate with other participants
|
||||||
self.is_isolated = True
|
self.is_isolated: bool = True
|
||||||
self.remote_site = None
|
self.remote_site: Optional[Participant] = None
|
||||||
|
|
||||||
## The other participants communicating with this participant
|
## The other participants communicating with this participant
|
||||||
self.others = []
|
self.others: list[Participant] = []
|
||||||
|
|
||||||
if port != 0:
|
if port != 0:
|
||||||
self.is_isolated = False
|
self.is_isolated = False
|
||||||
@ -54,7 +60,7 @@ class ParticipantUDP(Participant):
|
|||||||
self.remote_site = Participant(ip_address, port)
|
self.remote_site = Participant(ip_address, port)
|
||||||
self.others.append(self.remote_site)
|
self.others.append(self.remote_site)
|
||||||
|
|
||||||
self.buffer = bytearray(256)
|
self.buffer: bytearray = bytearray(256)
|
||||||
self.publishInterval = 3000 # 3 seconds
|
self.publishInterval = 3000 # 3 seconds
|
||||||
|
|
||||||
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
@ -65,14 +71,15 @@ class ParticipantUDP(Participant):
|
|||||||
self.thread.daemon = True
|
self.thread.daemon = True
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
def Isolated():
|
@staticmethod
|
||||||
|
def Isolated() -> 'ParticipantUDP':
|
||||||
if ParticipantUDP.isolated_participant == None:
|
if ParticipantUDP.isolated_participant == None:
|
||||||
ParticipantUDP.isolated_participant = ParticipantUDP(0)
|
ParticipantUDP.isolated_participant = ParticipantUDP(0)
|
||||||
return ParticipantUDP.isolated_participant
|
return ParticipantUDP.isolated_participant
|
||||||
|
|
||||||
#region Update
|
#region Update
|
||||||
|
|
||||||
def GetParticipant(self, ip_address, port):
|
def GetParticipant(self, ip_address: str, port: int):
|
||||||
# print(f'{self.name} Get participant {ip_address} {port}')
|
# print(f'{self.name} Get participant {ip_address} {port}')
|
||||||
# for item in self.others:
|
# for item in self.others:
|
||||||
# print(f'- {item.ip_address} {item.port}')
|
# print(f'- {item.ip_address} {item.port}')
|
||||||
@ -82,15 +89,15 @@ class ParticipantUDP(Participant):
|
|||||||
participant = next(found_participants, None)
|
participant = next(found_participants, None)
|
||||||
return participant
|
return participant
|
||||||
|
|
||||||
def AddParticipant(self, ip_address, port):
|
def AddParticipant(self, ip_address: str, port: int):
|
||||||
print(f'{self.name} Add participant {ip_address} {port}')
|
print(f'{self.name} Add participant {ip_address} {port}')
|
||||||
remote_participant = Participant(ip_address = ip_address, port = port)
|
remote_participant = Participant(ip_address = ip_address, port = port)
|
||||||
self.others.append(remote_participant)
|
self.others.append(remote_participant)
|
||||||
return remote_participant
|
return remote_participant
|
||||||
|
|
||||||
def Update(self, currentTimeMs = None):
|
def Update(self, currentTimeMs: Optional[int] = None):
|
||||||
if currentTimeMs is None:
|
if currentTimeMs is None:
|
||||||
currentTimeMs = time.time() * 1000
|
currentTimeMs = int(time.time() * 1000)
|
||||||
|
|
||||||
if self.is_isolated == False:
|
if self.is_isolated == False:
|
||||||
if self.publishInterval > 0 and currentTimeMs > self.nextPublishMe:
|
if self.publishInterval > 0 and currentTimeMs > self.nextPublishMe:
|
||||||
@ -104,16 +111,15 @@ class ParticipantUDP(Participant):
|
|||||||
|
|
||||||
self.UpdateMyThings(currentTimeMs)
|
self.UpdateMyThings(currentTimeMs)
|
||||||
|
|
||||||
def UpdateMyThings(self, currentTimeMs):
|
def UpdateMyThings(self, currentTimeMs: int):
|
||||||
for thing in self.things:
|
for thing in self.things:
|
||||||
if thing is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# if thing.hierarchyChanged and not (self.isIsolated or self.network_id == ):
|
# if thing.hierarchyChanged and not (self.isIsolated or self.network_id == ):
|
||||||
# thingMsg = ThingMsg(self.network_id, thing)
|
# thingMsg = ThingMsg(self.network_id, thing)
|
||||||
# self.Send(self.remote_site, thingMsg)
|
# self.Send(self.remote_site, thingMsg)
|
||||||
poseMsg = PoseMsg(thing.owner.network_id, thing)
|
if thing.owner is not None:
|
||||||
self.Send(self.remote_site, poseMsg)
|
poseMsg = PoseMsg(thing.owner.network_id, thing)
|
||||||
|
if self.remote_site is not None:
|
||||||
|
self.Send(self.remote_site, poseMsg)
|
||||||
|
|
||||||
thing.Update(currentTimeMs, False)
|
thing.Update(currentTimeMs, False)
|
||||||
if not(self.is_isolated or self.network_id == 0):
|
if not(self.is_isolated or self.network_id == 0):
|
||||||
@ -121,11 +127,12 @@ class ParticipantUDP(Participant):
|
|||||||
# destroyMsg = DestroyMsg(self.network_id, thing)
|
# destroyMsg = DestroyMsg(self.network_id, thing)
|
||||||
# self.Send(self.remote_site, destroyMsg)
|
# self.Send(self.remote_site, destroyMsg)
|
||||||
# else:
|
# else:
|
||||||
# Send to remote site
|
if self.remote_site is not None and thing.owner is not None:
|
||||||
poseMsg = PoseMsg(thing.owner.network_id, thing)
|
# Send to remote site
|
||||||
self.Send(self.remote_site, poseMsg)
|
poseMsg = PoseMsg(thing.owner.network_id, thing)
|
||||||
binaryMsg = BinaryMsg(thing.owner.network_id, thing)
|
self.Send(self.remote_site, poseMsg)
|
||||||
self.Send(self.remote_site, binaryMsg)
|
binaryMsg = BinaryMsg(thing.owner.network_id, thing)
|
||||||
|
self.Send(self.remote_site, binaryMsg)
|
||||||
# if thing.terminate:
|
# if thing.terminate:
|
||||||
# self.Remove(thing)
|
# self.Remove(thing)
|
||||||
|
|
||||||
@ -133,7 +140,7 @@ class ParticipantUDP(Participant):
|
|||||||
|
|
||||||
#region Send
|
#region Send
|
||||||
|
|
||||||
def SendThingInfo(self, owner, thing, recursively: bool = False):
|
def SendThingInfo(self, owner: Participant, thing: 'Thing', recursively: bool = False):
|
||||||
self.Send(owner, ThingMsg(self.network_id, thing))
|
self.Send(owner, ThingMsg(self.network_id, thing))
|
||||||
self.Send(owner, NameMsg(self.network_id, thing))
|
self.Send(owner, NameMsg(self.network_id, thing))
|
||||||
self.Send(owner, ModelUrlMsg(self.network_id, thing))
|
self.Send(owner, ModelUrlMsg(self.network_id, thing))
|
||||||
@ -145,7 +152,7 @@ class ParticipantUDP(Participant):
|
|||||||
self.SendThingInfo(owner, child, recursively)
|
self.SendThingInfo(owner, child, recursively)
|
||||||
|
|
||||||
|
|
||||||
def Send(self, owner, msg):
|
def Send(self, owner: Participant, msg: IMessage):
|
||||||
buffer_size = msg.Serialize([self.buffer])
|
buffer_size = msg.Serialize([self.buffer])
|
||||||
if buffer_size <= 0:
|
if buffer_size <= 0:
|
||||||
return True
|
return True
|
||||||
@ -154,7 +161,7 @@ class ParticipantUDP(Participant):
|
|||||||
self.udp_socket.sendto(self.buffer[:buffer_size], (owner.ip_address, owner.port))
|
self.udp_socket.sendto(self.buffer[:buffer_size], (owner.ip_address, owner.port))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def Publish(self, msg):
|
def Publish(self, msg: IMessage):
|
||||||
buffer_size = msg.Serialize([self.buffer])
|
buffer_size = msg.Serialize([self.buffer])
|
||||||
if buffer_size <= 0:
|
if buffer_size <= 0:
|
||||||
return True
|
return True
|
||||||
@ -183,7 +190,7 @@ class ParticipantUDP(Participant):
|
|||||||
self.network_id = 0
|
self.network_id = 0
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def ReceiveData(self, data, sender):
|
def ReceiveData(self, data: bytes, sender: Participant):
|
||||||
msgId = data[0]
|
msgId = data[0]
|
||||||
# print(f'msg {msgId} ')
|
# print(f'msg {msgId} ')
|
||||||
match msgId:
|
match msgId:
|
||||||
@ -201,11 +208,13 @@ class ParticipantUDP(Participant):
|
|||||||
self.ProcessModelUrlMsg(ModelUrlMsg(data))
|
self.ProcessModelUrlMsg(ModelUrlMsg(data))
|
||||||
case BinaryMsg.id:
|
case BinaryMsg.id:
|
||||||
self.ProcessBinaryMsg(BinaryMsg(data))
|
self.ProcessBinaryMsg(BinaryMsg(data))
|
||||||
|
case _:
|
||||||
|
pass
|
||||||
|
|
||||||
def ProcessParticipantMsg(self, sender, msg: ParticipantMsg):
|
def ProcessParticipantMsg(self, sender: Participant, msg: ParticipantMsg):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def ProcessSiteIdMsg(self, sender, msg: NetworkIdMsg):
|
def ProcessSiteIdMsg(self, sender: Participant, msg: NetworkIdMsg):
|
||||||
print(f'{self.name} Process SiteMsg {self.network_id} -> {msg.network_id}')
|
print(f'{self.name} Process SiteMsg {self.network_id} -> {msg.network_id}')
|
||||||
if self.network_id != msg.network_id:
|
if self.network_id != msg.network_id:
|
||||||
self.network_id = msg.network_id
|
self.network_id = msg.network_id
|
||||||
@ -227,8 +236,8 @@ class ParticipantUDP(Participant):
|
|||||||
|
|
||||||
def ProcessBinaryMsg(self, msg: BinaryMsg):
|
def ProcessBinaryMsg(self, msg: BinaryMsg):
|
||||||
# print('received binary data')
|
# print('received binary data')
|
||||||
thing: Thing = self.Get(msg.thing_id)
|
thing: Optional[Thing] = self.Get(msg.thing_id)
|
||||||
if thing != None:
|
if thing is not None:
|
||||||
thing.ProcessBinary(msg.data)
|
thing.ProcessBinary(msg.data)
|
||||||
|
|
||||||
#endregion
|
#endregion
|
@ -1,8 +1,8 @@
|
|||||||
from LinearAlgebra.Spherical import *
|
from Participant import Participant
|
||||||
from LinearAlgebra.Quaternion import *
|
from LinearAlgebra.Spherical import Spherical
|
||||||
from LinearAlgebra.SwingTwist import *
|
from LinearAlgebra.Quaternion import Quaternion
|
||||||
from RoboidControl.Messages import *
|
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
import time
|
import time
|
||||||
|
|
||||||
class Thing:
|
class Thing:
|
||||||
@ -34,7 +34,7 @@ class Thing:
|
|||||||
|
|
||||||
# region Init
|
# region Init
|
||||||
|
|
||||||
def __init__(self, owner = None, parent = None, thing_type = Type.Undetermined, thing_id = 0):
|
def __init__(self, owner: Optional[Participant] = None, parent: Optional['Thing'] = None, thing_type: int = Type.Undetermined, thing_id: int = 0) -> None:
|
||||||
"""! Create a new thing
|
"""! Create a new thing
|
||||||
@param owner The owning participant
|
@param owner The owning participant
|
||||||
@param parent The parent thing (will override owner if set)
|
@param parent The parent thing (will override owner if set)
|
||||||
@ -42,16 +42,16 @@ class Thing:
|
|||||||
@param thingId The ID of the thing, leave out or set to zero to generate an ID
|
@param thingId The ID of the thing, leave out or set to zero to generate an ID
|
||||||
"""
|
"""
|
||||||
## The participant owning this thing
|
## The participant owning this thing
|
||||||
self.owner = None
|
self.owner: Optional[Participant] = None
|
||||||
## The ID of the thing
|
## The ID of the thing
|
||||||
self.id = thing_id
|
self.id: int = thing_id
|
||||||
## The type of the thing
|
## The type of the thing
|
||||||
#
|
#
|
||||||
## This can be either a \ref RoboidControl::Thing::Thing::Type "Thing.Type" or a byte value for custom types.
|
## This can be either a \ref RoboidControl::Thing::Thing::Type "Thing.Type" or a byte value for custom types.
|
||||||
self.type = thing_type
|
self.type: int = thing_type
|
||||||
|
|
||||||
## The parent of this thing
|
## The parent of this thing
|
||||||
self.parent = None
|
self.parent: Optional[Thing] = None
|
||||||
if parent is not None:
|
if parent is not None:
|
||||||
self.owner = parent.owner
|
self.owner = parent.owner
|
||||||
self.SetParent(parent)
|
self.SetParent(parent)
|
||||||
@ -62,12 +62,12 @@ class Thing:
|
|||||||
self.owner = owner
|
self.owner = owner
|
||||||
|
|
||||||
## The children of this thing
|
## The children of this thing
|
||||||
self.children = []
|
self.children: list[Thing] = list()
|
||||||
|
|
||||||
## The name of the thing
|
## The name of the thing
|
||||||
self.name = None
|
self.name: Optional[str] = None
|
||||||
## An URL pointing to the location where a model of the thing can be found
|
## An URL pointing to the location where a model of the thing can be found
|
||||||
self.model_url = None
|
self.model_url: Optional[str] = None
|
||||||
|
|
||||||
## The position of the thing in local space, in meters
|
## The position of the thing in local space, in meters
|
||||||
self.position: Spherical = Spherical.zero
|
self.position: Spherical = Spherical.zero
|
||||||
@ -89,14 +89,14 @@ class Thing:
|
|||||||
## Boolean indicating the thing has an updated angular velocity
|
## Boolean indicating the thing has an updated angular velocity
|
||||||
self.angular_velocity_updated: bool = False
|
self.angular_velocity_updated: bool = False
|
||||||
|
|
||||||
#self.pose_updated = 0x00 # the bits indicate which fields have been updated
|
if self.owner is not None:
|
||||||
self.owner.Add(self)
|
self.owner.Add(self)
|
||||||
|
|
||||||
# endregion Init
|
# endregion Init
|
||||||
|
|
||||||
# region Hierarchy
|
# region Hierarchy
|
||||||
|
|
||||||
def SetParent(self, parent):
|
def SetParent(self, parent: Optional['Thing']):
|
||||||
"""! Sets the parent of this Thing
|
"""! Sets the parent of this Thing
|
||||||
@param The Thing which should become the parent
|
@param The Thing which should become the parent
|
||||||
@note Do not set Thing.parent directly, as that will break the parent-child relation
|
@note Do not set Thing.parent directly, as that will break the parent-child relation
|
||||||
@ -109,7 +109,7 @@ class Thing:
|
|||||||
else:
|
else:
|
||||||
parent.AddChild(self)
|
parent.AddChild(self)
|
||||||
|
|
||||||
def AddChild(self, child):
|
def AddChild(self, child: 'Thing'):
|
||||||
"""! Add a child Thing to this Thing
|
"""! Add a child Thing to this Thing
|
||||||
@param child The Thing which should become a child
|
@param child The Thing which should become a child
|
||||||
@remark When the Thing is already a child, it will not be added again
|
@remark When the Thing is already a child, it will not be added again
|
||||||
@ -120,21 +120,20 @@ class Thing:
|
|||||||
|
|
||||||
child.parent = self
|
child.parent = self
|
||||||
self.children.append(child)
|
self.children.append(child)
|
||||||
def RemoveChild(self, child):
|
|
||||||
|
def RemoveChild(self, child: 'Thing'):
|
||||||
"""! Remove the given thing as a child of this thing
|
"""! Remove the given thing as a child of this thing
|
||||||
@param child The child to remove
|
@param child The child to remove
|
||||||
"""
|
"""
|
||||||
self.children.remove(child)
|
self.children.remove(child)
|
||||||
|
|
||||||
def GetChild(self, thing_id, recurse = False):
|
def GetChild(self, thing_id: int, recurse: bool = False) -> Optional['Thing']:
|
||||||
"""! Get a child by thing Id
|
"""! Get a child by thing Id
|
||||||
@param id The thing ID to find
|
@param id The thing ID to find
|
||||||
@param recurse Look recursively through all descendants
|
@param recurse Look recursively through all descendants
|
||||||
@returns The found thing of nullptr when nothing is found
|
@returns The found thing of nullptr when nothing is found
|
||||||
"""
|
"""
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
if child is None:
|
|
||||||
continue
|
|
||||||
if child.id == thing_id:
|
if child.id == thing_id:
|
||||||
return child
|
return child
|
||||||
if recurse:
|
if recurse:
|
||||||
@ -143,19 +142,17 @@ class Thing:
|
|||||||
return found_child
|
return found_child
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def FindChild(self, name, recurse = True):
|
def FindChild(self, name: str, recurse: bool = True) -> Optional['Thing']:
|
||||||
"""! Find a thing by name
|
"""! Find a thing by name
|
||||||
@param name The name of the thing
|
@param name The name of the thing
|
||||||
@return The found thing or nullptr when nothing is found
|
@return The found thing or nullptr when nothing is found
|
||||||
@param recurse Look recursively through all descendants
|
@param recurse Look recursively through all descendants
|
||||||
"""
|
"""
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
if child is None:
|
|
||||||
continue
|
|
||||||
if child.name == name:
|
if child.name == name:
|
||||||
return child
|
return child
|
||||||
if recurse:
|
if recurse:
|
||||||
found_child = child.GetChild(name, recurse)
|
found_child = child.FindChild(name, recurse)
|
||||||
if found_child is not None:
|
if found_child is not None:
|
||||||
return found_child
|
return found_child
|
||||||
return None
|
return None
|
||||||
@ -163,21 +160,21 @@ class Thing:
|
|||||||
|
|
||||||
# region Pose
|
# region Pose
|
||||||
|
|
||||||
def SetPosition(self, position):
|
def SetPosition(self, position: Spherical) -> None:
|
||||||
"""! Set the position of the thing
|
"""! Set the position of the thing
|
||||||
@param position The new position in local space, in meters
|
@param position The new position in local space, in meters
|
||||||
"""
|
"""
|
||||||
self.position = position
|
self.position = position
|
||||||
self.position_updated = True
|
self.position_updated = True
|
||||||
|
|
||||||
def SetOrientation(self, orientation):
|
def SetOrientation(self, orientation: Quaternion) -> None:
|
||||||
"""! Set the orientation of the thing
|
"""! Set the orientation of the thing
|
||||||
@param orientation The new orientation in local space
|
@param orientation The new orientation in local space
|
||||||
"""
|
"""
|
||||||
self.orientation = orientation
|
self.orientation = orientation
|
||||||
self.orientation_updated = True
|
self.orientation_updated = True
|
||||||
|
|
||||||
def SetLinearVelocity(self, linear_velocity):
|
def SetLinearVelocity(self, linear_velocity: Spherical) -> None:
|
||||||
"""! Set the linear velocity of the thing
|
"""! Set the linear velocity of the thing
|
||||||
@param linearVelocity The new linear velocity in local space, in meters per second
|
@param linearVelocity The new linear velocity in local space, in meters per second
|
||||||
"""
|
"""
|
||||||
@ -186,7 +183,7 @@ class Thing:
|
|||||||
|
|
||||||
self.linear_velocity = linear_velocity
|
self.linear_velocity = linear_velocity
|
||||||
|
|
||||||
def SetAngularVelocity(self, angular_velocity):
|
def SetAngularVelocity(self, angular_velocity: Spherical) -> None:
|
||||||
"""! Set the angular velocity of the thing
|
"""! Set the angular velocity of the thing
|
||||||
@param angularVelocity the new angular velocity in local space
|
@param angularVelocity the new angular velocity in local space
|
||||||
"""
|
"""
|
||||||
@ -200,13 +197,13 @@ class Thing:
|
|||||||
# region Update
|
# region Update
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def GetTimeMs():
|
def GetTimeMs() -> int:
|
||||||
"""! Get the current time in milliseconds
|
"""! Get the current time in milliseconds
|
||||||
@return The current time in milliseconds
|
@return The current time in milliseconds
|
||||||
"""
|
"""
|
||||||
return time.time() * 1000
|
return int(time.time() * 1000)
|
||||||
|
|
||||||
def Update(self, currentTime = 0, recurse = False):
|
def Update(self, currentTimeMs: int = 0, recurse: bool = False) -> None:
|
||||||
"""! Update de state of the thing
|
"""! Update de state of the thing
|
||||||
@param currentTimeMs The current clock time in milliseconds; If this is zero, the current time is retrieved automatically
|
@param currentTimeMs The current clock time in milliseconds; If this is zero, the current time is retrieved automatically
|
||||||
@param recurse When true, this will Update the descendants recursively
|
@param recurse When true, this will Update the descendants recursively
|
||||||
@ -218,21 +215,19 @@ class Thing:
|
|||||||
|
|
||||||
if recurse:
|
if recurse:
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
if child is None:
|
child.Update(currentTimeMs, recurse)
|
||||||
continue
|
|
||||||
child.Update(currentTime, recurse)
|
|
||||||
|
|
||||||
# endregion Update
|
# endregion Update
|
||||||
|
|
||||||
def GenerateBinary(self, buffer, ix_ref) -> int:
|
def GenerateBinary(self, bytes: bytearray, ix_ref: set[int]) -> int:
|
||||||
"""! Function used to generate binary data for this thing
|
"""! Function used to generate binary data for this thing
|
||||||
@param buffer The byte array for thw binary data
|
@param buffer The byte array for thw binary data
|
||||||
@param ix The starting position for writing the binary data
|
@param ix_ref A single element array with the starting position for writing the binary data
|
||||||
@returns The size of the binary data
|
@returns The size of the binary data
|
||||||
"""
|
"""
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def ProcessBinary(self, data):
|
def ProcessBinary(self, data: bytes):
|
||||||
"""! Function used to process binary data received for this thing
|
"""! Function used to process binary data received for this thing
|
||||||
@param bytes The binary data
|
@param bytes The binary data
|
||||||
"""
|
"""
|
||||||
|
32
RoboidControl/Things/DigitalSensor.py
Normal file
32
RoboidControl/Things/DigitalSensor.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from RoboidControl.Thing import Thing
|
||||||
|
|
||||||
|
class TouchSensor(Thing):
|
||||||
|
"""! A sensor which can detect touches
|
||||||
|
"""
|
||||||
|
def __init__(self, owner = None, parent = None, thing_id = 0):
|
||||||
|
"""! Create a touch sensor
|
||||||
|
"""
|
||||||
|
super().__init__(owner = owner, parent = parent, thing_type = Thing.Type.TouchSensor, thing_id = thing_id)
|
||||||
|
|
||||||
|
## Value which is true when the sensor is touching something, false otherwise
|
||||||
|
self.touched_something = False
|
||||||
|
|
||||||
|
def GenerateBinary(self, bytes, ix_ref):
|
||||||
|
"""! Function used to generate binary data for this touch sensor
|
||||||
|
@param bytes The byte array for thw binary data
|
||||||
|
@param ix_ref A single element array with the starting position for writing the binary data
|
||||||
|
@returns The size of the binary data
|
||||||
|
"""
|
||||||
|
ix = ix_ref[0]
|
||||||
|
if self.touched_something:
|
||||||
|
bytes[ix] = 0
|
||||||
|
else:
|
||||||
|
bytes[ix] = 1
|
||||||
|
ix_ref[0] += 1
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def ProcessBinary(self, bytes):
|
||||||
|
"""! Function used to process binary data received for this touch sensor
|
||||||
|
@param bytes The binary data to process
|
||||||
|
"""
|
||||||
|
self.touched_something = bytes[0] == 1
|
@ -2,18 +2,26 @@ from RoboidControl.Thing import Thing
|
|||||||
from RoboidControl.Messages import LowLevelMessages
|
from RoboidControl.Messages import LowLevelMessages
|
||||||
|
|
||||||
class TemperatureSensor(Thing):
|
class TemperatureSensor(Thing):
|
||||||
def __init__(self, thing_id):
|
"""! A temperature sensor
|
||||||
super().__init__(thing_id, thing_type = Thing.Type.TemperatureSensor)
|
"""
|
||||||
self.temp = 0
|
def __init__(self, owner = None, parent = None, thing_id = 0):
|
||||||
self._watchers = []
|
super().__init__(owner = owner, parent = parent, thing_type = Thing.Type.TemperatureSensor, thing_id = thing_id)
|
||||||
|
|
||||||
def OnUpdate(self, handler):
|
## The temperature in degrees celcius
|
||||||
self._watchers.append(handler)
|
self.temperature = 0
|
||||||
def CancelOnUpdate(self, handler):
|
|
||||||
self._watchers.remove(handler)
|
|
||||||
|
|
||||||
def ProcessBinary(self, data):
|
def GenerateBinary(self, bytes, ix_ref):
|
||||||
|
"""! Function used to generate binary data for this temperature sensor
|
||||||
|
@param bytes The byte array for thw binary data
|
||||||
|
@param ix_ref A single element array with the starting position for writing the binary data
|
||||||
|
@returns The size of the binary data
|
||||||
|
"""
|
||||||
|
LowLevelMessages.SendFloat16(bytes, ix_ref, self.temperature)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def ProcessBinary(self, bytes):
|
||||||
|
"""! Function used to process the binary data received for this temperature sensor
|
||||||
|
@param bytes The binary data to process
|
||||||
|
"""
|
||||||
ix = 0
|
ix = 0
|
||||||
self.temp = LowLevelMessages.ReceiveFloat16(data, [ix])
|
self.temperature = LowLevelMessages.ReceiveFloat16(bytes, [ix])
|
||||||
for watcher in self._watchers:
|
|
||||||
watcher(self.temp)
|
|
||||||
|
@ -3,19 +3,30 @@ from RoboidControl.Thing import Thing
|
|||||||
class TouchSensor(Thing):
|
class TouchSensor(Thing):
|
||||||
"""! A sensor which can detect touches
|
"""! A sensor which can detect touches
|
||||||
"""
|
"""
|
||||||
def __init__(self, owner = None, parent = None):
|
def __init__(self, owner = None, parent = None, thing_id = 0):
|
||||||
"""! Create a touch sensor
|
"""! Create a touch sensor
|
||||||
"""
|
"""
|
||||||
super().__init__(owner = owner, parent = parent, thing_type = Thing.Type.TouchSensor)
|
super().__init__(owner = owner, parent = parent, thing_type = Thing.Type.TouchSensor, thing_id = thing_id)
|
||||||
|
|
||||||
## Value which is true when the sensor is touching something, false otherwise
|
## Value which is true when the sensor is touching something, false otherwise
|
||||||
self.touched_something = False
|
self.touched_something = False
|
||||||
|
|
||||||
|
def GenerateBinary(self, bytes, ix_ref):
|
||||||
|
"""! Function used to generate binary data for this touch sensor
|
||||||
|
@param bytes The byte array for thw binary data
|
||||||
|
@param ix_ref A single element array with the starting position for writing the binary data
|
||||||
|
@returns The size of the binary data
|
||||||
|
"""
|
||||||
|
ix = ix_ref[0]
|
||||||
|
if self.touched_something:
|
||||||
|
bytes[ix] = 0
|
||||||
|
else:
|
||||||
|
bytes[ix] = 1
|
||||||
|
ix_ref[0] += 1
|
||||||
|
return 1
|
||||||
|
|
||||||
def ProcessBinary(self, bytes):
|
def ProcessBinary(self, bytes):
|
||||||
"""! Function to extract the touch state received in a binary message
|
"""! Function used to process binary data received for this touch sensor
|
||||||
|
@param bytes The binary data to process
|
||||||
"""
|
"""
|
||||||
self.touched_something = bytes[0] == 1
|
self.touched_something = bytes[0] == 1
|
||||||
if self.touched_something:
|
|
||||||
print(f"{self.name} touched something!")
|
|
||||||
else:
|
|
||||||
print(f"{self.name} touching nothing")
|
|
Loading…
x
Reference in New Issue
Block a user