Waschmaschine smart machen mit Shelly PM Mini und ioBroker

Eine Waschmaschine ist eigentlich ein ziemlich dankbares Smart-Home-Gerät. Sie muss nicht ferngesteuert werden, sie braucht keine App und sie muss auch nicht mit der Cloud reden. Interessant ist vor allem eine einzige Frage:

Ist die Waschmaschine fertig?

Genau dafür lässt sich die Waschmaschine smart machen – mit einem Shelly PM Mini (bezahlter Link), etwas Strommessung, ioBroker, InfluxDB und einem kleinen Blockly-Skript.

In meinem Fall hängt die Waschmaschine an einem Shelly PM Mini. Der misst nicht nur den Verbrauch, sondern liefert auch den aktuellen Leistungswert. Dieser Wert wird in ioBroker ausgewertet und zusätzlich in InfluxDB gespeichert. So sieht man sehr schön, wie sich der Stromverbrauch während eines Waschgangs verhält.


Schnellnavigation


Was soll überhaupt erkannt werden?

Die Waschmaschine soll nicht eingeschaltet oder ausgeschaltet werden. Das wäre bei einer Waschmaschine ohnehin nur bedingt sinnvoll. Mir ging es darum, den Zustand zuverlässig zu erkennen:

  • Waschmaschine läuft
  • Waschmaschine ist vermutlich fertig
  • Waschmaschine ist wirklich fertig
  • Benachrichtigung ausgeben

Der Shelly PM Mini (bezahlter Link) liefert dafür den entscheidenden Wert: die aktuelle Leistung in Watt.

Wenn die Waschmaschine aktiv arbeitet, liegt der Verbrauch deutlich höher. Beim Heizen kann er stark ansteigen, beim Drehen der Trommel schwankt er, und in Pausen fällt er wieder ab. Am Ende liegt der Verbrauch dauerhaft sehr niedrig.

Genau dieses Verhalten kann man auswerten.


Warum ein Shelly PM Mini?

Der Shelly PM Mini ist für solche Aufgaben sehr praktisch, weil er klein ist und reine Leistungsmessung bietet. Er ist also kein klassischer Schaltaktor, sondern misst den Verbrauch eines angeschlossenen Geräts.

Der Vorteil gegenüber einer reinen smarten Steckdose ist die saubere Integration in eine feste Installation. Natürlich gilt hier wie immer: Arbeiten an 230 Volt gehören nur in fachkundige Hände. Wer nicht genau weiß, was er da tut, lässt den Einbau von einem Elektriker machen.


Der Lastverlauf in InfluxDB

Bevor ich das Blockly gebaut habe, habe ich den Lastverlauf der Waschmaschine in InfluxDB gespeichert. Das ist ziemlich hilfreich, weil man nicht raten muss, wann die Maschine läuft oder fertig ist.

Man sieht im Verlauf meist sehr gut:

  • kurze Leistungsspitzen beim Motorlauf
  • hohe Leistung beim Aufheizen
  • ruhigere Phasen zwischen den Programmschritten
  • niedrigen Verbrauch am Ende des Waschgangs
Stromverlauf einer Waschmaschine in InfluxDB
Der Lastverlauf zeigt sehr gut, wann die Waschmaschine arbeitet, pausiert und am Ende dauerhaft in den niedrigen Verbrauch fällt.

InfluxDB Dokumentation


Die Logik hinter dem Blockly

Das Blockly arbeitet mit zwei Schwellenwerten:

  • ab 10 Watt gilt die Waschmaschine als laufend
  • unter oder gleich 5 Watt beginnt die mögliche Endphase

Zusätzlich gibt es einen Zeitstempel. Der ist wichtig, damit nicht jede kurze Pause direkt als „fertig“ erkannt wird.

Der grobe Ablauf sieht so aus:

  1. Der Leistungswert der Waschmaschine ändert sich.
  2. Liegt die Leistung bei mindestens 10 Watt, wird der Zustand läuft auf true gesetzt.
  3. Gleichzeitig wird der Zeitstempel zurückgesetzt.
  4. Fällt die Leistung auf 5 Watt oder weniger, wird ein Zeitstempel gesetzt.
  5. Steigt die Leistung wieder über 5 Watt, wird der Zeitstempel wieder gelöscht.
  6. Ein Minutentimer prüft regelmäßig, ob die Maschine weiterhin unter 5 Watt liegt.
  7. Wenn dieser Zustand lange genug anhält, wird läuft auf false gesetzt.
  8. Danach erfolgt die Meldung: „Die Waschmaschine ist fertig.“
