Skip to content

Notification when washing machine or dryer are finished, with openHAB

As part of my home automation project, I wanted the washing machine and the dryer to send notifications when they are finished. Both machines are in a separate room, and their alarm beeps are hard to hear in the other parts of the flat. Also because of the noise both machines make during operation, the door is usually closed.

 

 

After checking several options how to interact with the washing machine and the dryer (from listening to the audio signals to having light sensors glued over the status led, open the frame and install something inside, and a small cam with picture recognition), I settled with measuring the power consumption. Next step: find the right kit.

After another round of investigation, I settled with adding FRITZ!DECT 210 devices to the already existing FRITZ!Box. The "Smart Home" extensions send their data to the FRITZ!Box, which in turn provides the data using the "avmfritz" binding. Add the extension, again in Ansible:

- name: Get list of available and installed extensions
  uri:
    url: "http://{{ ansible_host }}:8080/rest/extensions"
  register: oh2_extensions
  changed_when: false


- name: Install extensions
  uri:
    url: "http://{{ ansible_host }}:8080/rest/extensions/{{ item }}/install"
    method: POST
  when: "not (oh2_extensions.json|byattr('id', item))[0].installed"
  with_items:
    - binding-avmfritz
  register: oh2_install_extensions

 

Auto-approve the new Items:

- name: Get inbox
  uri:
    url: "http://{{ ansible_host }}:8080/rest/inbox"
  register: oh2_inbox
  changed_when: false


- name: Auto-approve certain inbox items
  uri:
    url: "{{ oh2_inbox.url }}/{{ item.thingUID }}/approve"
    method: POST
  when: item.flag == "NEW" and
        (item.thingTypeUID[0:20] == "avmfritz:FRITZ_DECT_")
  loop: "{{ oh2_inbox.json }}"

The Play above will work with both the older FRITZ!DECT 200 and the newer FRITZ!DECT 210 adapters.

 

The "210" adapters provide Channels for total power consumption, current power consumption and the temperature. For now all I need is the current power consumption, but nevertheless I add Items for both the power consumption and the temperature. Everything goes into an .items file in /etc/openhab2/items:

Number Washingmachine_Power	"Washing machine power [%.2f W]"			<washingmachine>	(Energy)	{channel="avmfritz:FRITZ_DECT_210:*:*:power"}
Number Washingmachine_State	"Washing machine state [MAP(washingmachine.map):%s]"	<washingmachine>	(Energy)
Number Temperature_1		"Temperature 1 [%f°C]"					<temperature>		(Temperature)	{channel="avmfritz:FRITZ_DECT_210:*:*:temperature"}

Number Dryer_Power		"Dryer power [%.2f W]"					<dryer>			(Energy)	{channel="avmfritz:FRITZ_DECT_210:*:*:power"}
Number Dryer_State		"Dryer state [MAP(washingmachine.map):%s]"		<dryer>			(Energy)
Number Temperature_2		"Temperature 2 [%f°C]"					<temperature>		(Temperature)	{channel="avmfritz:FRITZ_DECT_210:*:*:temperature"}

The FRITZ!Box IP-address and the adapter UID are part of the channel name, but masked out in the example above.

 

The "washingmachine.map" file, in /etc/openhab2/transform:

0=Off
1=Standby
2=Running
3=Finished
NULL=Unknown

 

Now the rule for the washing machine, relatively straightforward:

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

rule "Washing machine Status"
when
    Item Washingmachine_Power received update
then
    // < 1.0 off
    // 1.0 - 5.0 standby
    // > 5.0 active
    if (Washingmachine_State.state == NULL) {
        // initial setup
        postUpdate(Washingmachine_State, MODE_OFF)
    }
    if (Washingmachine_Power.state < 1.0) {
        postUpdate(Washingmachine_State, MODE_OFF)
    } else if (Washingmachine_Power.state > 5.0) {
        postUpdate(Washingmachine_State, MODE_ACTIVE)
    } else if (Washingmachine_Power.state <= 5.0) {
        if (Washingmachine_State.state == MODE_OFF) {
            postUpdate(Washingmachine_State, MODE_STANDBY)
        } else if (Washingmachine_State.state == MODE_ACTIVE) {
            postUpdate(Washingmachine_State, MODE_FINISHED)
            logInfo("Washing machine", "Washing machine is finished")
            // SEND NOTIFICATION HERE
        }
    }
end

Everything above 5 watt of power consumption is considered active, everything below is either off or standby. Notification goes out when the state changes from active to finished.

 

The dryer is more complicated. The anti-crease program will turn on the dryer occasionally, and from a power consumption perspective there is no difference between a regular run and the anti-crease program. Afer carefully watching the openHAB logfile, I figured out that the anti-crease program turns the dryer on for about 2 minutes. I settled with adding another flag for the program, and a timer which fires after 3 minutes (to allow for openHAB delays):

var Timer anti_crease_timer = null
var Boolean anti_crease_program = null


rule "Dryer Status"
when
    Item Dryer_Power received update
then
    // < 1.0 off
    // 1.0 - 5.0 standby
    // > 5.0 active
    if (Dryer_State.state == NULL) {
        // initial setup
        postUpdate(Dryer_State, MODE_OFF)
        anti_crease_program = false
    }
    if (Dryer_Power.state < 1.0) {
        postUpdate(Dryer_State, MODE_OFF)
    } else if (Dryer_Power.state > 5.0) {
        postUpdate(Dryer_State, MODE_ACTIVE)
        anti_crease_program = true
        // occasionally the dryer, when in standby, turns on again
        // to prevent the clothes from crasing
        // this process lasts about 2 minutes
        anti_crease_timer = createTimer(now.plusSeconds(180)) [|
            if (Dryer_State.state == MODE_ACTIVE) {
                // if the dryer is still running after 3 minutes, it's the full program,
                // not just the anti crease program
                anti_crease_program = false
            }
        ]
    } else if (Dryer_Power.state <= 5.0) {
        if (Dryer_State.state == MODE_OFF) {
            postUpdate(Dryer_State, MODE_STANDBY)
            anti_crease_program = false
        } else if (Dryer_State.state == MODE_ACTIVE) {
            postUpdate(Dryer_State, MODE_FINISHED)
            // this flag is reset after 180 seconds,
            // only send a notification if the flag is 'false'
            // else it's just a short power-up from the anti-crease program
            if (anti_crease_program == false) {
                logInfo("Dryer", "Dryer is finished")
                // SEND NOTIFICATION HERE
            }
        }
    }
end

The timer fires when the power consumption goes up (active mode), and will check the power consumption after 3 minutes. Also when the power consumption goes up, the anti-crease program flag is set. If the power consumption is still high after the timer ended, it's not the anti-crease program - the flag is reset.

The important part is that the notification is only send when the flag is false - this avoids repeating the "is finished" message.

 

All in all that's a nice setup and I like the notification part.

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

No comments

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
To leave a comment you must approve it via e-mail, which will be sent to your address after submission.
Form options