--    ======================
--    Description
--    ======================
--
--    Logika umożliwiająca sterowanie gruntową pompą ciepła:
--
--    - sprężarka on/off
--    - pompa górnego źródła c.w.u.
--    - pompa górnego źródła c.o.
--    - pompę dolnego źródła
--    - chłodzenie pasywne
--    - chłodzenie aktywne
--    - regeneracja GWC dolnym źródłem
--
--    ======================
--    Parameters
--    ======================
--
--    SubLogic supports following variables:
--
--    input.supply.t.value
--    input.supply.t.err                      - temperatura zasilania c.o. (wyjścia z PC)
--
--    input.return.t.value
--    input.return.t.err                      - temperatura powrotu c.o. (powrotu na PC)
--
--    input.ground.out.t.value
--    input.ground.out.t.err                  - temperatura wyjścia dolnego źródła (z gruntu) do PC
--
--    input.ground.in.t.value
--    input.ground.in.t.err                   - temperatura powrotu dolnego źródła (do gruntu) z PC
--
--    input.cool.return.t.value
--    input.cool.return.t.err                 - temperatura powrotu dolnego źródła do pompy ciepła. Istotne dla chłodzenia aktywnego.
--                                              Jest to temperatura powrotu z chłodnicy (temperatura tego co wchodzi
--                                              na wymiennik dolnego źródła na pompę ciepła)
--
--    input.ghe.liq.out.t.value
--    input.ghe.liq.out.t.err                 - temperatura powrotu płynu z GWC
--
--    input.season                            - 0 - winter, 1 - summer [0..1]
--
--    input.alert.low                         - alarm niskiego ciśnienia układu gazowego [0..1]
--
--    input.alert.medium                      - alarm średniego ciśnienia układu gazowego [0..1]
--
--    input.alert.high                        - alarm wysokiego ciśnienia układu gazowego [0..1]
--
--    input.alert.other                       - alarm innego typu, skutkujący zatrzymaniem kompresora i kontrolowanym zatrzymaniem PC [0..1]
--
--    input.demand.dw.heating                 - żądanie aby pompa ciepła ładowała zbiornik c.w.u.
--
--    input.demand.buff.heating               - żądanie aby pompa ciepła ładowała zbiornik buforowy
--
--    input.demand.cool                       - żądanie aby pompa ciepła chłodziła pasywnie
--
--    input.demand.activcool                  - żądanie aby pompa ciepła chłodziła aktywnie
--
--    input.demand.ghe                        - żądanie aby pompa ciepła regenerowała GWC
--
--    output.compr                            - kompresor PC [0..1]
--
--    output.ground.pump                      - pompa dolnego źródła (gruntowa) PC [0..1]
--
--    output.dw.pump                          - pompa górnego źródła PC (ładowanie c.w.u.) [0..1]
--
--    output.buff.pump                        - pompa górnego źródła PC (ładowanie bufora) [0..1]
--
--    output.cool.passive                     - zawór załączający pasywny tryb chłodzenia (0 - ogrzewanie; 1 - chłodzenie) [0..1]
--
--    output.cool.active                      - pompa i zawór załączający aktywny tryb chłodzenia (0 - ogrzewanie; 1 - aktywne chłodzenie) [0..1]
--
--    output.ghe                              - kierowanie dolnego źródła na GWC (0 - powrót do gruntu, 1 - powrót przez GWC) [0..1]
--
--    setting.alert.med.dw.pump.state         - czy w czasie przerwy w ładowaniu c.w.u. pompa dw ma pracować cały czas
--
--    setting.alert.med.buff.load.state       - czy w czasie przerwy w ładowaniu c.w.u. ma być ładowany zbiornik buforowy
--                                              (0 - nie; 1 - tak; 2 - AUTO: w zimie tak, w lecie nie)
--
--    setting.alert.med.buff.load.max.supply.t.value
--                                            - jeżeli setting.alert.med.buff.load.state jest ustawiony to (po czasie zwłoki counter.alert.med.buff.load.max.supply.t.delay)
--                                              przy jakiej maksymalnej temperaturze zasilania ma zostać wyłączone żądanie grzania bufora
--
--    setting.dw.t.supply.buff.pump.cool      - czy pompa buforowa ma być używana do obniżania temperatury zasilania PC (na podstawie counter.dw.t.supply.max.status)
--
--    setting.buff.enabled                    - czy pompa ciepa jest aktywna do ogrzewania bufora
--
--    setting.dw.enabled                      - czy pompa ciepa jest aktywna do ogrzewania c.w.u.
--
--    setting.cool.enabled                    - czy pompa ciepa jest aktywna do chłodzenia pasywnego
--
--    setting.activcool.enabled               - czy pompa ciepa jest aktywna do chłodzenia aktywnego
--
--    setting.dw.t.supply.max                 - maksymalna temperatura zasilania (wyjścia z pompy ciepła) kiedy jest wymagane ogrzewanie c.w.u. i nie jest wymagane chłodzenie aktywne
--
--    setting.dw.t.supply.hyst                - histereza dla setting.dw.t.supply.max
--
--    setting.activcool.t.suppl.max           - maksymalna temperatura zasilania (wyjścia z pompy ciepła) kiedy jest wymagane chłodzenie aktywne i równocześnie jest wymagane ogrzewanie c.w.u.
--
--    setting.activcool.t.supply.hyst         - histereza dla setting.activcool.t.suppl.max
--
--    setting.activcool.t.ground.out.min      - minimalna temperatura dolnego źródła kiedy jest wymagane chłodzenie aktywne, oraz do odpadowego
--                                              chłodzenia pasywnego w trakcie ogrzewania c.w.u. (puszczenie przepływu wprost na grunt aby zapobiec zamrożeniu DZ)
--
--    setting.activcool.t.ground.out.hyst     - histereza dla setting.activcool.t.ground.out.min
--
--    setting.activcool.t.ground.out.ghe.min  - minimalna temperatura dolnego źródła kiedy jest wymagane chłodzenie aktywne, oraz do odpadowego chłodzenia pasywnego
--                                              w trakcie ogrzewania c.w.u. (regeneracja GWC)
--
--    setting.alert.compr.delay               - czas przerwy w pracy kompresora po wystąpieniu alertu błędu [s]
--
--    setting.alert.med.break.time            - czas przerwy w ładowaniu c.w.u. po wystąpieniu alarmu średniego ciśnienia [s]
--
--    setting.alert.med.buff.load.max.supply.t.delay
--                                            - czas powiązany z setting.alert.med.buff.load.max.supply.t.value [s]
--
--    setting.compr.start.delay               - czas opóźnienia startu kompresora względem uruchomienia dolnego i górnego źródła (po fladze uruchomienia pompy ciepła) [s]
--
--    setting.compr.stop.delay                - czas opóźnienia zatrzymania pomp dolnego i górnego źródła względem zatrzymania kompresora (po fladze zatrzymania pompy ciepła) [s]
--
--    setting.compr.main.delay                - czas minimalnej przerwy między kolejnymi startami kompresora [s]
--
--    setting.alert.service.blocked.reset     - wpisanie 1 powoduje resetowanie blokady serwisowej pompy ciepła
--
--    setting.logic.delay                     - czas zwłoki działania logiki. Dopiero po tym czasie logika zacznie wysterowywać wyjścia i odczytywać błędy [s]
--
--    counter.alert.med.buff.load.status      - flaga: w czasie przerwy w ładowaniu c.w.u. ma być ładowany zbiornik buforowy
--
--    counter.dw.t.supply.max.status          - flaga: czy warunek maksymalnej temperatury zasilania (wyjścia z pompy ciepła) kiedy jest wymagane ogrzewanie c.w.u. i kiedy nie jest
--                                              wymagane aktywne chłodzenie jest spełniony
--
--    counter.activcool.t.supply.max.status   - flaga: czy warunek maksymalnej temperatury zasilania (wyjścia z pompy ciepła) kiedy jest wymagane chłodzenie aktywne i równocześnie
--                                              jest wymagane ogrzewanie c.w.u. jest spełniony
--
--    counter.activcool.t.ground.out.min.status
--                                            - flaga: czy warunek minimalnej temperatury dolnego źródła kiedy jest wymagane chłodzenie aktywne lub podczas realizacji odpadowego
--                                              chłodzenia jest spełniony
--
--    counter.activcool.t.ground.out.ghe.min.status
--                                            - flaga: czy warunek minimalnej temperatury dolnego źródła kiedy jest wymagane chłodzenie aktywne lub podczas realizacji odpadowego
--                                              chłodzenia dla przełączenia na regeneracje GHE jest spełniony
--
--    counter.alert.compr.delay               - licznik przerwy w pracy kompresora po wystąpieniu alertu błędu [s]
--
--    counter.alert.med.break.time            - licznik przerwy w ładowaniu c.w.u. po wystąpieniu alarmu średniego ciśnienia [s]
--
--    counter.alert.med.buff.load.max.supply.t.delay
--                                            - licznik powiązany z setting.alert.med.buff.load.max.supply.t.value [s]
--
--    counter.compr.start.delay               - licznik opóźnienia startu kompresora względem uruchomienia dolnego i górnego źródła (po fladze uruchomienia pompy ciepła) [s]
--
--    counter.compr.stop.delay                - licznik opóźnienia zatrzymania pomp dolnego i górnego źródła względem zatrzymania kompresora (po fladze zatrzymania pompy ciepła) [s]
--
--    counter.compr.main.delay                - licznik minimalnej przerwy między kolejnymi startami kompresora [s]
--
--    counter.work.main.status                - flaga: czy logika chce załączyć pompę ciepła
--
--    counter.work.dw.status                  - flaga: czy logika chce aby pompa ciepła ładowała zbiornik c.w.u.
--
--    counter.work.buff.status                - flaga: czy logika chce aby pompa ciepła ładowała zbiornik buforowy
--
--    counter.work.cool.status                - flaga: czy logika chce aby pompa ciepła chłodziła pasywnie
--
--    counter.work.activcool.status           - flaga: czy logika chce aby pompa ciepła chłodziła aktywnie
--
--    counter.work.ghe.status                 - flaga: czy logika chce aby pompa ciepła regenerowała GWC
--
--    counter.work.mode                       - faza pracy pompy ciepła (0 - wyłączanie, 1 - uruchamianie i normalna praca)
--
--    counter.alert.service.blocked.state     - flaga: czy jest aktywna blokada serwisowa pompy ciepła
--
--    counter.alert.service.blocked.last.err  - kod błędy który spowodował blokadę serwisową:
--
--                                              0 - brak błędu
--                                              1 - alarm niskiego ciśnienia układu gazowego
--                                              2 - alarm wysokiego ciśnienia układu gazowego
--                                              3 - alarm innego typu, skutkujący zatrzymaniem kompresora i kontrolowanym zatrzymaniem PC
--
--    counter.alert.t.state                   - flaga: wartość 1 oznacza uszkodzenie jakiegokolwiek czujnika. Uszkodzenie jakiegokolwiek czujnika wyłącza wszystkie urządzenia.
--
--    counter.logic.delay                     - licznik czas zwłoki działania logiki. [s]
--
--    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
--    ======================
--
--    2019-09-20 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");
require("DownCounter");

g_outputCompr = nil;
g_outputGroundPump = nil;
g_outputDwPump = nil;
g_outputBuffPump = nil;
g_outputCoolPassive = nil;
g_outputCoolActive = nil;
g_outputGhe = nil;

g_counterAlertComprDelay = nil;
g_counterAlertMedBreakTime = nil;
g_counterAlertMedBuffLoadMaxSupplyTDelay = nil;
g_counterComprStartDelay = nil;
g_counterComprStopDelay = nil;
g_counterComprMainDelay = nil;
g_counterLogicDelay = nil;

g_counterAlertMedBuffLoadStatus = nil;
g_counterDwTSupplyMaxStatus = nil;
g_counterActivcoolTSupplyMaxStatus = nil;
g_counterActivcoolTGroundOutMinStatus = nil;
g_counterActivcoolTGroundOutGheMinStatus = nil;
g_counterWorkMainStatus = nil;
g_counterWorkDwStatus = nil;
g_counterWorkBuffStatus = nil;
g_counterWorkCoolStatus = nil;
g_counterWorkActivcoolStatus = nil;
g_counterWorkGheStatus = nil;
g_counterWorkMode = nil;
g_counterAlertServiceBlockedState = nil;

g_counterAlertServiceBlockedLastErr = 0;
g_oldInputAlertMedium = 0;


