Bread rise time

Maybe my idea sounds a bit strange at first, but heres the idea. (Could be realized in Node-RED or Hassio automation, i do not care:))

The time for bread dough to rise, especially of sourdough bread, depends on the room temperature.

I would like to make an automation that runs e.g. 20 hours (which should be configurable) at 20°C room temperature.
At higher temperatures, i will take less time, at lower temperatures it takes longer.

My idea is the following.

  1. Start a timer / counter with e.g. 20 hours
  2. After each hour check the average temperature (or even integrate). If the temperature was 20°C, reduce the timer /counter by one hour. Otherwise reduce it by a different number depending on the temperature deviation from 20°C. The correct time is calculated by a linear equation.
  3. When the timer is in the last hour/done → send message/notify (easist job).

I’m quite new to Node-REd, so i need some hints how to do this? Is it possible using nodes or do i need to use functions-nodes?

Best regards,

Stefan

I would use Home Assistant Automations & the average component.

  1. set initial values (start & stop times)
  2. check every hour (time pattern) and recalculate stop time (whatever your formula is)
  3. check at stop-time -1 hour.

With this configuration, the component updates every minute giving the average over the last hour.

- platform: average
  name: Average Temp
  duration:
    hours: 1
  entities:
    - sensor.acurite_tower_temperature

Thanks for your answer.

Do i have to add the average sensor like every other average sensor in the configuration.yaml or is there an “automation only” option.

How do i use functions in automations?

Yes add the average sensor to your configuration & restart HA. Wait awhile and you will see the sensor change values.

By function do you mean calculating the end time? If yes, that’s the actions performed when trigger & conditions are met. Automations have 3 parts, Trigger, Condition & Actions., not sure of your skill level. If you need more help, let me know.

I use something similar where input_number.hw_tank_timer is =16

    - service: input_datetime.set_datetime
      data_template:
        entity_id: input_datetime.stop_timer
        datetime: "{{ now() + timedelta(hours = states('input_number.hw_tank_timer')|float(0)) }}"

Using a timer wouln’t be good for such a long period of time. If HA restarts the timer is lost, that’s why I set input_datetime fields.

Instead of average sensor, you can also use Node red get history node to get every single reading from the temperature sensor and do your own math.
During a span of 20 hours a spike might not be noticed in a average sensor.
If that even makes a difference?

you’ll need node-red-contrib-stoptimer-varidelay. Here you have a sensor with the remaining hours for your bread. The sensors drops by one every hour and it’s safe against restarts/deploys. From this sensor you can do the rest.

You can do that by calculating every hour the deviation and sending a msg.delay to the varidelay node, the sensors changes its state every hour. It’ll be done when the sensors reaches 0.

