<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>funcptr - automation</title>
    <subtitle>An engineer&#39;s technical notebook</subtitle>
    <link rel="self" type="application/atom+xml" href="https://funcptr.net/category/automation/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://funcptr.net/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-24T16:55:53+00:00</updated>
    <id>https://funcptr.net/category/automation/atom.xml</id>
    <entry xml:lang="en">
        <title>Boiling Water at Altitude in a &quot;Smart Kettle&quot;</title>
        <published>2026-10-24T16:55:53+00:00</published>
        <updated>2026-10-24T16:55:53+00:00</updated>
        
        <author>
          <name>Delta Regeer</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/"/>
        <id>https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/</id>
        
        <content type="html" xml:base="https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/">&lt;p&gt;As a coffee afficionado I of course own a water kettle that can hold
temperatures. I had a really cheap one and it was decent, but I had wanted a
&lt;a rel=&quot;external&quot; href=&quot;https://fellowproducts.com/products/stagg-ekg-electric-pour-over-kettle&quot;&gt;Fellow Stagg EKG+&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-staggkettle-1&quot;&gt;&lt;a href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/#fn-staggkettle&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; for years, however I never could really
justify the cost of having such a fancy kettle. My friend was asked by his
girlfriend to replace the black kettle with a pink one, so he gave me his old
— but perfectly functioning — Stagg EKG+.&lt;/p&gt;
&lt;p&gt;I&#39;ve owned this kettle for years and have really enjoyed using it, and will
continue loving it.&lt;/p&gt;
&lt;figure class=&quot;post-figure&quot;&gt;&lt;a class=&quot;post-figure-link&quot; href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/StaggEKGKettle.jpeg&quot;&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://funcptr.net/processed_images/StaggEKGKettle.7bcfd0c78294c130.avif 480w, https://funcptr.net/processed_images/StaggEKGKettle.3caa6e10d99db5b1.avif 800w, https://funcptr.net/processed_images/StaggEKGKettle.a804d73f9141a654.avif 1200w, https://funcptr.net/processed_images/StaggEKGKettle.7df16fc03c138122.avif 1600w, https://funcptr.net/processed_images/StaggEKGKettle.b2a1041ac115a751.avif 2000w&quot; sizes=&quot;(min-width: 752px) 720px, calc(100vw - 32px)&quot;&gt;&lt;img src=&quot;https://funcptr.net/processed_images/StaggEKGKettle.37f84d2b0404726b.jpg&quot; srcset=&quot;https://funcptr.net/processed_images/StaggEKGKettle.a758493bd185f0b2.jpg 480w, https://funcptr.net/processed_images/StaggEKGKettle.737f24b4e943908a.jpg 800w, https://funcptr.net/processed_images/StaggEKGKettle.37f84d2b0404726b.jpg 1200w, https://funcptr.net/processed_images/StaggEKGKettle.5c9893e38c2a2e36.jpg 1600w, https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/StaggEKGKettle.jpeg 2000w&quot; sizes=&quot;(min-width: 752px) 720px, calc(100vw - 32px)&quot; width=&quot;1200&quot; height=&quot;675&quot; alt=&quot;Fellow Stagg EKG+ Kettle sitting on my countertop&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/a&gt;
&lt;figcaption&gt;
&lt;p&gt;The pretty &lt;em&gt;black&lt;/em&gt; Fellow Stagg EKG+ Kettle on its base&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;hidden-feature-bluetooth&quot;&gt;Hidden Feature: Bluetooth&lt;/h2&gt;
&lt;p&gt;One of the neat little features that was barely advertised when this Kettle was
releases is that it supports Bluetooth. It advertises itself over &lt;abbr
  title=&quot;Bluetooth Low Energy&quot;&gt;BLE&lt;/abbr&gt;, and then an application you can
download for your mobile device you can control the kettle remotely. Set the
temperature, turn it on/off, and watch the current temperature.&lt;/p&gt;
&lt;p&gt;Using the application on my phone really isn&#39;t something that I have used, also
its of course insecure in that anyone within Bluetooth range can see the &lt;abbr
  title=&quot;Bluetooth Low Energy&quot;&gt;BLE&lt;/abbr&gt; advertisement and then connect to the
