[SOLVED] [Bathroom fan] Migrate from DSL to Jython and update rule

I’ve used this rule from quite some time, where my bathroom fan starts blowing when someone starts showering.

First i have two items containing to old and the new humidity:

rule "Update Hum Badkamer"
when
    Item Sensor_Hum_BadkamerZ changed
then
    Sensor_Hum_Oud.postUpdate(Sensor_Hum_Nieuw.state.toString)
    Sensor_Hum_Nieuw.postUpdate(Sensor_Hum_BadkamerZ.state.toString)
end

Then this values are compared in a new rule:

rule "Badkamer Fan"
when
    Item Sensor_Hum_Nieuw received update
then
    var Number Humnew = Sensor_Hum_Nieuw.state as DecimalType
    var Number Humold = Sensor_Hum_Oud.state as DecimalType
    if((Schakel_Fan_Itho.state == OFF) && ((Humnew-Humold) > 5)) {
        logInfo("rules", "Badkamer FAN aan")
        sendCommand(Schakel_Fan_Itho, ON)
        Thread::sleep(2700000)
        sendCommand(Schakel_Fan_Itho, OFF)
    }
end

I know that it’s not right to use the Thread::sleep for so long time inside a rule. So i want to change the rule, that when the value get low again, under the 90(the sensor is quite slow, 90 will take more than one hour) so I changed the last part:

else if ((Schakel_Fan_Itho.state == ON) && (Humnew < 90 )) {
        logInfo("rules", "Badkamer FAN uit!")
        sendCommand(Schakel_Fan_Itho, OFF)
        }
end

But with this part, the fan is getting ON en OFF the first minutes before it reached 90%, off course. Is it possible to do this last part, but only when the humidity is going down and not when it’s rising.

I’m also in the (slow) proces of migrating rules to Jython. I’m not a programmer so i can only copy/paste and see whats working and not. I couple of light rules are already working. Changing this rule to Jython got me to this point:

@rule("Badkamer hum update", description="update de luchtvochtigheid", tags=["ventilator", "badkamer"])
@when("Item Sensor_Hum_BadkamerZ received update")
def Update_Sensor_Hum(event):
    Update_Sensor_Hum.log.info("De luchtvochtigheid wordt geupdate")
    events.postUpdate("Sensor_Hum_Oud", items["Sensor_Hum_Nieuw"])
    events.postUpdate("Sensor_Hum_Nieuw", items["Sensor_Hum_BadkamerZ"])

@rule("Badkamer FAN aanzetten", description="Als er iemand gaat douchen, de ventilator aanzetten", tags=["ventilator", "badkamer"])
@when("Item Sensor_Hum_Nieuw received update")
def Schakel_FAN__Itho_Aanzetten(event):
    Schakel_FAN__Itho_Aanzetten.log.info("De badkamer fan aanzetten")
    if items["Schakel_FAN_Itho"] == OFF and (items["Sensor_Hum_Nieuw"] - items["Sensor_Hum_Oud"]  > DecimalType(5))
        events.sendCommand("Schakel_Fan_Itho", "ON")

Now i need to make this working first and than add the part of the rule that it will shutdown the fan when the humidity drops below 90. Can someone put me in the right direction?

Frankly, I’d start over. There’s no need for the first rule and the Items to store the old and new state. Does this work for you?

@rule("Badkamer FAN aanzetten", description="Als er iemand gaat douchen, de ventilator aanzetten", tags=["ventilator", "badkamer"])
@when("Item Sensor_Hum_BadkamerZ changed")
def Schakel_FAN__Itho_Aanzetten(event):
    Schakel_FAN__Itho_Aanzetten.log.info("De badkamer fan aanzetten")
    if items["Schakel_FAN_Itho"] == OFF and (event.itemState.intValue() - event.oldItemState.intVaue() > DecimalType(5)):
        events.sendCommand("Schakel_Fan_Itho", "ON")
    elif items["Schakel_FAN_Itho"] == ON and event.itemState < DecimalType(90) and event.itemState < event.oldItemState:
        events sendCommand("Schakel_FAN_Itho", "OFF")

Thank you for your reply. with the event.OldItemState it much easier to do this without storing values. Was already reading about this.

I think this rule will work, but has the same problem, that it will be turned of if the humidity is raising and is still below 90. Is it possible to change the last bit of the rule to turn the fan OFF when it’s decreasing below 90 and not only below 90?

It might also be posible to wait for 5 minutes and than check if de value is below 90%. How to add this timer in the last bit of the rule, so it only waits 5 minutes and than execute the rest of the rule and not wait 5 minutes every time.

I added something that should help. I’m on my phone now and will add a 5 minute timer when I get to my computer. There is an example for timers in the HL repo though, so you might be able to get it going.

After taking some time to look through this, here is a better solution… and it adds a timer. Let me know if you have troubles with it (untested) or questions about how it all works!

from core.rules import rule
from core.triggers import when
from core.actions import ScriptExecution

fan_timer = None

