--[[
%% properties
147 value
%% globals
PresentState
KWLBoost
--]]
-- KWL Control KWL = (Kontrollierte Wohnraumlüftung)
-- Version 1.1 by Lodi: mit zwei CO2 Sensoren und zeitlimitierter boost Funktion
-- My first LUA script, so pls apologize amateurish scripting and theft of logic array from other scenes (e.g. perfekte Lichtsteuerung, RFID Alarm....from www.siio.com)
-- Event getriggerte version reagiert auf Netatmo CO2 sensoren und "PresentState" und "KWLBoost" variable
-- RGBW Controller mit 4 Stufen: 'weiss' = niedrigste Steuerspannung und 'rot' = höchste Steuerspannung
-- Globale Variable "KWLBoost" ermöglicht manuelles Schalten auf die höchste Stufe (z.B. beim Duschen oder Kochen) unabhängig vom CO2 Wert
-- Variable kann z.B. über virtuelles Device geschaltet werden ("KWLBoost" Variable hat Werte 'Boost' und 'Off')
-- Zur Schonung der Anlage läuft der Boost Modus immer nur für eine bestimmte Zeit (boostInterval) und schaltet dann auf die nächtst tiefere Stufe.
-- Diese Stufe wird eine Weile beibehalten (boostBreak) bevor wieder neu getriggert werden kann und ein erneuter CO2 check durchlaufen wird
-- bei Abwesenheit läuft die KWL unterhalb des Mittelwertes (CO2levels) auf niedrigster Stufe
-- um Doppelte Steuersignale zu vermeiden wird bei jeder Schaltung zunächst der RGBW Controller für 1 Sekunde auf 0,0,0,0 gesetzt (nicht sicher ob das nötig ist)
--initiate Variables
local sourceTrigger = fibaro:getSourceTrigger();
local debugging = true -- quite eccessive debugging toggle off if desired (true= on / false=off)
local CO2SensorID = {147,156} --Netatmo CO2 sensors as array. Needs to be two. Guess it should also work if you enter two times the same ID (not checked)
local KWLControlID = 225 --ID of the RGBW Controller
local VDcolorPlug = 231 --Virtual device for wall plug used as indicator LED
--local runInterval = 60 --Time period in minutes to run the CO2 check. NOT USED ANYMORE as the scene is no longer triggered by a scheduler
local boostInterval = 30 --Time the KWL will run in boost mode before switching down to the next lower volume level (3).
local boostBreak = 15 --Minimum time period for which boosting mode will forced to pause. Preserve the KWL from running ages on highest level
local CO2levels = {500,700,1600} --insert your 3 desired CO2 level cornerpoints (e.g. here for ranges 0-500 / 501-800 / 801-1600 / >1600)#
--Global variables that are needed. Script does not create them. So make sure they are in place.
local timeOfDay = fibaro:getGlobal("TimeOfDay"); --Time of Day Global variable.
local presentState = fibaro:getGlobal("PresentState"); --Present state Global variable.
local kwlBoost = fibaro:getGlobal("KWLBoost"); --manual boost Global variable (KWLBoost). Needs to be created with values "Boost" and "Off".
local CO2Sensor1Val = tonumber(fibaro:getValue((CO2SensorID[1]), "value"))
local CO2Sensor2Val = tonumber(fibaro:getValue((CO2SensorID[2]), "value"))
local Netatmo1room = fibaro:getRoomNameByDeviceID(CO2SensorID[1])
local Netatmo2room = fibaro:getRoomNameByDeviceID(CO2SensorID[2])
local highCO2ID = (CO2SensorID[1]) --Initiate variable. In my case ID '147' is located inside the most sensitive room.
local lowCO2ID = (CO2SensorID[2]) --Initiate variable.
--Not in use
--kwlBoostMapping = {Boost="Boost", Off="Off"};
--presentStateMapping = {Home="Home", Away="Away", Holiday="Holiday"};
--timeOfDayMapping = {Morning="Morning", Day="Day", Evening="Evening", Night="Night"};
--Color debugging
function ExtraDebug( color, message )
if (debugging) then
fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span"));
end
end
--Ensuring that only 1 instance is running at a time.
fibaro:sleep(50); --sleep to prevent all instances being killed.
if (fibaro:countScenes() > 1)
then
ExtraDebug( "grey", "Abort, Scene count = " .. fibaro:countScenes());
fibaro:abort();
end
----------------------------------------------------------------
--------------------checkHighCO2ID----------------------------
-- function to test which CO2 sensor has current highest level--
----------------------------------------------------------------
function checkHighCO2ID()
if tonumber(fibaro:getValue((CO2SensorID[1]), "value")) >= tonumber(fibaro:getValue((CO2SensorID[2]), "value"))
then
highCO2ID = tonumber(CO2SensorID[1])
lowCO2ID = tonumber(CO2SensorID[2])
local highCO2room = fibaro:getRoomNameByDeviceID(highCO2ID)
local lowCO2room = fibaro:getRoomNameByDeviceID(lowCO2ID)
ExtraDebug('magenta', "Reference sensor with higher CO2 level has ID "..highCO2ID.." ("..highCO2room.." @ "..fibaro:getValue(highCO2ID, "value").."ppm).");
-- ExtraDebug('magenta', "HighCO2ID value is:("..fibaro:getValue(highCO2ID, "value").."ppm) and LowCO2ID value is:("..fibaro:getValue(lowCO2ID, "value").."ppm).");
elseif tonumber(fibaro:getValue((CO2SensorID[2]), "value")) >= tonumber(fibaro:getValue((CO2SensorID[1]), "value")) then
highCO2ID = tonumber(CO2SensorID[2])
lowCO2ID = tonumber(CO2SensorID[1])
local highCO2room = fibaro:getRoomNameByDeviceID(highCO2ID)
local lowCO2room = fibaro:getRoomNameByDeviceID(lowCO2ID)
ExtraDebug('darkkhaki', "Reference sensor with higher CO2 level has ID "..highCO2ID.." ("..highCO2room.." @ "..fibaro:getValue(highCO2ID, "value").."ppm).");
-- ExtraDebug('darkkhaki', "HighCO2ID value is:("..fibaro:getValue(highCO2ID, "value").."ppm) and LowCO2ID value is:("..fibaro:getValue(lowCO2ID, "value").."ppm).");
else
highCO2ID = tonumber(CO2SensorID[1])--in case one or both of the Netatmos return no value (not sure if this will work)
lowCO2ID = tonumber(CO2SensorID[2])
local highCO2room = fibaro:getRoomNameByDeviceID(highCO2ID)
local lowCO2room = fibaro:getRoomNameByDeviceID(lowCO2ID)
ExtraDebug('orange', "COULD NOT GET BOTH CO2 VALUES. CHECK STATUS OF NETATMO DEVICES");
end
end
------------------------------------------------------------
--------------------boostFunc-------------------------------
--------Boost function (KWL runs at highest level)----------
------------------------------------------------------------
function boostFunc()
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
ExtraDebug('red', "-------BOOSTING for "..boostInterval.."mins.-------");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "255","0","0","0");
fibaro:call(VDcolorPlug, "pressButton", "3");
ExtraDebug('red', "CO2 levels are "..Netatmo2room.." ("..CO2Sensor2Val.." ppm) and "..Netatmo1room.." ("..CO2Sensor1Val.." ppm)");
fibaro:sleep(boostInterval*60000); --after boost interval switch back to level 3 and pause boosting for at least half the boosting time
fibaro:setGlobal('KWLBoost', 'Off'); --switch Global Variable back to "Off" if Boost mode was initiated manually by changing the variable to "Boost"
ExtraDebug('green', "-------BOOSTING OFF-----");
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "0","255","0","0");
fibaro:call(VDcolorPlug, "pressButton", "4");
ExtraDebug('green', "CO2 levels are "..Netatmo2room.." ("..CO2Sensor2Val.." ppm) and "..Netatmo1room.." ("..CO2Sensor1Val.." ppm)");
ExtraDebug('green', "Switched KWL after ".. boostInterval.."mins back to volume 3 (".. boostBreak.."mins)");
fibaro:sleep(boostBreak*60000); --boost break to give the KWL fan a minimum rest (e.g. 15mins)
ExtraDebug('yellow', "-------Boost sequence over, checking CO2 levels-----");
end
--------------------------EXECUTION----------------------------------
--------------Schleife wenn trigger ('for' Schleife geplant)---------
if (sourceTrigger["type"] == "property")
then
startSourceID = tonumber(sourceTrigger['deviceID']);
ExtraDebug('yellow', "Scene triggered by: " .. startSourceID .. "");
elseif ( sourceTrigger["type"] == "global" )
then
startSourceGlob = (sourceTrigger['name']);
ExtraDebug('yellow', "Scene triggered by: " .. startSourceGlob .. " global variable");
else
ExtraDebug('yellow', "Scene was started manually.")
end
checkHighCO2ID()
local highCO2Val = tonumber(fibaro:getValue(highCO2ID, "value"))
local lowCO2Val = tonumber(fibaro:getValue(lowCO2ID, "value"))
ExtraDebug('pink', "High CO2 Value: "..highCO2Val.."ppm. Low CO2 Value: "..lowCO2Val.."ppm");
if (presentState ~= "Home" ) and (highCO2Val <= (CO2levels[2]))
then
if (fibaro:getValue(KWLControlID, "color") ~= "0,0,0,255")
then
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "0","0","0","255");
fibaro:call(VDcolorPlug, "pressButton", "2");
ExtraDebug('white', "Home status = " .. presentState .. ". @ "..highCO2Val.."ppm. Switching KWL to lowest volume");
else
ExtraDebug('white', "Home status = " .. presentState .. " and KWL runs on low level. No further action required");
end
elseif (kwlBoost == "Boost" )
then
boostFunc()
elseif CO2Sensor1Val == nil or CO2Sensor2Val == nil
then
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "0","0","255","0");
fibaro:call(VDcolorPlug, "pressButton", "5");
ExtraDebug('orange', "PROBLEMS WITH CO2 READINGS, PLEASE CHECK NETATMO DEVICES. Set KWL to volume 2");
ExtraDebug('blue', "---Set KWL to volume 2---");
elseif (highCO2Val <= (CO2levels[1])) and fibaro:getValue(KWLControlID, "color") ~= "0,0,0,255"
then
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "0","0","0","255");
fibaro:call(VDcolorPlug, "pressButton", "2");
ExtraDebug('white', "---Set KWL to volume 1---");
elseif (highCO2Val >= (CO2levels[1])+1) and (highCO2Val <= (CO2levels[2])) and fibaro:getValue(KWLControlID, "color") ~= "0,0,255,0"
then
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "0","0","255","0");
fibaro:call(VDcolorPlug, "pressButton", "5");
ExtraDebug('blue', "---Set KWL to volume 2---");
elseif (highCO2Val >= (CO2levels[2])+1) and (highCO2Val <= (CO2levels[3])) and fibaro:getValue(KWLControlID, "color") ~= "0,255,0,0"
then
fibaro:call(KWLControlID, "setColor", "0","0","0","0");
fibaro:sleep(1000);
fibaro:call(KWLControlID, "setColor", "0","255","0","0");
fibaro:call(VDcolorPlug, "pressButton", "4");
ExtraDebug('green', "---Set KWL to volume 3---");
elseif (highCO2Val >= (CO2levels[3])+1) and fibaro:getValue(KWLControlID, "color") ~= "255,0,0,0"
then
boostFunc()
elseif (fibaro:getValue(KWLControlID, "color") == "0,0,0,0" )
then
fibaro:call(KWLControlID, "setColor", "0","0","0","255");
fibaro:call(VDcolorPlug, "pressButton", "2");
ExtraDebug('white', "!!RGBW Controller was off. Switching KWL to volume 1!!");
end