My first working automation - feedback on my rule

Hi everyone,

So, I’ve been at OpenHAB for a whole 24 hours and it’s not too bad! :slight_smile:

So far I’ve made one rule, which works (thanks to much copying from examples I’ve found online) but I’d like to know if what I have written is sufficient/correct/good.

The rule is designed to turn on a smart plug (which powers a fan in my roof space) once the temperature near my wood combustion heater reaches a certain level. The fan then distributes the hot air through the rest of the house. Here’s what I’ve done:

rule “Ceiling_fan_ON”
when
Item XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature received update
then
if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25){
if (XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state != ON) XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(ON)
}
end

rule “Ceiling_fan_OFF”
when
Item XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature received update
then
if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state <= 24){
if (XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state != OFF) XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(OFF)
}
end

So what do you think? Are there alternative ways of doing what I’ve done (and in case you were wondering, the on/off state temperatures are different on purpose to prevent the fan being turned on and off too much should the temperature hover just below/above 25.

Appreciate any feedback, I’m enjoying the learning experience.

EBF

rule “Ceiling_fan_ON”
  when
    Item XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature received update
  then
    if      (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25 && XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state != ON)  {XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(ON)}
    else if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state <= 24 && XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state != OFF) {XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(OFF)}
  end

Ok,

First feedback, please use the codes fences when posting code:

  • Both your rules have the same trigger so use one rule instead
  • Each rule has two ifs nested. This is equivalent of an &&

The first line can be commented out if you don’t have persistence installed

rule “Ceiling_fan_ON”
when
Item XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature received update
then
    // Do nothing if restart
    if (previousState == NULL) return; // You need persistence installed. This is to avoid the rule being run at start-up

   // Process what command to send
    var fanState = XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state.toString            
    if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25 && fanState != "ON") {
        fanState = "ON"
    } else if  (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state <= 24 && fanState != "OFF") {
        fanState = "OFF"
    }

    // Send command
    XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(fanState)
end

Thanks vzorglub.

Two things you did were to create a fanState var and you also put in a .toString item.

Is there a tutorial/manual that discusses these so that I can go into them in more detail?

I create a fanState variable than contains the state of XiaomiMiSmartSocketPlugCeilingInLineFan_Power
I put a .toString method at the end so that fanState is a string containing “ON” or “OFF” and not a state ON or OFF. It could work with just .state and then checking fanState != ON but I am not sure. I know that the .toString method work so I did that.
Then we check temperature and fanState
We assign a new value to fanState depending on the conditions
We send the command.

In this case it would have worked without the toString.

Then what type is the var, ONOFFType?

ONOFFType is the type. It is also if type State and Command.

Final version:

rule “Ceiling_fan_ON”
when
Item XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature received update
then
    // Do nothing if restart
    if (previousState == NULL) return; // You need persistence installed. This is to avoid the rule being run at start-up

   // Process what command to send
    var fanState = XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state
    if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25 && fanState != ON) {
        fanState = ON
    } else if  (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state <= 24 && fanState != OFF) {
        fanState = OFF
    }

    // Send command
    XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(fanState)
end

This is just for my own learning, the OP rule worked actually a little differently: it send only a command of the status of XiaomiMiSmartSocketPlugCeilingInLineFan_Power changed. The modified rule sends always a command every time the sensor is updated. Would there be a possibility to cause trouble if the sensor is very noisy and hence sends many updates? Or am I overthinking things?
Also in the same effort to understand better, could the second comparison in the if statements be deleted? I am missing what difference it would make in the modified rule. The OP used this to evaluate that no command needs to be send if the state is the same, however, this feature was lost in the modified rule and hence the second comparison seems unnecessary.

Just for the sake of learning you could try to create a proxy Switch item that holds the need to switch on or off based on temperature thresholds. That would require one rule.

Then you can create a second rule to only switch the fan when the proxy item receives a change (as opposed to an update).

You are not over thinking things. For some technologies this can indeed be a problem.

Luckily the fix is easy, just check to see if the new command is different before sending it. With Vincent’s application of the 1-2-3 Rule structure there only needs to be a change to the it line:

if(XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state != fanState)

  XiaomiMiSmartSocketPlugCeilingInLineFan_Power.sendCommand(fanState)

No because in think rule they are employing hysteresis. There is an degree range where no action is done (when temp is between 24 and 25 degrees. If you eliminated the else you lose this gap. Having this gap prevents the device from flapping when the temp is really close to the turn on/off value. Rapidly turning the fan on and off as the temp bounces above and then below. With the gap the temp had to change a full degree before it gets turned on or off.

1 Like

@rlkoshak, @lipp_markus

I thought I took care of that by having a double condition for each comparison
if temp>=25 AND fan is OFF
if temp<=24 AND fan is ON

I saw the hysteresis problem but that was taken care of by the OP with the 1c temperature gap

Thanks as always @rlkoshak
Sorry, I was not clear. When mentioning the second comparison, I meant this part: && fanState != ON or its equivalent for OFF. Not sure I see what its purpose is. Is there a computational advantage between a comparison and an assignment? I would think that this would work just well:

if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25) fanState = ON

The rest is clear, hysteresis is almost always a great idea

@lipp_markus

Original OP rule:

if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25){
    if (XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state != ON)
    ....

The two nested if are equivalent to a &&
So I did:

if (XiaomiMiTemperatureHumiditySensorLivingRoom_Temperature.state >= 25 && fanState != ON) 

instead

@vzorglub Thanks. I get that, but what purpose serves && fanState != ON

because
var fanState = XiaomiMiSmartSocketPlugCeilingInLineFan_Power.state

Thanks, appreciate your patience. Will need to do some more thinking obviously as I still have difficulties to see why I would not just delete && fanState != ON out…anyway, do not want to take more of your time and may just have to try this to understand.

It’s only a double check that the fan is off before we turn it on or off before we turn it on
It may not be necessary depending of the receiving device. If the receiving device reacts on a pulse to turn on or off then we need to do that.
Or if other rules down the line have a fan received command trigger, we may not want to duplicate the calls to those rules. Better be safe.

Ok, now I understand. I would drop that and just have the one check at the end like I showed above rather than repeating the check twice. I’d do so this primarily because it keeps from sending the same state to the device that it is already in. The checks in the above code so not do that.

1 Like