@rule("Badkamer FAN aanzetten", description="Als er iemand gaat douchen, de ventilator aanzetten", tags=["ventilator", "badkamer"])
@when("Item Sensor_Hum_BadkamerZ changed")
def Schakel_FAN__Itho_Aanzetten(event):
    Schakel_FAN__Itho_Aanzetten.log.info("De badkamer fan aanzetten")
    global fan_timer
    if event.itemState >= DecimalType(90) and event.oldItemState >= DecimalType(90):
        # The conditions have been met to turn on the fan
        if fan_timer is not None and not fan_timer.hasTerminated():
            # If the timer is running, cancel it
            fan_timer.cancel()
        if items["Schakel_FAN_Itho"] == OFF:
            # If the fan is OFF, turn it ON
            events.sendCommand("Schakel_Fan_Itho", "ON")
    elif items["Schakel_FAN_Itho"] == ON and event.itemState < DecimalType(90) and event.oldItemState < DecimalType(90):
        # The conditions have been met to turn OFF the fan
        if fan_timer is None or not fan_timer.hasTerminated():
            # If a timer doesn not exist, create one
            fan_timer = ScriptExecution.createTimer(DateTime.now().plusMinutes(5), lambda: events.sendCommand("Schakel_FAN_Itho", "OFF"))
1 Like

I’m trying this first example, but get this error when the rules fire. This might be because the humidity is a value with a dot? (like 53.45).

File "<script>", line 7, in schakel_fan_itho_aanzetten
TypeError: unsupported operand type(s) for -: 'org.eclipse.smarthome.core.library.types.DecimalType' and 'org.eclipse.smarthome.core.library.types.DecimalType'

Sorry about that… my bad. There are a few ways to get past this. You probably don’t care about the decimals, so try…

event.itemState.intValue() - event.oldItemState.intValue()

https://openhab-scripters.github.io/openhab-helper-libraries/Guides/But%20How%20Do%20I.html#convert-decimaltype-to-an-integer-or-float-for-arithmetic

For some reason the rule doesnt work:

2020-01-12 09:33:25.200 [vent.ItemStateChangedEvent] - Sensor_Hum_BadkamerZ changed from 54.18 to 64.38
2020-01-12 09:33:25.202 [.event.RuleStatusInfoEvent] - ae69b8eb-beac-40fe-9a0d-c8ac4c00f252 updated: RUNNING
2020-01-12 09:33:25.204 [.event.RuleStatusInfoEvent] - ae69b8eb-beac-40fe-9a0d-c8ac4c00f252 updated: IDLE

My Rule:

from core.rules import rule
from core.triggers import when

@rule("Badkamer FAN aanzetten", description="Als er iemand gaat douchen, de ventilator aanzetten", tags=["ventilator", "badkamer"])
@when("Item Sensor_Hum_BadkamerZ changed")
def schakel_fan_itho_aanzetten(event):
    if items["Schakel_Fan_Itho"] == OFF and (event.itemState.intValue() - event.oldItemState.intValue() > DecimalType(5)):
        schakel_fan_itho_aanzetten.log.info("De badkamer fan aanzetten")
        events.sendCommand("Schakel_Fan_Itho", "ON")
    elif items["Schakel_Fan_Itho"] == ON and event.itemState < DecimalType(90) and event.itemState < event.oldItemState:
        schakel_fan_itho_aanzetten.log.info("De badkamer fan uitzetten")
        events.sendCommand("Schakel_Fan_Itho", "OFF")

The last part of the rule is working(turned the fan on with hand before this):

2020-01-12 11:10:47.063 [vent.ItemStateChangedEvent] - Sensor_Hum_BadkamerZ changed from 92.23 to 87.44
2020-01-12 11:10:47.063 [.event.RuleStatusInfoEvent] - 2202c5a4-6da7-43c2-babe-111df28f0da0 updated: RUNNING
2020-01-12 11:10:47.065 [ome.event.ItemCommandEvent] - Item 'Schakel_Fan_Itho' received command OFF
2020-01-12 11:10:47.070 [.event.RuleStatusInfoEvent] - 2202c5a4-6da7-43c2-babe-111df28f0da0 updated: IDLE
2020-01-12 11:10:47.075 [vent.ItemStateChangedEvent] - Schakel_Fan_Itho changed from ON to OFF

I question the new_value - old_value > 5 logic. How are your Items defined? Are they using UoM (Number:Dimensionless)?

Have you tried the second version with the timer?

I think that part of the rule isnt working. If i change that line to:

    if items["Schakel_Fan_Itho"] == OFF and event.itemState > DecimalType(65):

It’s working correct. The items is defined inside the PaperUI as number. inside my JsonDB:

  "Sensor_Hum_BadkamerZ": {
    "class": "org.eclipse.smarthome.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [],
      "itemType": "Number",
      "tags": [],
      "label": "Sensor_Hum_BadkamerZ"
      }
   }

Both sides of the comparison need to be changed…

    if items["Schakel_Fan_Itho"] == OFF and (event.itemState.intValue() - event.oldItemState.intValue() > 5):

This last change solved the problem, many thanks!
Now i will try some other rules with timers :slight_smile: