Aller au contenu
OJC

Heating Manager

Recommended Posts

Oui, juste ça.  Pas besoin de mettre localP et local si tu utilise les valeurs par défaut. Pour fixer ces valeurs par défaut, c'est dans le VD Controller que ça se passe.

Partager ce message


Lien à poster
Partager sur d’autres sites

Ps : j'ai omis de préciser que les coefficients sont désormais à multiplier par 100 : donc la ou tu avais 0.6 tu mets 60 et 1 pour 0.01

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 46 minutes, OJC a dit :

sont désormais à multiplier par 100

hihi ca sent la modif du 1er post ;-)

Partager ce message


Lien à poster
Partager sur d’autres sites

Non il est ok mais j'ai pas pensé à faire un tuto mise à jour. My bad.

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Publication de la v. 3.0 avec de grosses modifications sur le fonctionnement et la configuration.

 

Heating Manager peut toujours fonctionner sur un mode classique de planification, mais il est désormais pensé pour fonctionner sur un mode événementiel, sans aucune planification mais uniquement en fonction de l'état de la maison, avec un nouveau VD Thermostat pour contrôler manuellement le chauffage dans chaque pièce.

 

Désolé pour le code que je n'ai pas mis en spoiler puisqu'il n'y a manifestement plus de spoiler, et que ce serait trop long directement dans le post.

Partager ce message


Lien à poster
Partager sur d’autres sites

@OJC, du gros gros boulot :-)

Felicutations pour les thermostats VIRTUELS, ton Heating MANAGER devient tres tres complet. Merci beaucoup.
Je n ai pas vu s il etait possible de tout mettre à OFF ou mettre à OFF une seule pièce.

Et un grand merci pour le tuto très complet.

Envoyé de mon Nexus 5X en utilisant Tapatalk

Partager ce message


Lien à poster
Partager sur d’autres sites

@pepite Merci :)

 

Pour l'arrêt total du chauffage ou dans une pièce seulement, c'est un événement à paramétrer (via une variable globale alimentée par GEA par exemple, ou un VD par exemple) en mettant une consigne à 0 °C ou 8 °C (hors-gel). Un arrêt total hors période de chauffe, qui revient à arrêter la scène, n'est pas géré en interne, il faut le faire manuellement ou via GEA par exemple. Perso je n'ai jamais coupé totalement mon script de chauffage (époque openHAB), l'évolution de la température à l'intérieur de la maison se suffisant à elle-même pour ne pas déclencher la chauffe.

 

Au fait, elle est à jour ta signature ?? :huh:

Partager ce message


Lien à poster
Partager sur d’autres sites

@OJC : Ok pour l'arret, c'est effectivement facilement faisable comme tu l'indiques. mais pourquoi pas l'implémenter, tu as déja fait tellement sur ton Heating Manager ;-)

 

Juste une remarque sur le "popupWarnErrLog" n'est pas adapté pour les WARNING qui pourraient être importants du fait du fonctionnement des Popups.

 

En fait les Popups n'apparaissent que lorsque l’application est ouverte, ce qui enlève de l'interet à l'usage des popups. Peut-etre qe pour avoir 2 types de notification, le plus judicieux serait de couplet PUSH + SMS plutôt que PUSH +POPUP.

Ce n'est évidemment qu'une suggestion, étant incapable d'écrire ce genre de code comme tu le fais ;-)

 

Ma signature ? A quel sujet ?

Partager ce message


Lien à poster
Partager sur d’autres sites

@pepite Au départ, je n'avais mis que le popup ne sachant qu'il était possible de faire un push. Puis j'ai vu comment faire, donc je l'ai ajouté, sans supprimer l'autre partie puisqu'elle existait.

 

