Własne moduły#
vCLU pozwala tworzyć własne moduły Lua w katalogu modules/. Moduły są ładowane po wszystkich plikach systemowych i proxy, więc mają dostęp do całego runtime - registry, obiektów zdalnych, helperów, timerów itd.
Struktura katalogu#
modules/
init.lua ← punkt wejścia (ładowany automatycznie)
lighting.lua ← moduł jako pojedynczy plik
heating/
init.lua ← moduł jako katalog (require("heating"))
zones.lua ← podmoduł (require("heating.zones"))
schedule.lua ← podmoduł (require("heating.schedule"))Katalog modules/ jest widoczny i edytowalny w edytorze (/editor). Można tam tworzyć pliki, katalogi i podkatalogi.
init.lua#
Plik modules/init.lua jest ładowany automatycznie przy starcie vCLU. Służy jako punkt wejścia - tutaj ładujemy własne moduły przez require():
-- modules/init.lua
local lighting = require("lighting")
local heating = require("heating")
print("[MODULES] User modules initialized")Jeżeli modules/init.lua nie istnieje, system pomija ładowanie modułów bez błędu.
require()#
require() szuka plików w katalogu modules/ według dwóch wzorców:
| Wywołanie | Szukany plik |
|---|---|
require("lighting") | modules/lighting.lua |
require("heating") | modules/heating/init.lua |
require("heating.zones") | modules/heating/zones.lua |
Lua cachuje wynik require() w package.loaded - każdy moduł jest wykonywany tylko raz, niezależnie od tego ile razy go zaimportujemy.
Tworzenie modułu#
Moduł to plik Lua, który zwraca tablicę z funkcjami i danymi:
-- modules/lighting.lua
local M = {}
function M.allOff()
local lights = _:byTag("lights")
lights:execute(DOUT.METHOD_SWITCH_OFF)
log.info("Wszystkie swiatla wylaczone")
end
function M.allOn()
local lights = _:byTag("lights")
lights:execute(DOUT.METHOD_SWITCH_ON)
end
function M.toggle(name)
local obj = _:get(name)
if obj then
obj:toggle()
end
end
return MPrzykład: moduł ogrzewania#
Moduł podzielony na kilka plików w katalogu:
modules/
init.lua
heating/
init.lua
zones.lua
schedule.luaheating/zones.lua#
-- modules/heating/zones.lua
local M = {}
M.config = {
salon = { thermostat = "CLU.THERM1", target = 21.5 },
sypialnia = { thermostat = "CLU.THERM2", target = 20.0 },
lazienka = { thermostat = "CLU.THERM3", target = 23.0 },
}
function M.setTarget(zone, temp)
local cfg = M.config[zone]
if not cfg then
log.warn("Nieznana strefa: %s", zone)
return
end
cfg.target = temp
local obj = _:get(cfg.thermostat)
if obj then
obj:set(0, temp)
log.info("Strefa %s: cel %.1f°C", zone, temp)
end
end
function M.getAll()
local result = {}
for zone, cfg in pairs(M.config) do
local obj = _:get(cfg.thermostat)
result[zone] = {
target = cfg.target,
current = obj and obj:get(0) or nil,
}
end
return result
end
return Mheating/schedule.lua#
-- modules/heating/schedule.lua
local zones = require("heating.zones")
local M = {}
function M.nightMode()
zones.setTarget("salon", 19.0)
zones.setTarget("sypialnia", 20.0)
zones.setTarget("lazienka", 19.0)
log.info("Tryb nocny aktywny")
end
function M.dayMode()
zones.setTarget("salon", 21.5)
zones.setTarget("sypialnia", 20.0)
zones.setTarget("lazienka", 23.0)
log.info("Tryb dzienny aktywny")
end
return Mheating/init.lua#
-- modules/heating/init.lua
local M = {}
M.zones = require("heating.zones")
M.schedule = require("heating.schedule")
return Mmodules/init.lua#
-- modules/init.lua
local lighting = require("lighting")
local heating = require("heating")
-- Harmonogram ogrzewania
after(1000, function()
local hour = os.date("*t").hour
if hour >= 23 or hour < 6 then
heating.schedule.nightMode()
else
heating.schedule.dayMode()
end
end)
print("[MODULES] Loaded: lighting, heating")Użycie w user.lua#
Moduły załadowane w init.lua są dostępne globalnie jeśli przypiszemy je do zmiennych globalnych, albo można użyć require() ponownie (zwróci wersję z cache):
-- user.lua
function onButtonPress()
local lighting = require("lighting")
lighting.allOff()
end
function onSceneEvening()
local heating = require("heating")
heating.schedule.nightMode()
local lighting = require("lighting")
lighting.toggle("LAMPA_SALON")
endKolejność ładowania#
1. bootstrap ← runtime (EventBus, Registry, klasy...)
2. user.lua ← funkcje użytkownika
3. om.lua ← obiekty, event bindingi
4. proxy_*.lua ← obiekty zdalne
5. modules/init.lua ← własne moduły (require)
6. SYSTEM.Init() ← EVENT_ON_INITModuły ładują się jako ostatnie przed inicjalizacją - mają dostęp do wszystkich obiektów (lokalnych i zdalnych), registry, helperów i timerów.
Dobre praktyki#
- Każdy moduł zwraca tablicę (
return M) - nie zanieczyszcza globalnej przestrzeni nazw - Logika biznesowa w modułach, funkcje eventowe w
user.lua - Podprojekty w podkatalogach z własnym
init.lua require()zamiast kopiowania kodu między plikami