Washing Machine State Machine

Did you take a look at mqtt? Maybe something has changed slightly and you have to redefine your items.

I have not made any changes to the MQTT, just the update of the Sonoff Pow R2 to 6.01

When the machine is on and active, everything works perfectly, but after the wash, the energy item goes to 0 and stays there (no more log entries). Before the update, there were always fluctuations between 0 and 1.2W (when the machine was on and not active)

I’ll try the downgrade to 5.11 or are there commands to make the POW “sensitive”?

My Config:

Number      kel_wmaschine           "Waschmaschine läuft? [MAP(tag.map):%s]"        <wmaschine>         (gKel, gInfo)
Number      kel_wmaschine_energy    "Waschmaschine [%.2f W]"                        <stromver>          (gKel, gEnergy)                         {mqtt="<[broker:tele/sonoff_CE0772/SENSOR:state:JSONPATH($.ENERGY.Power)]"}
Number      kel_wmaschine_geenergy  "Waschmaschine - Gesamtverbrauch [%.2f kwh]"    <stromver>          (gKel, gEnergy)                         {mqtt="<[broker:tele/sonoff_CE0772/SENSOR:state:JSONPATH($.ENERGY.Total)]"}
Number      kel_wmaschine_rssi      "Waschmaschine Empfang: RSSI [%d %%]"           <wlan>              (gKel, gEmpfang)                        {mqtt="<[broker:tele/sonoff_CE0772/STATE:state:JSONPATH($.Wifi.RSSI)]"}
val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3

rule "Waschmaschine Aktivitätsregel"
when
    Item kel_wmaschine_energy changed
then
    if (kel_wmaschine_energy.averageSince(now.minusMinutes(2)) < 0.5) kel_wmaschine.postUpdate(MODE_OFF)
    else if (kel_wmaschine_energy.averageSince(now.minusMinutes(2)) > 10) kel_wmaschine.postUpdate(MODE_ACTIVE)
    else if (kel_wmaschine_energy.averageSince(now.minusMinutes(2)) < 5) {
        if (kel_wmaschine.state == MODE_OFF) kel_wmaschine.postUpdate(MODE_STANDBY)
        else if (kel_wmaschine.state == MODE_ACTIVE) kel_wmaschine.postUpdate(MODE_FINISHED)
    }
end

rule "Waschmaschine Benachrichtigung"
when
    Item kel_wmaschine changed to 3
then
    if (nog_tag.state == "ON") {
        sendCommand(gw_soundvolume, 10)
		sendCommand(gw_sound, 29)
		Thread::sleep(9000) /* wait for 9 seconds */
		sendCommand(gw_sound, 10000)
		sendCommand(gw_soundvolume, 0)
        whz_echo_tts.sendCommand('Daniel, die Waschmaschine ist fertig!')
    }
	else if (nog_tag.state == "OFF")
		sendPushoverMessage(pushoverBuilder("[openHAB - Info] Deine Waschmaschine ist fertig!"))
end
broker.url=tcp://openhabxxxxxxxxx:1883
broker.clientId=OpenHAB2
broker.user=openhabian
broker.pwd=xxxxxxx
broker.qos=0
broker.retain=true
broker.async=false
1 Like

I should have been more clear :slight_smile:

