OctoPrint for the Seeed Studio reTerminal – Live Blog – Day 4

This post is a series of posts in which I detail my journey to bring OctoPrint to the Seeed Studio reTerminal.

Day 4

In today’s post we’ll be with learning how to make an OctoPrint Plugin including how to make it distributable.


Plugin Development – 08-09-22

I’d left the development environment running last night, and when I returned to VS Code today, there’s a whole heap of yellow debug messages;

OctoPrint – VS Code – Deprecation Warning

The messages are read;

DeprecationWarning: There is no current event loop
  loop = asyncio.get_event_loop()

They seem to be coming from the C:\repos\OctoPrint\venv\lib\site-packages\tornado\ioloop.py file on line 265.

Looking on Google, I don’t see anything obvious relating directly to OctoPrint itself.

This StackOverflow answer by Stephan202 offers the possibility to just ignore deprecation warnings by adding -W ignore::DeprecationWarning as a Python parameter. I guess I could do this as part of the launch.json perhaps?

I’ll leave this alone for now though as I’m keen to get going creating my first plugin!

Returning to the official documentation, the first thing it instructs us to do is make sure that our local development environment is setup, which we did over the last couple of days.

It’s apparently possible to develop plugins directly on the Pi if we like, we simple need to activate the oprintVirtual Environment. We won’t be doing that of course.

Hello World Plugin

First up we need to create a file name helloworld.py in the OctoPrint plugins directory, so let’s go ahead and do that;

OctoPrint Plugins Directory

So, it looks like the path is actually OctoPrint\src\octoprint\plugins.

Creating a file named helloworld.py in that directory, and pasting in the content from the blog;

__plugin_name__ = "Hello World"
__plugin_version__ = "1.0.0"
__plugin_description__ = "A quick \"Hello World\" example plugin for OctoPrint"
__plugin_pythoncompat__ = ">=3.7,<4"

Saving the file and running up OctoPrint, we can have a look at the Console Log;

OctoPrint Console Log – Hello World

We can see that our new helloworld plugin has been loaded successfully. We can also see that it’s picked up the Plugin name and the version of 1.0.0.

Of course, this plugin isn’t actually doing anything at all at the moment, and the docs go on to teach us how we can make our plugin do something.

The next step for us is to replace the contents of our helloworld.py file with;

import octoprint.plugin

class HelloWorldPlugin(octoprint.plugin.StartupPlugin):
    def on_after_startup(self):
        self._logger.info("Hello World!")

__plugin_name__ = "Hello World"
__plugin_version__ = "1.0.0"
__plugin_description__ = "A quick \"Hello World\" example plugin for OctoPrint"
__plugin_pythoncompat__ = ">=3.7,<4"
__plugin_implementation__ = HelloWorldPlugin()

Restarting OctoPrint now gives us our “Hello World” message in the console log;

OctoPrint – Hello World – Console Log

So that’s pretty cool, and really straightforward too.

We can see from what we have in the helloworld.py file now, that we’re using the StartupPlugin plugin mixin that we saw yesterday.

Reminding ourselves of what that plugin does;

The StartupPlugin Mixin

The docs for the StartupPlugin Mixin start with…

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.

So this makes sense in that we’ve seen the message in the log file when we started OctoPrint up.

An Aside – The Death of the Queen

As a note, while I’ve been writing this, the Queen has sadly died…. Sad news indeed;

Queen Elizabeth II has died

Making a Plugin Distributable

The next thing we need to do is convert our single file plugin into something resembling a more complete package which can be installed via the OctoPrint Plugin Manager.

We can do this by first installing the cookiecutter package. A quick google takes us to the official Cookiecutter page on pypi.org, where we learn that Cookiecutter is;

A command-line utility that creates projects from cookiecutters (project templates), e.g. creating a Python package project from a Python package project template.

To install Cookiecutter, we need to use pip in our OctoPrint virtual environment;

pip install "cookiecutter>=1.4,<1.7"

Looking at the command, it seems the docs require a version greater than or equal to 1.4 and less than 1.7… I wonder why we need those specific versions?

Either way, we can open a new Terminal Window, reactivate the Virtual Environment and run the command;

cd c:/repos/OctoPrint
pip install "cookiecutter>=1.4,<1.7"
OctoPrint – Terminal – Install Cookiecutter

With Cookiecutter installed successfully, we can run a command to create a new helloworld plugin;

octoprint dev plugin:new helloworld

Running this command actually prompts us for the plugin_package name;

OctoPrint – New Plugin – Plugin Package Name

I’m guessing I can just hit return to accept the default of octoprint_helloworld;

OctoPrint – New Plugin – Plugin Name

So, hitting return accepts the defaults… So doing this or entering info where I need to, the process completes;

OctoPrint – New Plugin – Created

Looking around in the directories, I find our new plugin folder in the root of the OctoPrint project;

OctoPrint – New plugin – Folder in Project Root

Looking back at the docs, I think perhaps I should’ve run this command in my repos directory rather than in the OctoPrint folder… This makes sense, as otherwise our plugin will become source controlled along with the OctoPrint project…

So, let’s delete the new folder and re-run the command in my repos folder directly…

I guess I could just move the folder, but I mainly want to do that in case there’s some scripting reason I need to move it (I doubt it, but better safe than sorry eh);

OctoPrint – New Plugin – Created (Again)

Checking my repos directory, I can see our new plugin alongside the OctoPrint directory;

OctoPrint – Hello World Plugin Folder

Looking at the contents of our new Plugin older;

OctoPrint – Hello World Plugin Folder Contents

We can see we have a set of folders and files created for us… Reading the docs, it appears we are able to delete some of these files if we like;

  • extras
  • translations
  • octoprint_helloworld/static
  • octoprint_helloworld/templates

With those folders deleted, we can move on. We need to move our existing helloworld.py plugin file to our new plugin and rename it to __init__.py (Thst’s underscore underscore init underscore underscore .py).

Leave a Reply