SUPPORTED_SUBLOGIC_TYPE = "HP01";
SUPPORTED_SUBLOGIC_VERSION = "1.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

  local inputSupplyTValue = getLogicValue("input.supply.t.value");
  local inputSupplyTErr = getLogicValue("input.supply.t.err");
  local inputReturnTValue = getLogicValue("input.return.t.value");
  local inputReturnTErr = getLogicValue("input.return.t.err");
  local inputGroundOutTValue = getLogicValue("input.ground.out.t.value");
  local inputGroundOutTErr = getLogicValue("input.ground.out.t.err");
  local inputGroundInTValue = getLogicValue("input.ground.in.t.value");
  local inputGroundInTErr = getLogicValue("input.ground.in.t.err");
  local inputGheLiqOutTValue = getLogicValue("input.ghe.liq.out.t.value");
  local inputGheLiqOutTErr = getLogicValue("input.ghe.liq.out.t.err");
  local inputCoolReturnTValue = getLogicValue("input.cool.return.t.value");
  local inputCoolReturnTErr = getLogicValue("input.cool.return.t.err");
  local inputSeason = getLogicValue("input.season");
  local inputAlertLow = getLogicValue("input.alert.low");
  local inputAlertMedium = getLogicValue("input.alert.medium");
  local inputAlertHigh = getLogicValue("input.alert.high");
  local inputAlertOther = getLogicValue("input.alert.other");
  local inputDemandDwHeating = getLogicValue("input.demand.dw.heating");
  local inputDemandBuffHeating = getLogicValue("input.demand.buff.heating");
  local inputDemandCool = getLogicValue("input.demand.cool");
  local inputDemandActivCool = getLogicValue("input.demand.activcool");
  local inputDemandGhe = getLogicValue("input.demand.ghe");

  local settingAlertMedDwPumpState = getLogicValue("setting.alert.med.dw.pump.state");
  local settingAlertMedBuffLoadState = getLogicValue("setting.alert.med.buff.load.state");
  local settingAlertMedBuffLoadMaxSupplyTValue = getLogicValue("setting.alert.med.buff.load.max.supply.t.value");
  local settingDwTSupplyBuffPumpCool = getLogicValue("setting.dw.t.supply.buff.pump.cool");
  local settingBuffEnabled = getLogicValue("setting.buff.enabled");
  local settingDwEnabled = getLogicValue("setting.dw.enabled");
  local settingCoolEnabled = getLogicValue("setting.cool.enabled");
  local settingActivcoolEnabled = getLogicValue("setting.activcool.enabled");
  local settingDwTSupplyMax = getLogicValue("setting.dw.t.supply.max");
  local settingDwTSupplyHyst = getLogicValue("setting.dw.t.supply.hyst");
  local settingActivcoolTSupplMax = getLogicValue("setting.activcool.t.suppl.max");
  local settingActivcoolTSupplyHyst = getLogicValue("setting.activcool.t.supply.hyst");
  local settingActivcoolTGroundOutMin = getLogicValue("setting.activcool.t.ground.out.min");
  local settingActivcoolTGroundOutHyst = getLogicValue("setting.activcool.t.ground.out.hyst");
  local settingActivcoolTGroundOutGheMin = getLogicValue("setting.activcool.t.ground.out.ghe.min");
  local settingAlertComprDelay = getLogicValue("setting.alert.compr.delay");
  local settingAlertMedBreakTime = getLogicValue("setting.alert.med.break.time");
  local settingAlertMedBuffLoadMaxSupplyTDelay = getLogicValue("setting.alert.med.buff.load.max.supply.t.delay");
  local settingComprStartDelay = getLogicValue("setting.compr.start.delay");
  local settingComprStopDelay = getLogicValue("setting.compr.stop.delay");
  local settingComprMainDelay = getLogicValue("setting.compr.main.delay");
  local settingAlertServiceBlockedReset = getLogicValue("setting.alert.service.blocked.reset");
  local settingLogicDelay = getLogicValue("setting.logic.delay");

  local counterAlertComprDelay = 0;
  local counterAlertMedBreakTime = 0;
  local counterAlertMedBuffLoadMaxSupplyTDelay = 0;
  local counterComprStartDelay = 0;
  local counterComprStopDelay = 0;
  local counterComprMainDelay = 0;
  local counterLogicDelay = 0;
  local counterAlertTState = 0;

  -- timers

  if g_counterAlertComprDelay == nil or firstCall then
    g_counterAlertComprDelay = DownCounter.create();
  end