<xml xmlns="https://developers.google.com/blockly/xml">
  <block type="on_ext" id="S6l_/[jUk2bQn~|j8L,o" x="-87" y="-312">
    <mutation xmlns="http://www.w3.org/1999/xhtml" items="1"></mutation>
    <field name="CONDITION">ne</field>
    <field name="ACK_CONDITION"></field>
    <value name="OID0">
      <shadow type="field_oid" id="Ipa]]`)lK__hg_XeC(xM">
        <field name="oid">alias.0.Waschkueche.Energie.Waschmaschine.ELECTRIC_POWER</field>
      </shadow>
    </value>
    <statement name="STATEMENT">
      <block type="controls_if" id="IF_MAIN">
        <value name="IF0">
          <block type="logic_compare" id="CMP_RUN">
            <field name="OP">GTE</field>
            <value name="A">
              <block type="on_source" id="SRC_POWER_1">
                <field name="ATTR">state.val</field>
              </block>
            </value>
            <value name="B">
              <block type="math_number" id="NUM_10">
                <field name="NUM">10</field>
              </block>
            </value>
          </block>
        </value>
        <statement name="DO0">
          <block type="control" id="SET_LAEUFT_TRUE">
            <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
            <field name="OID">0_userdata.0.Waschküche.Waschmaschine.läuft</field>
            <field name="WITH_DELAY">FALSE</field>
            <value name="VALUE">
              <block type="logic_boolean" id="BOOL_TRUE_1">
                <field name="BOOL">TRUE</field>
              </block>
            </value>
            <next>
              <block type="control" id="RESET_TS_ON_RUN">
                <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                <field name="WITH_DELAY">FALSE</field>
                <value name="VALUE">
                  <block type="math_number" id="NUM_0_1">
                    <field name="NUM">0</field>
                  </block>
                </value>
              </block>
            </next>
          </block>
        </statement>
        <next>
          <block type="controls_if" id="IF_LOWPOWER_START">
            <mutation elseif="1"></mutation>
            <value name="IF0">
              <block type="logic_multi_and" id="AND_LOWPOWER_START">
                <mutation xmlns="http://www.w3.org/1999/xhtml" items="3"></mutation>
                <value name="AND0">
                  <block type="logic_compare" id="CMP_LOWPOWER">
                    <field name="OP">LTE</field>
                    <value name="A">
                      <block type="on_source" id="SRC_POWER_2">
                        <field name="ATTR">state.val</field>
                      </block>
                    </value>
                    <value name="B">
                      <block type="math_number" id="NUM_5_1">
                        <field name="NUM">5</field>
                      </block>
                    </value>
                  </block>
                </value>
                <value name="AND1">
                  <block type="get_value" id="GET_LAEUFT_1">
                    <field name="ATTR">val</field>
                    <field name="OID">0_userdata.0.Waschküche.Waschmaschine.läuft</field>
                  </block>
                </value>
                <value name="AND2">
                  <block type="logic_compare" id="CMP_TS_IS_0">
                    <field name="OP">EQ</field>
                    <value name="A">
                      <block type="get_value" id="GET_TS_1">
                        <field name="ATTR">val</field>
                        <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                      </block>
                    </value>
                    <value name="B">
                      <block type="math_number" id="NUM_0_2">
                        <field name="NUM">0</field>
                      </block>
                    </value>
                  </block>
                </value>
              </block>
            </value>
            <statement name="DO0">
              <block type="control" id="SET_TS_NOW">
                <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                <field name="WITH_DELAY">FALSE</field>
                <value name="VALUE">
                  <block type="time_get" id="TIME_NOW_MS">
                    <mutation xmlns="http://www.w3.org/1999/xhtml" format="false" language="false"></mutation>
                    <field name="OPTION">sid</field>
                  </block>
                </value>
              </block>
            </statement>
            <value name="IF1">
              <block type="logic_compare" id="CMP_POWER_GT_5">
                <field name="OP">GT</field>
                <value name="A">
                  <block type="on_source" id="SRC_POWER_3">
                    <field name="ATTR">state.val</field>
                  </block>
                </value>
                <value name="B">
                  <block type="math_number" id="NUM_5_2">
                    <field name="NUM">5</field>
                  </block>
                </value>
              </block>
            </value>
            <statement name="DO1">
              <block type="control" id="RESET_TS_ON_POWER_UP">
                <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                <field name="WITH_DELAY">FALSE</field>
                <value name="VALUE">
                  <block type="math_number" id="NUM_0_3">
                    <field name="NUM">0</field>
                  </block>
                </value>
              </block>
            </statement>
          </block>
        </next>
      </block>
    </statement>
    <next>
      <block type="schedule" id="SCHED_CHECK">
        <field name="SCHEDULE">*/1 * * * *</field>
        <statement name="STATEMENT">
          <block type="controls_if" id="IF_FINISHED">
            <value name="IF0">
              <block type="logic_multi_and" id="AND_FINISHED">
                <mutation xmlns="http://www.w3.org/1999/xhtml" items="4"></mutation>
                <value name="AND0">
                  <block type="get_value" id="GET_LAEUFT_2">
                    <field name="ATTR">val</field>
                    <field name="OID">0_userdata.0.Waschküche.Waschmaschine.läuft</field>
                  </block>
                </value>
                <value name="AND1">
                  <block type="logic_compare" id="CMP_POWER_LTE_5_SCHED">
                    <field name="OP">LTE</field>
                    <value name="A">
                      <block type="get_value" id="GET_POWER_SCHED">
                        <field name="ATTR">val</field>
                        <field name="OID">alias.0.Waschkueche.Energie.Waschmaschine.ELECTRIC_POWER</field>
                      </block>
                    </value>
                    <value name="B">
                      <block type="math_number" id="NUM_5_3">
                        <field name="NUM">5</field>
                      </block>
                    </value>
                  </block>
                </value>
                <value name="AND2">
                  <block type="logic_compare" id="CMP_TS_GT_0">
                    <field name="OP">GT</field>
                    <value name="A">
                      <block type="get_value" id="GET_TS_2">
                        <field name="ATTR">val</field>
                        <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                      </block>
                    </value>
                    <value name="B">
                      <block type="math_number" id="NUM_0_4">
                        <field name="NUM">0</field>
                      </block>
                    </value>
                  </block>
                </value>
                <value name="AND3">
                  <block type="logic_compare" id="CMP_DIFF_GTE_8MIN">
                    <field name="OP">LTE</field>
                    <value name="A">
                      <block type="math_arithmetic" id="MATH_MINUS">
                        <field name="OP">ADD</field>
                        <value name="A">
                          <block type="get_value" id="GET_TS_3">
                            <field name="ATTR">val</field>
                            <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                          </block>
                        </value>
                        <value name="B">
                          <block type="math_number" id="NUM_8MIN_MS">
                            <field name="NUM">480</field>
                          </block>
                        </value>
                      </block>
                    </value>
                    <value name="B">
                      <block type="time_get" id="TIME_NOW_MS_2">
                        <mutation xmlns="http://www.w3.org/1999/xhtml" format="false" language="false"></mutation>
                        <field name="OPTION">sid</field>
                      </block>
                    </value>
                  </block>
                </value>
              </block>
            </value>
            <statement name="DO0">
              <block type="control" id="SET_LAEUFT_FALSE">
                <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                <field name="OID">0_userdata.0.Waschküche.Waschmaschine.läuft</field>
                <field name="WITH_DELAY">FALSE</field>
                <value name="VALUE">
                  <block type="logic_boolean" id="BOOL_FALSE_1">
                    <field name="BOOL">FALSE</field>
                  </block>
                </value>
                <next>
                  <block type="control" id="RESET_TS_ON_FINISH">
                    <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                    <field name="OID">0_userdata.0.Waschküche.Waschmaschine.timestamp</field>
                    <field name="WITH_DELAY">FALSE</field>
                    <value name="VALUE">
                      <block type="math_number" id="NUM_0_5">
                        <field name="NUM">0</field>
                      </block>
                    </value>
                    <next>
                      <block type="control" id="SPEAK_FINISH">
                        <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                        <field name="OID">alexa2.0.Echo-Devices.G092360930840799.Commands.speak</field>
                        <field name="WITH_DELAY">FALSE</field>
                        <value name="VALUE">
                          <block type="text" id="TEXT_FINISH">
                            <field name="TEXT">Die Waschmaschine ist fertig.</field>
                          </block>
                        </value>
                        <next>
                          <block type="control" id="k]c%i},y?ram:cUZyzx8">
                            <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                            <field name="OID">mqtt.0.LEDMatrix.Display1.text</field>
                            <field name="WITH_DELAY">FALSE</field>
                            <value name="VALUE">
                              <block type="text" id="doq|Av/!h_9E8h?l3-2x">
                                <field name="TEXT">Die Waschmaschine ist fertig.</field>
                              </block>
                            </value>
                          </block>
                        </next>
                      </block>
                    </next>
                  </block>
                </next>
              </block>
            </statement>
          </block>
        </statement>
      </block>
    </next>
  </block>