Sachant qu'en pratique, vu que le programme contrôle de manière très approfondie la configuration au démarrage, ce n'est que pendant la phase de configuration que ça présente un intérêt. En pratique, en régime de croisière, il n'est pas censé y avoir d'erreurs ou de warning (sauf si on s'amuse à supprimer des pièces ou des modules avec la scène en train de tourner).

 

Pour le SMS, cela implique d'avoir une passerelle que je n'ai pas, je ne peux donc pas tester. J'avais hésité à intégrer le support pour le Notification Center de Krikroff, mais il n'a plus l'air maintenu ?

 

Pour l'arrêt, ça m'embête qd même un peu de laisser la scène se "suicider" puisque, dans ce cas, si les conditions d'arrêt de la chauffe ne sont pas réunies, elle ne pourra pas redémarrer toute seule. Du coup, je vois pas bien comment faire pour que ce soit pertinent.

 

Pour ta signature, c'est par rapport à l'équipement domotique qui a l'air inversement proportionnel à l'intérêt que tu portes à la question :)

Modifié par OJC
Correction des fautes d'orthographe, je suis fatigué :)

Partager ce message


Lien à poster
Partager sur d’autres sites

Bon, voilà... Roadmap remplie :)

 

J'ai donc ajouté le paramètre persistent qui permet de faire en sorte que le programme continue de considérer qu'un événement est réalisé alors que ses conditions ne sont plus remplies, et de faire comme s'il n'avait jamais cessé d'être réalisé si les conditions sont de nouveau remplies dans le délai défini.

 

Concrètement, j'ai configuré mon chauffage pour que la température passe à 18 °C quand la variable SleepState est à true (variable qui se met toute seule à cette valeur en fonction de diverses conditions) et qu'aucun mouvement n'est détecté depuis 30 minutes. Comme la température baisse graduellement pendant une heure, pour éviter que la chauffe ne redémarre alors que le mouvement était juste mon fils qui va aux toilettes (plié en trois minutes), j'ai défini un délai de persistance à 5 minutes : comme ça, sauf à ce que le mouvement dure plus longtemps, le chauffage ne redémarre pas et reste à 18 °C.

 

J'ai aussi ajouté la possibilité de viser plusieurs pièces dans la fonction self:addEvent, et ajouté la fonction self:addGlobalEvent qui, comme son intitulé le suggère, permet de définir un événement s'appliquant à toutes les pièces.

 

Enfin, les conditions de réalisation des événements ne se limitent plus à vérifier si telle variable ou propriété est égale à telle valeur, mais accepte désormais tous les opérateurs de comparaison disponibles (==, ~=, >=, <=, > et <).

 

Je crois que je suis bon pour le chauffage :) maintenant, je vais m'attaquer à mes éclairages ^^

Modifié par OJC
  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

La beta 4.151 corrige le probleme des panneaux de chauffage pour info.

  • Upvote 1

Partager ce message


Lien à poster
Partager sur d’autres sites

OJC,

j'ai voulu rajouter 4 radiateurs supplémentaires soit 8 au total et j'ai ce message d'erreur avec le heating manager 1.3:

 

[DEBUG] 15:16:01: [INFO] Checking notre chambre...
[DEBUG] 15:16:01: line 154: bad argument #1 to 'match' (string expected, got nil)

Partager ce message


Lien à poster
Partager sur d’autres sites

la voici:

--[[
%% autostart
%% properties
1078 ui.lbldressing.value
1078 ui.lblsalle.value
1078 ui.lblbureau.value
1078 ui.lblsalledebains.value
1078 ui.lblchambre.value
1078 ui.lblenfant.value
1078 ui.lblclara.value
1078 ui.lblmatheo.value

%% globals
--]]

--[[
    Heating Manager v. 1.3.0 (2017) by OJC

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
--]]

--[[
    Versions Notes

    1.3.0   Add the possibility of using virtual device as heater controller
            Add the possibilité of using virtual device or global variable as setpoint provider
    1.2.0   New regulation code, inspired by eedomus box
            Add the possibility of using virtual temperature sondes
            Configuration simplification for both Manager and Panel
    1.1.0   Add motion sensor management
            Improve door/window sensor management
            Code Optimization
    1.0.0   Initial release
--]]


----------------------------------------------------------------------------------
--                                 GENERIC CODE                                 --
----------------------------------------------------------------------------------

logColor = {"YellowGreen", "SkyBlue", "NavajoWhite", "Tomato"}

