Introduction to Writing Klippy Extras
This page contains many things that are useful to know before writing Klippy extras.
The config
object
Every Klippy extra is a class. Everything in a Klippy extra starts when the class is initialized, passing a config
object into the class. This config
object allows access to many parts of Klipper discussed next.
The printer
object
This is probably the most useful object you can use in a Klippy extra. This code block below shows how to get it:
It's that simple!
The printer object lets you access all sorts of useful parts of Klippy, which will be explained later in this page.
The gcode
object
The next object you will want to get familiar with is the gcode
object. This code block below shows how to get it:
This gcode
object is useful for many things. Here are a few of its functions:
run_script_from_command
Runs any GCode provided as a stringrespond_info
Displays text to the Klipper terminal; essentially the same as runningRESPOND MSG=
in a macroregister_command
Allows for defining custom GCode commandsregister_mux_command
A different way to definine custom GCode commands. This is explained later in the examples.
For example, if you wanted to run a G28
command (home all axes), you would run:
Configuration options
The config
object also allows reading of the configuration options present in the printer.cfg
file. Here's an example config:
This configuration shows four main option types:
int
float
str
list
To read them, you can use the corresponding functions of config
:
getint
getfloat
get
getlist
Here's how to use them in code:
Tip
To make a configuration option optional, pass another parameter to the get
function as a default value. Example:
Where do Klippy Extras go?
Before we go much further into this tutorial, it's good to know how Klippy reads the extras files. First, there's one last missing part of our Python file:
This is explained later in the examples.
For Klippy to read your extras file, you need to put it in ~/klipper/klippy/extras
. The filename, in this case myextra.py
, becomes the config name, in this case [myextra]
. After putting your file in the extras
folder, you can put a corresponding section into your printer.cfg
and restart Klipper. Your extra is installed!
However, every time you want to change something, you have to copy your file to the extras folder and restart Klipper. This is a very slow way to develop extras, as each Klipper restart turns off your heaters, loses your home position, and wastes too much time.
Fortunately, DynamicMacros provides a better solution.
DynamicMacros
Follow the installation instructions here.
DynamicMacros supports running Python code from a macro. This makes testing parts of Klippy extras much quicker. Here's the current example, as a Klippy extra, excluding the config reading:
Here it is as a DynamicMacro (use the tabs to navigate between the two files):
Now, you can change anything without restarting Klipper! Whenever you change the macro/Python code, simply run the DYNAMIC_MACRO
command to internally refresh DynamicMacros.
Note
This setup is intended for development, and not release, as this approach has a few limitations:
- This approach can't read configuration sections
- This approach isn't as structured as a full Klippy extra
For these reasons, this approach is only intended for testing parts of a Klippy extra, and isn't a replacement of extras.
This tutorial won't go in depth about testing extras with DynamicMacros. Instead, this tutorial focuses on writing traditional Klippy extras.
The reactor
object
Another useful object from the config
object is the reactor
. The code block below shows how to get it:
The reactor opens up a new possibility of Klippy extras: scheduling code to run/repeat at any time. This ability is explained in more detail in the third example.
Other Extras
This is one more good-to-know about Klippy extras before continuing to the examples:
You can access other extras from an extra. This allows for extended capabilities of extras. For example, this project, DynamicMacros invokes the gcode_macro
extra to run macros internally. The code blocks below shows two ways to access any other extra:
Examples
I hope this introduction was helpful. The next part of this tutorial consists of three examples. The first one is linked below: