Washing Machine State Machine

Tags: #<Tag:0x00007faee00e6fa0>

Sorry…
This one I have bought 5 years ago… still working properly using a USB stick and 2 ‘plugs’
There is also a binding available. you can measure and switch on/off.
https://www.plugwise.com/en_US/products/plug

I read somewhere this also can be done by sonoff (Chinese stuff).

I like that tutorial a lot, unfortunately I’m not getting the expected results. I’m new at this which is why I suppose I’m making a beginners mistake. The only output I receive in my GUI is a “-”.

washingmachine.items:

String Washingmachine_OpState “Washingmachine State [MAP(washingmachine.map):%s]”

washingmachine.rules:

val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3

rule “Washingmachine Consumption State Machine”
when
Item avmfritz_FRITZ_DECT_200_1_087610044241_power changed
then
if (avmfritz_FRITZ_DECT_200_1_087610044241_power.state < 0.2) Washingmachine_OpState.postUpdate(MODE_OFF)
else if (avmfritz_FRITZ_DECT_200_1_087610044241_power.state > 10) Washingmachine_OpState.postUpdate(MODE_ACTIVE)
else if (avmfritz_FRITZ_DECT_200_1_087610044241_power.state < 3) {
if (Washingmachine_OpState.state == MODE_OFF) Washingmachine_OpState.postUpdate(MODE_STANDBY)
else if (Washingmachine_OpState.state == MODE_ACTIVE) Washingmachine_OpState.postUpdate(MODE_FINISHED)
}
end

default.sitemap entry, embedded in a frame:

Text item=Washingmachine_OpState label=“Waschmaschine [MAP(washingmachine.map):%d]” icon=“washingmachine_2”

washingmachine.map:

0=Aus
1=Standby
2=Aktiv
3=Fertig
NULL=?
-=-

Some example lines from my measurements:

2019-02-10 15:58:39.185 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 394.390 W to 389.310 W
2019-02-10 15:58:54.815 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 389.310 W to 15.300 W
2019-02-10 15:59:09.967 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 15.300 W to 15.230 W
2019-02-10 15:59:24.975 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 15.230 W to 15.300 W
2019-02-10 15:59:39.805 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 15.300 W to 15.230 W
2019-02-10 15:59:54.821 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 15.230 W to 15.660 W
2019-02-10 16:00:10.474 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 15.660 W to 3.140 W
2019-02-10 16:00:24.803 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.140 W to 3.360 W
2019-02-10 16:00:54.825 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.360 W to 3.070 W
2019-02-10 16:01:25.005 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.070 W to 3.360 W
2019-02-10 16:01:39.833 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.360 W to 3.140 W
2019-02-10 16:01:54.927 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.140 W to 14.730 W
2019-02-10 16:02:10.041 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 14.730 W to 3.430 W
2019-02-10 16:02:24.927 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.430 W to 3.070 W
2019-02-10 16:02:54.887 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.070 W to 3.360 W
2019-02-10 16:03:24.864 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.360 W to 3.070 W
2019-02-10 16:03:54.877 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 3.070 W to 2.930 W
2019-02-10 16:04:09.840 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 2.930 W to 2.640 W
2019-02-10 16:04:39.825 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 2.640 W to 2.930 W
2019-02-10 16:04:55.208 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 2.930 W to 2.640 W
2019-02-10 16:05:24.834 [vent.ItemStateChangedEvent] - avmfritz_FRITZ_DECT_200_1_087610044241_power changed from 2.640 W to 2.930 W

Basic UI Output:
BasicUI-Output

May somebody please help me to find the problem?

You are defining the mapping in both your .items and your .sitemap. Also, in your .sitemap you are using a %d which is for a number, you have the correct %s in your .items definition.

1 Like

Thank you very much. It’s working fine now, but I still get the following warning in the logs:

17:13:41.396 [WARN ] [.rest.core.item.EnrichedItemDTOMapper] - Failed transforming the state ‘0’ on item ‘Washingmachine_OpState’ with pattern ‘MAP(AVM.map):%d’: Cannot format state ‘0’ to format ‘%d’

It says “Cannot format state”, but still the “0” gets transformed into “Aus” as expected and described in my AVM.map file:

0=Aus
1=Standby
2=Active
3=Fertig
-=-
NULL=-

The result in the Basic UI is as expected:
image

For completeness, this is how my item looks like:

Number Washingmachine_OpState “Washingmachine State [MAP(AVM.map):%d]”

What am I doing wrong and how to avoid that warning?

You have to use %s instead.

Number Washingmachine_OpState “Washingmachine State [MAP(AVM.map):%s]”

trying to get this working here, but im not getting the MODE_FINISHED part.
It goes from off to on to off, but never to finished.

