Helpery#

vCLU udostępnia zestaw globalnych funkcji pomocniczych dostępnych w user.lua i om.lua. Wszystkie są zdefiniowane w Helpers.lua i ładowane automatycznie przy starcie runtime.

Timery - after / every / cancel#

Asynchroniczne timery oparte na Go (TimerManager). Rejestrują callback i wracają natychmiast - nie blokują runtime.

after(ms, callback)#

Wykonaj funkcję raz, po opóźnieniu.

-- Wlacz lampe za 5 sekund
after(5000, function()
    RELAY1:execute(DOUT.METHOD_SWITCH_ON)
end)

Zwraca ID timera (do anulowania):

local id = after(10000, function()
    log.info("za pozno!")
end)

-- Anuluj zanim sie odpali
cancel(id)

every(ms, callback)#

Wykonuj funkcję cyklicznie co ms milisekund.

-- Loguj temperature co minute
every(60000, function()
    local temp = _:get("CLU.ANA1"):get(0)
    log.info("Temperatura: " .. temp)
end)

cancel(id)#

Anuluj timer (jednorazowy lub cykliczny).

local id = every(1000, function() print("tick") end)

-- Po 10 sekundach - zatrzymaj
after(10000, function()
    cancel(id)
end)

Lua w vCLU jest jednowątkowy. Nigdy nie używaj pętli oczekującej (while, repeat, busy-wait) do opóźnień - zablokuje to cały runtime (zdarzenia, MQTT, GPIO, timery). Zawsze używaj after() lub every().

-- ZLE - zawiesi CLU!
local start = os.clock()
while os.clock() - start < 1 do end
doSomething()

-- DOBRZE
after(1000, function()
    doSomething()
end)

Limity timerów#

ParametrWartość
Max liczba timerów1000
Min interwał (every)10ms
Min timeout (after)1ms
Max okres24h (86 400 000ms)

Sceny - scene / runScene / getScene#

Sceny to nazwane funkcje, które można wywoływać z kodu, eksponować do Home Assistant / HomeKit, i włączać/wyłączać dynamicznie.

scene(name, fn)#

Definiuje scenę. Zwraca obiekt sceny.

scene("wieczor", function()
    _:get("CLU.DOU5048"):execute(DOUT.METHOD_SWITCH_ON)
    _:get("CLU.DOU4458"):execute(DOUT.METHOD_SWITCH_OFF)
end)

runScene(name, …)#

Uruchamia scenę po nazwie. Argumenty są przekazywane do funkcji sceny.

runScene("wieczor")

getScene(name)#

Zwraca obiekt sceny (do eksponowania lub sterowania).

local s = getScene("wieczor")
s:run()          -- uruchom
s:disable()      -- wylacz (run() nie zrobi nic)
s:enable()       -- wlacz ponownie
s:isEnabled()    -- true/false

getAllScenes()#

Zwraca posortowaną listę nazw wszystkich scen.

local names = getAllScenes()
-- {"poranek", "wieczor", "wylacz_wszystko"}

scenes.nazwa#

Dostęp do scen przez namespace z kropką:

scenes.wieczor:run()
scenes.wieczor:disable()

Eksponowanie scen#

Sceny można wyeksponować do Home Assistant i HomeKit:

scene("wieczor", function()
    _:get("CLU.DOU5048"):execute(DOUT.METHOD_SWITCH_ON)
end)

expose(getScene("wieczor"), "scene", {name = "Tryb wieczorny"})

W HomeKit scena pojawia się jako przycisk (włącz → wykonaj → wróć do OFF). W Home Assistant jako switch.

Przykłady scen#

-- Scena z argumentami
scene("ustaw_jasnosc", function(poziom)
    _:get("CLU.DIMM1"):set(0, poziom or 50)
end)
runScene("ustaw_jasnosc", 80)

-- Wlacz scene na przycisk GPIO
local btn = GPIO_DIN:new("BTN1", 27)
btn:add_event(DIN.EVENT_ON_CLICK, function()
    runScene("wieczor")
end)

-- Scena warunkowa
scene("auto_swiatlo", function()
    local lampa = _:get("CLU.DOU5048")
    if lampa:get(DOUT.FEATURE_VALUE) == 1 then
        lampa:execute(DOUT.METHOD_SWITCH_OFF)
    else
        lampa:execute(DOUT.METHOD_SWITCH_ON)
    end
end)

-- Wylacz scene na noc
scene("tryb_nocny", function()
    scenes.auto_swiatlo:disable()
end)

scene("tryb_dzienny", function()
    scenes.auto_swiatlo:enable()
end)

Sekwencje - sequence#

Sekwencja to łańcuch akcji i opóźnień, wykonywany asynchronicznie. Alternatywa dla zagnieżdżonych after().

Tworzenie i uruchamianie#

sequence()
    :add(function() r1:execute(DOUT.METHOD_SWITCH_ON) end)
    :wait(500)
    :add(function() r2:execute(DOUT.METHOD_SWITCH_ON) end)
    :wait(500)
    :add(function() r3:execute(DOUT.METHOD_SWITCH_ON) end)
    :run()

Odpowiednik z after() (mniej czytelny):

r1:execute(DOUT.METHOD_SWITCH_ON)
after(500, function()
    r2:execute(DOUT.METHOD_SWITCH_ON)
    after(500, function()
        r3:execute(DOUT.METHOD_SWITCH_ON)
    end)
end)

Callback po zakończeniu#

sequence()
    :add(function() r1:execute(DOUT.METHOD_SWITCH_ON) end)
    :wait(1000)
    :add(function() r2:execute(DOUT.METHOD_SWITCH_ON) end)
    :run(function()
        log.info("Sekwencja zakonczona")
    end)