--  g_counterAlertComprDelay:updateParams(settingAlertComprDelay * 1000);

--  if g_counterAlertComprDelay:elapsed() then
--    g_counterAlertComprDelay:reset();
--  end

  counterAlertComprDelay = g_counterAlertComprDelay:timeTo0() / 1000;
  counterAlertComprDelay = (counterAlertComprDelay < 0) and 0 or counterAlertComprDelay;


  if g_counterAlertMedBreakTime == nil or firstCall then
    g_counterAlertMedBreakTime = DownCounter.create();
  end
--  g_counterAlertMedBreakTime:updateParams(settingAlertMedBreakTime * 1000);

--  if g_counterAlertMedBreakTime:elapsed() then
--    g_counterAlertMedBreakTime:reset();
--  end

  counterAlertMedBreakTime = g_counterAlertMedBreakTime:timeTo0() / 1000;
  counterAlertMedBreakTime = (counterAlertMedBreakTime < 0) and 0 or counterAlertMedBreakTime;


  if g_counterAlertMedBuffLoadMaxSupplyTDelay == nil or firstCall then
    g_counterAlertMedBuffLoadMaxSupplyTDelay = DownCounter.create();
  end
--  g_counterAlertMedBuffLoadMaxSupplyTDelay:updateParams(settingAlertMedBuffLoadMaxSupplyTDelay * 1000);

--  if g_counterAlertMedBuffLoadMaxSupplyRDelay:elapsed() then
--    g_counterAlertMedBuffLoadMaxSupplyRDelay:reset();
--  end

  counterAlertMedBuffLoadMaxSupplyTDelay = g_counterAlertMedBuffLoadMaxSupplyTDelay:timeTo0() / 1000;
  counterAlertMedBuffLoadMaxSupplyTDelay = (counterAlertMedBuffLoadMaxSupplyTDelay < 0) and 0 or counterAlertMedBuffLoadMaxSupplyTDelay;


  if g_counterComprStartDelay == nil or firstCall then
    g_counterComprStartDelay = DownCounter.create();
  end
--  g_counterComprStartDelay:updateParams(settingComprStartDelay * 1000);

--  if g_counterComprStartDelay:elapsed() then
--    g_counterComprStartDelay:reset();
--  end

  counterComprStartDelay = g_counterComprStartDelay:timeTo0() / 1000;
  counterComprStartDelay = (counterComprStartDelay < 0) and 0 or counterComprStartDelay;


  if g_counterComprStopDelay == nil or firstCall then
    g_counterComprStopDelay = DownCounter.create();
  end
--  g_counterComprStopDelay:updateParams(settingComprStopDelay * 1000);

--  if g_counterComprStopDelay:elapsed() then
--    g_counterComprStopDelay:reset();
--  end

  counterComprStopDelay = g_counterComprStopDelay:timeTo0() / 1000;
  counterComprStopDelay = (counterComprStopDelay < 0) and 0 or counterComprStopDelay;


  if g_counterComprMainDelay == nil or firstCall then
    g_counterComprMainDelay = DownCounter.create();
  end
--  g_counterComprMainDelay:updateParams(settingComprMainDelay * 1000);

--  if g_counterComprMainDelay:elapsed() then
--    g_counterComprMainDelay:reset();
--  end

  counterComprMainDelay = g_counterComprMainDelay:timeTo0() / 1000;
  counterComprMainDelay = (counterComprMainDelay < 0) and 0 or counterComprMainDelay;


  if g_counterLogicDelay == nil or firstCall then
    g_counterLogicDelay = DownCounter.create();
  end
  g_counterLogicDelay:updateParams(settingLogicDelay * 1000);