lib = {}
  function lib:iif(a,b,c) if (a) then return b else return c end end
  function lib:log(m,l) if ((l or 1) >= logLevel) then print('<span style="color:' .. logColor[l or 1] .. ';">' .. m .. '</span>') end end

f = {"Ç","ç","[-èéêë']+","[-ÈÉÊË']+","[-àáâãäå']+","[-@ÀÁÂÃÄÅ']+","[-ìíîï']+","[-ÌÍÎÏ']+","[-ðòóôõö']+","[-ÒÓÔÕÖ']+","[-ùúûü']+","[-ÙÚÛÜ']+","[-ýÿ']+","Ý","%W"}
r = {"C","c","e","E","a","A","i","I","o","O","u","U","y","Y",""}

format = {}
  function format:ddigit(n) if (n < 10) then return "0"..n else return n end end
  function format:replace(s) local s = s for i, j in ipairs(f) do s = string.gsub(s, j, r) end return s end

function getDeviceIDbyName(name)
  local devices = api.get("/devices?name=" .. name)
  if (devices[1] ~= nil) then return devices[1].id end
end

function getInstanceAuthorization(max)
  local t = os.time()
  local max = tonumber(max) or 1
  while (fibaro:countScenes() > max) do
    fibaro:sleep(500)
    if (os.time() - t) > 30 then return false end
  end
  return true
end

--DEPENDENCIES = lib:log; getDeviceIDbyName
function getPanelID()
  local p = panel
  local v = fibaro:getGlobalValue(p.global)
  if (fibaro:getValue(v, p.label) == nil) then
    local ID = getDeviceIDbyName(p.name)
    if (ID ~= nil) then
      fibaro:setGlobal(p.global, ID)
      return ID
    else
      lib:log("[CRITICAL ERROR] " .. p.name .. " was not found !", 4)
      fibaro:abort()
    end
  else return v end
end

--DEPENDENCIES = format:ddgit
function getReadableTime(t)
  local d = ""
  local h = math.floor(t/3600)
  local m = math.floor(t/60 - (h * 60))
  local s = math.floor(t - h * 3600 - m * 60)
  if (h > 0) then d = d .. format:ddigit(h) .. " h " end
  if (m > 0) then d = d .. lib:iif(h ~= 0, format:ddigit(m), m) .. " m " end
  if (s > 0) then d = d .. lib:iif(m ~= 0, format:ddigit(s), s) .. " s" end
  return d
end

function getTemperatureSonde(ID)
  local r = api.get("/rooms?id=" .. ID)
  return r.defaultSensors.temperature
end

function setGlobalVariables(...)
  for _, v in ipairs{...} do
    if (fibaro:getGlobalValue(v) == nil) then api.post("/globalVariables", {name = v, isEnum = 0}) end
  end
end


----------------------------------------------------------------------------------
--                                 SPECIFIC CODE                                --
----------------------------------------------------------------------------------

collection = {}

HeatingManager = {}

--DEPENDENCIES = GetTemperatureSonde; format:replace
function HeatingManager:addHeater(idHeater, idSonde, localP, localT)
  local heater, on, off
  if type(idHeater) == "table" then
    heater, on, off = idHeater[1], idHeater[2], idHeater[3]
  else heater, on, off = idHeater, 0, 0
  end
  table.insert(collection, {
      heater = heater,
      OnOff = lib:iif(on ~= 0, {on, off}, 0),
      sonde = idSonde or getTemperatureSonde(fibaro:getRoomID(heater)),
      kP = localP or default.kP,
      kT = localT or default.kT,
      panel = "lbl" .. format:replace(fibaro:getRoomNameByDeviceID(heater))
    })
end

