Available plugin mixins

The following plugin mixins are currently available:

Please note that all plugin mixins inherit from Plugin and OctoPrintPlugin, which also provide attributes of interest to plugin developers.

StartupPlugin

class octoprint.plugin.StartupPlugin

The StartupPlugin allows hooking into the startup of OctoPrint. It can be used to start up additional services on or just after the startup of the server.

on_after_startup()

Called just after launch of the server, so when the listen loop is actually running already.

on_startup(host, port)

Called just before the server is actually launched. Plugins get supplied with the host and port the server will listen on. Note that the host may be 0.0.0.0 if it will listen on all interfaces, so you can’t just blindly use this for constructing publicly reachable URLs. Also note that when this method is called, the server is not actually up yet and none of your plugin’s APIs or blueprints will be reachable yet. If you need to be externally reachable, use on_after_startup() instead or additionally.

Parameters:
  • host (string) – the host the server will listen on, may be 0.0.0.0
  • port (int) – the port the server will listen on

ShutdownPlugin

class octoprint.plugin.ShutdownPlugin

The ShutdownPlugin allows hooking into the shutdown of OctoPrint. It’s usually used in conjunction with the StartupPlugin mixin, to cleanly shut down additional services again that where started by the StartupPlugin part of the plugin.

on_shutdown()

Called upon the imminent shutdown of OctoPrint.

SettingsPlugin

class octoprint.plugin.SettingsPlugin

Including the SettingsPlugin mixin allows plugins to store and retrieve their own settings within OctoPrint’s configuration.

Plugins including the mixing will get injected an additional property self._settings which is an instance of PluginSettingsManager already properly initialized for use by the plugin. In order for the manager to know about the available settings structure and default values upon initialization, implementing plugins will need to provide a dictionary with the plugin’s default settings through overriding the method get_settings_defaults(). The defined structure will then be available to access through the settings manager available as self._settings.

If your plugin needs to react to the change of specific configuration values on the fly, e.g. to adjust the log level of a logger when the user changes a corresponding flag via the settings dialog, you can override the on_settings_save() method and wrap the call to the implementation from the parent class with retrieval of the old and the new value and react accordingly.

Example:

import octoprint.plugin

