Washing Machine State Machine

But is this delay in value change somehow caused by the 61-second-sleep in the rule? For all other value changes the interval is exactly 60 seconds (and right after this it’s 59 seconds, so jumping back in the old rythm).

This isn’t a realtime system. Looking for a delay that you know will be around sixty seconds - and sometimes is known to vary to 59 seconds - using a 61 second threshold is dumb.

Yes, the long sleep in the rule may be contributing. It ties up system resources for the duration, so potentially could delay the processing of external events. There’d have to be other contributions as well - other rules with sleeps, lots of I/O activity, etc. - but not impossible.

1 Like

Do it without a Thread::Sleep and use your Persistence :slight_smile:

val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3
rule "Waschmaschine Status"
when
    Item Steckdose_Waschmaschine_Power changed
then
    if (Steckdose_Waschmaschine_Power.state < 0.4) Waschmaschine_Status.postUpdate(MODE_OFF)
    else if (Steckdose_Waschmaschine_Power.state > 30) Waschmaschine_Status.postUpdate(MODE_ACTIVE)
    else if (Steckdose_Waschmaschine_Power.averageSince(now.minusMinutes(3))< 5){
      if (Waschmaschine_Status.state == MODE_OFF) Waschmaschine_Status.postUpdate(MODE_STANDBY)
      else if (Waschmaschine_Status.state == MODE_ACTIVE) Waschmaschine_Status.postUpdate(MODE_FINISHED)
    }
end
1 Like

Still have to get into the persistence topic as I didn’t need it so far.
I only use mapdb to store the last item state.

I use mapdb for restore at startup and influxdb for use cases like the washing machine.

rule "Waschmaschine Status"
when
    Item Steckdose_Waschmaschine_Power changed
then
    if (Steckdose_Waschmaschine_Power.state < 0.4) Waschmaschine_Status.postUpdate(MODE_OFF)
    else if (Steckdose_Waschmaschine_Power.state > 30) Waschmaschine_Status.postUpdate(MODE_ACTIVE)
    else if (Steckdose_Waschmaschine_Power.averageSince(now.minusMinutes(3), "influxdb")< 5){
      if (Waschmaschine_Status.state == MODE_OFF) Waschmaschine_Status.postUpdate(MODE_STANDBY)
      else if (Waschmaschine_Status.state == MODE_ACTIVE) Waschmaschine_Status.postUpdate(MODE_FINISHED)
    }
end
1 Like

I had difficulties to make the script work with a tplink 110 added in openhab2 through simple mode. The issue was the Unit “W” (defined as Number:Power tplinksmarthome_hs110_A8E90C_power “Power [%.1f %unit%]”).
The workaround was to change the checks as follow, adding "| “W”:
if (tplinksmarthome_hs110_A8E90C_power.state < 1 | “W” )
I got this solution through this post

hope this can help.
J

Hi all together,

during my search i found this thread.
Maybe it can be approach for my project.
I have rule that starts and stop my Ventingsystem dependent on humidity

rule "WACLuftfeuchtigkeit"
when
    Member of Durchschnitt_Feuchte_Haus changed // Durchschnitt Feuchte durch Lacrosse Sensoren
then
    if (WAC350_Durchschnitt_Feuchte_Haus.state != ON) { // wenn Schalter aus(nicht an) , keine Aktionen
        logInfo("Feuchtesteuerung:","Steuerung deaktiviert!")
    return;
    }
    // bestimme die durchschnittliche und maximale Luftfeuchte
    var int lfSumme=0
    var int lfMax=0
    var int lfCnt=0
    for (item: Durchschnitt_Feuchte_Haus.members) {
        if (item.state instanceof Number) {
            lfCnt+=1
            val int lf=(item.state as Number).intValue()
            lfSumme+=lf
            if (lf>lfMax) lfMax=lf
        }
    }
    // nur bei mindestens 2 Werten ist es sinnvoll, die Werte zu betrachten
    var int lfAvg
    if (lfCnt>=2) {
        lfAvg=lfSumme/lfCnt
    }
    else {
        lfAvg=0
        lfMax=0
    }
    // Bei mehr als max 60% pro Sensor oder avg 55% Luftfeuchtigkeit lüfte.
    if ((lfMax>=60 || lfAvg>=55) && FanStandby_Switch.state != OFF) {  // Standby ist ON und nicht OFF = Lüftung läuft nicht
        FanStandby_Switch.sendCommand(OFF)                             // Schalte Lüftung EIN
        logInfo("Feuchtesteuerung:","Lüftung EIN") 
        sendBroadcastNotification("Feuchtesteuerung: Lüftung EIN")     //Pushnachricht
    }
    else {
    // fällt die Luftfeuchte aller Sensoren unter 55%, wurde genug gelüftet. Lüftung Stop
    if ((lfMax<55) && FanStandby_Switch.state != ON) {                 // Standby ist OFF und nicht ON = Lüftung läuft
        FanStandby_Switch.sendCommand(ON)                              // Schalte Lüftung Standby
        logInfo("Feuchtesteuerung:","Lüftung Standby")
        sendBroadcastNotification("Feuchtesteuerung: Lüftung Standby") //Pushnachricht
        }
    }