--DEPENDENCIES = getPanelID
function HeatingManager:getTemperatures(item)
  local c, s, e = 0, 0, 0
  if (type(item.sonde) == "number") then
      c = fibaro:getValue(item.sonde, "value")
  elseif (type(item.sonde) == "table") then
    c = string.match(fibaro:getValue(item.sonde[1], "ui." .. item.sonde[2] .. ".value"), "[0-9]+[,.][0-9]+") or string.match(fibaro:getValue(item.sonde[1], "ui." .. item.sonde[2] .. ".value"), "[0-9]+")    
  end
  s = string.match(fibaro:getValue(getPanelID(), "ui." .. item.panel .. ".value"), "[0-]+9[,.][0-9]+") or string.match(fibaro:getValue(getPanelID(), "ui." .. item.panel .. ".value"), "[0-9]+")
  if (outdoorSonde == nil) then
    o = api.get("/weather").Temperature
  elseif (type(outdoorSonde) == "number") then
      o = fibaro:getValue(outdoorSonde, "value")
  elseif (type(outdoorSonde) == "table") then
    o = string.match(fibaro:getValue(outdoorSonde[1], "ui." .. outdoorSonde[2] .. ".value"), "[0-9]+[,.][0-9]+") or string.match(fibaro:getValue(outdoorSonde[1], "ui." .. outdoorSonde[2] .. ".value"), "[0-9]+")
  end
  return c, s, o or s
end

function HeatingManager:setOutdoorSonde(idSonde)
  outdoorSonde = idSonde
end

----------------------------------------------------------------------------------
--                                  MAIN CODE                                   --
----------------------------------------------------------------------------------

--DEPENDENCIES = lib:log; getReadableTime ;
--               HeatingManager:getTemperatures
function SceneRun()
  
  local collection = collection
  
  for _, item in ipairs(collection) do
    
    local current, setpoint, C, T, P = 0, 0, 0, 0, 0

    lib:log("[INFO] Checking " .. fibaro:getRoomNameByDeviceID(item.heater) .. "...")
    current, setpoint, outdoor = HeatingManager:getTemperatures(item)  
    if (current == nil) then
      lib:log("[ERROR] " .. fibaro:getRoomNameByDeviceID(item.heater) .. " have no Temperature Sonde !",4)
      fibaro:call(item.heater, "turnOff")
      break
    end
    
    lib:log("[INFO] Current = " .. current .. " °C - Setpoint = " .. setpoint .." °C - Outdoor = " .. outdoor .. " °C")
    
    P = math.min((item.kP * (setpoint - current)) + (item.kT * (setpoint - outdoor)),1)

    if (P > 0) then
      lib:log("[ACTION] Start heating in " .. fibaro:getRoomNameByDeviceID(item.heater) .. " for " .. getReadableTime(P * heatingCycle * 60), 2)
      if type(item.OnOff) == "number" then
        fibaro:call(item.heater, "turnOn")
        if (P < 1) then setTimeout(function() fibaro:call(item.heater, "turnOff") end, P * heatingCycle * 60 * 1000) end
      else
        fibaro:call(item.heater, "pressButton", item.OnOff[1])
        if (P < 1) then setTimeout(function() fibaro:call(item.heater, "pressButton", item.OnOff[2]) end, P * heatingCycle * 60 * 1000) end
      end
    else
      lib:log("[INFO] Heating is not required in ".. fibaro:getRoomNameByDeviceID(item.heater))
      if type(item.OnOff) == "number" then
        fibaro:call(item.heater, "turnOff")
      else
        fibaro:call(item.heater, "pressButton", item.OnOff[2])
      end
    end

  end
  
  setTimeout(SceneRun, heatingCycle * 60 * 1000)
  
end


----------------------------------------------------------------------------------
--                                CONFIGURATION                                 --
----------------------------------------------------------------------------------

-- 1. Default Parameters

default = {}
  default.kP = 3.1
  default.kT = 0.02

-- For more information, see https://doc.eedomus.com/view/Algorithme_Chauffage

-- 2. General Parameters

heatingCycle = 10
logLevel = 1

-- 3. Collection Definition

--[[
    HeatingManager:addHeater(idHeater, [idSonde], [localP], [localT])

      + idHeater = ID of heater control device or {ID of heater virtuel device, order number of the ON button, order number of the OFF button}
      + idSonde  = ID of temperature sonde or {ID of temperature virtual device, ID of temperature label} - Optional : if not set, room temperature sonde is used
      + localP   = Optional : if not set, default.kP is used
      + localT   = Optional : if not set, default.kT is used

--]]

