NETIO 4x nativně obsahuje propracovaný grafický kalendář / Časovač (Funkce Scheduler), ten se ale nastavuje pro každý výstup zvlášť a pro kratší sekvence je nepraktický.
Lua skript AN07 je praktický pro textový zápis kdy a jak vyvolat akci na výstupu. Akce může být i hodnota 5 (neměň hodnotu výstupu). Hodnota 5 se hodí pro situace, kdy je výstup ovládán nějakým M2M protokolem nebo tlačítkem.
Skript spíná výstupy podle času
"1111,22:30:00,0001000"
„Outputs,time,week-days“
- Outputs = Akce pro každý výstup O1 O2 O3 O4
- Time = Čas provedení akce
- WeekDays = Které dny v týdnu se má akce provést
Podporovaná zařízení: NETIO 4All, NETIO PowerPDU 4C, NETIO 4
Vytvoření pravidla (rule)
Pro vytvoření a spuštění Lua skriptu je nutné následující:
1) Ve webové administraci NETIO 4 v sekci Actions, přidejte pravidlo pomocí tlačítka Create Rule
2) Vyplňte následující parametry:
- Enable rule: zaškrtnuto
- Name: Lua scheduler (uživatelsky definovatelné)
- Description: Lua script for switching outputs based on time (uživatelsky definovatelné)
- Trigger: System started up
- Schedule: Always
3) Do pole pro skript v jazyce Lua zkopírujte následující kód:
------------NETIO AN07------------ ------------Section 1------------ -- Actions for all outputs (1-4), time and days -- Format: -- 4 x number with action (0 - turn off, 1 - turn on, 2 - short off, 3 short on, 4 - toggle, 5 - keep previous state), time (hours:minutes:seconds), day (Mo-Sun, 0 - not active in this day, 1 - active in this day) -- Example – Toggle O1 and turn off other Outputs at 18:30 every day except Wednesday: "4000,18:30:00,1101111" local states = { "4444,16:14:00,1111111", "1000,09:00:00,1111100", "5515,22:33:44,0000011", "0000,00:00:00,1000000" } local initialState = "0055" -- state to which outputs will be set after restart (0-5) local shortTimeMs = 1000 -- time used for action 2 and 3 [milliseconds] ---------End of Section 1--------- local sortedStates = {} local swapped = false function checkFormat() for i=1,4 do local test = tonumber(initialState:sub(i,i)) if test == nil or test>5 or test<0 then logf("Action in initialState for outlet %d is invalid!", i) return false end end for i=1,#states do for j=1,4 do local test = tonumber(states[i]:sub(j,j)) if test == nil or test>5 or test<0 then logf("Action in state %d for outlet %d is invalid!", i,j) return false end end if states[i]:sub(5,5) ~= "," or states[i]:sub(14,14) ~= "," then logf("Time or days in state %d are not separated by comma!", i) return false end local hours = tonumber(states[i]:sub(6,6)) local minutes = tonumber(states[i]:sub(9,9)) local seconds = tonumber(states[i]:sub(12,12)) if hours == nil or hours > 2 or hours < 0 or tonumber(states[i]:sub(7,7)) == nil or states[i]:sub(8,8) ~= ":" or minutes == nil or minutes > 5 or minutes < 0 == nil or tonumber(states[i]:sub(10,10)) == nil or states[i]:sub(11,11) ~= ":" or seconds == nil or seconds > 5 or seconds < 0 == nil or tonumber(states[i]:sub(13,13)) == nil then logf("Time in state %d is invalid!",i) return false end for j=15,21 do local day = tonumber(states[i]:sub(j,j)) if day == nil or (day ~= 0 and day ~= 1) then logf("Value for day %d in state %d is invalid", (j-14), i) return false end end end log("FORMAT OK") return true end function loadStates() for i=1,#states do sortedStates[i] = {state,time} sortedStates[i].state = states[i] sortedStates[i].time = (3600*tonumber(states[i]:sub(6,7)) + 60*tonumber(states[i]:sub(9,10)) + tonumber(states[i]:sub(12,13))) end end function sortStates() for i=1,#states-1 do swapped = false for j=1, #states-1 do if sortedStates[j].time > sortedStates[j+1].time then local temp = sortedStates[j] sortedStates[j] = sortedStates[j+1] sortedStates[j+1] = temp swapped = true; end end if not swapped then break end end end function startScheduler() -- Current time local stringTime = os.date("%X") local time = (3600*tonumber(stringTime:sub(1,2)) + 60*tonumber(stringTime:sub(4,5)) + tonumber(stringTime:sub(7,8))) local nextState = sortedStates[1].state local timeLeft = (86400-time+sortedStates[1].time) local stateIndex = 1 for i=1,#sortedStates do if time < sortedStates[i].time then nextState = sortedStates[i].state timeLeft = (sortedStates[i].time - time) stateIndex = i break end end -- Delay between states must be at least 1s if timeLeft <= 0 then timeLeft = 1 end delay(timeLeft,function() scheduler(nextState,stateIndex) end) end function scheduler(currentState, stateIndex) if checkDay(currentState) then setOutputs(currentState:sub(1,4)) end local nextIndex = stateIndex%#sortedStates + 1 local currentTime = sortedStates[stateIndex].time local stringTime = os.date("%X") local realTime = (3600*tonumber(stringTime:sub(1,2)) + 60*tonumber(stringTime:sub(4,5)) + tonumber(stringTime:sub(7,8))) if currentTime ~= realTime then currentTime = realTime end local timeLeft = 0 if nextIndex == 1 then timeLeft = (86400-currentTime+sortedStates[nextIndex].time) else timeLeft = sortedStates[nextIndex].time - currentTime end -- Delay between states must be at least 1s if timeLeft <= 0 then timeLeft = 1 end delay(timeLeft,function() scheduler(sortedStates[nextIndex].state,nextIndex) end) end function checkDay(state) local day = tonumber(os.date("%w")) -- os.date("%w") returns 0 for Sunday if day == 0 then day = 7 end if tonumber(state:sub(14+day,14+day)) == 1 then return true end return false end function setOutputs(state) for i=1,4 do value = tonumber(state:sub(i,i)) if value == 0 then -- turn off devices.system.SetOut{output = i, value = false} elseif value == 1 then -- turn on devices.system.SetOut{output = i, value = true} elseif value == 2 then -- short off devices.system.SetOut{output = i, value = false} milliDelay(shortTimeMs,function() devices.system.SetOut{output=i,value=true} end) elseif value == 3 then -- short on devices.system.SetOut{output = i, value = true} milliDelay(shortTimeMs,function() devices.system.SetOut{output=i,value=false} end) elseif value == 4 then -- toggle if devices.system["output" ..i.. "_state"] == 'on' then devices.system.SetOut{output=i,value=false} else devices.system.SetOut{output=i, value=true} end elseif value == 5 then -- do nothing end end end function initiate() setOutputs(initialState) end log("Lua scheduler started") checkFormat() initiate() loadStates() sortStates() startScheduler()
Nastavení proměnných
-
states
- Proměnná pomocí které se nastavují akce, čas a dny. Jedná se o tabulku řetězců (strings). Každý řetězec je zodpovědný za akce v jednom konkrétním čase. Jednotlivé řetězce jsou uzavřeny do uvozovek a od sebe jsou odděleny čárkou.
- Řetězec má následující formu "aaaa,hh:mm:ss,mtwtfss".
-
akce (aaaa)
- První 4 symboly jsou vyhrazeny pro akce, které se vykonají s výstupy v zadaný čas.
- První číslo je vyhrazeno pro první výstup, druhé číslo pro druhý výstup atd.
- Čísla akcí odpovídají standardnímu číslování u zařízení NETIO
- 0 - vypnutí výstupu
- 1 - zapnutí výstupu
- 2 - “short off” (nastaví výstup do hodnoty 0, čeká čas v proměnné shortTimeMs a nastaví výstup do hodnoty 1)
- 3 - “short on” (nastaví výstup do hodnoty 1, čeká čas v proměnné shortTimeMs a nastaví výstup do hodnoty 0)
- 4 - “toggle”, přepne stav výstupu na opačnou hodnotu (pokud byl zapnutý, pak ho vypne a naopak)
- 5 - ponechání stavu beze změny
- Příklad pro zapnutí výstupu 3 a vypnutí výstupů 1, 2 a ponechání stavu výstupu 4: 0015
-
čas (hh:mm:ss)
- Druhá část řetězce slouží k určení času ve který se má daná akce vykonat.
- Skript používá čas ze zařízení NETIO (lze ho nastavit ve webové aplikaci v sekci Settings - Date/Time).
- Čas se zadává ve formátu hodiny:minuty:sekundy
- Hodiny musí být dvoumístné číslo (například 9 hodin je nutné zapsat jako 09:00:00) evropského formátu (5pm = 17:00:00).
- Příklad pro nastavení času na 5:30 ráno: 05:30:00.
-
den (mtwtfss)
- Vykonání akce je možné omezit na jednotlivé dny v týdnu
- V této části řetězce je možné nastavit ve které dny se akce bude vykonávat.
- Jednotlivé číslice odpovídají dnům v týdnu (pondělí - neděle).
- Možné hodnoty jsou 0 a 1.
- 0 - akce se v daný den nebude vykonávat.
- 1 - akce se v daný bude vykonávat.
- Příklad pro vykonávání akce pouze o víkendu: 0000011.
- Jednotlivé části řetězce jsou od sebe odděleny čárkou a celý řetězec je uzavřen v uvozovkách.
- Příklad pro přepnutí stavu všech výstupů vždy v 9:30 ráno každý pracovní den (pondělí - pátek): "4444,09:30:00,1111100".
- Příklad pro vypnutí všech výstupů v 18:00 každý pátek: "0000,18:00:00,0000100".
-
initialState
- V této proměnné jsou akce, které se vykonají s jednotlivými výstupy po restartu zařízení.
- Jedná se o řetězec, musí být tedy uzavřen do uvozovek.
- Řetězec má následující formu "aaaa". Za jednotlivá "a" je nutné vložit číslo akce, která se s daným výstupem vykoná.
- Akce mají stejné hodnoty jako v proměnné states
- Příklad pro vypnutí výstupů 1 a 2, ponechání původního stavu výstupů 3 a 4: local initialState = "0055"
-
shortTimeMs
- Nastavuje dobu v milisekundách, za kterou se výstup zapne/vypne ve stavech 2 respektive 3
- Minimální hodnota je 100ms.
- Příklad pro změnu za 2 sekundy: shortTimeMs = 2000
Spuštění skriptu
Po nastavení všech parametrů a uložení skriptu je potřeba restartovat chytré zásuvky NETIO. Po opětovném naběhnutí systému se skript spustí a výstupy se nastaví do stavů určených proměnnou initialState.
FAQ:
1) Kolik jednotlivých akcí je možné pomocí tohoto skriptu vytvořit?
Počet akcí není omezen. Do proměnné states je možné vložit neomezený počet řetězců.
2) Co se stane s výstupem, pokud se jeho stav změní z jiného zdroje (například pomocí tlačítka na zařízení, z webu, jiným M2M protokolem nebo z mobilní aplikace?)
Skript se spustí v nastaveném čase a nastaví hodnoty výstupu podle tabulky. Má-li dojít k zapnutí výstupu, který už zapnutý je, nic se nezmění a výstup zůstane zapnutý.
Pro ponechání výstupu beze změny (ať už 0 nebo 1) lze použít Akci 5 (5 = neprováděj žádnou změnu stavu výstupu).
3) Co se stane při přechodu z letního na zimní čas?
Při přechodu času je možné že se nevykoná akce která je naplánovaná v čase přechodu. Následující akce se budou vykonávat již normálně.
4) Co když je zařízení vypnuté v čase, který je v tabulce uvedený?
Akce se v tom případě nevykoná. Po zapnutí napájení se NETIO zásuvky uvedou do stavu nastaveného v proměnné initialState v záhlaví Lua skriptu a pokračují podle aktuálního času. .
5) Musí být akce v tabulce seřazeny za sebou podle času?
Není to nutné, nicméně to doporučujeme kvůli přehlednosti.
6) Co když vložím dvě akce na stejný čas?
První se provede a druhá se provede o sekundu později.
Podporované verze FW:
3.0.0 a vyšší (Archiv firmware)
Více o Lua:
https://wiki.netio-products.com
Tato Aplikační poznámka může být použita v:
|
NETIO 4NETIO 4 je PDU modul čtyř zásuvek 230V/8A s připojením do počítačové sítě pomocí LAN a WiFi. Každou ze zásuvek lze individuláně vypnout/zapnout pomocí různých M2M API protokolů. NETIO 4 je unikátní produkt, který najde uplatnění v IT, průmyslu, chytrých domech, multimediálních instalacích atd. Všude, kde potřebujete zásuvky na 230V ovládané z mobilní aplikace, z nějakého programu (M2M API), z uživatelského skriptu (Lua), z funkcí časovač (Scheduler) a automatický restartér (IP WatchDog).
|
|
NETIO 4AllNETIO 4All je PDU modul čtyř elektrických zásuvek 230V/8A s měřením spotřeby na každé zásuvce, který lze připojit do počítačové sítě pomocí LAN a WiFi. Každou ze čtyř zásuvek lze individuálně vypnout/zapnout přes web nebo pomocí různých M2M API protokolů. Na každé zásuvce lze měřit její spotřebu elektřiny (A, W, kWh). Chytré zásuvky NETIO 4All jsou určeny pro aplikace vzdáleného měření a ovládání elektrických zásuvek. |
|
NETIO PowerPDU 4CNETIO PowerPDU 4C je malé PDU (Power Distribution Unit) na 110/230V. Každý ze čtyř výstupů IEC-320 C13 lze ovládat samostatně (On / Off / Reset / přepni). Na každém výstupu jsou měřeny elektrické veličiny (A, W, kWh, TPF, V, Hz) s vysokou přesností. Zařízení obsahuje dva LAN porty pro připojení do sítě (vestavěný Ethernet switch). Každý výstup napájení podporuje ZCS (Zero Current Switching), to znamená šetrné ovládání připojených zařízení. |