</xml>

Warum nicht einfach „unter 5 Watt = fertig“?

Das wäre die einfache Lösung. Aber leider wäre sie auch ziemlich unzuverlässig.

Eine Waschmaschine hat während eines Programms immer wieder Pausen. Die Trommel steht kurz, das Wasser wird nicht geheizt, die Pumpe läuft gerade nicht. In solchen Momenten kann der Verbrauch kurzzeitig sehr niedrig sein.

Wenn man dann sofort „fertig“ meldet, kommt die Benachrichtigung viel zu früh.

Deshalb prüft mein Blockly nicht nur den aktuellen Verbrauch, sondern auch die Dauer. Erst wenn die Waschmaschine vorher wirklich gelaufen ist und anschließend über mehrere Minuten im niedrigen Verbrauch bleibt, wird sie als fertig erkannt.

Das ist der entscheidende Punkt.


Benachrichtigung per Alexa und Nerd-Display

Wenn die Waschmaschine fertig ist, passiert bei mir aktuell Folgendes:

  • Der Status Waschmaschine läuft wird auf false gesetzt.
  • Der Zeitstempel wird zurückgesetzt.
  • Alexa sagt: „Die Waschmaschine ist fertig.“
  • Zusätzlich wird der Text auf dem Nerd-Display angezeigt.

