QIDI moonraker

This commit is contained in:
Rainboooom
2023-06-15 12:58:13 +08:00
parent 74b5950fff
commit 1006bcb85e
105 changed files with 39954 additions and 0 deletions

376
docs/api_changes.md Normal file
View File

@@ -0,0 +1,376 @@
##
This document keeps a record of all changes to Moonraker's web APIs.
### March 4th 2022
- Moonraker API Version 1.0.1
- The `server.websocket.id` endpoint has been deprecated. It is
recommended to use `server.connection.idenitfy` method to identify
your client. This method returns a `connection_id` which is
the websocket's unique id. See
[the documentation](web_api.md#identify-connection) for details.
### May 8th 2021
- The `file_manager` has been refactored to support system file
file events through `inotify`. Only mutable `roots` are monitored,
(currently `gcodes` and `config`). Subfolders within these
these roots are also monitored, however hidden folders are not.
The following changes API changes have been made to acccommodate
this functionality:
- The `notify_filelist_changed` actions have changed. The new
actions are as follows:
- `create_file`: sent when a new file has been created. This
includes file uploads and copied files.
- `create_dir`: sent when a new directory has been created.
- `delete_file`: sent when a file has been deleted.
- `delete_dir`: sent when a directory has been deleted.
- `move_file`: sent when a file has moved.
- `move_dir`: sent when a directory has moved.
- `modify_file`: sent when an existing file has been modified
- `root_update`: sent when a root directory location has been set.
For example, if a user changes the gcode path in Klipper, this
action is sent with a `notify_filelist_changed` notification.
- File list notifications for gcode files are now only sent after
all metadata has been processed. Likewise, requests to copy,
move, or upload a file will only return after metadata has been
processed. Notifications are synced with requests so that the
request should always return before the notification is sent.
- Thumbnails are now stored in the `.thumbs` directory to prevent
changes to thumbnails from emitting filelist notications. This
change will be reflected in the metadata's `relative_path` field,
so clients that use this field should not need to take additional
action. Note that existing thumbnails will remain in the `thumbs`
directory and filelist notifications will be sent for changes to
these thumbnails.
- The `notify_metadata_update` notification has been removed Clients
- can reliably expect metadata to be available for new or moved gcode
files when a request returns.
- The return values for several endpoints have been updated. They
now contain information similar to that which is pushed by the
`notify_filelist_changed` notification.
- The deprecated `data` field in gcode metadata has been removed.
The `size` field now returns the size of the `.png` file.
### March 15th 2021
- The `data` field for gcode thumbnails is now deprecated and will
be removed in the near future. Thumbnails are now saved to png
files in a `thumbs` directory relative to a gcode file's location.
This path is available in the `relative_path` field for each
thumbnail entry in the metadata.
### January 31st 2021
- The `GET /server/temperature_store` endpoint now only returns fields
that each sensor reports. For example, if a particuarly temperature
sensor does not report "target" or "power", then the corresponding
fields will not be reported for that sensor in response to the
`temperature_store` request.
### January 22nd 2021
- The `POST /machine/update/client` endpoint now requires a `name`
argument. This change added multiple client support
- The response to `GET /machine/update/status` no longer returns a
`client` field. Instead it will add fields matching the `name` of
each configured client. Keep in mind that the client object could
have a different set of fields depending on the type of a client. The
easy way to check for this is to see if a `branch` field is present.
If so, this client is a `git repo`. Otherwise it is a `web` client.
### January 4th 2021
- A `notify_update_refreshed` notification has been added. Moonraker now
auto-refreshes the update status at roughly a 2 hour interval. When
an auto-refresh is complete this notification is broadcast. Included
is an object that matches the response from `/machine/update/status`.
- The behavior of some of the `update_manager` APIs has changed:
- The `refresh` argument for `/machine/update/status` is now more
of a suggestion than a rule. If an update or a print is in
progress then the request will ignore the refresh argument
and immediately return the current status. Generally speaking requesting
a refresh should not be necessary with addition of auto refresh.
- The update requests (ie `/machine/update/klipper`) will now return
an error if a print is in progress. If the requested update is in
progress then the request will return valid with a message stating
that the update is in progress. If another object is being updated
then the request will be queued and block until it its complete.
### January 1st 2021
- A `notify_klippy_shutdown` websocket notification has been added
### December 30th 2020
- Some additional fields are now reported in the response to
`GET /machine/update/status`.
### November 28th 2020
- The following new endpoints are available when the `[update_manager]`
section has been configured:
- `GET /machine/update/status`
- `POST /machine/update/moonraker`
- `POST /machine/update/klipper`
- `POST /machine/update/client`
- `POST /machine/update/system`
- The following endpoint has been added and is available as part of the
core API:
- `POST /machine/services/restart`
See [web_api.md](web_api.md) for details on these new endpoints.
### November 23rd 2020
- Moonraker now serves Klipper's "docs" directory. This can be access
at `GET /server/files/docs/<filename>`.
### November 19th 2020
- The path for the power APIs has changed from `gpio_power` to `device_power`:
- `GET /machine/device_power/devices`\
`{"jsonrpc":"2.0","method":"machine.device_power.devices","id":"1"}`\
Returns an array of objects listing all detected devices.
Each object in the array is guaranteed to have the following
fields:
- `device`: The device name
- `status`: May be "init", "on", "off", or "error"
- `type`: May be "gpio" or "tplink_smartplug"
- `GET /machine/device_power/status?dev_name`\
`{"jsonrpc":"2.0","method":"machine.device_power.status","id":"1",
"params":{"dev_name":null}}`\
It is no longer possible to call this method with no arguments.
Status will only be returned for the requested device, to get
status of all devices use `/machine/device_power/devices`. As
before, this returns an object in the format of
`{device_name: status}`, where device_name is the name of the device
and `status` is the devices current status.
- `POST /machine/device_power/on?dev_name`\
`{"jsonrpc":"2.0","method":"machine.device_power.on","id":"1",
"params":{"dev_name":null}}`\
Toggles device on. Returns the current status of the device.
- `POST /machine/device_power/off?dev_name`\
`{"jsonrpc":"2.0","method":"machine.device_power.off","id":"1",
"params":{"dev_name":null}}`\
Toggles device off. Returns the current status of the device.
- The `notify_power_changed` notification now includes an object
containing device info, matching that which would be recieved
from a single item in `/machine/power/devices`.
### November 12th 2020
- Two new fields have been added to the gcode metadata:
- `gcode_start_byte`: Indicates the byte position in the
file where the first "Gxx" or "Mxx" command is detected.
- `gcode_end_byte`: Indicates the byte position in the
file where the last "Gxx" or "Mxx" command is detected.
These fields may be used to more accurately predict print
progress based on the file size.
### November 11th 2020
- The `server.websocket.id` API has been added. This returns a
unique ID that Moonraker uses to track each client connection.
As such, this API is only available over the websocket, there
is no complementary HTTP request.
- All HTTP API request may now include arguments in either the
query string or in the request's body.
- Subscriptions are now managed on a per connection basis. Each
connection will only recieve updates for objects in which they
are currently subscribed. If an "empty" request is sent, the
subscription will be cancelled.
- The `POST /printer/object/subscribe` now requires a
`connection_id` argument. This is used to identify which
connection's associated subscription should be updated.
Currenlty subscriptions are only supported over the a
websocket connection, one may use the id received from
`server.websocket.id`.
- The `notify_klippy_ready` websocket notification has been
added.
### November 2nd 2020
- The `GET /server/files/directory` endpoint now accepts a new
optional argument, `extended`. If `extended=true`, then
the data returned for gcode files will also include extracted
metadata if it exists.
### October 25th 2020
- The `modified` field reported for files and directories is no
longer represented as a string. It is now a floating point
value representing unix time (in seconds). This can be used
to display the "last modified date" based on the client's
timezone.
### October 21st 2020
- The `/server/gcode_store` endpoint no longer returns a string
in the result's `gcode_store` field. It now returns an
Array of objects, each object containing `message` and `time`
fields. The time refers to a timestamp in unix time (seconds),
and may be used to determine when the gcode store received the
accompanying `message`.
### September 30th 2020
- Two new endpoints have been added:
- `GET /server/info` (`server.info`)
- `GET /server/gcode_store` (`server.gcode_store`)
See web_api.md for details on their usage.
### September 7th 2020
- A new websocket API has been added, `server.files.delete_file`:
```
{jsonrpc: "2.0", method: "server.files.delete_file", params:
{path: "<root>/<file_name>"}, id: <request id>}
```
Where <root> is either "gcodes" or "config", and <file_name> is
the relative path to the file for deletion. For example:
`path: "gcodes/my_sub_dir/my_gcode_file.gcode"`
### September 3rd 2020
- The Websocket APIs have changed for clarity. The APIs methods now
use namespaces similar to those found in common programming languages.
This change affects all websocket APIs, however websocket events have
not changed. Below is a chart mapping the Previous API to the New API:
| Previous Websocket Method | New Websocket Method |
|---------------------------|----------------------|
| get_printer_info | printer.info |
| post_printer_emergency_stop | printer.emergency_stop |
| post_printer_restart | printer.restart |
| post_printer_firmware_restart | printer.firmware_restart |
| get_printer_objects_list | printer.objects.list |
| get_printer_objects_query | printer.objects.query |
| post_printer_objects_subscribe | printer.objects.subscribe |
| get_printer_query_endstops_status | printer.query_endstops.status |
| post_printer_gcode_script | printer.gcode.script |
| get_printer_gcode_help | printer.gcode.help |
| post_printer_print_start | printer.print.start |
| post_printer_print_pause | printer.print.pause |
| post_printer_print_resume | printer.print.resume |
| post_printer_print_cancel | printer.print.cancel |
| post_machine_reboot | machine.reboot |
| post_machine_shutdown | machine.shutdown |
| get_server_temperature_store | server.temperature_store |
| get_file_list | server.files.list |
| get_file_metadata | server.files.metadata |
| get_directory | server.files.get_directory |
| post_directory | server.files.post_directory |
| delete_directory | server.files.delete_directory |
| post_file_move | server.files.move |
| post_file_copy | server.files.copy |
- The "power" plugin APIs have changed. This affects both HTTP and
Websocket APIs. They were originally added to the "/printer" path,
however this adds the possibility of a naming conflict. The new
APIs are as follows:
- `GET /machine/gpio_power/devices` : `machine.gpio_power.devices`
- `GET /machine/gpio_power/status` : `machine.gpio_power.status`
- `POST /machine/gpio_power/on` : `machine.gpio_power.on`
- `POST /machine/gpio_power/off` : `machine.gpio_power.off`
### September 1st 2020
- A new notification has been added: `notify_metdata_update`. This
notification is sent when Moonraker parses metdata from a new upload.
Note that the upload must be made via the API, files manually (using
SAMBA, SCP, etc) do not trigger a notification. The notification is
sent in the following format:
```
{jsonrpc: "2.0", method: "notify_metadata_update", params: [metadata]}
```
Where `metadata` is an object in the following format:
```json
{
filename: "file name",
size: <file size>,
modified: "last modified date",
slicer: "Slicer Name",
first_layer_height: <in mm>,
layer_height: <in mm>,
object_height: <in mm>,
estimated_time: <time in seconds>,
filament_total: <in mm>,
thumbnails: [
{
width: <in pixels>,
height: <in pixels>,
size: <length of string>,
data: <base64 string>
}, ...
]
}
```
### August 16th 2020
- The structure of data returned from `/printer/info` (`get_printer_info`)
has changed to the following format:
```json
{
state: "<klippy state>",
state_message: "<current state message>",
hostname: "<hostname>",
software_version: "<version>",
cpu_info: "<cpu_info>",
klipper_path: "<moonraker use only>",
python_path: "<moonraker use only>",
log_file: "<moonraker use only>",
config_file: "<moonraker use only>",
}
```
The "state" item can be one of the following:
- "startup" - Klippy is in the process of starting up
- "ready" - Klippy is ready
- "shutdown" - Klippy has shutdown
- "error" - Klippy has experienced an error during startup
The message from each state can be found in the `state_message`.
- A `webhooks` printer object has been added, available for subscription or
query. It includes the following items:
- `state` - Printer state identical to that returned from `/printer/info`
- `state_message` - identical to that returned from `/printer/info`
- `/printer/objects/status` (`get_printer_objects_status`) has been renamed to
`/printer/objects/query` (`get_printer_objects_query`). The format of the
websocket request has changed, it should now look like the following:
```json
{
jsonrpc: "2.0",
method: "get_printer_objects_query",
params: {
objects: {
gcode: null,
toolhead: ["position", "status"]
}
},
id: <request id>
}
```
As shown above, printer objects are now wrapped in an "objects" parameter.
When a client wishes to subscribe to all items of a printer object, they
should now be set to `null` rather than an empty array.
The return value has also changed:
```json
{
eventtime: <klippy time of update>,
status: {
gcode: {
busy: true,
gcode_position: [0, 0, 0 ,0],
...},
toolhead: {
position: [0, 0, 0, 0],
status: "Ready",
...},
...}
}
```
The `status` item now contains the requested status.
- `/printer/objects/subscription` (`post_printer_objects_subscription`) is now
`printer/objects/subscribe` (`post_printer_objects_subscribe`). This
request takes parameters in the same format as the `query`. It now returns
state for all currently subscribed objects (in the same format as a `query`).
This data can be used to initialize all local state after the request
completes.
- Subscriptions are now pushed as "diffs". Clients will only recieve updates
for subscribed items when that data changes. This requires that clients
initialize their local state with the data returned from the subscription
request.
- The structure of data returned from `/printer/objects/list` has changed. It
now returns an array of available printer objects:
```json
{ objects: ["gcode", "toolhead", "bed_mesh", "configfile",....]}
```
- The `notify_klippy_state_changed` notification has been removed. Clients
can subscribe to `webhooks` and use `webhooks.state` to be notified of
transitions to the "ready" and "shutdown" states
- A `notify_klippy_disconnected` event has been added to notify clients
when the connection between Klippy and Moonraker has been terminated.
This event is sent with no parameters:
```json
{jsonrpc: "2.0", method: "notify_klippy_disconnected"}
```

365
docs/components.md Normal file
View File

@@ -0,0 +1,365 @@
## Components
Components in Moonraker are used to extend Moonraker's functionality,
similar to "extras" in Klipper. Moonraker divides components into
two categories, "core" components and "optional" components. A core
component gets its configuration from the `[server]` section and is
loaded when Moonraker starts. For example, the `file_manager` is a
core component. If a core component fails to load Moonraker will
exit with an error.
Optional components must be configured in `moonraker.conf`. If they
have no specific configuration, a bare section, such as `[octoprint_compat]`
must be present in `moonraker.conf`. Unlike with core components,
Moonraker will still start if an optional component fails to load.
Its failed status will be available for clients to query and present
to the user.
### Basic Example
Components exist in the `components` directory. The below example
shows how an `example.py` component might look:
```python
# Example Component
#
# Copyright (C) 2021 Eric Callahan <arksine.code@gmail.com>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
class Example:
def __init__(self, config):
self.server = config.get_server()
self.name = config.get_name()
# Raises an error if "example_int_option" is not configured in
# the [example] section
self.example_int_opt = config.getint("example_int_option")
# Returns a NoneType if "example_float_option is not configured
# in the config
self.example_float_opt = config.getfloat("example_float_option", None)
self.server.register_endpoint("/server/example", ['GET'],
self._handle_example_request)
async def request_some_klippy_state(self):
klippy_apis = self.server.lookup_component('klippy_apis')
return await klippy_apis.query_objects({'print_stats': None})
async def _handle_example_request(self, web_request):
web_request.get_int("required_reqest_param")
web_request.get_float("optional_request_param", None)
state = await self.request_some_klippy_state()
return {"example_return_value": state}
def load_component(config):
return Example(config)
```
If you have created a "Klippy extras" module then the above should look
look familiar. Moonraker attempts to use similar method for adding
extensions, making easier Klipper contributors to add new functionality
to Moonraker. Be aware that there is no "Reactor" object in Moonraker,
it uses `asyncio` for coroutines. Like Klippy, you should not write
code that blocks the main thread.
### The ConfigHelper Object
As shown above, each component is passed a config object. This object
will be a `ConfigHelper` type, which is an object that wraps a
configuration section to simply access to the native `ConfigParser`.
A `ConfigHelper` should never be directly instantiated.
#### *ConfigHelper.get_server()*
Returns the primary [server](#the-server-object) instance.
#### *ConfigHelper.get_name()*
Returns the configuration section name associated with this `ConfigHelper`.
#### *ConfigHelper.get(option_name, default=Sentinel)*
Returns the value of the option`option_name` as a string. If
the option does not exist, returns `default`. If `default` is
not provided raises a `ConfigError`.
#### *ConfigHelper.getint(option_name, default=Sentinel)*
Returns the value of the option`option_name` as an integer. If
the option does not exist, returns `default`. If `default` is
not provided raises a `ConfigError`.
#### *ConfigHelper.getfloat(option_name, default=Sentinel)*
Returns the value of the option`option_name` as a float. If
the option does not exist, returns `default`. If `default` is
not provided raises a `ConfigError`.
#### *ConfigHelper.getboolean(option_name, default=Sentinel)*
Returns the value of the option`option_name` as a boolean. If
the option does not exist, returns `default`. If `default` is
not provided raises a `ConfigError`.
#### *ConfigHelper.has_section(section_name)*
Returns True if a section matching `section_name` is in the configuration,
otherwise False.
Note that a ConfigHelper object also implements `__contains__`,
which is an alias for `has_section`, ie: `section_name in config_instance`
#### *ConfigHelper.getsection(section_name)*
Returns a Config object for the section matching `section_name`. If the
section does not exist in the configuration raises a `ConfigError`.
Note that a ConfigHelper object also implements `__getitem__`,
which is an alias for `get_section`, ie: `config_instance[section_name]`
#### *ConfigHelper.get_options()*
Returns a dict mapping options to values for all options in the Config
object.
#### *ConfigHelper.get_prefix_sections(prefix)*
Returns a list section names in the configuration that start with `prefix`.
These strings can be used to retreve ConfigHelpers via
[get_section()](#confighelpergetsectionsection_name).
### The Server Object
The server instance represents the central management object in Moonraker.
It can be used to register endpoints, register notifications, look up other
components, send events, and more.
#### *Server.lookup_component(component_name, default=Sentinel)*
Attempts to look up a loaded component, returning the result. If
the component has not been loaded, `default` will be returned.
If `default` is not provided a `ServerError` will be raised.
#### *Server.load_component(config, component_name, default=Sentinel)*
Attempts to load an uninitialized component and returns the result. It is
only valid to call this within a a component's `__init__()` method, and
should only be necessary if one optional component relies on another. Core components will always be loaded before optional components, thus an optional
component may always call
[lookup_component()](#serverlookup_componentcomponent_name-defaultsentinel)
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, transports=["http", "websocket", "mqtt"], wrap_result=True)*
Registers the supplied `uri` with the server.
The `request_methods` argument should be a list of strings containing any
combination of `GET`, `POST`, and `DELETE`.
The `callback` is executed when a request matching the `uri` and a
`request_method` is received. The callback function will be passed a
`WebRequest` object with details about the request. This function
should be able of handling each registered `request_method`. The
provided callback must be a coroutine.
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)
```
would register a JSON-RPC method like:
```
server.example
```
However, if multiple requests methods are supplied, the generated JSON-RPC
methods will differ:
```python
self.server.register_endpoint("/server/example", ["GET", "POST", "DELETE"],
self._handle_request)
```
would register:
```
server.get_example
server.post_example
server.delete_example
```
The `wrap_result` argument applies only to the `http` protocol. In Moonraker
all http requests return a result with a JSON body. By default, the value returned
by a `callback` is wrapped in a dict:
```python
{"result": return_value}
```
It is only necessary to set this to false if you need to return a body that
does not match this result. For example, the `[octoprint_compat]` component
uses this functionality to return results in a format that match what
OctoPrint itself would return.
#### *Server.register_event_handler(event, callback)*
Registers the provided `callback` method to be executed when the
provided `event` is sent. The callback may be a coroutine, however it
is not required.
#### *Server.send_event(event, \*args)*
Emits the event named `event`, calling all callbacks registered to the
event. All positional arguments in `*args` will be passed to each
callback. Event names should be in the form of
`"module_name:event_description"`.
#### *Server.register_notification(event_name, notify_name=None)*
Registers a websocket notification to be pushed when `event_name`
is emitted. By default JSON-RPC notifcation sent will be in the form of
`notify_{event_description}`. For example, when the server sends the
`server:klippy_connected` event, the JSON_RPC notification will be
`notify_klippy_connected`.
If a `notify_name` is provided it will override the `{event_description}`
extracted from the `event_name`. For example, if the `notify_name="kconnect`
were specfied when registering the `server:klippy_connected` event, the
websocket would emit a `notify_kconnect` notification.
#### *Server.get_host_info()*
Returns a tuple of the current host name of the PC and the port Moonraker
is serving on.
#### *Server.get_klippy_info()*
Returns a dict containing the values from the most recent `info` request to
Klippy. If Klippy has never connected this will be an empty dict.
### The WebRequest Object
All callbacks registered with the
[register_endpoint()](#serverregister_endpointuri-request_methods-callback-protocolhttp-websocket-wrap_resulttrue)
method are passed a WebRequest object when they are executed. This object
contains information about the request including its endpoint name and arguments
parsed from the request.
#### *WebRequest.get_endpoint()*
Returns the URI registered with this request, ie: `/server/example`.
#### *WebRequest.get_action()*
Returns the request action, which is synonomous with its HTTP request
method. Will be either `GET`, `POST`, or `DELETE`. This is useful
if your endpoint was registered with multiple request methods and
needs to handle each differently.
#### *WebRequest.get_connection()*
Returns the associated Websocket connection ID. This will be `None`
for HTTP requests when no associated websocket is connected to
the client.
#### *WebRequest.get_args()*
Returns a reference to the entire argument dictionary. Useful if
one request handler needs to preprocess the arguments before
passing the WebRequest on to another request handler.
#### *WebRequest.get(key, default=Sentinel)*
Returns the request argument at the provided `key`. If the key is not
present `default` will be returned. If `default` is not provided a
`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 `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 `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 `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 `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
or until the specified timeout has exceeded. Returns true if the connection
was successful established, or False on timeout. If no timeout is specified
then this method will block indefinitely until a connection has been
established.
#### *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.

2067
docs/configuration.md Normal file

File diff suppressed because it is too large Load Diff

128
docs/contributing.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributing to Moonraker
While Moonraker exists as a service independently from Klipper, it relies
on Klipper to be useful. Thus, the tentative plan is to eventually merge
the Moonraker application into the Klipper repo after Moonraker matures,
at which point this repo will be archived. As such, contibuting guidelines
are near those of Klipper:
#### New Module Contributions
All source files should begin with a copyright notice in the following format:
```python
# Module name and brief description of module
#
# Copyright (C) 2021 YOUR NAME <YOUR EMAIL ADDRESS>
#
# This file may be distributed under the terms of the GNU GPLv3 license
```
#### Git Commit Format
Commits should be contain one functional change. Changes that are unrelated
or independent should be broken up into multiple commits. It is acceptable
for a commit to contain multiple files if a change to one module depends on a
change to another (ie: changing the name of a method).
Avoid merge commits. If it is necessary to update a Pull Request from the
master branch use git's interactive rebase and force push.
Each Commit message should be in the following format:
```text
module: brief description of commit
More detailed explanation of the change if required
Signed-off-by: Your Name <your email address>
```
Where:
- `module`: is the name of the Python module you are changing or parent
folder if not applicable
- `Your Name`: Your real first and last name
- `<your email address>`: A real, reachable email address
For example, the git log of a new `power.py` device implementation might look
like the following:
```git
power: add support for mqtt devices
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
```
```git
docs: add mqtt power device documentation
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
```
By signing off on commits, you acknowledge that you agree to the
[developer certificate of origin](../developer-certificate-of-origin)
shown below. As mentioned above, your signature must contain your
real name and a current email address.
```text
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
#### Code Style
Python methods should be fully annotated. Variables should be annotated where
the type cannot be inferred. Moonraker uses the `mypy` static type checker for
code validation with the following options:
- `--ignore-missing-imports`
- `--follow-imports=silent`
No line in the source code should exceed 80 characters. Be sure there is no
trailing whitespace. To validate code before submission one may use
`pycodestyle` with the following options:
- `--ignore=E226,E301,E302,E303,W503,W504`
- `--max-line-length=80`
- `--max-doc-length=80`
Generally speaking, each line in submitted documentation should also be no
longer than 80 characters, however there are situations where this isn't
possible, such as long hyperlinks or example return values. Documentation
isn't linted, so it
Don't peek into the member variables of another class. Use getters or
properties to access object state.

350
docs/dev_changelog.md Normal file
View File

@@ -0,0 +1,350 @@
### Moonraker Version 0.1 - August 11 2020
- It is no longer possible to configure the subscription timer. All subscribed
objects will update at an interval of 250ms.
- Request timeout configuration has been removed. The server will no longer
apply a timeout to requests. Any requests pending when Klippy disconnects
will be aborted with an error. All pending requests are logged each minute.
- The RESET_SD gcode is now SDCARD_RESET_FILE
- The "virtual_sdcard" object has removed the following items:
- "filename"
- "total_duration"
- "print_duration"
- "filament_used"
- A new object, "print_stats", has been added. It reports the following items:
- "filename"
- "total_duration"
- "print_duration"
- "filament_used"
- "state" - can be one of the following:
- "standby" - sd print not in progress
- "printing" - print in progress
- "paused" - print paused
- "error" - print experienced an error
- "complete" - print complete
- "message" - contains error message when state is "error"
- The behavior of print_stats is slightly different. When a print is finished the stats are
not cleared. They will remain populated with the final data until the user issues a
SDCARD_RESET_FILE gcode.
- Moonraker Configuration has moved to moonraker.conf
- Klippy now hosts the Unix Domain Socket. As a result, the order in which the
Klipper and Moonraker services are started no longer matters.
- The `notify_filelist_changed` event has been refactored for clarity. It now
returns a result in the following format:
```json
{
action: "<action>",
item: {
path: "<file or directory path>",
root: "<root_name>",
size: <file size>,
modified: "<date modified>"
},
source_item: {
path: "<file or directory path>",
root: "<root_name>"
}
}
```
Note that the `source_item` is only present for `move_item` and `copy_item`
actions. Below is a list of all available actions:
- `upload_file`
- `delete_file`
- `create_dir`
- `delete_dir`
- `move_item`
- `copy_item`
### Moonraker Version .08-alpha - 7/2/2020
- Moonraker has moved to its own repo.
- Python 3 support has been added.
- API Key management has moved from Klippy to Moonraker
- File Management has moved from Klippy to Moonraker. All static files are now
located in the the `/server/files` root path:
- klippy.log - `/server/files/klippy.log`
- moonraker.log - `/server/files/moonraker.log`
- gcode files - `/server/files/gcodes/(.*)`
Note that the new file manager will be capable of serving and listing files
in directories aside from "gcodes".
- Added basic plugin support
- Added metadata support for SuperSlicer
- Added thumbnail extraction from SuperSlicer and PrusaSlicer gcode files
- For status requests, `virtual_sdcard.current_file` has been renamed to
`virtual_sdcard.filename`
- Clients should not send `M112` via gcode to execute an emegency shutdown.
They should instead use the new API which exposes this functionality.
- New APIs:
- `POST /printer/emergency_stop` - `post_printer_emergency_stop`
- `GET /server/files/metadata` - `get_file_metadata`
- `GET /server/files/directory`
- `POST /server/files/directory`
- `DELETE /server/files/directory`
- The following API changes have been made:
| Previous URI | New URI | Previous JSON_RPC method | New JSON_RPC method |
|--------------|---------|--------------------------| --------------------|
| GET /printer/objects | GET /printer/objects/list | get_printer_objects | get_printer_objects_list |
| GET /printer/subscriptions | GET /printer/objects/subscription | get_printer_subscriptions | get_printer_objects_subscription |
| POST /printer/subscriptions | POST /printer/objects/subscription | post_printer_subscriptions | post_printer_objects_subscription |
| GET /printer/status | GET /printer/objects/status | get_printer_status | get_printer_objects_status |
| POST /printer/gcode | POST /printer/gcode/script | post_printer_gcode | post_printer_gcode_script |
| GET /printer/klippy.log | GET /server/files/klippy.log | | |
| GET /server/moonraker.log | GET /server/files/moonraker.log | | |
| GET /printer/files | GET /server/files/list | get_printer_files | get_file_list |
| POST /printer/files/upload | POST /server/files/upload | | |
| GET /printer/files/<filename> | GET /server/files/gcodes/<filename> | | |
| DELETE /printer/files/<filename> | DELETE /server/files/<filename> | | |
| GET /printer/endstops | GET /printer/query_endstops/status | get_printer_endstops | get_printer_query_endstops_status |
### Moonraker Version .07-alpha - 5/7/2020
- The server process is no longer managed directly by Klippy. It has moved
into its own process dubbed Moonraker. Please see README.md for
installation instructions.
- API Changes:
- `/printer/temperature_store` is now `/server/temperature_store`, or
`get_server_temperature_store` via the websocket
- `/printer/log` is now `/printer/klippy.log`
- `/server/moonraker.log` has been added to fetch the server's log file
- Klippy Changes:
- The remote_api directory has been removed. There is now a single
remote_api.py module that handles server configuration.
- webhooks.py has been changed to handle communications with the server
- klippy.py has been changed to pass itself to webhooks
- file_manager.py has been changed to specifiy the correct status code
when an error is generated attempting to upload or delete a file
- The nginx configuration will need the following additional section:
```
location /server {
proxy_pass http://apiserver/server;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
}
```
### Version .06-alpha - 5/4/2020
- Add `/machine/reboot` and `/machine/shutdown` endpoints. These may be used
to reboot or shutdown the host machine
- Fix issue where websocket was blocked on long transactions, resulting in the
connection being closed
- Log all client requests over the websocket
- Add `/printer/temperature_store` endpoint. Clients may use this to fetch
stored temperature data. By default the store for each temperature sensor
is updated every 1s, with the store holding 20 minutes of data.
### Version .05-alpha - 04/23/2020
- The `[web_server]` module has been renamed to `[remote_api]`. Please update
printer.cfg accordingly
- Static files no longer served by the API server. As a result, there is
no `web_path` option in `[remote_api]`.
- The server process now now forwards logging requests back to the Klippy
Host, thus all logging is done in klippy.log. The temporary endpoint serving
klippy_server.log has been removed.
- `/printer/info` now includes two additional keys:
- `error_detected` - Boolean value set to true if a host error has been
detected
- `message` - The current Klippy State message. If an error is detected this
message may be presented to the user. This is the same message returned
when by the STATUS gcode.
- The server process is now launched immediately after the config file is read.
This allows the client limited access to Klippy in the event of a startup
error, assuming the config file was successfully parsed and the
`remote_api` configuration section is valid. Note that when the server is
initally launched not all endpoints will be available. The following
endponts are guaranteed when the server is launched:
- `/websocket`
- `/printer/info`
- `/printer/restart`
- `/printer/firmware_restart`
- `/printer/log`
- `/printer/gcode`
- `/access/api_key`
- `/access/oneshot_token`
The following startup sequence is recommened for clients which make use of
the websocket:
- Attempt to connect to `/websocket` until successful
- Once connected, query `/printer/info` for the ready status. If not ready
check `error_detected`. If not ready and no error, continue querying on
a timer until the printer is either ready or an error is detected.
- After the printer has identified itself as ready make subscription requests,
get the current file list, etc
- If the websocket disconnects the client can assume that the server is shutdown.
It should consider the printer's state to be NOT ready and try reconnecting to
the websocket until successful.
### Version .04-alpha - 04/20/2020
- Add `/printer/gcode/help` endpoint to gcode.py
- Allow the clients to fetch .json files in the root web directory
- Add support for detailed print tracking to virtual_sdcard.py. This
includes filament usage and print time tracking
- Add new file_manager.py module for advanced gcode file management. Gcode
files may exist in subdirectories. This module also supports extracting
metadata from gcode files.
- Clean up API registration. All endpoints are now registered by Klippy
host modules outside of static files and `/api/version`, which is used for
compatibility with OctoPrint's file upload API.
- The server now runs in its own process. Communication between the Host and
the server is done over a duplex pipe. Currently this results in a second
log file being generated specifically for the server at
`/tmp/klippy_server.log`. This is likely a temporary solution, and as such
a temporary endpoint has been added at `/printer/klippy_server.log`. Users
can use the browser to download the log by navigating to
`http://<host>/printer/klippy_server.log`.
### Version .03-alpha - 03/09/2020
- Require that the configured port be above 1024.
- Fix hard crash if the webserver fails to start.
- Fix file uploads with names containing whitespace
- Serve static files based on their relative directory, ie a request
for "/js/main.js" will now look for the files in "<web_path>/js/main.js".
- Fix bug in CORS where DELETE requests raised an exception
- Disable the server when running Klippy in batch mode
- The the `/printer/cancel`, `/printer/pause` and `/printer/resume` gcodes
are now registed by the pause_resume module. This results in the following
changes:
- The `cancel_gcode`, `pause_gcode`, and `resume_gcode` options have
been removed from the [web_server] section.
- The `/printer/pause` and `/printer/resume` endpoints will run the "PAUSE"
and "RESUME" gcodes respectively. These gcodes can be overridden by a
gcode_macro to run custom PAUSE and RESUME commands. For example:
```
[gcode_macro PAUSE]
rename_existing: BASE_PAUSE
gcode:
{% if not printer.pause_resume.is_paused %}
M600
{% endif %}
[gcode_macro M600]
default_parameter_X: 50
default_parameter_Y: 0
default_parameter_Z: 10
gcode:
SET_IDLE_TIMEOUT TIMEOUT=18000
{% if not printer.pause_resume.is_paused %}
BASE_PAUSE
{% endif %}
G1 E-.8 F2700
G91
G1 Z{Z}
G90
G1 X{X} Y{Y} F3000
```
If you are calling "PAUSE" in any other macro of config section, please
remember that it will execute the macro. If that is not your intention,
change "PAUSE" in those sections to the renamed version, in the example
above it is BASE_PAUSE.
- The cancel endpoint runs a "CANCEL_PRINT" gcode. Users will need to
define their own gcode macro for this
- Remove "notify_paused_state_changed" and "notify_printer_state_changed"
events. The data from these events can be fetched via status
subscriptions.
- "idle_timeout" and "pause_resume" now default to tier 1 status updates,
which sets their default refresh time is 250ms.
- Some additional status attributes have been added to virtual_sdcard.py. At
the moment they are experimental and subject to change:
- 'is_active' - returns true when the virtual_sdcard is processing. Note
that this will return false when the printer is paused
- 'current_file' - The name of the currently loaded file. If no file is
loaded returns an empty string.
- 'print_duration' - The approximate duration (in seconds) of the current
print. This value does not include time spent paused. Returns 0 when
no file is loaded.
- 'total_duration' - The total duration of the current print, including time
spent paused. This can be useful for approximating the local time the
print started Returns 0 when no file is loaded.
- 'filament_used' - The approximate amount of filament used. This does not
include changes to flow rate. Returns 0 when no file is loaded.
- 'file_position' - The current position (in bytes) of the loaded file
Returns 0 when no file is loaded.
- 'progress' - This attribute already exists, however it has been changed
to retain its value while the print is paused. Previously it would reset
to 0 when paused. Returns 0 when no file is loaded.
### Version .02-alpha - 02/27/2020
- Migrated Framework and Server from Bottle/Eventlet to Tornado. This
resolves an issue where the server hangs for a period of time if the
network connection abruptly drops.
- A `webhooks` host module has been created. Other modules can use this
the webhooks to register endpoints, even if the web_server is not
configured.
- Two modules have been renamed, subscription_handler.py is now
status_handler.py and ws_handler.py is now ws_manager.py. These names
more accurately reflect their current functionality.
- Tornado Websockets support string encoded frames. Thus it is no longer
necessary for clients to use a FileReader object to convert incoming
websocket data from a Blob into a String.
- The endpoint for querying endstops has changed from `GET
/printer/extras/endstops` to `GET /printer/endstops`
- Serveral API changes have been made to accomodate the addition of webhooks:
- `GET /printer/klippy_info` is now `GET /printer/info`. This endpoint no
longer returns host information, as that can be retrieved direct via the
`location` object in javascript. Instead it returns CPU information.
- `GET /printer/objects` is no longer used to accomodate multiple request
types by modifying the "Accept" headers. Each request has been broken
down in their their own endpoints:
- `GET /printer/objects` returns all available printer objects that may
be queried
- `GET /printer/status?gcode=gcode_position,speed&toolhead` returns the
status of the printer objects and attribtues
- `GET /printer/subscriptions` returns all printer objects that are current
being subscribed to along with their poll times
- `POST /printer/subscriptions?gcode&toolhead` requests that the printer
add the specified objects and attributes to the list of subscribed objects
- Requests that query the Klippy host with additional parameters can no
longer use variable paths. For example, `POST /printer/gcode/<gcode>` is no
longer valid. Parameters must be added to the query string. This currently
affects two endpoints:
- `POST /printer/gcode/<gcode>` is now `POST /printer/gcode?script=<gcode>`
- `POST printer/print/start/<filename>` is now
`POST /printer/print/start?filename=<filename>`
- The websocket API also required changes to accomodate dynamically registered
endpoints. Each method name is now generated from its comparable HTTP
request. The new method names are listed below:
| new method | old method |
|------------|------------|
| get_printer_files | get_file_list |
| get_printer_info | get_klippy_info |
| get_printer_objects | get_object_info |
| get_printer_subscriptions | get_subscribed |
| get_printer_status | get_status |
| post_printer_subscriptions | add_subscription |
| post_printer_gcode | run_gcode |
| post_printer_print_start | start_print |
| post_printer_print_pause | pause_print |
| post_printer_print_resume | resume_print |
| post_printer_print_cancel | cancel_print |
| post_printer_restart | restart |
| post_printer_firmware_restart | firmware_restart |
| get_printer_endstops | get_endstops |
- As with the http API, a change was necessary to the way arguments are send
along with the request. Webocket requests should now send "keyword
arguments" rather than "variable arguments". The test client has been
updated to reflect these changes, see main.js and json-rpc.js, specifically
the new method `call_method_with_kwargs`. For status requests this simply
means that it is no longer necessary to wrap the Object in an Array. The
gcode and start print requests now look for named parameters, ie:
- gcode requests - `{jsonrpc: "2.0", method: "post_printer_gcode",
params: {script: "M117 FooBar"}, id: <request id>}`
- start print - `{jsonrpc: "2.0", method: "post_printer_print_start",
params: {filename: "my_file.gcode"}, id:<request id>}`
### Version .01-alpha - 02/14/2020
- The api.py module has been refactored to contain the bottle application and
all routes within a class. Bottle is now imported and patched dynamically
within this class's constructor. This resolves an issue where the "request"
context was lost when the Klippy host restarts.
- Change the Websocket API to use the JSON-RPC 2.0 protocol. See the test
client (main.js and json-rpc.js) for an example client side implementation.
- Remove file transfer support from the websocket. Use the HTTP for all file
transfer requests.
- Add support for Klippy Host modules to register their own urls.
Query_endstops.py has been updated with an example. As a result of this
change, the endpoint for endstop query has been changed to
`/printer/extras/endstops`.
- Add support for "paused", "resumed", and "cleared" pause events.
- Add routes for downloading klippy.log, restart, and firmware_restart.
- Remove support for trailing slashes in HTTP API routes.
- Support "start print after upload" requests
- Add support for user configured request timeouts
- The test client has been updated to work with the new changes

View File

@@ -0,0 +1,37 @@
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.

View File

@@ -0,0 +1,2 @@
mkdocs==1.3.0
pymdown-extensions==9.1

View File

@@ -0,0 +1,106 @@
# Example Home Assistant configuration file for a Artillery Sidewinder X1
# Credit to GitHub users @Kruppes and @pedrolamas
# extended by @tispokes
camera:
- platform: generic
still_image_url: http://192.168.178.66/webcam/?action=snapshot
stream_source: http://192.168.178.66/webcam/?action=stream
framerate: 10
sensor:
- platform: rest
name: SWX1_sensor
resource: "http://192.168.178.66:7125/printer/objects/query?heater_bed&extruder&print_stats&toolhead&display_status&virtual_sdcard"
json_attributes_path: "$.result.status"
json_attributes:
- heater_bed
- extruder
- print_stats
- toolhead
- display_status
- virtual_sdcard
value_template: >-
{{ "OK" if ("result" in value_json) else "offline" }}
# Adding an API key is only necessary while using the [authorization] component
# and if Home Assistant is not a trusted client
headers:
x-api-key: 123456789abcdefghijklmno
- platform: template
sensors:
swx1_state:
unique_id: sensor.swx1_state
friendly_name: "Status"
icon_template: mdi:printer-3d
value_template: >-
{{ states.sensor.swx1_sensor.attributes['print_stats']['state'] if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_current_print:
unique_id: sensor.swx1_current_print
friendly_name: >-
{{ "Printed" if states.sensor.swx1_sensor.attributes['display_status']['progress'] == 1 else "Printing..." }}
icon_template: mdi:video-3d
value_template: >-
{{ states.sensor.swx1_sensor.attributes['print_stats']['filename'].split(".")[0] if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_current_progress:
unique_id: sensor.swx1_current_progress
friendly_name: "Progress"
unit_of_measurement: '%'
icon_template: mdi:file-percent
value_template: >-
{{ (states.sensor.swx1_sensor.attributes['display_status']['progress'] * 100) | round(1) if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_print_time:
unique_id: sensor.swx1_print_time
friendly_name: "T-elapsed"
icon_template: mdi:clock-start
value_template: >-
{{ states.sensor.swx1_sensor.attributes['print_stats']['print_duration'] | timestamp_custom("%H:%M:%S", 0) if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_time_remaining:
unique_id: sensor.swx1_time_remaining
friendly_name: "T-remaining"
icon_template: mdi:clock-end
value_template: >-
{{ (((states.sensor.swx1_sensor.attributes['print_stats']['print_duration'] / states.sensor.swx1_sensor.attributes['display_status']['progress'] - states.sensor.swx1_sensor.attributes['print_stats']['print_duration']) if states.sensor.swx1_sensor.attributes['display_status']['progress'] > 0 else 0) | timestamp_custom('%H:%M:%S', 0)) if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_eta:
unique_id: sensor.swx1_eta
friendly_name: "T-ETA"
icon_template: mdi:clock-outline
value_template: >-
{{ (as_timestamp(now()) + 2 * 60 * 60 + ((states.sensor.swx1_sensor.attributes['print_stats']['print_duration'] / states.sensor.swx1_sensor.attributes['display_status']['progress'] - states.sensor.swx1_sensor.attributes['print_stats']['print_duration']) if states.sensor.swx1_sensor.attributes['display_status']['progress'] > 0 else 0)) | timestamp_custom("%H:%M:%S", 0) if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_nozzletemp:
unique_id: sensor.swx1_nozzletemp
friendly_name: >-
Nozzle
{{ ["(shall ", (states.sensor.swx1_sensor.attributes['extruder']['target'] | float | round(1)), "°C)"] | join if states.sensor.swx1_sensor.attributes['display_status']['progress'] < 1 }}
icon_template: >-
{{ "mdi:printer-3d-nozzle-heat" if states.sensor.swx1_sensor.attributes['extruder']['target'] > 0 else "mdi:printer-3d-nozzle-heat-outline" }}
value_template: >-
{{ states.sensor.swx1_sensor.attributes['extruder']['temperature'] | float | round(1) if is_state('sensor.swx1_sensor', 'OK') else None }}
swx1_bedtemp:
unique_id: sensor.swx1_bedtemp
friendly_name: >-
Bed
{{ ["(shall ", (states.sensor.swx1_sensor.attributes['heater_bed']['target'] | float | round(1)), "°C)"] | join if states.sensor.swx1_sensor.attributes['display_status']['progress'] < 1 }}
icon_template: >-
{{ "mdi:radiator" if states.sensor.swx1_sensor.attributes['extruder']['target'] > 0 else "mdi:radiator-off" }}
value_template: >-
{{ states.sensor.swx1_sensor.attributes['heater_bed']['temperature'] | float | round(1) if is_state('sensor.swx1_sensor', 'OK') else None }}
# The following will allow you to control the power of devices configured in the "[power]" sections of moonraker
# Make sure to change the `Printer` name below to the device name on your configuration
#
switch:
- platform: rest
name: SWX1_power
resource: "http://192.168.178.66:7125/machine/device_power/device?device=SWX1"
body_on: '{"action": "on"}'
body_off: '{"action": "off"}'
headers:
Content-Type: 'application/json'
is_on_template: >-
{{ 'result' in value_json and (value_json.result.values() | list | first == "on") }}

View File

@@ -0,0 +1,111 @@
# Example Home Assistant configuration file for a Voron V0.
# Credit to GitHub users @Kruppes and @pedrolamas
#
sensor:
- platform: rest
name: Voron_V0_sensor
resource: "http://192.168.178.56:7125/printer/objects/query?heater_bed&extruder&print_stats&toolhead&display_status&virtual_sdcard"
json_attributes_path: "$.result.status"
json_attributes:
- heater_bed
- extruder
- print_stats
- toolhead
- display_status
- virtual_sdcard
value_template: >-
{{ 'OK' if ('result' in value_json) else None }}
# Adding an API key is only necessary while using the [authorization] component
# and if Home Assistant is not a trusted client
headers:
x-api-key: 123456789abcdefghijklmno
- platform: template
sensors:
vzero_hotend_target:
friendly_name: 'V0.126 Hotend Target'
device_class: temperature
unit_of_measurement: '°C'
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['extruder']['target'] | float | round(1) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_hotend_actual:
device_class: temperature
unit_of_measurement: '°C'
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['extruder']['temperature'] | float | round(1) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_bed_target:
device_class: temperature
unit_of_measurement: '°C'
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['heater_bed']['target'] | float | round(1) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_bed_actual:
device_class: temperature
unit_of_measurement: '°C'
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['heater_bed']['temperature'] | float | round(1) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_state:
icon_template: mdi:printer-3d
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['print_stats']['state'] if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_current_print:
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['print_stats']['filename'] if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_current_progress:
unit_of_measurement: '%'
icon_template: mdi:file-percent
value_template: >-
{{ (states.sensor.voron_v0_sensor.attributes['display_status']['progress'] * 100) | round(1) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_print_time:
icon_template: mdi:clock-start
value_template: >-
{{ states.sensor.voron_v0_sensor.attributes['print_stats']['print_duration'] | timestamp_custom("%H:%M:%S", 0) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_time_remaining:
icon_template: mdi:clock-end
value_template: >-
{{ (((states.sensor.voron_v0_sensor.attributes['print_stats']['print_duration'] / states.sensor.voron_v0_sensor.attributes['display_status']['progress'] - states.sensor.voron_v0_sensor.attributes['print_stats']['print_duration']) if states.sensor.voron_v0_sensor.attributes['display_status']['progress'] > 0 else 0) | timestamp_custom('%H:%M:%S', 0)) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_eta:
icon_template: mdi:clock-outline
value_template: >-
{{ (as_timestamp(now()) + 2 * 60 * 60 + ((states.sensor.voron_v0_sensor.attributes['print_stats']['print_duration'] / states.sensor.voron_v0_sensor.attributes['display_status']['progress'] - states.sensor.voron_v0_sensor.attributes['print_stats']['print_duration']) if states.sensor.voron_v0_sensor.attributes['display_status']['progress'] > 0 else 0)) | timestamp_custom("%H:%M:%S", 0) if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_nozzletemp:
icon_template: mdi:thermometer
value_template: >-
{{ [(states.sensor.voron_v0_sensor.attributes['extruder']['temperature'] | float | round(1) | string), " / ", (states.sensor.voron_v0_sensor.attributes['extruder']['target'] | float | round(1) | string)] | join if is_state('sensor.voron_v0_sensor', 'OK') else None }}
vzero_bedtemp:
icon_template: mdi:thermometer
value_template: >-
{{ [(states.sensor.voron_v0_sensor.attributes['heater_bed']['temperature'] | float | round(1) | string), " / ", (states.sensor.voron_v0_sensor.attributes['heater_bed']['target'] | float | round(1) | string)] | join if is_state('sensor.voron_v0_sensor', 'OK') else None }}
# The following will allow you to control the power of devices configured in the "[power]" sections of moonraker
# Make sure to change the `Printer` name below to the device name on your configuration
#
switch:
- platform: rest
name: Voron_V0_power
resource: "http://192.168.178.56:7125/machine/device_power/device?device=Printer"
body_on: '{"action": "on"}'
body_off: '{"action": "off"}'
headers:
Content-Type: 'application/json'
is_on_template: >-
{{ 'result' in value_json and (value_json.result.values() | list | first == "on") }}
# MJPEG camera can be exposed to HA
#
camera:
- platform: mjpeg
name: Voron_V0_camera
still_image_url: http://192.168.178.56/webcam/?action=snapshot
mjpeg_url: http://192.168.178.56/webcam/?action=stream

21
docs/index.md Normal file
View File

@@ -0,0 +1,21 @@
# Welcome to Moonraker Documentation
Moonraker is a Python 3 based web server that exposes APIs with which
client applications may use to interact with the 3D printing firmware
[Klipper](https://github.com/KevinOConnor/klipper). Communcation between
the Klippy host and Moonraker is done over a Unix Domain Socket. Tornado
is used to provide Moonraker's server functionality.
Users should refer to the [Installation](installation.md) and
[Configuration](configuration.md) sections for documentation on how
to install and configure Moonraker.
Client developers may refer to the [Client API](web_api.md)
documentation.
Backend developers should refer to the
[contibuting](contributing.md) section for basic contribution
guidelines prior to creating a pull request. The
[components](components.md) document provides a brief overview
of how to create a component and interact with Moonraker's
primary internal APIs.

342
docs/installation.md Normal file
View File

@@ -0,0 +1,342 @@
## Installation
This document provides a guide on how to install Moonraker on a Raspberry
Pi running Raspian/Rasperry Pi OS. Other SBCs and/or linux distributions
may work, however they may need a custom install script. Moonraker
requires Python 3.7 or greater, verify that your distribution's
Python 3 packages meet this requirement.
### Installing Klipper
Klipper should be installed prior to installing Moonraker. Please see
[Klipper's Documention](https://klipper3d.com/Overview.html) for details.
After installing Klipper you should make sure to add Moonraker's
[configuration requirements](#klipper-configuration-requirements).
### Klipper Configuration Requirements
Moonraker depends on the following Klippy extras for full functionality:
- `[virtual_sdcard]`
- `[pause_resume]`
- `[display_status]`
If you have a `[filament_switch_sensor]` configured then `[pause_resume]` will
automatically be loaded. Likewise, if you have a `[display]` configured then
`[display_status]` will be automatically loaded. If your configuration is
missing one or both, you can simply add the bare sections to `printer.cfg`:
```ini
[pause_resume]
[display_status]
[virtual_sdcard]
path: ~/gcode_files
```
### Enabling the Unix Socket
After Klipper is installed it may be necessary to modify its `defaults` file in
order to enable the Unix Domain Socket. Begin by opening the file in your
editor of choice, for example:
```
sudo nano /etc/default/klipper
```
You should see a file that looks something like the following:
```
# Configuration for /etc/init.d/klipper
KLIPPY_USER=pi
KLIPPY_EXEC=/home/pi/klippy-env/bin/python
KLIPPY_ARGS="/home/pi/klipper/klippy/klippy.py /home/pi/printer.cfg -l /tmp/klippy.log"
```
Add `-a /tmp/klippy_uds` to KLIPPY_ARGS:
```
# Configuration for /etc/init.d/klipper
KLIPPY_USER=pi
KLIPPY_EXEC=/home/pi/klippy-env/bin/python
KLIPPY_ARGS="/home/pi/klipper/klippy/klippy.py /home/pi/printer.cfg -l /tmp/klippy.log -a /tmp/klippy_uds"
```
!!! note
Your installation of Klipper may use systemd instead of
the default LSB script. In this case, you need to modify the
klipper.service file.
You may also want to take this opportunity to change the location of
printer.cfg to match Moonraker's `config_path` option (see the
[configuration document](configuration.md#primary-configuration)
for more information on the config_path). For example, if the `config_path`
is set to `~/printer_config`, your klipper defaults file might look
like the following:
```
# Configuration for /etc/init.d/klipper
KLIPPY_USER=pi
KLIPPY_EXEC=/home/pi/klippy-env/bin/python
KLIPPY_ARGS="/home/pi/klipper/klippy/klippy.py /home/pi/printer_config/printer.cfg -l /tmp/klippy.log -a /tmp/klippy_uds"
```
If necessary, create the config directory and move printer.cfg to it:
```
cd ~
mkdir printer_config
mv printer.cfg printer_config
```
### Installing Moonraker
Begin by cloning the git respository:
```
cd ~
git clone https://github.com/Arksine/moonraker.git
```
Now is a good time to create [moonraker.conf](configuration.md). If you are
using the `config_path`, create it in the specified directory otherwise create
it in the HOME directory. The [sample moonraker.conf](./moonraker.conf) in
the `docs` directory may be used as a starting point.
For a default installation run the following commands:
```
cd ~/moonraker/scripts
./install-moonraker.sh
```
Or to install with `moonraker.conf` in the `config_path`:
```
cd ~/moonraker/scripts
./install-moonraker.sh -f -c /home/pi/printer_config/moonraker.conf
```
The install script has a few command line options that may be useful,
particularly for those upgrading:
- `-r`:
Rebuilds the virtual environment for existing installations.
Sometimes this is necessary when a dependency has been added.
- `-f`:
Force an overwrite of Moonraker's systemd script. By default the
the systemd script will not be modified if it exists.
- `-c /home/pi/moonraker.conf`:
Specifies the path to Moonraker's config file. The default location
is `/home/<user>/moonraker.conf`. When using this option to modify
an existing installation it is necessary to add `-f` as well.
- `-z`:
Disables `systemctl` commands during install (ie: daemon-reload, restart).
This is useful for installations that occur outside of a standard environment
where systemd is not running.
Additionally, installation may be customized with the following environment
variables:
- `MOONRAKER_VENV`
- `MOONRAKER_REBUILD_ENV`
- `MOONRAKER_FORCE_DEFAULTS`
- `MOONRAKER_DISABLE_SYSTEMCTL`
- `MOONRAKER_CONFIG_PATH`
- `MOONRAKER_LOG_PATH`
When the script completes it should start both Moonraker and Klipper. In
`/tmp/klippy.log` you should find the following entry:
`webhooks client <uid>: Client info {'program': 'Moonraker', 'version': '<version>'}`
Now you may install a client, such as
[Mainsail](https://github.com/mainsail-crew/mainsail) or
[Fluidd](https://github.com/cadriel/fluidd).
!!! Note
Moonraker's install script no longer includes the nginx dependency.
If you want to install one of the above clients on the local machine,
you may want to first install nginx (`sudo apt install nginx` on
debian/ubuntu distros).
### Command line usage
This section is intended for users that need to write their own
installation script. Detailed are the command line arguments
available to Moonraker:
```
usage: moonraker.py [-h] [-c <configfile>] [-l <logfile>] [-n]
Moonraker - Klipper API Server
optional arguments:
-h, --help show this help message and exit
-c <configfile>, --configfile <configfile>
Location of moonraker configuration file
-l <logfile>, --logfile <logfile>
log file name and location
-n, --nologfile disable logging to a file
```
The default configuration is:
- config file path- `~/moonraker.conf`
- log file path - `/tmp/moonraker.log`
- logging to a file is enabled
If one needs to start moonraker without generating a log file, the
`-n` option may be used, for example:
```
~/moonraker-env/bin/python ~/moonraker/moonraker/moonraker.py -n -c /path/to/moonraker.conf
```
In general it is not recommended to install moonraker with this option.
While moonraker will still log to stdout, all requests for support must
be accompanied by moonraker.log.
These options may be changed by editing
`/etc/systemd/system/moonraker.service`. The `install-moonraker.sh` script
may also be used to modify the config file location.
### PolicyKit Permissions
Some of Moonraker's components require elevated privileges to perform actions.
Previously these actions could only be run via commandline programs launched
with the `sudo` prefix. This has significant downsides:
- The user must be granted `NOPASSWD` sudo access. Raspberry Pi OS
grants the Pi user this access by default, however most other distros
require that this be enabled through editing `visudo` or adding files
in `/etc/sudoers.d/`.
- Some linux distributions require additional steps such as those taken
in `sudo_fix.sh`.
- Running CLI programs is relatively expensive. This isn't an issue for
programs that are run once at startup, but is undesirable if Moonraker
wants to poll information about the system.
Moonraker now supports communicating with system services via D-Bus.
Operations that require elevated privileges are authrorized through
PolicyKit. On startup Moonraker will check for the necessary privileges
and warn users if they are not available. Warnings are presented in
`moonraker.log` and directly to the user through some clients.
To resolve these warnings users have two options:
1) Install the PolicyKit permissions with the `set-policykit-rules.sh` script,
for example:
```shell
cd ~/moonraker/scripts
./set-policykit-rules.sh
sudo service moonraker restart
```
!!! tip
If you still get warnings after installing the PolKit rules, run the
install script with no options to make sure that all new dependencies
are installed.
```shell
cd ~/moonraker/scripts
./install-moonraker.sh
```
2) Configure Moonraker to use the legacy backend implementations for
the `machine` and/or `update_manager` components, ie:
```ini
# Use the systemd CLI provider rather than the DBus Provider
[machine]
provider: systemd_cli
# Edit your existing [update_manager] section to disable
# PackageKit. This will fallback to the APT CLI Package Update
# implementation.
[update_manager]
#..other update manager options
enable_packagekit: False
# Alternatively system updates can be disabled
[update_manager]
#..other update manager options
enable_system_updates: False
```
!!! Note
Previously installed PolicyKit rules can be removed by running
`set-policykit-rules.sh -c`
### Retrieving the API Key
Some clients may require an API Key to connect to Moonraker. After the
`[authorization]` component is first configured Moonraker will automatically
generate an API Key. There are two ways in which the key may be retrieved
by the user:
Retrieve the API Key via the command line (SSH):
```
cd ~/moonraker/scripts
./fetch-apikey.sh
```
Retrieve the API Key via the browser from a trusted client:
- Navigate to `http://{moonraker-host}/access/api_key`, where
`{moonraker-host}` is the host name or ip address of the desired
moonraker instance.
- The result will appear in the browser window in JSON format. Copy
The API Key without the quotes.
{"result": "8ce6ae5d354a4365812b83140ed62e4b"}
### Recovering a broken repo
Currently Moonraker is deployed using `git`. Without going into the gritty
details,`git` is effectively a file system, and as such is subject to
file system corruption in the event of a loss of power, bad sdcard, etc.
If this occurs, updates using the `[update_manager]` may fail. In most
cases Moonraker provides an automated method to recover, however in some
edge cases this is not possible and the user will need to do so manually.
This requires that you `ssh` into your machine. The example below assumes
the following:
- You are using a Raspberry Pi
- Moonraker and Klipper are installed at the default locations in the `home`
directory
- Both Moonraker and Klipper have been corrupted and need to be restored
The following commands may be used to restore Moonraker:
```shell
cd ~
rm -rf moonraker
git clone https://github.com/Arksine/moonraker.git
cd moonraker/scripts
./install-moonraker.sh
./set-policykit-rules.sh
sudo systemctl restart moonraker
```
And for Klipper:
```shell
cd ~
rm -rf klipper
git clone https://github.com/Klipper3d/klipper.git
sudo systemctl restart klipper
```
### Additional Notes
- Make sure that Moonraker and Klipper both have read and write access to the
directory set in the `path` option for the `[virtual_sdcard]` in
`printer.cfg`.
- Upon first starting Moonraker is not aware of the gcode file path, thus
it cannot serve gcode files, add directories, etc. After Klippy enters
the "ready" state it sends Moonraker the gcode file path.
Once Moonraker receives the path it will retain it regardless of Klippy's
state, and update it if the path is changed in printer.cfg.
Please see [configuration.md](configuration.md) for details on how to
configure moonraker.conf.

30
docs/moonraker.conf Normal file
View File

@@ -0,0 +1,30 @@
# Sample Moonraker Configuration File
#
# !!! Moonraker does not load this file. See configuration.md !!!
# !!! for details on path to Moonraker's configuration. !!!
#
[server]
# Bind server defaults of 0.0.0.0, port 7125
enable_debug_logging: True
config_path: ~/printer_config
[authorization]
enabled: True
trusted_clients:
# Enter your client IP here or range here
192.168.1.0/24
cors_domains:
# Allow CORS requests for Fluidd
http://app.fluidd.xyz
# Enable OctoPrint compatibility for Slicer uploads
# Supports Cura, Slic3r, and Slic3r dervivatives
# (PrusaSlicer, SuperSlicer)
[octoprint_compat]
# Default webcam config values:
# flip_h = false
# flip_v = false
# rotate_90 = false
# stream_url = /webcam/?action=stream
# webcam_enabled = true

385
docs/printer_objects.md Normal file
View File

@@ -0,0 +1,385 @@
#
As mentioned in the API documentation, it is possible to
[query](web_api.md#query-printer-object-status) or
[subscribe](web_api.md#subscribe-to-printer-object-status)
to "Klipper Printer Objects." There are numerous printer objects in
Klipper, many of which are optional and only report status if they are
enabled by Klipper's configuration. Client's may retrieve a list of
available printer objects via the
[list objects endpoint](web_api.md#list-available-printer-objects). This
should be done after Klipper reports its state as "ready".
This section will provide an overview of the most useful printer objects.
If a developer is interested in retrieving state for an object not listed here,
look in Klipper's source code for module you wish to query. If the module
contains a "get_status()" method, its return value will contain a dictionary
that reports state which can be queried.
## webhooks
```json
{
"state": "startup",
"state_message": "message"
}
```
The `webhooks` object contains the current printer state and the current
state message. These fields match those returned via the `/printer/info`
endpoint. This is provided as a convience, clients may subscribe to `webhooks`
so they are asynchonously notified of a change to printer state. The `state`
may be `startup`, `ready`, `shutdown`, or `error`. The `state_message`
contains a message specific to the current printers state.
## gcode_move
```json
{
"speed_factor": 1.0,
"speed": 100.0,
"extrude_factor": 1.0,
"absolute_coordinates": true,
"absolute_extrude": false,
"homing_origin": [0.0, 0.0, 0.0, 0.0],
"position": [0.0, 0.0, 0.0, 0.0],
"gcode_position": [0.0, 0.0, 0.0, 0.0]
}
```
The `gcode_move` object reports the current gcode state:
- `speed_factor`: AKA "feedrate", this is the current speed multiplier
- `speed`: The current gcode speed in mm/s.
- `extrude_factor`: AKA "extrusion multiplier".
- `absolute_coorinates`: true if the machine axes are moved using
absolute coordinates, false if using relative coordinates.
- `absolute_extrude`: true if the extruder is moved using absolute
coordinates, false if using relative coordinates.
- `homing_origin`: [X, Y, Z, E] - returns the "gcode offset" applied to
each axis. For example, the "Z" axis can be checked to determine how
much offset has been applied via "babystepping".
- `position`: [X, Y, Z, E] - The internal gcode position, including
any offsets (gcode_offset, G92, etc) added to an axis.
- `gcode_position`: [X, Y, Z, E] - The current gcode position
sans any offsets applied. For X, Y, and Z, this should match
the most recent "G1" or "G0" processed assuming the machine is
using absolute coordinates.
!!! Note
The printer's actual movement will lag behind the reported positional
coordinates due to lookahead.
## toolhead
```json
{
"homed_axes": "xyz",
"print_time": 0.0,
"estimated_print_time": 0.0,
"extruder": "extruder",
"position": [0.0, 0.0, 0.0, 0.0],
"max_velocity": 500.0,
"max_accel": 3000.0,
"max_accel_to_decel": 1500.0,
"square_corner_velocity": 5.0
}
```
The `toolhead` object reports state of the current tool:
- `homed_axes`: a string containing the axes that are homed. If no axes
are homed, returns a null string.
- `print_time`: internal value, not generally useful for clients
- `estimated_print_time`: internal value, not generally useful for clients.
- `extruder`: the name of the currently selected extruder, ie "extruder"
or "extruder1".
- `position`: [X, Y, Z, E] - This the the last position toward which the tool
was commanded to move. It includes any offsets applied via gcode as well
as any transforms made by modules such as "bed_mesh", "bed_tilt", or
"skew_correction".
- `max_velocity`: The currently set maximum velocity of the tool (mm/s^2).
- `max_accel`: The currently set maximum acceleration of the tool (mm/s^2).
- `max_accel_to_decel`: The currently set maximum accel to decel of the tool.
This value is the maximum rate at which the tool can transition from
acceleration to deceleration (mm/s^2).
- `square_corner_velocity`: The currently set square corner velocity. This
is the maximum velocity at which the tool may travel a 90 degree corner.
!!! tip
`max_velocity`, `max_accel`, `max_accel_to_decel`, and
`square_corner_velocity` can be changed by the `SET_VELOCITY_LIMIT` gcode.
`M204` can also change `max_accel`.
## configfile
```json
{
"config": {},
"settings": {},
"save_config_pending": false
}
```
The `configfile` object reports printer configuration state:
- `config`: This is an object containing the configuration as read from
printer.cfg. Each config section will be an object containing the
configured options. Values will ALWAYS be reported as
strings. Note that default values are not reported, only options
configured in printer.cfg are present.
- `settings`: Similar to `config`, however this object includes default
values that may not have been included in `printer.cfg`. It is possible
for a value to be a string, integer, boolean, or float.
- `save_config_pending`: True if the printer has taken an action which
has updated the internal configuration (ie: PID calibration, probe
calibration, bed mesh calibration). This allows clients to present
the user with the option to execute a SAVE_CONFIG gcode which will
save the configuration to printer.cfg and restart the Klippy Host.
## extruder
*Enabled when `[extruder]` is included in printer.cfg*
!!! note
If multiple extruders are configured, extruder 0 is available as
`extruder`, extruder 1 as `extruder1` and so on.
```json
{
"temperature": 0.0,
"target": 0.0,
"power": 0.0,
"pressure_advance": 0.0,
"smooth_time": 0.0
}
```
The `extruder` object reports state of an extruder:
- `temperature`: The extruder's current temperature (in C).
- `target`: The extruder's target temperature (in C).
- `power`: The current pwm value applied to the heater. This value is
expressed as a percentage from 0.0 to 1.0.
- `pressure_advance`: The extruder's current pressure advance value.
- `smooth_time`: The currently set time range to use when calculating the
average extruder velocity for pressure advance.
## heater_bed
*Enabled when `[heater_bed]` is included in printer.cfg*
```json
{
"temperature": 0.0,
"target": 0.0,
"power": 0.0,
}
```
The `heater_bed` object reports state of the heated bed:
- `temperature`: The bed's current temperature
- `target`: The bed's target temperature
- `power`: The current pwm value applied to the heater. This value is
expressed as a percentage from 0.0 to 1.0.
## fan
*Enabled when `[fan]` is included in printer.cfg*
```json
{
"speed": 0.0,
"rpm": 4000
}
```
The `fan` object returns state of the part cooling fan:
- `speed`: The current fan speed. This is reported as a
percentage of maximum speed in the range of 0.0 - 1.0.
- `rpm`: The fan's revolutions per minute if the tachometer
pin has been configured. Will report `null` if no tach
has been configured.
## idle_timeout
```json
{
"state": "Idle",
"printing_time": 0.0
}
```
The `idle_timeout` object reports the idle state of the printer:
- `state`: Can be `Idle`, `Ready`, or `Printing`. The printer will
transition to the `Printing` state whenever a gcode is issued that
commands the tool, this includes manual commands. Thus this should
not be used to determine if a gcode file print is in progress. It can
however be used to determine if the printer is busy.
- `printing_time`: The amount of time the printer has been in the
`Printing` state. This is reset to 0 whenever the printer transitions
from `Printing` to `Ready`.
## virtual_sdcard
*Enabled when `[virtual_sdcard]` is included in printer.cfg*
```json
{
"progress": 0.0,
"is_active": false,
"file_position": 0
}
```
The `virtual_sdcard` object reports the state of the virtual sdcard:
- `progress`: The print progress reported as a percentage of the file
read, in the range of 0.0 - 1.0.
- `is_active`: Returns true if the virtual sdcard is currently processing
a file. Note that this will return false if a virtual sdcard print is
paused.
- `file_position`: The current file position in bytes. This will always
be an integer value
!!! Note
`progress` and `file_position` will persist after a print has
paused, completed, or errored. They are cleared when the user issues
a SDCARD_RESET_FILE gcode or when a new print has started.
## print_stats
*Enabled when `[virtual_sdcard]` is included in printer.cfg*
```json
{
"filename": "",
"total_duration": 0.0,
"print_duration": 0.0,
"filament_used": 0.0,
"state": "standby",
"message": ""
}
```
The `print_stats` object reports `virtual_sdcard` print state:
- `filename`: The name of the current file loaded. This will be a null
string if no file is loaded. Note that name is a path relative to the
gcode folder, thus if the file is located in a subdirectory it would
be reported as "my_sub_dir/myprint.gcode".
- `total_duration`: The total time (in seconds) elapsed since a print
has started. This includes time spent paused.
- `print_duration`: The total time spent printing (in seconds). This is
equivalent to `total_duration` - time paused.
- `filament_used`: The amount of filament used during the current print
(in mm). Any extrusion during a pause is excluded.
- `state`: Current print state. Can be one of the following values:
- `"standby"`
- `"printing"`
- `"paused"`
- `"complete"`
- `"cancelled"`
- `"error"` - Note that if an error is detected the print will abort
- `message`: If an error is detected, this field contains the error
message generated. Otherwise it will be a null string.
!!! Note
After a print has started all of the values above will persist until
the user issues a SDCARD_RESET_FILE gcode or when a new print has started.
## display_status
*Enabled when `[display]` or `[display_status]` is included in printer.cfg*
```json
{
"message": "",
"progress": 0.0
}
```
The `display_status` object contains state typically used to update displays:
- `message`: The message set by a M117 gcode. If no message is set this will
be a null string.
- `progress`: The percentage of print progress, as reported by M73. This
will be in the range of 0.0 - 1.0. If no M73 has been issued this value
will fallback to the eqivalent of `virtual_sdcard.progress`. Note that
progress updated via M73 has a timeout. If no M73 is received after 5
seconds, `progress` will be set to the fallback value.
## temperature_sensor sensor_name
*Enabled when `[temperature_sensor sensor_name]` is included in printer.cfg.
It is possible for multiple temperature sensors to be configured.*
```json
{
"temperature": 0.0,
"measured_min_temp": 0.0,
"measured_max_temp": 0.0
}
```
A `temperature_sensor` reports the following state:
- `temperature`: Sensor's current reported temperature
- `measured_min_temp`: The mimimum temperature read from the sensor
- `measured_max_temp`: The maximum temperature read from the sensor
## temperature_fan fan_name
*Enabled when `[temperature_fan fan_name]` is included in printer.cfg. It is
possible for multiple temperature fans to be configured.*
```json
{
"speed": 0.0,
"temperature": 0.0,
"target": 0.0
}
```
A `temperature_fan` reports the following state:
- `speed`: Current fan speed as a percentage of maximum speed, reported
in the range of 0.0 - 1.0
- `temperature`: Currently reported temperature of the sensor associated
with the fan
- `target`: The current target temperature for the `temperature_fan`.
## filament_switch_sensor sensor_name
*Enabled when `[filament_switch_sensor sensor_name]` is included in
printer.cfg. It is possible for multiple filament sensors to be configured.*
```json
{
"filament_detected": false,
"enabled": true
}
```
A `filament_switch_sensor` reports the following state:
- `filament_detected`: Set to true if the switch detects filament, otherwise
false
- `enabled`: Set to true if the sensor is currently enabled, otherwise false
## output_pin pin_name
*Enabled when `[output_pin pin_name]` is included in printer.cfg.
It is possible for multiple output pins to be configured.*
```json
{
"value": 0.0
}
```
An `output_pin` reports the following state:
- `value`: The currently set value of the pin, in the range of 0.0 - 1.0.
A digital pin will always be 0 or 1, whereas a pwm pin may report a value
across the entire range.
## bed_mesh
*Enabled when `[bed_mesh]` is included in printer.cfg.*
```json
{
"profile_name": "",
"mesh_min": [0.0, 0.0],
"mesh_max": [0.0, 0.0],
"probed_matrix": [[]],
"mesh_matrix": [[]]
}
```
The `bed_mesh` printer object reports the following state:
- `profile_name`: The name of the currently loaded profile. If no profile is
loaded then this will report a null string. If the user is not using
bed_mesh profile management then this will report `default` after mesh
calibration completes.
- `mesh_min`: [X, Y] - The minimum x and y coordinates of the mesh.
- `mesh_max`: [X, Y] - The maximum x and y coordinates of the mesh.
- `probed_matrix`: A 2 dimensional array representing the matrix of probed
values. If the matrix has not been probed the the result is `[[]]`.
- `mesh_matrix`: A 2 dimension array representing the interpolated mesh. If
no matrix has been generated the result is `[[]]`.
!!! tip
See [web_api.md](web_api.md##bed-mesh-coordinates) for an example
of how to use this information to generate (X,Y,Z) coordinates.
## gcode_macro macro_name
*Enabled when `[gcode_macro macro_name]` is included in printer.cfg.
It is possible for multiple gcode macros to be configured.*
Gcode macros will report the state of configured `variables`.
While user defined macros likely won't report state that is useful
for a client, it is possible for client developers to recommend or
request a specific gcode_macro configuration, then have the client
take action based on the variables reported by the macro.

136
docs/user_changes.md Normal file
View File

@@ -0,0 +1,136 @@
##
This file will track changes that require user intervention,
such as a configuration change or a reinstallation.
### April 6th 2022
- The ability to configure core components in the `[server]`section
is now deprecated. When legacy items are detected in `[server]` a
warning will be generated. It is crucially important to move configuration
to the correct section as in the future it will be a hard requirement.
### Feburary 22nd 2022
- The `on_when_upload_queued` option for [power] devices has been
deprecated in favor of `on_when_job_queued`. As the new option
name implies, this option will power on the device when any new
job is queued, not only when its sourced from an upload. The
`on_when_upload_queued` option will be treated as an alias to
`on_when_job_queued` until its removal.
### February 16th 2022
- Webcam settings can now be defined in the `moonraker.conf` file, under
the `[octoprint_compat]` section. The default values are being used as
default values.
Default values:
| Setting | Default value |
|---------|---------------|
| flip_h | False |
| flip_v | False |
| rotate_90 | False |
| stream_url | /webcam/?action=stream |
| webcam_enabled | True |
### January 22th 2022
- The `color_order` option in the `[wled]` section has been deprecated.
This is configured in wled directly. This is not a breaking change,
the setting will simply be ignored not affecting functionality.
### December 24th 2021
- The `password_file` option in the `[mqtt]` section has been deprecated.
Use the `password` option instead. This option may be a template, thus
can resolve secrets stored in the `[secrets]` module.
### November 7th 2021
- Previously all core components received configuration through
the `[server]` config section. As Moonraker's core functionality
has expanded this is becoming unsustainable, thus core components
should now be configured in their own section. For example, the
`config_path` and `log_path` should now be configured in the
`[file_manager]` section of `moonraker.conf`. See the
[configuration documentation](https://moonraker.readthedocs.io/en/latest/configuration/)
for details. This is not a breaking change, core components
will still fall back to checking the `[server]` section for
configuration.
### April 19th 2021
- The `[authorization]` module is now a component, thus is only
loaded if the user has it configured in `moonraker.conf`. This
deprecates the previous `enable` option, as it is enabled
if configured and disabled otherwise.
- The API Key is now stored in the database. This deprecates the
`api_key_file` option in the `[authorization]` module. Users can
no longer read the contents of the API Key file to retrieve the
API Key. Instead, users can run `scripts/fetch-apikey.sh` to
print the API Key. Alternative a user can navigate to
`http://{moonraker-host}/access/api_key` from a trusted client
to retrieve the API Key.
### March 10th 2021
- The `cors_domain` option in the `[authoriztion]` section is now
checked for dangerous entries. If a domain entry contains a
wildcard in the top level domain (ie: `http://www.*`) then it
will be rejected, as malicious website can easily reproduce
this match.
### March 6th 2021
- The `enable_debug_logging` in the `[server]` section now defaults
to `False`. This dramatically reduces the amount of logging produced
by Moonraker for the typical user.
### March 4th 2021
- To enable OctoPrint compatibility with slicer uploads it is now
required to add `[octoprint_compat]` to `moonraker.conf`. After
making this change it is necessary to restart the Moonraker service
so the module is loaded.
### December 31st 2020
- The file manager no longer restricts the `config_path` to a folder
within the HOME directory. The path may not be the system root,
however it can reside anywhere else on the file system as long as
Moonraker has read and write access to the directory. This applies
to gcode path received from Klipper via the `virtual_sdcard` section
as well.
### December 6th 2020
- Moonraker is now installed as a systemd service. This allows logging
to stdout which can be viewed with the `journalctl -u moonraker` command.
This changes requires the user to rerun the install script. If
`moonraker.conf` is not located in the home directory, the command
will looks something like the following:
cd ~/moonraker
./scripts/install-moonraker.sh -f -c /home/pi/klipper_config/moonraker.conf
Otherwise you can run the install script with no arguments.
### November 19th 2020
- The install script (`install-moonraker.sh`) now has command-line
options:\
`-r` Rebuild the python virtual env\
`-f` Force an overwrite of `/etc/default/moonraker` during installation\
`-c /path/to/moonraker.conf` Allows user to specify the path to
moonraker.conf during configuration. Using this in conjunction with `-f`
will update the defaults file wih the new path.
- New dependencies have been added to Moonraker which require reinstallation.
Run the following command to reinstall and rebuild the virtualenv:
~/moonraker/scripts/install-moonraker.sh -r
- The power plugin configuration has changed. See the
[install guide](installation.md#power-control-plugin) for
details on the new configuration.
- Users transitioning from the previous version of the power plugin will need
to unexport any curently used pins. For example, the following command
may be used to unexport pin 19:
echo 19 > /sys/class/gpio/unexport
Alternatively one may reboot the machine after upgrading:
cd ~/moonraker/
git pull
~/moonraker/scripts/install-moonraker.sh -r
sudo reboot
Make sure that the power plugin configuration has been updated prior
to rebooting the machine.

5768
docs/web_api.md Normal file

File diff suppressed because it is too large Load Diff