class MySettingsPlugin(octoprint.plugin.SettingsPlugin, octoprint.plugin.StartupPlugin):
    def get_settings_defaults(self):
        return dict(
            some_setting="foo",
            some_value=23,
            sub=dict(
                some_flag=True
            )
        )

    def on_settings_save(self, data):
        old_flag = self._settings.get_boolean(["sub", "some_flag"])

        octoprint.plugin.SettingsPlugin.on_settings_save(self, data)

        new_flag = self._settings.get_boolean(["sub", "some_flag"])
        if old_flag != new_flag:
            self._logger.info("sub.some_flag changed from {old_flag} to {new_flag}".format(**locals()))

    def on_after_startup(self):
        some_setting = self._settings.get(["some_setting"])
        some_value = self._settings.get_int(["some_value"])
        some_flag = self._settings.get_boolean(["sub", "some_flag"])
        self._logger.info("some_setting = {some_setting}, some_value = {some_value}, sub.some_flag = {some_flag}".format(**locals())

__plugin_implementation__ = MySettingsPlugin()

Of course, you are always free to completely override both on_settings_load() and on_settings_save() if the default implementations do not fit your requirements.

_settings

The PluginSettings instance to use for accessing the plugin’s settings. Injected by the plugin core system upon initialization of the implementation.

config_version_key = '_config_version'

Key of the field in the settings that holds the configuration format version.

get_settings_defaults()

Retrieves the plugin’s default settings with which the plugin’s settings manager will be initialized.

Override this in your plugin’s implementation and return a dictionary defining your settings data structure with included default values.

get_settings_preprocessors()

Retrieves the plugin’s preprocessors to use for preprocessing returned or set values prior to returning/setting them.

The preprocessors should be provided as a dictionary mapping the path of the values to preprocess (hierarchically) to a transform function which will get the value to transform as only input and should return the transformed value.

Example:

def get_settings_defaults(self):
    return dict(some_key="Some_Value", some_other_key="Some_Value")

def get_settings_preprocessors(self):
    return dict(some_key=lambda x: x.upper()),        # getter preprocessors
           dict(some_other_key=lambda x: x.lower())   # setter preprocessors

def some_method(self):
    # getting the value for "some_key" should turn it to upper case
    assert self._settings.get(["some_key"]) == "SOME_VALUE"

    # the value for "some_other_key" should be left alone
    assert self._settings.get(["some_other_key"] = "Some_Value"

    # setting a value for "some_other_key" should cause the value to first be turned to lower case
    self._settings.set(["some_other_key"], "SOME_OTHER_VALUE")
    assert self._settings.get(["some_other_key"]) == "some_other_value"
Returns:A tuple consisting of two dictionaries, the first being the plugin’s preprocessors for getters, the second the preprocessors for setters
Return type:(dict, dict)
get_settings_restricted_paths()

Retrieves the list of paths in the plugin’s settings which be restricted on the REST API.

Override this in your plugin’s implementation to restrict whether a path should only be returned to logged in users & admins, only to admins, or never on the REST API.

Return a dict with the keys admin, user, never mapping to a list of paths (as tuples or lists of the path elements) for which to restrict access via the REST API accordingly. Paths returned for the admin key will only be available on the REST API when access with admin rights, user will only be available when accessed as a logged in user. never will never be returned on the API.

Example:

def get_settings_defaults(self):
    return dict(some=dict(admin_only=dict(path="path", foo="foo"),
                          user_only=dict(path="path", bar="bar")),
                another=dict(admin_only=dict(path="path"),
                             field="field"),
                path=dict(to=dict(never=dict(return="return"))))

def get_settings_restricted_path(self):
    return dict(admin=[["some", "admin_only", "path], ["another", "admin_only", "path"],
                user=[["some", "user_only", "path"],],
                never=[["path", "to", "never", "return"],])

# this will make the plugin return settings on the REST API like this for an anonymous user
#
#     dict(some=dict(admin_only=dict(path=None, foo="foo"),
#                    user_only=dict(path=None, bar="bar")),
#          another=dict(admin_only=dict(path=None),
#                       field="field"),
#          path=dict(to=dict(never=dict(return=None))))
#
# like this for a logged in user
#
#     dict(some=dict(admin_only=dict(path=None, foo="foo"),
#                    user_only=dict(path="path", bar="bar")),
#          another=dict(admin_only=dict(path=None),
#                       field="field"),
#          path=dict(to=dict(never=dict(return=None))))
#
# and like this for an admin user
#
#     dict(some=dict(admin_only=dict(path="path", foo="foo"),
#                    user_only=dict(path="path", bar="bar")),
#          another=dict(admin_only=dict(path="path"),
#                       field="field"),
#          path=dict(to=dict(never=dict(return=None))))
get_settings_version()

Retrieves the settings format version of the plugin.

Use this to have OctoPrint trigger your migration function if it detects an outdated settings version in config.yaml.

Returns:an int signifying the current settings format, should be incremented by plugins whenever there are backwards incompatible changes. Returning None here disables the version tracking for the plugin’s configuration.
Return type:int or None
on_settings_cleanup()

Called after migration and initialization but before call to on_settings_initialized().

Plugins may overwrite this method to perform additional clean up tasks.

The default implementation just minimizes the data persisted on disk to only contain the differences to the defaults (in case the current data was persisted with an older version of OctoPrint that still duplicated default data).

on_settings_initialized()

Called after the settings have been initialized and - if necessary - also been migrated through a call to func:on_settings_migrate.

This method will always be called after the initialize method.

on_settings_load()

Loads the settings for the plugin, called by the Settings API view in order to retrieve all settings from all plugins. Override this if you want to inject additional settings properties that are not stored within OctoPrint’s configuration.

Note

The default implementation will return your plugin’s settings as is, so just in the structure and in the types that are currently stored in OctoPrint’s configuration.

If you need more granular control here, e.g. over the used data types, you’ll need to override this method and iterate yourself over all your settings, using the proper retriever methods on the settings manager to retrieve the data in the correct format.

The default implementation will also replace any paths that have been restricted by your plugin through get_settings_restricted_paths() with either the provided default value (if one was provided), an empty dictionary (as fallback for restricted dictionaries), an empty list (as fallback for restricted lists) or None values where necessary. Make sure to do your own restriction if you decide to fully overload this method.

Returns:the current settings of the plugin, as a dictionary
on_settings_migrate(target, current)

Called by OctoPrint if it detects that the installed version of the plugin necessitates a higher settings version than the one currently stored in _config.yaml. Will also be called if the settings data stored in config.yaml doesn’t have version information, in which case the current parameter will be None.

Your plugin’s implementation should take care of migrating any data by utilizing self._settings. OctoPrint will take care of saving any changes to disk by calling self._settings.save() after returning from this method.

This method will be called before your plugin’s on_settings_initialized() method, with all injections already having taken place. You can therefore depend on the configuration having been migrated by the time on_settings_initialized() is called.

Parameters:
  • target (int) – The settings format version the plugin requires, this should always be the same value as returned by get_settings_version().
  • current (int or None) – The settings format version as currently stored in config.yaml. May be None if no version information can be found.
on_settings_save(data)

Saves the settings for the plugin, called by the Settings API view in order to persist all settings from all plugins. Override this if you need to directly react to settings changes or want to extract additional settings properties that are not stored within OctoPrint’s configuration.

Note

The default implementation will persist your plugin’s settings as is, so just in the structure and in the types that were received by the Settings API view. Values identical to the default settings values will not be persisted.

If you need more granular control here, e.g. over the used data types, you’ll need to override this method and iterate yourself over all your settings, retrieving them (if set) from the supplied received data and using the proper setter methods on the settings manager to persist the data in the correct format.

Parameters:data (dict) – The settings dictionary to be saved for the plugin
Returns:The settings that differed from the defaults and were actually saved.
Return type:dict

AssetPlugin

class octoprint.plugin.AssetPlugin

The AssetPlugin mixin allows plugins to define additional static assets such as Javascript or CSS files to be automatically embedded into the pages delivered by the server to be used within the client sided part of the plugin.

A typical usage of the AssetPlugin functionality is to embed a custom view model to be used by templates injected through a TemplatePlugin.

get_asset_folder()

Defines the folder where the plugin stores its static assets as defined in get_assets(). Override this if your plugin stores its assets at some other place than the static sub folder in the plugin base directory.

Return string:the absolute path to the folder where the plugin stores its static assets
get_assets()

Defines the static assets the plugin offers. The following asset types are recognized and automatically imported at the appropriate places to be available:

js
Javascript files, such as additional view models
css
CSS files with additional styles, will be embedded into delivered pages when not running in LESS mode.
less
LESS files with additional styles, will be embedded into delivered pages when running in LESS mode.

The expected format to be returned is a dictionary mapping one or more of these keys to a list of files of that type, the files being represented as relative paths from the asset folder as defined via get_asset_folder(). Example:

def get_assets(self):
    return dict(
        js=['js/my_file.js', 'js/my_other_file.js'],
        css=['css/my_styles.css'],
        less=['less/my_styles.less']
     )

The assets will be made available by OctoPrint under the URL /plugin/<plugin identifier>/static/<path>, with plugin identifier being the plugin’s identifier and path being the path as defined in the asset dictionary.

Assets of the types js, css and less will be automatically bundled by OctoPrint using Flask-Assets.

Return dict:a dictionary describing the static assets to publish for the plugin

TemplatePlugin

class octoprint.plugin.TemplatePlugin

Using the TemplatePlugin mixin plugins may inject their own components into the OctoPrint web interface.

Currently OctoPrint supports the following types of injections out of the box:

Navbar

The right part of the navigation bar located at the top of the UI can be enriched with additional links. Note that with the current implementation, plugins will always be located to the left of the existing links.

The included template must be called <plugin identifier>_navbar.jinja2 (e.g. myplugin_navbar.jinja2) unless overridden by the configuration supplied through get_template_configs().

The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The wrapper structure will have all additional classes and styles applied as specified via the configuration supplied through get_template_configs().

Sidebar

The left side bar containing Connection, State and Files sections can be enriched with additional sections. Note that with the current implementations, plugins will always be located beneath the existing sections.

The included template must be called <plugin identifier>_sidebar.jinja2 (e.g. myplugin_sidebar.jinja2) unless overridden by the configuration supplied through get_template_configs().

The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The wrapper divs for both the whole box as well as the content pane will have all additional classes and styles applied as specified via the configuration supplied through get_template_configs().

Tabs

The available tabs of the main part of the interface may be extended with additional tabs originating from within plugins. Note that with the current implementation, plugins will always be located to the right of the existing tabs.

The included template must be called <plugin identifier>_tab.jinja2 (e.g. myplugin_tab.jinja2) unless overridden by the configuration supplied through get_template_configs().

The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The wrapper div and the link in the navigation will have the additional classes and styles applied as specified via the configuration supplied through get_template_configs().

Settings

Plugins may inject a dialog into the existing settings view. Note that with the current implementations, plugins will always be listed beneath the “Plugins” header in the settings link list, ordered alphabetically after their displayed name.

The included template must be called <plugin identifier>_settings.jinja2 (e.g. myplugin_settings.jinja2) unless overridden by the configuration supplied through get_template_configs().

The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The wrapper div and the link in the navigation will have the additional classes and styles applied as defined via the supplied configuration supplied through get_template_configs().

Generic
Plugins may also inject arbitrary templates into the page of the web interface itself, e.g. in order to add overlays or dialogs to be called from within the plugin’s javascript code.
Template injection types in the main part of the interface

Fig. 7 Template injection types in the main part of the interface

Template injection types in the settings

Fig. 8 Template injection types in the settings

You can find an example for a simple plugin which injects navbar, tab and settings content into the interface in the “helloworld” plugin in OctoPrint’s Plugin Tutorial.

Plugins may replace existing components, see the replaces keyword in the template configurations returned by get_template_configs() below. Note that if a plugin replaces a core component, it is the plugin’s responsibility to ensure that all core functionality is still maintained.

Plugins can also add additional template types by implementing the octoprint.ui.web.templatetypes hook.

get_template_configs()

Allows configuration of injected navbar, sidebar, tab and settings templates (and also additional templates of types specified by plugins through the octoprint.ui.web.templatetypes hook). Should be a list containing one configuration object per template to inject. Each configuration object is represented by a dictionary which may contain the following keys:

type The template type the configuration is targeting. Possible values here are navbar, sidebar, tab, settings and generic. Mandatory.
name

The name of the component, if not set the name of the plugin will be used. The name will be visible at a location depending on the type:

  • navbar: unused
  • sidebar: sidebar heading
  • tab: tab heading
  • settings: settings link
  • generic: unused
template

Name of the template to inject, default value depends on the type:

  • navbar: <plugin identifier>_navbar.jinja2
  • sidebar: <plugin identifier>_sidebar.jinja2
  • tab: <plugin identifier>_tab.jinja2
  • settings: <plugin identifier>_settings.jinja2
  • generic: <plugin identifier>.jinja2
suffix

Suffix to attach to the component identifier and the div identifier of the injected template. Will be _<index> if not provided and not the first template of the type, with index counting from 1 and increasing for each template of the same type.

Example: If your plugin with identifier myplugin defines two tab components like this:

return [
    dict(type="tab", template="myplugin_first_tab.jinja2"),
    dict(type="tab", template="myplugin_second_tab.jinja2")
]

then the first tab will have the component identifier plugin_myplugin and the second one will have the component identifier plugin_myplugin_2 (the generated divs will be tab_plugin_myplugin and tab_plugin_myplugin_2 accordingly). Notice that the first tab is not called plugin_myplugin_1 – as stated above while the index used as default suffix starts counting at 1, it will not be applied for the first component of a given type.

If on the other hand your plugin’s definition looks like this:

return [
    dict(type="tab", template="myplugin_first_tab_jinja2", suffix="_1st"),
    dict(type="tab", template="myplugin_second_tab_jinja2", suffix="_2nd")
]

then the generated component identifier will be plugin_myplugin_1st and plugin_myplugin_2nd (and the divs will be tab_plugin_myplugin_1st and tab_plugin_myplugin_2nd).

div Id for the div containing the component. If not provided, defaults to <type>_plugin_<plugin identifier> plus the suffix if provided or required.
replaces Id of the component this one replaces, might be either one of the core components or a component provided by another plugin. A list of the core component identifiers can be found in the configuration documentation. The identifiers of other plugin components always follow the format described above.
custom_bindings A boolean value indicating whether the default view model should be bound to the component (false) or if a custom binding will be used by the plugin (true, default).
data_bind Additional knockout data bindings to apply to the component, can be used to add further behaviour to the container based on internal state if necessary.
classes Additional classes to apply to the component, as a list of individual classes (e.g. classes=["myclass", "myotherclass"]) which will be joined into the correct format by the template engine.
styles Additional CSS styles to apply to the component, as a list of individual declarations (e.g. styles=["color: red", "display: block"]) which will be joined into the correct format by the template engine.

Further keys to be included in the dictionary depend on the type:

sidebar type

icon Icon to use for the sidebar header, should be the name of a Font Awesome icon without the leading icon- part.
template_header Additional template to include in the head section of the sidebar item. For an example of this, see the additional options included in the “Files” section.
classes_wrapper Like classes but only applied to the whole wrapper around the sidebar box.
classes_content Like classes but only applied to the content pane itself.
styles_wrapper Like styles but only applied to the whole wrapper around the sidebar box.
styles_content Like styles but only applied to the content pane itself

tab type and settings type

classes_link Like classes but only applied to the link in the navigation.
classes_content Like classes but only applied to the content pane itself.
styles_link Like styles but only applied to the link in the navigation.
styles_content Like styles but only applied to the content pane itself.

Note

As already outlined above, each template type has a default template name (i.e. the default navbar template of a plugin is called <plugin identifier>_navbar.jinja2), which may be overridden using the template configuration. If a plugin needs to include more than one template of a given type, it needs to provide an entry for each of those, since the implicit default template will only be included automatically if no other templates of that type are defined.

Example: If you have a plugin that injects two tab components, one defined in the template file myplugin_tab.jinja2 (the default template) and one in the template myplugin_othertab.jinja2, you might be tempted to just return the following configuration since one your templates is named by the default template name:

return [
    dict(type="tab", template="myplugin_othertab.jinja2")
]

This will only include the tab defined in myplugin_othertab.jinja2 though, myplugin_tab.jinja2 will not be included automatically since the presence of a defintion for the tab type overrides the automatic injection of the default template. You’ll have to include it explicitely:

return [
    dict(type="tab", template="myplugin_tab.jinja2"),
    dict(type="tab", template="myplugin_othertab.jinja2")
]
Return list:a list containing the configuration options for the plugin’s injected templates
get_template_folder()

Defines the folder where the plugin stores its templates. Override this if your plugin stores its templates at some other place than the templates sub folder in the plugin base directory.

Return string:the absolute path to the folder where the plugin stores its jinja2 templates
get_template_vars()

Defines additional template variables to include into the template renderer. Variable names will be prefixed with plugin_<plugin identifier>_.

Return dict:a dictionary containing any additional template variables to include in the renderer

SimpleApiPlugin

class octoprint.plugin.SimpleApiPlugin

Utilizing the SimpleApiPlugin mixin plugins may implement a simple API based around one GET resource and one resource accepting JSON commands POSTed to it. This is the easy alternative for plugin’s which don’t need the full power of a Flask Blueprint that the BlueprintPlugin mixin offers.

Use this mixin if all you need to do is return some kind of dynamic data to your plugin from the backend and/or want to react to simple commands which boil down to a type of command and a couple of flat parameters supplied with it.

The simple API constructed by OctoPrint for you will be made available under /api/plugin/<plugin identifier>/. OctoPrint will do some preliminary request validation for your defined commands, making sure the request body is in the correct format (content type must be JSON) and contains all obligatory parameters for your command.

Let’s take a look at a small example for such a simple API and how you would go about calling it.

Take this example of a plugin registered under plugin identifier mysimpleapiplugin:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import octoprint.plugin

import flask

class MySimpleApiPlugin(octoprint.plugin.SimpleApiPlugin):
    def get_api_commands(self):
        return dict(
            command1=[],
            command2=["some_parameter"]
        )

    def on_api_command(self, command, data):
        import flask
        if command == "command1":
            parameter = "unset"
            if "parameter" in data:
                parameter = "set"
            self._logger.info("command1 called, parameter is {parameter}".format(**locals()))
        elif command == "command2":
            self._logger.info("command2 called, some_parameter is {some_parameter}".format(**data))

    def on_api_get(self, request):
        return flask.jsonify(foo="bar")

__plugin_implementation__ = MySimpleApiPlugin()

Our plugin defines two commands, command1 with no mandatory parameters and command2 with one mandatory parameter some_parameter.

command1 can also accept an optional parameter parameter, and will log whether that parameter was set or unset. command2 will log the content of the mandatory some_parameter parameter.

A valid POST request for command2 sent to /api/plugin/mysimpleapiplugin would look like this:

POST /api/plugin/mysimpleapiplugin HTTP/1.1
Host: example.com
Content-Type: application/json
X-Api-Key: abcdef...

{
  "command": "command2",
  "some_parameter": "some_value",
  "some_optional_parameter": 2342
}

which would produce a response like this:

HTTP/1.1 204 No Content

and print something like this line to octoprint.log:

2015-02-12 17:40:21,140 - octoprint.plugins.mysimpleapiplugin - INFO - command2 called, some_parameter is some_value

A GET request on our plugin’s simple API resource will only return a JSON document like this:

HTTP/1.1 200 Ok
Content-Type: application/json

{
  "foo": "bar"
}
get_api_commands()

Return a dictionary here with the keys representing the accepted commands and the values being lists of mandatory parameter names.

is_api_adminonly()

Return True if the API is only available to users having the admin role.

on_api_command(command, data)

Called by OctoPrint upon a POST request to /api/plugin/<plugin identifier>. command will contain one of the commands as specified via get_api_commands(), data will contain the full request body parsed from JSON into a Python dictionary. Note that this will also contain the command attribute itself. For the example given above, for the command2 request the data received by the plugin would be equal to dict(command="command2", some_parameter="some_value").

If your plugin returns nothing here, OctoPrint will return an empty response with return code 204 No content for you. You may also return regular responses as you would return from any Flask view here though, e.g. return flask.jsonify(result="some json result") or return flask.make_response("Not found", 404).

Parameters:
  • command (string) – the command with which the resource was called
  • data (dict) – the full request body of the POST request parsed from JSON into a Python dictionary
Returns:

None in which case OctoPrint will generate a 204 No content response with empty body, or optionally a proper Flask response.

on_api_get(request)

Called by OctoPrint upon a GET request to /api/plugin/<plugin identifier>. request will contain the received Flask request object which you may evaluate for additional arguments supplied with the request.

If your plugin returns nothing here, OctoPrint will return an empty response with return code 204 No content for you. You may also return regular responses as you would return from any Flask view here though, e.g. return flask.jsonify(result="some json result") or return flask.make_response("Not found", 404).

Parameters:request – the Flask request object
Returns:None in which case OctoPrint will generate a 204 No content response with empty body, or optionally a proper Flask response.

BlueprintPlugin

class octoprint.plugin.BlueprintPlugin

The BlueprintPlugin mixin allows plugins to define their own full fledged endpoints for whatever purpose, be it a more sophisticated API than what is possible via the SimpleApiPlugin or a custom web frontend.

The mechanism at work here is Flask’s own Blueprint mechanism.

The mixin automatically creates a blueprint for you that will be registered under /plugin/<plugin identifier>/. All you need to do is decorate all of your view functions with the route() decorator, which behaves exactly the same like Flask’s regular route decorators. Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import octoprint.plugin
import flask

class MyBlueprintPlugin(octoprint.plugin.BlueprintPlugin):
    @octoprint.plugin.BlueprintPlugin.route("/echo", methods=["GET"])
    def myEcho(self):
        if not "text" in flask.request.values:
            return flask.make_response("Expected a text to echo back.", 400)
        return flask.request.values["text"]

__plugin_implementation__ = MyBlueprintPlugin()

Your blueprint will be published by OctoPrint under the base URL /plugin/<plugin identifier>/, so the above example of a plugin with the identifier “myblueprintplugin” would be reachable under /plugin/myblueprintplugin/echo.

Just like with regular blueprints you’ll be able to create URLs via url_for, just use the prefix plugin.<plugin identifier>.<method_name>, e.g.:

flask.url_for("plugin.myblueprintplugin.myEcho") # will return "/plugin/myblueprintplugin/echo"
static errorhandler(code_or_exception)

A decorator to mark errorhandlings methods in your BlueprintPlugin subclass. Works just the same as Flask’s own errorhandler decorator available on blueprints.

See the documentation for flask.Blueprint.errorhandler and the documentation for flask.Flask.errorhandler for more information.

get_blueprint()

Creates and returns the blueprint for your plugin. Override this if you want to define and handle your blueprint yourself.

This method will only be called once during server initialization.

Returns:the blueprint ready to be registered with Flask
get_blueprint_kwargs()

Override this if you want your blueprint constructed with additional options such as static_folder, template_folder, etc.

Defaults to the blueprint’s static_folder and template_folder to be set to the plugin’s basefolder plus /static or respectively /templates, or – if the plugin also implements AssetPlugin and/or TemplatePlugin – the paths provided by get_asset_folder and get_template_folder respectively.

is_blueprint_protected()

Whether a valid API key is needed to access the blueprint (the default) or not. Note that this only restricts access to the blueprint’s dynamic methods, static files are always accessible without API key.

static route(rule, **options)

A decorator to mark view methods in your BlueprintPlugin subclass. Works just the same as Flask’s own route decorator available on blueprints.

See the documentation for flask.Blueprint.route and the documentation for flask.Flask.route for more information.

EventHandlerPlugin

class octoprint.plugin.EventHandlerPlugin

The EventHandlerPlugin mixin allows OctoPrint plugins to react to any of OctoPrint’s events. OctoPrint will call the on_event() method for any event fired on its internal event bus, supplying the event type and the associated payload. Please note that until your plugin returns from that method, further event processing within OctoPrint will block - the event queue itself is run asynchronously from the rest of OctoPrint, but the processing of the events within the queue itself happens consecutively.

This mixin is especially interesting for plugins which want to react on things like print jobs finishing, timelapse videos rendering etc.

on_event(event, payload)

Called by OctoPrint upon processing of a fired event on the platform.

Parameters:
  • event (str) – The type of event that got fired, see the list of events for possible values
  • payload (dict) – The payload as provided with the event

ProgressPlugin

class octoprint.plugin.ProgressPlugin

Via the ProgressPlugin mixing plugins can let themselves be called upon progress in print jobs or slicing jobs, limited to minimally 1% steps.

on_print_progress(storage, path, progress)

Called by OctoPrint on minimally 1% increments during a running print job.

Parameters:
  • location (string) – Location of the file
  • path (string) – Path of the file
  • progress (int) – Current progress as a value between 0 and 100
on_slicing_progress(slicer, source_location, source_path, destination_location, destination_path, progress)

Called by OctoPrint on minimally 1% increments during a running slicing job.

Parameters:
  • slicer (string) – Key of the slicer reporting the progress
  • source_location (string) – Location of the source file
  • source_path (string) – Path of the source file
  • destination_location (string) – Location the destination file
  • destination_path (string) – Path of the destination file
  • progress (int) – Current progress as a value between 0 and 100

SlicerPlugin

class octoprint.plugin.SlicerPlugin

Via the SlicerPlugin mixin plugins can add support for slicing engines to be used by OctoPrint.

cancel_slicing(machinecode_path)

Cancels the slicing to the indicated file.

Parameters:machinecode_path (str) – The absolute path to the machine code file to which to stop slicing to.
do_slice(model_path, printer_profile, machinecode_path=None, profile_path=None, position=None, on_progress=None, on_progress_args=None, on_progress_kwargs=None)

Called by OctoPrint to slice model_path for the indicated printer_profile. If the machinecode_path is None, slicer implementations should generate it from the provided model_path.

If provided, the profile_path is guaranteed by OctoPrint to be a serialized slicing profile created through the slicing plugin’s own save_slicer_profile() method.

If provided, position will be a dict containing and x and a y key, indicating the position the center of the model on the print bed should have in the final sliced machine code. If not provided, slicer implementations should place the model in the center of the print bed.

on_progress will be a callback which expects an additional keyword argument _progress with the current slicing progress which - if progress reporting is supported - the slicing plugin should call like the following:

if on_progress is not None:
    if on_progress_args is None:
        on_progress_args = ()
    if on_progress_kwargs is None:
        on_progress_kwargs = dict()

    on_progress_kwargs["_progress"] = your_plugins_slicing_progress
    on_progress(*on_progress_args, **on_progress_kwargs)

Please note that both on_progress_args and on_progress_kwargs as supplied by OctoPrint might be None, so always make sure to initialize those values to sane defaults like depicted above before invoking the callback.

In order to support external cancellation of an ongoing slicing job via cancel_slicing(), implementations should make sure to track the started jobs via the machinecode_path, if provided.

The method should return a 2-tuple consisting of a boolean flag indicating whether the slicing job was finished successfully (True) or not (False) and a result depending on the success of the slicing job.

For jobs that finished successfully, result should be a dict containing additional information about the slicing job under the following keys:

_analysis
Analysis result of the generated machine code as returned by the slicer itself. This should match the data structure described for the analysis queue of the matching maching code format, e.g. GcodeAnalysisQueue for GCODE files.

For jobs that did not finish successfully (but not due to being cancelled!), result should be a str containing a human readable reason for the error.

If the job gets cancelled, a SlicingCancelled exception should be raised.

Returns:A 2-tuple (boolean, object) as outlined above.
Return type:tuple
Raises:SlicingCancelled – The slicing job was cancelled (via cancel_slicing()).
get_slicer_default_profile()

Should return a SlicingProfile containing the default slicing profile to use with this slicer if no other profile has been selected.

Returns:The SlicingProfile containing the default slicing profile for this slicer.
Return type:SlicingProfile
get_slicer_profile(path)

Should return a SlicingProfile parsed from the slicing profile stored at the indicated path.

Parameters:path (str) – The absolute path from which to read the slicing profile.
Returns:The specified slicing profile.
Return type:SlicingProfile
get_slicer_properties()

Plugins should override this method to return a dict containing a bunch of meta data about the implemented slicer.

The expected keys in the returned dict have the following meaning:

type
The type identifier to use for the slicer. This should be a short unique lower case string which will be used to store slicer profiles under or refer to the slicer programmatically or from the API.
name
The human readable name of the slicer. This will be displayed to the user during slicer selection.
same_device
True if the slicer runs on the same device as OctoPrint, False otherwise. Slicers running on the same device will not be allowed to slice while a print is running due to performance reasons. Slice requests against slicers running on the same device will result in an error.
progress_report
True if the slicer can report back slicing progress to OctoPrint False otherwise.
source_file_types
A list of file types this slicer supports as valid origin file types. These are file types as found in the paths within the extension tree. Plugins may add additional file types through the octoprint.filemanager.extension_tree hook. The system will test source files contains in incoming slicing requests via octoprint.filemanager.valid_file_type() against the targeted slicer’s source_file_types.
destination_extension
The possible extensions of slicing result files.
Returns:A dict describing the slicer as outlined above.
Return type:dict
is_slicer_configured()

Unless the return value of this method is True, OctoPrint will not register the slicer within the slicing sub system upon startup. Plugins may use this to do some start up checks to verify that e.g. the path to a slicing binary as set and the binary is executable, or credentials of a cloud slicing platform are properly entered etc.

save_slicer_profile(path, profile, allow_overwrite=True, overrides=None)

Should save the provided SlicingProfile to the indicated path, after applying any supplied overrides. If a profile is already saved under the indicated path and allow_overwrite is set to False (defaults to True), an IOError should be raised.

Parameters:
  • path (str) – The absolute path to which to save the profile.
  • profile (SlicingProfile) – The profile to save.
  • allow_overwrite (boolean) – Whether to allow to overwrite an existing profile at the indicated path (True, default) or not (False). If a profile already exists on teh path and this is False an IOError should be raised.
  • overrides (dict) – Profile overrides to apply to the profile before saving it