labthings_fastapi.websockets

Handle notification of events, property, and action status changes.

There are several kinds of “event” in the WoT vocabulary, not all of which are called Event, which is why this module is called notifications. In all cases, these are events that happen on an exposed Thing, and may need to be relayed to one or more listeners (currently via a WebSocket connection, though long polling may also be an option in the future).

The aim at this stage (July 2023) is for a minimal working example that enables property changes to be fed via a websocket. Events proper should not be a big step thereafter.

The W3C standard does not define a way for one websocket to handle multiple Things, so for now the websocket endpoint will be associated with a single Thing instance. This may change in the future.

  1. Richard Bowman July 2023, released under GNU-LGPL-3.0

Attributes

LOGGER

WEBTHING_ERROR_URL

Functions

observation_error_response(→ dict[str, str | dict])

Generate a websocket error response for observing an action or property.

relay_notifications_to_websocket(→ None)

Relay objects from a stream to a websocket as JSON.

assert_property_is_observable(→ bool)

Check that a Thing has a particular property and it is observable.

process_messages_from_websocket(→ None)

Process messages received from a websocket.

websocket_endpoint(→ None)

Handle communication to a client via websocket.

Module Contents

labthings_fastapi.websockets.LOGGER
labthings_fastapi.websockets.WEBTHING_ERROR_URL = 'https://w3c.github.io/web-thing-protocol/errors'
labthings_fastapi.websockets.observation_error_response(name: str, affordance_type: Literal['action', 'property'], exception: Exception) dict[str, str | dict]

Generate a websocket error response for observing an action or property.

When a websocket client asks to observe a property or action that either doesn’t exist or isn’t observable, this function makes a dictionary that can be returned to the client indicating an error.

Parameters:
  • name – The name of the affordance being observed.

  • affordance_type – The type of the affordance.

  • exception – The error that was raised.

Returns:

A dictionary that may be returned to the websocket.

Raises:

TypeError – if the exception is not a KeyError or PropertyNotObservableError.

async labthings_fastapi.websockets.relay_notifications_to_websocket(websocket: fastapi.WebSocket, receive_stream: anyio.streams.memory.MemoryObjectReceiveStream[labthings_fastapi.message_broker.Message]) None

Relay objects from a stream to a websocket as JSON.

Interaction Affordances (events, actions) that we’ve registered with will post messages to the queue: this function takes those messages from the queue and passes them to the websocket.

Parameters:
  • websocket – the WebSocket we are communicating over.

  • receive_stream – a stream that will yield objects that we send over the websocket.

labthings_fastapi.websockets.assert_property_is_observable(thing: labthings_fastapi.thing.Thing, property: str) bool

Check that a Thing has a particular property and it is observable.

Parameters:
  • thing – the Thing instance being observed.

  • property – the name of the property.

Raises:
Returns:

True if an exception wasn’t raised.

async labthings_fastapi.websockets.process_messages_from_websocket(websocket: fastapi.WebSocket, send_stream: anyio.streams.memory.MemoryObjectSendStream[labthings_fastapi.message_broker.Message], broker: labthings_fastapi.message_broker.MessageBroker, thing: labthings_fastapi.thing.Thing) None

Process messages received from a websocket.

Currently, this will allow us to observe properties, by registering (or de-registering) for those properties.

Parameters:
  • websocket – the WebSocket we are communicating over.

  • send_stream – an anyio.abc.ObjectSendStream that we use to register for events, i.e. data sent to that stream will be sent through this websocket, by relay_notifications_to_websocket.

  • broker – the message broker to use for subscriptions.

  • thing – the Thing we are attached to. The websocket is specific to one Thing, and this is it.

async labthings_fastapi.websockets.websocket_endpoint(thing: labthings_fastapi.thing.Thing, websocket: fastapi.WebSocket, broker: labthings_fastapi.message_broker.MessageBroker) None

Handle communication to a client via websocket.

This function handles a websocket connection to a Thing‘s websocket endpoint. It can add observers to properties and actions, and will forward notifications from the property or action back to the websocket.

Parameters:
  • thing – the Thing the websocket is attached to.

  • websocket – the web socket that has been created.

  • broker – the message broker to use for subscriptions.