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żywajafter()lubevery().-- ZLE - zawiesi CLU! local start = os.clock() while os.clock() - start < 1 do end doSomething() -- DOBRZE after(1000, function() doSomething() end)
Limity timerów#
| Parametr | Wartość |
|---|---|
| Max liczba timerów | 1000 |
| Min interwał (every) | 10ms |
| Min timeout (after) | 1ms |
| Max okres | 24h (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/falsegetAllScenes()#
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) -- 50lerp(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) -- 25map(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.1Logowanie - 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#
| Poziom | Opis |
|---|---|
debug | Szczegółowe informacje (domyślnie wyłączone) |
info | Normalne komunikaty |
warn | Ostrzeżenia |
error | Błędy |
Zmiana poziomu#
log.level = "debug" -- pokaz wszystko
log.level = "warn" -- tylko ostrzezenia i bledy
log.*używastring.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#
| Funkcja | Opis |
|---|---|
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 |