Authoring
Plugins can be written in any language that supports generating wit bindings. This guide explains how to set this up in rust.
Introduction
Litehouse plugins are WebAssembly modules that extend the functionality of the Litehouse home automation system. They can be written in any language that compiles to WebAssembly, offering a wide range of possibilities for automation, integration, and customization.
The build
command
The authoring workflow centers around the build
command. This command
packages your plugin source into the litehouse plugin format which is, under
the hood, just a wasm component. For more about the build
command, see the
build command page.
Getting Started
The easiest way to start is to copy the sample plugin, noop
in the
repository. Please see the crate for more,
or follow the guide below.
Anatomy of a plugin
Lets learn a little about how to create plugins by walking through the anatomy
of the noop
plugin and see how we can extend it. It looks a lot like a
regular rust library, but with some extra tools to set up the traits you
need to implement and define what the plugin's configuration looks like.
At any time you can bail out and implement the plugin the 'manual' way; as long as it adheres to the plugin definition, it will work. The following is just a convenience wrapper for rust libraries.
To get started, you'll need to import the litehouse-plugin
crate which
includes some convenience macros for getting started with rust, the primary
entrypoint of which is the generate
macro. Notice that the crate-type
is
set to cdylib
. This is important for wasm modules as it signifies to cargo
that we intend on loading this plugin dynamically.
Looking at the lib.rs
file, we can see that it is mostly just a regular rust
library. generate
expects a struct which is instantiated by litehouse. You
may store any local state you like in here. The generate
macro also generates
for you some trait and types from the plugin schema.
If you forget to implement GuestRunner for your plugin, you will get a compile error. Same for if you fail to implement the interface correctly.
Lifecycle
When the function is created, you will receive a nickname which is the name the user used to instantiate the plugin. This is guaranteed to be unique. Then, subscribe will called to opt-in to a set of event types. Subscribing to nothing means that the server will never wake the plugin.
Lets change that to the most fundamental subscription, time.
The update
function is called whenever an event happens in the system that
matches one of your subscriptions. For us, you'll get an update every minute.
Note that schedules do not get persisted between starts. We are considering
allowing configuring the interval relative to some point in time such as
'every 4pm'.