Did you take a look at the mqtt data? (i.e. start mqttspy, connect to your broker, subscribe to # (or at least to the topic tele/sonoff_CE0772/#) and wait until some data was received).

thanks for the Answer and sorry.

Now i fix it.

The problem was the update of the Sonoff POW R2 to Tasmota version 6.1.0, with this version the low-engery measurements are more than bad. I flashed Sonoff back to version 5.12 and it works. Now I get measurements around 0 to 1.2W in standby (machine on, but not active)

@Likonaus

I hope that you were able to get an answer to your year old question by now. But in case you hadn’t…

I had the same issue. It seems that if openHAB encounters some kind of fault, it does a crash dump of sorts into the log. This includes some non-printable characters or some flat out binary content. In order for grep to read such a file, tell it to “accept binary file as input” using the ‘-a’ command line option.

Mike

Im new in Openhab 2 (im coming from fhem) and have a working homegear integrated CCU2 - I want to setup the washingmaschine with an Homematic HM-ES-PMSw1 - it works also correct under things - but how the hell I get the correct rule for that thing and add it to my sitemap like in first post ? Cause my confusion comes from the *.items … cause as i think i dont need an item file if its connected as thing ?

Hey @black0r1337
in most cases one would need an item linked to the thing. Generally speaking the thing is a device which may contain multiple channels. Like a power plug that can be switched on/off but also reports watts/amps/etc.
Then you have the hardware device as thing and the items as the channels tied to it. You can find a nice docu on https://www.openhab.org/docs/concepts/things.html & https://www.openhab.org/docs/concepts/items.html.

Thus you have to create items based on your thing in order to have the rule listen for changes on your configured item.

Hi Sebastian, thanks for the answer - you have maybe an example - to be clearer dont understand it correct :confused:

I dont own your HM-ES-PMSw1, but for a different Homematic device a config might look like this:
homematic.things:

     Thing HM-Sec-RHS    LEQ1248XXX  "eg_esszimmer_fenster" @ "Esszimmer"

and the corresponding eg_esszimmer_fenster,items (shortend)

 String eg_esszimmer_fenster
     "Esszimmer [MAP(contact3.map):%s]"
     { channel="homematic:HM-Sec-RHS:ccu2:LEQ1248XXX:1#STATE" }

 Switch eg_esszimmer_fenster_lowbat
     "Esszimmer Fenster Batterie [MAP(hmbattery.map):%s]"
     { channel="homematic:HM-Sec-RHS:ccu2:LEQ1248XXX:1#LOWBAT" }

As you can see the thing is referenced in items definition. I’m a bit old-school doing all the config in files still. You’re able to do the same via PaperUI.

You task is to create an item that holds the power consumption of your thing. Once you can have that, you can continue in writing the rule acting basen on the metered consumption.

now i got it ! thanks Sebastian !

Must I create *.map files by my own or whats the purpose of that ?

So I have tried to follow these instruction, but fails:-(
Sitemap:

Text item=Washingmachine_OpState label="Wasching machine " icon="washingmachine_2" mappings=[2="Active"]

Item:

Number Washingmachine_OpState "Wachingmachine [%d]" 

But it gives me the following error:

Configuration model ‘CarlErik.sitemap’ has errors, therefore ignoring it: [43,85]: mismatched input ‘mappings=[’ expecting ‘}’ [50,3]: missing EOF at ‘}’

And [43,85] is the location of the mappings in sitemap. Without the mappings attribute, it works fine. What am I doing wrong?

Hard to tell without the rest of the Sitemap. The error is likely occurring due to a syntax error before or after this line (line 43?).

Hi

This is all of my sitemap. What I am curious about is why it is working when I dont write the mappings-attribute, so for m it looked like the problem was on that line.
But if it is before or after, this is all of my Sitemap:

sitemap OlaHansen label="Myhouse 17" {

	Frame label="Myapartment" {
		//Living room
		Switch item=ZWaveWallPlugSwitch_Switch icon="poweroutlet" label="Living room"
		
		//Exit door
		Text item=ZWaveNode3TZDW100DoorWindowSensor_DoorSensor icon="door" label="Exit door [%s]"
    }

    Frame label="Vacum"{
	
	Text item=RoborockVacuumS5_Actions_ControlVacuum label="Vacuum is in " icon="cleaningrobot" {
	Frame label="Control"{
		Switch item=RoborockVacuumS5_Actions_ControlVacuum mappings=[vacuum="Vacuum", pause="Pause",spot="Spot", dock="Dock"]
	}
	Frame label="Wind"{
		Switch item=RoborockVacuumS5_Status_FanPower mappings=[38="Silent", 60="Normal", 77="Power",90="Full", -1="Custom"]
	}
	
	Frame label="Info"{
	Text item=RoborockVacuumS5_Status_BatteryLevel label="[%d %%]" icon="Battery"
	Text item=RoborockVacuumS5_Status_Error label=": [%s]" icon=""
	Text item=RoborockVacuumS5_Status_State label="[%s]" icon=""
	Text item=RoborockVacuumS5_Status_CleaningArea label="[%1.0fm²]" icon=""
	Text item=RoborockVacuumS5_Status_CleaningTime label=" [%1.0f']" icon=""
	Text item=RoborockVacuumS5_Status_FanPower label="[%1.0f %%]" icon=""
	
	Chart item=RoborockVacuumS5_Status_State period=24h refresh=300 legend=true service="influxdb"
	}
	/*
	Frame label="History"{
	Text item=RoborockVacuumS5_History_TotalCleaningArea label="  [%1.0fm²] " icon=""
	Text item=RoborockVacuumS5_History_TotalCleaningTime label=" [%1.0f'] " icon=""
	Text item=RoborockVacuumS5_History_TotalCleanings label="  [%1.0f]" icon=""
	Chart item=RoborockVacuumS5_Actions_ControlVacuum period=24h refresh=300 legend=true service="influxdb"
	}
	Selection item=RoborockVacuumS5_Actions_ControlVacuum label="<labelname>" [icon="<iconname>"] [mappings="<mapping definition>"]
*/
}}

    Frame label="Waching machine"{
	Text item=Washingmachine_OpState label="Waching machine[%d]"   icon="washingmachine" 
	Text item=Washingmachine_OpState label="Wasching machine " icon="washingmachine_2"  { /*mappings=[2="Active"]*/
	Switch item=FibaroWallPlugElectric_Switch icon="" label="On/off"
	Text item=FibaroWallPlugElectric_ElectricMeterKWh label=" [%.3f KWh] " icon=""
	Text item=FibaroWallPlugElectric_ElectricMeterWatts label=" [%.3f watt] " icon=""
	Text item=FibaroWallPlugElectric_SensorPower label=" [%.0f kW] " icon=""
	Chart item=FibaroWallPlugElectric_SensorPower period=24h refresh=300 legend=true service="influxdb"
	Chart item=FibaroWallPlugElectric_SensorPower period=h refresh=300 legend=true service="influxdb"
	}}
    
	Frame label="Weather in my city"{	
	Text item=Temperature {
	Frame{
	Chart item=Temperature period=24h refresh=300 legend=true service="influxdb"
	}
	
	Text item=Humidity
	Text item=Visibility    
	Text item=Visibility_Mph   
	Text item=Pressure    
	Text item=Pressure_Inches  
	Text item=Pressure_Trend   
	Text item=Ozone           
	Text item=UV_Index         
	Text item=Clouds   
	Text item=Condition        
	Text item=Condition
	Text item=ObservationTime  
	Text item=LastUpdate       
	Text item=CommonId         
	Text item=Rain         
	Text item=Rain_Inches          
	Text item=Snow                   
	Text item=Snow_Inches   
	Text item=Precip_Probability      
	Text item=Precip_Total              
	Text item=Precip_Total_Inches      
	Text item=Temperature            
	Text item=Temp_Feel           
	Text item=Temp_Dewpoint            
	Text item=Temp_Feel           
	Text item=Temp_Min                     
	Text item=Temp_Max   
	}
	
	//Text item=Dimensionless 
	Text item=Pressure {
	Frame{
	Chart item=Pressure period=24h refresh=300 legend=true service="influxdb"
	}} 
	}
	Frame label="Status i leiligheten"{Switch item=ZWaveNode5ZW100Multisensor6_BinarySensor
	Text item=ZWaveNode5ZW100Multisensor6_SensorTemperature
	Text item=ZWaveNode5ZW100Multisensor6_SensorUltraviolet
	Text item=ZWaveNode5ZW100Multisensor6_SensorLuminance
	Text item=ZWaveNode5ZW100Multisensor6_SensorRelativeHumidity
	Text item=ZWaveNode5ZW100Multisensor6_MotionAlarm
	Text item=ZWaveNode5ZW100Multisensor6_TamperAlarm
	Text item=ZWaveNode5ZW100Multisensor6_BatteryLevel {
	Text item=ZWaveNode5ZW100Multisensor6_BatteryLevel 
	Chart item=ZWaveNode5ZW100Multisensor6_SensorTemperature period=D refresh=300 legend=true service="influxdb"
	Chart item=ZWaveNode5ZW100Multisensor6_MotionAlarm period=24h refresh=300 legend=true service="influxdb"
	Chart item=ZWaveNode5ZW100Multisensor6_SensorLuminance period=24h refresh=300 legend=true service="influxdb"
	Chart item=ZWaveNode5ZW100Multisensor6_SensorRelativeHumidity period=24h refresh=300 legend=true service="influxdb"
	}
	}
}

Edit:
Even if I removed almost everything of my sitemap (except the beginning, it still failed when i added the mappings-attribute.

Edit 2:
Actually this one got the same error:

sitemap TestOlaHansen label="Myhome" {
    Frame label="Waching machine"{
	Text item=Washingmachine_OpState label="Wachimg Machine [%d]" icon="washingmachine" mappings=[2="Active"] 
	}}
 Configuration model 'TestOlaHansen.sitemap' has errors, therefore ignoring it: [3,86]: mismatched input 'mappings=[' expecting '}'[4,3]: extraneous input '}' expecting EOF

[3,86] is the mapping attribute
and
[4,3] is the last } in the sitemap

A Text Widget has no option mappings, this is Switch/Selection Widget only. :wink:

Maybe this is, what you want to achieve?

Text item=Washingmachine_OpState label="Washing machine [MAP(washingmachine.map):%d]" icon="washingmachine_2" 

transform/washingmachine.map:

2=Active
-=-
NULL=-

I did this with a Fibaro Wall plug and a Miele BLDC without any state-machine what so ever. Only a simple trigger.
Plug is part of a HVACwatts group.
When finished, sens a FB chat message to the missus:

var boolean washerActive = false
val String washStart = "'openHAB: washer warming up..'"
val String washDone = "'openHAB: washer ready :-)'"

rule 'HVACwatts'
when Member of  hvacWatt changed
then
    logInfo(name10, triggeringItem.name + "=" + triggeringItem.state)
    switch(triggeringItem.name) {
        case "WasherPower": {
           var Number washerWatts = ((triggeringItem.state as DecimalType).floatValue)
           if (washerWatts > 1000.0) {
               if (washerActive == false) {
                   logInfo(name10, "Washer heating water")
                   washerActive = true
                   //var test = executeCommandLine("/usr/bin/python /home/omr/sendFBchatMsg.py " + MDYfbChatUid.state.toString + " " + washStart, 10000)
                   //logInfo("fbchat", "sendFBchatMsg returned:" + test);  
               }
           }

           if ((washerWatts  < 1.5) && (washerActive == true)) {
                   logInfo(name10, "Washer done")
                   washerActive = false
                   var test = executeCommandLine("/usr/bin/python /home/omr/sendFBchatMsg.py " + MDYfbChatUid.state.toString + " " + washDone, 10000)
                   logInfo("fbchat", "sendFBchatMsg returned:" + test);  
           }
        }
    }
end

My version of the state machine for tracking the washingmachine states. This way the FSM is synchronous with the instant power samples sent from the sonoff pow device and don’t use thread sleeps (using sleep you’re not sure you’re still evaluating and old sample beacause it depends on how you set the sleeping time and the MQTT frequency telemetries ). Notice the graph under the instant power graph tracking the washing machine states. The FSM has to be debugged, but I think this is a good way to track washing machine state. Notice also that I added the capability of auto-shutdown after 6 power samples.

val Number STATE_OFF = 0
val Number STATE_STANDBY = 3
val Number STATE_ACTIVE = 1
val Number STATE_FINISHED = 2
val Number STATE_DEBOUNCE = 4
val Number STATE_SHUTDOWN_WAIT = 5

val Number THRESHOLD_OFF = 2
val Number THRESHOLD_STANDBY = 2
val Number THRESHOLD_ACTIVE_TO_FINISH = 5
val Number THRESHOLD_ACTIVE = 30

val Number DEBOUNCE_SAMPLES = 3
val Number AUTOSHUTDOWN_SAMPLES = 6
var int debounce_counter
var int auto_shutdown_counter

rule "WM startup"
when
        System started
then
        postUpdate(Sonoff_WM_P, OFF)
        postUpdate(WashingMachine_OpState, STATE_OFF)
        postUpdate(WashingMachine_OpStateSwitch, STATE_OFF)
        postUpdate(autoShutDown_WM, OFF)
        postUpdate(notify_WM, OFF)
end

rule "Washingmachine_StateMachine"
when
    Item Sonoff_WM_P changed
then
        switch WashingMachine_OpStateSwitch.state       {
                case STATE_OFF: {
                                if (Sonoff_WM_P.state > THRESHOLD_STANDBY){
                                        WashingMachine_OpState.postUpdate(STATE_STANDBY)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_STANDBY)
                                }
                                if (Sonoff_WM_P.state > THRESHOLD_ACTIVE) {
                                        WashingMachine_OpState.postUpdate(STATE_ACTIVE)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_ACTIVE)
                                        if(notify_WM.state == ON)
                                                callScript("WM")
                                }
                        }
                case STATE_STANDBY: {
                                if (Sonoff_WM_P.state > THRESHOLD_ACTIVE) {
                                        WashingMachine_OpState.postUpdate(STATE_ACTIVE)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_ACTIVE)
                                        if(notify_WM.state == ON)
                                                callScript("WM")
                                }
                                if (Sonoff_WM_P.state < THRESHOLD_OFF) {
                                        WashingMachine_OpState.postUpdate(STATE_OFF)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_OFF)
                                }
                        }
                case STATE_ACTIVE: {
                                if (Sonoff_WM_P.state < THRESHOLD_ACTIVE_TO_FINISH)     {
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_DEBOUNCE)
                                        debounce_counter = 0
                                }
                        }
                case STATE_DEBOUNCE: {
                                if (Sonoff_WM_P.state < THRESHOLD_ACTIVE_TO_FINISH)     {

                                        debounce_counter = debounce_counter + 1;

                                        if(debounce_counter >= DEBOUNCE_SAMPLES){

                                                WashingMachine_OpState.postUpdate(STATE_FINISHED)

                                                if(notify_WM.state == ON){
                                                        callScript("endWM")
                                                }
                                                if(autoShutDown_WM.state == ON){
                                                        WashingMachine_OpStateSwitch.postUpdate(STATE_SHUTDOWN_WAIT)
                                                        auto_shutdown_counter = 0
                                                }
                                                else
                                                {
                                                        WashingMachine_OpStateSwitch.postUpdate(STATE_FINISHED)
                                                }
                                        }
                                }
                                else
                                {
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_ACTIVE)
                                }
                        }
                case STATE_FINISHED: {
                                if (Sonoff_WM_P.state < THRESHOLD_OFF){
                                        WashingMachine_OpState.postUpdate(STATE_OFF)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_OFF)
                                }
                                else if(Sonoff_WM_P.state >= THRESHOLD_ACTIVE){
                                        WashingMachine_OpState.postUpdate(STATE_ACTIVE)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_ACTIVE)
                                }
                        }
                case STATE_SHUTDOWN_WAIT: {
                                auto_shutdown_counter = auto_shutdown_counter + 1

                                if (Sonoff_WM_P.state < THRESHOLD_OFF){
                                        WashingMachine_OpState.postUpdate(STATE_OFF)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_OFF)
                                }
                                else if (auto_shutdown_counter >= AUTOSHUTDOWN_SAMPLES){
                                        WashingMachine_OpState.postUpdate(STATE_OFF)
                                        WashingMachine_OpStateSwitch.postUpdate(STATE_OFF)
                                        sendCommand(Sonoff_WM_Switch, OFF)
                                }
                        }

                default: WashingMachine_OpState.postUpdate(STATE_OFF)
        }
