Moduł Base umożliwia tworzenie i uruchamianie własnych skryptów w języku Lua. Jest to zdecydowanie
najbardziej zaawansowana funkcjonalność w module Base, która wymaga wiedzy z zakresu programowania. Użycie skryptów nie jest obligatoryjne i zdecydowana większość funkcjonalności w systemie DOMIQ
może być skonfigurowana bez ich użycia.
Sam opis języka Lua i jego standardowych modułów nie jest ujęty w niniejszej instrukcji.
Zakładka Logika zawiera wbudowany edytor skryptów Lua, z funkcją kolorowania składni oraz autouzupełnianiem wprowadzanego kodu. Możesz użyć także dowolnego innego edytora kodu źródłowego, a następnie po prostu wkleić kod do zakładki Logika.
Pod oknem edytora znajduje się okno konsoli, w którym wyświetlane są logi. W logach znajdziesz informacje o ewentualnych błędach napotkanych przy wykonywaniu skryptu (nr linii wraz z opisem błędu), a
także są tam wyświetlane wpisy będące efektem wywołania funkcji print.
Nad edytorem skryptów znajduje się pasek z przyciskami:
- Wyczyść – Kliknij, aby wyczyścić dane konsoli.
- Kopiuj – Kopiuje do schowka zawartość konsoli.
- Zatrzymaj – Jeżeli opcja jest zaznaczona, wówczas wpisy w konsoli nie przewijają się automatycznie.
- Zapisz – Kliknij, aby zapisać skrypt. Zapisanie kodu powoduje także jego przeładowanie i wykonanie.
Zatem wszystkie deklaracje zmiennych, a także linie zawierające wywołania funkcji zostaną
wykonane.
Załóżmy, że w edytorze znajduje się następujący kod:
function test_fun()
print('To jest funkcja testowa')
end
test_fun()Każdorazowe zapisanie zakładki spowoduje wykonanie linii test_fun(), będącej wywołaniem funkcji test_fun. Efektem będzie wypisanie w konsoli: To jest funkcja testowa.
Prawidłowe przeładowanie skryptu zostaje każdorazowo potwierdzone następującym wpisem w konsoli: INFO: SCRIPT RELOADED AT <godzina_wykonania>
- Przywóć – Kliknij, aby przywrócić ostatnio zapisaną wersję skryptu.
1. Uwagi ogólne #
Zapoznaj się z ogólnymi zasadami dotyczącymi pisania i wykonania kodu w zakładce
Logika:
- zmienne zadeklarowane poza jakąkolwiek funkcją są globalne dla całego kodu w zakładce Logika.
- nie należy definiować funkcji jako funkcji lokalnych z użyciem słowa
local. - funkcje i zmienne zawarte w skryptach zaimportowanych z użyciem funkcji
importsą globalne dla
reszty kodu w zakładce Logika. - każdorazowe zapisanie zakładki Logika powoduje skompilowanie kodu i uruchomienie wywołań
funkcji, które znajdują się w kodzie.
2. Moduły i funkcje standardowe #
Na potrzeby edytora Logika język Lua pracuje w limitowanym środowisku. Oznacza to, że nie wszystkie
moduły języka są dostępne do użycia. Jest to funkcja bezpieczeństwa uniemożliwiająca uruchomienie
szkodliwego kodu.
Poniżej znajdziesz listę standardowych modułów i funkcji języka Lua, które są dostępne do użycia.
- Moduły:
tablestringmath
- Funkcje:
printtime– funkcja z modułuos, wywołanie bez przedrostkaos.pairsipairsassertdate– funkcja z modułuos; wywołanie bez przedrostkaos.typepcalltostringtonumberunpacksetmetatablegetmetatable
3. Moduły i funkcje niestandardowe #
Moduły i funkcje niestandardowe są naszą własną implementacją, stanowiącą rozszerzenie możliwości języka Lua.
1. Moduły #
timer
Moduł timer umożliwia tworzenie i uruchamianie asynchronicznych timerów. Timer asynchroniczny to
taki, który wykona przypisaną do niego funkcjonalność po upływie określonego czasu bez blokowania
wykonywania kodu źródłowego. Moduł udostępnia dwa rodzaj timerów:
- timery jednorazowe
- timery cykliczne
Timery jednorazowe
1.1. Tworzenie instancji timera #
Timer jednorazowy wywołuje przypisaną do niego funkcję po upływie określonego czasu.
Wywołanie funkcji delay z modułu timer zwraca nową instancję timera (obiekt): zmienna = timer.delay(opóźnienie)Opóźnienie wyrażane jest w sekundach i może być przekazane jako liczba lub jako zmienna, która zawiera
liczbę. Możliwe jest również użycie wartości ułamkowych.
Przykład użycia: local some_timer = timer.delay(10) lublocal some_timer = timer.delay(some_var), gdzie some_var przechowuje wartość liczbową.
Na tym etapie timer został utworzony, ale jest w stanie wstrzymania – odliczanie jeszcze się nie
rozpoczeło.
Timer należy przypisać do zmiennej, która jest zmienną globalną z punktu widzenia skryptu. Przestudiuj
poniższe przykłady:
Prawidłowa deklaracja:
local tmr -- zadeklarowanie zmiennej na poziomie globalnym dla
całego skryptu w zakładce Logika
function some_function()
tmr = timer.delay(30)
tmr:on('timeout',function()
-- kod do wykonania
end)
tmr:start()
endNieprawidłowa deklaracja:
function some_function()
local tmr = timer.delay(30)
tmr:on('timeout',function()
-- kod do wykonania
end)
tmr:start()
endW przykładzie powyżej, zmienna tmr jest lokalna wewnątrz funkcji some_function, zatem kiedy funkcja skończy wykonywanie, zmienna tmr przestanie istnieć.
1.2. Dostępne metody: #
Instancja timera udostępnia następujące metody:
- on(’timeout’,funkcja_do_wykonania)
To metoda, która pozwala przypisać funkcję, która zostanie wykonana po upływie odliczania.
instancja_timera:on('timeout',function()
print("Odliczanie zakończone")
-- tu wprowadź kod, który będzie wykonany po zakończeniu odliczania
end)Wewnątrz funkcji przypisanej do timera może znajdować się dowolny kod, np. wywołanie innej funkcji,
wysłanie komendy do urządzenia w systemie DOMIQ, wysłanie żądania do zewnętrzenego serwera itd.
Funkcja, która zostaje przekazana jako argument do metody on ma dostęp do wszystkich zmiennych i
funkcji znajdujących się w otaczającym środowisku i do środowiska globalnego.
start()– Metoda służąca do uruchomienia odliczania.stop()– Metoda służaca do zatrzymania odliczania. Timer zatrzymany metodąstopmoże być ponownie uruchomiony z użyciem metodyagain.cancel()– Anuluje odliczanie bez możliwości ponownego jego uruchomienia. Po wywołaniu tej
metody, obiekt timera znajduje się w stanie nieaktywności i należy go zainicjować ponownie przez
utworzenie nowej instancji.again()– Rozpoczyna odliczanie od nowa. Tę funkcję można wywołać w timerze, który został zatrzymany przy użyciu metodystop. Wówczas timer rozpoczyna odliczanie od początku. Gdy metodaagainzostanie wywołana w timerze, którego odliczanie już płynie, wówczas licznik odliczania zostanie zresetowany i odliczanie rozpocznie się od nowa.
Wykorzystując metodęagainmożliwe jest utworzenie timera, który będzie wywoływał się automatycznie ponownie, po wykonaniu przypisanych do niego zadań.
Przykłady wywołania poszczególnych metod:
instancja_timera:start()– uruchomienie odliczania;instancja_timera:stop() – zastopowanie odliczania;instancja_timera:cancel() – anulowanie timera, po nim nie można ponownie
uruchomić odliczania;instancja_timera:again() – reset odliczania;
Automatyczne wznowienie timera:
local tmr = timer.delay(10)
tmr:on('timeout',function()
-- zadanie 1
-- zadanie 2
-- zadanie n
tmr:again() -- automatyczne wznowienie timera
end)
tmr:start()1.3. Usunięcie timera #
Jeżeli timer nie jest już dłużej potrzebny w skrypcie należy go usunąć i skasować zawartość zmiennej, do
której timer był przypisany. Załóżmy, że timer był przypisany do zmiennej some_timer, wówczas należy
wywołać następujacy kod:some_timer:stop()
some_timer = nil
Timery cykliczne
Timery cykliczne wykonują odliczanie i przypisaną do nich funkcję powtarzalnie, do momentu ich
zatrzymania.
- Tworzenie instancji timera
Obowiązują tu te same zasady, jak dla timerów jednorazowych. Do tworzenia timerów cyklicznych służy
metodaperiodic.zmienna = timer.periodic(opóźnienie)Przykład użycia:local some_timer = timer.periodic(10)lublocal some_timer = timer.periodic(some_var), gdziesome_varprzechowuje wartość liczbową.
Dostępne metody są identyczne, jak dla timerów jednorazowych poza metodąagain, która jest
niedostępna.
1. math #
Dostępne są 3 dodatkowe funkcje, które dodaliśmy do standardowego modułu math.
1.1 sum
Funkcja, która umożliwia obliczenie sumy dowolnej liczby elementów. Argumenty należy przekazać w
rozdzielone przecinkami.
local suma = sum(1,3,5,7)
print(suma) -- 16
1.2. avg
Funkcja do obliczania średniej arytmetycznej z przekazanego zbioru liczb.
local srednia = avg(1,3,5,7)
print(srednia) -- 4
1.3. round
Funkcja jako wynik zawraca liczbę zaokrągloną do najbliższej liczby całkowitej.
local calkowita = round(16.052)
print(calkowita) -- 16
local calkowita = round(16.521)
print(calkowita) -- 17
2. tcp #
Moduł tcp umożliwa tworzenie asynchronicznych gniazd TCP (ang. async socket). Gniazdo asynchroniczne to takie, które nie blokuje pozostałego kodu w skrypcie, oczekując na odebranie lub wysłanie danych.
Gniazdo TCP może pracować, jako klient lub jako serwer. Dzięki temu modułowi z łatwością utworzysz
własne integracje z zewnętrznym oprogramowaniem np. wysyłanie żądań do zewnętrznych serwerów
oraz obsługę odpowiedzi. Moduł tcp jest powszechnie używany w systemie operacyjnym modułu Base.
2.1. Tworzenie gniazda (socketu) #
Aby utworzyć nowy socket należy wywołać funkcję socket z modułu tcp:Do zmiennej
local sock = tcp.socket().sock została przypisana nowa instancja socketu.
2.2. Dostępne metody #
Instancja socketu umożliwia wywołanie metod opisanych poniżej. We wszystkich opisach zakładamy, że
instancja gniazda przypisana jest do zmiennej sock .
connect(host,port)– Metoda służy do nawiązania połączenia ze wskazanym hostem, na wskazanym porcie.sock:connect('192.168.1.100',80)
sock:connect('example.com',80)mode(mode)– Metoda służąca do wyboru trybu pracy. Dostępne są następujące tryby pracy:binary– Odebranie porcji danych emituje zdarzenie 'data’, które z kolei wywołuje przypisaną
funkcję obsługującą (handler), przekazując do niej odebrane dane. Jest to domyślny tryb pracy
socketu.
Sposób użycia:sock:mode('binary')line– Tryb liniowy. Socket odbierając znak\r (CR)lub\n (LF)emituje zdarzenie'line',
które z kolei wywołuje funkcję obsługującą (handler), przekazując do niej odebrane dane.
Sposób użycia:sock:mode('line')
send(data)– Metoda służąca do wysyłania danych przez socket.sock:send(data)on(event,handler)– Metoda służąca do przypisywania funkcji obsługujących (handlerów) do
zdarzeń, które są emitowane przez socket. Funkcje obsługujące można zdefiniować wewnątrz metody
on – jako tzw. funkcja anonimowa lub przekazać nazwę funkcji, która została zdefiniowana w innym miejscu kodu.
Przestudiuj dwa poniższe przykłady:
1. Funkcja anonimowa jako handler.sock:on('connect',function(client,addr,port))
-- kod do wykonania
end
2. Funkcja zdefiniowana w innymi miejscu kodu:function handle_connect(client,addr,port)
-- kod do wykonania
end
sock:on('connect',handle_connect)
Socket może wyemitować następujące rodzaje zdarzeń:- ’connect’ – zdarzenie jest emitowane w dwóch przypadkach:
- Jako efekt wywołania metody connect , gdy udało się nawiązać połączenie ze wskazanym
hostem – socket pełni tu rolę klienta.sock:on('connect',function()
print('Socket Connected')
-- reszta kodu do wykonania po nazwiązaniu połączenia
end) - Jako reakcja na połączenie przychodzące – socket pełni tu rolę serwera.
function handle_connect(client,addr,port)Funkcja obsługująca jako argumenty otrzymuje socket oraz adres i port identyfikujący połączenie przychodzące
-- kod do wykonania
end
sock:on('connect',handle_connect)
- Jako efekt wywołania metody connect , gdy udało się nawiązać połączenie ze wskazanym
- WAŻNE! Wszystkie poniższe zdarzenia należy obsługiwać wewnątrz funkcji przypisanej do obsługi zdarzenia ’
connect’. Dzięki temu funkcje zostaną zadeklarowane i przypisane wyłącznie, gdy połączenie faktycznie dojdzie do skutku.- ’
data’ – zdarzenie jest emitowane po odebraniu porcji danych, gdy socket pracuje w trybiebinary. Przypisany handler otrzymuje jako argument odebrane dane.sock:on('data',function(data)
print('RECV DATA')
-- kod przetwarzający odebrane dane
end) - ’
line’ – zdarzenie jest emitowane po odebraniu porcji danych, gdy socket pracuje w trybieline. Przypisany handler otrzymuje jako argument odebrane dane.sock:on('line',function(data)
print('RECV LINE',data)
-- kod przetwarzający odebrane dane
end) - ’
drain’ – zdarzenie jest emitowane, gdy bufor nadawczy socketu został opróżniony. Dane trafiają do bufora nadawczego, gdy nie mogły być natychmiastowo wysłane po wywołaniu metodysend. To zdarzenie jest szczególnie przydatne, gdy wysyłasz dane porcjami i wysłanie kolejnej
porcji powinno nastąpić tylko wtedy, gdy poprzednia porcja została dostarczona. - ’
close’ – zdarzenie emitowane w przypadku zamknięcia połączenia. Jest ono emitowane niezależnie od tego, która ze stron je zamknęła. Przypisana funkcja obsługująca otrzymuje jako argument komunikat o ewentualnych błędach.sock:on('close',function(msg)To zdarzenie można użyć np. do implementacji autowznowienia połączenia w przypadku jego
print("Socket Closed: "..msg)
end)
zamknięcia. - ’
error’ – zdarzenie emitowane w przypadku błędu, który wystąpił w połączeniu. Połączenie zostanie automatycznie zamknięte po wystąpieniu błędu. Przypisana funkcja obsługująca otrzymuje
jako argument komunikat o błędzie.sock:on('error',function(err)
print("Socket Error: "..err)
end)
- ’
- ’connect’ – zdarzenie jest emitowane w dwóch przypadkach:
off(event)– Metoda będąca przeciwieństwem do metodyon. Umożliwia anulowanie działanie funkcji obsługującej przypisanej do danego zdarzenia. Jest to rzadko używana funkcjonalność, jednakże czasem bardzo przydatna. Jednym ze scenariuszy jest potrzeba natychmiastowego zaprzestania przetwarzania danych, zanim połączenie zostanie ostatecznie zamknięte. Wówczas wywołanie metodyoffjest właściwym rozwiązaniem.sock:off('data')Socket od tego momentu nie będzie rozgłaszał zdarzenia typu ’data’.
close()– Metoda służąca do zamykania połączenia.sock:close()Jeżeli połączenie nie jest już dłużej potrzebne, zaleca się jego zamknięcie (wywołanieclose()) i skasowanie zawartości zmiennej, do której socket był przypisany (przypisanie do zmiennej wartościnil).bind(port)– Metoda przypisująca numer portu, na którym socket będzie oczekiwał przychodzących połączeń. Nr portu można przekazać jako liczbę lub jako zmienną, która zawiera liczbę.sock:bind(1234)lublocal port = 1234
sock:bind(port)listen()– Metoda uruchamiająca nasłuch na przychodzące połączenia, na porcie wskazanym metodąbind.
2.3. Przykłady użycia #
Na koniec przedstawiamy dwa przykłady: pierwszy z nich pokazuje użycie socketu jako połączenia typu
klient, a drugi użycie socketu TCP do implementacji funkcji serwerowych.
SOCKET JAKO KLIENT
Przykład przedstawia nawiązanie połączenia z serwerem o adresie example.com, wysłanie żądania HTTP
oraz obsługę odpowiedzi z serwera.
local socket
local sendRequest
function createConnection(req)
socket = tcp.socket()
socket:connect("example.com",80)
socket:on('connect', function()
tr:print('Example Server Connected')
socket:mode('line')
sendRequest(req)
socket:on("close", function()
socket = nil
end)
socket:on('line', function(data)
print(data)
-- the rest of handler's code
end)
end)
end
sendRequest = function(req)
if socket ~= nil then
local qm = string.find(req,"?") -- check for a query mark
local name,query
if qm then
name,query = string.match(req,"([^?]+)%?([^?]+)") -- if
query mark present, split request string on it
else
name = req
end
local path = "http://example.com/somepath/"..name)
if query then
socket:send(string.format("GET %s?%s HTTP/
1.1\r\nHost:%s\r\nConnection: keep-alive\r\n\r\n",path, query, "example.com"))
else
socket:send(string.format("GET %s HTTP/
1.1\r\nHost:%s\r\nConnection: keep-alive\r\n\r\n",path,"example.com"))
end
else
createConnection(req)
end
end
sendRequest('sometestrequest')3. udp #
Moduł udp umożliwa tworzenie asynchronicznych gniazd UDP (ang. async socket). Gniazdo asynchroniczne to takie, które nie blokuje pozostałego kodu w skrypcie, oczekując na odebranie lub wysłanie danych. W swojej strukturze moduł udp jest bardzo podobny do modułu tcp. Różnice między tymi dwoma
modułami wynikają z różnic pomiędzy protokołem TCP a UDP – protokół UDP jest protokołem bezstanowym. Zatem nie znajdziemy tu metody connect, jak i zdarzeń dla obsługi połączeń przychodzących.
Gniazdo UDP może pracować, jako klient lub jako serwer. Dzięki temu modułowi z łatwością utworzysz
własne integracje z zewnętrznym oprogramowaniem np. wysyłanie żądań do zewnętrznych serwerów
oraz obsługę odpowiedzi.
3.1. Tworzenie gniazda (socketu) #
Aby utworzyć nowy socket należy wywołać funkcję socket z modułu udp:local sock = udp.socket().Do zmiennej sock została przypisana nowa instancja socketu.
3.2. Dostępne metody #
Instancja socketu umożliwia wywołanie metod opisanych poniżej. We wszystkich opisach zakładamy, że
instancja gniazda przypisana jest do zmiennej sock .
send(data)– Metoda służąca do wysyłania danych przez socket.sock:send(data)on(event,handler)– Metoda służąca do przypisywania funkcji obsługujących (handlerów) do
zdarzeń, które są emitowane przez socket. Funkcje obsługujące można zdefiniować wewnątrz metody
on – jako tzw. funkcja anonimowa lub przekazać nazwę funkcji, która została zdefiniowana w innym
miejscu kodu. Przestudiuj dwa przykłady:
1. Funkcja anonimowa jako handler.sock:on('message',function(data,addr,port)2. Funkcja zdefiniowana w innymi miejscu kodu:
-- kod do wykonania
end)function handle_message(data,addr,port)
-- kod do wykonania
end
sock:on('message',handle_ message)
Socket może wyemitować następujące rodzaje zdarzeń:- ’message’ – zdarzenie jest emitowane po odebraniu porcji danych. Przypisana funkcja obsługująca otrzymuje jako argument odebrane dane oraz adres i numer portu nadawcy.
sock:on('message',function(data,addr,port)
print('RECV DATA')
-- kod przetwarzający odebrane dane
end) - ’
error’ – zdarzenie emitowane w przypadku błędu. Przypisana funkcja obsługująca otrzymuje
jako argument komunikat o błędzie.sock:on('error',function(err)
print("Socket Error: "..err)
end)
- ’message’ – zdarzenie jest emitowane po odebraniu porcji danych. Przypisana funkcja obsługująca otrzymuje jako argument odebrane dane oraz adres i numer portu nadawcy.
off(event)– Metoda będąca przeciwieństwem do metody on. Umożliwia anulowanie działanie
funkcji obsługującej przypisanej do danego zdarzenia.- sock:off(’message’)
Socket od tego momentu nie będzie rozgłaszał zdarzenia typu 'message’.
- sock:off(’message’)
bind(port)– Metoda przypisująca numer portu, na którym socket będzie oczekiwał przychodzących danych. Nr portu można przekazać jako liczbę lub jako zmienną, która zawiera liczbę.sock:bind(1234)lublocal port = 1234
sock:bind(port)addMembership(adres)– Metoda umożliwiająca przypisanie do grupy multicast.dropMembership(adres)– Metoda umożliwiająca porzucenie przynależności do grupy multicast
3.3. Przykłady użycia #
SOCKET JAKO SERWER
W poniższym przykładzie, socket będzie nasłuchiwał na porcie 1234. W przypadku odebrania danych, będzie odsyłał te same dane (echo serwer).
sock = udp.socket()
sock:bind(1234)
sock:on('message',function(data,addr,port)
print('RX',addr,port)
print(data..'\n')
sock:send(data,addr,port)
end)
sock:on('error',function(err)
print('ERROR',sock,err)
end)
print("Listening",sock)SOCKET JAKO KLIENT
Przykład pokazuje, jak wysyłać dane do dowolnego hosta.
sock = udp.socket()
sock:on('message',function(data,addr,port)
print('RX',addr,port)
print(data..'\n')
-- the rest of handler's code
end)
sock:on('error',function(err)
print('ERROR',sock,err)
end)
function sendData(data,addr,port)
sock:send(data,addr,port)
end
sendData("some data",'192.168.1.100',44544)4. webapi #
Moduł umożliwiający z poziomu kodu w zakładce Logika, obsługę żądań HTTP przez wbudowany w
module Base serwer HTTP. W ten sposób możesz utworzyć własne API HTTP do integracji modułu Base z
dowolnym oprogramowaniem. Każdy adres żądania może mieć zdefiniowaną osobną funkcję
obsługującą (handler).
public(name,handler)Metodapublicsłuży do rejestrowania funkcji obsługujących dla żądań, które nie wymagają autoryzacji.name– nazwa identyfikująca żądaniehandler– nazwa funkcji wywoływanej do obsługi żądania.
Żądanie musi zawsze mieć określoną strukturę wg poniższego wzoru:http://<host>/call/public?vm=LOGIC&call=&<nazwa_żądania>&<dowolne_zmienne>
Przestudiuj poniższy przykład:
http://192.168.1.30/call/public?
vm=LOGIC&call=examplerequest&message=somemessage&value=100
Powyższe żądanie zostanie odebrane z nazwą examplerequest oraz dwoma
dodatkowymi parametrami: message z wartością somemessage oraz value z
wartością 100.
Kod w zakładce Logika:
function handleExampleRequest(params)
-- params to tablica parametrów przekazanych w żądaniu
print('message: '..params.message)
print('value: '..params.value)
end
webapi.public('examplerequest',handleExampleRequest)
Powyższe wywołanie webapi.public zarejestrowało żądanie pod nazwą examplerequest i przypisało do niego funkcji obsługującą handleExampleRequest. Funkcja obsługująca w momencie wywołania otrzymuje jako argument, tablicę parametrów, które zostały użyte w żądaniu. Jeżeli w żądaniu nie było dodatkowych parametrów, wówczas funkcja otrzyma pustą tablicę.
secure(name,handler)
Metodasecuredziała analogicznie, jak metodapublic, jednakże wymaga aby żądanie było autoryzowane z użyciem loginu i hasła do konfiguratora. Dane autoryzacji nalezy przesłać w nagłówkuAuthorization. Dane mogą być zakodowane metodą Basic lub Digest.
Użycie metodysecureróżni się jedynie fragmentem żądania – zamiastcall/publictrzeba użyćcall/secure. Oraz należy wywołaćwebapi.securezamiastwebapi.public.
Nawiązując do przykładu dla metodypublic, mamy wówczas:http://192.168.1.30/call/secure?vm=LOGIC&call=examplerequest&message=somemessage&value=100
oraz
webapi.secure(’examplerequest’,handleExampleRequest)
2. Funkcje #
2.1. use #
Funkcja służy do deklarowania obiektów, które pozwalają na interakcję ze wskazanym identyfikatorem w
stanie modułu Base. Utworzone w ten sposób obiekty można używać w całej zakładce Logika, przekazując je między funkcjami lub używać ich jako zmiennych globalnych.
1. Deklaracja obiektu #
Ogólna składnia jest następująca:local somevariable = use'identyfikator', gdzie identyfikator należy zastąpić konkretnym identyfikatorem ze stanu.local somevariable = use'LCN.output.0.10.1'
WAŻNE! Obiekt tworzy automatycznie subskrybcję na odbieranie zdarzeń o zmianie stanu wskazanego
identyfikatora. Umożliwia to programową obsługę zdarzeń – patrz metoda onchange.
2. Własności obiektu #
value– Aktualna wartość identyfikatora przypisanego do obiektu.new– Nowa wartość identyfikatora odebrana przy użyciu metody onchange.old– Ostatnia znana wartość identyfikatora. Własność ustawiana jest przy wywołaniu metody onchange. Ułatwia porównywanie bieżącej i poprzedniej wartości identyfikatora.age– Wartość w sekundach od czasu ostatniej zmiany stanu.
3. Dostępne metody #
Na potrzeby opisu dostępnych metod przyjmujemy obiekt utworzony w punkcie 1 – identyfikator
odnoszący się do wyjścia ściemnianego nr 1 w module LCN o adresie 10.
set(value)– Metoda umożliwiająca nadanie nowej wartości identyfikatorowi.
Wartość przekazana do funkcji set może być dowolna, istotne jest aby była dopasowana do rodzaju
identyfikatora.
Składnia ogólna:obj:set(value)somevariable:set(100)Powyższe wywołanie metody set pociąga za sobą dwie akcje:
1. Przypisuje w stanie modułu Base wartość 100 do identyfikatoraLCN.output.0.10.1
2. Wysłanie komendy z wartością 100 do wyjścia ściemnianego nr 1 w module LCN.
get()– Metoda zwracająca bieżący stan identyfikatora przypisanego do obiektu.local currentValue = somevariable:get()
print(currentValue) --> 100
channel()– Metoda zwraca nazwę identyfikatora przypisanego do obiektu.local name = somevariable:channel()
print(name) --> LCN.output.0.10.1
onchange(new,old)– Metoda umożliwiaja przypisanie funkcji obsługującej (handlera), która będzie wywołana za każdym razem, gdy identyfikator zmieni swój stan. Funkcja obsługująca jako argumenty otrzymuje nowy stan identyfikatora oraz jego wartość sprzed zmiany.- Oba poniższe zapisy są tożsame:
function somevariable:onchange(new,old)
print(„New value: „..new)
print(„Old value: „..old)
end
somevariable.onchange = function(somevariable,new,old)
print(„New value: „..new)
print(„Old value: „..old)
end
- Oba poniższe zapisy są tożsame:
ontick()– Metoda umożliwia przypisanie funkcji obsługującej, która będzie wywoływana co
sekundę. Jest funkcjonalność podobna dotimer.periodic.- Oba poniższe zapisy są tożsame:
function somevariable:ontick()
print(„Ticking”)
end
somevariable.ontick = function()
print(„Ticking”)
end
- Oba poniższe zapisy są tożsame:
2.2. age #
Funkcja zwraca czas wyrażony w sekundach od ostatniej zmiany stanu danego identyfikatora. Funkcja
Jako argument przyjmuje string z nazwą identyfikatora lub obiekt utworzony z użyciem metody use.
Identyfikator jako stringlocal age = age('LCN.output.0.10.1')Przekazanie obiektu
print(age) --> 1234local somevariable = use'LCN.output.0.10.1'
local age = age(somevariable)
print(age) --> 1234
2.4. systime #
Funkcja zwraca czasu od momentu uruchomienia modułu Base. Jest to wygodne narzędzie do pomiaru
upływu czasu pomiędzy dwoma zdarzeniami w systemie, gdyż funkcja systime w odróżnieniu od standardowej funkcji time, zwraca czas z dokładnością większą niż pełne sekundy.
Przykład pomiaru czasu pomiędzy dwoma miejscami kodu
function veryResourceHungryFunction()
-- some very time consuming operations go here
end
local start = systime()
veryResourceHungryFunction()
local end = systime()
print("Duration: "..end - start) --> 8.81252.5. command #
Funkcja umożliwia wysłanie komendy lub rozgłoszenie zdarzenia z określoną wartością. Wymagane jest
tu użycie przedrostka C.(komendy) lub E.(zdarzenia).
Dopuszczalne są dwa rodzaje wywołania funkcji, oba są równoważne, choć pierwsza metoda jest bardziej
optymalna pod względem wydajności.command(komenda/zdarzenie,wartość) lubcommand(komenda/zdarzenie=wartość)
- Włączenie przekaźnika np. 1 w module Satel INT-IORS z adresem 3 sterowany.
command('C.EXP.output.3.1,1) - Wysterowanie wyjścia ściemnianego nr 2 w module LCN o adresie 10 na 100%.
command('C.LCN.output.0.10.2,100) - Rozgłoszenie zdarzenia na przełączenie ekranu wizualizacji w aplikacji Remote.
Na potrzeby przykładu, załóżmy że ekran ma nazwętest. Kiedy taka akcja zostanie
wykonana, wszystkie aplikacje Remote, które aktualnie wyświetlają wizualizację pokażą ekran o nazwietest.command('E.DISPLAY.screen,"test")
2.6. import #
Funkcja służy do importowania skryptów wgranych w zakładce Zasoby do kodu w Logice. Funkcje i
zmienne zaimportowanego skryptu stają się globalne na poziomie całego kodu w zakładce Logika.
- import’script_name’
2.7. set #
Funkcja umożliwiająca ustawienie stanu dowolnego identyfikatora. Różnica między funkcją set a metodą set obiektu utworzonego przy użyciu funkcji use jest następująca: funkcja set ustawia jedynie wartość identyfikatora w tabeli stanu w module Base, nie powodując wysłania komendy do urządzenia, które
kryje się za tym identyfikatorem. Natomiast metoda set obiektu robi obie czynności. Zatem jeżeli chcesz
zmienić identyfikator, który jest jedynie zmienną wirtualną np. zmienną typu VAR, wówczas wystarczy
użyć funkcji set.
- Zmiana stanu zmiennej
VAR.testna wartość 100.set('VAR.test',100) - Porównaj różnice między funkcją
set, a metodąsetobiektuset('LCN.output.0.10.1',100) -- ustawia stan na wartość 100
local somevariable = use'LCN.output.0.10.1'
somevariable:set(100) --> ustawia stan i wysyła komendę do
modułu LCN
2.8. get #
Funkcja zwraca aktualny stan wskazanego identyfikatora.
- local value = get(’LCN.output.0.10.1′)
print(value) –> wypisuje aktualną wartość wyjścia ściemnianego
2.9. set_attr #
Funkcja służy do zmiany wartości atrybutów dowolnego identyfikatora w stanie modułu Base. Każdy
identyfikator ma atrybut description (opis) oraz age (czas od ostatniej zmiany).
Funkcja przyjmuje trzy argumenty: nazwa identyfikatora, nazwa atrybutu, nowa wartość atrybutu
set_attr("LCN.output.0.10.1","description","lampa sufit")
2.10. get_attr #
Funkcja zwraca wartość wskazanego atrybutu identyfikatora. Do funkcji należy przekazać nazwę identyfikatora i nazwę atrybutu.
local description = get_attr("IDS.input.10","description")