--    ======================
--    Description
--    ======================
--
--    Konfigurator interfejsu H4F6V3.
--
--    Umożliwia sterowanie 3 strefami grzewczymi A, F lub AF oraz wentylacją.
--
--    ======================
--    Parameters
--    ======================
--
--    SubLogic supports following variables:
--
--    setting.keylock                       - [RWS] (0..2) tryb blokady klawiatury, wartość fabryczna 0.
--                                            0 - menu oraz ustawienia temperatur/wentylacji są dostępne.
--                                            1 - wyłącza dostęp do menu nastaw, gdy jest ono załączone, można do niego wejść przez dłuższe przytrzymanie przycisku M.
--                                            2 - wyłącza wszystkie funkcje klawiatury, prócz przemieszczania się przyciskiem P pomiędzy strefami i wentylacją. Widoczny
--                                                jest symbol kłódki - t10.
--
--    setting.features.mask                 - [RWS] (1..15) maska bitowa załączająca obsługę stref oraz wentylacji sterownika.
--                                            0b000000000000WXYZ, gdzie Z - bit strefy 1, Y - bit strefy 2, X - bit strefy 3, W - bit wentylacji.
--                                            ustawienie danego bitu oznacza załączenie obsługi danej funkcji w sterowniku. Wartość fabryczna: 15
--                                            Przełączenie pomiędzy kolejnymi strefami i wentylacją realizowane jest przez krótkie naciśnięcie P.
--                                            Urządzenie sygnalizuje aktualnie wyświetlaną strefę (lub wentylację) przez wyświetlanie cyfr 1, 2, 3
--                                            dla stref oraz cyfry 4 dla wentylacji. (symbole t35..t37)
--
--    input.z1.t.a.value
--    input.z2.t.a.value
--    input.z3.t.a.value                    - [RW] (-250..1000) - wejściowe wskazania temperatur pomieszczenia dla stref 1, 2, 3. temperatury te są ustawiane przez
--                                            zewnętrzną aplikację przy pomocy interfejsu modbus. Jeżeli setting.phy.t.zone.idx ma wartość indeksu danej strefy (1, 2 lub 3)
--                                            wówczas lokalne wskazanie input.t.0.value jest kopiowane do odpowiedniego rejestru input.zN.t.a.value. Wartość fabryczna: 0
--                                            Bieżące temperatury wyświetlane są w segmentach 12, 13 oraz 14 wyświetlacza. Jeżeli status danej temperatury jest różny od 0,
--                                            wówczas widoczny jest napis "err". Gdy wyświetlane są temperatury otoczenia, wówczas widoczny jest napis "RT" - segment t31.
--
--    input.z1.t.f.value
--    input.z2.t.f.value
--    input.z3.t.f.value                    - [RW] (0..8) - wejściowe wskazania temperatur podłogi dla stref 1, 2, 3. temperatury te są ustawiane przez
--                                            zewnętrzną aplikację przy pomocy interfejsu modbus. Jeżeli setting.phy.t.zone.idx ma wartość indeksu danej strefy (1, 2 lub 3)
--                                            wówczas lokalne wskazanie input.t.0.value jest kopiowane do odpowiedniego rejestru input.zN.t.f.value. Wartość fabryczna: 0
--                                            Bieżące temperatury wyświetlane są w segmentach 12, 13 oraz 14 wyświetlacza. Jeżeli status danej temperatury jest różny od 0,
--                                            wówczas widoczny jest napis "err". Gdy wyświetlane są temperatury otoczenia, wówczas widoczny jest napis "FT" - segment t32.
--
--    input.z1.t.a.err
--    input.z2.t.a.err
--    input.z3.t.a.err                      - [RW] (0..8) - wejściowe statusy temperatur pomieszczenia dla stref 1, 2, 3. statusy te są ustawiane przez
--                                            zewnętrzną aplikację przy pomocy interfejsu modbus. Jeżeli setting.phy.t.zone.idx ma wartość indeksu danej strefy (1, 2 lub 3)
--                                            wówczas lokalny status input.t.1.err jest kopiowany do odpowiedniego rejestru input.zN.t.a.err. Wartość fabryczna: 8
--
--    input.z1.t.f.err
--    input.z2.t.f.err
--    input.z3.t.f.err                      - [RW] (0..8) - wejściowe statusy temperatur podłogi dla stref 1, 2, 3. statusy te są ustawiane przez
--                                            zewnętrzną aplikację przy pomocy interfejsu modbus. Jeżeli setting.phy.t.zone.idx ma wartość indeksu danej strefy (1, 2 lub 3)
--                                            wówczas lokalny status input.t.1.err jest kopiowany do odpowiedniego rejestru input.zN.t.f.err. Wartość fabryczna: 8
--
--
--    setting.z1.a.value
--    setting.z2.a.value
--    setting.z3.a.value                    - [RW] (0..1) - wyjście grzejnika. Wartość fabryczna: 0.
--                                            Stan wyjścia jest sygnalizowany poprzez symbol płomienia (t56) zawsze w trybie A, lub w trybie AF, gdy jest widoczny symbol RT - t31.
--    setting.z1.f.value
--    setting.z2.f.value
--    setting.z3.f.value                    - [RW] (0..1) - wyjście ogrzewania podłogowego. Wartość fabryczna: 0.
--                                            Stan wyjścia jest sygnalizowany poprzez symbol płomienia (t56) zawsze w trybie F, lub w trybie AF, gdy jest widoczny symbol FT - t33.
--
--    setting.z1.features.mask
--    setting.z2.features.mask
--    setting.z3.features.mask              - [RWS] (1..15) - maska bitowa funkcji dla danej strefy. Wartość fabryczna: 15.
--                                            0b000000000000WXYZ gdzie X - funkcja termostatu A, Y - funkcja termostatu F, Z - funkcja termostatu AF. W - uwzględnianie pór doby.
--                                            Przełączanie pomiędzy funkcjami następuje poprzez krótkie naciśnięcie przycisku M. Bieżącą funkcję sygnalizuje symbol A (t28),
--                                            F (t29) lub oba. Gdy bit W jest ustawiony, wówczas sterownik obsługuję dla danej strefy pory doby - dzień/noc. W tym wypadku,
--    setting.z1.dn
--    setting.z2.dn
--    setting.z3.dn                         - [RW] (0..1) - informacja mówiąca czy aktualnie obowiązuje dzień (0) czy noc (1). Wówczas o ile bit W w rejestrze właściwości strefy
--                                            setting.zN.features jest ustawiony, wtedy przy wyświetlaniu danej stref widoczny jest symbol t19 lub t20 oraz wyświetlana jest albo
--                                            zadana temperatura dzienna albo nocna otoczenia/podłogi. Rejestry te są ignorowane gdy bit W w rejestrze setting.zN.features jest
--                                            wyzerowany - wówczas dla całej doby uwzględniana jest temperatura dzienna - z przyrostkiem .d.
--
--    setting.af.display.mode               - [RWS] (0..2) - tryb wyświetlania temperatur dla stref w trybie pracy AF. Wartość fabryczna: 0
--                                            0 - co 10 sekund naprzemiennie wartości dla A i F.
--                                            1 - pokazywane są tylko wartości dla F.
--                                            2 - pokazywane są tylko wartości dla A.
--
--    setting.vent.auto.level               - [RW] (0..6) - bieżący bieg wentylatora, nie może on być większy niż setting.max.vent.level. Bieg ten jest wizualizowany na pasku
--                                            stępu (symbole t41..t46) gdy aktualnie wyświetlana jest wentylacja (ekran 4) oraz gdy wentylacja znajduje się w trybie auto - czytaj 
--                                            opis rejestru setting.vent.downtime.
--
--    setting.vent.max.level                - [RWS] (0..6) - maksymalny bieg wentylatora, jaki może ustawić urządzenie. Wartość fabryczna: 6.
--
--    Logic uses lua language to implement own behaviour
--
--    ======================
--    mandatory variables
--    ======================
--
--    Logic expects following mandatory variables:
--
--    reload.trigger                          - causes reloading lua script
--
--    memcnt                                  - current amount of memory used by lua in bytes
--
--    Logic expects following kv settings:
--
--    LuaScriptPath                           - path to the lua script - must be absolute
--
--    ======================
--    ChangeLog
--    ======================
--
--    2017-03-31 ver 0.0.0
--
--    # First release
--
-- user can use some functions provided by ibmanager.

