Rule to show which rooms need to be vented

Hi,

having used openHAB since 0.9 (or has it been 0.6) for years and finally finding about lambdas, here’s my rules file on how to detect which room needs to be vented in order to get humidity out.

You’ll need those items (example for Bad/Bath):

Number  T_Bad         "Bad [%.1f °C]"      (avgThermo)     // Current Temperature
Number  TSBad         "Bad [%.0f °C]"               (TS) // Set Temperature
Number  H_Bad         "Bad [%.0f %%]"             (avgHydro) // Humidity

You also need to put items in groups in order for the rule to “find” the items:

Group:Number:MAX avgHydro                          <humidity>
Group:Number:AVG avgThermo "Ø Innen [%.1f °C]"     <temperature>
Group TS

I copied and pasted the whole calculus from someone else. I’m sorry not to be able to mention him/her here for credit :frowning:

Please see the rule file for item names you need to replace.

import org.eclipse.xtext.xbase.lib.Functions

val Functions$Function2<StringType, Number, DecimalType> vent_room= [ n, crit |
  //logDebug("vent_room", n + "")
  val t = avgThermo.members.findFirst[name.equals("T_"+n)]
  val h = avgHydro.members.findFirst[name.equals("H_"+n)]
  val ts = TS.members.findFirst[name.equals("TS"+n)]
  val tp = TP.members.findFirst[name.equals("TP"+n)]

  if ((t.state == NULL) || (T_Outside.state == NULL) || (h.state == NULL) || (Humidity.state == NULL)) {
    logWarn("vent_room", n + " Fehler")
    return false
  }

  // Variablen
  var Number temp_in = t.state as DecimalType           //Inner Temperature in Grad Celsius
  var Number rel_hum_in = h.state as DecimalType         //relative Humidity inside

  var Number temp_out = T_Outside.state as DecimalType  //Outside Temperature in Grad Celsius
  var Number rel_hum_out = Humidity.state as DecimalType //relative Humidity outside

  var Number abs_hum_in = 0
  var Number abs_hum_out = 0
  var Number td_in = 0
  var Number td_out = 0

  // Konstanten
  val gas_const = 8314.3
  val mol = 18.016
//  var Number ab = 0
  var Number sdd = 0
  var Number dd = 0
  var Number v = 0
  var Number a_out = 0
  var Number b_out = 0

  val a_in=7.5
  val b_in=237.3
  if (temp_out >= 0) {
    a_out=7.5
    b_out=237.3
  } else {
    a_out=7.6
    b_out=240.7
  }

  // Formeln
  // Sättingungsdampfdruck:   SDD = 6.1078 * 10^((a*temp)/(b+temp))
  // Dampfdruck:              DD  = rel_hum * 100 / SDD
  // Absolute Feuchte:        AF  = 10^5 * mol / gas_const * DD / (temp + 273.15)
  // Taupunkt:                TD  = b*v/(a-v) mit v = log10(DD / 6.1078)

  // absolute Humidity inside, not used
  //  ab = ((a_in * temp_in) / (b_in + temp_in)).doubleValue()
  sdd = 6.1078 * Math::pow(10, ((a_in * temp_in) / (b_in + temp_in)).doubleValue())
  dd = rel_hum_in / 100 * sdd
  v = Math::log10((dd/6.1078).doubleValue())
  td_in = b_in * v / (a_in - v)
  //N_TPInnen.postUpdate(td_in)
  abs_hum_in = Math::pow(10, 5) * mol / gas_const * dd / (temp_in + 273.15)
  //N_TPInnen.postUpdate(abs_hum_in)

  // absolute Außenfeuchte
  //    ab = ((a_out * temp_out) / (b_out + temp_out)).doubleValue()
  sdd = 6.1078 * Math::pow(10, ((a_out * temp_out) / (b_out + temp_out)).doubleValue())
  dd = rel_hum_out / 100 * sdd
  v = Math::log10((dd/6.1078).doubleValue())
  td_out = b_in * v / (a_in - v)
  abs_hum_out = Math::pow(10, 5) * mol / gas_const * dd / (temp_out + 273.15)

  //logDebug("vent_room", n + " Abs. Luftfeuchte - in: " + abs_hum_in + " g/m3, out: " + abs_hum_out + " g/m3")
  logDebug("vent_room", n + " Taupunkt - in: " + td_in + " °C" + ", out: " + td_out + " °C")

  // Room not hot enough
  // Does not work well
  if ( 
      (temp_in >= ts.state) && 
      (temp_out <= td_in) && 
      ((td_in + 2.5) < td_out) &&
      (td_in >= (crit + 1))
  ) {
    // VENT
  } else {
    // DONT VENT
  }
]

rule "Lüften"
when
  Time cron "0 */5 * * * ?" or
  System started
then
  logDebug("vent_room", "Calculating")
// Only when at home
  if (Present.state == ON) {
    // Syntax is Room, [Temperatur on critical surface]
    vent_room.apply("Wohnen", 9)
    vent_room.apply("Bad", 8)
    vent_room.apply("Eltern", 8)
    vent_room.apply("KindN", 12)
    vent_room.apply("KindS", 12)
  }
end

The critical temperature is the lowest known temperature on a surface in the room because of thermal bridges. For example, the last rooms (KindN, KindS) both have bridges because of the shutters not being installed properly :construction_worker_man::man_facepalming:

Please let me know how this works for you. Me and my parents made good results venting the humidity out and fighting the mold.

Best,
Sascha

5 Likes

Very interesting solution. We’re fighting mould in our house in the UK but don’t have vents. What do you have fitted? I can look at retro-fitting them if they are suitable

Hi Rob,

I’m sorry to have caused a misunderstanding - we’re letting some air in by simply opening the windows. We don’t have any ventilation system (thus need to let some air in).

Best,
Sascha

1 Like

I’m jealous, my problem is increasing the humidity. I run a humidifier in the bedrooms all the time and it’s only able to stay in the mid 20% most days in Winter.

Great tutorial, thanks for posting!

1 Like