Extending
Architecture
Section titled “Architecture”The primary things managed and provided by the plugin are:
- ESL Vendor
- Sub-package per vendor
- ESL Device
- Metadata in the vendor package, using a
pidor sometimespidcombined withhwidin the BLE results to pinpoint a model
- Metadata in the vendor package, using a
- SVG Template
- SignalK API base URL
- Used for automatic unit conversion on
signalk-sourced numeric values and for resolving an explicitcategory=binding - neither has an in-process equivalent, both go via this server’s own REST API - Optional: left blank, the plugin probes the probable values in likelihood order at startup -
http://localhost:3000,http://localhost,https://localhost. Set it explicitly to skip probing - Either way, errors clearly if nothing responds (wrong port) or the probe is rejected (anonymous read access not enabled) - these endpoints must allow anonymous read access, since the plugin has no login flow
- Used for automatic unit conversion on
Hardware
Section titled “Hardware”Additional vendors and devices can be added by a separate npm package that implements the VendorDriver interface and registers itself - there’s no scanning of installed packages, registration is always an explicit call by the extension’s own code.
import esl from '@rhizomatics/signalk-einklabel-plugin'; esl.registerVendorDriver(myDriver)- In the SignalK runtime, call this from the extension’s own plugin
start(). In the CLI, load the extension withesl-cli --require <module> <command>. - Declare this package as a regular npm
dependencyin the extension package - not apeerDependency, per SignalK’s own guidance that npm’s peer-dependency resolution interacts poorly with the server’s plugin install layout - and declare the SignalK-level relationship via"signalk": { "requires": ["@rhizomatics/signalk-einklabel-plugin"] }in the extension’s ownpackage.jsoninstead, so the App Store can install/report it.
Template Providers
Section titled “Template Providers”An alternative way to produce a device’s content, alongside hand-authored SVG templates, can be added the same way - esl.registerTemplateProvider({ suffix, listTemplates, render }), from a separate package’s own plugin start() (or esl-cli --require <module>). This is what @rhizomatics/signalk-einklabel-genai-plugin is: listTemplates() returns the entries it currently offers (already including its own suffix, e.g. "forecast (GenAI)") for the “Template” dropdown, and render(request) - given the same signalk/resources/label context any SVG template’s bindings get - returns a Bitmap, exactly as new esl.Renderer().render() would for an SVG template. Rejecting from render() routes the repaint through this plugin’s own generic fallback-warning template, the same as a broken hand-authored template failing to render. An optional describeContent(request) returns a human-readable description of what render() will be given (the GenAI plugin returns its fully-substituted LLM prompt); when present, it’s logged to the plugin’s debug output just before each render(), standing in for the <desc> bindings an SVG template’s debug output would show.
esl.Renderer (the SVG renderer), esl.bitmapToPng, esl.buildLabel, esl.findBindingsInText, and esl.substituteBindingsInText are also exported for a TemplateProvider extension to reuse - e.g. to resolve its own {...}-style placeholders against the request’s context, or to rasterize whatever SVG it produces into the Bitmap its render() must return.
CLI Commands
Section titled “CLI Commands”esl-cli can also be extended with new subcommands by a -r/--require’d package, which is how @rhizomatics/signalk-einklabel-genai-plugin adds its own prompt/generate commands for testing prompts without a device. See Command Line Interface for the built-in commands.