2020-07-02 04:21:35 +03:00
|
|
|
# API
|
|
|
|
|
|
|
|
Most API methods are supported over both the Websocket and HTTP transports.
|
|
|
|
File Transfer and "/access" requests are only available over HTTP. The
|
|
|
|
Websocket is required to receive printer generated events such as gcode
|
|
|
|
responses. For information on how to set up the Websocket, please see the
|
|
|
|
Appendix at the end of this document.
|
|
|
|
|
|
|
|
Note that all HTTP responses are returned as a json encoded object in the form
|
|
|
|
of:
|
|
|
|
|
|
|
|
`{result: <response data>}`
|
|
|
|
|
|
|
|
The command matches the original command request, the result is the return
|
|
|
|
value generated from the request.
|
|
|
|
|
|
|
|
Websocket requests are returned in JSON-RPC format:
|
|
|
|
`{jsonrpc: "2.0", "result": <response data>, id: <request id>}`
|
|
|
|
|
|
|
|
HTML requests will recieve a 500 status code on error, accompanied by
|
|
|
|
the specific error message.
|
|
|
|
|
|
|
|
Websocket requests that result in an error will receive a properly formatted
|
|
|
|
JSON-RPC response:
|
|
|
|
`{jsonrpc: "2.0", "error": {code: <code>, message: <msg>}, id: <request_id>}`
|
|
|
|
Note that under some circumstances it may not be possible for the server to
|
|
|
|
return a request ID, such as an improperly formatted json request.
|
|
|
|
|
|
|
|
The `test\client` folder includes a basic test interface with example usage for
|
|
|
|
most of the requests below. It also includes a basic JSON-RPC implementation
|
|
|
|
that uses promises to return responses and errors (see json-rcp.js).
|
|
|
|
|
|
|
|
## Printer Administration
|
|
|
|
|
|
|
|
### Get Klippy host information:
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /printer/info`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.info", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
2020-08-15 14:02:42 +03:00
|
|
|
An object containing the build version, cpu info, Klippy's current state.
|
|
|
|
|
|
|
|
```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>",
|
|
|
|
}
|
|
|
|
```
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
### Emergency Stop
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/emergency_stop`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.emergency_stop", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
### Restart the host
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/restart`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.restart", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
### Restart the firmware (restarts the host and all connected MCUs)
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/firmware_restart`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.firmware_restart", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
## Printer Status
|
|
|
|
|
|
|
|
### Request available printer objects and their attributes:
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /printer/objects/list`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.objects.list", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
2020-08-15 14:02:42 +03:00
|
|
|
An a list of "printer objects" that are currently available for query
|
|
|
|
or subscription. This list will be passed in an "objects" parameter.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
```json
|
2020-08-16 21:06:59 +03:00
|
|
|
{ objects: ["gcode", "toolhead", "bed_mesh", "configfile",....]}
|
2020-07-02 04:21:35 +03:00
|
|
|
```
|
|
|
|
|
2020-08-15 14:02:42 +03:00
|
|
|
### Query the a status for an object, or group of objects:
|
2020-07-02 04:21:35 +03:00
|
|
|
- HTTP command:\
|
2020-08-15 14:02:42 +03:00
|
|
|
`GET /printer/objects/query?gcode`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
The above will fetch a status update for all gcode attributes. The query
|
|
|
|
string can contain multiple items, and specify individual attributes:
|
|
|
|
|
|
|
|
`?gcode=gcode_position,busy&toolhead&extruder=target`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.objects.query", params:
|
2020-08-15 14:02:42 +03:00
|
|
|
{objects: {gcode: [], toolhead: ["position", "status"]}},
|
|
|
|
id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
Note that an empty array will fetch all available attributes for its key.
|
|
|
|
|
|
|
|
- Returns:\
|
2020-08-15 14:02:42 +03:00
|
|
|
An object where the top level items are "eventtime" and "status". The
|
|
|
|
"status" item contains data about the requested update.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
```json
|
2020-08-15 14:02:42 +03:00
|
|
|
{
|
|
|
|
eventtime: <klippy time of update>,
|
|
|
|
status: {
|
|
|
|
gcode: {
|
|
|
|
busy: true,
|
|
|
|
gcode_position: [0, 0, 0 ,0],
|
|
|
|
...},
|
|
|
|
toolhead: {
|
|
|
|
position: [0, 0, 0, 0],
|
|
|
|
status: "Ready",
|
|
|
|
...},
|
|
|
|
...}
|
|
|
|
}
|
2020-07-02 04:21:35 +03:00
|
|
|
```
|
|
|
|
### Subscribe to a status request or a batch of status requests:
|
|
|
|
- HTTP command:\
|
2020-08-15 14:02:42 +03:00
|
|
|
`POST /printer/objects/subscribe?gcode=gcode_position,bus&extruder=target`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.objects.subscribe", params:
|
2020-08-15 14:02:42 +03:00
|
|
|
{objects: {gcode: [], toolhead: ["position", "status"]}},
|
|
|
|
id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
2020-08-15 14:02:42 +03:00
|
|
|
Status data for all currently subscribed objects, with the format matching that of
|
|
|
|
the `/printer/objects/query`:
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-08-15 14:02:42 +03:00
|
|
|
```json
|
|
|
|
{
|
|
|
|
eventtime: <klippy time of update>,
|
|
|
|
status: {
|
|
|
|
gcode: {
|
|
|
|
busy: true,
|
|
|
|
gcode_position: [0, 0, 0 ,0],
|
|
|
|
...},
|
|
|
|
toolhead: {
|
|
|
|
position: [0, 0, 0, 0],
|
|
|
|
status: "Ready",
|
|
|
|
...},
|
|
|
|
...}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
Note that Moonraker's current behavior is maintain a superset of all client
|
|
|
|
subscriptions, thus you may received data for objects that you did not
|
|
|
|
request. This behavior is subject to change in the future (where each
|
|
|
|
client receives only the subscriptions it requested).
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-08-15 14:02:42 +03:00
|
|
|
Future updates for subscribed objects are sent asynchronously over the
|
|
|
|
websocket. See the `notify_status_update` notification for details.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
### Query Endstops
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /printer/query_endstops/status`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.query_endstops.status", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
An object containing the current endstop state, with each attribute in the
|
|
|
|
format of `endstop:<state>`, where "state" can be "open" or "TRIGGERED", for
|
|
|
|
example:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{x: "TRIGGERED",
|
|
|
|
y: "open",
|
|
|
|
z: "open"}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Fetch stored temperature data
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/temperature_store`
|
|
|
|
|
|
|
|
- Websocket command:
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.temperature_store", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
An object where the keys are the available temperature sensor names, and with
|
|
|
|
the value being an array of stored temperatures. The array is updated every
|
|
|
|
1 second by default, containing a total of 1200 values (20 minutes). The
|
|
|
|
array is organized from oldest temperature to most recent (left to right).
|
|
|
|
Note that when the host starts each array is initialized to 0s.
|
|
|
|
|
|
|
|
## Gcode Controls
|
|
|
|
|
|
|
|
### Run a gcode:
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/gcode/script?script=<gc>`
|
|
|
|
|
|
|
|
For example,\
|
|
|
|
`POST /printer/gcode/script?script=RESPOND MSG=Hello`\
|
|
|
|
Will echo "Hello" to the terminal.
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.gcode.script",
|
2020-07-02 04:21:35 +03:00
|
|
|
params: {script: <gc>}, id: <request id>}`
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
An acknowledgement that the gcode has completed execution:
|
|
|
|
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
### Get GCode Help
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /printer/gcode/help`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.gcode.help",
|
2020-07-02 04:21:35 +03:00
|
|
|
params: {script: <gc>}, id: <request id>}`
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
An object where they keys are gcode handlers and values are the associated
|
|
|
|
help strings. Note that help strings are not available for basic gcode
|
|
|
|
handlers such as G1, G28, etc.
|
|
|
|
|
|
|
|
## Print Management
|
|
|
|
|
|
|
|
### Print a file
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/print/start?filename=<file name>`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.print.start",
|
2020-07-02 04:21:35 +03:00
|
|
|
params: {filename: <file name>, id:<request id>}`
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok` on success
|
|
|
|
|
|
|
|
### Pause a print
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/print/pause`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.print.pause", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
### Resume a print
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/print/resume`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.print.resume", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
### Cancel a print
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /printer/print/cancel`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "printer.print.cancel", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok`
|
|
|
|
|
|
|
|
## Machine Commands
|
|
|
|
|
|
|
|
### Shutdown the Operating System
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /machine/shutdown`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "machine.shutdown", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
No return value as the server will shut down upon execution
|
|
|
|
|
|
|
|
### Reboot the Operating System
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /machine/reboot`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "machine.reboot", id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
No return value as the server will shut down upon execution
|
|
|
|
|
|
|
|
|
|
|
|
## File Operations
|
|
|
|
|
2020-07-04 21:33:17 +03:00
|
|
|
Most file operations are available over both APIs, however file upload,
|
|
|
|
file download, and file delete are currently only available via HTTP APIs.
|
2020-07-27 19:58:23 +03:00
|
|
|
|
|
|
|
Moonraker organizes different local directories into "roots". For example,
|
|
|
|
gcodes are located at `http:\\host\server\files\gcodes\*`, otherwise known
|
|
|
|
as the "gcodes" root. The following roots are available:
|
|
|
|
- gcodes
|
|
|
|
- config
|
|
|
|
- config_examples (read-only)
|
|
|
|
|
|
|
|
Write operations (upload, delete, make directory, remove directory) are
|
2020-08-05 13:50:42 +03:00
|
|
|
only available on the `gcodes` and config roots. Note that the `config` root
|
|
|
|
is only available if the "config_path" option has been set in Moonraker's
|
|
|
|
configuration.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
### List Available Files
|
|
|
|
Walks through a directory and fetches all files. All file names include a
|
|
|
|
path relative to the specified "root". Note that if the query st
|
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/files/list?root=gcodes`
|
|
|
|
|
|
|
|
If the query string is omitted then the command will return
|
|
|
|
the "gcodes" file list by default.
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.list", params: {root: "gcodes"}
|
2020-07-02 04:21:35 +03:00
|
|
|
, id: <request id>}`
|
|
|
|
|
|
|
|
If `params` are are omitted then the command will return the "gcodes"
|
|
|
|
file list.
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
A list of objects containing file data in the following format:
|
|
|
|
|
|
|
|
```json
|
|
|
|
[
|
|
|
|
{filename: "file name",
|
|
|
|
size: <file size>,
|
|
|
|
modified: "last modified date",
|
|
|
|
...]
|
|
|
|
```
|
|
|
|
|
|
|
|
### Get GCode Metadata
|
|
|
|
Get file metadata for a specified gcode file. If the file is located in
|
|
|
|
a subdirectory, then the file name should include the path relative to
|
|
|
|
the "gcodes" root. For example, if the file is located at:\
|
|
|
|
`http://host/server/files/gcodes/my_sub_dir/my_print.gcode`
|
|
|
|
Then the filename should be `my_sub_dir/my_print.gcode`.
|
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/files/metadata?filename=<filename>`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.metadata", params: {filename: "filename"}
|
2020-07-02 04:21:35 +03:00
|
|
|
, id: <request id>}`
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
Metadata for the requested file if it exists. If any fields failed
|
|
|
|
parsing they will be omitted. The metadata will always include the file name,
|
|
|
|
modified time, and size.
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
filename: "file name",
|
2020-09-09 18:32:37 +03:00
|
|
|
size: <file_size>,
|
2020-07-02 04:21:35 +03:00
|
|
|
modified: "last modified date",
|
|
|
|
slicer: "Slicer Name",
|
2020-09-09 18:32:37 +03:00
|
|
|
slicer_version: "<version>",
|
|
|
|
first_layer_height: <mm>,
|
|
|
|
first_layer_bed_temp: <C>,
|
|
|
|
first_layer_extr_temp: <C>,
|
|
|
|
layer_height: <mm>,
|
|
|
|
object_height: <mm>,
|
2020-07-02 04:21:35 +03:00
|
|
|
estimated_time: <time in seconds>,
|
2020-09-09 18:32:37 +03:00
|
|
|
filament_total: <mm>,
|
2020-07-02 04:21:35 +03:00
|
|
|
thumbnails: [
|
|
|
|
{
|
|
|
|
width: <in pixels>,
|
|
|
|
height: <in pixels>,
|
|
|
|
size: <length of string>,
|
|
|
|
data: <base64 string>
|
|
|
|
}, ...
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Get directory information
|
|
|
|
Returns a list of files and subdirectories given a supplied path.
|
|
|
|
Unlike `/server/files/list`, this command does not walk through
|
|
|
|
subdirectories.
|
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/files/directory?path=gcodes/my_subdir`
|
|
|
|
|
|
|
|
If the query string is omitted then the command will return
|
|
|
|
the "gcodes" file list by default.
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.get_directory",
|
|
|
|
params: {path: "gcodes/my_subdir"} , id: <request id>}`
|
2020-07-04 21:33:17 +03:00
|
|
|
|
|
|
|
If the "params" are omitted then the command will return
|
|
|
|
the "gcodes" file list by default.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
An object containing file and subdirectory information in the
|
|
|
|
following format:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
files: [
|
|
|
|
{
|
|
|
|
filename: "file name",
|
|
|
|
size: <file size>,
|
|
|
|
modified: "last modified date"
|
|
|
|
}, ...
|
|
|
|
],
|
|
|
|
dirs: [
|
|
|
|
{
|
|
|
|
dirname: "directory name",
|
|
|
|
modified: "last modified date"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Make new directory
|
|
|
|
Creates a new directory at the specified path.
|
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /server/files/directory?path=gcodes/my_new_dir`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.post_directory", params:
|
2020-07-04 21:33:17 +03:00
|
|
|
{path: "gcodes/my_new_dir"}, id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
Returns:\
|
|
|
|
`ok` if successful
|
|
|
|
|
|
|
|
### Delete directory
|
|
|
|
Deletes a directory at the specified path.
|
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`DELETE /server/files/directory?path=gcodes/my_subdir`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.delete_directory", params:
|
2020-07-27 19:58:23 +03:00
|
|
|
{path: "gcodes/my_subdir"} , id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
If the specified directory contains files then the delete request
|
|
|
|
will fail, however it is possible to "force" deletion of the directory
|
|
|
|
and all files in it with and additional argument in the query string:\
|
|
|
|
`DELETE /server/files/directory?path=gcodes/my_subdir&force=true`
|
|
|
|
|
2020-07-04 21:33:17 +03:00
|
|
|
OR to the JSON-RPC params:\
|
|
|
|
`{jsonrpc: "2.0", method: "get_directory", params:
|
|
|
|
{path: "gcodes/my_subdir", force: True}, id: <request id>}`
|
|
|
|
|
2020-07-02 04:21:35 +03:00
|
|
|
Note that a forced deletion will still check in with Klippy to be sure
|
|
|
|
that a file in the requested directory is not loaded by the virtual_sdcard.
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
`ok` if successful
|
|
|
|
|
2020-07-13 19:12:52 +03:00
|
|
|
### Move a file or directory
|
|
|
|
Moves a file or directory from one location to another. Note that the following
|
|
|
|
conditions must be met for a move successful move:
|
|
|
|
- The source must exist
|
2020-07-27 19:58:23 +03:00
|
|
|
- The source and destinations must have the same "root" directory
|
2020-07-13 19:12:52 +03:00
|
|
|
- The user (typically "Pi") must have the appropriate file permissions
|
|
|
|
- Neither the source nor destination can be loaded by the virtual_sdcard.
|
|
|
|
If the source or destination is a directory, it cannot contain a file
|
|
|
|
loaded by the virtual_sdcard.
|
|
|
|
|
2020-07-27 19:58:23 +03:00
|
|
|
When specifying the `source` and `dest`, the "root" directory should be
|
|
|
|
prefixed. Currently the only supported roots are "gcodes/" and "config/".
|
2020-07-13 19:12:52 +03:00
|
|
|
|
2020-07-27 19:58:23 +03:00
|
|
|
This API may also be used to rename a file or directory. Be aware that an
|
|
|
|
attempt to rename a directory to a directory that already exists will result
|
|
|
|
in *moving* the source directory to the destination directory.
|
2020-07-13 19:12:52 +03:00
|
|
|
|
|
|
|
- HTTP command:\
|
2020-07-27 19:58:23 +03:00
|
|
|
`POST /server/files/move?source=gcodes/my_file.gcode
|
|
|
|
&dest=gcodes/subdir/my_file.gcode`
|
2020-07-13 19:12:52 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.move", params:
|
2020-07-27 19:58:23 +03:00
|
|
|
{source: "gcodes/my_file.gcode",
|
2020-07-13 19:12:52 +03:00
|
|
|
dest: "gcodes/subdir/my_file.gcode"}, id: <request id>}`
|
|
|
|
|
|
|
|
### Copy a file or directory
|
|
|
|
Copies a file or directory from one location to another. A successful copy has
|
|
|
|
the pre-requesites as a move with one exception, a copy may complete if the
|
2020-07-27 19:58:23 +03:00
|
|
|
source file/directory is loaded by the virtual_sdcard. As with the move API,
|
|
|
|
the source and destination should have the root prefixed.
|
2020-07-13 19:12:52 +03:00
|
|
|
|
|
|
|
- HTTP command:\
|
2020-07-27 19:58:23 +03:00
|
|
|
`POST /server/files/copy?source=gcodes/my_file.gcode
|
|
|
|
&dest=gcodes/subdir/my_file.gcode`
|
2020-07-13 19:12:52 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-03 15:55:49 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.copy", params:
|
2020-07-27 19:58:23 +03:00
|
|
|
{source: "gcodes/my_file.gcode", dest: "gcodes/subdir/my_file.gcode"},
|
|
|
|
id: <request id>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
### Gcode File Download
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/files/gcodes/<file_name>`
|
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The requested file
|
|
|
|
|
|
|
|
### File Upload
|
2020-07-27 19:58:23 +03:00
|
|
|
Upload a file. Currently files may be uploaded to the "gcodes" or "config"
|
|
|
|
root, with "gcodes" being the default location. If one wishes to upload
|
|
|
|
to a subdirectory, the path may be added to the upload's file name
|
|
|
|
(relative to the root). If the directory does not exist an error will be
|
|
|
|
returned. Alternatively, the "path" argument may be set, as explained
|
|
|
|
below.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /server/files/upload`
|
|
|
|
|
|
|
|
The file to be uploaded should be added to the FormData per the XHR spec.
|
2020-07-27 19:58:23 +03:00
|
|
|
The following arguments may be added to the form:
|
|
|
|
- root: The root location in which to upload the file. Currently this may
|
|
|
|
be "gcodes" or "config". If not specified the default is "gcodes".
|
|
|
|
- path: This argument may contain a path (relative to the root) indicating
|
|
|
|
a subdirectory to which the file is written. If a "path" is present, the
|
|
|
|
server will attempt to create any subdirectories that do not exist.
|
|
|
|
Arguments available only for the "gcodes" root:
|
|
|
|
- print: If set to "true", Klippy will attempt to start the print after
|
|
|
|
uploading. Note that this value should be a string type, not boolean. This
|
|
|
|
provides compatibility with Octoprint's legacy upload API.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
2020-07-27 19:58:23 +03:00
|
|
|
The file name along with a successful response.
|
|
|
|
```json
|
|
|
|
{'result': "file_name"}
|
|
|
|
```
|
|
|
|
If the supplied root is "gcodes", a "print_started" attribute is also
|
|
|
|
returned.
|
|
|
|
```json
|
|
|
|
{'result': "file_name", 'print_started': <boolean>}
|
|
|
|
```
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-07-27 19:58:23 +03:00
|
|
|
### Gcode File Delete
|
2020-07-02 04:21:35 +03:00
|
|
|
Delete a file in the "gcodes" root. A relative path may be added to the file
|
|
|
|
to delete a file in a subdirectory.
|
|
|
|
- HTTP command:\
|
|
|
|
`DELETE /server/files/gcodes/<file_name>`
|
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-07 19:51:39 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.delete_file", params:
|
|
|
|
{path: "gcodes/<file_name>"}, id: <request id>}`
|
|
|
|
|
|
|
|
If the gcode file exists within a subdirectory, the relative
|
|
|
|
path should be included in the file name.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The HTTP request returns the name of the deleted file.
|
|
|
|
|
2020-07-27 19:58:23 +03:00
|
|
|
### Download included config file
|
|
|
|
- HTTP command:\
|
2020-08-05 13:50:42 +03:00
|
|
|
`GET /server/files/config/<file_name>`
|
2020-07-27 19:58:23 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The requested file
|
|
|
|
|
|
|
|
### Delete included config file
|
|
|
|
Delete a file in the "config" root. A relative path may be added to the file
|
|
|
|
to delete a file in a subdirectory.
|
|
|
|
- HTTP command:\
|
2020-08-05 13:50:42 +03:00
|
|
|
`DELETE /server/files/config/<file_name>`
|
2020-07-27 19:58:23 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
2020-09-07 19:51:39 +03:00
|
|
|
`{jsonrpc: "2.0", method: "server.files.delete_file", params:
|
|
|
|
{path: "config/<file_name>}, id: <request id>}`
|
2020-07-27 19:58:23 +03:00
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The HTTP request returns the name of the deleted file.
|
|
|
|
|
|
|
|
### Download a config example
|
|
|
|
- HTTP command:\
|
2020-08-05 13:50:42 +03:00
|
|
|
`GET /server/files/config_examples/<file_name>`
|
2020-07-27 19:58:23 +03:00
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The requested file
|
|
|
|
|
2020-07-02 04:21:35 +03:00
|
|
|
### Download klippy.log
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/files/klippy.log`
|
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
klippy.log
|
|
|
|
|
|
|
|
### Download moonraker.log
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /server/files/moonraker.log`
|
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
moonraker.log
|
|
|
|
|
|
|
|
## Authorization
|
|
|
|
|
|
|
|
Untrusted Clients must use a key to access the API by including it in the
|
|
|
|
`X-Api-Key` header for each HTTP Request. The API below allows authorized
|
|
|
|
clients to receive and change the current API Key.
|
|
|
|
|
|
|
|
### Get the Current API Key
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /access/api_key`
|
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not Available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The current API key
|
|
|
|
|
|
|
|
### Generate a New API Key
|
|
|
|
- HTTP command:\
|
|
|
|
`POST /access/api_key`
|
|
|
|
|
|
|
|
- Websocket command:\
|
|
|
|
Not available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
The newly generated API key. This overwrites the previous key. Note that
|
|
|
|
the API key change is applied immediately, all subsequent HTTP requests
|
|
|
|
from untrusted clients must use the new key.
|
|
|
|
|
|
|
|
### Generate a Oneshot Token
|
|
|
|
|
|
|
|
Some HTTP Requests do not expose the ability the change the headers, which is
|
|
|
|
required to apply the `X-Api-Key`. To accomodiate these requests it a client
|
|
|
|
may ask the server for a Oneshot Token. Tokens expire in 5 seconds and may
|
|
|
|
only be used once, making them relatively for inclusion in the query string.
|
|
|
|
|
|
|
|
- HTTP command:\
|
|
|
|
`GET /access/oneshot_token`
|
|
|
|
|
|
|
|
- Websocket command:
|
|
|
|
Not available
|
|
|
|
|
|
|
|
- Returns:\
|
|
|
|
A temporary token that may be added to a requests query string for access
|
|
|
|
to any API endpoint. The query string should be added in the form of:
|
|
|
|
`?token=randomly_generated_token`
|
|
|
|
|
|
|
|
## Websocket notifications
|
|
|
|
Printer generated events are sent over the websocket as JSON-RPC 2.0
|
|
|
|
notifications. These notifications are sent to all connected clients
|
|
|
|
in the following format:
|
|
|
|
|
2020-08-16 21:06:59 +03:00
|
|
|
`{jsonrpc: "2.0", method: <event method name>}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-08-16 21:06:59 +03:00
|
|
|
OR
|
|
|
|
|
|
|
|
`{jsonrpc: "2.0", method: <event method name>, params: [<event parameter>]}`
|
|
|
|
|
|
|
|
If a notification has parameters, the `params` value will always be
|
2020-07-02 04:21:35 +03:00
|
|
|
wrapped in an array as directed by the JSON-RPC standard. Currently
|
2020-08-16 21:06:59 +03:00
|
|
|
all notifications available are broadcast with either no parameters
|
|
|
|
or a single parameter.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
### Gcode response:
|
|
|
|
All calls to gcode.respond() are forwarded over the websocket. They arrive
|
|
|
|
as a "gcode_response" notification:
|
|
|
|
|
|
|
|
`{jsonrpc: "2.0", method: "notify_gcode_response", params: ["response"]}`
|
|
|
|
|
|
|
|
### Status subscriptions:
|
|
|
|
Status Subscriptions arrive as a "notify_status_update" notification:
|
|
|
|
|
|
|
|
`{jsonrpc: "2.0", method: "notify_status_update", params: [<status_data>]}`
|
|
|
|
|
|
|
|
The structure of the status data is identical to the structure that is
|
2020-08-16 21:06:59 +03:00
|
|
|
returned from an object query's "status" attribute.
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-08-16 21:06:59 +03:00
|
|
|
### Klippy Disconnected:
|
|
|
|
Notify clients when Moonraker's connection to Klippy has terminated
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-08-16 21:06:59 +03:00
|
|
|
`{jsonrpc: "2.0", method: "notify_klippy_disconnected"}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
### File List Changed
|
|
|
|
When a client makes a change to the virtual sdcard file list
|
|
|
|
(via upload or delete) a notification is broadcast to alert all connected
|
|
|
|
clients of the change:
|
|
|
|
|
2020-08-05 13:50:42 +03:00
|
|
|
`{jsonrpc: "2.0", method: "notify_filelist_changed",
|
|
|
|
params: [<file changed info>]}`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-08-11 00:49:00 +03:00
|
|
|
The <file changed info> param is an object in the following format, where
|
|
|
|
the "action" is the operation that prompted the change, and the "item"
|
|
|
|
contains information about the item that has changed:
|
2020-07-02 04:21:35 +03:00
|
|
|
|
|
|
|
```json
|
2020-08-11 00:49:00 +03:00
|
|
|
{action: "<action>",
|
|
|
|
item: {
|
|
|
|
path: "<file or directory path>",
|
|
|
|
root: "<root_name>",
|
|
|
|
size: <file size>,
|
|
|
|
modified: "<date modified>"
|
|
|
|
}
|
2020-07-27 19:58:23 +03:00
|
|
|
```
|
2020-08-11 00:49:00 +03:00
|
|
|
Note that file move and copy actions also include a "source item" that
|
|
|
|
contains the path and root of the source file or directory.
|
2020-07-27 19:58:23 +03:00
|
|
|
```json
|
2020-08-11 00:49:00 +03:00
|
|
|
{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>"
|
|
|
|
}
|
|
|
|
}
|
2020-07-02 04:21:35 +03:00
|
|
|
```
|
|
|
|
|
2020-08-11 00:49:00 +03:00
|
|
|
The following `actions` are currently available:
|
|
|
|
- `upload_file`
|
|
|
|
- `delete_file`
|
|
|
|
- `create_dir`
|
|
|
|
- `delete_dir`
|
|
|
|
- `move_item`
|
|
|
|
- `copy_item`
|
2020-07-02 04:21:35 +03:00
|
|
|
|
2020-09-01 18:37:06 +03:00
|
|
|
### Metadata Update
|
|
|
|
When a new file is uploaded via the API a websocket notification is broadcast
|
|
|
|
to all connected clients after parsing is complete:
|
|
|
|
|
|
|
|
`{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>
|
|
|
|
}, ...
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-07-02 04:21:35 +03:00
|
|
|
# Appendix
|
|
|
|
|
|
|
|
### Websocket setup
|
|
|
|
All transmissions over the websocket are done via json using the JSON-RPC 2.0
|
|
|
|
protocol. While the websever expects a json encoded string, one limitation
|
|
|
|
of Eventlet's websocket is that it can not send string encoded frames. Thus
|
|
|
|
the client will receive data om the server in the form of a binary Blob that
|
|
|
|
must be read using a FileReader object then decoded.
|
|
|
|
|
|
|
|
The websocket is located at `ws://host:port/websocket`, for example:
|
|
|
|
```javascript
|
|
|
|
var s = new WebSocket("ws://" + location.host + "/websocket");
|
|
|
|
```
|
|
|
|
|
|
|
|
It also should be noted that if authorization is enabled, an untrusted client
|
|
|
|
must request a "oneshot token" and add that token's value to the websocket's
|
|
|
|
query string:
|
|
|
|
|
|
|
|
```
|
|
|
|
ws://host:port/websocket?token=<32 character base32 string>
|
|
|
|
```
|
|
|
|
|
|
|
|
This is necessary as it isn't currently possible to add `X-Api-Key` to a
|
|
|
|
websocket's request header.
|
|
|
|
|
|
|
|
The following startup sequence is recommened for clients which make use of
|
|
|
|
the websocket:
|
|
|
|
1) Attempt to connect to `/websocket` until successful using a timer-like
|
|
|
|
mechanism
|
2020-09-03 15:55:49 +03:00
|
|
|
2) Once connected, query `/printer/info` (or `printer.info`) for the ready
|
2020-07-02 04:21:35 +03:00
|
|
|
status.
|
|
|
|
- If the response returns an error (such as 404), set a timeout for
|
|
|
|
2 seconds and try again.
|
2020-08-15 14:02:42 +03:00
|
|
|
- If the response returns success, check the result's `state` attribute
|
|
|
|
- If `state == "ready"` you may proceed to request status of printer objects
|
2020-07-02 04:21:35 +03:00
|
|
|
make subscriptions, get the file list, etc.
|
2020-08-15 14:02:42 +03:00
|
|
|
- If `state == "error"` then Klippy has experienced an error
|
2020-07-02 04:21:35 +03:00
|
|
|
- If an error is detected it might be wise to prompt the user. You can
|
2020-08-15 14:02:42 +03:00
|
|
|
get a description of the error from the `state_message` attribute
|
|
|
|
- If `state == "shutdown"` then Klippy is in a shutdown state.
|
|
|
|
- If `state == "startup"` then re-request printer info in 2s.
|
2020-07-02 04:21:35 +03:00
|
|
|
- Repeat step 2s until Klipper reports ready. T
|
2020-09-03 15:55:49 +03:00
|
|
|
- Client's should watch for the `notify_klippy_disconnected` event. If it reports
|
2020-07-02 04:21:35 +03:00
|
|
|
disconnected then Klippy has either been stopped or restarted. In this
|
|
|
|
instance the client should repeat the steps above to determine when
|
|
|
|
klippy is ready.
|