Zatrzymywanie#

local seq = sequence()
    :add(function() r1:execute(DOUT.METHOD_SWITCH_ON) end)
    :wait(5000)
    :add(function() r2:execute(DOUT.METHOD_SWITCH_ON) end)
    :run()

-- Przerwij sekwencje (r2 sie nie wlaczy)
after(2000, function()
    seq:stop()
end)

Sekwencja nie może być uruchomiona ponownie dopóki trwa - kolejne wywołanie run() jest ignorowane.

Kaskada - cascade#

Wykonuje funkcję na każdym obiekcie w grupie z opóźnieniem między nimi.

-- Wlacz wszystkie lampy po kolei, co 300ms
local lampy = _:byTag("lights")
cascade(lampy, 300, function(obj, i)
    obj:execute(DOUT.METHOD_SWITCH_ON)
end)

Dostępna też jako metoda na RemoteGroup:

_:byTag("lights"):cascade(300, function(obj, i)
    obj:execute(DOUT.METHOD_SWITCH_ON)
end)

Matematyka - clamp / lerp / map / round#

clamp(value, min, max)#

Ogranicza wartość do zakresu.

clamp(150, 0, 100)   -- 100
clamp(-5, 0, 100)    -- 0
clamp(50, 0, 100)    -- 50

lerp(a, b, t)#

Interpolacja liniowa między a i b. Parametr t od 0 do 1.

lerp(0, 100, 0.5)   -- 50
lerp(0, 100, 0.25)  -- 25

map(value, inMin, inMax, outMin, outMax)#

Mapuje wartość z jednego zakresu na drugi.

-- Czujnik 0-1023 → jasnosc 0-100
local brightness = map(sensorValue, 0, 1023, 0, 100)

-- Temperatura 15-30°C → pozycja zaworu 0-100%
local valve = map(temp, 15, 30, 0, 100)

round(value, decimals)#

Zaokrągla do podanej liczby miejsc po przecinku.

round(3.14159)      -- 3
round(3.14159, 2)   -- 3.14
round(3.14159, 1)   -- 3.1

Logowanie - log#

Globalny moduł logowania z czterema poziomami. Logi trafiają na stdout procesu Go.

log.debug("Szczegoly: pin=%d, value=%d", pin, val)
log.info("System uruchomiony")
log.warn("Brak polaczenia z brokerem")
log.error("Blad GPIO: %s", err)

Poziomy#

PoziomOpis
debugSzczegółowe informacje (domyślnie wyłączone)
infoNormalne komunikaty
warnOstrzeżenia
errorBłędy

Zmiana poziomu#

log.level = "debug"   -- pokaz wszystko
log.level = "warn"    -- tylko ostrzezenia i bledy

log.* używa string.format - można używać formatowania: log.info("Wartosc: %d, nazwa: %s", 42, "test").

Debug - inspect / dump#

inspect(value, depth)#

Zwraca czytelną reprezentację dowolnej wartości Lua. Rozpoznaje typy vCLU: Plugin, RemoteObject, RemoteGroup, obiekty registry.

local s = inspect(_:get("CLU.DOU5048"))
-- "RemoteObject<DOU5048>\n  type: DOUT\n  value: 0\n  ..."

inspect({1, 2, 3})          -- "[1, 2, 3]"
inspect({a = 1, b = "x"})   -- "{\n  a: 1,\n  b: \"x\"\n}"
inspect(nil)                 -- "nil"

Parametr depth (domyślnie 2) kontroluje głębokość rekurencji dla zagnieżdżonych tabel.

dump(value, label)#

Wypisuje inspect() przez print(). Opcjonalny label.

dump(_:get("CLU.DOU5048"))
dump(_:byTag("lights"), "Lampy")
-- Lampy: RemoteGroup<lights> (3 objects)
--   objects: [DOU5048, DOU4458, DOU3327]

Stan obiektów - saveState / restoreState#

Dostępne na RemoteObject i RemoteGroup. Pozwalają zapisać i przywrócić stan obiektów.

-- Zapisz stan przed scena
local lampy = _:byTag("lights")
local stan = lampy:saveState()

-- Uruchom scene "kino" (wylacz wszystkie lampy)
runScene("kino")

-- Po filmie - przywroc poprzedni stan
after(2 * 60 * 60 * 1000, function()  -- po 2 godzinach
    lampy:restoreState(stan)
end)

Na pojedynczym obiekcie:

local lampa = _:get("CLU.DOU5048")
local stan = lampa:saveState()
-- ... operacje ...
lampa:restoreState(stan)

Podsumowanie#

FunkcjaOpis
after(ms, fn)Jednorazowy timer (asynchroniczny)
every(ms, fn)Cykliczny timer
cancel(id)Anuluj timer
scene(name, fn)Zdefiniuj scenę
runScene(name, ...)Uruchom scenę
getScene(name)Pobierz obiekt sceny
getAllScenes()Lista nazw scen
sequence()Łańcuch akcji z opóźnieniami
cascade(group, ms, fn)Akcja na grupie z opóźnieniem
clamp(v, min, max)Ogranicz do zakresu
lerp(a, b, t)Interpolacja liniowa
map(v, iMin, iMax, oMin, oMax)Mapowanie zakresów
round(v, dec)Zaokrąglenie
log.info(fmt, ...)Logowanie (debug/info/warn/error)
inspect(value, depth)Czytelna reprezentacja wartości
dump(value, label)Wypisz inspect na stdout