-- ======================
-- Description
-- ======================
--
-- Logika sterująca rekuperatorem.
--
-- Osobny wentylator nawiewny i wywiewny, każdy sterowany proporcjonalnie. Dowolna ilość nastawialnych poziomów wentylacji.
--
-- "Realizacja funkcji wyrównania temperatury" - oznacza, zwiększenie obrotów wentylatora nawiewnego i wywiewnego o odpowiednie
-- deltę względem trybu nastawionego. Delta jest różna dla każdego biegu.
--
-- Obsługa trybu override (obejście). Jeżeli obejście jest aktywne to wentylacja jest ustawiana na wybranym biegu obejścia. Przy czym jest również realizowana
-- funkcja wyrównania temperatury (wartość obrotów wentylacji powiększona o deltę dla biegu obejścia)
--
-- Obsługa sygnału alarmowego. Jeżeli sygnał alarmowy jest aktywny to wentylacja jest ustawiana na wybranym biegu alarmowym. Przy czym NIE jest realizowana
-- funkcja wyrównania temperatury
--
-- ======================
-- Parameters
-- ======================
--
-- SubLogic supports following variables:
--
-- input.override - sygnał tymczasowego obejścia wentylacji [0 - brak sygnału; różne od 0 - jest sygnał]
--
-- input.alert - sygnał alarmowy. Podczas alarmu wentylacja przechodzi na bieg alarmowy [0 - brak sygnału; różne od 0 - jest sygnał]
--
-- output.fan.supply - wentylator nawiewny [0..100]
--
-- output.fan.exhaust - wentylator wywiewny [0..100]
--
-- setting.fan.level.demand - aktualnie wymagany bieg wentylacji
--
-- setting.fan.level.delta.enabled - czy ma być realizowana funkcja wyrównania temperatury [0..1]
--
-- setting.fan.level.supply - lista wartości wentylatora nawiewnego na danym biegu [0..100]
--
-- setting.fan.level.exhaust - lista wartości wentylatora wywiewnego na danym biegu [0..100]
--
-- setting.fan.level.delta.supply - lista wartości delta wentylatora nawiewnego dla wyrównania temperatury na danym biegu [0..100]
--
-- setting.fan.level.delta.exhaust - lista wartości delta wentylatora wywiewnego dla wyrównania temperatury na danym biegu [0..100]
--
-- setting.fan.level.enabled - lista flag informujących o tym czy dany bieg jest możliwy do załączenia. Jeżeli wybrany bieg nie jest
-- możliwy do załączenia to wybierany jest następny (w/g kolejności alfabetycznej).
-- Ostatni bieg zapętla wybór do pierwszego. Jeżeli wszystkie biegi są zablokowane na wyjściu
-- podawana jest wartość 0.
--
-- setting.override.fan.level - poziom wentylacji w trybie override
--
-- setting.alert.fan.level - poziom wentylacji w trybie alarmowym
--
-- counter.fan.levels.count - ilość biegów wentylacji
--
-- 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-12-07 ver 0.2.2
-- + obsługa trybu alarmowego
-- + możliwość aktywowania dodatku wydajności wentylacji o zadaną deltę dla każdego biegu
--
-- 2019-03-13 ver 0.1.1
-- + możliwość deaktywowania biegu
--
-- 2017-11-13 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");
require("Functions");
g_outputFanSupply = nil;
g_outputFanExhaust = nil;
SUPPORTED_SUBLOGIC_TYPE = "Recu02";
SUPPORTED_SUBLOGIC_VERSION = "0.2.2";
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 inputOverride = getLogicValue("input.override");
local inputAlert = getLogicValue("input.alert");
local settingFanLevelDemand = getLogicValue("setting.fan.level.demand");
local settingFanLevelDeltaEnabled = getLogicValue("setting.fan.level.delta.enabled");
local settingFanLevelSupplyList = getVarList("setting.fan.level.supply");
local settingFanLevelExhaustList = getVarList("setting.fan.level.exhaust");
local settingFanLevelDeltaSupplyList = getVarList("setting.fan.level.delta.supply");
local settingFanLevelDeltaExhaustList = getVarList("setting.fan.level.delta.exhaust");
local settingFanLevelEnabledList = getVarList("setting.fan.level.enabled");
local settingOverrideFanLevel = getLogicValue("setting.override.fan.level");
local settingAlertFanLevel = getLogicValue("setting.alert.fan.level");
local counterFanLevelsCount = 0;
local FanLevelSupplyList = {};
local FanLevelExhaustList = {};
local FanLevelDeltaSupplyList = {};
local FanLevelDeltaExhaustList = {};
local FanLevelEnabledList = {};
-- states
if g_outputFanSupply == nil or firstCall then
g_outputFanSupply = State.create(0, 0, 100, true);
end
g_outputFanSupply:call();
if g_outputFanExhaust == nil or firstCall then
g_outputFanExhaust = State.create(0, 0, 100, true);
end
g_outputFanExhaust:call();
-- tablica wartości wentylacji na podstawie ustawień
if settingFanLevelSupplyList ~= nil then
for var, value in pairs(settingFanLevelSupplyList) do
FanLevelSupplyList[var] = value;
counterFanLevelsCount = counterFanLevelsCount + 1;
end
end
if settingFanLevelExhaustList ~= nil then
for var, value in pairs(settingFanLevelExhaustList) do
FanLevelExhaustList[var] = value;
end
end
if settingFanLevelDeltaSupplyList ~= nil then
for var, value in pairs(settingFanLevelDeltaSupplyList) do
FanLevelDeltaSupplyList[var] = value;
end
end
if settingFanLevelDeltaExhaustList ~= nil then
for var, value in pairs(settingFanLevelDeltaExhaustList) do
FanLevelDeltaExhaustList[var] = value;
end
end
if settingFanLevelEnabledList ~= nil then
for var, value in pairs(settingFanLevelEnabledList) do
FanLevelEnabledList[var] = value;
end
end
-- zabezpieczenie przed zbyt wysokimi biegami nastaw
if (settingFanLevelDemand >= counterFanLevelsCount) then
settingFanLevelDemand = counterFanLevelsCount - 1;
setLogicValue("setting.fan.level.demand", settingFanLevelDemand);
end
if (settingOverrideFanLevel >= counterFanLevelsCount) then
settingOverrideFanLevel = counterFanLevelsCount - 1;
setLogicValue("setting.override.fan.level", settingOverrideFanLevel);
end
local outputFanSupply = 0;
local outputFanExhaust = 0;
local counterFanSupplyDelta = 0;
local counterFanExhaustDelta = 0;
local fail = 1;
local tmp_next = 0;
-- tryb alert
if (inputAlert ~= 0) then
g_outputFanSupply:setValue(FanLevelSupplyList['' .. settingAlertFanLevel]);
g_outputFanExhaust:setValue(FanLevelExhaustList['' .. settingAlertFanLevel]);
end
-- tryb override
if (inputOverride ~= 0) then
if (settingFanLevelDeltaEnabled ~=0) then
outputFanSupply = FanLevelSupplyList['' .. settingOverrideFanLevel] + FanLevelDeltaSupplyList['' .. settingOverrideFanLevel];
outputFanExhaust = FanLevelExhaustList['' .. settingOverrideFanLevel] + FanLevelDeltaExhaustList['' .. settingOverrideFanLevel];
if outputFanSupply > 100 then
outputFanSupply = 100
end
if outputFanExhaust > 100 then
outputFanExhaust = 100
end
g_outputFanSupply:setValue(outputFanSupply);
g_outputFanExhaust:setValue(outputFanExhaust);
else
g_outputFanSupply:setValue(FanLevelSupplyList['' .. settingOverrideFanLevel]);
g_outputFanExhaust:setValue(FanLevelExhaustList['' .. settingOverrideFanLevel]);
end;
end
if (FanLevelEnabledList['' .. settingFanLevelDemand] == 1) then
outputFanSupply = FanLevelSupplyList['' .. settingFanLevelDemand];
outputFanExhaust = FanLevelExhaustList['' .. settingFanLevelDemand];
counterFanSupplyDelta = FanLevelDeltaSupplyList['' .. settingFanLevelDemand];
counterFanExhaustDelta = FanLevelDeltaExhaustList['' .. settingFanLevelDemand];
else
-- szukaj następnej możliwej wartości do przyjęcia
for k, v in pairsByKeys(FanLevelExhaustList) do
if (tmp_next == 1) then
if (FanLevelEnabledList['' .. k] == 1) and (fail == 1) then
fail = 0;
outputFanSupply = FanLevelSupplyList['' .. k];
outputFanExhaust = FanLevelExhaustList['' .. k];
counterFanSupplyDelta = FanLevelDeltaSupplyList['' .. k];
counterFanExhaustDelta = FanLevelDeltaExhaustList['' .. k];
end
end
if (k == ('' .. settingFanLevelDemand)) then
tmp_next = 1;
end
end
-- nie znaleziono żadnej następnej możliwej wartości do przyjęcia
-- szukaj na początku tablicy
if (fail == 1) then
for k, v in pairsByKeys(FanLevelExhaustList) do
if (FanLevelEnabledList['' .. k] == 1) and (fail == 1) then
fail = 0;
outputFanSupply = FanLevelSupplyList['' .. k];
outputFanExhaust = FanLevelExhaustList['' .. k];
counterFanSupplyDelta = FanLevelDeltaSupplyList['' .. k];
counterFanExhaustDelta = FanLevelDeltaExhaustList['' .. k];
end
end
end
end
if (settingFanLevelDeltaEnabled ~=0) then
outputFanSupply = outputFanSupply + counterFanSupplyDelta;
outputFanExhaust = outputFanExhaust + counterFanExhaustDelta;
end
if outputFanSupply > 100 then
outputFanSupply = 100
end
if outputFanExhaust > 100 then
outputFanExhaust = 100
end
-- sterowanie normalną pracą wentylacji
g_outputFanSupply:setValue(outputFanSupply);
g_outputFanExhaust:setValue(outputFanExhaust);
-- send logic variables to ibmanager
setLogicValue("output.fan.supply", g_outputFanSupply:getValue());
setLogicValue("output.fan.exhaust", g_outputFanExhaust:getValue());
setLogicValue("counter.fan.levels.count", counterFanLevelsCount);
end