end

2 Likes

Hello all,

I bought some Gosund SP1 and flashed them with ESPurna. All values are arriving via MQTT and can be displayed in BasicUI.
Then I wanted to try the magic thing from first post. The weired thing is, I see no status message in UI but no error message in logs. Maybe I may ask you for a little help to check my settings?

items:

Switch  Dose_WaMa_Switch      "Steckdose Waschmaschine"  <switchwash>   (gKE_Naehen) 	{ mqtt=">[mymosquitto:Dose-WaMa/relay/0/set:command:*:MAP(ohtoespurna.map)], <[mymosquitto:Dose-WaMa/relay/0:state:MAP(espurnatooh.map)]" }

Number	Dose_WaMa_Power	    "WaMa Leistung [%.0f W]"		<ownvoltage>	(gKE_Naehen)	{ mqtt="<[mymosquitto:Dose-WaMa/power:state:default]" }
Number	Dose_WaMa_Voltage	"WaMa Spannung [%.0f V]"		<ownvoltage>	(gKE_Naehen)	{ mqtt="<[mymosquitto:Dose-WaMa/voltage:state:default]" }
Number	Dose_WaMa_Energy	"WaMa Verbrauch [%.3f kWh]"		<ownvoltage>	(gKE_Naehen)	{ mqtt="<[mymosquitto:Dose-WaMa/energy:state:default]" }
Number	Dose_WaMa_Current	"WaMa Stromstärke [%.3f A]"		<ownvoltage>	(gKE_Naehen)	{ mqtt="<[mymosquitto:Dose-WaMa/current:state:default]" }
String  WaMa_Status         "Waschmaschine Status [MAP(waschmaschine.map):%s]"    <switchwash>   (gKE_Naehen)

