docs: add MQTT documentation

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2021-06-23 20:58:02 -04:00
parent 0126aa794f
commit 188dc4c782
3 changed files with 287 additions and 22 deletions

View File

@ -153,7 +153,7 @@ when it needs a reference to core component.
If the component fails to load `default` will be returned. If `default`
is not provided a `ServerError` will be raised.
#### *Server.register_endpoint(uri, request_methods, callback, protocol=["http", "websocket"], wrap_result=True)*
#### *Server.register_endpoint(uri, request_methods, callback, transports=["http", "websocket", "mqtt"], wrap_result=True)*
Registers the supplied `uri` with the server.
@ -166,10 +166,11 @@ The `callback` is executed when a request matching the `uri` and a
should be able of handling each registered `request_method`. The
provided callback must be a coroutine.
The `protocol` is a list containing any combination of `http` and `websocket`.
If `websocket` is selected associated JSON-RPC methods will be generated based
on what is supplied by the `uri` and `request_methods` argument. A unique
JSON_RPC method is generated for each request method. For example:
The `transports` argument is a list containing any combination of
`http`, `websocket` and `mqtt`. JSON-RPC methods for `websocket` and `mqtt`
will be generated based on what is supplied by the `uri` and
request_methods` argument. A unique JSON_RPC method is generated for each
request method. For example:
```python
self.server.register_endpoint("/server/example", ["POST"], self._handle_request)
```
@ -273,32 +274,90 @@ passing the WebRequest on to another request handler.
Returns the request argument at the provided `key`. If the key is not
present `default` will be returned. If `default` is not provided a
`SeverError` will be raised.
`ServerError` will be raised.
#### *WebRequest.get_str(key, default=Sentinel)*
Retrieves the request argument at the provided `key` and converts it
to a string, returning the result. If the key is not present the `default`
value will be returned. If `default` is not provided or if the attempt at
type conversion fails a `SeverError` will be raised.
type conversion fails a `ServerError` will be raised.
#### *WebRequest.get_int(key, default=Sentinel)*
Retrieves the request argument at the provided `key` and converts it
to an integer, returning the result. If the key is not present the `default`
value will be returned. If `default` is not provided or if the attempt at
type conversion fails a `SeverError` will be raised.
type conversion fails a `ServerError` will be raised.
#### *WebRequest.get_float(key, default=Sentinel)*
Retrieves the request argument at the provided `key` and converts it
to a float, returning the result. If the key is not present the `default`
value will be returned. If `default` is not provided or if the attempt at
type conversion fails a `SeverError` will be raised.
type conversion fails a `ServerError` will be raised.
#### *WebRequest.get_boolean(key, default=Sentinel)*
Retrieves the request argument at the provided `key` and converts it
to a boolean, returning the result. If the key is not present the `default`
value will be returned. If `default` is not provided or if the attempt at
type conversion fails a `SeverError` will be raised.
type conversion fails a `ServerError` will be raised.
### MQTT
If configured by the user the MQTT component is available for lookup.
Developers may use this to subscribe and publish topics.
#### *MQTTClient.is_connected()*
Returns true if Moonraker is currently connected to the Broker, false
otherwise.
#### *MQTTClient.wait_connection(timeout=None)*
Blocks until a connection with the broker has been successfully established.
If the optional `timeout` argument is specified then `asyncio.TimeoutError`
will be raised if the timeout has exceeded.
#### *MQTTClient.publish_topic(topic, payload=None, qos=None, retain=False)*
Attempts to publish a topic to the Broker. The `payload` may be a bool, int,
float, string, or json encodable (Dict or List). If omitted then an empty
payload is sent. The `qos` may be an integer from 0 to 2. If not specifed
then the QOS level will use the configured default. If `retain` is set to
`True` then the retain flag for the payload will be set.
Returns a Future that will block until topic is confirmed as published.
For QOS level 0 an exception will be raised if the broker is not connected.
#### *MQTTClient.publish_topic_with_response(topic, response_topic, payload=None, qos=None, retain=False, timeout=None)*
Publishes the supplied `topic` with the arguments specified by `payload`,
`qos`, and `retain`, then subscribes to the `response_topic`. The payload
delivered by the response topic is returned. Note that this method is
a coroutine, it must always be awaited. The call will block until the
entire process has completed unless a `timeout` (in seconds) is specifed.
The `timeout` is applied to both the attempt to publish and the pending
response, so the maximum waiting time would be approximately 2*timeout.
!!! warning
This should only be used when it is guaranteed that the `response_topic`
does not have a retained value. Otherwise the returned response will
be the retained value.
#### *MQTTClient.subscribe_topic(topic, callback, qos=None)*
Subscibes to the supplied `topic` with the specified `qos`. If `qos` is not
supplied the configured default will be used. The `callback` should be a
callable that accepts a `payload` argument of a `bytes` type. The callable
may be a coroutine. The callback will be run each time the subscribed topic
is published by another client.
Returns a `SubscriptionHandle` that may be used to unsubscribe the topic.
#### *MQTTClinet.unsubscribe(hdl)*
Unsubscribes the callback associated with `hdl`. If no outstanding callbacks
exist for the topic then the topic is unsubscribed from the broker.

View File

@ -427,7 +427,8 @@ persistent_files:
```
This second example is for git repositories that have a service that need
updating.
updating. Note that git repos must have at least one tag for Moonraker
to identify its version.
```ini
# moonraker.conf
@ -468,3 +469,60 @@ enable_node_updates:
# package-lock.json in its root directory then the plugin will fail to load.
# Default is False.
```
## `[mqtt]`
Enables an MQTT Client. When configured most of Moonraker's APIs are availble
by publishing JSON-RPC requests to `{instance_name}/moonraker/api/request`.
Responses will be published to `{instance_name}/moonraker/api/response`. See
the [API Documentation](web_api.md#json-rpc-api-overview) for details on
on JSON-RPC.
It is also possible for other components within Moonraker to use MQTT to
publish and subscribe to topics.
```ini
address:
# Address of the Broker. This may be a hostname or IP Address. This
# parameter must be provided.
port:
# Port the Broker is listening on. Default is 1883.
username:
# An optional username used to log in to the Broker. Default is no
# username (an anonymous login will be attempted)
password_file:
# An optional path to a text file containing a password used to log in
# to the broker. It is strongly recommended that this file be located
# in a folder not served by Moonraker. It is also recommended that the
# password be unique and not used for other logins, as it is stored in
# plain text. To create a password file, one may ssh in to the device
# and enter the following commands:
# cd ~
# echo mypassword > .mqttpass
# Then set this option to:
# ~/.mqttpass
# If this option is omitted no password will be used to login.
mqtt_protocol: v3.1.1
# The protocol to use when connecting to the Broker. May be v3.1,
# v3.1.1, and v5. The default is v3.1.1
enable_moonraker_api: True
# If set to true the MQTT client will subscribe to API topic, ie:
# {instance_name}/moonraker/api/request
# This can be set to False if the user does not wish to allow API
# requests over MQTT. The default is True.
instance_name:
# An identifer used to create unique API topics for each instance of
# Moonraker on network. This name cannot contain wildcards (+ or #).
# For example, if the instance name is set to my_printer, Moonraker
# will subscribe to the following topic for API requests:
# my_printer/moonraker/api/request
# Responses will be published to the following topic:
# my_printer/moonraker/api/response
# The default is the machine's hostname.
default_qos: 0
# The default QOS level used when publishing or subscribing to topics.
# Must be an integer value from 0 to 2. The default is 0.
api_qos:
# The QOS level to use for the API topics. If not provided, the
# value specified by "default_qos" will be used.
```

View File

@ -1,10 +1,10 @@
#
Most API methods are supported over both the Websocket and HTTP transports.
File Transfer and `/access` requests are only available over HTTP. The
Websocket is required to receive server generated events such as gcode
responses. For information on how to set up the Websocket, please see the
Appendix at the end of this document.
Most API methods are supported over the Websocket, HTTP, and MQTT
(if configured) transports. File Transfer and `/access` requests are only
available over HTTP. The Websocket is required to receive server generated
events such as gcode responses. For information on how to set up the
Websocket, please see the Appendix at the end of this document.
### HTTP API Overview
@ -71,10 +71,19 @@ thus using this functionality should be seen as a "last resort." If at
all possible clients should attempt to put these arguments in the body
of a request.
### Websocket API Overview
### JSON-RPC API Overview
The Websocket API is based on JSON-RPC, an encoded request should look
something like:
The Websocket and MQTT transports use the [JSON-RPC 2.0](https://jsonrpc.org)
protocol. The Websocket transmits objects in a text frame, whereas MQTT
transmits them in the payload of a topic. When MQTT is configured Moonraker
subscribes to an api request topic. After an api request is processed Moonraker
publishes the return value to a response topic. By default these topics are
`{instance_name}/moonraker/api/request` and
`{instance_name}/moonraker/api/response`. The `{instance_name}` should be a
unique identifier for each instance of Moonraker and defaults to the machine's
host name.
An encoded request should look something like:
```json
{
"jsonrpc": "2.0",
@ -85,10 +94,19 @@ something like:
```
The `params` field may be left out if the API request takes no arguments.
The `id` should be a unique integer value that has no chance of colliding
The `id` should be a unique value that has no chance of colliding
with other JSON-RPC requests. The `method` is the API method, as defined
for each API in this document.
!!! tip
MQTT requests may provide an optional `mqtt_timestamp` keyword
argument in the `params` field of the JSON-RPC request. To avoid
potential collisions from time drift it is recommended to specify
the timestamp in microseconds since the Unix Epoch. If provided
Moonraker will use the timestamp to discard duplicate requests.
It is recommended to either provide a timestamp or publish API
requests at a QoS level of 0 or 2.
A successful request will return a response like the following:
```json
{
@ -114,7 +132,7 @@ Some errors may not return a request ID, such as an improperly formatted request
The `test/client` folder includes a basic test interface with example usage for
most of the requests below. It also includes a basic JSON-RPC implementation
that uses promises to return responses and errors (see json-rcp.js).
that uses promises to return responses and errors (see json-rpc.js).
### Printer Administration
@ -303,6 +321,9 @@ POST /printer/objects/subscribe?connection_id=123456789&gcode_move&extruder`
request that includes only the `connection_id` argument will cancel the
subscription on the specified websocket.
This request is not available over MQTT, as it is not possible to
associate a connected websocket with an MQTT client.
JSON-RPC request:
```json
{
@ -2794,7 +2815,7 @@ JSON-RPC request:
"jsonrpc": "2.0",
"method":"server.history.get_job",
"params":{"uid": "{uid}"},
"id": 4564,
"id": 4564
}
```
Returns:
@ -2849,6 +2870,133 @@ An array of deleted job ids
]
```
### MQTT APIs
The following API is available when `[mqtt]` has been configured.
!!! Note
These requests are not available over the `mqtt` transport as they
are redundant. MQTT clients can publish and subscribe to
topics directly.
#### Publish a topic
HTTP request:
```http
POST /server/mqtt/publish
Content-Type: application/json
{
"topic": "home/test/pub",
"payload": "hello",
"qos": 0,
"retain": false,
"timeout": 5
}
```
JSON-RPC request:
```json
{
"jsonrpc": "2.0",
"method":"server.mqtt.publish",
"params":{
"topic": "home/test/pub",
"payload": "hello",
"qos": 0,
"retain": false,
"timeout": 5
},
"id": 4564
}
```
Only the `topic` parameter is required. Below is an explanation for
each paramater:
- `topic`: The topic to publish.
- `payload`: Payload to send with the topic. May be a boolean, float,
integer, string, object, or array. All values are converted to strings prior
to publishing. Objects and Arrays are JSON encoded. If omitted an empty
payload is sent.
- `qos`: QOS level to use when publishing the topic. Must be an integer value
from 0 to 2. If omitted the system configured default is used.
- `retain`: If set to `true` the MQTT broker will retain the payload of this
request. Note that only the mostly recently tagged payload is retained.
When other clients first subscribe to the topic they immediately recieve the
retained message. The default is `false`.
- `timeout`: A float value in seconds. By default requests with QoS levels of
1 or 2 will block until the Broker acknowledges confirmation. This option
applies a timeout to the request, returning a 504 error if the timeout is
exceeded. Note that the topic will still be published if the QoS level is 1
or 2.
!!! tip
To clear a retained value of a topic, publish the topic with an empty
payload and `retain` set to `true`.
Returns:
The published topic:
```json
{
"topic": "home/test/pub"
}
```
#### Subscribe to a topic
HTTP request:
```http
POST /server/mqtt/subscribe
Content-Type: application/json
{
"topic": "home/test/sub",
"qos": 0,
"timeout": 5
}
```
JSON-RPC request:
```json
{
"jsonrpc": "2.0",
"method":"server.mqtt.subscribe",
"params":{
"topic": "home/test/sub",
"qos": 0,
"timeout": 5
},
"id": 4564
}
```
Only the `topic` parameter is required. Below is an explanation for
each paramater:
- `topic`: The topic to subscribe. Note that wildcards may not be used.
- `qos`: QOS level to use when subscribing to the topic. Must be an integer
value from 0 to 2. If omitted the system configured default is used.
- `timeout`: A float value in seconds. By default requests will block
indefinitely until a response is received. This option applies a timeout to
the request, returning a 504 error if the timeout is exceeded. The
subscription will be removed after a timeout.
!!! note
If the topic was previously published with a retained payload this request
will return with the retained value.
Returns:
The subscribed topic and its payload:
```json
{
"topic": "home/test/pub",
"payload": "test"
}
```
If the payload is json encodable it will be returned as an object or array.
Otherwise it will be a string.
### Websocket notifications
Printer generated events are sent over the websocket as JSON-RPC 2.0
notifications. These notifications are sent to all connected clients