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

Thing

Represents a Thing, as defined by the Web of Things standard.

Data

_LOGGER

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 be None unless 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 a finally: block.

  • Properties and Actions are defined using decorators: the @thing_action decorator declares a method to be an action, which will run when it’s triggered, and the @thing_property decorator (or ThingProperty descriptor) does the same for a property. See the documentation on those functions for more detail.

  • title will 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 Thing is probably best left along. They may in time be collected together into a single object to avoid namespace clashes.

title: str

None

_labthings_blocking_portal: Optional[anyio.from_thread.BlockingPortal]

None

path: Optional[str]

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

_settings_store: Optional[dict[str, labthings_fastapi.descriptors.ThingSetting]]

None

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.

_setting_storage_path: Optional[str]

None

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

_labthings_thing_state: Optional[dict]

None

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