map:

2=Laeuft
3=Fertig
-=-
NULL=-
/*ANFANG SubFrame Keller ########################################################################################*/
	Text label=Keller icon="cellar"{
                
                Frame {
                        Group item=gKE_Werkstatt  label="Werkstatt"	icon="owntoolshop"
                        /*Text item=Werkstatt  icon="owntoolshop"{
                                Default		item=TemperatureAussenHinten		label="TemperaturHinten: [%.1f °C]"
                        }*/
                        Group item=gKE_Naehen  label="Nähzimmer"	icon="ownkate"
                        }
                }
        }

/*ENDE SubFrame Keller ########################################################################################*/

and finally rules:

import java.util.concurrent.locks.ReentrantLock

val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3
var java.util.concurrent.locks.ReentrantLock finishLock  = new java.util.concurrent.locks.ReentrantLock()

rule "Waschmaschine aktiv"
when
    Item Dose_WaMa_Power changed
then
    logInfo ("WaMa_Status","WaMa_Status" + WaMa_Status)
    if (Dose_WaMa_Power.state < 0.2) WaMa_Status.postUpdate("Aus")
    else if (Dose_WaMa_Power.state > 10) WaMa_Status.postUpdate("Läuft")
    else if (Dose_WaMa_Power.state < 4.5) {
        if (WaMa_Status.state == "Aus") WaMa_Status.postUpdate("Standby")
        else if (WaMa_Status.state == "Läuft") {
            finishLock.lock()
            try {
                Thread::sleep(10000) // Debounce for 10 seconds
                if (Dose_WaMa_Power.state < 4.5) WaMa_Status.postUpdate("Fertig!")
            } finally {
                finishLock.unlock()
            }
        }
    }
end

Has anyone find a good power consumption measuring that I can use in Australia.

Good project and do you think you could you the same idea on your metre box to tell you how much power is coming from fridge or the washing machine also on… Of course you couldn’t use a wall socket in the metre box.

@ adtwomey
I use plugwise for that.

https://www.plugwise.com/nl_NL/

what you use it with. I don’t know what you saying