This guide walks you through the process of creating a new plugin for InkyPi.
-
Navigate to the
src/plugins
directory. -
Create a new directory named after your plugin. The directory name will be the
id
of your plugin and should be all lowercase with no spaces. Example:mkdir plugins/clock
- Inside your new plugin directory, create a Python file with the same name as the directory.
- Define a class in the file that inherits from
BasePlugin
. - In your new class, implement the
generate_image
function- Arguments:
settings
: A dictionary of plugin configuration values from the form inputs in the web UI.device_config
: An instance of the Config class, used to retrieve device configurations such as display resolution or dotenv keys for any secrets.
- Images can be generated via the Pillow library or rendered from HTML and CSS file, see See Generating Images by Rendering HTML and CSS for details.
- Return a single
PIL.Image
object to be displayed - If there are any issues (e.g., missing configuration options or API keys), raise a
RuntimeError
exception with a clear and concise message to be displayed in the web UI.
- Arguments:
- (Optional) If your settings template requires any additional variables, override the default
generate_settings_template
function- In this function, call
BasePlugin
'sgenerate_settings_template
method to retrieve the default template parameters. Add any extra key-value pairs needed for your template and return the updated dictionary. - To add the predefined style settings (see the Weather and AI Text plugins in the Web UI) to your plugin settings page, set
style_settings
to True. - Example:
def generate_settings_template(self): template_params = super().generate_settings_template() template_params['custom_template_variable'] = self.get_custom_variable() template_params['style_settings'] = True return template_params
- In this function, call
- (Optional) If your plugin needs to cache or store data across refreshes, you can manage this within the
generate_image
function.- For example, you can retrieve and update values as follows:
def generate_image(self, settings, device_config): # retrieve stored value with a default cached_index = settings.get("index", 0) # update value for next refresh settings["index"] = settings["index"] + 1
- For example, you can retrieve and update values as follows:
If your plugin requires user configuration through the web UI, you’ll need to define a settings template.
- In your plugin directory, create a
settings.html
file - Inside this file, define HTML input elements for any settings required by your plugin:
- The
name
attribute of each input element will be passed as keys in thesettings
argument of thegenerate_image
function
- The
- Any template variables added in
generate_settings_template
function will be accessible in the settings template. This is useful for dynamic content, such as populating options in a dropdown menu. - Ensure the settings template visually matches the style of the existing web UI and other plugin templates for consistency.
- When a plugin is added to a playlist, editing the plugin instance should prepopulate the form with the current settings, and saving changes should update the settings accordingly.
- Create an
icon.png
file in your plugin’s directory. This will be the icon displayed in the web UI.- Ensure the icon visually matches the style of existing icons in the project.
- Open the
src/plugins/plugins.json
file. - Add an entry for your plugin using the following structure:
{ "display_name": "Clock", # The name shown in the web UI for the plugin. "id": "clock", # A unique identifier for the plugin (use lowercase and avoid spaces) "class": "Clock" # The name of your plugin’s Python class. }
- Restart the InkyPi service by running
sudo systemctl restart inkypi.service
- Test and ensure that your plugin:
- Loads correctly on service start.
- Appears under the "Plugins" section in the web UI with it's icon.
- Generates images for different display sizes and orientations.
- Settings template is rendered correctly.
- Generates and displays images with immediate updates and in a playlist.
- Setting template is prepopulated and saved correctly when editing an existing playlist
Here’s how your plugin directory should look:
plugins/{plugin_id}/
├── {plugin_id}.py # Main plugin script
├── icon.png # Plugin icon
├── settings.html # Optional: Plugin settings page (if applicable)
├── render/ # Optional: If generating images from html and css files, store them here
└── {other files/resources} # Any additional files or resources used by the plugin
When a plugin is added to a playlist, a "Plugin Instance" is created, and its settings are stored in the src/config/device.json
file. These settings can be updated from the playlist page, so the form in settings.html should be prepopulated with the existing settings.
- The
loadPluginSettings
variable should be checked to ensure the settings page is in "edit" mode. - Plugin settings are accessible via the
pluginSettings
object. - Example:
document.addEventListener('DOMContentLoaded', () => { if (loadPluginSettings) { # Text Input document.getElementById('{textInputElementId}').value = pluginSettings.textInpuElementName || ''; # Radio document.querySelector(`input[name="radioElementName"][value="${pluginSettings.radioElementName}"]`).checked = true; # Color Input document.getElementById('{colorInputElementId}').value = pluginSettings.colorInputElementName ... } });
For more complex plugins or dashboards that display dynamic content, you can generate images from HTML and CSS files.
You can generate an image by calling the BasePlugin
's render_image
function, which accepts the following arguments:
dimensions
(tuple) The width and height of the generated image.html_file
(str) Name of the HTML file to render, located in therender/
directory.css_file
(str, optional) Name of the CSS file in therender/
directory.template_params
(dict, optional) A dictionary of values to be passed into the Jinja template.
- Place your HTML and CSS files in the
render/
subdirectory, asrender_image
looks for them there. - Your HTML file should extend
BasePlugin
'splugin.html
and define its content like this:
{% extends "plugin.html" %}
{% block content %}
<!-- Your content here -->
{% endblock %}
- The
plugin.html
base template includes all font faces found in thestatic/fonts/
directory, making them available for use in your templates - The base template also handles style options such as text color, background image or color, margin and frame settings. To apply these styles, pass the
settings
parameter from thegenerate_image
function as part of template_params argument with theplugin_settings
key.
For reference, see the Weather and AI Text plugins.
- The
render_image
function renders the HTML template using the Jinja2 library. - It then calls the
take_screenshot_html
function inimage_utils.py
. - This function uses the Chromium Browser in headless mode to load the HTML file and capture a screenshot.