<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Over Engineered]]></title><description><![CDATA[A personal lab notebook of automations, tech experiments, and things that absolutely did not need this much effort.]]></description><link>https://overengineered.jamesposs.com</link><image><url>https://substackcdn.com/image/fetch/$s_!C9up!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3a3d1cd-4d26-47a4-bbae-e7c5afbbcf63_400x400.png</url><title>Over Engineered</title><link>https://overengineered.jamesposs.com</link></image><generator>Substack</generator><lastBuildDate>Fri, 01 May 2026 11:00:19 GMT</lastBuildDate><atom:link href="https://overengineered.jamesposs.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[James Poss]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[overengineeredbyjames@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[overengineeredbyjames@substack.com]]></itunes:email><itunes:name><![CDATA[James]]></itunes:name></itunes:owner><itunes:author><![CDATA[James]]></itunes:author><googleplay:owner><![CDATA[overengineeredbyjames@substack.com]]></googleplay:owner><googleplay:email><![CDATA[overengineeredbyjames@substack.com]]></googleplay:email><googleplay:author><![CDATA[James]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[I Bought a Receipt Printer on Impulse… and Now People Send It Mail]]></title><description><![CDATA[I&#8217;m not sure what possessed me to impulsively buy a thermal receipt printer, but here we are.]]></description><link>https://overengineered.jamesposs.com/p/i-bought-a-receipt-printer-on-impulse</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/i-bought-a-receipt-printer-on-impulse</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Wed, 18 Feb 2026 19:00:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!bTZD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bTZD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bTZD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!bTZD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!bTZD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!bTZD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bTZD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic" width="559" height="372.79464285714283" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:559,&quot;bytes&quot;:321870,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://overengineered.jamesposs.com/i/187803642?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bTZD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!bTZD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!bTZD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!bTZD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c755fbc-8017-45fe-b9c6-9c60d2859cae_1536x1024.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It started innocently. I wrote a little program that prints news headlines and random facts when you press a button. Which is objectively cool, I suppose. But after the novelty wore off, I realized what I <em>really</em> wanted wasn&#8217;t just information&#8230;</p><p>I wanted <strong>mail</strong>!!</p><p>Because getting mail is mostly fun. Especially when it&#8217;s <em>not</em> junk. And there&#8217;s something satisfying about a machine <em>physically</em> spitting out a message into the real world like, &#8220;Congrats, you have been perceived.&#8221;</p><p>That idea became <strong>TinyMail</strong>: a tiny web app that lets anyone send a message (and optionally a photo) to my receipt printer.</p><p>And after I started posting the printouts on Instagram, people began using it more&#8230; and more&#8230; and <em>more</em>. Apparently, we as a society are not done enjoying the thrill of &#8220;I sent a thing and it showed up somewhere.&#8221;</p><h2><strong>What TinyMail Does</strong></h2><p>TinyMail is simple on purpose:</p><ul><li><p>Visitors type a <strong>name</strong> (optional-ish, you can put whatever you want or nothing at all)</p></li><li><p>Write a <strong>message</strong></p></li><li><p>Snap a <strong>photo </strong>(optional)</p></li><li><p>Hit send</p></li><li><p>The receipt printer does what receipt printers do best: <strong>prints and cuts.</strong></p></li></ul><p>It&#8217;s basically a public guestbook, but instead of living on a website forever, it gets <strong>printed into REAL LIFE existence</strong> like a tiny monochrome postcard.</p><h2><strong>The Surprisingly Good Economics of Tiny Paper</strong></h2><p>Thermal receipt paper is cheap, and a roll lasts way longer than you&#8217;d expect.</p><p>A common roll size for 80mm printers is <strong>about 262 feet </strong>of paper (80 meters). How many TinyMail messages does that become? It depends on how long each print is, but here&#8217;s a real-world estimate that I spent way too long working out:</p><ul><li><p>If an average TinyMail print is <strong>6 inches (15 cm)</strong> long</p><ul><li><p>80 meters &#247; 0.15 meters = ~<strong>533 message</strong></p><p><strong>s</strong></p></li></ul></li><li><p>If it&#8217;s a little longer, say <strong>8 inches (20 cm)</strong></p><ul><li><p>80 meters &#247; 0.20 meters = <strong>400 messages</strong></p></li></ul></li></ul><p>So a single roll is roughly <strong>400&#8211;530 messages</strong>.</p><p>In other words: <strong>many many many manyyy messages</strong> per roll is not an exaggeration. </p><h2><strong>Building It Was the Fun Part (But Also: The &#8220;Oh No, The Internet&#8221; Part)</strong></h2><p>Once you make something public-facing, especially something that prints on physical paper, you have to understand that there is plenty of room for abuse.</p><p>So over time, TinyMail grew up a little. It gained features and protections to keep it fun without becoming a streamer generator.</p><h3><strong>Bot Protection: Cloudflare Turnstile</strong></h3><p>I added <strong>Cloudflare Turnstile</strong> (a CAPTCHA alternative) to reduce automated spam. It&#8217;s a nice balance: it keeps bots out without making humans solve six puzzles about traffic lights like they&#8217;re studying for a CDL.</p><h3><strong>Rate Limiting</strong></h3><p>Even without bots, one enthusiastic person with free time can turn <em>any</em> public form into chaos.</p><p>So TinyMail rate limits requests to prevent someone from hammering the printer nonstop. The goal isn&#8217;t to kill the vibe&#8230; just to ensure it doesn&#8217;t become <em>a paper waterfall</em>.</p><h2><strong>Privacy: &#8220;Cute Project&#8221; Doesn&#8217;t Mean &#8220;Creepy Project&#8221;</strong></h2><p>Privacy matters. A lot. I get it.</p><p>TinyMail is designed to be lightweight and respectful:</p><ul><li><p><strong>Photos are only stored long enough to be processed and printed</strong>, then they&#8217;re removed.</p></li><li><p>The app doesn&#8217;t collect identifiable information beyond what the user voluntarily types into the <strong>name</strong> or <strong>message </strong>field.</p></li><li><p>The user&#8217;s <strong>IP address is logged only</strong> so rate limiting can be applied.</p></li><li><p>Once the rate limit window passes, <strong>that record is purged</strong>.</p></li></ul><p>That&#8217;s it. No profiles. No tracking. No targeted ads.</p><h2><strong>Why This Project Rules</strong></h2><p>TinyMail scratches a very specific itch:</p><ul><li><p>It makes online interaction feel <strong>physical</strong></p></li><li><p>It turns messages into <strong>artifacts</strong></p></li><li><p>It&#8217;s simple enough that anyone can use it</p></li><li><p>And it creates this tiny moment of connection where someone out there goes &#8220;I just printed that to his printer.&#8221;</p></li></ul><p>It&#8217;s silly, wholesome, and just the right amount of over-engineered. (The best amount)</p><h2><strong>Give It a Shot!</strong></h2><p>Use the link below to send me some TinyMail!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://overengineered.jamesposs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://overengineered.jamesposs.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://tinymail.rainbowlink.org&quot;,&quot;text&quot;:&quot;Send TinyMail&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://tinymail.rainbowlink.org"><span>Send TinyMail</span></a></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Never Forget the Laundry Again]]></title><description><![CDATA[Our washer, dryer and dishwasher now speak up when they&#8217;re done. No guesswork, no forgotten cycles, just nice, over-engineered peace of mind delivered automatically.]]></description><link>https://overengineered.jamesposs.com/p/never-forget-the-laundry-again</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/never-forget-the-laundry-again</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Wed, 11 Feb 2026 19:00:27 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6c440e66-7a5a-47e6-8c52-7012264f0d08_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If there&#8217;s one universal truth about household chores, it&#8217;s this:</p><p><strong>The dishwasher finishes the moment you forget it exists</strong>, and laundry only becomes urgent once it smells <em>slightly suspicious</em>.</p><p>To solve this, I built a set of Home Assistant automations that <strong>watch power usage</strong>, determine appliance state, and then <strong>politely </strong>notify us when something is done.</p><p>No smart appliances required.</p><div><hr></div><h2><strong>The Hardware: Energy Tells No Lies</strong></h2><p>At the core of this setup is a <strong>Refoss energy monitor</strong>, installed at the electrical panel using CT clamps. I found it easy to install, but I&#8217;m going to tell you to hire an electrician.</p><p>Each appliance (dishwasher, washer, dryer) has its own circuit monitored, giving me real-time power readings straight to Home Assistant.</p><div><hr></div><h2><strong>The Secret Sauce</strong></h2><p>Instead of relying on a single &#8220;power dropped = done&#8221; trigger, each appliance uses a <strong>three-state lifecycle</strong> tracked with a helper:</p><ul><li><p><strong>Off</strong> &#8211; Appliance is idle</p></li><li><p><strong>Running</strong> &#8211; Appliance is actively doing its thing</p></li><li><p><strong>Done</strong> &#8211; Appliance finished and is waiting for human intervention</p></li></ul><p>This prevents false alerts when someone opens the door mid-cycle or power briefly dips.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iMfs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iMfs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 424w, https://substackcdn.com/image/fetch/$s_!iMfs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 848w, https://substackcdn.com/image/fetch/$s_!iMfs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 1272w, https://substackcdn.com/image/fetch/$s_!iMfs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iMfs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png" width="1024" height="348" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:348,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iMfs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 424w, https://substackcdn.com/image/fetch/$s_!iMfs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 848w, https://substackcdn.com/image/fetch/$s_!iMfs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 1272w, https://substackcdn.com/image/fetch/$s_!iMfs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbce53e3-c77e-43a6-b0f2-74bdd1aef7f7_1024x348.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Power draw graph during a dishwasher cycle</figcaption></figure></div><div><hr></div><h2><strong>Dishwasher Logic</strong></h2><h3><strong>&#9654;&#65039; When it Starts</strong></h3><ul><li><p>Power rises <strong>above 5W for 1 minute</strong></p></li><li><p>Status flips from <strong>Off &#8594; Running</strong></p></li></ul><h3><strong>&#9209;&#65039; When it Finishes</strong></h3><ul><li><p>Power stays <strong>below 5W for 5 minutes</strong></p></li><li><p>Status flips <strong>Running &#8594; Done</strong></p></li><li><p>A green indicator on our AWTRIX Kitchen display turns on, a message is displayed and a quick tone is played.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1g1V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1g1V!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!1g1V!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!1g1V!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!1g1V!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1g1V!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif" width="1052" height="260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!1g1V!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!1g1V!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!1g1V!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!1g1V!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F333d064f-55df-4ea3-a441-17db426fb366_1052x260.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3><strong>&#9989; Acknowledgement</strong></h3><ul><li><p>Zigbee tilt sensor on the dishwasher door is at 90 degrees for 5 minutes</p></li><li><p>Status moves <strong>Done &#8594; Off</strong></p></li><li><p>Indicator light turns off.</p></li></ul><div><hr></div><h2><strong>Dryer Logic</strong></h2><p>Dryers are less subtle, so they get different thresholds.</p><h3><strong>&#9654;&#65039; When it Starts</strong></h3><ul><li><p>Power <strong>above 40W for 1 minute</strong></p></li><li><p>Status flips from <strong>Off &#8594; Running</strong></p></li></ul><h3><strong>&#9209;&#65039; When it Finishes</strong></h3><ul><li><p>Power stays <strong>below 50W for 5 minutes</strong></p></li><li><p>Status flips <strong>Running &#8594; Done</strong></p></li><li><p>A cyan indicator on our AWTRIX Kitchen display turns on, a message is displayed and a quick tone is played.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p-fM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p-fM!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!p-fM!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!p-fM!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!p-fM!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p-fM!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif" width="1052" height="260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de853c64-def1-4d56-abde-d716e211268f_1052x260.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!p-fM!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!p-fM!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!p-fM!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!p-fM!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde853c64-def1-4d56-abde-d716e211268f_1052x260.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3><strong>&#9989; When It&#8217;s Acknowledged</strong></h3><ul><li><p>Clear button located in the laundry closet is pushed</p></li><li><p>Status moves <strong>Done &#8594; Off</strong></p></li><li><p>Indicator light turns off</p></li></ul><p>I&#8217;m only monitoring a single leg of the dryer&#8217;s power. The first leg I tried would drop to 0W during cool-down, which caused the notification to fire early. This lead me to believe the drum motor and controls are only powered on the other leg. Moving the CT over made sure the alert only triggers when the dryer is actually finished.</p><div><hr></div><h2><strong>Washer Logic</strong></h2><p>While working on this project, I found that washers fluctuate wildly. Spin cycles, fills and seemingly random pauses. Our new front load washer is a bit less dramatic since there are no pulses from an agitator.</p><p>Additionally, we have a small peltier dehumidifier and the Dyson vacuum charger in the laundry closet which shares a circuit with the washer. I just needed to tune the threshold to account for the power draw of those devices.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9Zv_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9Zv_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 424w, https://substackcdn.com/image/fetch/$s_!9Zv_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 848w, https://substackcdn.com/image/fetch/$s_!9Zv_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 1272w, https://substackcdn.com/image/fetch/$s_!9Zv_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9Zv_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png" width="1024" height="348" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:348,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!9Zv_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 424w, https://substackcdn.com/image/fetch/$s_!9Zv_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 848w, https://substackcdn.com/image/fetch/$s_!9Zv_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 1272w, https://substackcdn.com/image/fetch/$s_!9Zv_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361e0900-63bc-4b8d-861e-cdfd25dd8526_1024x348.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Power draw graph during a washer cycle</figcaption></figure></div><h3><strong>&#9654;&#65039; When it Starts</strong></h3><ul><li><p>Power <strong>above 80W for 1 minute</strong></p></li><li><p>Status flips from <strong>Off &#8594; Running</strong></p></li></ul><h3><strong>&#9209;&#65039; When it Finishes</strong></h3><ul><li><p>Power <strong>below 80W for 5 minutes</strong></p></li><li><p>Status &#8594; <strong>Done</strong></p></li><li><p>A cyan indicator on our AWTRIX Kitchen display turns on, a message is displayed and a quick tone is played.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uJs-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uJs-!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!uJs-!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!uJs-!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!uJs-!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uJs-!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif" width="1052" height="260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!uJs-!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!uJs-!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!uJs-!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!uJs-!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35594b7-1717-4ade-a8ab-97b2a32abbe4_1052x260.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3><strong>&#9989; When It&#8217;s Acknowledged</strong></h3><ul><li><p>Clear button located in the laundry closet is pushed</p></li><li><p>Status moves <strong>Done &#8594; Off</strong></p></li><li><p>Indicator light turns off</p></li></ul><div><hr></div><h2>Just One Laundry Button?</h2><p>I didn&#8217;t see a need for separate reset buttons for the washer and dryer. Instead, a single button handles both. When pressed, it only resets appliances that are currently marked as <strong>Done</strong>, returning them to <strong>Off</strong>.</p><p>For example, if the washer is still running but the dryer has finished and been emptied, pressing the button will only reset the dryer. If <em>both</em> appliances are marked <strong>Done</strong>, they&#8217;ll both be reset&#8212;so yes, that&#8217;s your cue to empty both.</p><div><hr></div><h2><strong>Notifications That Exist in the Real World</strong></h2><p>We&#8217;re all pretty desensitized to push notifications and text messages. So to ensure it gets our attention in a somewhat subtle way, I use the following:</p><ul><li><p>Indicator lights on the AWTRIX Display in the Kitchen</p></li><li><p><strong>Audible alerts</strong> using RTTTL tones</p></li></ul><div><hr></div><h2><strong>Why This Works So Well</strong></h2><p>&#10004; No smart appliances required</p><p>&#10004; No cloud dependencies</p><p>&#10004; Highly configurable thresholds</p><p>&#10004; Scales easily to other appliances</p><div><hr></div><h2><strong>Final Thoughts</strong></h2><p>This is one of those automations that quietly becomes essential. Once it&#8217;s running, you stop thinking about it and your life adapts to it.</p><p>Next up?<br>I am considering adding a reminder with timing depending on the appliance. A reminder to empty the washer is far more time sensitive. Meanwhile, those dishes can hang out in the dishwasher until tomorrow</p>]]></content:encoded></item><item><title><![CDATA[Subtle Notifications: AWTRIX Display]]></title><description><![CDATA[The Quiet Game Changer]]></description><link>https://overengineered.jamesposs.com/p/subtle-notifications-awtrix-display</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/subtle-notifications-awtrix-display</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Wed, 04 Feb 2026 19:01:11 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/70f0d76b-cb4f-4a0e-a805-4f19ecc7bc12_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>ime-sensitive notifications from Home Assistant.</p><p>Things like:</p><ul><li><p><strong>A guest has arrived</strong></p></li><li><p><strong>The laundry is done</strong></p></li><li><p><strong>Someone is on the nice list</strong></p></li><li><p><strong>CO&#8322; levels are high, open a window</strong></p></li></ul><p>I wanted visibility without chaos. Awareness without anxiety. Information without my phone because I&#8217;m ignoring most of those notifications anyway.</p><div><hr></div><h2><strong>Why AWTRIX?</strong></h2><p>The moment I stumbled across the project, I ordered one immediately. This is my version of <em>&#8220;doing research&#8221;</em>.</p><p>Its <strong>compact size</strong>, <strong>clean pixel display</strong>, and <strong>ridiculous flexibility</strong> make it perfect for ambient notifications. Ours lives on top of the kitchen cabinet, clearly visible from the living room but not screaming for attention like a billboard in Times Square. (But I wouldn&#8217;t say no to a <a href="https://www.vice.com/en/article/vestaboard-and-vestboard-note/">Vesta Board</a> if one showed up at my door.)</p><p>When it&#8217;s idle, it simply shows the time. Calm. Respectful. Mind-your-business energy.</p><div><hr></div><h2><strong>How It Works</strong></h2><p>The AWTRIX is configured to subscribe to an <strong>MQTT</strong> broker that&#8217;s already running alongside Home Assistant. Whenever something worth knowing happens, Home Assistant publishes a message.</p><p>The flow looks like this:</p><blockquote><p>Thing happens &#8594; HA publishes MQTT message &#8594; AWTRIX sees it &#8594; AWTRIX displays it</p></blockquote><p>If I wanted to add <strong>more AWTRIX displays later</strong>, it would take almost no additional configuration. Additional displays would just need to be configured to subscribe to the same MQTT topic. Scales beautifully.</p><div><hr></div><h2><strong>The Sounds of Notifications</strong></h2><p>Many of the notifications include a short chime. The AWTRIX supports <strong>RTTTL tones only</strong>, which means&#8230;</p><p>Yes.</p><p>It sounds <strong>exactly like an old-school Nokia ringtone</strong>.</p><p>I didn&#8217;t plan this. I would have denied wanting this. But now? I love it.</p><p>It&#8217;s nostalgic, unmistakable, and somehow <em>less stressful</em> than modern notification sounds.</p><p>(Shoutout to Nokia for accidentally inventing the perfect home automation alert format. Miss you!)</p><div><hr></div><h2><strong>The Weird Nostalgia I Didn&#8217;t Expect</strong></h2><p>This setup unlocked a memory I didn&#8217;t know I still had.</p><p>When I was a kid, my dentist&#8217;s office had this <strong>non-verbal communication system</strong>. Whenever a patient arrived, was ready, or needed something, a staff member would press a combination of colored buttons.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cb13!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cb13!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cb13!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cb13!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cb13!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cb13!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg" width="472" height="239" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:239,&quot;width&quot;:472,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!cb13!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cb13!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cb13!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cb13!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1936c715-5d96-4801-b689-d426878ea870_472x239.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>An analog tone would play.</p><p>Colored lights would blink on a board somewhere.</p><p>I had <strong>no idea what any of it meant</strong>, but I was obsessed with trying to guess.</p><p>Now? Same vibe.</p><p>Whenever the AWTRIX makes its little tone, we both glance up, read the message, mentally file it away, and go back to what we were doing. No disruption, no discussion required.</p><p>Exactly like the hygienists did.</p><div><hr></div><h2><strong>Subtle, Informative, and Slightly Secretive</strong></h2><p>The display also uses <strong>small indicator lights</strong> to represent status at a glance. Laundry? Dishwasher? Guest Access?</p><p>Only <strong>we</strong> know what those colors mean.</p><p>To everyone else, it&#8217;s just a neat little glowing rectangle.</p><p>To us, it&#8217;s a shared language.</p><p>Which, apparently, completes my transformation into a dentist&#8217;s office from 1997. Don&#8217;t forget to get a prize from the toy chest on your way out!</p><div><hr></div><h2><strong>Dangerous Ideas (Proceed with Caution)</strong></h2><p>Here&#8217;s a thought that <em>definitely</em> won&#8217;t spiral:</p><p>If my husband is sick in bed&#8230;</p><p>I could set up a <strong>Zigbee button</strong> that sends a notification when pressed.</p><p>&#8220;Assistance requested.&#8221;</p><p>Displayed quietly.</p><p>With a Nokia chime.</p><p>&#8230;Okay.</p><p>We&#8217;ll see about that one. &#128516;</p><div><hr></div><h2><strong>Final Verdict</strong></h2><p>This has been a <strong>game changer</strong>.</p><p>The AWTRIX doesn&#8217;t interrupt. It doesn&#8217;t nag. It doesn&#8217;t demand attention.</p><p>It just&#8230; informs.</p><p>And somehow, that makes all the difference.</p><p>If you&#8217;re drowning in push notifications but still want to stay informed, this little pixel display might be exactly what you didn&#8217;t know you were missing. At least, while your at home...</p>]]></content:encoded></item><item><title><![CDATA[PiTunes]]></title><description><![CDATA[AirPlay for the Whole Home!]]></description><link>https://overengineered.jamesposs.com/p/pitunes</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/pitunes</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Wed, 28 Jan 2026 19:00:44 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b9010896-1e0e-405e-bb3a-30c6033afe2d_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When we moved in a few years ago, one of the quirks we inherited was a built-in Nuvo Simplese home audio system. But we already had a bunch of Sonos speakers scattered around.</p><p>The goal was simple: <strong>AirPlay everything! Music, AppleTV audio and party playlists to all speakers at once, Sonos and Nuvo alike.</strong></p><div><hr></div><h3><strong>Why Not Just Buy the Sonos Amp?</strong></h3><p>Sonos sells an amp that would&#8217;ve solved this in, like, ten minutes. But&#8230; Sonos pricing. It would have sounded great, I&#8217;m sure, but the project wasn&#8217;t exactly didn&#8217;t demand the premium route.</p><p>So instead, I dug out a Raspberry Pi gathering dust, plus a 3.5 mm &#8594; RCA cable. This led me down a rabbit hole I now affectionately call <strong>PiTunes</strong>.</p><div><hr></div><h2><strong>Shairport Sync</strong></h2><p>I stumbled on <strong>Shairport Sync</strong>, which is an open-source AirPlay audio player for Linux. Basically, it lets computers pretend to be AirPlay speakers. It supports:</p><ul><li><p><strong>AirPlay 1 &amp; AirPlay 2</strong></p></li><li><p>Sync&#8217;d multi-speaker playback</p></li><li><p>Various audio backends (ALSA, PulseAudio)</p></li><li><p>Metadata display and timing corrections</p></li></ul><p>&#10145;&#65039; Full project: <a href="https://github.com/mikebrady/shairport-sync">https://github.com/mikebrady/shairport-sync</a></p><p>I fired up Shairport Sync on the Pi and initially had it broadcasting as an <strong>AirPlay 1 device</strong>. Great, but that <strong>doesn&#8217;t</strong> support multi-speaker sync. The meant I couldn&#8217;t play the same audio in sync with my Sonos speakers.</p><p>I poked around and found out that multi-speaker playback is only available for AirPlay 2 devices. Luckily, Shairport Sync <strong>does</strong> have AirPlay 2 support, and once enabled, PiTunes showed up as an AirPlay 2 target. That meant I could:</p><p>&#10004;&#65039; Select PiTunes + all Sonos speakers</p><p>&#10004;&#65039; Play music everywhere in sync</p><p>&#10004;&#65039; Not have echos with timing mismatches</p><p>Magic!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kqnb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kqnb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kqnb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kqnb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kqnb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kqnb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg" width="204" height="357.6986301369863" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:584,&quot;resizeWidth&quot;:204,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!kqnb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kqnb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kqnb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kqnb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ce0bd47-48c6-47d0-b1ac-7b4f9042e7f8_584x1024.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2><strong>Volume Woes... Because Why Would It Be Easy?</strong></h2><p>Turns out the Raspberry Pi&#8217;s built-in audio output is&#8230; modest. Probably giving the same power as a walkman, it needs to be fed into something that amps the signal. The Nuvo system does amplify it, but it wasn&#8217;t enough, especially to drown out my singing in the shower.</p><p>Solution: I added a small headphone preamp (20 dB gain) between the Pi and the Nuvo input. Audio became loud enough and the Pi&#8217;s output can be turned down for cleaner headroom.</p><p>But here&#8217;s the twist: over time, the volume started drifting lower, even with the preamp. Reboots would reset the Pi&#8217;s mixer, and ALSA settings wouldn&#8217;t always stick. After some wrestling with alsamixer and persistent config files, it&#8217;s <em>mostly</em> stable. Occasionally a reboot still requires a quick manual volume check.</p><p>Because the Pi is plugged into a UPS, reboots are rare. So I&#8217;ve let this one sit for now. That&#8217;s a problem for future me.</p><div><hr></div><h2><strong>Is the Nuvo System Dying?</strong></h2><p>I have noticed the home speakers sound <em>slightly quieter</em> than before, even with the same PiTunes volume settings.</p><p>My current theory is that the Nuvo amp is maybe&#8230; fading? Aging electronics do that. I haven&#8217;t run any formal tests yet, but it&#8217;s on the to-do list after I finish ~30 other half-baked projects.</p><p>For now, the system works well enough, our place has synced audio throughout, and that&#8217;s good enough for us.</p><div><hr></div><h2><strong>Future Adventures: Paging with SIP</strong></h2><p>At one point I was working on a SIP client on the Pi that would be used to auto-answering and auto-broadcasting into the system for <strong>paging</strong>.</p><p>That experiment deserves its own post. Stay tuned for another post that I will probably call.... PiPage!</p><div><hr></div><h2><strong>TL;DR</strong></h2><ul><li><p>Built a Raspberry Pi&#8211;powered AirPlay 2 target with <strong>Shairport Sync</strong></p></li><li><p>Integrated it with an old Nuvo system via a preamp</p></li><li><p>Syncs with Sonos speakers for whole-home audio</p></li><li><p>Volume quirks solved (mostly)</p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://overengineered.jamesposs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Over Engineered by James! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Callbox Concierge]]></title><description><![CDATA[Opens the door so you don't have to!]]></description><link>https://overengineered.jamesposs.com/p/callbox-concierge</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/callbox-concierge</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Wed, 21 Jan 2026 19:01:11 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d8aa8186-559e-494d-a4b3-95a8f4fdc2db_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you live in a building with a call box, you probably know the routine...</p><blockquote><p>You&#8217;re expecting someone<br>You miss the call box call<br>Your guest is left waiting</p></blockquote><p>I&#8217;ve lived in many places that have had callboxes and it&#8217;s always been just a little annoying:</p><ul><li><p>We had to answer every call box call to let a visitor in and most of the time we didn&#8217;t know which of us the visitor was going to call</p></li><li><p>Hosting a party? Don&#8217;t loose track of your phone, otherwise someone will be stranded</p></li><li><p>We occasionally left our phones <strong>and</strong> key fob inside, locking us out of the building until we could follow a neighbor inside</p></li></ul><p>So naturally, instead of accepting this as &#8220;how buildings work&#8221; or forcing myself to remember my phone and/or key fob, I built <strong>Callbox Concierge</strong>.</p><div><hr></div><h2>How it started&#8230;</h2><p>My building&#8217;s call box has an entry for both me and my husband. Normally, each of these go straight to our respective cell phones.</p><p>I asked the property manager to change my number to a <strong>dedicated phone number</strong> that routes to my <strong>FreePBX server </strong>instead.</p><p>I was nervous at first, but was feeling better knowing that the number associated with my husband&#8217;s name is still his actual cell phone number. So if my plan didn&#8217;t work out, we could at least have that until I could switch it back.</p><div><hr></div><h2>Version 1: Just for Us</h2><p>When a call comes in, FreePBX does the following:</p><ol><li><p><strong>Inbound route checks caller ID</strong></p><ul><li><p>If it matches one of the known call box numbers in my building, it&#8217;s sent to a special dial plan.</p></li></ul></li><li><p><strong>The dial plan checks Home Assistant</strong></p><ul><li><p>If you&#8217;re new to my life, I run Home Assistant for automation.</p></li><li><p>There&#8217;s a virtual switch called <strong>Guest Access</strong>.</p></li><li><p>This switch can be toggled:</p><ul><li><p>From Apple Home</p></li><li><p>From a physical button on our fridge (yes, really)</p></li></ul></li></ul></li></ol><h4><strong>If Guest Access is ON</strong></h4><ul><li><p>The system immediately plays the sound of a <strong>&#8220;9&#8221; button press</strong></p></li><li><p>That&#8217;s the unlock key for our building</p></li><li><p>Door opens, no interaction required</p></li></ul><h4><strong>If Guest Access is OFF</strong></h4><ul><li><p>The caller hears a prompt:</p><ul><li><p>Enter an access code <strong>or</strong></p></li><li><p>Press <strong>0</strong> if you don&#8217;t have one (for the unexpected guest or delivery driver)</p></li></ul></li></ul><h4><strong>Outcomes:</strong></h4><ul><li><p><strong>Valid access code</strong> &#8594; unlock key plays &#8594; door opens</p></li><li><p><strong>Press 0</strong> &#8594; call forwards to a ring group:</p><ul><li><p>Both of our cell phones</p></li><li><p>Desk IP phones (who doesn&#8217;t love a corded phone?)</p></li></ul></li></ul><h4><strong>Notifications</strong></h4><p>Any time someone is granted access, whether by code or Guest Access, we get:</p><ul><li><p>A visual notification on a display in our kitchen</p></li><li><p>A paging announcement over the various IP phones</p></li><li><p>A text message heads-up</p></li></ul><p>At this point, we were both sold.</p><p>We barely use access codes anymore. If we&#8217;re expecting someone, we just turn Guest Access on.</p><p>I honestly can&#8217;t imagine <em>not</em> having this now.</p><div><hr></div><h2>&#8220;Other People Might Want This&#8230;&#8221;</h2><p>As you can imagine, the functionality is sometimes a topic of conversation when people come over. Those who saw the value expressed an interest in having something like this.</p><p>The first version, however, was very much <strong>built for us</strong>, not others.</p><p>So I started thinking... Phone numbers from my provider are cheap. Like, <em>shockingly</em> cheap.</p><p>So I did what any reasonable person would do:</p><p>I rebuilt it from scratch&#8230;</p><div><hr></div><h2>Version 2: Callbox Concierge</h2><p>The new model is built around <strong>subscribers</strong>.</p><p>Each subscriber gets their own dedicated DID (phone number) that they give to their property manager. I call this number their &#8220;RainbowLink Number&#8221;.</p><h3><strong>Incoming Call Flow</strong></h3><p>When a call comes in:</p><ol><li><p>FreePBX identifies the DID as belonging to a subscriber</p></li><li><p>The dial plan matches the DID to a subscriber record in the database</p></li><li><p>It checks the subscriber&#8217;s current <strong>Concierge Mode</strong>:</p><ul><li><p><strong>Allow All</strong></p></li><li><p><strong>Code / Normal</strong></p></li><li><p><strong>Forward</strong></p></li></ul></li></ol><h3><strong>Concierge Modes Explained</strong></h3><h4><strong>Allow All (Guest Access)</strong></h4><ul><li><p>Plays the subscriber&#8217;s configured unlock key (usually &#8220;9&#8221;)</p></li><li><p>Door opens immediately</p></li></ul><h4><strong>Code / Normal Mode</strong></h4><ul><li><p>Caller is prompted for an access code or to press 0</p></li><li><p><strong>Valid code</strong> &#8594; unlock key plays</p></li><li><p><strong>Press 0</strong> &#8594; call forwards to the subscriber&#8217;s configured phone number</p><ul><li><p>They can answer, talk, and press the unlock key themselves</p></li></ul></li></ul><h4><strong>Forward Mode</strong></h4><ul><li><p>Concierge is bypassed entirely</p></li><li><p>Call forwards straight to the subscriber&#8217;s phone</p></li></ul><div><hr></div><h2><strong>Self-Service</strong></h2><p>Subscribers can manage their system in <strong>two different ways</strong>.</p><h3><strong>1. Dial-In Management</strong></h3><ul><li><p>Call your RainbowLink Number <em>from your registered cell phone number</em></p></li><li><p>Caller ID is verified</p></li><li><p>Enter a PIN (just in case someone out there is doing Caller ID spoofing)</p></li><li><p>You&#8217;re dropped into an admin menu where you can:</p><ul><li><p>Change the current mode</p></li><li><p>List access codes</p></li><li><p>Add or remove codes</p></li></ul></li></ul><h3><strong>2. Concierge Portal (Web)</strong></h3><p>Manage:</p><ul><li><p>Current mode</p></li><li><p>Access codes</p></li><li><p>Subscriber details</p></li></ul><p>Log in using your registered email address</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EX6l!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EX6l!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 424w, https://substackcdn.com/image/fetch/$s_!EX6l!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 848w, https://substackcdn.com/image/fetch/$s_!EX6l!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 1272w, https://substackcdn.com/image/fetch/$s_!EX6l!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EX6l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png" width="257" height="314.825" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:980,&quot;width&quot;:800,&quot;resizeWidth&quot;:257,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!EX6l!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 424w, https://substackcdn.com/image/fetch/$s_!EX6l!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 848w, https://substackcdn.com/image/fetch/$s_!EX6l!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 1272w, https://substackcdn.com/image/fetch/$s_!EX6l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed01d3d-a34d-43d1-a412-b97b428ee333_800x980.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2><strong>Building the Portal</strong></h2><p>The original Concierge system was built with:</p><ul><li><p>MariaDB</p></li><li><p>Python</p></li><li><p>PHP AGI (the &#8220;brain&#8221;)</p></li><li><p>Asterisk dial plans</p></li></ul><p>That handled dial-in management just fine.</p><p>But of course&#8230; that wasn&#8217;t enough.</p><h3><strong>Concierge Portal</strong></h3><p>I built a full web interface using <strong>Laravel</strong>.</p><p>This was my first time working with Laravel, and while there <em>was</em> a learning curve, I was pleasantly surprised by how efficient and well-structured it is.</p><p>That said:</p><ul><li><p>I am still wrestling with CSS</p></li><li><p>Overrides don&#8217;t always behave how I expect</p></li></ul><p>It looks <em>okay</em> right now. There is absolutely room for improvement. That&#8217;s a problem for another day.</p><p>Currently:</p><ul><li><p>One user per subscriber, but this would be easy to expand with the current structure</p></li><li><p>Google-only authentication (no shared passwords)</p></li><li><p>Multiple admin phone numbers per subscriber are already supported</p></li></ul><p>Multi-user portal access is on the roadmap.</p><div><hr></div><h2><strong>The Admin Side</strong></h2><p>Once subscribers existed, managing them cleanly became essential. I was not about to be over here manually adjusting things in the database.</p><p>Anyway, that lead me to building:</p><ul><li><p>A separate internal <strong>Admin Portal</strong>, just for me</p></li><li><p>Used for:</p><ul><li><p>On-boarding</p></li><li><p>Off-boarding</p></li><li><p>Managing subscribers</p></li></ul></li></ul><p>At this point, Concierge became something I could easily manage for as many subscribers as I need.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TCoi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TCoi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 424w, https://substackcdn.com/image/fetch/$s_!TCoi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 848w, https://substackcdn.com/image/fetch/$s_!TCoi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!TCoi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TCoi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png" width="198" height="492.11650485436894" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:412,&quot;resizeWidth&quot;:198,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!TCoi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 424w, https://substackcdn.com/image/fetch/$s_!TCoi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 848w, https://substackcdn.com/image/fetch/$s_!TCoi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!TCoi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2716daa7-d40e-4984-a87e-ef8a9ada1f44_412x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2><strong>&#8220;But What If the Server Dies?&#8221;</strong></h2><p>Great question, and believe me... I&#8217;ve gone through the scenarios in my head...</p><p>Could I build but a robust, multi-node, multi-site platform to drastically reduce the downtime risk? Absolutely. But I&#8217;m not at the point where full high availability makes sense yet, but:</p><ul><li><p>My PBX already has a <strong>warm spare</strong> on a VPS</p></li><li><p>It can handle basic call functionality if my primary site is down</p></li><li><p>The web portal wouldn&#8217;t be available, but calls into the admin menu would still work</p></li></ul><h3><strong>Last-Resort Fallback</strong></h3><p>My phone provider allows a <strong>failover forwarding number</strong> if <em>both</em> PBXs are unreachable.</p><p>Right now, I configure this to forward calls directly to the subscriber&#8217;s cell phone, which should prevent almost all full-service interruptions.</p><div><hr></div><h2><strong>Final Thoughts</strong></h2><p>Callbox Concierge started as a way to stop answering the same phone call over and over.</p><p>It turned into:</p><ul><li><p>A custom dial plan</p></li><li><p>A subscriber platform</p></li><li><p>A web portal</p></li><li><p>An admin system</p></li><li><p>And a fridge button (still my favorite and the most used part)</p></li></ul><p>It works beautifully for us and now it&#8217;s built in a way that others can use too.</p><p>More to come!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://overengineered.jamesposs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Over Engineered by James! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The North Pole Department of List Verification Hotline]]></title><description><![CDATA[An overview of the Christmas Hotline I created to determine where callers stand on Santa's list.]]></description><link>https://overengineered.jamesposs.com/p/the-north-pole-department-of-list</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/the-north-pole-department-of-list</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Thu, 15 Jan 2026 19:51:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a2cf5ba6-2996-40c7-8992-3ce015ef0106_1427x924.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every year around the holidays, there&#8217;s a certain kind of magic that only exists for a very short window of time. I found a way to bottle some of that in a way that involved phones, automation, and just enough whimsy to justify the effort.</p><p>The <strong>North Pole Department of List Verification Hotline</strong> was born!</p><blockquote><p>You call in.<br>You wait.<br>Clementine Bell consults the official records.<br>And you find out where you stand.<br>Nice. Naughty. Or&#8230; <em>Undetermined</em>.</p></blockquote><div><hr></div><h2><strong>The Inspiration</strong></h2><p>The idea came from a North Pole communicator that both my sister and brother had when their kids were younger. It was a little device that let them &#8220;call&#8221; the North Pole and hear messages from Clementine Bell herself.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IeMF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IeMF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 424w, https://substackcdn.com/image/fetch/$s_!IeMF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 848w, https://substackcdn.com/image/fetch/$s_!IeMF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 1272w, https://substackcdn.com/image/fetch/$s_!IeMF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IeMF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png" width="134" height="208.915611814346" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a550584-47cd-4877-9dac-4cf731a72349_474x739.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:739,&quot;width&quot;:474,&quot;resizeWidth&quot;:134,&quot;bytes&quot;:292791,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!IeMF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 424w, https://substackcdn.com/image/fetch/$s_!IeMF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 848w, https://substackcdn.com/image/fetch/$s_!IeMF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 1272w, https://substackcdn.com/image/fetch/$s_!IeMF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a550584-47cd-4877-9dac-4cf731a72349_474x739.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>This hotline was my attempt to recreate that feeling. Something fun, slightly mysterious, and charmingly over-the-top just in time for Christmas.</p><div><hr></div><h2><strong>How the Hotline Works</strong></h2><p>When you dial the hotline, the call lands in a dedicated dial plan. From there, the experience is carefully paced:</p><ul><li><p>The phone rings briefly (otherwise it answers right away and you might miss something!)</p></li><li><p>The call is answered</p></li><li><p>Clementine introduces herself</p></li><li><p>She starts looking you up to see your status</p></li></ul><p>Behind the scenes, that look up is powered by a little randomness:</p><ul><li><p>A random &#8220;look up&#8221; audio clip plays (one of many)</p></li><li><p>A random number between <strong>1 and 20</strong> is chosen</p></li><li><p>That number determines your fate:</p><ul><li><p><strong>1&#8211;10</strong> &#8594; Nice (50%)</p></li><li><p><strong>11&#8211;15</strong> &#8594; Undetermined (25%)</p></li><li><p><strong>16&#8211;20</strong> &#8594; Naughty (25%)</p></li></ul></li></ul><p>So yes&#8230; statistically speaking, it <em>is</em> easier to be Nice. Clementine believes in hot coco and optimism.</p><div><hr></div><h2><strong>Avoiding Holiday Limbo</strong></h2><p>Early on, I realized there was a flaw:</p><p>No one wants to call twice and get <em>Undetermined</em> twice in a row and callers that did didn&#8217;t call back. I&#8217;d call that a poor experience.</p><p>So in a later version, I added logging for each call, noting their phone number and what their result was. With that in place, I built logic to inspect the caller&#8217;s <strong>most recent result</strong> at the beginning of the call.</p><p>If your last call resulted in <strong>Undetermined</strong>, your next call is <em>forced</em> to be decisive and the odds are updated:</p><ul><li><p>50% chance for Nice</p></li><li><p>50% change for Naughty</p></li><li><p>No back-to-back ambiguity</p></li></ul><p>Clementine&#8217;s keyboard may be full of gingerbread crumbs, but she is not inefficient&#8230;</p><p>I actually wish I had started doing this much sooner because this added functionality allowed me to run reports and provide statistics on the outcomes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eE5F!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eE5F!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!eE5F!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!eE5F!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!eE5F!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eE5F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg" width="186" height="329.52249134948096" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:578,&quot;resizeWidth&quot;:186,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!eE5F!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!eE5F!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!eE5F!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!eE5F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd908dd72-cf5e-4495-aadc-3b61aecd291a_578x1024.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It seemed like I was making improvements almost every day after launch. (I even kept a change log!) With enhancements such as:</p><ul><li><p>Removing unnecessary keypresses</p></li><li><p>Tightening timing (including keeping most calls under 1 minute)</p></li><li><p>Improving audio pacing</p></li><li><p>Making outcomes feel fair but fun</p></li></ul><div><hr></div><h2><strong>Home Assistant Integration (Because I Had To)</strong></h2><p>Eventually, I wanted to keep tabs on what Clementine was declaring in real time.</p><ul><li><p>When a caller is declared <strong>Nice</strong> or <strong>Naughty</strong>:</p><ul><li><p>A Home Assistant text field called &#8220;last_decision&#8221; is updated as soon as it is determined.</p></li><li><p>A virtual button called &#8220;send_decision&#8221; is pressed right after Clementine finishes reading the decision.</p></li></ul></li><li><p><em>Undetermined</em> results are intentionally ignored&#8230; I only wanted to hear if someone got Naughty or Nice.</p></li></ul><p>A Home Assistant automation listens for that button press and sends the result to an <strong><a href="https://jamesposs.com/awtrix/">AWTRIX display</a></strong> in our kitchen, so we get a festive little announcement when Clementine reaches a verdict, complete with a monophonic chime of Jingle Bells.</p><p>It&#8217;s subtle. It&#8217;s unnecessary. It&#8217;s perfect.</p><p>I even brought the AWTRIX display along to our family&#8217;s Christmas Eve gathering, which was fun for us to watch as everyone called to check their status. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xWcN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xWcN!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!xWcN!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!xWcN!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!xWcN!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xWcN!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif" width="1052" height="260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!xWcN!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 424w, https://substackcdn.com/image/fetch/$s_!xWcN!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 848w, https://substackcdn.com/image/fetch/$s_!xWcN!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 1272w, https://substackcdn.com/image/fetch/$s_!xWcN!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed40f14-278b-405a-a6a0-d41d1bf38a57_1052x260.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><h2><strong>Writing the Voice of the North Pole</strong></h2><p>All of the prompts were written specifically for this project and recorded using <strong>Google&#8217;s Text-to-Speech</strong> voices.</p><p>It was surprisingly time-consuming, but also a lot of fun.</p><p>ChatGPT helped me get started with the scripts, especially in finding the right tone. Clementine needed to be authoritative, cheerful, and just official enough to feel real without breaking the illusion.</p><p>A few revisions later (and some aggressive silence trimming), Clementine sounded exactly how she should.</p><div><hr></div><h2><strong>Popular Demand</strong></h2><p>What started as a fun little seasonal project turned out to be&#8230; <em>very</em> popular.</p><p>So popular, in fact, that I had to move the hotline to a different VoIP service provider just to handle the number of concurrent incoming calls.</p><p>That was not a problem I expected, but I&#8217;ll happily take it.</p><div><hr></div><h2><strong>Final Thoughts</strong></h2><p>Obviously, the North Pole Department of List Verification Hotline was never meant to be serious.</p><p>It was meant to:</p><ul><li><p>Spark nostalgia</p></li><li><p>Make people smile</p></li><li><p>Add a little magic to December</p></li><li><p>Engage people using a slightly more analog technology</p></li><li><p>And, naturally, give me an excuse to build something ridiculous with FreePBX/Asterisk</p></li></ul><p>Mission accomplished.</p><p>If you were one of the 250+ people that called in, thank you! I will begin working on 2026 Clementine soon so she will be better then ever next season! Please let me know if you have any suggestions!!</p><p>And remember&#8230; if your status couldn&#8217;t be determined&#8230; call back!</p>]]></content:encoded></item><item><title><![CDATA[Breathing Data]]></title><description><![CDATA[My Slightly Obsessive Home Assistant Environmental Monitoring Setup]]></description><link>https://overengineered.jamesposs.com/p/breathing-data</link><guid isPermaLink="false">https://overengineered.jamesposs.com/p/breathing-data</guid><dc:creator><![CDATA[James]]></dc:creator><pubDate>Wed, 14 Jan 2026 02:42:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/5659fabb-a581-4f32-8250-5eda29a29b43_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Some people track steps.</p><p>Some track sleep.</p><p>I track <em>the vibes of the air in our home</em>.</p><p>This project started innocently enough: I wanted to understand how temperature and humidity varied across the space and how well (or poorly) the HVAC system was doing its job. Naturally, this escalated.</p><h2><strong>Phase 1: Temperature, Humidity and HVAC</strong></h2><p>I began with Zigbee temperature and humidity sensors placed all over the place:</p><ul><li><p>One in each room</p></li><li><p>One on the balcony for outdoor reference</p></li><li><p>One at the HVAC return</p></li><li><p>One directly on a supply vent</p></li></ul><p>All of this feeds neatly into <strong>Home Assistant</strong>, where I built a dashboard to visualize room-by-room temperatures <em>and</em> the HVAC delta between supply and return (inspired by my experience with commercial building automation systems).</p><p>This alone was enlightening:</p><ul><li><p>Rooms don&#8217;t heat or cool evenly (shocking, I know).</p></li><li><p>The HVAC delta tells me all about system performance.</p></li></ul><p>I checked this dashboard <em>constantly</em>&#8230; at least until the novelty wore off and it became &#8220;background knowledge.&#8221;</p><p>Obsessive? Absolutely.</p><p>Sustainable obsession? Apparently not.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CyVl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CyVl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 424w, https://substackcdn.com/image/fetch/$s_!CyVl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 848w, https://substackcdn.com/image/fetch/$s_!CyVl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 1272w, https://substackcdn.com/image/fetch/$s_!CyVl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CyVl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png" width="1024" height="525" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ac41964-c82a-400e-8284-623999a620f2_1024x525.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:525,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CyVl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 424w, https://substackcdn.com/image/fetch/$s_!CyVl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 848w, https://substackcdn.com/image/fetch/$s_!CyVl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 1272w, https://substackcdn.com/image/fetch/$s_!CyVl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac41964-c82a-400e-8284-623999a620f2_1024x525.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Phase 2: Enter the AirGradient (aka: The Point of No Return)</strong></h2><p>Just when I thought I was done, I added an <a href="https://www.airgradient.com/indoor/">AirGradient indoor air quality sensor</a>.</p><p>And wow. That escalated quickly.</p><p>Now I&#8217;m tracking:</p><ul><li><p>CO&#8322;</p></li><li><p>PM0.3, PM1.0, PM2.5, PM10</p></li><li><p>VOC Index</p></li><li><p>NOx Index</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JMtM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JMtM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 424w, https://substackcdn.com/image/fetch/$s_!JMtM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 848w, https://substackcdn.com/image/fetch/$s_!JMtM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 1272w, https://substackcdn.com/image/fetch/$s_!JMtM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JMtM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png" width="590" height="367.53434065934067" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:907,&quot;width&quot;:1456,&quot;resizeWidth&quot;:590,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!JMtM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 424w, https://substackcdn.com/image/fetch/$s_!JMtM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 848w, https://substackcdn.com/image/fetch/$s_!JMtM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 1272w, https://substackcdn.com/image/fetch/$s_!JMtM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30f03d09-3e29-41ea-b097-4499b27888b0_1480x922.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li></ul><h2><strong>What the Data Taught Me (Besides Humility)</strong></h2><p>The biggest takeaway? <strong>Indoor air circulation is&#8230; not great.</strong></p><p>CO&#8322; levels rise faster than you&#8217;d expect, especially with doors and windows closed. Elevated CO&#8322; is known to impact cognitive performance, and seeing it climb in real time is a powerful reminder that sometimes the smartest automation would be&#8230; opening a window.</p><p>Honestly, I think everyone should have a CO&#8322; monitor. Not to induce panic&#8230; but to gently say:</p><p>&#8220;Hey, maybe let the outside in for a minute.&#8221;</p><p>The particulate and gas sensors were equally revealing:</p><ul><li><p>Cooking spikes PM levels fast (especially frying).</p></li><li><p>Laundry and mopping have a noticeable VOC impact.</p></li><li><p>Candles are tiny pollution machines.</p></li><li><p>Leaving the door open while the Turkish restaurant nearby is cooking onions? Immediate confirmation. No notes needed.</p></li></ul><h2><strong>Mitigation</strong></h2><p>We do have a standalone air purifier, and it <em>absolutely</em> works. You can see particulates drop in near real time once it detects the pollutants and the fan turns up. That said, the data made me think about how many people don&#8217;t have these things..</p><ul><li><p>Air quality monitoring</p></li><li><p>Active purification</p></li><li><p>Or even awareness that indoor air quality can vary this much</p></li></ul><p>You can&#8217;t fix what you can&#8217;t see. But I guess seeing <em>everything</em> is not always great either.</p><h2><strong>Final Thoughts</strong></h2><p>Is this setup overkill?</p><p>Yes.</p><p>Do I regret it?</p><p>Not at all.</p><p>The combination of distributed temperature sensors and the AirGradient has turned my home into a living, breathing dataset. One that gently nudges better habits, including a subtle <a href="https://jamesposs.com/awtrix/">AWTRIX</a> notification when CO&#8322; levels get too high.</p><p>And if nothing else, it&#8217;s deeply satisfying to say:</p><p>&#8220;These onions aren&#8217;t just strong&#8230; they&#8217;re measurable.&#8221;</p>]]></content:encoded></item></channel></rss>