View Categories

Rozdział 8.4. – Automatyzacja (Logika) – Skrypty Lua

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:

  1. Wyczyść – Kliknij, aby wyczyścić dane konsoli.
  2. Kopiuj – Kopiuje do schowka zawartość konsoli.
  3. Zatrzymaj – Jeżeli opcja jest zaznaczona, wówczas wpisy w konsoli nie przewijają się automatycznie.
  4. 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:

  1. zmienne zadeklarowane poza jakąkolwiek funkcją są globalne dla całego kodu w zakładce Logika.
  2. nie należy definiować funkcji jako funkcji lokalnych z użyciem słowa local.
  3. funkcje i zmienne zawarte w skryptach zaimportowanych z użyciem funkcji import są globalne dla
    reszty kodu w zakładce Logika.
  4. 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.

  1. Moduły:
    • table
    • string
    • math
  2. Funkcje:
    • print
    • time – funkcja z modułu os, wywołanie bez przedrostka os.
    • pairs
    • ipairs
    • assert
    • date – funkcja z modułu os; wywołanie bez przedrostka os.
    • type
    • pcall
    • tostring
    • tonumber
    • unpack
    • setmetatable
    • getmetatable

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:

  1. timery jednorazowe
  2. 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) lub
local 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()
end

Nieprawidłowa deklaracja:

function some_function()
      local tmr = timer.delay(30)
      tmr:on('timeout',function()
           -- kod do wykonania
      end)
      tmr:start()
end

W 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:

  1. 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.

  1. start() – Metoda służąca do uruchomienia odliczania.
  2. stop() – Metoda służaca do zatrzymania odliczania. Timer zatrzymany metodą stop może być ponownie uruchomiony z użyciem metody again.
  3. 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.
  4. again() – Rozpoczyna odliczanie od nowa. Tę funkcję można wywołać w timerze, który został zatrzymany przy użyciu metody stop. Wówczas timer rozpoczyna odliczanie od początku. Gdy metoda
    again zostanie 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ę again moż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.

  1. Tworzenie instancji timera
    Obowiązują tu te same zasady, jak dla timerów jednorazowych. Do tworzenia timerów cyklicznych służy
    metoda periodic.
    zmienna = timer.periodic(opóźnienie)
    Przykład użycia: local some_timer = timer.periodic(10) lub
    local some_timer = timer.periodic(some_var), gdzie some_var przechowuje 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:
local sock = tcp.socket().
Do zmiennej 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 .

  1. 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)
  2. 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')
  3. send(data) – Metoda służąca do wysyłania danych przez socket.
    sock:send(data)
  4. 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)
        -- kod do wykonania
        end
        sock:on('connect',handle_connect)
        Funkcja obsługująca jako argumenty otrzymuje socket oraz adres i port identyfikujący połączenie przychodzące
    • 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 trybie binary. 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 trybie
        line. 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 metody
        send. 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)
        print("Socket Closed: "..msg)
        end)
        To zdarzenie można użyć np. do implementacji autowznowienia połączenia w przypadku jego
        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)
  5. off(event) – Metoda będąca przeciwieństwem do metody on. 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 metody off jest właściwym rozwiązaniem.
    • sock:off('data')
      Socket od tego momentu nie będzie rozgłaszał zdarzenia typu ’data’.
  6. 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łanie close()) i skasowanie zawartości zmiennej, do której socket był przypisany (przypisanie do zmiennej wartości nil).
  7. 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)
    lub
    local port = 1234
    sock:bind(port)
  8. 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 .

  1. send(data) – Metoda służąca do wysyłania danych przez socket.
    sock:send(data)
  2. 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)
    -- kod do wykonania
    end)
    2. Funkcja zdefiniowana w innymi miejscu kodu:
    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)
  3. 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’.
  4. 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)
    lub
    local port = 1234
    sock:bind(port)
  5. addMembership(adres) – Metoda umożliwiająca przypisanie do grupy multicast.
  6. 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) Metoda public służy do rejestrowania funkcji obsługujących dla żądań, które nie wymagają autoryzacji.
    name – nazwa identyfikująca żądanie
    handler – 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)
    Metoda secure działa analogicznie, jak metoda public, jednakże wymaga aby żądanie było autoryzowane z użyciem loginu i hasła do konfiguratora. Dane autoryzacji nalezy przesłać w nagłówku Authorization. Dane mogą być zakodowane metodą Basic lub Digest.
    Użycie metody secure różni się jedynie fragmentem żądania – zamiast call/public trzeba użyć
    call/secure. Oraz należy wywołać webapi.secure zamiast webapi.public.
    Nawiązując do przykładu dla metody public, 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 #
  1. value – Aktualna wartość identyfikatora przypisanego do obiektu.
  2. new – Nowa wartość identyfikatora odebrana przy użyciu metody onchange.
  3. 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.
  4. 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.

  1. 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 identyfikatora LCN.output.0.10.1
      2. Wysłanie komendy z wartością 100 do wyjścia ściemnianego nr 1 w module LCN.
  2. get() – Metoda zwracająca bieżący stan identyfikatora przypisanego do obiektu.
    • local currentValue = somevariable:get()
      print(currentValue) --> 100
  3. channel()– Metoda zwraca nazwę identyfikatora przypisanego do obiektu.
    • local name = somevariable:channel()
      print(name) --> LCN.output.0.10.1
  4. 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
  5. ontick() – Metoda umożliwia przypisanie funkcji obsługującej, która będzie wywoływana co
    sekundę. Jest funkcjonalność podobna do timer.periodic.
    • Oba poniższe zapisy są tożsame:
      function somevariable:ontick()
      print(„Ticking”)
      end
      somevariable.ontick = function()
      print(„Ticking”)
      end

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 string
local age = age('LCN.output.0.10.1')
print(age) --> 1234
Przekazanie obiektu
local 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.8125

2.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ść) lub
command(komenda/zdarzenie=wartość)

  1. Włączenie przekaźnika np. 1 w module Satel INT-IORS z adresem 3 sterowany.
    command('C.EXP.output.3.1,1)
  2. Wysterowanie wyjścia ściemnianego nr 2 w module LCN o adresie 10 na 100%.
    command('C.LCN.output.0.10.2,100)
  3. 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 nazwie test.
    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.

  1. Zmiana stanu zmiennej VAR.test na wartość 100.
    set('VAR.test',100)
  2. Porównaj różnice między funkcją set, a metodą set obiektu
    set('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")

Powered by BetterDocs