Dynamic Price-Based Smart Washing Machine Control with Solar Forecast and Tibber Integration
This flow optimizes the start time of your washing machine based on Tibber's dynamic electricity prices and solar production forecasts from Home Assistant. It ensures that the washing machine runs within a defined time window (e.g., 07:00–20:00) and selects the cheapest 5-hour block of the day.
Additionally, it factors in solar energy production forecasts and adjusts energy price calculations to account for self-generated solar power, thus promoting energy cost savings and green energy usage.
The flow uses Home Assistant entities, Tibber API data, and triggers Alexa voice notifications when the washing is done or in case of errors.
✅ Main Features: Dynamic Price Optimization (Tibber Price API): Selects the cheapest time window for washing based on live hourly electricity prices.
Solar Surplus Compensation: Reduces calculated price impact based on upcoming PV surplus from forecast.solar integration.
Washing Machine Power Control: Automatically turns on the machine's power plug before remote start, and triggers the remote start button.
State and Error Handling: Waits for device readiness (Power On state, wash cycle status) and handles errors if the machine doesn't start or fails mid-cycle.
Completion Detection: Watches a binary sensor for wash completion and sends multi-device notifications (Alexa, Mobile App) when washing is finished.
Fallback Logic: Handles situations when the machine is already powered on or running.
Home Assistant Sensor Output: Writes optimized price schedule and control signals to a Home Assistant sensor entity for dashboard visualization and logging.
Manual Override: Includes manual injection nodes for testing and forced execution.
[{"id":"7d1b640a5a1e563c","type":"ps-strategy-lowest-price","z":"3ab217fef43e55c3","name":"Lowest Price Waschmaschine","fromTime":"07","toTime":"20","hoursOn":"5","maxPrice":"","doNotSplit":false,"sendCurrentValueWhenRescheduling":true,"outputValueForOn":"on","outputValueForOff":"off","outputValueForOntype":"str","outputValueForOfftype":"str","outputIfNoSchedule":"false","outputOutsidePeriod":"false","contextStorage":"memory","x":870,"y":300,"wires":[["83819d880da3d3de","255f31890c1982b9"],["83819d880da3d3de"],["83819d880da3d3de","2fa43d1c48e8232c"]]},{"id":"83819d880da3d3de","type":"debug","z":"3ab217fef43e55c3","name":"Waschmaschine debug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1510,"y":160,"wires":[]},{"id":"2fa43d1c48e8232c","type":"function","z":"3ab217fef43e55c3","name":"Convert true/false to 1/0","func":"msg.payload.hours.forEach(wasch => wasch.onOff = wasch.onOff ? \"1\" : \"0\")\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1230,"y":340,"wires":[["97a8685aa9cb463c"]]},{"id":"97a8685aa9cb463c","type":"ha-sensor","z":"3ab217fef43e55c3","name":"Preis Planung Waschmaschine","entityConfig":"38547a1876e184b3","version":0,"state":"payload","stateType":"str","attributes":[{"property":"Schedule","value":"payload.schedule","valueType":"msg"},{"property":"Hours","value":"payload.hours","valueType":"msg"},{"property":"Control","value":"payload.hours[0].onOff","valueType":"str"},{"property":"Current","value":"payload.current","valueType":"str"}],"inputOverride":"allow","outputProperties":[],"x":1510,"y":340,"wires":[["94c6d6260a37652b"]]},{"id":"94c6d6260a37652b","type":"debug","z":"3ab217fef43e55c3","name":"Preis Planung Waschmaschine","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1790,"y":340,"wires":[]},{"id":"382bea213157557e","type":"api-call-service","z":"3ab217fef43e55c3","name":"s Washing-machine Remote Start","server":"xxx","version":7,"debugenabled":true,"action":"button.press","floorId":[],"areaId":["keller"],"deviceId":[],"entityId":["button.s_washing_remote_start"],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"button","service":"press","x":2420,"y":280,"wires":[["83819d880da3d3de","c6ea624073d4772c"]]},{"id":"a711044c1a81e122","type":"inject","z":"3ab217fef43e55c3","name":"On","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"","payload":"on","payloadType":"str","x":970,"y":360,"wires":[["50018eb6afa5ebd6"]]},{"id":"d1fdda7c06a88f4b","type":"comment","z":"3ab217fef43e55c3","name":"Waschmaschine Start nach Strompreis","info":"","x":890,"y":200,"wires":[]},{"id":"d61959fa2ff8e14f","type":"function","z":"3ab217fef43e55c3","name":"Strompreise - Solarersparnis mit Verbraucher Waschmaschine","func":"// Holt die Daten aus den globalen Variablen\nvar solarDataMsg = global.get(\"SolarForecast\");\nvar priceDataMsg = global.get(\"TibberPriceReceiver\");\n\n// Formatierung des SolarForecast\nlet solarForecast = Object.entries(solarDataMsg.result).map(([time, power]) => ({ time: new Date(time), power }));\n\n// Formatierung der Preisdaten\nlet prices = priceDataMsg.map(({ value, start }) => ({ price: value, time: new Date(start) }));\n\nlet totalConsumption = 1; // in kWh\nlet duration = 4; // in Stunden\n\n// Berechnung des durchschnittlichen Verbrauchs pro Stunde\nlet averageConsumptionPerHour = totalConsumption / duration;\n\n// Berechnung der Solarersparnis für jede Stunde und Reduzierung des Strompreises\nlet adjustedPrices = prices.map(({ price, time }) => {\n let solarData = solarForecast.find(({ time: solarTime }) => solarTime.getHours() === time.getHours());\n let power = solarData ? solarData.power : 0;\n let savings = Math.min(power, averageConsumptionPerHour * 1000) / 1000 * price; // Ersparnis durch Solarstrom\n let adjustedSavings = savings / totalConsumption; // Anpassung der Ersparnisse an den Gesamtverbrauch\n let adjustedPrice = price - adjustedSavings; // Reduzierung des Strompreises um die angepassten Ersparnisse\n return { value: parseFloat(adjustedPrice.toFixed(4)), start: time.toISOString() };\n});\n\n// Speicherung der angepassten Preise in einer neuen globalen Variable\nglobal.set(\"SolarAdjustedTibberPriceReceiverWaschmaschine\", { priceData: adjustedPrices, source: \"Tibber\" });\n\n// Ausgabe der angepassten Preise mit Solarstromabzug\nmsg.payload = global.get(\"SolarAdjustedTibberPriceReceiverWaschmaschine\");\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":730,"y":400,"wires":[["7d1b640a5a1e563c"]]},{"id":"76798b64db5c93ca","type":"api-call-service","z":"3ab217fef43e55c3","name":"s Washing-machine Power an","server":"xxx","version":7,"debugenabled":false,"action":"switch.turn_on","floorId":[],"areaId":[],"deviceId":[],"entityId":["switch.s_washing_power"],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"switch","service":"turn_on","x":1630,"y":220,"wires":[["376189f87a86bdc4"]]},{"id":"376189f87a86bdc4","type":"ha-wait-until","z":"3ab217fef43e55c3","name":"Warte Power On","server":"xxx","version":3,"outputs":2,"entities":{"entity":["sensor.s_washing"],"substring":[],"regex":[]},"property":"state","comparator":"is","value":"on","valueType":"str","timeout":"30","timeoutType":"num","timeoutUnits":"seconds","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[],"entityLocation":"data","entityLocationType":"none","x":1860,"y":220,"wires":[["5c53832bd7b229e0"],[]]},{"id":"280f1edddf6e177a","type":"api-current-state","z":"3ab217fef43e55c3","name":"Washing-machine off","server":"xxx","version":3,"outputs":2,"halt_if":"off","halt_if_type":"str","halt_if_compare":"is","entity_id":"switch.s_washing_power","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1770,"y":280,"wires":[["76798b64db5c93ca"],["5c53832bd7b229e0"]]},{"id":"f73443b01b916a0b","type":"ha-wait-until","z":"3ab217fef43e55c3","name":"Wäsche fertig","server":"xxx","version":3,"outputs":2,"entities":{"entity":["binary_sensor.s_washing_wash_completed"],"substring":[],"regex":[]},"property":"state","comparator":"is","value":"on","valueType":"str","timeout":"4","timeoutType":"num","timeoutUnits":"hours","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[],"entityLocation":"data","entityLocationType":"none","x":1500,"y":400,"wires":[["db4132522f9de7ca"],["0eed0810d47ff6bd"]]},{"id":"5c53832bd7b229e0","type":"api-current-state","z":"3ab217fef43e55c3","name":"Status Waschen","server":"xxx","version":3,"outputs":2,"halt_if":"Waschen","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.s_washing_run_state","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":2020,"y":280,"wires":[[],["36812fb4fea7e7b9"]]},{"id":"d1255e496a96b07e","type":"api-call-service","z":"3ab217fef43e55c3","name":"Wäsche fertig with Alexa","server":"xxx","version":7,"debugenabled":false,"action":"notify.alexa_media_users_echo_dot","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{ \"message\": \"Alexa hier die Sonne hat die Wäsche gewaschen\", \"data\": { \"type\": \"announce\" }, \"target\": \"{{entity}}\" }","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"notify","service":"alexa_media_users_echo_dot","x":2010,"y":400,"wires":[["8012ec9148034153"]]},{"id":"36812fb4fea7e7b9","type":"api-current-state","z":"3ab217fef43e55c3","name":"Status Fehler","server":"xxx","version":3,"outputs":2,"halt_if":"Fehler","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.s_washing_run_state","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":2190,"y":280,"wires":[[],["382bea213157557e"]]},{"id":"501257f4497cf258","type":"inject","z":"3ab217fef43e55c3","name":"On","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"","payload":"on","payloadType":"str","x":1510,"y":460,"wires":[["db4132522f9de7ca"]]},{"id":"0eed0810d47ff6bd","type":"api-call-service","z":"3ab217fef43e55c3","name":"Wäsche waschen nicht geklappt with Alexa","server":"xxx","version":7,"debugenabled":false,"action":"notify.alexa_media_users_echo_dot","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{ \"message\": \"Alexa hier, Wäsche waschen mit Sonne hat leider nicht geklappt\", \"data\": { \"type\": \"announce\" }, \"target\": \"{{entity}}\" }","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"notify","service":"alexa_media_users_echo_dot","x":1870,"y":460,"wires":[[]]},{"id":"60707df6223a05d4","type":"api-call-service","z":"3ab217fef43e55c3","name":"Wäsche gestartet with Alexa","server":"xxx","version":7,"debugenabled":false,"action":"notify.alexa_media_users_echo_dot","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{ \"message\": \"Alexa hier, die Sonne wäscht jetzt\", \"data\": { \"type\": \"announce\" }, \"target\": \"{{entity}}\" }","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"notify","service":"alexa_media_users_echo_dot","x":2380,"y":340,"wires":[["f73443b01b916a0b"]]},{"id":"50018eb6afa5ebd6","type":"api-current-state","z":"3ab217fef43e55c3","name":"Washing-machine erreichbar","server":"xxx","version":3,"outputs":2,"halt_if":"unavailable","halt_if_type":"str","halt_if_compare":"is_not","entity_id":"switch.s_washing_power","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1370,"y":280,"wires":[["12bab6147121a4aa"],[]]},{"id":"c6ea624073d4772c","type":"api-call-service","z":"3ab217fef43e55c3","name":"users Echo Dot Volume 5","server":"xxx","version":7,"debugenabled":false,"action":"media_player.volume_set","floorId":[],"areaId":[],"deviceId":[],"entityId":["media_player.users_echo_dot"],"labelId":[],"data":"{\"volume_level\":\"0.5\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"media_player","service":"volume_set","x":2120,"y":340,"wires":[["60707df6223a05d4"]]},{"id":"db4132522f9de7ca","type":"api-call-service","z":"3ab217fef43e55c3","name":"users Echo Dot Volume 5","server":"xxx","version":7,"debugenabled":false,"action":"media_player.volume_set","floorId":[],"areaId":[],"deviceId":[],"entityId":["media_player.users_echo_dot"],"labelId":[],"data":"{\"volume_level\":\"0.5\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"media_player","service":"volume_set","x":1740,"y":400,"wires":[["d1255e496a96b07e"]]},{"id":"12bab6147121a4aa","type":"api-current-state","z":"3ab217fef43e55c3","name":"Washing-machine nicht fertig","server":"xxx","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is_not","entity_id":"binary_sensor.s_washing_wash_completed","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1570,"y":280,"wires":[["280f1edddf6e177a"],[]]},{"id":"255f31890c1982b9","type":"delay","z":"3ab217fef43e55c3","name":"alle 10 Stunden","pauseType":"rate","timeout":"1","timeoutUnits":"hours","rate":"1","nbRateUnits":"10","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":1180,"y":280,"wires":[["50018eb6afa5ebd6"]]},{"id":"8012ec9148034153","type":"api-call-service","z":"3ab217fef43e55c3","name":"Notify Rauchalarm Pixel 8","server":"xxx","version":7,"debugenabled":false,"action":"notify.mobile_app_pixel_8","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{ \"message\": \"Wäsche ist fertig!\", \"data\": { \"type\": \"announce\" }, \"target\": \"{{entity}}\" }","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"notify","service":"mobile_app_pixel_8","x":2270,"y":460,"wires":[["862ece8d57e0d761"]]},{"id":"862ece8d57e0d761","type":"api-call-service","z":"3ab217fef43e55c3","name":"Notify Rauchalarm FP5","server":"xxx","version":7,"debugenabled":false,"action":"notify.mobile_app_fp5","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{ \"message\": \"Wäsche ist fertig!\", \"data\": { \"type\": \"announce\" }, \"target\": \"{{entity}}\" }","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"notify","service":"mobile_app_fp5","x":2530,"y":460,"wires":[[]]},{"id":"27ed460fa38905e5","type":"ps-receive-price","z":"3ab217fef43e55c3","name":"Price Receiver","x":190,"y":360,"wires":[["d61959fa2ff8e14f"]]},{"id":"75cff2bade53561a","type":"tibber-query","z":"3ab217fef43e55c3","name":"Get Tibber prices","active":true,"apiEndpointRef":"f037801398711328","x":560,"y":300,"wires":[["27ed460fa38905e5"]]},{"id":"27d7f8acea9ed94b","type":"template","z":"3ab217fef43e55c3","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\n viewer {\n homes {\n currentSubscription {\n priceInfo {\n today {\n total\n startsAt\n }\n tomorrow {\n total\n startsAt\n }\n }\n }\n }\n }\n}","output":"str","x":370,"y":300,"wires":[["75cff2bade53561a"]]},{"id":"ddbaac66a0243ef0","type":"inject","z":"3ab217fef43e55c3","name":"TibberTagesPreise 13:30 Uhr ","props":[{"p":"payload"}],"repeat":"","crontab":"30 13 * * *","once":true,"onceDelay":"200","topic":"","payload":"","payloadType":"date","x":240,"y":200,"wires":[["27d7f8acea9ed94b"]]},{"id":"714b7e7442e48257","type":"comment","z":"3ab217fef43e55c3","name":"Dynamischen Strompreis von Tibber abrufen","info":"","x":250,"y":160,"wires":[]},{"id":"38547a1876e184b3","type":"ha-entity-config","server":"xxx","deviceConfig":"e0669c77ac021e25","name":"sensor.powersaver_planning_washing","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"powersaver_planning_washing"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"xxx","type":"server","name":"Home Assistant ","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":": ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"default","statusTimeFormat":"h:m","enableGlobalContextStore":false},{"id":"f037801398711328","type":"tibber-api-endpoint","queryUrl":"https://api.tibber.com/v1-beta/gql","feedConnectionTimeout":"30","feedTimeout":"60","queryRequestTimeout":"30","name":"Demo"},{"id":"e0669c77ac021e25","type":"ha-device-config","name":"sensor.powersaver_planning_washing","hwVersion":"","manufacturer":"Node-RED","model":"","swVersion":""}]