-- ibmanager provides following functions to use:
--
-- function returns value of required ibmanager variable
-- @param fullName - string - variable name - name of variable of which value must be returned, for example "rs.0.id.255.input.t.0.value"
-- @return         - string or integer - variable value or "nil" if variable not exist or is not readable
--
-- getValue(fullName)


-- function set value of given ibmanager variable
-- @param fullName - string - variable name - name of variable of which value we want to set, for example "rs.0.id.255.input.t.0.value"
-- @param value    - string, int or boolean - value to set
-- @return         - nothing
--
-- setValue(fullName, value)


-- function returns value of required ibmanager variable
-- @param key      - placed in xml logic configuration file:
--                   * as attribute: Name, in Var, RemoteVar and ImportVar elements in the case of stand alone variables
--                   * as concatenation of two attributes: ListName.Postfix in VarListItem, RemoteVarListItem and ImportVarListItem elements
--                     in the case of variables that are placed in lists
-- @return         - string or integer - variable value or "nil" if variable not exist or is not readable
--
-- getLogicValue(key)


-- function set value of given ibmanager variable
-- @param key      - placed in xml logic configuration file:
--                   * as attribute: Name, in Var, RemoteVar and ImportVar elements in the case of stand alone variables
--                   * as concatenation of two attributes: ListName.Postfix in VarListItem, RemoteVarListItem and ImportVarListItem elements
--                     in the case of variables that are placed in lists
-- @param value    - string, int or boolean - value to set
-- @return         - nothing
--
-- setLogicValue(key, value)