kettle, but we are going to ignore that, since it has enough built-in
protections to stop it from burning my house down (at least, it seems like it
does).&lt;/p&gt;
&lt;p&gt;I have a large &lt;a rel=&quot;external&quot; href=&quot;https://www.home-assistant.io/&quot;&gt;Home Assistant&lt;/a&gt; install, and was already running some
&lt;a rel=&quot;external&quot; href=&quot;https://esphome.io/&quot;&gt;ESPHome&lt;/a&gt; &lt;a rel=&quot;external&quot; href=&quot;https://esphome.io/components/bluetooth_proxy/&quot;&gt;Bluetooth Proxies&lt;/a&gt; so the next thing to do was see if someone
had already written a &lt;a rel=&quot;external&quot; href=&quot;https://hacs.xyz/&quot;&gt;HACS&lt;/a&gt; plugin so that I could control the Kettle.
After some searching I found the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/samwiseg0/ha-stagg-ekg-plus&quot;&gt;ha-stagg-ekg-plus&lt;/a&gt; repository made by
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/samwiseg0/&quot;&gt;samwiseg0&lt;/a&gt;, and loaded it into my Home Assistant setup. It found my Kettle
and setup was dead simple. Now that I had the kettle in Home Assistant, the next
thing to do is write some automations... because the real fun in home
automation is doing things like flashing your lights when the temperature
reaches its setpoint.&lt;/p&gt;
&lt;h2 id=&quot;boiling-at-altitude&quot;&gt;Boiling at Altitude&lt;/h2&gt;
&lt;p&gt;I live at ~1,770 meters (5800 ft&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-freedom units-1&quot;&gt;&lt;a href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/#fn-freedom units&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;) which means that the boiling
point of water is not actually 100C (212F), but far lower. Depending on the
weather and thus pressure it is either 93C (199.4F) or 94C (201.2F).&lt;/p&gt;
&lt;p&gt;If you set the kettle to 100C, it will continue to run forever and will never
shut off and go into hold mode. It will also boil the water so hard that when
the lid is on it will if you slightly overfill the kettle start overflowing out
the pour spout.&lt;/p&gt;
&lt;p&gt;So the next automation of course was to take the pressure from one of the many
pressure sensors around my house and use that information to automatically set
the kettle to either 93C or 94C, automaticall reacting to changes in the
weather and updating the kettle before I even go to use it (Bluetooth commands
are accepted and remembered even when the kettle is turned off)!&lt;/p&gt;
&lt;h2 id=&quot;antoine-equation-for-water-vapor-at-a-certain-pressure&quot;&gt;Antoine equation for water vapor at a certain pressure&lt;/h2&gt;
&lt;p&gt;Using the &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Antoine_equation&quot;&gt;Antoine equation&lt;/a&gt; we can the write a formula that uses the
pressure sensors to automatically set the boiling point.&lt;/p&gt;
&lt;p&gt;The formula is presented here with &lt;code&gt;p&lt;/code&gt; being the pressure in &lt;abbr
  title=&quot;Hectopascal&quot;&gt;hPa&lt;/abbr&gt; which is then converted to &lt;abbr
  title=&quot;millimeter of mercury [0 °C]&quot;&gt;mmHg&lt;/abbr&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot; &gt;&lt;code data-lang=&quot;jinja&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(1730.63 / (8.07131 - log(p * 0.750062, 10)) - 233.426)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Antoine equation relates the vapour pressure of a liquid to its temperature&lt;/p&gt;
&lt;div class=&quot;math-display&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi&gt;log&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;/mrow&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;&amp;#92;log&amp;#95;{10} P = A - &amp;#92;frac{B}{C + T}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/div&gt;
&lt;p&gt;Here &lt;em&gt;P&lt;/em&gt; is in &lt;abbr title=&quot;millimeter of mercury [0 °C]&quot;&gt;mmHg&lt;/abbr&gt; and &lt;em&gt;T&lt;/em&gt;
is in °C. Water boils when its vapour pressure equals the air pressure around
it. So if you put in the air pressure and solve for &lt;em&gt;T&lt;/em&gt;, you get the boiling
point:&lt;/p&gt;
&lt;div class=&quot;math-display&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi&gt;log&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;/mrow&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T = &amp;#92;frac{B}{A - &amp;#92;log&amp;#95;{10} P} - C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/div&gt;
&lt;h3 id=&quot;the-magic-numbers&quot;&gt;The magic numbers&lt;/h3&gt;
&lt;p&gt;The Antoine equation is not a perfect fit and can not actually be used across
the whole satured vapour pressure curve, so there are different constants that
are used to plug into the equation to do a close curve fit, that is good enough
for our use case since we will just &lt;code&gt;floor()&lt;/code&gt; the number we get to the closest
round number.&lt;/p&gt;
&lt;p&gt;The numbers here are directly from the Wikipedia page, and thus the well known
values:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Number&lt;/th&gt;&lt;th&gt;What it is&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;8.07131&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Antoine constant &lt;em&gt;A&lt;/em&gt; for water&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1730.63&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Antoine constant &lt;em&gt;B&lt;/em&gt; for water (in C)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;233.426&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Antoine constant &lt;em&gt;C&lt;/em&gt; for water (in C)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;So solving for T = 94 gives a P of ~610.6 &lt;abbr title=&quot;millimeter of mercury
  [0 °C]&quot;&gt;mmHg&lt;/abbr&gt; (~814.1 &lt;abbr title=&quot;Hectopascal&quot;&gt;hPa&lt;/abbr&gt;), so below
that pressure we can maximally heat to just 93C.&lt;/p&gt;
&lt;h2 id=&quot;home-assistant-automation-yaml&quot;&gt;Home Assistant Automation (YAML)&lt;/h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; kettle_boiling_point_limit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;alias&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #D9F5DD;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;Kettle: Keep Target Below Boiling Point&lt;/span&gt;&lt;span style=&quot;color: #D9F5DD;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #C792EA;font-style: italic;&quot;&gt; &amp;gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;  The Stagg EKG+ resets to 100 °C after losing power, and at altitude it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;  never reaches that and boils forever. Lowers the target to the local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;  boiling point (from the median house pressure sensor) whenever it is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;  above it: 94 °C normally, 93 °C below about 814 hPa. Never raises a lower&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;  target.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;triggers&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; trigger&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    entity_id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; sensor.kitchen_stagg_ekg_target_temperature&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; trigger&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    entity_id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; climate.kitchen_stagg_ekg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    from&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; unavailable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; unknown&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; trigger&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    entity_id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; sensor.office_aranet4_pressure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; trigger&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; homeassistant&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    event&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;conditions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; condition&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; template&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    value_template&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #C792EA;font-style: italic;&quot;&gt; &amp;gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;      {{ target | is_number and target | float &amp;gt; max_target | int }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; condition&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; template&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    value_template&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #C792EA;font-style: italic;&quot;&gt; &amp;gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;      {{ states(&amp;#39;climate.kitchen_stagg_ekg&amp;#39;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;         not in [&amp;#39;unavailable&amp;#39;, &amp;#39;unknown&amp;#39;] }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;actions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; action&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; climate.set_temperature&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    target&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;      entity_id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; climate.kitchen_stagg_ekg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    data&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;      temperature&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #D9F5DD;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;{{ max_target | int }}&lt;/span&gt;&lt;span style=&quot;color: #D9F5DD;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt; action&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; logbook.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;    data&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;      name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; Stagg EKG+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;      message&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #C792EA;font-style: italic;&quot;&gt; &amp;gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;        target lowered from {{ target }} °C to the local boiling point,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;        {{ max_target }} °C&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;      entity_id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; climate.kitchen_stagg_ekg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;mode&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt; queued&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;max&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #F78C6C;&quot;&gt; 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;variables&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;  max_target&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #C792EA;font-style: italic;&quot;&gt; &amp;gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;    {%- set ps = [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;          &amp;#39;sensor.office_aranet4_pressure&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;          &amp;#39;sensor.main_bedroom_aranet4_pressure&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;          &amp;#39;sensor.basement_atmospheric_pressure&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;          &amp;#39;sensor.purpleair_outside_pressure&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;        ] | map(&amp;#39;states&amp;#39;) | select(&amp;#39;is_number&amp;#39;) | map(&amp;#39;float&amp;#39;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;          | sort | list -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;    {%- if ps | count == 0 -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;      93&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;    {%- else -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;      {%- set p = ps[(ps | count) // 2] -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;      {{ (1730.63 / (8.07131 - log(p * 0.750062, 10)) - 233.426)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;         | round(0, &amp;#39;floor&amp;#39;) | int }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;    {%- endif -%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FDBCA;&quot;&gt;  target&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #D9F5DD;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #ECC48D;&quot;&gt;{{ states(&amp;#39;sensor.kitchen_stagg_ekg_target_temperature&amp;#39;) }}&lt;/span&gt;&lt;span style=&quot;color: #D9F5DD;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This automation explicitly sets the temperature to 93C if no pressure sensors
are available and thus it can&#39;t calculate anything so that it is set to at
least the safe temperature.&lt;/p&gt;
&lt;figure class=&quot;post-figure&quot;&gt;&lt;a class=&quot;post-figure-link&quot; href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/DialSetTemp.png&quot;&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://funcptr.net/processed_images/DialSetTemp.a41c3a7918edeb8b.avif 480w, https://funcptr.net/processed_images/DialSetTemp.1476ec030dde8e45.avif 760w&quot; sizes=&quot;(min-width: 752px) 720px, calc(100vw - 32px)&quot;&gt;&lt;img src=&quot;https://funcptr.net/processed_images/DialSetTemp.740f9b19f8c84e08.png&quot; srcset=&quot;https://funcptr.net/processed_images/DialSetTemp.740f9b19f8c84e08.png 480w, https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/DialSetTemp.png 760w&quot; sizes=&quot;(min-width: 752px) 720px, calc(100vw - 32px)&quot; width=&quot;480&quot; height=&quot;288&quot; alt=&quot;Home Assistant Logbook entry detailing the temperature the kettle attempted to be set to, and it clamping it down to the local maximum&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/a&gt;
&lt;figcaption&gt;
&lt;p&gt;Setting the temperature above the allowed
maximum forces the temperature to be clamped&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Trying to set the temperature above the maximum setpoint will automatically
clamp it, which means accidentally touching the dial when turning the kettle
on or when going from a lower temperature (such as required for specialty teas)
to max boiling will always leave it set to the safe boiling temperature.&lt;/p&gt;
&lt;figure class=&quot;post-figure&quot;&gt;&lt;a class=&quot;post-figure-link&quot; href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/KettleRebooted.png&quot;&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://funcptr.net/processed_images/KettleRebooted.c318a13bd8eeb7a9.avif 480w, https://funcptr.net/processed_images/KettleRebooted.a75b559c58afa47d.avif 762w&quot; sizes=&quot;(min-width: 752px) 720px, calc(100vw - 32px)&quot;&gt;&lt;img src=&quot;https://funcptr.net/processed_images/KettleRebooted.df923500c79081dd.png&quot; srcset=&quot;https://funcptr.net/processed_images/KettleRebooted.df923500c79081dd.png 480w, https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/KettleRebooted.png 762w&quot; sizes=&quot;(min-width: 752px) 720px, calc(100vw - 32px)&quot; width=&quot;480&quot; height=&quot;147&quot; alt=&quot;Home Assistant Logbook entry showing the kettle set itself to 100C, and the automation clamping it down to the local maximum again&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/a&gt;
&lt;figcaption&gt;
&lt;p&gt;Kettle restarts also clamp the
boiling point automatically&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Lastly, when the kettle&#39;s power is cycled, it will set itself back at a 100C as
the default setpoint. As soon as the kettle is connected to Home Assistant it
will once again be clamped down to the maximum setpoint.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-staggkettle&quot;&gt;
&lt;p&gt;This is a newer version than the one I have, I have the Stagg
EKG+ which has been replaced since then with a new version that uses wifi,
and there has been some work done to try and reverse engineer that protocol
so that it too can be added to Home Assistant. &lt;a href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/#fr-staggkettle-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-freedom units&quot;&gt;
&lt;p&gt;Freedom Units ™ for the eagle loving Americans that
visit my blog. &lt;a href=&quot;https://funcptr.net/2026/boiling-water-at-altitude-in-a-smart-kettle/#fr-freedom units-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
    </entry>
</feed>