Hi,
could you share .items,.map and script?
i’ve tried this method but it hangs at STATE_DEBOUNCE and changing to STATE_FINISHED
this thread is very big and for someone new trying to find a decent working method it’s a mission.
the first method presented and extended one jumps from Active to Off and never Finished. i’m cursed :slight_smile:

Hello,
I’ve tried every solution given in this tutorial but for some reason i had no success. This could also be due to cheap “Tuya SP23” that loves to report 0W between the cycles when power drop from 1000w to 1w.
It may be me that didn’t have success with InfluxDb but in Grafana i can see everything.
Long story short…I took simplified version of the tutorial and i added timers to confirm if the power is constant or was just a spike, if it was a spike then the timer gets cancelled and is waiting for the next power drop.
the two variables on top represents the gaps between cycles.
this it works for me and i would like to share with others if helpful but i would like an opinion from someone with more experience if can be polished or it’s bad way of doing
I’ve left logInfo to help debug until timings are identified and working as intended
Washingmachine.rules

val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3

val Washingmachine_Timer_1_Delay_sec  = 15
val Washingmachine_Timer_2_Delay_sec  = 21 //time off between cycles

var Timer Washingmachine_Timer_1       // timer < 0.5 W
var Timer Washingmachine_Timer_2       // timer < 3.5 W

rule "Washingmachine Consumption State Machine"
when
    Item Power4 changed
then
    if (Power4.state < 0.5){ 
        if (Washingmachine_Timer_1 === null) {
            Washingmachine_Timer_1 = createTimer(now.plusSeconds(Washingmachine_Timer_1_Delay_sec), [ |
                logInfo("Washingmachine Timer1", "Started < 0.5 W")
                if (Power4.state < 0.5){ 
                        Washingmachine_OpState.postUpdate(MODE_OFF) 
                        Washingmachine_Timer_1 = null  // Cancels the timer 1 when run out
                        logInfo("Washingmachine Timer1", "MODE_OFF < 0.5 W")
                }
                else if (Power4.state > 0.5){
                    if (Washingmachine_Timer_1 !== null) {  //// Cancels the timer 2 when Power4 > 3.5 W
                    Washingmachine_Timer_1.cancel()
                    Washingmachine_Timer_1 = null
                    logInfo("Washingmachine Timer1", "Canceled >0.5 W")
                    }
                }
            ])
            
        }
    }        
        
    else if (Power4.state > 3.5) {
                Washingmachine_OpState.postUpdate(MODE_ACTIVE)
                if (Washingmachine_Timer_1 !== null) {  //// Cancels the timer 1 when Power4 > 3.5 W
                    Washingmachine_Timer_1.cancel()
                    Washingmachine_Timer_1 = null
                    logInfo("Washingmachine Timer1", "Canceled > 3.5 W")
                }
                else if (Washingmachine_Timer_2 !== null) {  //// Cancels the timer 2 when Power4 > 3.5 W
                    Washingmachine_Timer_2.cancel()
                    Washingmachine_Timer_2 = null
                    logInfo("Washingmachine Timer2", "Canceled > 3.5 W")
                }

    }
    else if (Power4.state < 3.5) {
        if (Washingmachine_Timer_2 === null) {
            Washingmachine_Timer_2 = createTimer(now.plusSeconds(Washingmachine_Timer_2_Delay_sec), [ |
                if (Power4.state < 3.5) { 
                        logInfo("Washingmachine Timer2", "Started < 3.5 W")
                        if (Washingmachine_OpState.state == MODE_OFF){
                            Washingmachine_OpState.postUpdate(MODE_STANDBY)
                            Washingmachine_Timer_2 = null  // Cancels the timer 2 when run out
                            logInfo("Washingmachine Timer2", "Standby after MODE_OFF ")
                            }
                        else if (Washingmachine_OpState.state == MODE_ACTIVE){
                            Washingmachine_OpState.postUpdate(MODE_FINISHED) 
                            Washingmachine_Timer_2 = null  // Cancels the timer 2 when run out
                            logInfo("Washingmachine Timer2", "Finished after MODE_FINISHED ")
                            }
                    }
                else if (Power4.state > 3.5){
                    if (Washingmachine_Timer_2 !== null) {  //// Cancels the timer 2 when Power4 > 3.5 W
                    Washingmachine_Timer_2.cancel()
                    Washingmachine_Timer_2 = null
                    logInfo("Washingmachine Timer2", "Canceled >3.5 W")
                    }
                    else if (Washingmachine_Timer_1 !== null) {  //// Cancels the timer 1 when Power4 > 3.5 W
                    Washingmachine_Timer_1.cancel()
                    Washingmachine_Timer_1 = null
                    logInfo("Washingmachine Timer1", "Canceled > 3.5 W")
                    }  
                }
            ])
                
        }
    }
end