-- function returns two sections of kvsettings from xml configuration file
-- returned value is two element table, each of these elements is table too.
-- indices of returned table are strings and equal "instance" and "global"
-- values of returned tables are tables and contain KVsettings for applicable section.
-- nested tables have form key = value, where key is index in nested table and value is value.
-- example: {"instance" = {"ikey1" = "ivalue1", "ikey2" = "gvalue2"}, "global" = {"gkey1" = "gvalue1", "gkey2" = "gvalue2", "gkey3" = "gvalue3"}}
-- @return          - two dimensional array - kvsettings for global and instance sections
-- getKvSettings()


-- function schedules alert to send.
-- rules are defined in separated alert configuration files and are described in ibmanager instruction manual
-- @param id - alert identifier - must be defined in current logic configuration file in section: <Alert Id="any_identifier" ...
-- scheduleAlert(id)

-- function cancels alert sending, if was previously scheduled. if not then only wakes up alerts handling thread, so if there is no need to call this function, then do not call it.
-- rules are defined in separated alert configuration files and are described in ibmanager instruction manual
-- @param id - alert identifier - must be defined in current logic configuration file in section: <Alert Id="any_identifier" ...
-- cancelAlert(name)

-- function returns table, containing Variables that belongs to required list.
-- @param listName - Name attribute of VarList, RemoteVarList or ImportVarList elemetnst in configurationfile
-- @return array of key-value pairs. Key - variable postfix, Value - Variable value
-- getVarList(listName)

-- function returns monotonic system clock value, that elapsed since specific epoch
-- returned time is expressed in milliseconds.
-- getClock()

-- function logs message to file, if defined in configuration file log level is less than passed to this function
-- @param logLevel - one of:
--        LogLevel.TraceLo
--        LogLevel.Trace
--        LogLevel.TraceHi
--        LogLevel.DebugLo
--        LogLevel.Debug
--        LogLevel.DebugHi
--        LogLevel.Info
--        LogLevel.Notice
--        LogLevel.Warning
--        LogLevel.Error
--        LogLevel.Critical
-- @param logMessage - string to log
-- log(logLevel, logMessage)


-- ibmanager provides following global variables:

-- logic type, (in this case it will always be "Lua") - the same as in logic configuration file in section: <Logic Type="Lua" ...
-- LOGIC_TYPE

-- logic version, the same as in logic configuration file in section: <Logic ... Version="x.y.z" ...
-- LOGIC_VERSION

-- logic sub-type, the same as in logic configuration file in section: <Logic ... SubType="Hysteresis" ...
-- LOGIC_SUBTYPE

-- logic sub-version, the same as in logic configuration file in section: <Logic ... SubVersion="x.y.z" ...
-- LOGIC_SUBVERSION

-- logic instance name - the same as in logic configuration file, in section: <Instance Name="0">
-- LOGIC_INSTANCE_NAME

-- add script directory to package path
package.path = package.path .. ";./logic/scripts/utils/?.lua";

-- use script - without .lua extension - delta class
require("State");

SUPPORTED_SUBLOGIC_TYPE = "Configh4f6v3";
SUPPORTED_SUBLOGIC_VERSION = "0.0.0";
g_versionChecked = false;

-- entry point to the logic
-- @param firstCall - tells if logic is called first time
-- @return        - nothing
function onLogicCall(firstCall)

  if not g_versionChecked then
    -- checking sublogic type and sublogic version
    if LOGIC_SUBTYPE ~= SUPPORTED_SUBLOGIC_TYPE then
      error("Wrong logic sub-type. expected " .. SUPPORTED_SUBLOGIC_TYPE .. " but used " .. LOGIC_SUBTYPE);
    end
    local versionWithoutBuild = string.match(LOGIC_SUBVERSION, "[0-9]+%.[0-9]+%.[0-9]+");
    if versionWithoutBuild ~= SUPPORTED_SUBLOGIC_VERSION then
      error("Wrong logic sub-version. expected " .. SUPPORTED_SUBLOGIC_VERSION .. " but used " .. LOGIC_SUBVERSION);
    end
    g_versionChecked = true;
  end

end
