Storage (KV Store)#
vCLU udostepnia persystentny key-value store dostepny z Lua. Dane przetrwaja restart silnika i sa zapisywane na dysku jako pliki JSON.
API z poziomu Lua#
kv:set(key, value, secure, ttl)#
Zapisz wartosc.
-- Podstawowy zapis
kv:set("sensor_threshold", 22)
-- Zapis stringa
kv:set("last_scene", "wieczor")
-- Zapis tablicy (automatyczna serializacja)
kv:set("config", {temp_min = 18, temp_max = 25})kv:get(key)#
Odczytaj wartosc. Zwraca (value, exists).
local val, exists = kv:get("sensor_threshold")
if exists then
log.info("Prog: " .. val)
end
-- Z wartoscia domyslna
local threshold = kv:get("sensor_threshold") or 22kv:has(key)#
Sprawdz czy klucz istnieje (i nie wygasl).
if kv:has("api_token") then
-- token jest dostepny
endkv:delete(key)#
Usun klucz.
kv:delete("session_token")kv:list(prefix)#
Lista kluczy z opcjonalnym prefixem.
local keys = kv:list("sensor_")
-- {"sensor_threshold", "sensor_interval", "sensor_last_read"}
local all = kv:list() -- wszystkie kluczekv:getAll()#
Pobierz wszystkie pary klucz-wartosc. Wartosci zaszyfrowane sa zastepowane przez "[SECURE]".
local all = kv:getAll()
for k, v in pairs(all) do
log.info(k .. " = " .. tostring(v))
endSzyfrowanie#
Wrazliwe dane (tokeny API, hasla) mozna zapisac zaszyfrowane:
-- Trzeci parametr = secure
kv:set("api_secret", "s3cret_token_123", true)
-- Odczyt dziala normalnie
local secret = kv:get("api_secret") -- "s3cret_token_123"
-- Ale getAll() maskuje wartosc
local all = kv:getAll()
-- all.api_secret = "[SECURE]"W logach wartosc tez jest ukryta:
[KV] Set myplugin.api_secret = [REDACTED] (secure, ttl=0)TTL (Time-to-Live)#
Klucze moga wygasac automatycznie po zadanym czasie:
-- Czwarty parametr = TTL w sekundach
kv:set("session_token", token, false, 3600) -- wygasnie po 1 godzinie
kv:set("cache_data", data, false, 300) -- wygasnie po 5 minutach
-- Szyfrowane + z TTL
kv:set("oauth_token", token, true, 7200) -- szyfrowane, wygasa po 2hPo wygasnieciu klucz jest usuwany przy nastepnym odczycie (lazy expiration):
kv:set("temp", "wartosc", false, 5) -- 5 sekund TTL
-- Po 5 sekundach:
local val, exists = kv:get("temp")
-- val = nil, exists = falseScope - izolacja per plugin#
Kazdy plugin ma wlasny namespace w KV store. Pluginy nie widza kluczy innych pluginow:
-- W pluginie "weather":
kv:set("api_key", "abc123") -- zapisane w pliku kv/weather.json
kv:get("api_key") -- "abc123"
-- W pluginie "lights":
kv:get("api_key") -- nil (nie widzi kluczy "weather")Pliki na dysku:
kv/
weather.json
lights.json
vclu--my-plugin.json -- @vclu/my-plugin → vclu--my-pluginZapis na dysk#
Dane sa zapisywane atomowo (zapis do pliku tymczasowego, potem rename) przy kazdej operacji set() i delete(). Format pliku:
{
"_meta": {
"version": 1,
"updated": 1708617600
},
"entries": {
"sensor_threshold": {
"v": 22,
"created": 1708617500
},
"api_secret": {
"v": "zaszyfrowana_wartosc",
"secure": true,
"created": 1708617550
},
"cache": {
"v": "dane",
"ttl": 300,
"exp": 1708617900,
"created": 1708617600
}
}
}Przyklady#
Zapamietanie ostatniej sceny#
scene("wieczor", function()
_:get("CLU.DOU5048"):execute(DOUT.METHOD_SWITCH_ON)
_:get("CLU.DOU4458"):execute(DOUT.METHOD_SWITCH_OFF)
kv:set("last_scene", "wieczor")
end)
scene("poranek", function()
_:get("CLU.DOU5048"):execute(DOUT.METHOD_SWITCH_OFF)
_:get("CLU.DOU4458"):execute(DOUT.METHOD_SWITCH_ON)
kv:set("last_scene", "poranek")
end)
-- Po restarcie - przywroc ostatnia scene
local last = kv:get("last_scene")
if last then
runScene(last)
endLicznik wlaczen#
_:get("CLU.DOU5048"):add_event(DOUT.EVENT_ON_SWITCH_ON, function()
local count = kv:get("relay1_count") or 0
kv:set("relay1_count", count + 1)
end)Cache z automatycznym wygasaniem#
local function getWeather()
local cached = kv:get("weather_data")
if cached then
return cached -- zwroc z cache
end
-- Pobierz z API
http:get("https://api.weather.com/current", function(status, body)
if status == 200 then
kv:set("weather_data", body, false, 600) -- cache na 10 minut
end
end)
endPrzechowywanie konfiguracji uzytkownika#
-- Zapisz progi z panelu webowego
kv:set("config", {
temp_min = 18,
temp_max = 25,
auto_mode = true
})
-- Odczytaj
local cfg = kv:get("config") or {temp_min = 20, temp_max = 24, auto_mode = false}
if cfg.auto_mode then
-- ...
endPlugin API (kvGet / kvSet)#
Pluginy uzywaja metod na obiekcie plugin zamiast globalnego kv:
-- W pluginie:
function Plugin:onInit()
local token = self:kvGet("api_token", "")
if token == "" then
self:log("warn", "Brak tokenu API")
end
end
-- Zapis
self:kvSet("cache", data, {secure = false, ttl = 300})
-- Sprawdzenie
if self:kvHas("token") then ... end
-- Lista kluczy
local keys = self:kvList("cache:")
-- Usun
self:kvDelete("old_key")Go bridge#
| Lua | Go | Opis |
|---|---|---|
kv:get(key) | __go_kv_get(pluginID, key) | Zwraca (value, exists) |
kv:set(key, val, secure, ttl) | __go_kv_set(pluginID, key, val, secure, ttl) | Zapis |
kv:delete(key) | __go_kv_delete(pluginID, key) | Usuwanie |
kv:has(key) | __go_kv_has(pluginID, key) | Sprawdzenie |
kv:list(prefix) | __go_kv_list(pluginID, prefix) | Lista kluczy |
kv:getAll() | __go_kv_get_all(pluginID) | Wszystkie pary |