Data i czas#
Lua w vCLU udostepnia standardowe funkcje os.time(), os.date() i os.clock() do pracy z czasem. Czas pochodzi z systemu operacyjnego hosta (Raspberry Pi, serwer).
os.time() - aktualny czas#
Zwraca aktualny czas jako Unix timestamp (liczba sekund od 1 stycznia 1970 UTC).
local now = os.time()
log.info("Timestamp: %d", now)
-- Timestamp: 1740268800Mozna tez uzyskac timestamp dla konkretnej daty:
-- Timestamp dla 1 marca 2026, 14:30:00
local ts = os.time({year = 2026, month = 3, day = 1, hour = 14, min = 30, sec = 0})os.date() - formatowanie daty#
Formatuje timestamp do czytelnej postaci. Bez argumentu formatuje aktualny czas.
Tabela daty#
local t = os.date("*t")
-- t = {
-- year = 2026, month = 2, day = 22,
-- hour = 14, min = 30, sec = 15,
-- wday = 1, -- dzien tygodnia (1=niedziela, 2=poniedzialek, ..., 7=sobota)
-- yday = 53, -- dzien roku
-- isdst = false
-- }
log.info("Godzina: %d:%02d", t.hour, t.min)
log.info("Dzien tygodnia: %d", t.wday)Formatowanie stringow#
-- Pelna data i czas
log.info(os.date("%Y-%m-%d %H:%M:%S"))
-- "2026-02-22 14:30:15"
-- Tylko godzina
log.info(os.date("%H:%M"))
-- "14:30"
-- Tylko data
log.info(os.date("%Y-%m-%d"))
-- "2026-02-22"
-- Formatowanie historycznego timestampu
local ts = os.time() - 3600 -- godzine temu
log.info("Godzine temu: %s", os.date("%H:%M:%S", ts))Kody formatu#
| Kod | Opis | Przyklad |
|---|---|---|
%Y | Rok (4 cyfry) | 2026 |
%m | Miesiac (01-12) | 02 |
%d | Dzien miesiaca (01-31) | 22 |
%H | Godzina 24h (00-23) | 14 |
%M | Minuta (00-59) | 30 |
%S | Sekunda (00-59) | 15 |
%A | Nazwa dnia tygodnia | Sunday |
%a | Skrot dnia | Sun |
%B | Nazwa miesiaca | February |
%b | Skrot miesiaca | Feb |
%w | Dzien tygodnia (0=niedziela) | 0 |
%j | Dzien roku (001-366) | 053 |
%X | Czas lokalny | 14:30:15 |
%x | Data lokalna | 02/22/26 |
%% | Literalny % | % |
Czas UTC#
Prefix ! daje czas UTC zamiast lokalnego:
local utc = os.date("!*t")
local local_time = os.date("*t")
log.info("UTC: %s", os.date("!%H:%M:%S"))
log.info("Lokalny: %s", os.date("%H:%M:%S"))os.clock() - czas CPU#
Zwraca czas CPU procesu w sekundach (z dokladnoscia do milisekund). Przydatny do mierzenia czasu wykonania.
local start = os.clock()
-- ... jakas operacja ...
local elapsed = os.clock() - start
log.info("Czas wykonania: %.3f ms", elapsed * 1000)`os.clock()` mierzy czas CPU, nie czas scienny. Do mierzenia odstepow czasu w sekundach uzyj `os.time()`. Do precyzyjnych pomiarow w milisekundach uzyj `os.clock() * 1000`.
os.difftime(t2, t1) - roznica czasu#
Zwraca roznice miedzy dwoma timestampami w sekundach.
local start = os.time()
-- ... po jakims czasie ...
local elapsed = os.difftime(os.time(), start)
log.info("Minelo %d sekund", elapsed)Przyklady#
Akcje o okreslonej godzinie#
-- Sprawdzaj co minute czy jest pora na akcje
every(60000, function()
local t = os.date("*t")
-- Wlacz swiatla o 18:00
if t.hour == 18 and t.min == 0 then
runScene("wieczor")
end
-- Wylacz swiatla o 23:00
if t.hour == 23 and t.min == 0 then
runScene("wylacz_wszystko")
end
end)Harmonogram dzienny#
local schedule = {
{hour = 7, min = 0, scene = "poranek"},
{hour = 18, min = 0, scene = "wieczor"},
{hour = 22, min = 30, scene = "noc"},
}
every(60000, function()
local t = os.date("*t")
for _, entry in ipairs(schedule) do
if t.hour == entry.hour and t.min == entry.min then
runScene(entry.scene)
log.info("Harmonogram: %s o %02d:%02d", entry.scene, t.hour, t.min)
end
end
end)Akcje tylko w dni robocze#
local function isWeekday()
local wday = os.date("*t").wday
-- 1=niedziela, 7=sobota
return wday >= 2 and wday <= 6
end
every(60000, function()
local t = os.date("*t")
-- Pobudka o 6:30 tylko w dni robocze
if isWeekday() and t.hour == 6 and t.min == 30 then
runScene("pobudka")
end
end)Tryb nocny (zakres godzin)#
local function isNightTime()
local hour = os.date("*t").hour
-- Noc = 22:00 - 06:00
return hour >= 22 or hour < 6
end
-- Czujnik ruchu - inne zachowanie w nocy
_:get("CLU.DIN1"):add_event(DIN.EVENT_ON_CLICK, function()
if isNightTime() then
-- Noc: delikatne swiatlo
_:get("CLU.DIMM1"):set(0, 20)
else
-- Dzien: pelna jasnosc
_:get("CLU.DIMM1"):set(0, 100)
end
end)Logowanie z timestamp#
local function logWithTime(msg, ...)
local time = os.date("%H:%M:%S")
local formatted = string.format(msg, ...)
log.info("[%s] %s", time, formatted)
end
logWithTime("Temperatura: %.1f°C", 22.5)
-- [14:30:15] Temperatura: 22.5°CObliczanie czasu do zdarzenia#
-- Ile sekund do polnocy?
local function secondsToMidnight()
local t = os.date("*t")
local midnight = os.time({
year = t.year, month = t.month, day = t.day + 1,
hour = 0, min = 0, sec = 0
})
return os.difftime(midnight, os.time())
end
log.info("Do polnocy: %d minut", secondsToMidnight() / 60)Cykliczny raport#
-- Raport co godzine o pelnej godzinie
every(60000, function()
local t = os.date("*t")
if t.min == 0 then
local report = string.format(
"Raport %02d:00 - Relay1: %d, Temp: %.1f",
t.hour,
_:get("CLU.DOU5048"):get(DOUT.FEATURE_VALUE),
_:get("CLU.ANA1"):get(0)
)
log.info(report)
-- Wyslij przez HTTP
HttpClient:asyncPOST("https://hooks.example.com/report",
JSON.encode({message = report, time = os.time()}),
function() end
)
end
end)Przechowywanie timestampow w KV#
-- Zapisz czas ostatniej aktywnosci
_:get("CLU.DIN1"):add_event(DIN.EVENT_ON_CLICK, function()
kv:set("last_motion", os.time())
kv:set("last_motion_formatted", os.date("%Y-%m-%d %H:%M:%S"))
end)
-- Sprawdz ile minelo od ostatniego ruchu
local function minutesSinceLastMotion()
local last = kv:get("last_motion")
if not last then return 999999 end
return os.difftime(os.time(), last) / 60
end
-- Wylacz swiatla jezeli brak ruchu > 30 minut
every(60000, function()
if minutesSinceLastMotion() > 30 then
runScene("wylacz_swiatla")
end
end)Sunrise/sunset (przyblizony)#
-- Uproszczony kalkulator wschodu/zachodu slonca
-- Dla dokladnych wartosci uzyj zewnetrznego API
local function estimateSunset()
local t = os.date("*t")
local dayOfYear = t.yday
-- Przyblizenie dla Warszawy (52°N)
-- Lato ~21:00, zima ~15:30
local baseHour = 16
local amplitude = 2.5
local offset = math.sin((dayOfYear - 80) / 365 * 2 * math.pi)
return baseHour + amplitude * offset
end
every(60000, function()
local t = os.date("*t")
local sunsetHour = estimateSunset()
local currentHour = t.hour + t.min / 60
if currentHour >= sunsetHour and currentHour < sunsetHour + 0.02 then
runScene("wieczor")
log.info("Zachod slonca - uruchamiam scene wieczorna")
end
end)Plugin Time Sync#
Funkcje os.time() / os.date() zwracaja czas systemowy maszyny. Na Raspberry Pi bez RTC (zegar czasu rzeczywistego) czas po restarcie moze byc niepoprawny do momentu synchronizacji NTP. Plugin Time Sync rozwiazuje ten problem - synchronizuje czas z internetowego serwera (WorldTimeAPI) i udostepnia wygodne API do automatyzacji.
Instalacja#
Plugin @vclu/time-sync dostepny w repozytorium vCLU. Instalacja przez panel Plugins w interfejsie webowym.
Konfiguracja#
| Parametr | Typ | Domyslnie | Opis |
|---|---|---|---|
timezone | string | Europe/Warsaw | Strefa czasowa IANA |
interval | number | 3600 | Interwal synchronizacji w sekundach (0 = manualny) |
autoSync | boolean | true | Automatyczna synchronizacja przy starcie |
Tryby pracy:
| autoSync | interval | Zachowanie |
|---|---|---|
true | 3600 | Sync przy starcie + co godzine (domyslne) |
false | 3600 | Bez sync przy starcie, potem co godzine |
true | 0 | Tylko sync przy starcie |
false | 0 | Tylko manualny sync, fallback na os.time() |
API#
local time = Plugin.get("@vclu/time-sync")
-- Aktualny czas (synchronizowany z serwerem)
time:getTimestamp() -- Unix timestamp (korygowany o drift)
time:getHour() -- 0-23
time:getMinute() -- 0-59
time:getSecond() -- 0-59
time:getFormatted() -- "15:30:45"
time:getFormattedDate() -- "2025-12-30"
time:getFormatted("%H:%M") -- "15:30" (custom format)
-- Informacje o strefie czasowej
time:getTimezone() -- "Europe/Warsaw"
time:getUtcOffset() -- "+01:00"
time:isDst() -- true/false (czas letni)
time:getDayOfWeek() -- 0=niedziela, 6=sobota
time:getWeekNumber() -- numer tygodnia w roku
-- Wygodne helpery do automatyzacji
time:isBetween(8, 0, 22, 0) -- czy miedzy 8:00 a 22:00
time:isBetween(22, 0, 6, 0) -- dziala tez przez polnoc
time:isWeekday() -- poniedzialek-piatek
time:isWeekend() -- sobota/niedziela
-- Kontrola synchronizacji
time:sync() -- wymus synchronizacje
time:setTimezone("Europe/London") -- zmien strefe
time:getDrift() -- roznica serwer vs lokalny (sekundy)
time:isReady() -- czy czas jest zsynchronizowany
time:getLastSync() -- timestamp ostatniej sync
time:getData() -- wszystkie dane jako tabelaZdarzenia#
-- Czas zsynchronizowany
plugin:on("time:synced", function(data)
log.info("Czas: %s, drift: %+ds", data.datetime, data.drift)
end)
-- Zmiana godziny - idealne do automatyzacji
plugin:on("time:hourChanged", function(data)
log.info("Nowa godzina: %d", data.hour)
if data.hour == 18 then
runScene("wieczor")
end
end)
-- Blad synchronizacji
plugin:on("time:error", function(data)
log.warn("Sync error: %s", data.error)
end)Przyklady z pluginem#
Automatyzacja oparta na godzinie#
-- Uzyj zdarzenia hourChanged zamiast pollowania co minute
plugin:on("time:hourChanged", function(data)
local time = Plugin.get("@vclu/time-sync")
-- Wlacz swiatla o 18:00 w dni robocze
if data.hour == 18 and time:isWeekday() then
runScene("wieczor")
end
-- Wylacz wszystko o 23:00
if data.hour == 23 then
runScene("wylacz_wszystko")
end
end)Czujnik ruchu z trybem nocnym#
local time = Plugin.get("@vclu/time-sync")
_:get("CLU.DIN1"):add_event(DIN.EVENT_ON_CLICK, function()
if time:isBetween(22, 0, 6, 0) then
-- Noc: delikatne swiatlo
_:get("CLU.DIMM1"):set(0, 20)
elseif time:isBetween(6, 0, 8, 0) then
-- Poranek: srednia jasnosc
_:get("CLU.DIMM1"):set(0, 60)
else
-- Dzien: pelna jasnosc
_:get("CLU.DIMM1"):set(0, 100)
end
end)Tryb pracy biurowej#
local time = Plugin.get("@vclu/time-sync")
-- Sprawdz czy godziny pracy
local function isOfficeHours()
return time:isWeekday() and time:isBetween(8, 0, 17, 0)
end
_:get("CLU.DIN1"):add_event(DIN.EVENT_ON_CLICK, function()
if isOfficeHours() then
runScene("biuro_on")
else
runScene("po_godzinach")
end
end)os.time() vs Plugin Time Sync#
os.time() | Plugin Time Sync | |
|---|---|---|
| Zrodlo | Zegar systemowy | WorldTimeAPI (internet) |
| Strefa czasowa | Strefa systemu | Konfigurowalna (IANA) |
| Po restarcie bez RTC | Moze byc bledny | Synchronizuje sie automatycznie |
| Czas letni (DST) | os.date("*t").isdst | time:isDst() |
| Helpery | Brak - trzeba pisac samemu | isBetween(), isWeekday(), isWeekend() |
| Zdarzenia | Brak | time:synced, time:hourChanged |
| Drift detection | Brak | time:getDrift() |
Dla prostych skryptow `os.time()` / `os.date()` sa wystarczajace. Plugin Time Sync jest zalecany gdy: potrzebujesz pewnosci co do strefy czasowej, urzadzenie nie ma RTC (np. Raspberry Pi), chcesz korzystac z gotowych helperow jak `isBetween()`, lub potrzebujesz zdarzen `hourChanged`.
Podsumowanie#
| Funkcja | Opis |
|---|---|
os.time() | Aktualny Unix timestamp (sekundy) |
os.time(table) | Timestamp dla podanej daty |
os.date("*t") | Tabela z rozbita data |
os.date(fmt) | Sformatowany string daty |
os.date(fmt, ts) | Formatowanie konkretnego timestampu |
os.date("!*t") | Tabela daty w UTC |
os.clock() | Czas CPU procesu (sekundy, precyzja ms) |
os.difftime(t2, t1) | Roznica dwoch timestampow w sekundach |
Plugin time-sync | Synchronizowany czas z helperami i zdarzeniami |