.. _labthings_cc: .. _structure: LabThings structure =================== LabThings is intended to simplify the process of making a piece of hardware available through an HTTP API and documenting that API with :ref:`gen_docs`\ . Server ------ LabThings is a server-based framework. The `~lt.ThingServer` creates and manages the `~lt.Thing` instances that represent individual hardware or software units. The functionality of those `~lt.Thing`\ s is accessed via HTTP requests, which can be made from a web browser, the command line, or any programming language with an HTTP library. LabThings-FastAPI is built on top of `fastapi`\ , which is a fast, modern HTTP framework. LabThings provides functionality to manage `~lt.Thing`\ s and their actions, including: * Initialising, starting up, and shutting down the `~lt.Thing` instances, so that hardware is correctly started up and shut down. * Managing actions, including making logs and output values available over HTTP. * Managing `.Blob` input and output (i.e. binary objects that are best not serialised to JSON). * Generating a :ref:`gen_td` in addition to the :ref:`openapi` documentation produced by `fastapi`\ . * Making connections between `~lt.Thing` instances as required. .. _things: Things ----------- Each unit of hardware (or software) that should be exposed by the server is implemented as a subclass of `~lt.Thing`\ . A `~lt.Thing` subclass represents a particular type of instrument (whether hardware or software), and its functionality is described using actions and properties, described below. `~lt.Thing`\ s don't have to correspond to separate pieces of hardware: it's possible (and indeed recommended) to use `~lt.Thing` subclasses for software components, plug-ins, swappable modules, or anything else that needs to add functionality to the server. `~lt.Thing`\ s may access each other's attributes, so you can write a `~lt.Thing` that implements a particular measurement protocol or task, using hardware that's accessed through other `~lt.Thing` instances on the server. Each `~lt.Thing` is documented by a :ref:`gen_td` which outlines its features in a higher-level way than :ref:`openapi`\ . The attributes of a `~lt.Thing` are made available over HTTP by decorating or marking them with the following functions: * `~lt.property` may be used as a decorator analogous to Python's built-in ``@property``\ . It can also be used to mark class attributes as variables that should be available over HTTP. * `~lt.setting` works similarly to `~lt.property` but it is persisted to disk when the server stops, so the value is remembered. * `lt.action` is a decorator that makes methods available over HTTP. * `~lt.thing_slot` tells LabThings to supply an instance of another `~lt.Thing` at runtime, so your `~lt.Thing` can make use of it. Client Code ----------- Client code can be written in any language that supports an HTTP request. However, LabThings FastAPI provides additional functionality that makes writing client code in Python easier. See :ref:`using_things` for more detail. `~lt.ThingClient` is a class that wraps up the required HTTP requests into a simpler interface. It can retrieve the :ref:`gen_td` over HTTP and use it to generate a new object with methods matching each `lt.action` and properties matching each `~lt.property`. While the current dynamic implementation of `~lt.ThingClient` can be inspected with functions like `help` at runtime, it does not work well with static tools like `mypy` or `pyright`\ . In the future, LabThings should be able to generate static client code that works better with autocompletion and type checking. Data types ----------- LabThings follows `fastapi`\ 's approach of using type hints to define the data types of action parameters and property values. Standard Python types can be used wherever possible, and `pydantic` will be used in the background to generate JSONSchema definitions as part of the API documentation. More complicated datatypes may be described using `pydantic` models, which can be used as type hints in action signatures or property definitions. Binary data that is not easily serialised to JSON (e.g. images, large arrays, or files) may be represented using the `.Blob` datatype. This is described in more detail in :ref:`blobs`\ .