Das ist nicht spektakulär, aber genau die Art Smart Home, die im Alltag sinnvoll ist. Keine App öffnen, keine Push-Nachricht suchen, kein Rätselraten. Die Waschmaschine meldet sich einfach.


Was man anpassen sollte

Die Werte aus meinem Blockly passen zu meiner Waschmaschine. Bei anderen Geräten können die Schwellen anders sein.

Ich würde deshalb immer zuerst den Verbrauch aufzeichnen und mir den Verlauf anschauen. Danach kann man die Werte sauber festlegen.

Wichtige Punkte:

  • Wie hoch ist der Standby-Verbrauch?
  • Wie niedrig fällt der Verbrauch während echter Pausen?
  • Wie lange dauern normale Pausen im Programm?
  • Ab wann ist wirklich klar, dass die Maschine fertig ist?

Bei mir funktioniert die Kombination aus 10 Watt für „läuft“ und 5 Watt für „Endphase“ gut. Die Wartezeit verhindert Fehlmeldungen durch kurze Pausen.


Mögliche Erweiterungen

Das Ganze lässt sich natürlich noch weiter ausbauen.

Denkbar wären zum Beispiel:

  • Push-Nachricht aufs Handy
  • Telegram- oder Signal-Meldung
  • Anzeige im Home Assistant Dashboard
  • Erinnerung nach 30 Minuten, wenn die Wäsche noch nicht herausgenommen wurde
  • verschiedene Meldungen je nach Tageszeit
  • automatische Anzeige auf einem Wanddisplay
  • Energieverbrauch pro Waschgang berechnen

Gerade der letzte Punkt ist interessant, wenn die Daten ohnehin in InfluxDB landen. Dann kann man nicht nur erkennen, dass die Waschmaschine fertig ist, sondern auch auswerten, wie viel Strom ein Waschgang tatsächlich verbraucht hat.


Mein Fazit

Die Waschmaschine smart machen muss nicht kompliziert sein. Man braucht keinen Cloud-Zwang, keine Hersteller-App und auch keine Waschmaschine mit eingebautem WLAN.

Ein Shelly PM Mini, ioBroker, InfluxDB und ein kleines Blockly reichen völlig aus, um den Zustand zuverlässig zu erkennen.

Für mich ist das eine der sinnvolleren Smart-Home-Automationen: Sie löst ein echtes Alltagsproblem, bleibt lokal kontrollierbar und ist technisch angenehm nachvollziehbar.

Die Waschmaschine wird dadurch nicht „intelligent“. Aber sie hört endlich auf, heimlich fertig zu sein.


Weiterführende Beiträge

Wenn dich solche lokalen Smart-Home-Lösungen interessieren, passen dazu auch diese Beiträge:

Schreibe einen Kommentar