plugin.json#
Manifest pluginu — metadane, schemat konfiguracji, eksporty.
Pełny przykład#
{
"id": "weather",
"name": "Weather Plugin",
"version": "2.0.0",
"description": "Get weather data from OpenWeatherMap",
"author": "vclu",
"homepage": "https://github.com/vclu-plugins/weather",
"license": "MIT",
"minVcluVersion": "1.0.0",
"tags": ["weather", "api", "sensor"],
"dependencies": [],
"files": ["init.lua"],
"configSchema": [
{
"key": "apiKey",
"type": "string",
"label": "API Key",
"description": "OpenWeatherMap API key",
"required": true
},
{
"key": "city",
"type": "string",
"label": "City",
"default": "Warsaw"
},
{
"key": "interval",
"type": "number",
"label": "Refresh interval (seconds)",
"default": "3600"
}
],
"config": {
"apiKey": {"type": "string", "required": true, "env": "OPENWEATHERMAP_API_KEY"},
"city": {"type": "string", "default": "Warsaw"},
"interval": {"type": "number", "default": 3600, "min": 300, "max": 86400},
"units": {"enum": ["metric", "imperial"], "default": "metric"}
},
"exports": {
"objects": {"current": {"type": "WeatherData"}},
"sensors": [
{"id": "temperature", "type": "temperature", "description": "Current temperature"},
{"id": "humidity", "type": "humidity", "description": "Relative humidity"}
],
"controls": [
{"id": "fanSpeed", "type": "fan", "range": "0-4"}
],
"events": [
{"name": "weather:changed", "description": "Weather data updated"},
{"name": "weather:rain", "description": "Rain alert"}
]
},
"docs": [
{"title": "Getting Started", "file": "README.md"}
]
}Metadane#
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
id | string | tak | Krótki identyfikator (np. "weather") |
name | string | tak | Nazwa wyświetlana |
version | string | tak | Wersja semver |
description | string | nie | Opis pluginu |
author | string | nie | Autor |
homepage | string | nie | URL strony |
license | string | nie | Licencja |
minVcluVersion | string | nie | Minimalna wersja vCLU |
tags | array | nie | Tagi do wyszukiwania |
dependencies | array | nie | Zależności (planowane) |
files | array | nie | Pliki Lua (domyślnie ["init.lua"]) |
configSchema#
Generuje formularz konfiguracji w UI (/plugins):
| Pole | Typ | Opis |
|---|---|---|
key | string | Klucz w obiekcie config |
type | string | "string", "number", "boolean" |
label | string | Etykieta w formularzu |
description | string | Opis/podpowiedź |
required | boolean | Pole wymagane |
default | string | Wartość domyślna |
config (rozszerzony format)#
Alternatywny format z walidacją, używany w init.lua:
| Pole | Typ | Opis |
|---|---|---|
type | string | Typ wartości |
required | boolean | Wymagane |
default | any | Wartość domyślna |
min, max | number | Zakres dla number |
enum | array | Dozwolone wartości (dropdown) |
env | string | Zmienna środowiskowa jako źródło |
exports#
Deklaracja eksportowanych obiektów, sensorów, kontrolek i eventów:
objects#
"objects": {
"current": {"type": "WeatherData"}
}Obiekty tworzone przez plugin:upsertObject() w runtime.
sensors#
"sensors": [
{"id": "temperature", "type": "temperature", "unit": "°C"},
{"id": "humidity", "type": "humidity", "unit": "%"},
{"id": "connected", "type": "sensor"}
]Tworzone przez plugin:sensor() — read-only, integrowalne z expose().
controls#
"controls": [
{"id": "fanSpeed", "type": "fan", "range": "0-4"},
{"id": "temperature", "type": "number", "range": "15-30"}
]Tworzone przez plugin:control() — read-write, integrowalne z expose().
events#
"events": [
{"name": "weather:changed", "description": "Weather data updated"},
{"name": "weather:rain", "description": "Rain alert"}
]Emitowane przez plugin:emit().
docs#
"docs": [
{"title": "Getting Started", "file": "README.md"},
{"title": "API Reference", "file": "docs/api.md"}
]Dostępne przez GET /api/plugins/:id/doc?file=README.md.
Przykłady z produkcyjnych pluginów#
Telegram#
{
"id": "telegram",
"config": {
"botToken": {"type": "string", "required": true},
"chatId": {"type": "string", "required": false},
"defaultParseMode": {"default": "HTML", "enum": ["HTML", "Markdown", "MarkdownV2"]},
"enablePolling": {"type": "boolean", "default": true},
"pollingInterval": {"type": "number", "default": 5}
}
}Sun Position#
{
"id": "sun-position",
"config": {
"latitude": {"type": "number", "required": true},
"longitude": {"type": "number", "required": true},
"timezoneOffset": {"type": "number", "default": 1},
"sunriseOffset": {"type": "number", "default": 0},
"sunsetOffset": {"type": "number", "default": 0}
}
}