--  if g_counterLogicDelay:elapsed() then
--    g_counterLogicDelay:reset();
--  end

  counterLogicDelay = g_counterLogicDelay:timeTo0() / 1000;
  counterLogicDelay = (counterLogicDelay < 0) and 0 or counterLogicDelay;

  -- states
  if g_outputCompr == nil or firstCall then
    g_outputCompr = State.create(0, 0, 1, true);
  end
  g_outputCompr:call();

  if g_outputGroundPump == nil or firstCall then
    g_outputGroundPump = State.create(0, 0, 1, true);
  end
  g_outputGroundPump:call();

  if g_outputDwPump == nil or firstCall then
    g_outputDwPump = State.create(0, 0, 1, true);
  end
  g_outputDwPump:call();

  if g_outputBuffPump == nil or firstCall then
    g_outputBuffPump = State.create(0, 0, 1, true);
  end
  g_outputBuffPump:call();

  if g_outputCoolPassive == nil or firstCall then
    g_outputCoolPassive = State.create(0, 0, 1, true);
  end
  g_outputCoolPassive:call();

  if g_outputCoolActive == nil or firstCall then
    g_outputCoolActive = State.create(0, 0, 1, true);
  end
  g_outputCoolActive:call();

  if g_outputGhe == nil or firstCall then
    g_outputGhe = State.create(0, 0, 1, true);
  end
  g_outputGhe:call();


  if g_counterAlertMedBuffLoadStatus == nil or firstCall then
    g_counterAlertMedBuffLoadStatus = State.create(0, 0, 1, true);
  end
  g_counterAlertMedBuffLoadStatus:call();

  if g_counterDwTSupplyMaxStatus == nil or firstCall then
    g_counterDwTSupplyMaxStatus = State.create(0, 0, 1, true);
  end
  g_counterDwTSupplyMaxStatus:call();

  if g_counterActivcoolTSupplyMaxStatus == nil or firstCall then
    g_counterActivcoolTSupplyMaxStatus = State.create(0, 0, 1, true);
  end
  g_counterActivcoolTSupplyMaxStatus:call();

  if g_counterActivcoolTGroundOutMinStatus == nil or firstCall then
    g_counterActivcoolTGroundOutMinStatus = State.create(0, 0, 1, true);
  end
  g_counterActivcoolTGroundOutMinStatus:call();

  if g_counterActivcoolTGroundOutGheMinStatus == nil or firstCall then
    g_counterActivcoolTGroundOutGheMinStatus = State.create(0, 0, 1, true);
  end
  g_counterActivcoolTGroundOutGheMinStatus:call();

  if g_counterWorkMainStatus == nil or firstCall then
    g_counterWorkMainStatus = State.create(0, 0, 1, true);
  end
  g_counterWorkMainStatus:call();

  if g_counterWorkDwStatus == nil or firstCall then
    g_counterWorkDwStatus = State.create(0, 0, 1, true);
  end
  g_counterWorkDwStatus:call();

  if g_counterWorkBuffStatus == nil or firstCall then
    g_counterWorkBuffStatus = State.create(0, 0, 1, true);
  end
  g_counterWorkBuffStatus:call();

  if g_counterWorkCoolStatus == nil or firstCall then
    g_counterWorkCoolStatus = State.create(0, 0, 1, true);
  end
  g_counterWorkCoolStatus:call();

  if g_counterWorkActivcoolStatus == nil or firstCall then
    g_counterWorkActivcoolStatus = State.create(0, 0, 1, true);
  end
  g_counterWorkActivcoolStatus:call();

  if g_counterWorkGheStatus == nil or firstCall then
    g_counterWorkGheStatus = State.create(0, 0, 1, true);
  end
  g_counterWorkGheStatus:call();

  if g_counterWorkMode == nil or firstCall then
    g_counterWorkMode = State.create(0, 0, 1, true);
  end
  g_counterWorkMode:call();

  if g_counterAlertServiceBlockedState == nil or firstCall then
    g_counterAlertServiceBlockedState = State.create(0, 0, 1, true);
  end
  g_counterAlertServiceBlockedState:call();


  if (counterLogicDelay == 0) then
  
    -- obsługa alarmu temperatur
    if ((inputSupplyTErr ~= 0)
      or (inputReturnTErr ~=0)
      or (inputGroundOutTErr ~=0)
      or (inputGroundInTErr ~=0)
      or (inputCoolReturnTErr ~=0)
      or (inputGheLiqOutTErr ~=0)) then
  
      counterAlertTState = 1;
      g_outputCompr:setValue(0);
      g_outputGroundPump:setValue(0);
      g_outputDwPump:setValue(0);
      g_outputBuffPump:setValue(0);
      g_outputCoolPassive:setValue(0);
      g_outputCoolActive:setValue(0);
      g_outputGhe:setValue(0);
  
    end
  
    -- obsługa licznika przerwy w pracy kompresora po wystąpieniu alertu błędu
    if ((inputAlertLow ~= 0) or (inputAlertHigh ~= 0) or (inputAlertOther ~= 0)) then
      g_counterAlertComprDelay:updateParams(settingAlertComprDelay * 1000);
      g_counterAlertComprDelay:reset();
    end
  
    -- obsługa licznika przerwy w ładowaniu c.w.u. po wystąpieniu alarmu średniego ciśnienia
    if (inputAlertMedium ~= 0) then
      g_counterAlertMedBreakTime:updateParams(settingAlertMedBreakTime * 1000);
      g_counterAlertMedBreakTime:reset();
    end
  
    -- reakcja na alarm niskiego ciśnienia
    if (inputAlertLow ~= 0) then
      -- wyłączenie pompy ciepła
      g_counterWorkMainStatus:setValue(0);
      -- natychmiastowe zatrzymanie kompresora
      g_outputCompr:setValue(0);
      -- natychmiastowe zatrzymanie pompy dolnego źródła
      g_outputGroundPump:setValue(0);
    end
  
    -- reakcja na alarm wysokiego ciśnienia, pozostałe alarmy, blokadę serwisową oraz gdy licznik alarmowy liczy
    if ((inputAlertHigh ~= 0)
      or (inputAlertOther ~= 0)
      or (g_counterAlertServiceBlockedState:getValue() ~= 0)
      or (counterAlertComprDelay ~= 0) ) then
  
      -- wyłączenie pompy ciepła
      g_counterWorkMainStatus:setValue(0);
      -- natychmiastowe zatrzymanie kompresora
      g_outputCompr:setValue(0);
  
    end
  
    -- blokada serwisowa pompy ciepła
    if ((inputAlertLow ~= 0)
      or (inputAlertHigh ~= 0)
      or (inputAlertOther ~= 0) ) then
  
      g_counterAlertServiceBlockedState:setValue(1);

      if (g_counterAlertServiceBlockedLastErr == 0) then

        if (inputAlertLow ~= 0) then
          g_counterAlertServiceBlockedLastErr = 1;
        end

        if (inputAlertHigh ~= 0) then
          g_counterAlertServiceBlockedLastErr = 2;
        end

        if (inputAlertOther ~= 0) then
          g_counterAlertServiceBlockedLastErr = 3;
        end
        
      end;
      
  
    end
  
    -- obsługa alarmu średniego ciśnienia
  
    -- ustalenie wartości counter.alert.med.buff.load.status
  
    if ((settingAlertMedBuffLoadState == 0) or (settingAlertMedBuffLoadState == 1) ) then
      g_counterAlertMedBuffLoadStatus:setValue(settingAlertMedBuffLoadState);
    else
      if (inputSeason == 0) then
        -- zimą tak
        g_counterAlertMedBuffLoadStatus:setValue(1);
      else
        -- latem nie
        g_counterAlertMedBuffLoadStatus:setValue(0);
      end
    end
  
    -- jeżeli jest przerwa w ładowaniu c.w.u. ze względu na alarm średniego ciśnienia
  
    if (counterAlertMedBreakTime ~= 0) then
      -- jeżeli jest odpowiedni setting i zbiornik dw jest do grzania to pompa dw cały czas chodzi
      if (settingAlertMedDwPumpState ~= 0) then
        -- włączenie pompy dw
        g_outputDwPump:setValue(1);
  
        -- przy aktywnym chłodzeniu włącz pompę buff
        if (g_counterWorkActivcoolStatus:getValue() ~= 0) then
          g_outputBuffPump:setValue(1);
        end
      end
  
      -- jeżeli jest flaga counter.alert.med.buff.load.status
      if (g_counterAlertMedBuffLoadStatus:getValue() ~= 0) then
  
        -- jeżeli jest zewnętrzny sygnał ładowania bufora to należy go ładować
        -- pod warunkiem, że jest aktywna pompa ciepła do ładowania bufora
        if (inputDemandBuffHeating ~= 0) then
          if (settingBuffEnabled ~= 0) then
            g_counterWorkBuffStatus:setValue(1);
          else
            g_counterWorkBuffStatus:setValue(0);
          end
        end
  
        -- jeżeli sprężarka nie pracuje i nie ma zewnętrznego sygnału ładowania bufora
        -- to nie ma sensu ładować bufora
        if ((inputDemandBuffHeating == 0) and (g_outputCompr:getValue() == 0)) then
          g_counterWorkBuffStatus:setValue(0);
        end
  
        -- jeżeli przed chwilą wybiło alarm średniego ciśnienia to zresetuj licznik
        if ((inputAlertMedium ~= 0) and (g_oldInputAlertMedium ~= inputAlertMedium)) then
          g_counterAlertMedBuffLoadMaxSupplyTDelay:updateParams(settingAlertMedBuffLoadMaxSupplyTDelay * 1000);
          g_counterAlertMedBuffLoadMaxSupplyTDelay:reset();
        end
  
        -- jeżeli licznik counter.alert.med.buff.load.status odlicza to włącz zapotrzebowanie
        -- na ładowanie bufora
        if (counterAlertMedBuffLoadMaxSupplyTDelay ~= 0) then
          g_counterWorkBuffStatus:setValue(1);
        else
          -- jeżeli licznik dojdzie do 0 to ładowanie bufora uzależnione od temperatury
          -- zasilania c.o.
          g_counterWorkBuffStatus:set1IfLowerThan(inputSupplyTValue, settingAlertMedBuffLoadMaxSupplyTValue, 10);
        end
      else
        g_counterWorkBuffStatus:setValue(inputDemandBuffHeating);
      end
  
      -- kasujemy zapotrzebowanie na ogrzewanie c.w.u.
      g_counterWorkDwStatus:setValue(0);
    else
      -- ustalamy zapotrzebowanie na c.w.u. w zależności od aktywności pompy do celów c.w.u.
      if (settingDwEnabled == 1) then
        g_counterWorkDwStatus:setValue(inputDemandDwHeating);
      else
        g_counterWorkDwStatus:setValue(0);
      end
  
      g_counterWorkBuffStatus:setValue(inputDemandBuffHeating);
    end
  
    -- sprawdzenie warunku przekroczenia temperatury zasilania PC przy ładowaniu c.w.u.
    g_counterDwTSupplyMaxStatus:set1IfHigherThan(inputSupplyTValue, settingDwTSupplyMax, settingDwTSupplyHyst);
  
    -- sprawdzenie warunku przekroczenia temperatury zasilania PC przy aktywnym
    g_counterActivcoolTSupplyMaxStatus:set1IfHigherThan(inputSupplyTValue, settingActivcoolTSupplMax, settingActivcoolTSupplyHyst);
  
    -- sprawdzenie warunku przekroczenia minimalnego progu temperatury wejścia DZ
    g_counterActivcoolTGroundOutMinStatus:set1IfLowerThan(inputCoolReturnTValue, settingActivcoolTGroundOutMin, settingActivcoolTGroundOutHyst);
  
    -- sprawdzenie warunku przekroczenia minimalnego progu temperatury wejścia DZ dla regeneracji GHE
    g_counterActivcoolTGroundOutGheMinStatus:set1IfLowerThan(inputGheLiqOutTValue, settingActivcoolTGroundOutGheMin, settingActivcoolTGroundOutHyst);
  
    -- ustawiamy żądanie chłodzenia aktywnego na podstawie flagi aktywności pompy ciepła dla chłodzenia aktywnego
    -- oraz żądania zewnętrznego dla chłodzenia aktywnego
    if (settingActivcoolEnabled == 1) then
      g_counterWorkActivcoolStatus:setValue(inputDemandActivCool);
    else
      g_counterWorkActivcoolStatus:setValue(0);
    end
  
    -- jeżeli jest żądany activcool to zawsze musi być żądany cool (chłodzenie pasywne)
    if (g_counterWorkActivcoolStatus:getValue() == 1) then
      g_counterWorkCoolStatus:setValue(1);
    end
  
    -- ocena czy chcemy załączyć pompę ciepła (na podstawie żądania grzania c.o., c.w.u. lub active cool)
    if ( (g_counterWorkDwStatus:getValue() == 1)
      or (g_counterWorkBuffStatus:getValue() == 1)
      or (g_counterWorkActivcoolStatus:getValue() == 1)) then
  
      g_counterWorkMainStatus:setValue(1);
  
    else
      g_counterWorkMainStatus:setValue(0);
    end
  
    -- ustalenie fazy pracy pompy ciepła, czy zmienił się status
    if (g_counterWorkMainStatus:isChanged() == true) then
  
      if (g_counterWorkMainStatus:getValue() == 1) then
        -- włączono żądanie pracy pompy ciepła - faza rozruchu
        g_counterWorkMode:setValue(1);
  
        g_counterComprStartDelay:updateParams(settingComprStartDelay * 1000);
        g_counterComprStartDelay:reset();
  
        g_counterComprStopDelay:updateParams(1);
        g_counterComprStopDelay:reset();
  
      else
        -- wyłączono żądanie pracy pompy ciepła - faza wyłączania
        g_counterWorkMode:setValue(0);
  
        g_counterComprStartDelay:updateParams(1);
        g_counterComprStartDelay:reset();
  
        g_counterComprStopDelay:updateParams(settingComprStopDelay * 1000);
        g_counterComprStopDelay:reset();
      end
  
    end
  
    -- ustawiamy żądanie chłodzenia pasywnego na podstawie flagi aktywności pompy ciepła dla chłodzenia pasywnego
    -- oraz żądania zewnętrznego dla chłodzenia pasywnego
    if (settingCoolEnabled == 1) then
      g_counterWorkCoolStatus:setValue(inputDemandCool);
    else
      g_counterWorkCoolStatus:setValue(0);
    end
  
    -- jeżeli jest wyłączone żądanie aktywnego chłodzenia, jest włączone żądanie pasywnego chłodzenia
    -- i temperatura dolnego źródła jest poniżej minimalnej DZ dla aktywnego chłodzenia to jest ryzyko
    -- zamrożenia chłodnicy dlatego przełącz zawór chłodzenia pasywnego na przepływ bezpośrednio do gruntu
  
    if ( (g_counterWorkActivcoolStatus:getValue() == 0)
      or (g_counterWorkCoolStatus:getValue() == 1)
      or (g_counterActivcoolTGroundOutMinStatus:getValue() == 1)) then
  
      g_outputCoolPassive:setValue(0);
  
    end
  
    -- ustawiamy zawór chłodzenia pasywnego
    if (g_counterWorkCoolStatus:getValue() == 1) then
      g_outputCoolPassive:setValue(1);
    else
      g_outputCoolPassive:setValue(0);
    end
  
    -- załączamy pompę dolnego źródła jeżeli chcemy chłodzić lub regenerować GWC
    if ( (g_counterWorkCoolStatus:getValue() == 1)
      or (g_counterWorkGheStatus:getValue() == 1)) then
  
      g_outputGroundPump:setValue(1);
  
    end
  
    -- faza włączania i normalnej pracy
    if ( (g_counterWorkMainStatus:getValue() == 1)
      and (g_counterWorkMode:getValue() == 1)) then
  
      -- obsługa kompresora
      if (counterComprStartDelay ~= 0) then
        g_outputCompr:setValue(0);
      else
  
        -- uruchom kompresor tylko jeżeli była odpowiednia przerwa od poprzedniego jej zatrzymania
        if (counterComprMainDelay == 0) then
          g_outputCompr:setValue(1);
        end
  
      end
  
      -- włączenie pompy dolnego źródła
      g_outputGroundPump:setValue(1);
  
      -- obsługa żądania ładowania dw
      if (g_counterWorkDwStatus:getValue() == 1) then
        -- włączenie pompy dw
        g_outputDwPump:setValue(1);
      end
  
      -- włączenie pompy buff po przekroczeniu temperatury zasilania i przy aktywnym wychładzaniu zasilania przy pomocy pompy buff
      if ( (settingDwTSupplyBuffPumpCool == 1)
        and (g_counterDwTSupplyMaxStatus:getValue() == 1)
        and (g_counterWorkActivcoolStatus:getValue() == 0)) then
  
        g_outputBuffPump:setValue(1);
  
      end
  
      -- włączenie pompy buff na podstawie wewnętrznego żądania buff
      if (g_counterWorkBuffStatus:getValue() == 1) then
        g_outputBuffPump:setValue(1);
      end
  
      -- obsługa żądania chłodzenia aktywnego (activcool)
      if (g_counterWorkActivcoolStatus:getValue() == 1) then
  
        -- włącz pompę activecool i zawór
        g_outputCoolActive:setValue(1);
  
        -- włączenie regeneracji GHE (równocześnie podniesienie temperatury na powrocie do PC
        if (g_counterActivcoolTGroundOutGheMinStatus:getValue() == 1) then
          g_counterWorkGheStatus:setValue(1);
        end
  
        if (g_counterWorkDwStatus:getValue() == 1) then
          -- jeżeli jest żądanie chłodzenia aktywnego i równocześnie
          -- jest żądanie ładowania dw to system ma utrzymać temperaturę na wyjściu z PC
          -- na maksymalnym zadanym poziomie. Włączenie output.buff.pump powoduje spadek temperatury
          -- na zasilaniu. Wyłączenie output.buff.pump powoduje wzrost temperatury na zasilaniu.
  
          g_outputBuffPump:setValue(g_counterActivcoolTSupplyMaxStatus:getValue());
        else
          -- jeżeli jest żądanie chłodzenia aktywnego i nie ma żądania ładowania dw
          -- to utrzymujemy wejście dolnego źródła (powrotu z chłodnicy) na minimalnym poziomie. Jeżeli temperatura
          -- wejścia DZ spadnie poniżej wartości minimalnej to należy podnieść temperaturę na zasilaniu PC
          -- tak aby spadła sprawność PC (zaczęła chłodzić z mniejszą mocą). Aby zwiększyć temperaturę wejścia DZ
          -- i równocześnie temperaturę zasilania PC należy wyłączyć output.buff.pump i włączyć output.dw.pump.
          -- jeżeli temperatura wejścia DZ jest OK to output.buff.pump jest włączona i output.dw.pump jest wyłączona.
  
          if (g_counterActivcoolTGroundOutMinStatus:getValue() == 1) then
            g_outputBuffPump:setValue(0);
            g_outputDwPump:setValue(1);
          else
            g_outputBuffPump:setValue(1);
            g_outputDwPump:setValue(0);
          end
  
        end
  
      end
  
      -- wyłączenie pomp które nie zostały włączone wcześniej
      g_outputDwPump:setValue(0);
      g_outputBuffPump:setValue(0);
      g_outputCoolActive:setValue(0);
  
    end
  
    -- faza wyłączania
    if ( (g_counterWorkMainStatus:getValue() == 0)
      and (g_counterWorkMode:getValue() == 0)) then
  
      -- wyłączenie kompresora
      g_outputCompr:setValue(0);
  
      -- wyłączenie pomp górnego źródła, dolnego źródła, activcool
      if (counterComprStopDelay== 0) then
        g_outputGroundPump:setValue(0);
        g_outputDwPump:setValue(0);
        g_outputBuffPump:setValue(0);
        g_outputCoolActive:setValue(0);
      else
        -- pozostaw włączone te pompy które pracowały w poprzednim przejściu logiki
        -- (nie zmieniamy ich stanów ale blokujemy możliwośc ich zmienienia dalej)
        g_outputGroundPump:setValue(g_outputGroundPump:getValue());
        g_outputDwPump:setValue(g_outputDwPump:getValue());
        g_outputBuffPump:setValue(g_outputBuffPump:getValue());
        g_outputCoolActive:setValue(g_outputCoolActive:getValue());
      end
    end
  
    -- wyłączamy pompę dolnego źródła, jeżeli wcześniejsze warunki ją nie załączyły
    g_outputGroundPump:setValue(0);
  
    -- reset licznika minimalnej przerwy między kolejnymi startami kompresora
    if ( (g_outputCompr:isChanged() == true)
     and (g_outputCompr:getValue() == 0)) then
  
        g_counterComprMainDelay:updateParams(settingComprMainDelay * 1000);
        g_counterComprMainDelay:reset();
  
    end
  
    -- ustawiamy żądanie regeneracji GWC zgodnie z sygnałem żądania
    g_counterWorkGheStatus:setValue(inputDemandGhe);
  
    -- ustawiamy zawór regeneracji GWC
    if (g_counterWorkGheStatus:getValue() == 1) then
      g_outputGhe:setValue(1);
    else
      g_outputGhe:setValue(0);
    end

  end

  if (settingAlertServiceBlockedReset == 1) then
    setLogicValue("setting.alert.service.blocked.reset", 0);
    g_counterAlertServiceBlockedState:setValue(0);
    g_counterAlertServiceBlockedLastErr = 0;
  end

  -- send logic variables to ibmanager
  setLogicValue("output.compr", g_outputCompr:getValue());
  setLogicValue("output.ground.pump", g_outputGroundPump:getValue());
  setLogicValue("output.dw.pump", g_outputDwPump:getValue());
  setLogicValue("output.buff.pump", g_outputBuffPump:getValue());
  setLogicValue("output.cool.passive", g_outputCoolPassive:getValue());
  setLogicValue("output.cool.active", g_outputCoolActive:getValue());
  setLogicValue("output.ghe", g_outputGhe:getValue());

  setLogicValue("counter.alert.compr.delay", counterAlertComprDelay);
  setLogicValue("counter.alert.med.break.time", counterAlertMedBreakTime);
  setLogicValue("counter.alert.med.buff.load.max.supply.t.delay", counterAlertMedBuffLoadMaxSupplyTDelay);
  setLogicValue("counter.compr.start.delay", counterComprStartDelay);
  setLogicValue("counter.compr.stop.delay", counterComprStopDelay);
  setLogicValue("counter.compr.main.delay", counterComprMainDelay);
  setLogicValue("counter.logic.delay", counterLogicDelay);

  setLogicValue("counter.alert.med.buff.load.status", g_counterAlertMedBuffLoadStatus:getValue());
  setLogicValue("counter.dw.t.supply.max.status", g_counterDwTSupplyMaxStatus:getValue());
  setLogicValue("counter.activcool.t.supply.max.status", g_counterActivcoolTSupplyMaxStatus:getValue());
  setLogicValue("counter.activcool.t.ground.out.min.status", g_counterActivcoolTGroundOutMinStatus:getValue());
  setLogicValue("counter.activcool.t.ground.out.ghe.min.status", g_counterActivcoolTGroundOutGheMinStatus:getValue());
  setLogicValue("counter.work.main.status", g_counterWorkMainStatus:getValue());
  setLogicValue("counter.work.dw.status", g_counterWorkDwStatus:getValue());
  setLogicValue("counter.work.buff.status", g_counterWorkBuffStatus:getValue());
  setLogicValue("counter.work.cool.status", g_counterWorkCoolStatus:getValue());
  setLogicValue("counter.work.activcool.status", g_counterWorkActivcoolStatus:getValue());
  setLogicValue("counter.work.ghe.status", g_counterWorkGheStatus:getValue());
  setLogicValue("counter.work.mode", g_counterWorkMode:getValue());
  setLogicValue("counter.alert.service.blocked.state", g_counterAlertServiceBlockedState:getValue());
  setLogicValue("counter.alert.service.blocked.last.err", g_counterAlertServiceBlockedLastErr);
  setLogicValue("counter.alert.t.state", counterAlertTState);

  g_oldInputAlertMedium = inputAlertMedium;

end