HeatingManager:addHeater({437, 1, 2}, 1053, localP, localT)
HeatingManager:addHeater({511, 1, 2}, 453, 0.6, 0.01)
HeatingManager:addHeater({438, 1, 2}, 1059, 2.6, localT)
HeatingManager:addHeater({439, 1, 2}, 415, 1.2, 0.01)
HeatingManager:addHeater({1076, 1, 2}, 1073, localP, localT)
HeatingManager:addHeater({943, 1, 2}, 1070, 0.6, 0.01)
HeatingManager:addHeater({1075, 1, 2}, 457, 2.6, localT)
HeatingManager:addHeater({1077, 1, 2}, 450, 1.2, 0.01)


--HeatingManager:setOutdoorSonde(ID Device or {ID VirtualDevice, ID Label})
--idSonde = ID Device or {ID VirtualDevice, ID Label} - Optional : If not set, weather plugin is used

HeatingManager:setOutdoorSonde(1045)


-------------------------------------------------------------------------
--                            START CODE                               --
-------------------------------------------------------------------------

--DEPENDENCIES = lib:log; getInstanceAuthorization;
--               HeatingManager:checkGlobalVariables;
--               SceneRun

trigger = fibaro:getSourceTrigger()

if not (getInstanceAuthorization(lib:iif(trigger.type == "property", 9, 1))) then
  lib.log("[CRITICAL ERROR] Too many instances are running !", 4)
  fibaro:abort()
end
  
panel = {name   = "Heating Panel",
         label  = "ui.lblHeatingPanel.value",
         global  = "HeatingPanelID"}

setGlobalVariables("HeatingPanelID")

if (trigger.type == "property") then

  for _, item in ipairs(collection) do
    if item.panel == string.match(trigger.propertyName,"ui.(%a+).value") then
      local current = 0
      local setPoint = 0
      current, setPoint = HeatingManager:getTemperatures(item)  
      if (current == nil) then
        lib:log("[ERROR] " .. fibaro:getRoomNameByDeviceID(item.heater) .. " have no Temperature Sonde !",4)
        fibaro:call(item.heater, "turnOff")
        fibaro:abort()
      end
      if (current < setPoint) then
        lib.log("[OVERRIDE] Start heating in " .. fibaro:getRoomNameByDeviceID(item.heater), 4)
        fibaro:call(item.heater,"turnOn")
      elseif (current >= setPoint) then
        lib.log("[OVERRIDE] Heating is not required in " .. fibaro:getRoomNameByDeviceID(item.heater), 4)
        fibaro:call(item.heater,"turnOff")
      end
    end
  end
      
else
        
  lib:log("Heating Manager v. 1.3.0 (2017) by OJC", 3)
  SceneRun()
  
end


