-- ======================
-- Description
-- ======================
--
-- Logika ma za zadanie zresetować np. zasilanie urządzenia jeżeli na wejściu pojawi się wartość różna od 0.
--
-- Jeżeli na wejściu pojawiła się wartość różna od 0 i trwa przez okres setting.activation.time to output = 0 na okres setting.reset.time. następnie ustawiany jest output = 1.
-- Kolejne ustawienie output na 0 jest możliwe dopiero po czasie setting.idle.time.
--
-- Jeżeli na wejściu jest wartość 0 to output = 1.
--
-- ======================
-- Parameters
-- ======================
--
-- SubLogic supports following variables:
--
-- input - wejście. Jeżeli 0 to watchdog ma być nieaktywny. Jeżeli różne od 0 to watchdog ma zostać aktywowany [0..]
--
-- output - stan wyjścia resetującego np. przekaźnik. 1 - zasilanie (normalna praca); 0 - brak zasilania (reset) [0..1]
--
-- setting.manual.mode - tryb pracy. 0 - tryb automatyczny; 1 - tryb manualny [0..1]
--
-- setting.manual.output - wartość wyjścia output w trybie manualnym [0..1]
--
-- setting.activation.time - jeżeli przez ten czas wejście jest różne od 0 to może nastąpić zmiana output = 0 [s]
--
-- setting.reset.time - przez ten czas output = 0 (czas stanu wyłączenia) [s]
--
-- setting.idle.time - czas przerwy po załączeniu output = 1, zanim będzie możliwe ponowna zmiana stanu output = 1 [s]
--
-- setting.clear.resets.no - wpisanie jedynki do tego parametru powoduje wyzerowanie parametru counter.resets.no [0..1]
--
-- counter.resets.no - ilość wywołanych resetów [0..]
--
-- counter.activation.downcounter - licznik do zadziałania watchdoga [0..]
--
-- counter.reset.downcounter - licznik zerowania wyjścia output [0..]
--
-- counter.idle.downcounter - licznik pozostały do kolejnego zadziałania watchdoga [0..]
--
-- 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-12-02 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_output = nil;
g_counterActivationDowncounter = nil;
g_counterResetDowncounter = nil;
g_counterIdleDowncounter = nil;
g_state = 0;
SUPPORTED_SUBLOGIC_TYPE = "Watchdog";
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
local input = getLogicValue("input");
local settingManualMode = getLogicValue("setting.manual.mode");
local settingManualOutput = getLogicValue("setting.manual.output");
local settingActivationTime = getLogicValue("setting.activation.time");
local settingResetTime = getLogicValue("setting.reset.time");
local settingIdleTime = getLogicValue("setting.idle.time");
local counterActivationDowncounter = 0;
local counterResetDowncounter = 0;
local counterIdleDowncounter = 0;
-- states
if g_output == nil or firstCall then
g_output = State.create(0, 0, 1, true);
end
g_output:call();
-- timers
if g_counterActivationDowncounter == nil or firstCall then
g_counterActivationDowncounter = DownCounter.create();
end
g_counterActivationDowncounter:updateParams(settingActivationTime * 1000);
-- if g_counterActivationDowncounter:elapsed() then
-- g_counterActivationDowncounter:reset();
-- end
counterActivationDowncounter = g_counterActivationDowncounter:timeTo0() / 1000;
counterActivationDowncounter = (counterActivationDowncounter < 0) and 0 or counterActivationDowncounter;
if g_counterResetDowncounter == nil or firstCall then
g_counterResetDowncounter = DownCounter.create();
end
g_counterResetDowncounter:updateParams(settingResetTime * 1000);
-- if g_counterResetDowncounter:elapsed() then
-- g_counterResetDowncounter:reset();
-- end
counterResetDowncounter = g_counterResetDowncounter:timeTo0() / 1000;
counterResetDowncounter = (counterResetDowncounter < 0) and 0 or counterResetDowncounter;
if g_counterIdleDowncounter == nil or firstCall then
g_counterIdleDowncounter = DownCounter.create();
end
g_counterIdleDowncounter:updateParams(settingIdleTime * 1000);
-- if g_counterIdleDowncounter:elapsed() then
-- g_counterIdleDowncounter:reset();
-- end
counterIdleDowncounter = g_counterIdleDowncounter:timeTo0() / 1000;
counterIdleDowncounter = (counterIdleDowncounter < 0) and 0 or counterIdleDowncounter;
-- obsługa trybu ręcznego
if ((settingManualMode == 1)) then
g_output:setValue(settingManualOutput);
end
-- wartości g_state:
-- 0 - input == 0; normalna praca; wyjście = 1; liczniki zresetowane i stoją;
-- 1 - input == 1; biegnie czas do aktywacji; wyjście = 1; liczniki reset i idle zresetowane;
-- 2 - input == 1; upłynął czas aktywacji; wyjście = 0; biegnie czas resetu; liczniki aktywacji i idle zresetowane;
-- 3 - input == 1; upłynął czas resetu; wyjście = 1; biegnie czas idle i aktywacji; licznik resetu zresetowane
if input == 0 then
g_output:setValue(1);
g_counterActivationDowncounter:reset();
g_counterResetDowncounter:reset();
g_counterIdleDowncounter:reset();
g_state = 0;
else
if g_state == 0 then
g_state = 1;
end
if g_state == 1 then
g_output:setValue(1);
g_counterResetDowncounter:reset();
g_counterIdleDowncounter:reset();
if g_counterActivationDowncounter:elapsed() then
setLogicValue("counter.resets.no", getLogicValue("counter.resets.no") + 1);
g_state = 2;
end
end
if g_state == 2 then
g_output:setValue(0);
g_counterActivationDowncounter:reset();
g_counterIdleDowncounter:reset();
if g_counterResetDowncounter:elapsed() then
g_state = 3;
end
end
if g_state == 3 then
g_output:setValue(1);
g_counterResetDowncounter:reset();
if g_counterIdleDowncounter:elapsed() then
g_state = 1;
end
end
end
-- zerowanie licznika resetów
if getLogicValue("setting.clear.resets.no") == 1 then
setLogicValue("setting.clear.resets.no", 0);
setLogicValue("counter.resets.no", 0);
end
-- send logic variables to ibmanager
setLogicValue("output", g_output:getValue());
setLogicValue("counter.activation.downcounter", counterActivationDowncounter);
setLogicValue("counter.reset.downcounter", counterResetDowncounter);
setLogicValue("counter.idle.downcounter", counterIdleDowncounter);
end