{"id":3993,"date":"2024-12-19T09:24:29","date_gmt":"2024-12-19T14:24:29","guid":{"rendered":"https:\/\/jimsghost.place\/?p=3993"},"modified":"2024-12-27T18:08:55","modified_gmt":"2024-12-27T23:08:55","slug":"house-is-talking-en","status":"publish","type":"post","link":"https:\/\/jimsghost.place\/?p=3993","title":{"rendered":"Silence! House is talking!"},"content":{"rendered":"\n<p>In the process of expanding my smart home setup, a few of the voices in my head decided to relocate somewhere more comfortable.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Everyone has their own takes on what \u201csmart home\u201d really means. Some picture it as a kind of living, thinking creature you can chat up or otherwise hang out with. Me, though? I\u2019m going completely the other way: I figure the smarter the home, the less I have to fuss with it. What\u2019s the point of a smart home if it needs a prompt just to flip on the lights? C\u2019mon, I can handle a light switch on my own \u2014 doesn\u2019t take a genius. In my book, a truly smart home should be as subtle as possible, quietly running the show without giving the orderlies any reason to drop by.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>For &#8220;communication and interaction&#8221; at home, I\u2019m all set with my wife, my dog, and my cat. The last thing I need is some <a href=\"\/?tag=ktchsrvbox-en&amp;order=asc\">server hanging overhead<\/a>, driving me nuts and demanding my attention.<\/p>\n<\/blockquote>\n\n\n\n<p>Still, there are moments when a smart home should speak up. Sure, it\u2019s obvious when the smoke alarm goes off. But even something like a sprinkler warning \u2014 letting you know before it soaks you head to toe \u2014 can make life easier.<\/p>\n\n\n\n<p>So at some point, it became necessary to give the house some simple audio alerts. After all, we\u2019re not glued to its graphical control console 24\/7, keeping an eye on every single event. We might miss something important otherwise.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>So, bottom line\u2026 The project\u2019s goal is to set up a bunch of simple devices with speakers and mics that can play media content at the level of basic voice announcements and, when necessary, handle simple voice commands. Absolutely not a \u201csound system\u201d \u2014 we already have one of those. I\u2019m talking about the simplest  speaker-horns, like the ones you\u2019d find at a train station. As bare-bones as possible. And they\u2019d be spread all over every single room in the house:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"366\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3-640x366.webp\" alt=\"\" class=\"wp-image-3836\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3-640x366.webp 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3-1024x585.webp 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3-768x439.webp 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3-1536x878.webp 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/b56c4a9d-399f-478a-97b8-184eb6719ff3.webp 1792w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>The advantages of having a cluster of devices instead of just one big setup:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Say goodbye to blasting one speaker at full volume just so it\u2019s loud enough for someone in the backyard to hear. With distributed speakers, every space gets its own tailored sound.<\/li>\n\n\n\n<li>Each resident can fine-tune their personal speaker \u2014 voice, volume, and all that \u2014 just the way they want it.<\/li>\n\n\n\n<li>Selective targeting. For example, the heads-up that the lawn sprinklers are about to turn on really only matters to whoever\u2019s out in the yard, not the person snoozing peacefully in their bedroom.<\/li>\n\n\n\n<li>Easy intercom connections between rooms. Let\u2019s face it, we\u2019re not all surgically attached to our cell phones, and trying to holler from the garage to the kitchen for wife\u2019s attention doesn\u2019t always work so well.<\/li>\n\n\n\n<li>Compactness. Obviously, a small low-power alert device takes up far less space than a single beefy PA system with a massive amp and speakers.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>You could pick up some simple, not-too-pricey wireless speakers on Amazon or some other Alibaba-like site. They come in all shapes and sizes. Some can even be wrangled into working with Home Assistant \u2014 if you\u2019re lucky. But I decided to take a more interesting and reliable route: build my own wireless speaker as a smart home component. Nothing too outlandish. It\u2019s what I\u2019d call an \u201cearly-to-mid-level\u201d project in terms of complexity. It\u2019ll be cheaper, and I won\u2019t have to deal with any compatibility drama.<\/p>\n\n\n\n<p>I started by hooking up an ESP32 to a DAC board based on the UDA1334A, which speaks I2S. Then I added a PAM8403-based amplifier. After that, I connected a pair of 2-inch, 4\u03a9-3W speakers:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb.png\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"419\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-640x419.png\" alt=\"\" class=\"wp-image-4141\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-640x419.png 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1024x670.png 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-768x503.png 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1536x1006.png 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb.png 1845w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>And it worked like a charm. The DAC module\u2019s output goes to the amp either through a built-in 3mm jack (option #2) or via the onboard analog output pins (option #1). All the modules in this example are chosen so they can run off the existing 5V supply in the system. That way, you don\u2019t have to rig up any extra step-up or step-down converters.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Of course, nothing\u2019s stopping you from tossing in a truck-sized Class-D amp, powering it straight from the nearest nuclear reactor, and blasting a city-wide announcement that there\u2019s been a spike in methane level in your home\u2019s bathroom atmosphere.<\/p>\n<\/blockquote>\n\n\n\n<p>Pre-built firmware for this kind of setup is easy enough to find online, whether you\u2019re running something like ESPHome or going for a standalone Arduino-style project. Just search by module names or I2S in the context of the ESP32. They generally all rely on standard libraries and some rock-solid, bare-bones code you can fit on a Post-it note. Here\u2019s one of my favorite DIY YouTubers \u2014 he goes to absurd lengths in his \u201ctutorial\u201d videos \u2014 who covered this topic in excruciating detail ages ago:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:15%\"><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:70%\">\n<figure class=\"wp-block-embed aligncenter is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"ESP32 Sound - Working with I2S\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/m-MPBjScNRk?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:15%\"><\/div>\n<\/div>\n\n\n\n<p>I doubt I could add anything more to that.<\/p>\n\n\n\n<p>The speaker setup I mentioned above works and plugs right into <a href=\"https:\/\/www.home-assistant.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">HA<\/a> + <a href=\"https:\/\/esphome.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESPHome<\/a> right out of the gate. Literally, you can just copy and paste snippets <a href=\"https:\/\/esphome.io\/components\/media_player\/\" target=\"_blank\" rel=\"noreferrer noopener\">from the documentation<\/a> as is. It\u2019s that straightforward.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>I was already thinking about how to quickly bundle all this into a single enclosure, when I randomly stumbled upon the exact same setup, but in the form of a single board called the ESP32-A1S Audio Kit:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71X2hL9CMWL._AC_SL1500_.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"491\" data-id=\"3839\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71X2hL9CMWL._AC_SL1500_-640x491.jpg\" alt=\"\" class=\"wp-image-3839\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71X2hL9CMWL._AC_SL1500_-640x491.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71X2hL9CMWL._AC_SL1500_-1024x786.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71X2hL9CMWL._AC_SL1500_-768x590.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71X2hL9CMWL._AC_SL1500_.jpg 1240w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"640\" data-id=\"3841\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_-640x640.jpg\" alt=\"\" class=\"wp-image-3841\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_-640x640.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_-1024x1024.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_-150x150.jpg 150w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_-768x768.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71U48N9X3dL._AC_SL1500_.jpg 1500w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"640\" data-id=\"3840\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_-640x640.jpg\" alt=\"\" class=\"wp-image-3840\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_-640x640.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_-1024x1024.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_-150x150.jpg 150w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_-768x768.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/71vhU2nOpAL._AC_SL1500_.jpg 1500w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>It\u2019s got everything right there: an ESP32, DAC, amplifier, control buttons, microphones, speaker outputs, line-in, line-out, and even microSD support for local media. In short, everything you need. Its cost ended up being about one and a half times more expensive than piecing together the same thing from separate components. But the beauty of it is that with this board, you don\u2019t have to do a darn thing. Literally nothing! Just flash the firmware and build the enclosure. And since I would\u2019ve had to build an enclosure one way or another, I decided to scrap the initial combo of modules in favor of the single ESP32-A1S Audio Kit.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Anyone looking to follow my lead can choose either path. The end result will be exactly the same, except for one tiny detail: in my first setup, I didn\u2019t have microphones yet. I just hadn\u2019t gotten around to that part of the project before I came across the ready-made A1S Audio Kit, which included them. But adding a microphone module to your parts collection is trivial. So, as I said, the outcome is the same. It\u2019s just a matter of convenience (one board is easier to mount in a case than several), cost (the difference is literally just a few bucks), and time (since you have to wire the separate modules yourself).<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>In the end, the entire project boiled down to simply creating an enclosure. And I didn\u2019t have to rack my brains over that, either.<\/p>\n\n\n\n<p>No fancy artistry or technical trickery was required, so I just went with a \u201cpoint the cursor and see where it goes\u201d approach:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"366\" data-id=\"3829\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01-640x366.jpg\" alt=\"\" class=\"wp-image-3829\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01-640x366.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01-1024x586.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01-768x440.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01-1536x879.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_01.jpg 1677w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"366\" data-id=\"3828\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02-640x366.jpg\" alt=\"\" class=\"wp-image-3828\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02-640x366.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02-1024x586.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02-768x440.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02-1536x879.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_02.jpg 1677w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>Mainly, the enclosure was designed to allow for at least some spacing for the speakers and to accommodate their size. So, inside it\u2019s basically just a whole lot of empty space:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"366\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05-640x366.jpg\" alt=\"\" class=\"wp-image-3832\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05-640x366.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05-1024x586.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05-768x440.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05-1536x879.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_05.jpg 1677w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>Despite how simple the structure is, the number of little parts did pile up a bit:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"324\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04-640x324.jpg\" alt=\"\" class=\"wp-image-3830\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04-640x324.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04-1024x518.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04-768x389.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04-1536x778.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_04.jpg 1896w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Bottom half of the enclosure.<\/li>\n\n\n\n<li>Feet.<\/li>\n\n\n\n<li>A decorative faceplate \u2014 purely for aesthetics. Its presence or absence makes no difference to how the device works.<\/li>\n\n\n\n<li>Front panel.<\/li>\n\n\n\n<li>A protective mesh for the microphones.<\/li>\n\n\n\n<li>Control buttons.<\/li>\n\n\n\n<li>A control panel. In theory, it could have been one piece with that part of the enclosure, but then I\u2019d have to print it with support structures, which I fiercely hate for obvious reasons. It\u2019s much easier to print it separately and just glue it in place.<\/li>\n\n\n\n<li>Top half of the enclosure.<\/li>\n\n\n\n<li>The ESP32-A1S Audio Kit board.<\/li>\n\n\n\n<li>Speakers.<\/li>\n\n\n\n<li>The same as #7 above, but without holes for the buttons and mics. It\u2019s a separate element for the same reason as before.<\/li>\n<\/ol>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:15%\"><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:70%\"><div class=\"wp-block-embed-stl-embed-stl\" >\n<div id=\"stl-preview-56774a1d_6a35_46fc_a77c_dd638a56d879\" class=\"embed-stl-target embed-stl-size-md \">\n<img decoding=\"async\" src=\"https:\/\/jimsghost.place\/wp-content\/plugins\/embed-stl\/public\/img\/icon.svg\" class=\"embed-stl-cube-icon\">\n<\/div>\n<script>\ndocument.addEventListener(\"DOMContentLoaded\", function() {\nvar e = document.getElementById(\"stl-preview-56774a1d_6a35_46fc_a77c_dd638a56d879\"); var stlView_56774a1d_6a35_46fc_a77c_dd638a56d879 = new StlViewer(e, {\"models\":[{\"id\":0,\"filename\":\"https:\\\/\\\/jimsghost.place\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/Assembly.stl\",\"color\":\"#dadada\",\"display\":\"flat\"}],\"bg_color\":\"#b0bbcb\",\"auto_rotate\":false,\"grid\":false,\"allow_drag_and_drop\":false,\"send_no_model_click_event\":true});\nfunction stlView_56774a1d_6a35_46fc_a77c_dd638a56d879_recenter(id,evt,dist,ct) { if (ct != 11) return; v=stlView_56774a1d_6a35_46fc_a77c_dd638a56d879; c=v.get_camera_state(); c.position={...c.position, x:0, y:0, z:v.calc_z_for_auto_zoom()}; c.target={...c.target, x:0, y:0, z:0}; v.set_camera_state(c);};\nfunction stlView_56774a1d_6a35_46fc_a77c_dd638a56d879_orient() { v=stlView_56774a1d_6a35_46fc_a77c_dd638a56d879; m=v.models[0].mesh; m.rotation.x=-1.2043; m.rotation.y=-3.1416; m.rotation.z=-0.3840; m.scale.setScalar(0.8850); };\nwindow.addEventListener(\"resize\", function() { stlView_56774a1d_6a35_46fc_a77c_dd638a56d879_recenter(0,0,0,11); });\nstlView_56774a1d_6a35_46fc_a77c_dd638a56d879.set_on_model_mousedown(stlView_56774a1d_6a35_46fc_a77c_dd638a56d879_recenter);\nstlView_56774a1d_6a35_46fc_a77c_dd638a56d879.all_loaded_callback=stlView_56774a1d_6a35_46fc_a77c_dd638a56d879_orient;\n});\n<\/script>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:15%\"><\/div>\n<\/div>\n\n\n\n<p>As for the controls, honestly, they\u2019re not super necessary:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"366\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1-640x366.jpg\" alt=\"\" class=\"wp-image-4154\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1-640x366.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1-1024x586.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1-768x440.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1-1536x879.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-1.jpg 1677w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Mute\/Unmute<\/li>\n\n\n\n<li>Vol. &#8211;<\/li>\n\n\n\n<li>Vol. +<\/li>\n\n\n\n<li>Voice Assistant<\/li>\n<\/ol>\n\n\n\n<p>The first three volume buttons duplicate functions already available in the HA interface. In other words, you can just do it all manually or via automations right from the console. The \u201cVoice Assistant\u201d button isn\u2019t really needed either, since you can configure activation with a magic phrase \u2014 \u201cHey, house!\u201d or whatever\u2026<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>At the moment, since I don\u2019t actually need voice control of the home, this capability exists in the speakers but isn\u2019t being used. On the interface side, I see that the activation button works, and on the server side the \u201cvoice assistant\u201d wakes up and starts listening. It\u2019s just that nothing else happens after that because the system doesn\u2019t have any further instructions. I haven\u2019t gotten around to exploring this part of HA\u2019s functionality yet, so I still have no idea how it works. But it\u2019s there, and it apparently does something.<\/p>\n<\/blockquote>\n\n\n\n<p>Anyway, I implemented these controls mostly because the controller board already had them \u2014 six whole buttons. I struggled to even come up with basic uses for four of them. On the other hand, a device without any buttons at all goes against human nature. People need the illusion that their actions influence something, that they\u2019re in control.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Before assembling everything, I had to make a small tweak \u2014 relocating the GPIO rail to the back of the board:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4047\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002-640x311.jpg\" alt=\"\" class=\"wp-image-4047\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_002.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4046\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003-640x311.jpg\" alt=\"\" class=\"wp-image-4046\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_003.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>I did this purely to make room for an RGB LED \u2014 because, honestly, who doesn\u2019t love a few extra lights?<\/p>\n\n\n\n<p>Here&#8217;s what it currently indicates:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Glows green when the device is powered on.<\/li>\n\n\n\n<li>Briefly flashes red to show it&#8217;s connected to Home Assistant.<\/li>\n\n\n\n<li>Turns blue when the &#8220;voice assistant&#8221; feature is activated.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4052\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004-640x311.jpg\" alt=\"\" class=\"wp-image-4052\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_004.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"498\" data-id=\"4053\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_005-1024x498.jpg\" alt=\"\" class=\"wp-image-4053\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_005-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_005-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_005-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_005-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-17_005.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/figure>\n\n\n\n<p>Just like with the buttons, this illumination isn\u2019t strictly necessary \u2014 you can easily do without it. But I love the lights. Plus, why let an unused GPIO go to waste?<\/p>\n\n\n\n<p>At this stage, it\u2019s also the most convenient time to flash the base firmware onto the board:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022-640x311.jpg\" alt=\"\" class=\"wp-image-4049\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_022.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>Later, the firmware can be configured and updated &#8220;over the air.&#8221; However, the very first flashing must be done via a direct USB connection to a computer or server. I didn\u2019t add an external USB port to the device case, so for this task, the device will need to be disassembled.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>The fabrication of the case parts started with the front panel:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"324\" data-id=\"3887\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07-640x324.jpg\" alt=\"\" class=\"wp-image-3887\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07-640x324.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07-1024x518.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07-768x389.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07-1536x778.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_07.jpg 1677w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"366\" data-id=\"3886\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06-640x366.jpg\" alt=\"\" class=\"wp-image-3886\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06-640x366.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06-1024x586.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06-768x440.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06-1536x879.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/render_06.jpg 1677w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>It consists of a flat base panel, a decorative overlay, speakers, an RGB LED, and some fasteners. Out of these, only the base panel and the decorative overlay need to be custom-made. While it would have been possible to <a href=\"\/?tag=marsh-turret-en&amp;order=asc\">3D print<\/a> these parts \u2014 just like the rest of the case \u2014 I decided to take a different approach.<\/p>\n\n\n\n<p>As it happens, I unexpectedly ended up with an &#8220;industrial&#8221; CO laser cutter in my garage. That\u2019s a story for another time. The thing is, I didn\u2019t particularly need it \u2014 it doesn\u2019t see much use around here. Most of the time, it just sits in the garage collecting dust. But I hate having tools go to waste, so I try to put it to use wherever and whenever I can, even if it\u2019s not strictly necessary. That\u2019s exactly what happened here \u2014 I decided to laser-cut the panel and the overlay out of acrylic instead of 3D printing them:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-6 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"3890\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001-640x311.jpg\" alt=\"\" class=\"wp-image-3890\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_001.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"3889\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002-640x311.jpg\" alt=\"\" class=\"wp-image-3889\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_002.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>For both parts, I recycled some old acrylic and jazzed it up with vinyl film \u2014 beige-gold for the panel, pearlescent for the overlay (don\u2019t ask, my wife picked the colors).<\/p>\n\n\n\n<p>For fans of industrial &#8220;craft-porn,&#8221; here\u2019s the uncut and unsped-up footage of the laser cutting the decorative overlay. No edits, no time-lapses \u2014 just raw process.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:15%\"><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:75%\">\n<figure class=\"wp-block-video\"><video height=\"480\" style=\"aspect-ratio: 854 \/ 480;\" width=\"854\" controls preload=\"auto\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/20241208_115826.mp4\"><\/video><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:15%\"><\/div>\n<\/div>\n\n\n\n<p>All the necessary parts for the front panel are ready:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003-640x311.jpg\" alt=\"\" class=\"wp-image-3891\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_003.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>I temporarily assembled the front panel using nuts:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-7 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"3893\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004-640x311.jpg\" alt=\"\" class=\"wp-image-3893\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_004.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"3892\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005-640x311.jpg\" alt=\"\" class=\"wp-image-3892\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_005.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>In the future, the bolts securing the speakers will screw directly into the case, eliminating the need for nuts.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Here I decided to experiment a little with the output signal power. The printer was still busy churning out case parts, and I needed something to keep myself occupied in the meantime.<\/p>\n\n\n\n<p>The ESP32-A1S Audio Kit board comes with its own amplifier. According to the documentation, it provides 2W per channel for 4\u03a9 speakers. That\u2019s generally enough for typical household use within a single room (I even have to dial the volume down to 70-80%).<\/p>\n\n\n\n<p>But the speakers I found stashed away in my supplies are rated for up to 3W at the same 4\u03a9. So why not crank things up a notch? I tried bypassing the onboard amp and used the board\u2019s line-out with a PAM8403 module. It\u2019s nothing groundbreaking \u2014 just a small boost to 3W per channel for my 4\u03a9 speakers. But since I already had the parts, it was a quick and easy upgrade.<\/p>\n\n\n\n<p>The ESP32-A1S Audio Kit doesn\u2019t have a dedicated 5V output \u2014 only 3.3V. But 3.3V isn\u2019t enough for the PAM8403; it needs 5V. Luckily, the board has two USB ports: one for power only and the other for full UART functionality. Regardless of which USB port you supply power to, both will output 5V. This means I can power the device from one USB port and use the other to feed 5V to the amplifier.<\/p>\n\n\n\n<p>In the photo, the lower USB port is used for power input, while the upper one provides 5V to the amplifier. And, of course, the 3mm jack from the line-out goes to the amplifier as well:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-8 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"3894\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006-640x311.jpg\" alt=\"\" class=\"wp-image-3894\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_006.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"3895\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007-640x311.jpg\" alt=\"\" class=\"wp-image-3895\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-08_007.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>The volume \u2014 oh, what a miracle! \u2014 got just a touch louder. Not that there was much else we could\u2019ve expected, right? My unpretentious yet finely tuned musical ear didn\u2019t take offense in the slightest, and from that point on, this very setup was the one chosen for production.<\/p>\n\n\n\n<p>The best part is, we didn\u2019t have to mess with the already-printing case at all. We can just drop the amplifier module inside and wrap it in some heat-shrink tubing \u2014 no big deal:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013-640x311.jpg\" alt=\"\" class=\"wp-image-4059\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_013.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>I also tried another amp \u2014 the PAM8610. It\u2019s just as tiny, but this one needs a 12V supply, and let me tell you, this bad boy cranks up to 15W. The speakers I picked for the project started doing exactly what you\u2019d expect at that power level: crackling and basically screaming, \u201cI\u2019m about to blow!\u201d<\/p>\n\n\n\n<p>So, I decided to stick with the PAM8403 for this project, so I don\u2019t have to hunt down new speakers or rig an extra power supply. Still, I\u2019ve tucked away the PAM8610 option in my mind. I might use it for some other loud-as-hell setups around the house. I\u2019m gonna need more than one or two anyway. We\u2019ll see\u2026<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>While I was busy playing around with lasers and amps, the printer wrapped up the rest of the enclosure parts. Here\u2019s what the full set of components for the loudspeaker rig looks like:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006-640x311.jpg\" alt=\"\" class=\"wp-image-4050\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_006.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>The printer is such a sweetheart. It\u2019s doing all the heavy lifting, while I just twist a few screws and glue some parts together.<\/p>\n\n\n\n<p>First up, I melt in the threaded inserts wherever they\u2019re needed, in both the top and bottom halves of the enclosure:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007-640x311.jpg\" alt=\"\" class=\"wp-image-4051\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_007.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>The button panel gets fitted with a protective mesh for the mics and glued onto the top half of the enclosure:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-9 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4054\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008-640x311.jpg\" alt=\"\" class=\"wp-image-4054\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_008.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4056\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009-640x311.jpg\" alt=\"\" class=\"wp-image-4056\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_009.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4058\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010-640x311.jpg\" alt=\"\" class=\"wp-image-4058\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_010.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4057\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011-640x311.jpg\" alt=\"\" class=\"wp-image-4057\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_011.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4055\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012-640x311.jpg\" alt=\"\" class=\"wp-image-4055\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_012.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>Next, the controller board gets installed, and while I\u2019m at it, I hook up all the necessary wiring:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-10 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4060\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015-640x311.jpg\" alt=\"\" class=\"wp-image-4060\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_015.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4061\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014-640x311.jpg\" alt=\"\" class=\"wp-image-4061\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_014.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>The front panel with the speaker gets attached to one of the halves and wired up to the amp:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-11 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4063\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016-640x311.jpg\" alt=\"\" class=\"wp-image-4063\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_016.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4064\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017-640x311.jpg\" alt=\"\" class=\"wp-image-4064\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_017.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>There\u2019s not much going on with the lower half of the enclosure \u2014 just some feet and a decorative plug:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018-640x311.jpg\" alt=\"\" class=\"wp-image-4070\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_018.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>The space behind the speakers is stuffed with polyfill salvaged from old dog toys. We\u2019ve got a practically endless stash of \u2019em, thanks to that monthly <a href=\"https:\/\/www.barkbox.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Bark-Box<\/a> subscription:<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-2 is-cropped wp-block-gallery-12 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4069\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001-640x311.jpg\" alt=\"\" class=\"wp-image-4069\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-15_001.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4067\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019-640x311.jpg\" alt=\"\" class=\"wp-image-4067\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_019.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4068\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020-640x311.jpg\" alt=\"\" class=\"wp-image-4068\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_020.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4066\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023-640x311.jpg\" alt=\"\" class=\"wp-image-4066\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_023.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>With the polyfill and wires in place, you can close it all up with the second half of the enclosure:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021-640x311.jpg\" alt=\"\" class=\"wp-image-4071\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-18_021.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>And that\u2019s basically it\u2026<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>In the end, I cranked out two identical loudspeaker units:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024-640x311.jpg\" alt=\"\" class=\"wp-image-4072\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_024.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>One for my study room\/workshop, and the other for the shared family room.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-13 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"311\" data-id=\"4073\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026-640x311.jpg\" alt=\"\" class=\"wp-image-4073\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_026.jpg 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"498\" data-id=\"4074\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_025-1024x498.jpg\" alt=\"\" class=\"wp-image-4074\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_025-1024x498.jpg 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_025-640x311.jpg 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_025-768x374.jpg 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_025-1536x747.jpg 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/2024-12-19_025.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/figure>\n\n\n\n<p>I\u2019ll live with them for a bit and see if it was worth the trouble. After that, I can decide whether to bang out another five or so just like these, or maybe do something different. Or even figure out if I need them in the system at all.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>For now, the funniest part is this: the system\u2019s person-detection alert turned my dog into an automated guard. It ignores cars and all other movement. But if it recognizes a human, the house says, \u201cWarning! Person detected in the front yard.\u201d<\/p>\n\n\n\n<p>Here\u2019s the kicker: It once took the Dog a good couple of weeks to confidently offer a paw on command. But he picked up this new phrase in two days \u2014 two freaking days! And he learned it totally on his own, without even a single treat as a reward. Now he thinks it\u2019s a command to leap up and tear off to the window near the door, barking like crazy. He probably thinks, \u201c<em>Great job, humans! No more window duty. I\u2019ll nap until the robot yells.<\/em>\u201d<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>I\u2019m convinced he picked it up so fast thanks to the polyfill from the dog toys stuffed inside these loudspeakers. The sound waves passing through that \u201cdog-sourced\u201d filler must pick up some sort of canine vibe that\u2019s easier for him to understand. I can\u2019t explain it any other way\u2026<\/p>\n<\/blockquote>\n\n\n\n<p>So, at least one family member gave this new house feature a roaring thumbs-up \u2014 er, paws-up.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Thinking of building something similar? Everything you need \u2014 from the parts list to configuration files \u2014 is right here. Dive in and start tinkering! Here\u2019s the component layout diagram:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-medium\"><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"361\" src=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1-640x361.png\" alt=\"\" class=\"wp-image-4148\" style=\"aspect-ratio:16\/9;object-fit:cover\" srcset=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1-640x361.png 640w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1-1024x577.png 1024w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1-768x433.png 768w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1-1536x866.png 1536w, https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/Untitled-Sketch_bb-1-2048x1155.png 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>And the 3D-printable parts:<\/p>\n\n\n\n<div class=\"wp-block-file aligncenter\"><a id=\"wp-block-file--media-52a77b66-6c10-4bb9-a6cd-31b29799aaf3\" href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/JHomeEcho.zip\">ZIP (~ 1.00MB)<\/a><a href=\"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/JHomeEcho.zip\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-52a77b66-6c10-4bb9-a6cd-31b29799aaf3\">Download<\/a><\/div>\n\n\n\n<p>A sample ESPHome firmware config file:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:.75rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(3 * 0.6 * .75rem);--cbp-line-highlight-color:rgba(201, 218, 248, 0.2);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">YAML<\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Substitutions\n# ================================================================\n# Substitutions allow defining reusable variables for values that are repeated\n# across the configuration file.\n\nsubstitutions:\n  # Controller Configuration\n  name:             'jh-echo'     # Unique identifier for the device in this configuration\n  friendly_name:    'JHome Echo'  # User-friendly name for display in interfaces\n\n  # Project Information\n  project_name:     'JHome.NNVI'  # Unique identifier for the project\n  project_version:  '6.0'        # Current version of the project configuration\n\n  # Board Specifications\n  board_master: 'ESP32-A1S'                 # Primary ESP32-based board model\n  board_slave:  'ESP32 Audio Kit v2.2 A426' # Secondary ESP32-based board model for additional functionality\n\n  # On-board Devices Configuration\n  led_service_pin:  '22'                # GPIO pin assigned to the service indicator LED\n  led_action_pin:   '05'                # GPIO pin assigned to the action indicator LED\n\n  # I2C Bus Configuration\n  i2c_sda_pin:      '33'                # GPIO pin for I2C data line (SDA)\n  i2c_scl_pin:      '32'                # GPIO pin for I2C clock line (SCL)\n\n  # DAC (Digital-to-Analog Converter) Pin Configuration\n  dac_lrclk_pin:    '25'                # GPIO pin for DAC Left-Right Clock (LRCLK)\n  dac_bclk_pin:     '27'                # GPIO pin for DAC Bit Clock (BCLK)\n  dac_dout_pin:     '26'                # GPIO pin for DAC Data Output (DOUT)\n  dac_din_pin:      '35'                # GPIO pin for DAC Data Input (DIN)\n\n  # Headphone Jack Configuration\n  hdp_state_pin:    '39'                # GPIO pin connected to headphone jack state detection\n\n  # Amplifier Control\n  amp_output_pin:   '21'                # GPIO pin controlling the amplifier power state (ON\/OFF)\n\n  # Button Configuration\n  btn_1_pin:        '36'                # GPIO pin assigned to button 1 (Key 1)\n  btn_2_pin:        '13'                # GPIO pin assigned to button 2 (Key 2)\n  btn_3_pin:        '19'                # GPIO pin assigned to button 3 (Key 3)\n  btn_4_pin:        '23'                # GPIO pin assigned to button 4 (Key 4)\n  btn_5_pin:        '18'                # GPIO pin assigned to button 5 (Key 5)\n  #btn_6_pin:        '05'                # GPIO pin assigned to button 6 (Key 6)\n\n\n\n# Basic ESPhome Configuration\n# ================================================================\nesphome:\n  # This section defines the basic configuration for the ESPHome device.\n  name: ${name}                   # Device's name\n  friendly_name: ${friendly_name} # Device's friendly name\n  project:\n    name: ${project_name}         # Project name from substitutions\n    version: ${project_version}   # Project version from substitutions\n  name_add_mac_suffix: false      # Prevent appending the MAC address to the name\n\n  # Actions to perform on device boot\n  on_boot:\n    priority: -100\n    then:\n      - if:\n          condition:\n            binary_sensor.is_on: jack_status\n          then:\n            - output.turn_off: amp_output\n          else:\n            - output.turn_on: amp_output\n\nesp32:\n  # This section specifies the hardware platform and framework type for the ESP32 board.\n  board: esp-wrover-kit            # ESP32 development board type\n  framework:\n    type: arduino                  # Arduino framework\n\n# Network Configurations\n# ================================================================\nwifi:\n  # This section configures the Wi-Fi settings for connecting the device\n  # to a network or creating an access point for direct communication.\n  ssid: !secret wifi_ssid           # Wi-Fi network name from secrets\n  password: !secret wifi_password   # Wi-Fi password from secrets\n  ap:\n    ssid: ${friendly_name}          # Access Point (AP) mode SSID\n    password: !secret ap_password   # Access Point (AP) mode password\n\n# Enabling ESPHome Features\n# ================================================================\napi:\n  # Enables integration with Home Assistant using the ESPHome API.\n  encryption:\n    key: !secret api_key            # Encryption key for secure communication\n\nota:\n  # Configures Over-the-Air (OTA) updates to allow firmware updates.\n  platform: esphome                 # Required platform for OTA\n  password: !secret ota_password    # Password for OTA updates\n\ncaptive_portal:\n  # Provides a captive portal for easy Wi-Fi setup when no known network is available.\n\nweb_server:\n  # Enables a local web server for device management and diagnostics.\n\nlogger:\n  # Configures logging options to debug or monitor device activity.\n  level: INFO                       # Set logging level to INFO for reduced verbosity\n\n# Additional Features and Integrations\n# ================================================================\n# Uncomment the section below if you need Improv Wi-Fi setup\n# esp32_improv:\n#   authorizer: none                # Setup for Improv without authorization\n\ndashboard_import:\n  # Imports external configuration files from GitHub for easy reuse and updates.\n  package_import_url: github:\/\/esphome\/example-configs\/esphome-web\/esp32.yaml@main\n  import_full_config: true         # Import full configuration from GitHub\n\n# External Components\n# ================================================================\nexternal_components:\n  # Configures additional components from external sources like GitHub.\n  - source: github:\/\/mulcmu\/esphome-es8388-a1s@nightdav-patch\n    components: [es8388]\n    refresh: 0s\n\nes8388:\n  # Initializes and configures the ES8388 audio codec component.\n\n\n\n# GLOBAL VARIABLES\n# ================================================================\nglobals:\n  # Memory for volume level\n  - id: mem_volume\n    type: float\n    restore_value: no\n    initial_value: '0.5'\n\n\n\n# SERIAL INTERFACES\n# ================================================================\ni2c:\n  # I2C Bus Configuration\n  id: bus_a\n  sda: ${i2c_sda_pin}\n  scl: ${i2c_scl_pin}\n  frequency: 400kHz\n  scan: true\n\ni2s_audio:\n  # I2S Audio Configuration\n  i2s_lrclk_pin: ${dac_lrclk_pin}\n  i2s_bclk_pin: ${dac_bclk_pin}\n  i2s_mclk_pin: 0\n\n\n\n# OUTPUTS\n# ================================================================\noutput:\n  # Service LED\n  - platform: gpio\n    id: led_service\n    pin: ${led_service_pin}\n    #inverted: true\n\n  # Action LED\n  - platform: gpio\n    id: led_action\n    pin: ${led_action_pin}\n\n  # Amplifier Output\n  - platform: gpio\n    id: amp_output\n    pin: ${amp_output_pin}\n\n\n\n# MEDIA FUNCTIONS\n# ================================================================\nmedia_player:\n  # I2S Audio Player\n  - platform: i2s_audio\n    id: mplayer\n    name: &quot;Player&quot;\n    i2s_dout_pin: ${dac_dout_pin}\n    dac_type: external\n    mode: stereo\n\nmicrophone:\n  # External Microphone\n  - platform: i2s_audio\n    id: mic1\n    i2s_din_pin: ${dac_din_pin}\n    adc_type: external\n    channel: left\n    pdm: false\n\nvoice_assistant:\n  microphone: mic1\n\n\n\n# BINARY SENSORS\n# ================================================================\nbinary_sensor:\n  # Connection status\n  - platform: status\n    id: status_connection\n    internal: true\n\n  # Headphones mode (Jack status)\n  - platform: gpio\n    id: jack_status\n    pin:\n      number: ${hdp_state_pin}\n      inverted: true\n      mode:\n        input: true\n    name: &quot;Headphones mode&quot;\n    on_state:\n      - if:\n          condition:\n            binary_sensor.is_on: jack_status\n          then:\n            - output.turn_off: amp_output\n          else:\n            - output.turn_on: amp_output\n\n  # Key 2 - Mute\n  - platform: gpio\n    id: btn_mute\n    pin:\n      number: ${btn_2_pin}\n      inverted: true\n      mode:\n        input: true\n        pullup: true\n    name: &quot;Mute&quot;\n    icon: mdi:volume-mute\n    on_press:\n      - if:\n          condition:\n            lambda: 'return id(mplayer).volume == 0.0;'\n          then:\n            - media_player.volume_set:\n                id: mplayer\n                volume: !lambda 'return id(mem_volume);'\n          else:\n            - lambda: 'id(mem_volume) = id(mplayer).volume;'\n            - media_player.volume_set:\n                id: mplayer\n                volume: 0.0\n\n  # Key 3 - Volume down\n  - platform: gpio\n    id: btn_vol_down\n    pin:\n      number: ${btn_3_pin}\n      inverted: true\n    name: &quot;Vol. down&quot;\n    icon: mdi:volume-minus\n    filters:\n      - delayed_off: 10ms\n    on_press:\n      - media_player.volume_down: mplayer\n\n  # Key 4 - Volume up\n  - platform: gpio\n    id: btn_vol_up\n    pin:\n      number: ${btn_4_pin}\n      inverted: true\n      mode:\n        input: true\n        pullup: true\n    name: &quot;Vol. up&quot;\n    icon: mdi:volume-plus\n    filters:\n      - delayed_off: 10ms\n    on_press:\n      - media_player.volume_up: mplayer\n\n  # Key 5 - Assistant\n  - platform: gpio\n    id: btn_assistant\n    pin: \n      number: ${btn_5_pin}\n      inverted: true\n      mode:\n        input: true\n        pullup: true\n    name: &quot;Voice assistant&quot;\n    icon: mdi:assistant\n    filters:\n      - delayed_off: 10ms\n    on_press:\n      - output.turn_on: led_action\n      - voice_assistant.start:\n    on_release:\n      - output.turn_off: led_action\n      - voice_assistant.stop:\n\n\n\n\n\n\n# SENSORS\n# ================================================================\nsensor:\n  # Signal strength\n  - platform: wifi_signal\n    id: info_signal\n    name: &quot;[network] Signal&quot;\n    icon: &quot;mdi:information-box-outline&quot;\n    unit_of_measurement: &quot;%&quot;\n    entity_category: diagnostic\n    filters:\n      - lambda: |-\n          return min(max(2 * (x + 100.0), 0.0), 100.0);\n\n  # Board temperature\n  - platform: internal_temperature\n    id: info_brd_temperature\n    name: &quot;[board] Temperature&quot;\n    icon: &quot;mdi:information-box-outline&quot;\n    unit_of_measurement: &quot;\u00b0C&quot;\n    entity_category: diagnostic\n    update_interval: 1min\n\n\n\n# BUTTONS\n# ================================================================\nbutton:\n  # Restart button\n  - platform: restart\n    id: btn_restart\n    name: &quot;Restart&quot;\n\n  # Factory reset button\n  - platform: factory_reset\n    id: btn_factory_reset\n    name: &quot;Reset with Defaults&quot;\n\n\n\n# INTERVALS\n# ================================================================\ninterval:\n  - interval: 10s\n    then:\n      - if:\n          condition:\n            binary_sensor.is_on: status_connection\n          then:\n            - output.turn_on: led_service\n            - delay: 100ms\n            - output.turn_off: led_service\n          else:\n            - output.turn_on: led_service\n\n\n\n# DIAGNOSTIC SENSORS\n# ================================================================\ntext_sensor:\n  # Wi-Fi Info\n  - platform: wifi_info\n    ip_address:\n      id: info_IP\n      name: &quot;[network] IP&quot;\n      icon: &quot;mdi:information-box-outline&quot;\n      entity_category: diagnostic\n    ssid:\n      id: info_SSID\n      name: &quot;[network] SSID&quot;\n      icon: &quot;mdi:information-box-outline&quot;\n      entity_category: diagnostic\n    bssid:\n      id: info_MAC\n      name: &quot;[network] MAC&quot;\n      icon: &quot;mdi:information-box-outline&quot;\n      entity_category: diagnostic\n\n  # Board Master Info\n  - platform: template\n    id: info_brd_master\n    name: &quot;[board] Master&quot;\n    icon: &quot;mdi:information-box-outline&quot;\n    entity_category: diagnostic\n    update_interval: 1d\n    lambda: |-\n      return std::string(&quot;${board_master}&quot;);\n\n  # Board Slave Info\n  - platform: template\n    id: info_brd_slave\n    name: &quot;[board] Slave&quot;\n    icon: &quot;mdi:information-box-outline&quot;\n    entity_category: diagnostic\n    update_interval: 1d\n    lambda: |-\n      return std::string(&quot;${board_slave}&quot;);\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\"># Substitutions<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Substitutions allow defining reusable variables for values that are repeated<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># across the configuration file.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">substitutions<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Controller Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">             <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">jh-echo<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">     <\/span><span style=\"color: #616E88\"># Unique identifier for the device in this configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">friendly_name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">JHome Echo<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #616E88\"># User-friendly name for display in interfaces<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Project Information<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">project_name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">     <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">JHome.NNVI<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #616E88\"># Unique identifier for the project<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">project_version<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">6.0<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #616E88\"># Current version of the project configuration<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Board Specifications<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">board_master<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">ESP32-A1S<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                 <\/span><span style=\"color: #616E88\"># Primary ESP32-based board model<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">board_slave<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">ESP32 Audio Kit v2.2 A426<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\"># Secondary ESP32-based board model for additional functionality<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># On-board Devices Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">led_service_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">22<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to the service indicator LED<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">led_action_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">   <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">05<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to the action indicator LED<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># I2C Bus Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">i2c_sda_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">33<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin for I2C data line (SDA)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">i2c_scl_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">32<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin for I2C clock line (SCL)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># DAC (Digital-to-Analog Converter) Pin Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">dac_lrclk_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">25<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin for DAC Left-Right Clock (LRCLK)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">dac_bclk_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">     <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">27<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin for DAC Bit Clock (BCLK)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">dac_dout_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">     <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">26<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin for DAC Data Output (DOUT)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">dac_din_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">35<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin for DAC Data Input (DIN)<\/span><\/span>\n<span class=\"line cbp-see-more-line \"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Headphone Jack Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">hdp_state_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">39<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin connected to headphone jack state detection<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Amplifier Control<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">amp_output_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">   <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">21<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin controlling the amplifier power state (ON\/OFF)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Button Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">btn_1_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">36<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to button 1 (Key 1)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">btn_2_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">13<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to button 2 (Key 2)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">btn_3_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">19<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to button 3 (Key 3)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">btn_4_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">23<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to button 4 (Key 4)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">btn_5_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">18<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #616E88\"># GPIO pin assigned to button 5 (Key 5)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\">#btn_6_pin:        &#39;05&#39;                # GPIO pin assigned to button 6 (Key 6)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Basic ESPhome Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">esphome<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># This section defines the basic configuration for the ESPHome device.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${name}<\/span><span style=\"color: #D8DEE9FF\">                   <\/span><span style=\"color: #616E88\"># Device&#39;s name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">friendly_name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${friendly_name}<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\"># Device&#39;s friendly name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">project<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${project_name}<\/span><span style=\"color: #D8DEE9FF\">         <\/span><span style=\"color: #616E88\"># Project name from substitutions<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">version<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${project_version}<\/span><span style=\"color: #D8DEE9FF\">   <\/span><span style=\"color: #616E88\"># Project version from substitutions<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name_add_mac_suffix<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">false<\/span><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #616E88\"># Prevent appending the MAC address to the name<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Actions to perform on device boot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">on_boot<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">priority<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">-100<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">then<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">if<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">condition<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #8FBCBB\">binary_sensor.is_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">jack_status<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">then<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">amp_output<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">else<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">amp_output<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">esp32<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># This section specifies the hardware platform and framework type for the ESP32 board.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">board<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">esp-wrover-kit<\/span><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #616E88\"># ESP32 development board type<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">framework<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">type<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">arduino<\/span><span style=\"color: #D8DEE9FF\">                  <\/span><span style=\"color: #616E88\"># Arduino framework<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Network Configurations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">wifi<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># This section configures the Wi-Fi settings for connecting the device<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># to a network or creating an access point for direct communication.<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">ssid<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!secret<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">wifi_ssid<\/span><span style=\"color: #D8DEE9FF\">           <\/span><span style=\"color: #616E88\"># Wi-Fi network name from secrets<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">password<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!secret<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">wifi_password<\/span><span style=\"color: #D8DEE9FF\">   <\/span><span style=\"color: #616E88\"># Wi-Fi password from secrets<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">ap<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">ssid<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${friendly_name}<\/span><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #616E88\"># Access Point (AP) mode SSID<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">password<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!secret<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">ap_password<\/span><span style=\"color: #D8DEE9FF\">   <\/span><span style=\"color: #616E88\"># Access Point (AP) mode password<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Enabling ESPHome Features<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">api<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Enables integration with Home Assistant using the ESPHome API.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">encryption<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">key<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!secret<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">api_key<\/span><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #616E88\"># Encryption key for secure communication<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">ota<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Configures Over-the-Air (OTA) updates to allow firmware updates.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">esphome<\/span><span style=\"color: #D8DEE9FF\">                 <\/span><span style=\"color: #616E88\"># Required platform for OTA<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">password<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!secret<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">ota_password<\/span><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #616E88\"># Password for OTA updates<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">captive_portal<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Provides a captive portal for easy Wi-Fi setup when no known network is available.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">web_server<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Enables a local web server for device management and diagnostics.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">logger<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Configures logging options to debug or monitor device activity.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">level<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">INFO<\/span><span style=\"color: #D8DEE9FF\">                       <\/span><span style=\"color: #616E88\"># Set logging level to INFO for reduced verbosity<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Additional Features and Integrations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Uncomment the section below if you need Improv Wi-Fi setup<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># esp32_improv:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#   authorizer: none                # Setup for Improv without authorization<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">dashboard_import<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Imports external configuration files from GitHub for easy reuse and updates.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">package_import_url<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">github:\/\/esphome\/example-configs\/esphome-web\/esp32.yaml@main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">import_full_config<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><span style=\"color: #D8DEE9FF\">         <\/span><span style=\"color: #616E88\"># Import full configuration from GitHub<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># External Components<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">external_components<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Configures additional components from external sources like GitHub.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">source<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">github:\/\/mulcmu\/esphome-es8388-a1s@nightdav-patch<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">components<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[<\/span><span style=\"color: #A3BE8C\">es8388<\/span><span style=\"color: #ECEFF4\">]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">refresh<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">0s<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">es8388<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Initializes and configures the ES8388 audio codec component.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># GLOBAL VARIABLES<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">globals<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Memory for volume level<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mem_volume<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">type<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">restore_value<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">no<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">initial_value<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">0.5<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># SERIAL INTERFACES<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">i2c<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># I2C Bus Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">bus_a<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">sda<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${i2c_sda_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">scl<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${i2c_scl_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">frequency<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">400kHz<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">scan<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">i2s_audio<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># I2S Audio Configuration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">i2s_lrclk_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${dac_lrclk_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">i2s_bclk_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${dac_bclk_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">i2s_mclk_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># OUTPUTS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">output<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Service LED<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_service<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${led_service_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">#inverted: true<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Action LED<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_action<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${led_action_pin}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Amplifier Output<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">amp_output<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${amp_output_pin}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># MEDIA FUNCTIONS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">media_player<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># I2S Audio Player<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">i2s_audio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mplayer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Player<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">i2s_dout_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${dac_dout_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">dac_type<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">external<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">mode<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">stereo<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">microphone<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># External Microphone<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">i2s_audio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mic1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">i2s_din_pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${dac_din_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">adc_type<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">external<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">channel<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">left<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pdm<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">false<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">voice_assistant<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">microphone<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mic1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># BINARY SENSORS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">binary_sensor<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Connection status<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">status<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">status_connection<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">internal<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Headphones mode (Jack status)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">jack_status<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">number<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${hdp_state_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">inverted<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">mode<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">input<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Headphones mode<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">on_state<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">if<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">condition<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #8FBCBB\">binary_sensor.is_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">jack_status<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">then<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">amp_output<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">else<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">amp_output<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Key 2 - Mute<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">btn_mute<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">number<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${btn_2_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">inverted<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">mode<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">input<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">pullup<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Mute<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mdi:volume-mute<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">on_press<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">if<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">condition<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #8FBCBB\">lambda<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">return id(mplayer).volume == 0.0;<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">then<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">media_player.volume_set<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mplayer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #8FBCBB\">volume<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!lambda<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">return id(mem_volume);<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">else<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">lambda<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">id(mem_volume) = id(mplayer).volume;<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">media_player.volume_set<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mplayer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #8FBCBB\">volume<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Key 3 - Volume down<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">btn_vol_down<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">number<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${btn_3_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">inverted<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Vol. down<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mdi:volume-minus<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">filters<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">delayed_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">10ms<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">on_press<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">media_player.volume_down<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mplayer<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Key 4 - Volume up<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">btn_vol_up<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">number<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${btn_4_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">inverted<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">mode<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">input<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">pullup<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Vol. up<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mdi:volume-plus<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">filters<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">delayed_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">10ms<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">on_press<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">media_player.volume_up<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mplayer<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Key 5 - Assistant<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">gpio<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">btn_assistant<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">pin<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">number<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">${btn_5_pin}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">inverted<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">mode<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">input<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">pullup<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Voice assistant<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">mdi:assistant<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">filters<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">delayed_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">10ms<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">on_press<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_action<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">voice_assistant.start<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">on_release<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_action<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">voice_assistant.stop<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># SENSORS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">sensor<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Signal strength<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">wifi_signal<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_signal<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[network] Signal<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">unit_of_measurement<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">%<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">filters<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">lambda<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">|-<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">          return min(max(2 * (x + 100.0), 0.0), 100.0);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Board temperature<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">internal_temperature<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_brd_temperature<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[board] Temperature<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">unit_of_measurement<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u00b0C<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">update_interval<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">1min<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># BUTTONS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">button<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Restart button<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">restart<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">btn_restart<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Restart<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Factory reset button<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">factory_reset<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">btn_factory_reset<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Reset with Defaults<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># INTERVALS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">interval<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">interval<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">10s<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">then<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">if<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">condition<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #8FBCBB\">binary_sensor.is_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">status_connection<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">then<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_service<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">delay<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">100ms<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_off<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_service<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">else<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">output.turn_on<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">led_service<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># DIAGNOSTIC SENSORS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">text_sensor<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Wi-Fi Info<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">wifi_info<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">ip_address<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_IP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[network] IP<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">ssid<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_SSID<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[network] SSID<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">bssid<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_MAC<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[network] MAC<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Board Master Info<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">template<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_brd_master<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[board] Master<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">update_interval<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">1d<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">lambda<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">|-<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">      return std::string(&quot;${board_master}&quot;);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\"># Board Slave Info<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">platform<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">template<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">id<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">info_brd_slave<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[board] Slave<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">icon<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mdi:information-box-outline<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">entity_category<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">diagnostic<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">update_interval<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">1d<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">lambda<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">|-<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">      return std::string(&quot;${board_slave}&quot;);<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Note that I repurposed the GPIO from the unused button six (btn_6_pin) for the LED. In other words, for the RGB LED: G (green) is hardwired to the 3.3V power line, R (red) is tied to the board\u2019s built-in LED (led_service_pin) that indicates connection status, and B (blue) is on led_action_pin, which I moved from the unused button.<\/p>\n<\/blockquote>\n\n\n\n<p>To adapt it for your own setup, don\u2019t forget to set the SSID\/pass for your network, as well as the AP mode access and system-side access, including the API key (these lines are highlighted in the example above). I pull these values from a common secrets.yaml file shared by all my controllers (example shown):<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:.75rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">YAML<\/span><span role=\"button\" tabindex=\"0\" data-code=\"wifi_ssid:      &quot;MyWiFyck&quot;\nwifi_password:  &quot;b0brkyrva&quot;\nota_password:   &quot;ol0lo&quot;\nap_password:    &quot;popya4sa&quot;\napi_key:        &quot;mnoGAbuKoV_AFtarPESHiEsho=&quot;\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #8FBCBB\">wifi_ssid<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">MyWiFyck<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">wifi_password<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">b0brkyrva<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">ota_password<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">   <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">ol0lo<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">ap_password<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">popya4sa<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">api_key<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">mnoGAbuKoV_AFtarPESHiEsho=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Otherwise, you can pretty much leave everything as is.<\/p>\n\n\n\n<p>Some notable features of the configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>There\u2019s built-in logic that cuts off the internal amplifier whenever a 3.5mm jack is plugged in. The board automatically checks if its own amplifier is in use or if it\u2019s switched over to external.<\/li>\n\n\n\n<li>The Mute button saves the current volume when pressed. When you press it again, it restores that exact volume level. This works whether you press the physical hardware button on the device or call it remotely from the server.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>This may not be super relevant to the finished version of the device as presented here, since it doesn\u2019t have any external outputs, but I\u2019m big on standardization\u2014and who knows what I\u2019ll use this same firmware config for in the future.<\/p>\n<\/blockquote>\n\n\n\n<p>And, just to repeat: I haven\u2019t tested the microphones in these examples. One of them (the left one) is initialized and recognized by the system, supposedly. Whether it\u2019s actually picking up sound and sending it anywhere is another story\u2026 For now, I don\u2019t need that feature and I\u2019m not really interested in it, so I\u2019m putting off testing until later. If and when I need it, I\u2019ll update the article with more detailed info.<\/p>\n\n\n\n<p>That\u2019s the situation so far\u2026<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the process of expanding my smart home setup, a few of the voices in my head decided to relocate somewhere more comfortable.<\/p>\n","protected":false},"author":1,"featured_media":3821,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_sitemap_exclude":false,"_sitemap_priority":"","_sitemap_frequency":"","footnotes":""},"categories":[234],"tags":[211,215,219,229,295],"class_list":["post-3993","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-smarthome-en","tag-ha-en","tag-esphome-en","tag-nnvi-en","tag-sound-en","tag-esp32-en"],"featured_image_src":"https:\/\/jimsghost.place\/wp-content\/uploads\/2024\/12\/silence.jpg","author_info":{"display_name":"Jim","author_link":"https:\/\/jimsghost.place\/?author=1"},"_links":{"self":[{"href":"https:\/\/jimsghost.place\/index.php?rest_route=\/wp\/v2\/posts\/3993","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jimsghost.place\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jimsghost.place\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jimsghost.place\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jimsghost.place\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3993"}],"version-history":[{"count":0,"href":"https:\/\/jimsghost.place\/index.php?rest_route=\/wp\/v2\/posts\/3993\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jimsghost.place\/index.php?rest_route=\/wp\/v2\/media\/3821"}],"wp:attachment":[{"href":"https:\/\/jimsghost.place\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jimsghost.place\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jimsghost.place\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}