et avec le panneau le déboguer est OK par contre message erreur avec la scène sur le rajout à partir de chambre:(

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Ta pièce semble s'appeler «notre chambre» or je ne vois pas de label «ui.lblnotrechambre.value» dans les triggers

Partager ce message


Lien à poster
Partager sur d’autres sites

Tu es sur du nom de ton label dans le VD ?

Partager ce message


Lien à poster
Partager sur d’autres sites

entre temps temps j'ai rectifier et mis tous avec le label chambre ainsi que le nom de la pièce 

Partager ce message


Lien à poster
Partager sur d’autres sites

dans le VD les labels sont identique et voici la scène et message erreur:

--[[
%% autostart
%% properties
1078 ui.lbldressing.value
1078 ui.lblsalle.value
1078 ui.lblbureau.value
1078 ui.lblsalledebains.value
1078 ui.lblchambre.value
1078 ui.lblenfant.value
1078 ui.lblclara.value
1078 ui.lblmatheo.value

%% globals
--]]

--[[
    Heating Manager v. 1.3.0 (2017) by OJC

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
--]]

--[[
    Versions Notes

    1.3.0   Add the possibility of using virtual device as heater controller
            Add the possibilité of using virtual device or global variable as setpoint provider
    1.2.0   New regulation code, inspired by eedomus box
            Add the possibility of using virtual temperature sondes
            Configuration simplification for both Manager and Panel
    1.1.0   Add motion sensor management
            Improve door/window sensor management
            Code Optimization
    1.0.0   Initial release
--]]


----------------------------------------------------------------------------------
--                                 GENERIC CODE                                 --
----------------------------------------------------------------------------------

logColor = {"YellowGreen", "SkyBlue", "NavajoWhite", "Tomato"}

lib = {}
  function lib:iif(a,b,c) if (a) then return b else return c end end
  function lib:log(m,l) if ((l or 1) >= logLevel) then print('<span style="color:' .. logColor[l or 1] .. ';">' .. m .. '</span>') end end

f = {"Ç","ç","[-èéêë']+","[-ÈÉÊË']+","[-àáâãäå']+","[-@ÀÁÂÃÄÅ']+","[-ìíîï']+","[-ÌÍÎÏ']+","[-ðòóôõö']+","[-ÒÓÔÕÖ']+","[-ùúûü']+","[-ÙÚÛÜ']+","[-ýÿ']+","Ý","%W"}
r = {"C","c","e","E","a","A","i","I","o","O","u","U","y","Y",""}

format = {}
  function format:ddigit(n) if (n < 10) then return "0"..n else return n end end
  function format:replace(s) local s = s for i, j in ipairs(f) do s = string.gsub(s, j, r) end return s end

function getDeviceIDbyName(name)
  local devices = api.get("/devices?name=" .. name)
  if (devices[1] ~= nil) then return devices[1].id end
end

function getInstanceAuthorization(max)
  local t = os.time()
  local max = tonumber(max) or 1
  while (fibaro:countScenes() > max) do
    fibaro:sleep(500)
    if (os.time() - t) > 30 then return false end
  end
  return true
end

--DEPENDENCIES = lib:log; getDeviceIDbyName
function getPanelID()
  local p = panel
  local v = fibaro:getGlobalValue(p.global)
  if (fibaro:getValue(v, p.label) == nil) then
    local ID = getDeviceIDbyName(p.name)
    if (ID ~= nil) then
      fibaro:setGlobal(p.global, ID)
      return ID
    else
      lib:log("[CRITICAL ERROR] " .. p.name .. " was not found !", 4)
      fibaro:abort()
    end
  else return v end
end

--DEPENDENCIES = format:ddgit
function getReadableTime(t)
  local d = ""
  local h = math.floor(t/3600)
  local m = math.floor(t/60 - (h * 60))
  local s = math.floor(t - h * 3600 - m * 60)
  if (h > 0) then d = d .. format:ddigit(h) .. " h " end
  if (m > 0) then d = d .. lib:iif(h ~= 0, format:ddigit(m), m) .. " m " end
  if (s > 0) then d = d .. lib:iif(m ~= 0, format:ddigit(s), s) .. " s" end
  return d
end

function getTemperatureSonde(ID)
  local r = api.get("/rooms?id=" .. ID)
  return r.defaultSensors.temperature
end

function setGlobalVariables(...)
  for _, v in ipairs{...} do
    if (fibaro:getGlobalValue(v) == nil) then api.post("/globalVariables", {name = v, isEnum = 0}) end
  end
end


----------------------------------------------------------------------------------
--                                 SPECIFIC CODE                                --
----------------------------------------------------------------------------------

collection = {}

HeatingManager = {}

--DEPENDENCIES = GetTemperatureSonde; format:replace
function HeatingManager:addHeater(idHeater, idSonde, localP, localT)
  local heater, on, off
  if type(idHeater) == "table" then
    heater, on, off = idHeater[1], idHeater[2], idHeater[3]
  else heater, on, off = idHeater, 0, 0
  end
  table.insert(collection, {
      heater = heater,
      OnOff = lib:iif(on ~= 0, {on, off}, 0),
      sonde = idSonde or getTemperatureSonde(fibaro:getRoomID(heater)),
      kP = localP or default.kP,
      kT = localT or default.kT,
      panel = "lbl" .. format:replace(fibaro:getRoomNameByDeviceID(heater))
    })
end

--DEPENDENCIES = getPanelID
function HeatingManager:getTemperatures(item)
  local c, s, e = 0, 0, 0
  if (type(item.sonde) == "number") then
      c = fibaro:getValue(item.sonde, "value")
  elseif (type(item.sonde) == "table") then
    c = string.match(fibaro:getValue(item.sonde[1], "ui." .. item.sonde[2] .. ".value"), "[0-13]+[,.][0-13]+") or string.match(fibaro:getValue(item.sonde[1], "ui." .. item.sonde[2] .. ".value"), "[0-13]+")    
  end
  s = string.match(fibaro:getValue(getPanelID(), "ui." .. item.panel .. ".value"), "[0-]+13[,.][0-13]+") or string.match(fibaro:getValue(getPanelID(), "ui." .. item.panel .. ".value"), "[0-13]+")
  if (outdoorSonde == nil) then
    o = api.get("/weather").Temperature
  elseif (type(outdoorSonde) == "number") then
      o = fibaro:getValue(outdoorSonde, "value")
  elseif (type(outdoorSonde) == "table") then
    o = string.match(fibaro:getValue(outdoorSonde[1], "ui." .. outdoorSonde[2] .. ".value"), "[0-9]+[,.][0-9]+") or string.match(fibaro:getValue(outdoorSonde[1], "ui." .. outdoorSonde[2] .. ".value"), "[0-9]+")
  end
  return c, s, o or s
end

function HeatingManager:setOutdoorSonde(idSonde)
  outdoorSonde = idSonde
end

----------------------------------------------------------------------------------
--                                  MAIN CODE                                   --
----------------------------------------------------------------------------------

--DEPENDENCIES = lib:log; getReadableTime ;
--               HeatingManager:getTemperatures
function SceneRun()
  
  local collection = collection
  
  for _, item in ipairs(collection) do
    
    local current, setpoint, C, T, P = 0, 0, 0, 0, 0

    lib:log("[INFO] Checking " .. fibaro:getRoomNameByDeviceID(item.heater) .. "...")
    current, setpoint, outdoor = HeatingManager:getTemperatures(item)  
    if (current == nil) then
      lib:log("[ERROR] " .. fibaro:getRoomNameByDeviceID(item.heater) .. " have no Temperature Sonde !",4)
      fibaro:call(item.heater, "turnOff")
      break
    end
    
    lib:log("[INFO] Current = " .. current .. " °C - Setpoint = " .. setpoint .." °C - Outdoor = " .. outdoor .. " °C")
    
    P = math.min((item.kP * (setpoint - current)) + (item.kT * (setpoint - outdoor)),1)

    if (P > 0) then
      lib:log("[ACTION] Start heating in " .. fibaro:getRoomNameByDeviceID(item.heater) .. " for " .. getReadableTime(P * heatingCycle * 60), 2)
      if type(item.OnOff) == "number" then
        fibaro:call(item.heater, "turnOn")
        if (P < 1) then setTimeout(function() fibaro:call(item.heater, "turnOff") end, P * heatingCycle * 60 * 1000) end
      else
        fibaro:call(item.heater, "pressButton", item.OnOff[1])
        if (P < 1) then setTimeout(function() fibaro:call(item.heater, "pressButton", item.OnOff[2]) end, P * heatingCycle * 60 * 1000) end
      end
    else
      lib:log("[INFO] Heating is not required in ".. fibaro:getRoomNameByDeviceID(item.heater))
      if type(item.OnOff) == "number" then
        fibaro:call(item.heater, "turnOff")
      else
        fibaro:call(item.heater, "pressButton", item.OnOff[2])
      end
    end

  end
  
  setTimeout(SceneRun, heatingCycle * 60 * 1000)
  
end


----------------------------------------------------------------------------------
--                                CONFIGURATION                                 --
----------------------------------------------------------------------------------

-- 1. Default Parameters

default = {}
  default.kP = 3.1
  default.kT = 0.02

-- For more information, see https://doc.eedomus.com/view/Algorithme_Chauffage

-- 2. General Parameters

heatingCycle = 10
logLevel = 1

-- 3. Collection Definition

--[[
    HeatingManager:addHeater(idHeater, [idSonde], [localP], [localT])

      + idHeater = ID of heater control device or {ID of heater virtuel device, order number of the ON button, order number of the OFF button}
      + idSonde  = ID of temperature sonde or {ID of temperature virtual device, ID of temperature label} - Optional : if not set, room temperature sonde is used
      + localP   = Optional : if not set, default.kP is used
      + localT   = Optional : if not set, default.kT is used

--]]

HeatingManager:addHeater({437, 1, 2}, 1053, localP, localT)
HeatingManager:addHeater({511, 1, 2}, 453, 0.6, 0.01)
HeatingManager:addHeater({438, 1, 2}, 1059, 2.6, localT)
HeatingManager:addHeater({439, 1, 2}, 415, 1.2, 0.01)
HeatingManager:addHeater({1076, 1, 2}, 1073, 0.6, 0.01)
HeatingManager:addHeater({943, 1, 2}, 1070, 0.6, 0.01)
HeatingManager:addHeater({1075, 1, 2}, 457, 0.6, 0.01)
HeatingManager:addHeater({1077, 1, 2}, 450, 0.6, 0.01)


--HeatingManager:setOutdoorSonde(ID Device or {ID VirtualDevice, ID Label})
--idSonde = ID Device or {ID VirtualDevice, ID Label} - Optional : If not set, weather plugin is used

HeatingManager:setOutdoorSonde(1045)


-------------------------------------------------------------------------
--                            START CODE                               --
-------------------------------------------------------------------------

--DEPENDENCIES = lib:log; getInstanceAuthorization;
--               HeatingManager:checkGlobalVariables;
--               SceneRun

trigger = fibaro:getSourceTrigger()

if not (getInstanceAuthorization(lib:iif(trigger.type == "property", 9, 1))) then
  lib.log("[CRITICAL ERROR] Too many instances are running !", 4)
  fibaro:abort()
end
  
panel = {name   = "Heating Panel",
         label  = "ui.lblHeatingPanel.value",
         global  = "HeatingPanelID"}

setGlobalVariables("HeatingPanelID")

if (trigger.type == "property") then

  for _, item in ipairs(collection) do
    if item.panel == string.match(trigger.propertyName,"ui.(%a+).value") then
      local current = 0
      local setPoint = 0
      current, setPoint = HeatingManager:getTemperatures(item)  
      if (current == nil) then
        lib:log("[ERROR] " .. fibaro:getRoomNameByDeviceID(item.heater) .. " have no Temperature Sonde !",4)
        fibaro:call(item.heater, "turnOff")
        fibaro:abort()
      end
      if (current < setPoint) then
        lib.log("[OVERRIDE] Start heating in " .. fibaro:getRoomNameByDeviceID(item.heater), 4)
        fibaro:call(item.heater,"turnOn")
      elseif (current >= setPoint) then
        lib.log("[OVERRIDE] Heating is not required in " .. fibaro:getRoomNameByDeviceID(item.heater), 4)
        fibaro:call(item.heater,"turnOff")
      end
    end
  end
      
else
        
  lib:log("Heating Manager v. 1.3.0 (2017) by OJC", 3)
  SceneRun()
  
end

 

[DEBUG] 17:54:32: [INFO] Checking chambre...
[DEBUG] 17:54:32: line 153: bad argument #1 to 'match' (string expected, got nil)

Partager ce message


Lien à poster
Partager sur d’autres sites

Ok. Je suis sur mon smartphone, tu peux me mettre juste la ligne 153 qui génère l'erreur stp ?

Partager ce message


Lien à poster
Partager sur d’autres sites

honte à moi:(, je viens de trouver j'ai 2 VD et je change la variable suivant la cheminée si elle est en route et j'ai modifier qu'un seul des VD et évidemment le mauvais:huh:

merci encore pour ton aide OJC sinon pour la régule c top

Partager ce message


Lien à poster
Partager sur d’autres sites

Cool :)

Je suis content que ça marche bien.

Partager ce message


Lien à poster
Partager sur d’autres sites

OJC,

ma scène fonctionne mais le setpoint=1 °c il ne prend pas la consigne du VD?

Partager ce message


Lien à poster
Partager sur d’autres sites

×