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#

PoleTypWymaganeOpis
idstringtakKrótki identyfikator (np. "weather")
namestringtakNazwa wyświetlana
versionstringtakWersja semver
descriptionstringnieOpis pluginu
authorstringnieAutor
homepagestringnieURL strony
licensestringnieLicencja
minVcluVersionstringnieMinimalna wersja vCLU
tagsarraynieTagi do wyszukiwania
dependenciesarraynieZależności (planowane)
filesarrayniePliki Lua (domyślnie ["init.lua"])

configSchema#

Generuje formularz konfiguracji w UI (/plugins):

PoleTypOpis
keystringKlucz w obiekcie config
typestring"string", "number", "boolean"
labelstringEtykieta w formularzu
descriptionstringOpis/podpowiedź
requiredbooleanPole wymagane
defaultstringWartość domyślna

config (rozszerzony format)#

Alternatywny format z walidacją, używany w init.lua:

PoleTypOpis
typestringTyp wartości
requiredbooleanWymagane
defaultanyWartość domyślna
min, maxnumberZakres dla number
enumarrayDozwolone wartości (dropdown)
envstringZmienna ś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}
  }
}