end

This works very well.
But now i want to start the Venting also if in the kitchen the recirculation hood is swichted on.
I can detect this by taking the energy consumption in watts by a Shelly Plug S.
So at the end i have a number item with the watts value in it.
If the hood is switched on the watts value is minimum 50Watts.
How can i put this into my exsiting rule?
Basically the use of the hood should my have more priority like the humidiy.
So i want to say:
If the venting is off and the hood is in use, switch on the venting for 60minutes no matter what the humindiy is.

Or is it more easy to do this with time cron ?
Ususally the Kitchen is in use between 11.30 and 12.30 every day.
So can i say: If the time is in between 11.30 and 12.30 every day, switch on the venting if the venting is not on, but dont allow the humidity value to switch of the venting during that period of time

Or is it more usefull to have a second rule that send a postUpdate to the “WAC350_Durchschnitt_Feuchte_Haus” (it´s activating or deactivating the humidity rule)

Is this possible ?

Br Peter

This is really not the topic of this tutorial. Start a new thread.

You seem to have a good idea of what you need to do, it’s not really clear what difficulty you are having with doing it.

There are some Zigbee Devices: https://forum.iobroker.net/topic/20234/steckdose-mit-zigbee-und-verbrauchsmessung/9

i’ve adjusted an example from above and get an “error” on the “<” sign in VSCode

rule "Spülmaschine Status"
when
    Item BW1_Power changed
then
    if (BW1_Power.state < 0.4) Spuelmaschine_Status.postUpdate(MODE_OFF)
    else if (BW1_Power.state > 30) Spuelmaschine_Status.postUpdate(MODE_ACTIVE)
    else if (BW1_Power.averageSince(now.minusMinutes(3), "influxdb") < 5){
      if (Spuelmaschine_Status.state == MODE_OFF) Spuelmaschine_Status.postUpdate(MODE_STANDBY)
      else if (Spuelmaschine_Status.state == MODE_ACTIVE) Spuelmaschine_Status.postUpdate(MODE_FINISHED)
    }
end

popup from VSCode:

Ambiguous binary operation.
The operator declarations
operator_lessThan(Number, Number) in NumberExtensions and
operator_lessThan(Type, Number) in NumberExtensions
both match.(org.eclipse.xtext.xbase.validation.IssueCodes.ambiguous_feature_call)

What is there to do?

Rules DSL has some odd quirks, one of them is guessing what a character is about based on what came before. Here, it’s ambiguous … the < may be the less-than operator, or the first of a pair as in <QuantityType>.

You need to give it a clue. Knowing the preceding thing was a Number would be enough … but here, it isn’t a Number it’s an Item state object.

Boils down to
( (BW1_Power.state as Number) < 0.4)

i understand your explanation, but have same issue

no change on “<”

forgot to mention

