labthings_fastapi.thing
The Thing class enables most of the functionality of this library,
and is the way in to most of its features. In the future, we might
support a stub version of the class in a separate package, so
that instrument control libraries can be LabThings compatible
without a hard dependency on LabThings. But that is something we
will do in the future…
Module Contents
Classes
Represents a Thing, as defined by the Web of Things standard. |
Data
API
- labthings_fastapi.thing._LOGGER
‘getLogger(…)’
- class labthings_fastapi.thing.Thing
Represents a Thing, as defined by the Web of Things standard.
This class should encapsulate the code that runs a piece of hardware, or provides a particular function - it will correspond to a path on the server, and a Thing Description document.
Subclassing Notes
__init__: You should accept any arguments you need to configure the Thing in__init__. Don’t initialise any hardware at this time, as your Thing may be instantiated quite early, or even at import time.__enter__(self)and__exit__(self, exc_t, exc_v, exc_tb)are where you should start and stop communications with the hardware. This is Python’s standard “context manager” protocol. The arguments of__exit__will beNoneunless an exception has occurred. You should be safe to ignore them, and just include code that will close down your hardware. It’s equivalent to afinally:block.Properties and Actions are defined using decorators: the
@thing_actiondecorator declares a method to be an action, which will run when it’s triggered, and the@thing_propertydecorator (orThingPropertydescriptor) does the same for a property. See the documentation on those functions for more detail.titlewill be used in various places as the human-readable name of your Thing, so it makes sense to set this in a subclass.
There are various LabThings methods that you should avoid overriding unless you know what you are doing: anything not mentioned above that’s defined in
Thingis probably best left along. They may in time be collected together into a single object to avoid namespace clashes.- _labthings_blocking_portal: Optional[anyio.from_thread.BlockingPortal]
None
- async __aenter__()
Context management is used to set up/close the thing.
As things (currently) do everything with threaded code, we define async aenter and aexit wrappers to call the synchronous code, if it exists.
- async __aexit__(exc_t, exc_v, exc_tb)
Wrap context management functions, if they exist.
See aenter docs for more details.
- attach_to_server(server: labthings_fastapi.server.ThingServer, path: str, setting_storage_path: str)
Attatch this thing to the server.
Things need to be attached to a server before use to function correctly.
- Parameters:
server – The server to attach this Thing to
settings_storage_path – The path on disk to save the any Thing Settings to. This should be the path to a json file. If it does not exist it will be created.
Wc3 Web Of Things explanation: This will add HTTP handlers to an app for all Interaction Affordances
- property _settings: Optional[dict[str, labthings_fastapi.descriptors.ThingSetting]]
A private property that returns a dict of all settings for this Thing
Each dict key is the name of the setting, the corresponding value is the ThingSetting class (a descriptor). This can be used to directly get the descriptor so that the value can be set without emitting signals, such as on startup.
- property setting_storage_path: Optional[str]
The storage path for settings. This is set as the Thing is added to a server
- load_settings(setting_storage_path)
Load settings from json. This is run when the Thing is added to a server
- save_settings()
Save settings to JSON. This is called whenever a setting is updated
- property thing_state: collections.abc.Mapping
Return a dictionary summarising our current state
This is intended to be an easy way to collect metadata from a Thing that summarises its state. It might be used, for example, to record metadata along with each reading/image/etc. when an instrument is saving data.
It’s best to populate this automatically so it can always be accessed. If it requires calls e.g. to a serial instrument, bear in mind it may be called quite often and shouldn’t take too long.
Some measure of cacheing here is a nice aim for the future, but not yet implemented.
- validate_thing_description()
Raise an exception if the thing description is not valid
- _cached_thing_description: Optional[tuple[Optional[str], Optional[str], labthings_fastapi.thing_description.model.ThingDescription]]
None
- thing_description(path: Optional[str] = None, base: Optional[str] = None) labthings_fastapi.thing_description.model.ThingDescription
A w3c Thing Description representing this thing
The w3c Web of Things working group defined a standard representation of a Thing, which provides a high-level description of the actions, properties, and events that it exposes. This endpoint delivers a JSON representation of the Thing Description for this Thing.
- thing_description_dict(path: Optional[str] = None, base: Optional[str] = None) dict
A w3c Thing Description representing this thing, as a simple dict
The w3c Web of Things working group defined a standard representation of a Thing, which provides a high-level description of the actions, properties, and events that it exposes. This endpoint delivers a JSON representation of the Thing Description for this Thing.
- observe_property(property_name: str, stream: anyio.abc.ObjectSendStream)
Register a stream to receive property change notifications
- observe_action(action_name: str, stream: anyio.abc.ObjectSendStream)
Register a stream to receive action status change notifications