This post is a series of posts in which I detail my journey to bring OctoPrint to the Seeed Studio reTerminal.
In today’s post we’ll be with learning how to make an OctoPrint Plugin including how to make it distributable.
- Getting Started – 05/09/2022
- My Initial Plans
- Cloning the Repos
- A pointer in the right direction from the folks at OctoPrint3D – Plugins
- OctoPrint Plugin Mixin Development Docs
- Getting the Development Environment setup
- Installing Python
- Checking out the OctoPrint Sources
- Creating and Activating a Virtual Environment
- Build Tools for Visual Studio 2019
- Setting up VirtualEnv
- Adding VirtualEnv to the Windows Path
- Upgrading Pip
- Setting up the Virtual Environment
- OctoEverywhere – 06-09-22
- Continuing with VirtualEnv
- Activating the Virtual Environment
- Setting up the Virtual Environment
- Installing Microsoft Visual C++ 14.0
- Using pip to install packages in the Virtual Environment
- Git Pre-Commit
- Git Changes, Blame and Ignore
- Configuring VS Code
- Running OctoPrint for the first time
- Changing the Python Interpreter
- Running the OctoPrint from VS Code
- Setting up OctoPrint in the Debug Environment – 07-09-22
- Setup Wizard – Access Control
- Setup Wizard – Online Connectivity
- Setup Wizard – Usage Tracking
- Setup Wizard – Plugin Blacklist
- Setup Wizard – Printer Profile
- Setup Wizard – Please Reload
- Setup Wizard – Setup Printer (Again)
- Setup Wizard – Server Commands
- Setup Wizard – Webcam and Timelapse Recordings
- Setup Wizard – Finish
- Virtual 3d Printer Plugin
- Beginning Plugin Development
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;
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;
So, it looks like the path is actually
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;
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;
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…
StartupPluginallows 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;
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 .\venv\Scripts\activate pip install "cookiecutter>=1.4,<1.7"
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
I’m guessing I can just hit return to accept the default of
So, hitting return accepts the defaults… So doing this or entering info where I need to, the process completes;
Looking around in the directories, I find our new plugin folder in the root of the OctoPrint project;
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);
Checking my repos directory, I can see our new plugin alongside the OctoPrint directory;
Looking at the contents of our new Plugin older;
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;
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).