[{"id":"60963229.8ab40c","type":"stoptimer-varidelay","z":"937ef78.ec6b408","duration":"20","durationType":"num","units":"Hour","payloadtype":"num","payloadval":"0","name":"","reporting":"last_minute_seconds","persist":true,"x":380,"y":1840,"wires":[["338169a1.7f4b26"],[],["d82f1f0e.2a8b9"]]},{"id":"656c0971.864948","type":"inject","z":"937ef78.ec6b408","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"stop","payloadType":"str","x":210,"y":1860,"wires":[["60963229.8ab40c"]]},{"id":"a2fd998c.ae0d08","type":"ha-entity","z":"937ef78.ec6b408","name":"Timer","server":"9405c3fe.d0a6c","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Bread timer"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":890,"y":1860,"wires":[[]]},{"id":"7ca3c8af.936fd8","type":"comment","z":"937ef78.ec6b408","name":"Timer","info":"","x":350,"y":1760,"wires":[]},{"id":"959e5582.b74b88","type":"server-state-changed","z":"937ef78.ec6b408","name":"Timer","server":"9405c3fe.d0a6c","version":3,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.bread_timer","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":350,"y":2060,"wires":[[]]},{"id":"1d21794.ae57487","type":"comment","z":"937ef78.ec6b408","name":"Every hour","info":"","x":360,"y":2000,"wires":[]},{"id":"a7a8498b.627408","type":"inject","z":"937ef78.ec6b408","name":"start","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":1820,"wires":[["60963229.8ab40c"]]},{"id":"6c4ba372.bbaa1c","type":"change","z":"937ef78.ec6b408","name":"Get hour","rules":[{"t":"set","p":"payload","pt":"msg","to":"$round($number($substring(payload,0,2)))","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":1860,"wires":[["a2fd998c.ae0d08"]]},{"id":"338169a1.7f4b26","type":"change","z":"937ef78.ec6b408","name":"Set timer to 0","rules":[{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":1820,"wires":[["a2fd998c.ae0d08"]]},{"id":"d82f1f0e.2a8b9","type":"switch","z":"937ef78.ec6b408","name":"o´clock?","property":"$substring(payload,3,5)","propertyType":"jsonata","rules":[{"t":"eq","v":"00:00","vt":"str"},{"t":"neq","v":"00:00","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":540,"y":1880,"wires":[["6c4ba372.bbaa1c"],["38f838de.14a718"]]},{"id":"38f838de.14a718","type":"change","z":"937ef78.ec6b408","name":"Get hour","rules":[{"t":"set","p":"payload","pt":"msg","to":"$round($number($substring(payload,0,2))) + 1","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":1900,"wires":[["a2fd998c.ae0d08"]]},{"id":"9405c3fe.d0a6c","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

I think you need to calculate the minimum amount of time that it would take for the bread to rise and start there. Let’s say 18 hours is the fastest rise.

This flow will wait 18 hours, then take an average of the temp for that same period. From that adv temp either start a new timer or notify.

[{"id":"854589d4864e1971","type":"inject","z":"f80b6c338afd5483","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":220,"y":3640,"wires":[["5c48051172556ae6"]]},{"id":"260c495e63ea3b17","type":"api-get-history","z":"f80b6c338afd5483","name":"","server":"","version":0,"startdate":"","enddate":"","entityid":"sensor.flue_temp_2","entityidtype":"is","useRelativeTime":true,"relativeTime":"18 hours","flatten":true,"output_type":"array","output_location_type":"msg","output_location":"payload","x":560,"y":3640,"wires":[["18e2a65cdc2a20cb"]]},{"id":"18e2a65cdc2a20cb","type":"function","z":"f80b6c338afd5483","name":"","func":"msg.payload = msg.payload.reduce((a,o) => a+Number(o.state), 0)/msg.payload.length\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":720,"y":3640,"wires":[["051151e5aeed81ad"]]},{"id":"5c48051172556ae6","type":"stoptimer-varidelay","z":"f80b6c338afd5483","duration":"18","durationType":"num","units":"Hour","payloadtype":"num","payloadval":"0","name":"","reporting":"none","persist":true,"ignoretimerpass":false,"x":380,"y":3640,"wires":[["260c495e63ea3b17"],[],[]]},{"id":"051151e5aeed81ad","type":"switch","z":"f80b6c338afd5483","name":"start a new timer or notify now","property":"payload","propertyType":"msg","rules":[{"t":"lte","v":"74","vt":"num"},{"t":"btwn","v":"74","vt":"num","v2":"78","v2t":"num"},{"t":"gte","v":"78","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":950,"y":3640,"wires":[["5a34ca1ee6fd84a4"],["29ec58c5099102d8"],["2f6b8ed81bf412bc"]]},{"id":"2f6b8ed81bf412bc","type":"api-call-service","z":"f80b6c338afd5483","name":"notify","server":"","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1450,"y":3660,"wires":[[]]},{"id":"5a34ca1ee6fd84a4","type":"stoptimer-varidelay","z":"f80b6c338afd5483","duration":"2","durationType":"num","units":"Hour","payloadtype":"num","payloadval":"0","name":"","reporting":"none","persist":true,"ignoretimerpass":false,"x":1250,"y":3560,"wires":[["2f6b8ed81bf412bc"],[],[]]},{"id":"29ec58c5099102d8","type":"stoptimer-varidelay","z":"f80b6c338afd5483","duration":"1","durationType":"num","units":"Hour","payloadtype":"num","payloadval":"0","name":"","reporting":"none","persist":true,"ignoretimerpass":false,"x":1250,"y":3620,"wires":[["2f6b8ed81bf412bc"],[],[]]}]

Thank you for your replies. I’m going to try your recommendations.

Best regards,

Stefan