else if (BW1_Power.averageSince(now.minusMinutes(3), "influxdb") < 5){

in this line is the error of <

got it with your hint

else if ((BW1_Power.averageSince(now.minusMinutes(3))as Number) < 5){

Hi,
just switching to OH3 and trying to port my wasching maschine rule and just not getting anywhere. Since it is a must for switching to OH3 because of the WAF I would appreciate your help.

Here is what I tried so far:
First attemt:

  1. created Item to get my measuerments: WasherCEUtilityroom_Power and put that in the modell
    This works so I see the W when the maschine is running
  2. created the Washer_OpState_CE_Utilityroom item
  3. Copied the old rule to the rules folder
    Result: Washer_OpState_CE_Utilityroom stays at NULL

Second attemt:
3. Created a new rule via UI and put in the script part:

Summary

This text will be hidden

if (WasherCEUtilityroom_Power.state < 0.2) Washer_OpState_CE_Utilityroom.postUpdate(0)
    else if (WasherCEUtilityroom_Power.state > 7) Washer_OpState_CE_Utilityroom.postUpdate(2)
    else if (WasherCEUtilityroom_Power.state < 2.5) {
        if (Washer_OpState_CE_Utilityroom.state == 0) Washer_OpState_CE_Utilityroom.postUpdate(1)
        else if (Washer_OpState_CE_Utilityroom.state == 2) Washer_OpState_CE_Utilityroom.postUpdate(3)
    }

Result: Washer_OpState_CE_Utilityroom stays at NULL

Would be grateful if anybody can push me in the right direction.

What kind of Item? What values do you see? This makes a difference about how you perform if() comparisons on it’s state.

It’s a Number:Power Item created via UI. The values are stated in WATTS. Is it possible that the conversion to W is the problem?

Yes, it’s the units.

So … less than 0.2 mW? 0.2kW? To compare with your state “xx W”, you need to be comparing to something with units as well.
You can use units in a constant with a | pipe character

if (WasherCEUtilityroom_Power.state < 0.2 | W)
or, exactly the same,
if (WasherCEUtilityroom_Power.state < 200 | mW)
it doesn’t matter, openHAB takes care of any scaling.

2 Likes

Yep the | W did the trick.

Thank you very much! Another lesson learned!

I migrated this template from OH 2.5 to OH 3.1.

The rule is only working partly now, it triggers only State 0 and State 2. But not State 1 or State 3, even though the Watt numbers are coming correctly from my Fibaro Plug.

Rule:

val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3
  
if (ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower.state < 1.0) WasherOpState.postUpdate(MODE_OFF)
    else if (ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower.state > 28.0) WasherOpState.postUpdate(MODE_ACTIVE)
    else if (ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower.state < 2.0) {
        if (WasherOpState.state == MODE_OFF) WasherOpState.postUpdate(MODE_STANDBY)
        else if (WasherOpState.state == MODE_ACTIVE) WasherOpState.postUpdate(MODE_FINISHED)
    }```

And here should be the trigger to change from State 2 to State 3, as Wattage is falling below 2.
2021-07-08 15:44:07.681 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item ‘ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower’ changed from 2.7 to 2.4

2021-07-08 15:44:08.681 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item ‘ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower’ changed from 2.4 to 2

2021-07-08 15:44:09.680 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item ‘ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower’ changed from 2 to 1.7

Only if other conditions are met too. Log out the states of your Items before entering the if() to figure out what is going on, and to make sure the rule runs when you think it should.

I’m surprised your zwave power is not reported with units.

It’s fixed now. Issue was - I guess - that WasherOpState was not of type “Number”.
If it helps, below my rule that I enriched with some logInfos.

val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3
logInfo("Washingmachine Consumption State Machine","I am running this rule")
  
if (ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower.state < 1.0 | W) {
   WasherOpState.postUpdate(MODE_OFF) 
   logInfo("Washingmachine Consumption State Machine","Washer is OFF")
} else if (ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower.state > 28.0 | W) {
    WasherOpState.postUpdate(MODE_ACTIVE)
    logInfo("Washingmachine Consumption State Machine","Washer is ON")
    } else if (ZWaveNode011FGWP101MeteredWallPlugSwitch_Sensorpower.state < 2.2 | W) {
        logInfo("Washingmachine Consumption State Machine","I am now checking if it's STANDBY or FINISHED (Status "+WasherOpState.state+")")
        if (WasherOpState.state == MODE_OFF) {
          logInfo("Washingmachine Consumption State Machine","Washer is STANDBY as it has been OFF before")  
          WasherOpState.postUpdate(MODE_STANDBY)
        } else if (WasherOpState.state == MODE_ACTIVE) {
          WasherOpState.postUpdate(MODE_FINISHED)
          logInfo("Washingmachine Consumption State Machine","Washer is FINISHED as it was ACTIVE before")
        } else {
          logInfo("Washingmachine Consumption State Machine","I did not enter here")
        }
    }
1 Like