<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Markus Haack // Software Engineer</title>
  <subtitle></subtitle>
  <link href="https://markus-haack.com/feed/feed.xml" rel="self"/>
  <link href="https://markus-haack.com/"/>
  <updated>2026-03-16T00:00:00Z</updated>
  <id>https://markus-haack.com</id>
  <author>
    <name>Markus Haack</name>
    <email>info@markus-haack.de</email>
  </author>
  <entry>
    <title>DA MCP: Giving AI Assistants Direct Access to Document Authoring</title>
    <link href="https://markus-haack.com/da-mcp/"/>
    <updated>2026-03-16T00:00:00Z</updated>
    <id>https://markus-haack.com/da-mcp/</id>
    <content type="html">&lt;p&gt;Over the past few months, AI assistants have gone from useful chat tools to something more interesting: agents that can actually &lt;em&gt;do&lt;/em&gt; things. Not just draft text, but read files, write content, move things around, and connect to external systems. The key technology making this possible is the &lt;a href=&quot;https://modelcontextprotocol.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Model Context Protocol&lt;/a&gt; (MCP) — an open standard for giving AI tools structured access to external services.&lt;/p&gt;
&lt;p&gt;I’ve been working deeply with &lt;a href=&quot;https://da.live&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Document Authoring (DA)&lt;/a&gt; — Adobe’s content platform for Edge Delivery Services — and I kept thinking about the same question: what if Claude could just &lt;em&gt;talk&lt;/em&gt; to DA directly? Not through copy-pasting, not through a browser, but as a first-class tool in a conversation?&lt;/p&gt;
&lt;p&gt;So I built it.&lt;/p&gt;
&lt;h2 id=&quot;what-is-da-mcp%3F&quot;&gt;What is DA MCP?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/da-mcp/#what-is-da-mcp%3F&quot; aria-labelledby=&quot;what-is-da-mcp%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/adobe-rnd/da-mcp&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DA MCP&lt;/a&gt; is a remote MCP server that gives AI assistants like Claude or ChatGPT direct access to DA management operations. Once connected, your AI assistant can browse your DA repositories, read and write files, create new pages, move content around, check version history, and look up media and fragment references — all without leaving the chat window.&lt;/p&gt;
&lt;p&gt;Think of it as giving your AI assistant a command-line-like interface to DA. Instead of switching between tools and copying content back and forth, you can say things like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Draft a new landing page at /products/overview and save it directly to DA.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Create 5 event pages with details for the provided CSV file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And it just does it.&lt;/p&gt;
&lt;h2 id=&quot;the-10-tools&quot;&gt;The 10 Tools&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/da-mcp/#the-10-tools&quot; aria-labelledby=&quot;the-10-tools&quot;&gt;#&lt;/a&gt;&lt;p&gt;DA MCP exposes 10 tools covering the full content lifecycle:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_list_sources&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Browse directories and list files in a repository&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_get_source&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read the full content of any file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_create_source&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create a new file with provided content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_update_source&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update an existing file in place&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_delete_source&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete a file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_copy_content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Copy content from one location to another&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_move_content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Move or rename content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_get_versions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;View version history for a file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_lookup_media&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Look up media asset references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;da_lookup_fragment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Look up content fragment references&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/da-mcp/#how-it-works&quot; aria-labelledby=&quot;how-it-works&quot;&gt;#&lt;/a&gt;&lt;p&gt;The server is built in TypeScript and runs on Cloudflare Workers. Authentication uses a token pass-through model — the client sends a DA Admin API token in the &lt;code&gt;Authorization&lt;/code&gt; header, which the server forwards to the DA Admin API. If you use the public endpoint at &lt;code&gt;mcp.adobeaemcloud.com&lt;/code&gt;, Adobe IMS authentication is handled automatically. No token configuration needed.&lt;/p&gt;
&lt;p&gt;The code is open source: &lt;a href=&quot;https://github.com/adobe-rnd/da-mcp&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;github.com/adobe-rnd/da-mcp&lt;/a&gt;. Pull requests and feedback welcome.&lt;/p&gt;
&lt;h2 id=&quot;getting-connected&quot;&gt;Getting Connected&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/da-mcp/#getting-connected&quot; aria-labelledby=&quot;getting-connected&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://Claude.ai&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Claude.ai&lt;/a&gt;&lt;/strong&gt; is the easiest way to start. Go to &lt;strong&gt;Settings → Connectors&lt;/strong&gt;, find &lt;em&gt;DA MCP&lt;/em&gt;, click &lt;strong&gt;Connect&lt;/strong&gt;, and sign in with your Adobe IMS account. Done.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;Claude Desktop&lt;/strong&gt;, add this to your config file — on macOS: &lt;code&gt;~/Library/Application Support/Claude/claude_desktop_config.json&lt;/code&gt;, on Windows: &lt;code&gt;%APPDATA%&#92;Claude&#92;claude_desktop_config.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;da-mcp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;streamable-http&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mcp.adobeaemcloud.com/adobe/mcp/da&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For &lt;strong&gt;VS Code or Cursor&lt;/strong&gt;, add to &lt;code&gt;.vscode/mcp.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;da-mcp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mcp.adobeaemcloud.com/adobe/mcp/da&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-i%E2%80%99ve-been-using-it-for&quot;&gt;What I’ve Been Using It For&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/da-mcp/#what-i%E2%80%99ve-been-using-it-for&quot; aria-labelledby=&quot;what-i%E2%80%99ve-been-using-it-for&quot;&gt;#&lt;/a&gt;&lt;p&gt;I’ve been running this day-to-day for a few weeks. A few things work well: drafting and saving content without leaving the conversation, bulk updates across multiple pages without writing scripts, and using &lt;code&gt;da_get_versions&lt;/code&gt; to check what changed in a file without context-switching. Combining it with web research is also useful — Claude can look something up and save the result to DA in one pass.&lt;/p&gt;
&lt;h2 id=&quot;a-real-world-example&quot;&gt;A Real-World Example&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/da-mcp/#a-real-world-example&quot; aria-labelledby=&quot;a-real-world-example&quot;&gt;#&lt;/a&gt;&lt;p&gt;A colleague &lt;a href=&quot;https://www.linkedin.com/posts/auniverseaway_adobeexperiencemanager-edgedeliveryservices-activity-7439341002504658944-9BNN&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;posted a good example on LinkedIn&lt;/a&gt;: auditing Summit Labs for missing content pages, scaffolding them out from a CSV export — all in a single conversation, saving around 6 hours of manual work. That’s the kind of multi-step workflow where having Claude directly connected to DA pays off.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Our 2025 Home Solar Performance: 5 Years of Real Data</title>
    <link href="https://markus-haack.com/our-2025-solar-power-performance/"/>
    <updated>2026-03-07T00:00:00Z</updated>
    <id>https://markus-haack.com/our-2025-solar-power-performance/</id>
    <content type="html">&lt;p&gt;If you want to know if it makes financial sense to install a home solar system in Germany, or if you’re curious about how long these systems last, we have the answers for you. Here is five years of real data from our own rooftop PV system in Germany. In 2025, our 9.45 kWp system produced &lt;strong&gt;8,624 kWh&lt;/strong&gt;, covering 54% of our household electricity needs and saving us around €2,200 in grid costs. The full breakdown is below.&lt;/p&gt;
&lt;p&gt;This is our fifth annual solar review. You can find the previous ones for &lt;a href=&quot;https://markus-haack.com/our-2024-solar-power-performance/&quot;&gt;2024&lt;/a&gt; and &lt;a href=&quot;https://markus-haack.com/solar-update-2023/&quot;&gt;2023&lt;/a&gt;, along with the original &lt;a href=&quot;https://markus-haack.com/our-own-electricity-1/&quot;&gt;installation posts from 2021&lt;/a&gt;. Quick system overview: 9.45 kWp of panels on a south-facing roof in southern Germany, installed in 2021, paired with a BYD battery and a SolarEdge inverter. Since mid-2025 we also have a Polestar 4 that we charge primarily on solar surplus using &lt;a href=&quot;https://markus-haack.com/intro-into-evcc-charging/&quot;&gt;evcc&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;2025%3A-steady-production%2C-higher-consumption&quot;&gt;2025: Steady Production, Higher Consumption&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2025-solar-power-performance/#2025%3A-steady-production%2C-higher-consumption&quot; aria-labelledby=&quot;2025%3A-steady-production%2C-higher-consumption&quot;&gt;#&lt;/a&gt;&lt;p&gt;Our panels produced 8,624 kWh in 2025 — down just 0.9% from 2024. Essentially flat. Total household consumption climbed to 10,714 kWh, a 6.3% jump compared to the previous year. The new EV is almost certainly responsible for a big chunk of that.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/solar-2025-scorecard.png&quot; alt=&quot;Solar 2025 Scorecard&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The seasonal pattern was familiar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Best month: June, with 1,291 kWh — narrowly edging out May (1,260 kWh). For the first time in five years, June rather than July claimed the top spot.&lt;/li&gt;
&lt;li&gt;Worst month: January, as expected — just 169 kWh in a month where we consumed over 1,000 kWh. Very similar to the previous years.&lt;/li&gt;
&lt;li&gt;Most grid-independent months: July and June, where we drew only 104 kWh and 161 kWh from the grid respectively.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What was different compared to 2024? Spring was notably stronger — February was up +55 kWh, May up +99 kWh. But July let us down badly: 1,074 kWh against July 2024’s 1,299 kWh, a drop of 225 kWh. October was similarly disappointing (352 kWh vs. 482 kWh in 2024). Whatever the weather was doing in those months, it hit the panels hard.&lt;/p&gt;
&lt;p&gt;The flip side: December 2025 was almost double December 2024 — 166 kWh versus 85 kWh. That continues a pattern we’ve been watching for a few years now: milder winters, less snow cover on the panels, marginally better winter yields. Not much but it adds a little to our electricity savings.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/solar-2025-months.png&quot; alt=&quot;Solar 2025 monthly view&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;five-years-in-one-table&quot;&gt;Five Years in One Table&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2025-solar-power-performance/#five-years-in-one-table&quot; aria-labelledby=&quot;five-years-in-one-table&quot;&gt;#&lt;/a&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Production&lt;/th&gt;
&lt;th&gt;Consumption&lt;/th&gt;
&lt;th&gt;Grid Purchased&lt;/th&gt;
&lt;th&gt;Self-consumed&lt;/th&gt;
&lt;th&gt;Solar Coverage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;8,065 kWh&lt;/td&gt;
&lt;td&gt;9,926 kWh&lt;/td&gt;
&lt;td&gt;4,549 kWh&lt;/td&gt;
&lt;td&gt;5,378 kWh&lt;/td&gt;
&lt;td&gt;54%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;9,320 kWh&lt;/td&gt;
&lt;td&gt;10,322 kWh&lt;/td&gt;
&lt;td&gt;4,482 kWh&lt;/td&gt;
&lt;td&gt;5,840 kWh&lt;/td&gt;
&lt;td&gt;57%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;8,459 kWh&lt;/td&gt;
&lt;td&gt;10,143 kWh&lt;/td&gt;
&lt;td&gt;4,827 kWh&lt;/td&gt;
&lt;td&gt;5,317 kWh&lt;/td&gt;
&lt;td&gt;52%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;8,706 kWh&lt;/td&gt;
&lt;td&gt;10,078 kWh&lt;/td&gt;
&lt;td&gt;4,661 kWh&lt;/td&gt;
&lt;td&gt;5,418 kWh&lt;/td&gt;
&lt;td&gt;54%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025&lt;/td&gt;
&lt;td&gt;8,624 kWh&lt;/td&gt;
&lt;td&gt;10,714 kWh&lt;/td&gt;
&lt;td&gt;4,953 kWh&lt;/td&gt;
&lt;td&gt;5,761 kWh&lt;/td&gt;
&lt;td&gt;54%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A few things stand out. 2022 was our best year by a wide margin — an exceptional spring that has never been repeated. Since then we’ve settled into a band of 8,400–8,700 kWh, which is probably where we’ll stay barring unusual weather.&lt;/p&gt;
&lt;p&gt;The column I pay most attention to is self-consumed solar — up from 5,378 kWh in year one to 5,761 kWh in year five, a 7% increase even though production has barely moved. The battery is doing its job. Our &lt;em&gt;Eigenverbrauchsquote&lt;/em&gt; (to use one of our famous long German words) aka. the solar coverage ratio has been remarkably stable at 52–57% across all five years, landing at 54% in three of those years.&lt;/p&gt;
&lt;h2 id=&quot;the-financial-reality&quot;&gt;The Financial Reality&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2025-solar-power-performance/#the-financial-reality&quot; aria-labelledby=&quot;the-financial-reality&quot;&gt;#&lt;/a&gt;&lt;p&gt;German residential electricity prices averaged around €0.38/kWh in 2025 — still the highest in the EU despite a slight easing from the 2023 peak of €0.47/kWh. Our current electricity contract is slightly lower at €0.29/kWh, however every kWh we produce ourselves is worth substantially more than when we installed the system.&lt;/p&gt;
&lt;p&gt;In 2025 we self-consumed 5,761 kWh of solar energy, representing €2,189 in avoided grid costs. We also exported 2,833 kWh back to the grid at the current feed-in tariff of ~7.9 ct/kWh, adding around €224 in income.&lt;/p&gt;
&lt;p&gt;Total 2025 benefit: roughly &lt;strong&gt;€2,400&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Over five years, we’ve self-consumed approximately 27,700 kWh in total. Even at a conservative blended average of €0.30/kWh (accounting for lower prices in the early years), that’s around €8,300 in cumulative grid savings — plus another around €1,000 in feed-in revenue across the period.&lt;/p&gt;
&lt;p&gt;The system is approaching the midpoint of its expected 20-year lifespan. At current benefit rates, we remain on track for a full payback well within that window.&lt;/p&gt;
&lt;h2 id=&quot;how-we-compare-to-other-german-systems&quot;&gt;How We Compare to Other German Systems&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2025-solar-power-performance/#how-we-compare-to-other-german-systems&quot; aria-labelledby=&quot;how-we-compare-to-other-german-systems&quot;&gt;#&lt;/a&gt;&lt;p&gt;For southern Germany, the typical annual yield benchmark is 1,000–1,200 kWh per kWp of installed capacity for ideally oriented systems. We live roughly in the middle of the country, where the forecast figures are somewhat lower. Our 9.45 kWp system produced 8,624 kWh in 2025 — a specific yield of &lt;strong&gt;912 kWh/kWp&lt;/strong&gt;. Our real-world yield reflects the actual installation geometry of our four-sided roof, with only the east, south and west sides covered by solar panels.&lt;/p&gt;
&lt;p&gt;Our 66.8% self-consumption rate places us well within the range for battery-equipped residential systems. &lt;a href=&quot;https://www.ise.fraunhofer.de/en/press-media/press-releases/2025/self-consumption-of-solar-power-is-rising-sharply-in-germany.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Fraunhofer ISE&lt;/a&gt; reports that self-consumption in Germany rose from 13% to 17% of total PV generation in 2024, driven by growing battery storage adoption. Systems with batteries typically reach 60–80% — we’re in the top portion of that range. Without a battery, systems self-consume 25–35% of their production — an example of why the battery pays for itself in terms of system efficiency.&lt;/p&gt;
&lt;h2 id=&quot;what%E2%80%99s-next&quot;&gt;What’s Next&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2025-solar-power-performance/#what%E2%80%99s-next&quot; aria-labelledby=&quot;what%E2%80%99s-next&quot;&gt;#&lt;/a&gt;&lt;p&gt;We had a smart meter installed at the end of 2025. The next step is obvious: switch to a dynamic electricity tariff. I’m not 100% sure yet, but with our battery and EV charging, we’re in a good place to make the most of changing prices.&lt;/p&gt;
&lt;p&gt;Regarding the system itself, after five years the panels show no obvious signs of degradation, the battery is in good condition and the SolarEdge inverter is working fine. Sometimes the best update is that everything just works.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;faq&quot;&gt;FAQ&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2025-solar-power-performance/#faq&quot; aria-labelledby=&quot;faq&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;strong&gt;How much electricity does a home solar system produce per year?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ours produced 8,624 kWh in 2025 — roughly what a typical German household consumes in a year. For us that’s no longer enough, since adding an EV pushed our annual consumption to over 10,700 kWh. We have 9.45 kWp installed; a typical single-family home in Germany can fit 10–12 kWp depending on roof size and orientation. The theoretical benchmark for a well-sited system is around 1,000–1,200 kWh per kWp installed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is a battery worth adding to a home solar system?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For us, clearly yes. Without a battery we’d self-consume maybe 25–35% of what we produce — the rest goes to the grid at the low feed-in rate. With our 10.5 kWh battery we’re at 66.8%. It shifts solar production from midday, when we don’t need it, to mornings and evenings, when we do. Five years in, that call still looks right.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How much money can a home solar system save per year in Germany?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In 2025 our system saved us around €2,400 in total: €2,189 from not buying that electricity from the grid, plus €224 in feed-in income. With grid prices at €0.38/kWh — and our own contract at €0.29/kWh — every kWh we produce ourselves is direct money saved. Five years in, the annual benefit has grown every year as prices have risen.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This post is part of my annual solar performance series. Previous years: &lt;a href=&quot;https://markus-haack.com/our-2024-solar-power-performance/&quot;&gt;2024&lt;/a&gt; · &lt;a href=&quot;https://markus-haack.com/solar-update-2023/&quot;&gt;2023&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Migrating from Plausible to Pirsch Analytics using Netlify Edge Functions</title>
    <link href="https://markus-haack.com/pirsch-analytics/"/>
    <updated>2025-12-20T00:00:00Z</updated>
    <id>https://markus-haack.com/pirsch-analytics/</id>
    <content type="html">&lt;p&gt;I’ve been a happy Plausible Analytics user for quite some time. The UI is clean, the solution is privacy-focused, and does exactly what it’s supposed to do. Honestly, there was no technical reason to switch — until we exceed the current subscription plan.&lt;/p&gt;
&lt;p&gt;Lately, my websites — this one and the &lt;a href=&quot;https://dino-fakten.de/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;dinosaur website of my daughter&lt;/a&gt; have seen a nice increase in traffic, consistently exceeding the 10k monthly pageview limit. While this growth is great, Plausible’s pricing model is a bit steep for hobby projects. The next tier with 100k monthly pageviews jumps straight to €190 + VAT (up from €90 + VAT). With both sites together receiving around 12,000 page views per month, there is certainly plenty of room for growth. However, I don’t think we’ll reach 100k in the next five years.&lt;/p&gt;
&lt;p&gt;That’s why I decided to move to &lt;a href=&quot;https://pirsch.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch.io&lt;/a&gt;. The analytics features offered by &lt;a href=&quot;http://Pirsch.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch.io&lt;/a&gt; are comparable with those offered by Plausible. Both tools are privacy-focused, no-cookie analytics solutions. Fortunately, both providers offer good documentation. This makes comparison easy, as does subsequent migration. The way in which website visitors and page views are counted is quite similar. &lt;a href=&quot;http://Pirsch.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch.io&lt;/a&gt; has slightly better bot detection, or at least better documentation of it. Otherwise, I can’t see any major differences.&lt;/p&gt;
&lt;p&gt;Plausible is certainly the more popular provider of the two, while &lt;a href=&quot;http://Pirsch.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch.io&lt;/a&gt; is the niche player from Germany. But in terms of pricing, &lt;a href=&quot;http://Pirsch.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch.io&lt;/a&gt; beats Plausible. They also offer a 100k plan for €120 + VAT per year. While the 10k page view plan is at €60 + VAT per year.&lt;/p&gt;
&lt;h2 id=&quot;the-migration&quot;&gt;The Migration&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#the-migration&quot; aria-labelledby=&quot;the-migration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The transition was remarkably smooth. Pirsch provides a built-in import tool for historical data from Google Analytics, Plausible Analytics and Fathom Analytics, so I didn’t lose any of my existing stats.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/pirsch-screenshot1.png&quot; alt=&quot;Pirsch Import Dashboard&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;I was able to import all historical data from Plausible simply via a CSV file.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-pirsch-analytics&quot;&gt;Setting up Pirsch Analytics&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#setting-up-pirsch-analytics&quot; aria-labelledby=&quot;setting-up-pirsch-analytics&quot;&gt;#&lt;/a&gt;&lt;p&gt;Setting up Pirsch Analytics is really easy.&lt;/p&gt;
&lt;p&gt;Once you have created your account, generate a tracking script via the &lt;a href=&quot;https://dashboard.pirsch.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch dashboard&lt;/a&gt;. You only need to provide the hostname of your website, an optional subdomain and a time zone. Once you have created your dashboard, you can select from the integration options. Finally, you will receive a custom JavaScript snippet specific to your website, which you should copy and paste into the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your website.&lt;/p&gt;
&lt;p&gt;There are also a large number of ready-made integrations for CMS (such as WordPress), e-commerce platforms (such as Shopify) or SSG frameworks (via Astro or Gatsby) available from the community.&lt;/p&gt;
&lt;p&gt;I went for a more advanced option via a bumpy round.&lt;/p&gt;
&lt;h3 id=&quot;using-a-proxy-with-netlify-edge-functions&quot;&gt;Using a Proxy with Netlify Edge Functions&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#using-a-proxy-with-netlify-edge-functions&quot; aria-labelledby=&quot;using-a-proxy-with-netlify-edge-functions&quot;&gt;#&lt;/a&gt;&lt;p&gt;I prefer to serve my analytics script through a proxy on my own domain. This ensures first-party data collection and helps bypass common ad-blocker issues. I have already used this pattern for my previous Plausible Analytics integration.&lt;/p&gt;
&lt;p&gt;Pirsch offers this proxy via a custom subdomain, but only with the Plus subscription. For those of us who want to save money, they provide &lt;a href=&quot;https://docs.pirsch.io/advanced/proxy#available-proxies&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;self-hosting proxy options&lt;/a&gt; in three different languages. PHP, Go and JavaScript.&lt;/p&gt;
&lt;p&gt;Since my sites are hosted on Netlify, I wanted to leverage &lt;a href=&quot;https://docs.netlify.com/build/edge-functions/overview/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Edge Functions&lt;/a&gt; for this. The Pirsch documentation includes a JavaScript &lt;a href=&quot;https://docs.pirsch.io/advanced/cf-workers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Cloudflare Worker proxy guide&lt;/a&gt;, but since the environments differ, the code needed some adjustments for Netlify.&lt;/p&gt;
&lt;p&gt;In order for our Edge proxy function to send analytics events to Pirsch securely, we need to generate an access key via the Pirsch dashboard. Navigate to the Integration Settings page of your Pirsch dashboard and click Add Client to create a new client. Set the type to ‘Access Key’. Give it a memorable name and click Create Client. Copy the access key and save it for later as it will not be visible again. We will configure it in Netlify as secure environment variable later.&lt;/p&gt;
&lt;h3 id=&quot;refactoring-with-cursor&quot;&gt;Refactoring with Cursor&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#refactoring-with-cursor&quot; aria-labelledby=&quot;refactoring-with-cursor&quot;&gt;#&lt;/a&gt;&lt;p&gt;Instead of rewriting the logic manually, I used Cursor. I provided the Cloudflare example and asked it to convert the code to a Netlify Edge Function.&lt;/p&gt;
&lt;p&gt;Cursor handled the conversion perfectly, mapping the correct Netlify header names and adjusting the fetch logic. I also had it move the Pirsch identification code into an environment variable to keep the repository clean.&lt;/p&gt;
&lt;p&gt;Here is a look at the core logic:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dashboards &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;markus-haack.com&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;accessKey&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; Netlify &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;undefined&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; Netlify&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Netlify&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;PIRSCH_CLIENT_EDGE&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; scriptPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/assets/js/pa.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pageViewPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/p/pv&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eventPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/p/e&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sessionPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/p/s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; accessControlAllowOrigin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pirschScriptURL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://api.pirsch.io/pa.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pirschPageViewEndpoint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://api.pirsch.io/api/v1/hit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pirschEventEndpoint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://api.pirsch.io/api/v1/event&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pirschSessionEndpoint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://api.pirsch.io/api/v1/session&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; scriptPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getScript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pirschScriptURL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; pageViewPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handlePageView&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; eventPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; sessionPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;404&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Access-Control-Allow-Origin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; accessControlAllowOrigin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Access-Control-Allow-Methods&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;GET, POST, OPTIONS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Access-Control-Allow-Headers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type, Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Accept-CH&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA, Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-Width, Sec-CH-Viewport-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getScript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;script&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&#39;Cache-Control&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;public, max-age=3600&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handlePageView&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pirschPageViewEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAccessKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;getRollupViews&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;accessKey&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pirschPageViewEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;accessKey&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            body
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pirschEventEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAccessKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;prefix&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rewritePath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prefix&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;getRollupViews&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;accessKey&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pirschEventEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;accessKey&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            body
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getClientIP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;user_agent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User-Agent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua_mobile&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Mobile&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua_platform&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Platform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua_platform_version&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Platform-Version&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_viewport_width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-Viewport-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pirschSessionEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAccessKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        body
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;getRollupViews&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;accessKey&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pirschSessionEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;accessKey&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            body
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getClientIP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;x-nf-client-connection-ip&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; 
           request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;x-forwarded-for&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; 
           &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAccessKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboardConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;accessKey &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getRollupViews&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboardConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;rollup &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboardConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; d &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; dashboards&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^www&#92;.&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; dashboards&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getHostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fromBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^www&#92;.&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; urlParam &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlParam&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^www&#92;.&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^www&#92;.&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; prefix&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rewritePath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prefix&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getClientIP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;user_agent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User-Agent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;accept_language&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Accept-Language&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua_mobile&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Mobile&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua_platform&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Platform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_ua_platform_version&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Platform-Version&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sec_ch_viewport_width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-Viewport-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;t&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;referrer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ref&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;screen_width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Number&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;screen_height&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Number&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;h&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; prefix&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rewritePath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prefix&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getClientIP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_agent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User-Agent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;accept_language &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Accept-Language&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sec_ch_ua &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sec_ch_ua_mobile &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Mobile&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sec_ch_ua_platform &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Platform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sec_ch_ua_platform_version &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-UA-Platform-Version&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sec_ch_width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sec_ch_viewport_width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sec-CH-Viewport-Width&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDashboardConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fromBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;options &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rewritePath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prefix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; suffix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; u &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; prefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; suffix&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;scriptPath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pageViewPath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; eventPath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sessionPath&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can find the full implementation, includuing comments and description in my GitHub repo:&lt;br&gt;
&lt;strong&gt;&lt;a href=&quot;https://markus-haack.com/pirsch-analytics/&quot;&gt;pirsch.js on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Depending on how the edge functions are stored in the project, they are either recognised automatically or must be declared separately in netlify.toml. In addition, you must map the function to one or more URL routes. This can be done automatically using function name matching, directly in the code, or via netlify.toml. I selected the code option via the &lt;code&gt;config&lt;/code&gt; object export, mapping the four paths that we are interested in. See above.&lt;/p&gt;
&lt;p&gt;In addition to path mapping for a URL route, there are &lt;a href=&quot;https://markus-haack.com/pirsch-analytics/&quot;&gt;other ways to link a function to a request&lt;/a&gt;, for example via HTTP headers.&lt;/p&gt;
&lt;h2 id=&quot;configuration-%26-setup&quot;&gt;Configuration &amp;amp; Setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#configuration-%26-setup&quot; aria-labelledby=&quot;configuration-%26-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;To get this running, you need to add the &lt;code&gt;PIRSCH_CODE&lt;/code&gt; to your Netlify environment variables. You can find this under Site configuration &amp;gt; Environment variables. Just create a new entry with your code from the Pirsch dashboard. For more details, check the &lt;a href=&quot;https://docs.netlify.com/build/configure-builds/environment-variables/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Netlify Docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;page-setup&quot;&gt;Page Setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#page-setup&quot; aria-labelledby=&quot;page-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;Finally, embed the script in your site’s &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; is needed. You can use the script generated during the initial dashboard setup as a starting point. We need to adjust it slightly to ensure that the analytics events are sent to our proxy. This means we need to change or replace the hostname and add additional hints to the Pirsch Analytics script to indicate where to send the data, depending on the paths configured in our edge function.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;src&lt;/code&gt; attribute must point to the proxy path of the JavaScript file. If you are running the proxy on the main hostname of your website, the path must be relative. However, if you have chosen to bind the proxy to a subdomain, the &lt;code&gt;src&lt;/code&gt; attribute must be an absolute URL. The same applies for the &lt;code&gt;data-hit-endpoint&lt;/code&gt;, &lt;code&gt;data-event-endpoint&lt;/code&gt; and &lt;code&gt;data-session-endpoint&lt;/code&gt; attributes. For my website the script tag looks like the following:&lt;/p&gt;
&lt;pre class=&quot;language-razor&quot;&gt;&lt;code class=&quot;language-razor&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;defer&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/assets/js/pa.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pirschjs&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-hit-endpoint&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/p/pv&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-event-endpoint&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/p/e&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;data-session-endpoint&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/p/s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/pirsch-analytics/#summary&quot; aria-labelledby=&quot;summary&quot;&gt;#&lt;/a&gt;&lt;p&gt;Would moving to &lt;a href=&quot;http://Pirsch.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pirsch.io&lt;/a&gt; be a good idea for my setup? How does it compare to Plausible in a real project? I suppose we’ll find out over the next few months. It’s definitely a more cost-effective option for my current level of traffic. pattern. The dashboard looks nice! as well. With the first data flowing in:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/pirsch-screenshot2.png&quot; alt=&quot;Pirsch Dashboard for markus-haack.com&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;From a technical perspective, setting up the Netlify Edge Function proxy with the help of Cursor took just minutes. For now, I can see that the proxy solution is working pretty reliably.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>My Home Assistant Setup 2025: Reolink, EVCC, and New Dashboards</title>
    <link href="https://markus-haack.com/jama-villa-2025/"/>
    <updated>2025-11-19T00:00:00Z</updated>
    <id>https://markus-haack.com/jama-villa-2025/</id>
    <content type="html">&lt;p&gt;Another year has passed and 2025 is coming to an end. Since my &lt;a href=&quot;https://markus-haack.com/jama-villa-2024/&quot;&gt;2024 update&lt;/a&gt;, our Home Assistant setup has continued to mature and there have been some notable additions and refinements worth sharing. This post outlines the changes, new devices and valuable insights gained over the past year.&lt;/p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#architecture&quot; aria-labelledby=&quot;architecture&quot;&gt;#&lt;/a&gt;&lt;p&gt;As always, here’s the updated architecture diagram to help visualize the entire setup:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/jama-villa-2025.png&quot; alt=&quot;Home Assistant Architecture Diagram 2025&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-foundation&quot;&gt;The Foundation&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#the-foundation&quot; aria-labelledby=&quot;the-foundation&quot;&gt;#&lt;/a&gt;&lt;p&gt;The &lt;a href=&quot;https://www.hardkernel.com/shop/odroid-n2-with-4gbyte-ram/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Odroid N2&lt;/a&gt; continues its remarkable run as the backbone of our system. Five years in, and it remains rock-solid reliable. I’ve already thought about upgrading to a Home Assistant Green Box, but so far there’s no real reason to upgrade. Sometimes the best upgrade is no upgrade at all.&lt;/p&gt;
&lt;p&gt;The same applies to our Ubiquiti network infrastructure, which remains unchanged with the Unifi UDM Pro](&lt;a href=&quot;https://ui.com/eu/en/cloud-gateways/dream-machine&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://ui.com/eu/en/cloud-gateways/dream-machine&lt;/a&gt;)o handling all routing duties. While this may be excessive for a residential setup, the stability and range of features make me confident that the investment is worthwhile.&lt;/p&gt;
&lt;p&gt;The core technologies powering our smart home:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device / Solution&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://sonoff.tech/product/gateway-and-sensors/sonoff-zigbee-3-0-usb-dongle-plus-p/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ZHA using SonOff ZigBee 3.0 USB dongle&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;This is the main ZigBee Hub with over 40 devices connected via ZHA.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.eq-3.com/start.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic CCU3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Still in place for some remaing r remaining sensors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.rademacher.de/en/smart-home/smart-home-systeme&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Rademacher DuoFern&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Continue to operate all the window blinds and shutters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://unifi-network.ui.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Ubiquiti UniFi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Our home network is operated by UniFi wired and wireless devices.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://reolink.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Reolink&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;New to the house: a Reolink camera surveillance system.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://tasmota.github.io/docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://www.shelly.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shelly&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A variety of Wi-Fi switches and sockets. The Shelly devices are permanently installed, whereas the Sonoff devices — primarily Wi-Fi sockets.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.keba.com/en/emobility/products/product-overview/keba-wallbox&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Keba P30&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Our EV charging station.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/&quot;&gt;Solaregde Inverter&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;We can harvest our own energy, free of charge, from the sun.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;electric-vehicle-charging&quot;&gt;Electric Vehicle Charging&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#electric-vehicle-charging&quot; aria-labelledby=&quot;electric-vehicle-charging&quot;&gt;#&lt;/a&gt;&lt;p&gt;One significant change this year was replacing our Mercedes with a &lt;a href=&quot;https://www.polestar.com/polestar-4/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Polestar 4&lt;/a&gt;. The switch meant updating our Home Assistant integration from MercedesME to the &lt;a href=&quot;https://github.com/pypolestar/polestar_api&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Polestar integration&lt;/a&gt;. Both car integrations in Home Assistant are custom components. Unfortunately, however, the one for Mercedes was significantly better and more comprehensive in terms of the data provided. This is simply because Mercedes provides a public API for developers, while Polestar unfortunately does not. This means that developers have to try to reverse engineer it. Polestar definitely has some catching up to do here; other car manufacturers are much more advanced in this respect.&lt;/p&gt;
&lt;p&gt;I should also mention our &lt;a href=&quot;https://www.keba.com/en/emobility/products/product-overview/keba-wallbox&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Keba P30 charging station&lt;/a&gt;, which I somehow forgot to document in previous posts despite having it for a while now. Combined with the Polestar integration, we now have complete visibility into our EV’s status and can automate charging based on electricity rates and solar availability.&lt;/p&gt;
&lt;p&gt;For optimized charging with solar power, we use EVCC. I have already written &lt;a href=&quot;https://markus-haack.com/evcc-setup-guide/&quot;&gt;an introduction and setup guide for EVCC&lt;/a&gt; and a &lt;a href=&quot;https://markus-haack.com/smart-ev-charging/&quot;&gt;guide to smart charging with AI&lt;/a&gt; control.&lt;/p&gt;
&lt;h2 id=&quot;cameras&quot;&gt;Cameras&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#cameras&quot; aria-labelledby=&quot;cameras&quot;&gt;#&lt;/a&gt;&lt;p&gt;Late 2024 brought another complete camera overhaul. After experimenting with Scrypted and HomeKit Secure Video throughout the year, I decided to replace all cameras with &lt;a href=&quot;https://reolink.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Reolink&lt;/a&gt; devices. The Hikvision and Tapo cameras were sold off, and the entire surveillance system was rebuilt from scratch.&lt;/p&gt;
&lt;p&gt;The Reolink cameras offer several advantages: &lt;a href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/&quot;&gt;excellent native Home Assistant integration&lt;/a&gt;, local recording without any cloud dependency, and superior image quality also with poor lighting conditions. The setup now includes a mix of Reolink PoE cameras at critical locations and WiFi models for easier installation in hard-to-wire areas.&lt;/p&gt;
&lt;h2 id=&quot;wireless-devices&quot;&gt;Wireless Devices&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#wireless-devices&quot; aria-labelledby=&quot;wireless-devices&quot;&gt;#&lt;/a&gt;&lt;p&gt;The ZigBee network grew significantly with approximately 15 new devices, primarily new sensors and a few additional smart sockets joined the fleet as well.&lt;/p&gt;
&lt;p&gt;On the WiFi side, we expanded our Tasmota fleet with four additional sockets (&lt;a href=&quot;https://nous.technology/product/nous-smart-wi-fi-socket-a1.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Nous A1&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://templates.blakadder.com/eightree_16A.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eightree&lt;/a&gt;). Their compact design and pre-flashed Tasmota firmware continue to make them an easy choice for quick smart home additions.&lt;/p&gt;
&lt;p&gt;We added more &lt;a href=&quot;https://www.shelly.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shelly switches&lt;/a&gt; (mostly Gen 2 &amp;amp; 3) for power monitoring and control. These replaced old Homematic components and provide more detailed energy data.&lt;/p&gt;
&lt;h2 id=&quot;other-hardware-changes&quot;&gt;Other hardware changes&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#other-hardware-changes&quot; aria-labelledby=&quot;other-hardware-changes&quot;&gt;#&lt;/a&gt;&lt;p&gt;In late 2024, a Brother printer was integrated into our Home Assistant smart home system. It replaced an HP Inkjet, which was great but died suddenly. The &lt;a href=&quot;https://www.home-assistant.io/integrations/brother/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant integration for the printer&lt;/a&gt; allows us to monitor ink levels, paper status, and printer availability directly from our dashboards.&lt;/p&gt;
&lt;h2 id=&quot;home-assistant&quot;&gt;Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#home-assistant&quot; aria-labelledby=&quot;home-assistant&quot;&gt;#&lt;/a&gt;&lt;h3 id=&quot;integrations-%26-custom-components&quot;&gt;Integrations &amp;amp; Custom Components&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#integrations-%26-custom-components&quot; aria-labelledby=&quot;integrations-%26-custom-components&quot;&gt;#&lt;/a&gt;&lt;p&gt;The integration list has grown with a few notable changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Replaced &lt;a href=&quot;https://github.com/ReneNulschDE/mbapi2020&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MercedesME 2020&lt;/a&gt; with the &lt;a href=&quot;https://github.com/pypolestar/polestar_api&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Polestar integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Added &lt;a href=&quot;https://www.home-assistant.io/integrations/keba/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Keba&lt;/a&gt; for the P30 charging station&lt;/li&gt;
&lt;li&gt;Added &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/home-assistant&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;EVCC add-on&lt;/a&gt; and the &lt;a href=&quot;https://github.com/marq24/ha-evcc&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ha-evcc custom component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Switched to &lt;a href=&quot;https://www.home-assistant.io/integrations/reolink/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Reolink&lt;/a&gt; for all camera integrations&lt;/li&gt;
&lt;li&gt;Added &lt;a href=&quot;https://www.home-assistant.io/integrations/brother/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Brother Printer&lt;/a&gt; for printer monitoring&lt;/li&gt;
&lt;li&gt;Added &lt;a href=&quot;https://www.home-assistant.io/integrations/apple_tv/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Apple TV&lt;/a&gt; for media control and HomeKit hub functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The full list remains extensive, covering everything from &lt;a href=&quot;https://www.home-assistant.io/integrations/zha/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ZHA&lt;/a&gt;, &lt;a href=&quot;https://www.home-assistant.io/integrations/shelly/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shelly&lt;/a&gt;, &lt;a href=&quot;https://www.home-assistant.io/integrations/tasmota/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt;, &lt;a href=&quot;https://www.home-assistant.io/integrations/adguard/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AdGuard Home&lt;/a&gt; to &lt;a href=&quot;https://www.home-assistant.io/integrations/wled/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;WLED&lt;/a&gt;, with &lt;a href=&quot;https://hacs.xyz/docs/configuration/basic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HACS&lt;/a&gt; providing access to custom components.&lt;/p&gt;
&lt;h3 id=&quot;dashboards&quot;&gt;Dashboards&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#dashboards&quot; aria-labelledby=&quot;dashboards&quot;&gt;#&lt;/a&gt;&lt;p&gt;I have made progress towards my goal of migrating from YAML to UI-based dashboards. All dashboards and automations are now managed via the UI. When working on the automations however I Still switch to YAML mode from time to time.&lt;/p&gt;
&lt;p&gt;I also change the main theme; our dashboards now have a shiny &lt;s&gt;liquid&lt;/s&gt; &lt;a href=&quot;https://github.com/wessamlauf/homeassistant-frosted-glass-themes&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;frosted glass&lt;/a&gt; look.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-dashboard-2025.png&quot; alt=&quot;Home Assistant Frosted Glass Dashboard&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The main dashboard has also been significantly overhauled. The dashboard is now cleaner. It got a &lt;a href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/&quot;&gt;nice weather card&lt;/a&gt;, and many details are displayed based on conditions. Information only shows up when it is really important and needed. I’m also a big fan of the &lt;a href=&quot;https://www.home-assistant.io/blog/2025/03/05/release-20253/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;new dashboard headers introduced&lt;/a&gt; in HA 2025.3 and with the new theme almost all custom CSS &amp;amp; card-mod styles go removed.&lt;/p&gt;
&lt;h3 id=&quot;backup&quot;&gt;Backup&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#backup&quot; aria-labelledby=&quot;backup&quot;&gt;#&lt;/a&gt;&lt;p&gt;Backing up to our Synology NAS using the native Home Assistant continues to work perfectly. However, the &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-2025/&quot;&gt;new backup capabilities and cloud-based backup options &lt;/a&gt;introduced in early 2025 mean that we now have many more backup options and better control over backups when performing Home Assistant or add-on updates. Automated weekly backups provide peace of mind, and the integration is so seamless that I rarely think about it anymore — exactly as it should be!&lt;/p&gt;
&lt;h2 id=&quot;summary-%26-outlook&quot;&gt;Summary &amp;amp; Outlook&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#summary-%26-outlook&quot; aria-labelledby=&quot;summary-%26-outlook&quot;&gt;#&lt;/a&gt;&lt;p&gt;This year’s updates were more evolutionary than revolutionary. The focus has been on incremental expansion, replacing aging devices with more reliable alternatives, and optimizing existing automations. The camera migration to Reolink was probably the most significant change, finally settling on a surveillance solution that checks all the boxes: local control, excellent quality, and no subscription fees.&lt;/p&gt;
&lt;p&gt;Integrating EVCC with our Keba charging station opens up new possibilities for energy management and smart charging automation.&lt;/p&gt;
&lt;h3 id=&quot;looking-ahead-to-2026&quot;&gt;Looking Ahead to 2026&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2025/#looking-ahead-to-2026&quot; aria-labelledby=&quot;looking-ahead-to-2026&quot;&gt;#&lt;/a&gt;&lt;p&gt;For 2026, I’m planning to explore the &lt;a href=&quot;https://www.home-assistant.io/integrations/matter/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Matter protocol&lt;/a&gt; and compatible devices in Home Assistant. I already have a few dual-stack light bulbs (ZigBee and Matter) that I’m eager to experiment with. So far, there hasn’t been a compelling reason to introduce Matter into our smart home - ZigBee has proven to be exceptionally stable and reliable.&lt;/p&gt;
&lt;p&gt;I also plan to further optimize our energy management automations, particularly around EV charging. The goal is to better align charging schedules with solar production and dynamic electricity pricing. We recently had a smart meter installed by our electricity grid provider, so now I just need to find a suitable variable-rate electricity tariff to take full advantage of it.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>DA Meets Universal Editor: Transforming Edge Delivery Workflows</title>
    <link href="https://markus-haack.com/adaptto-2025-da-ue/"/>
    <updated>2025-11-11T00:00:00Z</updated>
    <id>https://markus-haack.com/adaptto-2025-da-ue/</id>
    <content type="html">&lt;p&gt;This year, I once again had the honour of speaking at the &lt;a href=&quot;https://adapt.to/2025/schedule/unlocking-edge-delivery-authoring-with-authorbus&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;adaptTo() 2025&lt;/a&gt; conference in Berlin.&lt;/p&gt;
&lt;p&gt;Together with my colleague Max Voos, I introduced a new authoring paradigm for AuthorBus (formerly Dark Alley aka. DA) in a session.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=i6dJVELaB_o&amp;amp;t=1s&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=i6dJVELaB_o&amp;amp;t=1s&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We demonstrate how AuthorBus integrates with Universal Editor and Edge Delivery Services, providing attendees with insight into its technical architecture and underlying mechanics. The talk covered implementation requirements and best practices for adoption, showcasing this innovative approach to content authoring on DA. It enables content creators to transparently switch between free-form, document-based authoring and guided WYSIWYG authoring using Universal Editor.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Complete evcc Setup Guide: Step-by-Step Installation and Configuration</title>
    <link href="https://markus-haack.com/evcc-setup-guide/"/>
    <updated>2025-07-18T00:00:00Z</updated>
    <id>https://markus-haack.com/evcc-setup-guide/</id>
    <content type="html">&lt;p&gt;In &lt;a href=&quot;https://markus-haack.com/intro-into-evcc-charging/&quot;&gt;my previous post about evcc&lt;/a&gt;, I introduced you to this powerful open-source energy management system and explained why it’s essential for anyone with solar panels and an electric vehicle. Now it’s time to get our hands dirty with the actual setup and configuration process.&lt;/p&gt;
&lt;p&gt;This guide will walk you through exactly how I configured evcc with our specific hardware setup: a SolarEdge inverter with BYD battery, Keba P30 charger, and Polestar vehicle. Even if you have different equipment, the principles and process remain the same - you’ll just need to adapt the specific templates and settings.&lt;/p&gt;
&lt;p&gt;Let’s dive into the technical details and get your smart charging system up and running!&lt;/p&gt;
&lt;h2 id=&quot;installing-the-home-assistant-add-on&quot;&gt;Installing the Home Assistant Add-On&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#installing-the-home-assistant-add-on&quot; aria-labelledby=&quot;installing-the-home-assistant-add-on&quot;&gt;#&lt;/a&gt;&lt;p&gt;As I mentioned in part 1, I chose the Home Assistant Add-On route for our setup. The installation process using the &lt;a href=&quot;https://github.com/evcc-io/hassio-addon&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Add-On&lt;/a&gt; was straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add the evcc repository to Home Assistant&lt;/strong&gt; - you can do this &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/home-assistant&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;via the button on the docs page&lt;/a&gt; or manually by adding &lt;code&gt;https://github.com/evcc-io/hassio-addon&lt;/code&gt; to your Home Assistant add-on repositories&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install the add-on from the Add-on Store&lt;/strong&gt; - once the repository is added, you’ll find evcc in your Add-on Store&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure through the built-in assistant or manual YAML editing&lt;/strong&gt; - evcc provides both options depending on your preference&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The entire installation took just a few minutes, and I was ready to start configuring my specific hardware.&lt;/p&gt;
&lt;h2 id=&quot;configuring-our-smart-charging-setup&quot;&gt;Configuring Our Smart Charging Setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#configuring-our-smart-charging-setup&quot; aria-labelledby=&quot;configuring-our-smart-charging-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;evcc is configured via a central file, &lt;code&gt;evcc.yaml&lt;/code&gt;. For a new setup, it can be created either with the &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/configuration#running-the-assistant&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;configuration assistant&lt;/a&gt; or manually. The configuration assistant guides you step by step through the configuration of the various devices (photovoltaic system, electricity meter, house battery, EV charger and electric car).&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/configuration#creation&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;template file&lt;/a&gt; is provided for manual configuration. This provides the basic structure, and you can add your own devices and vehicles. There is extensive documentation for individual solar inverters, electricity meters, energy tariffs and vehicles, including customisable examples.&lt;/p&gt;
&lt;p&gt;If something does not work or you have problems with the configuration, evcc also offers a debug mode to check the configuration of the individual devices and correct it if necessary.&lt;/p&gt;
&lt;p&gt;In addition, evcc can be integrated into Home Assistant with just a REST and an MQTT API, allowing it to be integrated almost anywhere.&lt;/p&gt;
&lt;h2 id=&quot;our-hardware-setup&quot;&gt;Our Hardware Setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#our-hardware-setup&quot; aria-labelledby=&quot;our-hardware-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;As you could already read in my &lt;a href=&quot;https://markus-haack.com/our-own-electricity-1/&quot;&gt;Going Green&lt;/a&gt; articles, our photovoltaic system features a SolarEdge inverter with a 10 kW BYD Battery. As EV Charger we have a Keba P30 c-series and currently we drive a Polestar. I will now provide an explanation of how to integrate these components into evcc and use them as examples.&lt;/p&gt;
&lt;p&gt;The first configuration steps are the global &lt;code&gt;site&lt;/code&gt; settings such as name and the existing &lt;code&gt;loadpoints&lt;/code&gt;. A load point is the designation for your charging station, for example a garage or carport. evcc supports more complex setups such as apartment blocks with several charging points. In our case it is only one EV charger in the carport.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa
  &lt;span class=&quot;token key atrule&quot;&gt;meters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_grid
    &lt;span class=&quot;token key atrule&quot;&gt;pv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; my_pv
    &lt;span class=&quot;token key atrule&quot;&gt;battery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; my_battery

&lt;span class=&quot;token key atrule&quot;&gt;loadpoints&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Carport
    &lt;span class=&quot;token key atrule&quot;&gt;charger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_charger
    &lt;span class=&quot;token key atrule&quot;&gt;vehicle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_car&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;solaredge-system-integration&quot;&gt;SolarEdge System Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#solaredge-system-integration&quot; aria-labelledby=&quot;solaredge-system-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The next step is to define the &lt;code&gt;meters&lt;/code&gt;. These are the existing electricity meters for the different sources, but at least the solar inverter and electricity grid. Optionally, if a home battery is installed, it will be metered as well.&lt;/p&gt;
&lt;p&gt;Our case the &lt;a href=&quot;https://docs.evcc.io/en/docs/devices/meters#solaredge&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge hybrid inverter&lt;/a&gt; with battery storage required three meter configurations:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;meters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_grid
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
    &lt;span class=&quot;token key atrule&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; solaredge&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;hybrid
    &lt;span class=&quot;token key atrule&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid
    &lt;span class=&quot;token key atrule&quot;&gt;modbus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tcpip
    &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; modbus&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;proxy
    &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1502&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10s
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_pv
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
    &lt;span class=&quot;token key atrule&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; solaredge&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;hybrid
    &lt;span class=&quot;token key atrule&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pv
    &lt;span class=&quot;token key atrule&quot;&gt;modbus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tcpip
    &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; modbus&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;proxy
    &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1502&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10s
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_battery
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
    &lt;span class=&quot;token key atrule&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; solaredge&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;hybrid
    &lt;span class=&quot;token key atrule&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; battery
    &lt;span class=&quot;token key atrule&quot;&gt;modbus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tcpip
    &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; modbus&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;proxy
    &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1502&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see as &lt;code&gt;host&lt;/code&gt; address I do not use the IP address of the inverter directly, but the host name of a “ModBus proxy”. This is necessary because the SolarEdge inverters only allow one client on the ModBus server. As I had &lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/#two-integration-options&quot;&gt;already integrated the SolarEdge inverter directly into Home Assistant&lt;/a&gt;, I had to find another solution. A ModBus proxy makes it possible for multiple clients to access a ModBus server, even if this server did not originally support this. There are several options for a ModBus proxy, I use a separate &lt;a href=&quot;https://github.com/Akulatraxas/ha-modbusproxy&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant AddOn&lt;/a&gt;, but &lt;a href=&quot;https://docs.evcc.io/en/docs/reference/configuration/modbusproxy&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;evcc can also take over this task&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The configuration of other solar inverters, especially via ModBus, is very similar.&lt;/p&gt;
&lt;p&gt;Once the meters are configured the configuration can be checked via the following command:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;/app &lt;span class=&quot;token comment&quot;&gt;# evcc -c /homeassistant/evcc.yaml meter&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;main  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; INFO &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;/07/05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:07:51 using config file: /homeassistant/evcc.yaml
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;db    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; INFO &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;/07/05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:07:51 using sqlite database: /root/.evcc/evcc.db
my_pv
-----
Power: 1748W

my_battery
----------
Power:        &lt;span class=&quot;token parameter variable&quot;&gt;-0W&lt;/span&gt;
Soc:          &lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;%
Controllable: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;

my_grid
-------
Power:          &lt;span class=&quot;token parameter variable&quot;&gt;-818W&lt;/span&gt;
Energy:         &lt;span class=&quot;token number&quot;&gt;23571&lt;/span&gt;.0kWh
Current L1&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;L3: &lt;span class=&quot;token parameter variable&quot;&gt;-1.78A&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;.817A &lt;span class=&quot;token parameter variable&quot;&gt;-2.18A&lt;/span&gt;
Voltage L1&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;L3: 227V 228V 229V
Power L1&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;L3:   &lt;span class=&quot;token parameter variable&quot;&gt;-358W&lt;/span&gt; 14W &lt;span class=&quot;token parameter variable&quot;&gt;-479W&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are, like me, running evcc via the Home Assistant AddOn you need to use Docker command to open a shell first, this is described &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/home-assistant#how-can-i-use-the-evcc-cli&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;keba-p30-charger-configuration&quot;&gt;Keba P30 Charger Configuration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#keba-p30-charger-configuration&quot; aria-labelledby=&quot;keba-p30-charger-configuration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The next and most important device we need to configure is the charging station for our electric vehicle.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;chargers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_charger
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
    &lt;span class=&quot;token key atrule&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; keba&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;modbus
    &lt;span class=&quot;token key atrule&quot;&gt;modbus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tcpip
    &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.1.111
    &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;502&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;welcomecharge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like the majority of chargers, our Keba P30 c-series Wallbox is also addressed via Modbus TCP. Integration is very simple, you just have to use the correct configuration template and specify the IP address. A sponsor token is always required for a Keba charging station, like for many other charger brands as well.&lt;/p&gt;
&lt;p&gt;A special feature of our charger is the authorisation to unlock the car charging. This is valid for 1 minute after the charging station has been activated. If no charging is started during this time, it expires and you have to re-authorise yourself with an RFID card or app. evcc therefore starts a ‘welcome charge’ so that the wallbox is not blocked again after 1 minute.&lt;/p&gt;
&lt;p&gt;Unlocking the EV charger &lt;a href=&quot;https://markus-haack.com/smart-ev-charging/&quot;&gt;can be automated very easily via Home Assistant&lt;/a&gt;, with that no RFID card or charger app is needed.&lt;/p&gt;
&lt;p&gt;There is also a check command for the charger. In my case the output looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;/app &lt;span class=&quot;token comment&quot;&gt;# evcc -c /homeassistant/evcc.yaml charger&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;main  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; INFO &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;/07/05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:10:23 using config file: /homeassistant/evcc.yaml
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;db    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; INFO &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;/07/05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:10:23 using sqlite database: /root/.evcc/evcc.db
Power:          0W
Energy:         &lt;span class=&quot;token number&quot;&gt;8071&lt;/span&gt;.9kWh
Current L1&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;L3: 0A 0A 0A
Charge status:  B
Status reason:  unknown
Enabled:        &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
Identifier:     AABBCCDD
Features:       &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;WelcomeCharge&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;polestar-integration&quot;&gt;Polestar Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#polestar-integration&quot; aria-labelledby=&quot;polestar-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;Most chargers do not have the capability to read the State of Charge (SoC) of the car. That’s why we also want our car to be integrated with evcc. The software can then communicate directly with the vehicle via the manufacturer’s cloud service. A car integration is not strictly necessary and guest cars can be charged as well. However, if you own several vehicles and want to allocate the charging sessions and costs to the respective vehicle, the configuration is required. It also allows you to setup charging plans.&lt;/p&gt;
&lt;p&gt;The Polestar integration, similar to other cars as well, provides state of charge, charging status, and remaining range. This enables evcc to calculate optimal charging schedules and stop charging at predetermined levels.&lt;/p&gt;
&lt;p&gt;The config looks like:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;vehicles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_car
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
    &lt;span class=&quot;token key atrule&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; polestar
    &lt;span class=&quot;token key atrule&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; abcd@gmail.com
    &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my_password
    &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Polestar
    &lt;span class=&quot;token key atrule&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;identifiers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; AABBCCDD &lt;span class=&quot;token comment&quot;&gt;# RFID token ID&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;capacity&lt;/code&gt; is important here as this can not be automatically detected. In some cases, depending on the car brand, there is also a range of advanced options for the vehicle.&lt;/p&gt;
&lt;p&gt;Similarly to the above, the vehicle configuration can also be checked via the command line:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;/app &lt;span class=&quot;token comment&quot;&gt;# evcc -c /homeassistant/evcc.yaml vehicle&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;main  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; INFO &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;/07/05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:23:39 using config file: /homeassistant/evcc.yaml
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;db    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; INFO &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;/07/05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:23:39 using sqlite database: /root/.evcc/evcc.db
Soc:           &lt;span class=&quot;token number&quot;&gt;90&lt;/span&gt;%
Capacity:      &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;.0kWh
Charge status: A
Range:         553km
Odometer:      9999km
Finish time:   &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt;-07-05 &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;:24:00 +0200 CEST
Identifiers:   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;AABBCCDD&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;energy-tariff-configuration&quot;&gt;Energy Tariff Configuration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#energy-tariff-configuration&quot; aria-labelledby=&quot;energy-tariff-configuration&quot;&gt;#&lt;/a&gt;&lt;p&gt;In contrast to other countries, dynamic electricity tariffs are not yet widespread in Germany. There is a lack of infrastructure here and our electricity meters are not yet suitable for this. I have already ordered a new meter from our grid operator, but it will probably be a few months before it is installed.&lt;/p&gt;
&lt;p&gt;evcc supports dynamic electricity tariffs in various countries and from various providers. When combined with charging plans, evcc automatically schedules charging sessions during low-price periods while still prioritizing solar energy. But we have to live with a fixed electricity tariff for now. The configuration for this is super simple:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;tariffs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; EUR
  &lt;span class=&quot;token key atrule&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; fixed
    &lt;span class=&quot;token key atrule&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.30&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# EUR/kWh&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;feedin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; fixed
    &lt;span class=&quot;token key atrule&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.09&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# EUR/kWh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;it%E2%80%99s-alive!-let%E2%80%99s-charge&quot;&gt;It’s Alive! Let’s Charge&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#it%E2%80%99s-alive!-let%E2%80%99s-charge&quot; aria-labelledby=&quot;it%E2%80%99s-alive!-let%E2%80%99s-charge&quot;&gt;#&lt;/a&gt;&lt;p&gt;And that’s it. The complete configuration took about 30 minutes. I already had all the information for the respective devices available. I was able to copy most of it directly from Home Assistant.&lt;/p&gt;
&lt;p&gt;Now it’s time to connect the vehicle to the EV Charger and start the first charging process. Ideally on a sunny day. If everything is configured correctly, evcc should now start correctly and in the user interface we should be able to see the power generation data, the consumption, the status of the house battery and, most importantly, the charging process of the vehicle.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/evcc-2.png&quot; alt=&quot;evcc - car charging user interface&quot; title=&quot;evcc - car charging user interface&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;evcc - car charging user interface&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;cost-analysis-and-savings&quot;&gt;Cost Analysis and Savings&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#cost-analysis-and-savings&quot; aria-labelledby=&quot;cost-analysis-and-savings&quot;&gt;#&lt;/a&gt;&lt;p&gt;While it’s still early days, I’m already seeing the benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduced Grid Consumption&lt;/strong&gt;: In June &amp;amp; July we charged our car 13 times - 268,4 kWh so far with 71% solar power&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better Feed-in Utilization&lt;/strong&gt;: Rather than selling excess solar power for 9 cents/kWh, we’re using it to avoid buying grid power at 30 cents/kWh&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimized Battery Usage&lt;/strong&gt;: The home battery provides backup during cloud cover, reducing charging interruptions&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;questions-about-evcc-setup&quot;&gt;Questions about evcc setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#questions-about-evcc-setup&quot; aria-labelledby=&quot;questions-about-evcc-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;These are the top 5 questions I collected related to your own evcc setup:&lt;/p&gt;
&lt;h3 id=&quot;1.-do-i-need-the-exact-same-hardware-setup-to-follow-this-guide%3F&quot;&gt;1. &lt;strong&gt;Do I need the exact same hardware setup to follow this guide?&lt;/strong&gt;&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#1.-do-i-need-the-exact-same-hardware-setup-to-follow-this-guide%3F&quot; aria-labelledby=&quot;1.-do-i-need-the-exact-same-hardware-setup-to-follow-this-guide%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;No of course not, evcc supports a wide range of equipment from different manufacturers. The configuration principles remain the same - you’ll just need to use the appropriate templates for your specific solar inverter, charger, and car. Check the &lt;a href=&quot;https://docs.evcc.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;evcc documentation&lt;/a&gt; for your hardware’s compatibility and templates.&lt;/p&gt;
&lt;h3 id=&quot;2.-what-if-my-inverter-only-allows-one-modbus-connection%3F&quot;&gt;2. &lt;strong&gt;What if my inverter only allows one ModBus connection?&lt;/strong&gt;&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#2.-what-if-my-inverter-only-allows-one-modbus-connection%3F&quot; aria-labelledby=&quot;2.-what-if-my-inverter-only-allows-one-modbus-connection%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;There are a few solar inverters, like ours from Solaredge, which only support one ModBus connection. Use a ModBus proxy to allow multiple connections. You can either install a separate &lt;a href=&quot;https://github.com/Akulatraxas/ha-modbusproxy&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant ModBus Proxy AddOn&lt;/a&gt; or use evcc’s built-in ModBus proxy functionality.&lt;/p&gt;
&lt;h3 id=&quot;3.-is-vehicle-integration-mandatory-for-evcc-to-work%3F&quot;&gt;3. &lt;strong&gt;Is vehicle integration mandatory for evcc to work?&lt;/strong&gt;&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#3.-is-vehicle-integration-mandatory-for-evcc-to-work%3F&quot; aria-labelledby=&quot;3.-is-vehicle-integration-mandatory-for-evcc-to-work%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;No, vehicle integration is optional. evcc works fine without connecting to your car’s cloud service. However, integrating your vehicle provides State of Charge monitoring, charging plans, cost allocation for multiple vehicles, and better optimization. Guest vehicles can still be charged without integration.&lt;/p&gt;
&lt;h3 id=&quot;4.-how-long-does-the-initial-setup-and-configuration-take%3F&quot;&gt;4. &lt;strong&gt;How long does the initial setup and configuration take?&lt;/strong&gt;&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#4.-how-long-does-the-initial-setup-and-configuration-take%3F&quot; aria-labelledby=&quot;4.-how-long-does-the-initial-setup-and-configuration-take%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;About 30 minutes total once you have all device information ready. Installation via Home Assistant Add-on Store takes just a few minutes, configuration takes 20-30 minutes, and testing another 10-15 minutes. Preparation time varies depending on whether you need to research device specifications.&lt;/p&gt;
&lt;h3 id=&quot;5.-what-are-the-real-world-savings-i-can-expect-with-evcc%3F&quot;&gt;5. &lt;strong&gt;What are the real-world savings I can expect with evcc?&lt;/strong&gt;&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#5.-what-are-the-real-world-savings-i-can-expect-with-evcc%3F&quot; aria-labelledby=&quot;5.-what-are-the-real-world-savings-i-can-expect-with-evcc%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;Based on early results: 71% of EV charging powered by solar energy, avoiding 30 cents/kWh grid power by using 9 cents/kWh solar instead. evcc users report 50-80% solar-powered charging in good conditions. Actual savings depend on your solar system size, local electricity rates, car driving patterns, and weather.&lt;/p&gt;
&lt;h2 id=&quot;summary%3A-your-smart-charging-system-awaits&quot;&gt;Summary: Your Smart Charging System Awaits&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/evcc-setup-guide/#summary%3A-your-smart-charging-system-awaits&quot; aria-labelledby=&quot;summary%3A-your-smart-charging-system-awaits&quot;&gt;#&lt;/a&gt;&lt;p&gt;Setting up evcc turned out to be much easier than I expected. Excellent documentation and well-documented templates for devices and vehicles made the configuration process straightforward.&lt;/p&gt;
&lt;p&gt;If you have the basic components - solar panels, an EV charger, and an electric vehicle - evcc can transform your charging experience from a simple plug-and-go to an intelligent, cost-optimized system that maximizes your renewable energy usage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ready to optimize your own EV charging?&lt;/strong&gt; The evcc community is incredibly helpful, and the documentation is comprehensive. Whether you choose the Home Assistant add-on route like me or prefer a different installation method, you’ll have your smart charging system up and running in no time.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Introduction to evcc: Smart Solar EV Charging Made Simple</title>
    <link href="https://markus-haack.com/intro-into-evcc-charging/"/>
    <updated>2025-07-05T00:00:00Z</updated>
    <id>https://markus-haack.com/intro-into-evcc-charging/</id>
    <content type="html">&lt;p&gt;Two weeks ago, I took the next step in optimizing our smart home energy setup by implementing &lt;a href=&quot;https://evcc.io/en/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;evcc&lt;/a&gt; (Electric Vehicle Charging Controller). This post describes my journey and gives you a complete introduction to what evcc can do for your EV charging setup.&lt;/p&gt;
&lt;p&gt;Are you the proud owner of an electric car? Do you charge it at home? Have you installed a photovoltaic system on your roof? If so, then this article is exactly what you’re looking for!&lt;/p&gt;
&lt;p&gt;Look no further if you want to find the best and most cost-effective ways to charge your car with as much solar power as possible.&lt;/p&gt;
&lt;p&gt;I’m becoming a big fan of evcc, and I’m happy to share my experiences with it so far. To avoid making this post too long, I will give an introduction to evcc and explain what it does and why you should care. In a &lt;a href=&quot;https://markus-haack.com/evcc-setup-guide/&quot;&gt;second post&lt;/a&gt;, I’ll walk you through the complete setup and configuration process with real-world examples.&lt;/p&gt;
&lt;h2 id=&quot;what-is-evcc-and-why-should-you-care%3F&quot;&gt;What is evcc and Why Should You Care?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#what-is-evcc-and-why-should-you-care%3F&quot; aria-labelledby=&quot;what-is-evcc-and-why-should-you-care%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://evcc.io/en/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;evcc.io&lt;/a&gt;&lt;/strong&gt; is an open-source energy management system specifically designed for electric vehicle charging optimization. Think of it as the brain that decides when, how fast, and with what energy source your EV should charge.&lt;/p&gt;
&lt;p&gt;The core functionality of evcc revolves around surplus solar charging - using your excess photovoltaic energy to charge your electric car instead of feeding it back to the grid.&lt;/p&gt;
&lt;p&gt;But it goes beyond simple solar charging, it also handles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intelligent load management based on current household consumption&lt;/li&gt;
&lt;li&gt;Dynamic pricing integration to charge when electricity is cheapest&lt;/li&gt;
&lt;li&gt;Charging planning to ensure your car is ready when you need it&lt;/li&gt;
&lt;li&gt;Home Assistant integration for seamless automation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What sets evcc apart is its manufacturer-agnostic approach. evcc isn’t proprietary and works with all sorts of brands and devices. At the time of writing this post 106 EV charger brands, 28 car brands, 21 heat pumps &amp;amp; electric heaters, 71 solar inverter &amp;amp; storage systems and 82 energy meters are supported.&lt;/p&gt;
&lt;p&gt;Yes, there are also other (commercial) solutions for smart electric car charging, for example from energy providers or EV charger manufacturers, but which solution covers such a broad set of devices and vehicles?&lt;/p&gt;
&lt;p&gt;Where can you combine a Keba P30 EV charger, a SolarEdge solar inverter and a BYD battery storage system with a Polestar vehicle, all of which work together intelligently?&lt;/p&gt;
&lt;h2 id=&quot;how-does-evcc-work&quot;&gt;How does evcc Work&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#how-does-evcc-work&quot; aria-labelledby=&quot;how-does-evcc-work&quot;&gt;#&lt;/a&gt;&lt;p&gt;The basic functions of evcc are pretty simple. The software handles your electricity sources, like our photovoltaic system and the grid, the state of the home battery, and the charging status of your electric vehicle.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/evcc-diagram.png&quot; alt=&quot;Energy flow and control diagram&quot; title=&quot;evcc controlling the energy flow&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;evcc controlling the energy flow&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It uses all the data points to work out the best charge rate and time for your electric vehicle, based on how much solar power is being produced at the moment and the electricity tariff. The idea is to make sure you’ve got as much surplus energy as possible, while also keeping grid electricity costs as low as possible.&lt;/p&gt;
&lt;p&gt;The software runs always on your local hardware. It is cloud-free, privacy-friendly and independent of any charging, solar or electric vehicles brands. It is an open-source development, and the entire codebase can be found on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;evcc-io/evcc&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;As they don’t receive any external funding from vendors, the developers have chosen a community-funding-based approach to maintain the software. To use some of the commercial EV charger devices, you will need a sponsoring token. See the &lt;a href=&quot;https://docs.evcc.io/en/docs/sponsorship&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;sponsorship documentation&lt;/a&gt; for more details. If you are not yet sure whether evcc is right for you, don’t worry — you can also get a trial token and test whether all your hardware works together properly.&lt;/p&gt;
&lt;h2 id=&quot;understanding-the-charging-modes&quot;&gt;Understanding the Charging Modes&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#understanding-the-charging-modes&quot; aria-labelledby=&quot;understanding-the-charging-modes&quot;&gt;#&lt;/a&gt;&lt;p&gt;evcc offers three distinct charging modes, each serving different scenarios. In fact, there are four modes if we include “off”.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/evcc-1.png&quot; alt=&quot;evcc charging modes&quot; title=&quot;evcc charging modes&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;evcc charging modes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3 id=&quot;pv-mode-(solar-only)&quot;&gt;PV Mode (Solar Only)&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#pv-mode-(solar-only)&quot; aria-labelledby=&quot;pv-mode-(solar-only)&quot;&gt;#&lt;/a&gt;&lt;p&gt;This is my favorite mode, as it only charges when there is sufficient solar surplus. Charging begins when your PV system generates more energy than your household uses, and the power is constantly adjusted to minimise grid import and export.&lt;/p&gt;
&lt;h3 id=&quot;min%2Bpv-mode&quot;&gt;Min+PV Mode&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#min%2Bpv-mode&quot; aria-labelledby=&quot;min%2Bpv-mode&quot;&gt;#&lt;/a&gt;&lt;p&gt;It offers the best of both worlds, starting to charge immediately at a minimum power level (typically 6A) and increasing the power when a solar surplus is available. This ensures that charging always occurs while maximising solar utilisation.&lt;/p&gt;
&lt;p&gt;The beauty of evcc’s approach is the continuous power adjustment. Unlike simple on/off solar charging solutions, evcc adjusts the charging current in real time based on available surplus, ensuring that every watt counts.&lt;/p&gt;
&lt;p&gt;You can also configure a minimum SOC for the car battery. If the current charging state is below this level, evcc will charge in fast mode until the minimum SOC is reached and than switch to solar surplus charging. This ensures that you have enough power the next time you need the car.&lt;/p&gt;
&lt;h3 id=&quot;fast-mode&quot;&gt;Fast Mode&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#fast-mode&quot; aria-labelledby=&quot;fast-mode&quot;&gt;#&lt;/a&gt;&lt;p&gt;Maximum power charging, regardless of solar production or electricity prices. This is the ‘I need to leave in an hour’ mode, which charges as quickly as possible using any available solar power and grid power if necessary.&lt;/p&gt;
&lt;h3 id=&quot;off-mode&quot;&gt;Off Mode&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#off-mode&quot; aria-labelledby=&quot;off-mode&quot;&gt;#&lt;/a&gt;&lt;p&gt;Charging is completely disabled, even when a vehicle is connected. This mode can be useful for maintenance or when you want to prevent any charging.&lt;/p&gt;
&lt;h2 id=&quot;battery-support&quot;&gt;Battery Support&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#battery-support&quot; aria-labelledby=&quot;battery-support&quot;&gt;#&lt;/a&gt;&lt;p&gt;If your photovoltaic installation includes a home battery, it can support EV charging.&lt;/p&gt;
&lt;p&gt;On days when it is slightly cloudy and the clouds are moving quickly, there can be fluctuations in the electricity yield of the solar cells. In such cases, the battery backup is very advantageous as it can provide short-term power to bridge the gap when shade is cast over the cells. This means that charging the vehicle does not need to be interrupted so frequently. Of course you can adjust the home battery SOC levels according to your needs.&lt;/p&gt;
&lt;h2 id=&quot;installation-options%3A-which-route-should-you-choose%3F&quot;&gt;Installation Options: Which Route Should You Choose?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#installation-options%3A-which-route-should-you-choose%3F&quot; aria-labelledby=&quot;installation-options%3A-which-route-should-you-choose%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;evcc offers &lt;a href=&quot;https://docs.evcc.io/en/docs/installation&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;several installation methods&lt;/a&gt;, each with its own advantages:&lt;/p&gt;
&lt;h3 id=&quot;linux%2Fraspberry-pi-native&quot;&gt;Linux/Raspberry Pi Native&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#linux%2Fraspberry-pi-native&quot; aria-labelledby=&quot;linux%2Fraspberry-pi-native&quot;&gt;#&lt;/a&gt;&lt;p&gt;Direct installation via APT repository offers the best performance and easiest troubleshooting. This is ideal if you have a dedicated Linux system or Raspberry Pi. In my opinion, this setup is more suitable for advanced users, as you need to ensure that the entire system is kept updated and patched, and that you back up your data yourself, etc.&lt;/p&gt;
&lt;h3 id=&quot;proxmox&quot;&gt;Proxmox&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#proxmox&quot; aria-labelledby=&quot;proxmox&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you already use &lt;a href=&quot;https://www.proxmox.com/en/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Proxmox&lt;/a&gt; as a virtualisation platform, this is probably where you want to host evcc as well. The installation process is similar to that for a dedicated Linux server.&lt;/p&gt;
&lt;h3 id=&quot;docker-installation&quot;&gt;Docker Installation&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#docker-installation&quot; aria-labelledby=&quot;docker-installation&quot;&gt;#&lt;/a&gt;&lt;p&gt;Docker is perfect for NAS systems such as Synology, Unraid and QNAP, providing isolation and easy updates. However, this will require some experience with Docker. There are community guides dedicated to running an evcc Docker setup on &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/docker#synology-nas&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Synology&lt;/a&gt; and &lt;a href=&quot;https://docs.evcc.io/en/docs/installation/docker#qnap-nas&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;QNAP&lt;/a&gt; NAS systems.&lt;/p&gt;
&lt;h3 id=&quot;macos&quot;&gt;macOS&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#macos&quot; aria-labelledby=&quot;macos&quot;&gt;#&lt;/a&gt;&lt;p&gt;The setup on macOS is pretty easy, as evcc can be installed via Homebrew within minutes.&lt;/p&gt;
&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#windows&quot; aria-labelledby=&quot;windows&quot;&gt;#&lt;/a&gt;&lt;p&gt;It is possible to run evcc on Windows, but the creators do not really recommend it as it is Linux software.&lt;/p&gt;
&lt;h3 id=&quot;home-assistant-add-on%3A-my-choice&quot;&gt;Home Assistant Add-On: My Choice&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#home-assistant-add-on%3A-my-choice&quot; aria-labelledby=&quot;home-assistant-add-on%3A-my-choice&quot;&gt;#&lt;/a&gt;&lt;p&gt;This is the route I chose as a Home Assistant user, and for good reason. Since our entire smart home &lt;a href=&quot;https://markus-haack.com/jama-villa-2024/&quot;&gt;runs on Home Assistant&lt;/a&gt;, having evcc as a native add-on was the obvious choice for me. It provides me with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Seamless integration with existing Home Assistant entities&lt;/li&gt;
&lt;li&gt;A single interface for managing all smart home devices&lt;/li&gt;
&lt;li&gt;Unified configuration, logging and troubleshooting&lt;/li&gt;
&lt;li&gt;No need for an additional mobile app&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The installation process using the &lt;a href=&quot;https://github.com/evcc-io/hassio-addon&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Add-On&lt;/a&gt; was straightforward - I’ll walk you through the complete process in my setup guide.&lt;/p&gt;
&lt;h2 id=&quot;why-i-think-evcc-is-essential-for-solar-ev-owners&quot;&gt;Why I Think evcc is Essential for Solar EV Owners&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#why-i-think-evcc-is-essential-for-solar-ev-owners&quot; aria-labelledby=&quot;why-i-think-evcc-is-essential-for-solar-ev-owners&quot;&gt;#&lt;/a&gt;&lt;p&gt;After two weeks of using evcc, I can say it’s exactly what smart home technology should be: intelligent, automated, and genuinely useful.&lt;/p&gt;
&lt;p&gt;It transforms our EV charging into a seamless process that optimizes for cost, environment, and convenience. For anyone with solar panels and an electric vehicle, evcc is not just recommended – if you ask me – it’s essential.&lt;/p&gt;
&lt;p&gt;Here’s why I’m such a fan:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Universal Compatibility:&lt;/strong&gt; Unlike proprietary solutions, evcc works with virtually any combination of equipment. You’re not locked into specific brands and can combine devices from different vendors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Real Cost Savings:&lt;/strong&gt; Instead of selling your excess solar power back to the grid for a few cents and then buying expensive grid electricity to charge your car, evcc helps you use your own renewable energy directly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Privacy-Focused:&lt;/strong&gt; The software runs always on your local hardware. It is cloud-free, privacy-friendly and independent of any charging, solar or electric vehicle brands.&lt;/p&gt;
&lt;h2 id=&quot;what%E2%80%99s-next%3A-ready-to-set-it-up%3F&quot;&gt;What’s Next: Ready to Set It Up?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/intro-into-evcc-charging/#what%E2%80%99s-next%3A-ready-to-set-it-up%3F&quot; aria-labelledby=&quot;what%E2%80%99s-next%3A-ready-to-set-it-up%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you’re interested in implementing evcc for your setup, the next step is the actual installation and configuration. This involves configuring your specific solar inverter, EV charger, and vehicle - which can seem daunting but is actually quite straightforward with the right guidance.&lt;/p&gt;
&lt;p&gt;In my next post “&lt;a href=&quot;https://markus-haack.com/evcc-setup-guide/&quot;&gt;Complete evcc Setup Guide: Step-by-Step Installation and Configuration&lt;/a&gt;”, I’ll share the complete step-by-step setup process, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Detailed installation walkthrough for different methods&lt;/li&gt;
&lt;li&gt;Real-world configuration examples with specific hardware&lt;/li&gt;
&lt;li&gt;How to set up and test each component&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The complete configuration took me about 30 minutes, and I already had all the information for the respective devices available from my Home Assistant setup.&lt;/p&gt;
&lt;p&gt;Source Hero Image: Google AI Studio&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Smart EV Charging: Automatic Home Charger Control with AI License Plate Recognition</title>
    <link href="https://markus-haack.com/smart-ev-charging/"/>
    <updated>2025-07-04T00:00:00Z</updated>
    <id>https://markus-haack.com/smart-ev-charging/</id>
    <content type="html">&lt;p&gt;Are you familiar with the following situation?&lt;/p&gt;
&lt;p&gt;You’ve just returned from shopping or work and the battery in your electric car is running low, so you need to charge it. You just need to plug the charging cable into the EV charger and switch charging on. But at the same time, you’ve still got groceries and other stuff in the trunk, and your hands are full.  Ever found yourself fumbling for the RFID chip or card or opening the charger app just to start charging your electric vehicle?&lt;/p&gt;
&lt;p&gt;We are actually regularly in exactly this situation. Our EV charger is openly accessible from the street. That’s why we have a model that can be locked so that nobody can charge their car without authorisation. Unlocking them isn’t usually a big deal, but sometimes it is when you have your hands full, have to carry something, etc.&lt;/p&gt;
&lt;p&gt;What if your smart home could automatically recognize your car and start charging without any manual intervention? Today I’ll show you how I built an intelligent EV charging automation that uses camera motion detection and AI-powered license plate recognition to automatically unlock and start charging when our Polestar arrives home.&lt;/p&gt;
&lt;p&gt;This leads us to two challenges:&lt;/p&gt;
&lt;h2 id=&quot;securing-an-ev-charger-in-an-open-carport&quot;&gt;Securing an EV Charger in an Open Carport&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#securing-an-ev-charger-in-an-open-carport&quot; aria-labelledby=&quot;securing-an-ev-charger-in-an-open-carport&quot;&gt;#&lt;/a&gt;&lt;p&gt;As our carport faces the street, our EV charger is visible and accessible to anyone walking by. Without proper access control, neighbours or strangers could easily plug in their vehicles and charge at our expense. Of course, we have cameras, but they won’t stop everyone. This is particularly problematic if we’re away from home for a while.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ev-charging-carport.jpg&quot; alt=&quot;EV Charger&quot; title=&quot;Freely accessible EV Charger&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Freely accessible EV Charger&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Fortunately, most modern smart home chargers address this issue by offering built-in authorisation options, often via RFID or an app. However, having to unlock them manually every time becomes tedious. This is where automation comes in, intelligently recognising authorised vehicles and automatically managing access control.&lt;/p&gt;
&lt;h2 id=&quot;detecting-the-car&quot;&gt;Detecting the car&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#detecting-the-car&quot; aria-labelledby=&quot;detecting-the-car&quot;&gt;#&lt;/a&gt;&lt;p&gt;The second challenge is recognising the vehicle and, above all, the right vehicle. We only want to activate the charger when our own vehicle is parked and not a other random vehicle.&lt;/p&gt;
&lt;p&gt;You can try to recognise the car with the help of distance or motion sensors. At least whether an object, i.e. a vehicle, is in the carport or garage. But how do you know which vehicle it is?&lt;/p&gt;
&lt;p&gt;There are a number of &lt;a href=&quot;https://www.home-assistant.io/integrations/?cat=car&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;vehicle integrations&lt;/a&gt; in Home Assistant. There should be a way for almost every vehicle manufacturer to make the vehicle data visible in Home Assistant. Some of them, such as the BMW, Tesla or Mercedes integrations, can also provide GPS and location data. This is definitely a good way to recognise whether your own vehicle is in the carport.&lt;/p&gt;
&lt;p&gt;As the &lt;a href=&quot;https://github.com/pypolestar/polestar_api&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Polestar integration&lt;/a&gt; can only provide very little vehicle data, I had to fall back on another option.&lt;/p&gt;
&lt;p&gt;I used the cameras to recognise our car. The vehicle and the number plate are recognised via a snapshot which is analysed by AI. The automatic charging process is only started if the correct licence plate number is recognised.&lt;/p&gt;
&lt;h2 id=&quot;compatible-ev-charger-requirements&quot;&gt;Compatible EV Charger Requirements&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#compatible-ev-charger-requirements&quot; aria-labelledby=&quot;compatible-ev-charger-requirements&quot;&gt;#&lt;/a&gt;&lt;p&gt;This automation works with any smart EV home chargeer that supports authentication control and Home Assistant integration. Whether you have a KEBA - like our &lt;a href=&quot;https://www.keba.com/en/emobility/products/c-series/c-series?changelanguage=en&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Keba P30&lt;/a&gt;, Wallbox, Ohme, Easee, Myenergi, go-e Charger, OpenWB, or other compatible charging station, the core principles remain the same.&lt;/p&gt;
&lt;p&gt;If the charging station is installed in a garage or locked area, this is of course the easiest way. Since our carport is open and accessible to anyone passing by, we need a charger which can be locked and is only useable after authorization.&lt;/p&gt;
&lt;p&gt;For this automation to work with your setup, your EV charger must integrated with Home Assistant and needs to meet these essential requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lock entity: For controlling authentication/access (&lt;code&gt;lock.wallbox_authentication&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Binary sensors: For plug state and charging state monitoring&lt;/li&gt;
&lt;li&gt;Reliable connectivity: Either local network or cloud-based control&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;our-hardware-setup&quot;&gt;Our Hardware Setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#our-hardware-setup&quot; aria-labelledby=&quot;our-hardware-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;The core setup consists of three components.&lt;/p&gt;
&lt;h3 id=&quot;the-ev-charger&quot;&gt;The EV charger&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#the-ev-charger&quot; aria-labelledby=&quot;the-ev-charger&quot;&gt;#&lt;/a&gt;&lt;p&gt;The heart of our setup is the &lt;strong&gt;KEBA P30 wallbox&lt;/strong&gt;, which has &lt;a href=&quot;https://www.home-assistant.io/integrations/keba/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;excellent integration&lt;/a&gt; into Home Assistant. The KEBA integration provides binary sensors for charging state, plug state, energy counters, and crucially, a lock entity for authentication control and start/stop of the actually charging session.&lt;/p&gt;
&lt;h3 id=&quot;camera-system&quot;&gt;Camera System&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#camera-system&quot; aria-labelledby=&quot;camera-system&quot;&gt;#&lt;/a&gt;&lt;p&gt;I’m using &lt;strong&gt;&lt;a href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/&quot;&gt;Reolink cameras&lt;/a&gt;&lt;/strong&gt; and one of them is positioned in our carport to detect when a vehicle arrives. Our front door camera can also see the driveway. The cameras support generic motion detection, as well as person and vehicle detection, and snapshot functionality, all of which are accessible through Home Assistant. The vehicle detection binary sensors serve as our automation triggers.&lt;/p&gt;
&lt;h3 id=&quot;ai-integration-for-license-plate-detection&quot;&gt;AI Integration for License Plate Detection&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#ai-integration-for-license-plate-detection&quot; aria-labelledby=&quot;ai-integration-for-license-plate-detection&quot;&gt;#&lt;/a&gt;&lt;p&gt;As the camera itself can recognise vehicles as well as people or animals, we use it to take a snapshot photo. We now need image recognition to analyse the photo and recognise the number plate. For this we use an AI integration from Home Assistant.&lt;/p&gt;
&lt;p&gt;I use the &lt;strong&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/google_generative_ai_conversation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google Generative AI&lt;/a&gt;&lt;/strong&gt; for license plate recognition from camera snapshots. This eliminates the need for complex local computer vision setups while providing reliable plate detection and vehicle identification. Other AI integration such as &lt;a href=&quot;https://www.home-assistant.io/integrations/openai_conversation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI&lt;/a&gt; or &lt;a href=&quot;https://www.home-assistant.io/integrations/anthropic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Anthropic Conversation&lt;/a&gt; should also work here. If you don’t want to send your photos to the cloud, you can also use a local LLM (Large Language Model) via &lt;a href=&quot;https://www.home-assistant.io/integrations/ollama/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Ollama&lt;/a&gt; with a little more effort and computing power.&lt;/p&gt;
&lt;p&gt;For more information about Home Assistant and AI integration topics see this &lt;a href=&quot;https://www.home-assistant.io/blog/2024/06/07/ai-agents-for-the-smart-home/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-the-prerequisites&quot;&gt;Setting Up the Prerequisites&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#setting-up-the-prerequisites&quot; aria-labelledby=&quot;setting-up-the-prerequisites&quot;&gt;#&lt;/a&gt;&lt;p&gt;Before implementing this automation, ensure you have these integrations configured:&lt;/p&gt;
&lt;h3 id=&quot;ev-charger-integration&quot;&gt;EV Charger Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#ev-charger-integration&quot; aria-labelledby=&quot;ev-charger-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The configuration varies depending on the brand of EV charger:&lt;/p&gt;
&lt;p&gt;For a KEBA charger, such as the one we have, the configuration is pretty simple. You only need to provide the charger’s hostname or IP address in your network and the RFID tag key used for authorisation.&lt;/p&gt;
&lt;p&gt;For other common brands, this will be slightly different. Commonly used chargers (according to Google) are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wallbox brand chargers: use the built-in Home Assistant integration&lt;/li&gt;
&lt;li&gt;go-e Charger: install the &lt;a href=&quot;https://github.com/marq24/ha-goecharger-api2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;community integration&lt;/a&gt; via HACS&lt;/li&gt;
&lt;li&gt;Tesla Wall Connector: use the built-in Home Assistant integration&lt;/li&gt;
&lt;li&gt;ChargePoint: install the &lt;a href=&quot;https://github.com/mbillow/ha-chargepoint&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;community integration&lt;/a&gt; via HACS&lt;/li&gt;
&lt;li&gt;Zaptec: install the &lt;a href=&quot;https://github.com/custom-components/zaptec&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;community integration&lt;/a&gt; via HACS&lt;/li&gt;
&lt;li&gt;OpenWB: set up MQTT integration and configure the OpenWB MQTT topics&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;camera-integration&quot;&gt;Camera Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#camera-integration&quot; aria-labelledby=&quot;camera-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;Make sure your cameras are properly integrated into Home Assistant, that they expose motion detection binary sensors, and that they can take snapshot photos. While &lt;a href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/&quot;&gt;I recommend Reolink cameras&lt;/a&gt;, a wide range of other brands can be integrated with Home Assistant.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ev-charging-camera.png&quot; alt=&quot;Reolink Camera with vehicle detection&quot; title=&quot;Reolink Camera with vehicle detection&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Reolink Camera with vehicle detection&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Ideally, the camera will already have built-in object and person detection, which is also exposed to Home Assistant. This can be used instead of generic motion detection. This means that the automation will only be triggered when a vehicle is detected, rather than with every movement. If only a cat crosses the path and no vehicle is detected, the automation does not need to be started. If this is not available as a binary sensor, a generic motion sensor will suffice. However, this often leads to images being sent to the AI for analysis even when there are no cars.&lt;/p&gt;
&lt;h3 id=&quot;google-generative-ai-integration&quot;&gt;Google Generative AI Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#google-generative-ai-integration&quot; aria-labelledby=&quot;google-generative-ai-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;Set up the AI integration for image analysis capabilities. In case of Google Generative AI you’ll need an API key from Google AI Studio. For others the setup process is mostly similar.&lt;/p&gt;
&lt;h2 id=&quot;lets-make-it-smart&quot;&gt;Lets make it Smart&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#lets-make-it-smart&quot; aria-labelledby=&quot;lets-make-it-smart&quot;&gt;#&lt;/a&gt;&lt;p&gt;The automation follows a sophisticated workflow that balances security with convenience:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ev-charging-flow.png&quot; alt=&quot;EV Charging Flow&quot; title=&quot;EV Charging Flow&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;EV Charging Flow&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Motion Detection: Camera sensors detect movement in the carport area via two different cameras&lt;/li&gt;
&lt;li&gt;Condition Checks: Verify if the is already charging?&lt;/li&gt;
&lt;li&gt;Patience Delay: 5-minute wait to allow parking and cable connection&lt;/li&gt;
&lt;li&gt;Condition Checks: Verify the car is plugged in, the EV charger is locked, and not already charging&lt;/li&gt;
&lt;li&gt;AI Analysis: Capture and analyze a snapshot to identify the license plate&lt;/li&gt;
&lt;li&gt;Smart Decision: Unlock and start charging for authorized vehicles, or send alerts for unknown cars&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;the-complete-automation&quot;&gt;The Complete Automation&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#the-complete-automation&quot; aria-labelledby=&quot;the-complete-automation&quot;&gt;#&lt;/a&gt;&lt;p&gt;This is how my automation looks like with the KEBA P30 charger and the Reolink cameras:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ev-charging-automation.png&quot; alt=&quot;Complete EV Charging Automation&quot; title=&quot;The complete EV Charging Automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;The complete EV Charging Automation&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here is the YAML version so that you can better adopt and customise it:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Automatic Car Charging
&lt;span class=&quot;token key atrule&quot;&gt;triggers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turned_on
    &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; a8715&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;6f44e2
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 41585&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;7f54bc
    &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor
    &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; device
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turned_on
    &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3d634&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;76e7e4
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; e2dc6&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;5ede79
    &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor
    &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; device
&lt;span class=&quot;token key atrule&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.keba_p30_charging_state
    &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;off&quot;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;milliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
        &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.keba_p30_charging_state
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;off&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
        &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.keba_p30_plug
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;on&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
        &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; lock.keba_p30_authentication
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; locked
    &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ai_task.generate_data
        &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;task_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Analyse Parked Car
          &lt;span class=&quot;token key atrule&quot;&gt;instructions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
            Detect if a car enters the carport. Capture the license plate of the
            car and the car color.


            The camara taking the picture is place inside the carport below the
            roof. Only focus on cars directly inside the carport itself. The car
            must clearly entering the drive&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;in or be already inside the carport.


            &lt;span class=&quot;token key atrule&quot;&gt;Ignore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

            * Ignore cars just driving by.

            * Ignore cars on the other side of the street

            * Ignore cars in the neighbours garage or carport which is located
            on the opposite side of the street

            * Ignore the car directly next to the yellow house on the other side
            of the street.

            * Ignore cars in the background
          &lt;span class=&quot;token key atrule&quot;&gt;attachments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;media_content_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; media&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;source&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//camera/camera.carport_fluent
            &lt;span class=&quot;token key atrule&quot;&gt;media_content_type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; application/vnd.apple.mpegurl
            &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Carport
              &lt;span class=&quot;token key atrule&quot;&gt;thumbnail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /api/camera_proxy/camera.carport_fluent
              &lt;span class=&quot;token key atrule&quot;&gt;media_class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; video
              &lt;span class=&quot;token key atrule&quot;&gt;children_media_class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null important&quot;&gt;null&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;navigateIds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;media_content_type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; app
                  &lt;span class=&quot;token key atrule&quot;&gt;media_content_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; media&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;source&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//camera
          &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ai_task.google_ai_task
          &lt;span class=&quot;token key atrule&quot;&gt;structure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;license_plate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; The license plate of the car
              &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null important&quot;&gt;null&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; The color of the car
              &lt;span class=&quot;token key atrule&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null important&quot;&gt;null&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;response_variable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ai
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
            &lt;span class=&quot;token key atrule&quot;&gt;value_template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
              &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notify.mobile_app_iphone_von_markus
            &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 🚗
              &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
                Car is in garage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; start charging automatically.
          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; lock.unlock
            &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; lock.keba_p30_authentication
        &lt;span class=&quot;token key atrule&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notify.mobile_app_iphone_von_markus
            &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
                A car was detected&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; but not sure this is ours. Better check.
              &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 🚗
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;make-it-your-own&quot;&gt;Make it your own&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#make-it-your-own&quot; aria-labelledby=&quot;make-it-your-own&quot;&gt;#&lt;/a&gt;&lt;p&gt;Even if it is not a blueprint, the automation can be adapted relatively easily. The following changes are necessary for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Device and Entity IDs&lt;br&gt;
Replace all device IDs and entity IDs with those from your specific setup. Use &lt;em&gt;Developer Tools → States&lt;/em&gt; to find the correct entities for your cameras and charger.&lt;/li&gt;
&lt;li&gt;Licence plate check:&lt;br&gt;
Assuming your licence plate is different to ours 😃, you need to change the check in line XX as well.&lt;/li&gt;
&lt;li&gt;Unlock the charger:&lt;br&gt;
Depending on how Home Assistant integrates with the EV charger, this might involve unlocking a lock, as in our case, or sending a command via MQTT or triggering a service to authorise and start charging.&lt;/li&gt;
&lt;li&gt;Notification:&lt;br&gt;
Replace the notification service and adapt the messages as required.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Licence plate recognition may require 2-3 attempts and some trial and error. AI recognition was not 100% accurate in our case, so I configured three options. False positive detection might be possible. If the Home Assistant integration for your vehicle provides location data, I would also use this for an additional check and incorporate it into the automation.&lt;/p&gt;
&lt;h2 id=&quot;conclusion-and-future-enhancements&quot;&gt;Conclusion and Future Enhancements&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/smart-ev-charging/#conclusion-and-future-enhancements&quot; aria-labelledby=&quot;conclusion-and-future-enhancements&quot;&gt;#&lt;/a&gt;&lt;p&gt;The current automation works very well for us. I’m very happy with it as it makes starting the charging process really easy!&lt;/p&gt;
&lt;p&gt;However, as a Home Assistant Pro, you’re always thinking about how you can optimise things even further 😉. I also have the following ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multiple Vehicle Support: this is not an issue for us as we only have one car, but it certainly is for others.&lt;/li&gt;
&lt;li&gt;Smart surplus charging via the PV system, which will definitely be an option for us.&lt;/li&gt;
&lt;li&gt;Integrate with Home Assistant presence detection to disable the automation when residents are away, adding an extra security layer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This smart EV charging automation is a really versatile solution. It’s got camera motion detection, AI image analysis and a connected EV charger, all controlled by Home Assistant. This means it’s really convenient and secure, as it automatically starts charging the cars you know about while blocking others. The logic works with various EV charger brands and camera setups, just needing a few minor tweaks for your specific hardware.&lt;/p&gt;
&lt;p&gt;We’ve successfully used this automation with our KEBA P30 and Polestar over the last two weeks. Its key strength lies in Home Assistant’s ability to integrate diverse technologies – from simple sensors to advanced AI – into a practical automation that genuinely enhances daily life, regardless of your chosen EV charger.&lt;/p&gt;
&lt;p&gt;Happy automating, and enjoy the convenience of never having to fumble for charging authentication again – no matter which EV charger or car you choose!&lt;/p&gt;
&lt;p&gt;Image sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hero: &lt;a href=&quot;https://unsplash.com/de/@michael_marais?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Michael Marais&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Charger with car: &lt;a href=&quot;https://unsplash.com/de/@zaptec?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zaptec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Make Your Reolink Camera Speak with Home Assistant TTS &amp; AI</title>
    <link href="https://markus-haack.com/making-your-reolink-camera-talk/"/>
    <updated>2025-05-04T00:00:00Z</updated>
    <id>https://markus-haack.com/making-your-reolink-camera-talk/</id>
    <content type="html">&lt;p&gt;Ever wish your security camera could actually speak? Let’s talk about camera alerts and how we can make them even smarter. You’ve got your smart home cameras connected to the Home Assistant, and you get notifications whenever there’s motion. In my article &lt;a href=&quot;https://markus-haack.com/automate-reolink-camera-notifications/&quot;&gt;Automate Reolink camera notifications&lt;/a&gt;, I explained how you can automate the camera notifications. That’s useful, sure. But a generic “person/car/animal detected” alert often leaves you pulling out your phone, opening the app, and waiting for the live feed to figure out what’s actually going on. More often than not, it’s just the cat from next door or the postman doing his rounds.&lt;/p&gt;
&lt;p&gt;I wanted something smarter. I wanted Home Assistant to not just tell me that something happened, but what happened. Turns out with a little help from AI my smart home actually understand the camera feed.&lt;/p&gt;
&lt;p&gt;The idea for this little automation is simple: when motion is detected, take a quick picture (or multiple), send that picture to an AI for analysis, and then have Home Assistant tell you the AI’s description out loud.&lt;/p&gt;
&lt;p&gt;This guide will show you how to leverage Home Assistant with AI image analysis and &lt;a href=&quot;https://www.home-assistant.io/integrations/tts/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Text-to-Speech&lt;/a&gt; (TTS) capabilities to get voice alerts and messages directly from your camera. But don’t worry if you’re using a different brand. The core method – camera event -&amp;gt; triggered snapshot -&amp;gt; AI analysis -&amp;gt; spoken alert via TTS – works with any camera integrated into Home Assistant that supports taking snapshots.&lt;/p&gt;
&lt;p&gt;Here’s what you’ll need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A Camera:&lt;/strong&gt; Integrated into Home Assistant and capable of taking snapshots. I’m using Reolink, but the steps for the automation part are generic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Speaker/Media Player:&lt;/strong&gt; Also integrated into Home Assistant (like a Sonos, Google Home/Nest speaker, etc.) to play the audio message.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Text-to-speech integration&lt;/strong&gt;: I use Home Assistant Cloud TTS for this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Generative AI Access:&lt;/strong&gt; You’ll need an &lt;a href=&quot;https://aistudio.google.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google AI Studio&lt;/a&gt; account and an API key for Gemini. We’ll cover how to get the integration set up.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can also build this automation flow with other AI conversation integrations like &lt;a href=&quot;https://www.home-assistant.io/integrations/anthropic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Anthropic Conversation&lt;/a&gt; or &lt;a href=&quot;https://www.home-assistant.io/integrations/openai_conversation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI Conversation&lt;/a&gt;. I used &lt;a href=&quot;https://www.home-assistant.io/integrations/google_generative_ai_conversation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google AI Studio&lt;/a&gt; because it has a decent free tier with enough tokens for testing.&lt;/p&gt;
&lt;p&gt;Ready? Let’s dive in.&lt;/p&gt;
&lt;h2 id=&quot;step-1%3A-get-the-google-generative-ai-integration-hooked-up&quot;&gt;Step 1: Get the Google Generative AI Integration Hooked Up&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#step-1%3A-get-the-google-generative-ai-integration-hooked-up&quot; aria-labelledby=&quot;step-1%3A-get-the-google-generative-ai-integration-hooked-up&quot;&gt;#&lt;/a&gt;&lt;p&gt;First things first, Home Assistant needs a way to talk to Google’s AI. There’s an official integration for this.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to Settings -&amp;gt; Devices &amp;amp; Services.&lt;/li&gt;
&lt;li&gt;Click + Add Integration.&lt;/li&gt;
&lt;li&gt;Search for “Google Generative AI Conversation” and select it.&lt;/li&gt;
&lt;li&gt;It will ask for your API key. You’ll need to get one from Google AI Studio (it’s free for basic use). Just follow the link provided in the integration setup or search for “Google AI Studio API key”. It’s pretty quick to generate.&lt;/li&gt;
&lt;li&gt;Paste your API key into the configuration and submit.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot_camera_ai_1.png&quot; alt=&quot;Google Generative AI Conversation&quot; title=&quot;Screenshot 1: Google Generative AI Conversation integration&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 1: Google Generative AI Conversation integration&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Once added, you’ll have a new service available in Home Assistant:&lt;br&gt;
&lt;code&gt;google_generative_ai_conversation. generate_content&lt;/code&gt;. This is what we’ll use in the automation.&lt;/p&gt;
&lt;h2 id=&quot;step-2%3A-ensure-your-ai-conversation-integration-is-ready&quot;&gt;Step 2: Ensure Your AI Conversation Integration is Ready&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#step-2%3A-ensure-your-ai-conversation-integration-is-ready&quot; aria-labelledby=&quot;step-2%3A-ensure-your-ai-conversation-integration-is-ready&quot;&gt;#&lt;/a&gt;&lt;p&gt;You can test the AI conversation agent via the Developer Tool &amp;gt; Actions page.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot_camera_ai_2.png&quot; alt=&quot;Testing the Google Generative AI conversation agent&quot; title=&quot;Screenshot 2: Testing the Google Generative AI conversation agent&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 2: Testing the Google Generative AI conversation agent&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Search the &lt;em&gt;Google Generative AI: Generate content&lt;/em&gt; integration as shown in the screenshot and fill in the form with some test questions. Then click &lt;em&gt;Perform Action&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;step-3%3A-set-up-text-to-speech-(tts)&quot;&gt;Step 3: Set up Text-to-Speech (TTS)&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#step-3%3A-set-up-text-to-speech-(tts)&quot; aria-labelledby=&quot;step-3%3A-set-up-text-to-speech-(tts)&quot;&gt;#&lt;/a&gt;&lt;p&gt;The automation uses the Text-to-Speech feature to speak the response text from the AI’s analysis. I’m using the Home Assistant Cloud TTS in the example, but any configured TTS service like &lt;a href=&quot;https://www.home-assistant.io/integrations/microsoft/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;# Microsoft Text-to-Speech&lt;/a&gt; or &lt;a href=&quot;https://www.home-assistant.io/integrations/google_translate/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google Translate text-to-speech&lt;/a&gt; will work as well.&lt;/p&gt;
&lt;p&gt;Make sure you have a TTS integration set up and a media_player entity ready to receive the audio. If you’re using Home Assistant Cloud, the tts.home_assistant_cloud entity should be available by default if you have Nabu Casa subscribed.&lt;/p&gt;
&lt;p&gt;Similar like above, you can test it via the Developer Tool &amp;gt; Actions page.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot_camera_ai_3.png&quot; alt=&quot;Testing the Text-to-speech&quot; title=&quot;Screenshot 3: Testing the Text-to-speech&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 3: Testing the Text-to-speech&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Locate &lt;em&gt;Text-to-speech (TTS): Speak&lt;/em&gt; like in the screenshot and fill out the form. You can also select your preferred language and voice.&lt;/p&gt;
&lt;h2 id=&quot;step-4%3A-build-the-automation&quot;&gt;Step 4: Build the Automation&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#step-4%3A-build-the-automation&quot; aria-labelledby=&quot;step-4%3A-build-the-automation&quot;&gt;#&lt;/a&gt;&lt;p&gt;Now for the fun part: putting it all together in an automation. We’ll mostly use the UI editor, which is generally the easiest way to get started. For one step, we also need to switch to YAML.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to Settings -&amp;gt; Automations &amp;amp; Scenes -&amp;gt; Automations.&lt;/li&gt;
&lt;li&gt;Click + Create Automation and then Start with an empty automation.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;configuration%3A&quot;&gt;Configuration:&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#configuration%3A&quot; aria-labelledby=&quot;configuration%3A&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Give it a clear name, like “Camera Motion - AI Analysis”.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trigger&quot;&gt;Trigger&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#trigger&quot; aria-labelledby=&quot;trigger&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Click &lt;em&gt;+ Add Trigger&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Select Device.&lt;/li&gt;
&lt;li&gt;Choose your camera from the list of devices.&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; This part is specific to how your camera integrates. If your camera doesn’t expose a motion binary sensor directly as a device trigger, you might need to use an Entity trigger monitoring the motion sensor’s state change. For my Reolink camera in this example, a Device trigger works.&lt;/li&gt;
&lt;li&gt;The Entity field should automatically show related entities. Select the motion binary sensor for your camera (it might be named something like &lt;code&gt;binary_sensor.YOUR_CAMERA_NAME_motion&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The Type should be motion (see YAML below). This should be set automatically when using the visual editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot_camera_ai_4.png&quot; alt=&quot;Camera triggering the action&quot; title=&quot;Screenshot 4: Camera triggering the action&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 4: Camera triggering the action&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3 id=&quot;conditions&quot;&gt;Conditions&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#conditions&quot; aria-labelledby=&quot;conditions&quot;&gt;#&lt;/a&gt;&lt;p&gt;We won’t add any conditions for a basic example. Click &lt;em&gt;+ Add Condition&lt;/em&gt; if you want to refine when this automation runs (e.g., only during the day).&lt;/p&gt;
&lt;p&gt;In my example, I use a condition to run the automation only when we are at home using a simple stage condition.&lt;/p&gt;
&lt;h3 id=&quot;actions&quot;&gt;Actions&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#actions&quot; aria-labelledby=&quot;actions&quot;&gt;#&lt;/a&gt;&lt;p&gt;Here’s where the magic sequence happens. Click &lt;em&gt;+ Add Action&lt;/em&gt; multiple times to add these steps:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Action 1: Take a Snapshot&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browse to and select the &lt;em&gt;Camera: Take Snapshot&lt;/em&gt; service (aka &lt;code&gt;camera.snapshot&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;For Target, select the camera entity (&lt;code&gt;camera.YOUR_CAMERA_NAME&lt;/code&gt;) that you want to take a snapshot of.&lt;/li&gt;
&lt;li&gt;For Filename, you need to specify where you want to save the image. A good place is the &lt;code&gt;/media&lt;/code&gt; folder, which Home Assistant uses by default for recordings and snapshots. Set the filename to something like &lt;code&gt;/media/camera/frontdoor_snapshot.jpg&lt;/code&gt;. You can change &lt;code&gt;frontdoor_snapshot.jpg&lt;/code&gt; to whatever makes sense, but remember that the &lt;code&gt;/media/&lt;/code&gt; path is important. Home Assistant needs permission to write here, which it usually has for this path.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tip: You can take one or more snapshots. Gemini AI can also process more images and give you a more accurate answer. However, this will require more tokens and cost more money, depending on your conversation integration and AI subscription.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Action 2: Add a Delay&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click &lt;em&gt;+ Add Action&lt;/em&gt; again.&lt;/li&gt;
&lt;li&gt;Select Delay.&lt;/li&gt;
&lt;li&gt;Set a short delay, maybe 5 seconds. This gives Home Assistant time to actually write the snapshot file to disk before the next step tries to read it. It might not always be necessary, but it helps prevent errors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Action 3: Send to Gemini AI&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click &lt;em&gt;+ Add Action&lt;/em&gt; again.&lt;/li&gt;
&lt;li&gt;Locate and select the &lt;em&gt;Google Generative AI ‘Generate content’&lt;/em&gt; service.&lt;/li&gt;
&lt;li&gt;This service takes a prompt and can analyze camera snapshots.&lt;/li&gt;
&lt;li&gt;Enter the prompt: This is where you tell the AI what to do. The example YAML below has a specific, funny prompt that asks it to act like a “grumpy security officer” and answer in German. If you use this prompt, the AI’s response will be in English.&lt;br&gt;
You can copy this, or write your own prompt in English (or any other language Gemini supports) if you prefer a different output. Make it specific about what you expect, ask it to briefly describe what it sees, ignore stationary objects/cars/buildings, etc.&lt;/li&gt;
&lt;li&gt;Add a camera snapshot filename. Check &lt;em&gt;Attachment filenames&lt;/em&gt; and enter the filename of the camera snapshot image. Make sure the filename matches the one in your snapshot action, like &lt;code&gt;/media/camera/frontdoor_snapshot.jpg&lt;/code&gt;.&lt;br&gt;
If you are taking multiple snapshots from your camera, make sure you add all the filenames.&lt;/li&gt;
&lt;li&gt;It is important to add a field for the response variable. This is the name of a variable that will store the AI’s response for use in later actions. The example uses &lt;code&gt;response&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Action 4: Speak the Result&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;em&gt;+ Add Action&lt;/em&gt; again.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Browse to your TTS service and select it. If you’re using Home Assistant Cloud, it’s &lt;code&gt;tts.home_assistant_cloud&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For Target, select the media_player entity (your speaker) where you want to play the message.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the message file, enter or copy the following template &lt;code&gt;{{ response.text }}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This will cause Home Assistant to switch to the YAML-based editor, as templates are not supported in the visual editor.&lt;br&gt;
Your YAML should have at least three configurations: the speaker entity, the text-to-speech action and the message with the template.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Save:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Once all actions are added, click Save in the bottom right.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If set up correctly the automation steps should look like this:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot_camera_ai_5.png&quot; alt=&quot;Automation action flow&quot; title=&quot;Screenshot 5: Action flow of the automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 5: Action flow of the automation&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-complete-yaml&quot;&gt;The Complete YAML&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#the-complete-yaml&quot; aria-labelledby=&quot;the-complete-yaml&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you prefer to work with YAML, or just want to see how the whole thing is structured, here’s my automation code. If you build yours following the steps above, it should look similar. Feel free to copy it:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Front door motion detection with AI description
&lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;triggers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motion
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;camera devide id&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;camera motion sensor entity id&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor
   &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; device
&lt;span class=&quot;token key atrule&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; group.family
   &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Home
&lt;span class=&quot;token key atrule&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; camera.snapshot
   &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /media/camera/frontdoor_snapshot.jpg
   &lt;span class=&quot;token key atrule&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &amp;lt;camera entity id&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;milliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; google_generative_ai_conversation.generate_content
   &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
     You are a grumpy security officed whatching surveillance cameras all day
     long. Briefly describe what you see in this image from my frontdoor
     camera. Don&#39;t describe stationary objects&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cars or buildings. Answer
     always in German.
    &lt;span class=&quot;token key atrule&quot;&gt;filenames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; /media/camera/frontdoor_snapshot.jpg
   &lt;span class=&quot;token key atrule&quot;&gt;response_variable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; response
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tts.speak
   &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;media_player_entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; media_player.move
    &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tts.home_assistant_cloud
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you copy the example below, be sure to change the placeholders. You can find these in the Automation Editor when setting up the trigger/actions, or by looking at the entity and device details in Settings -&amp;gt; Devices &amp;amp; Services -&amp;gt; Entities or Devices. Also adjust the trigger definition if your specific camera integration requires a different method of detecting motion (e.g. an entity state change).&lt;/p&gt;
&lt;p&gt;Once copied, you can also switch to the Visual Automation Editor and change the parameters in the interface.&lt;/p&gt;
&lt;h2 id=&quot;testing-and-refinement&quot;&gt;Testing and Refinement&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#testing-and-refinement&quot; aria-labelledby=&quot;testing-and-refinement&quot;&gt;#&lt;/a&gt;&lt;p&gt;Save the automation and try triggering motion on your camera. With a bit of luck (and correct paths/entity IDs), you should:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get motion detected in Home Assistant.&lt;/li&gt;
&lt;li&gt;See a snapshot file appear in your /media/camera folder. You can check the stored snapshots using the Home Assistant &lt;a href=&quot;https://www.home-assistant.io/integrations/media_source/#identifying-a-media-source-from-the-media-browser&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Media Browser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;After a few seconds, hear your speaker announce (the language will depend on your prompt!) what the AI saw in the picture, hopefully ignoring boring stuff like the wall or a parked car.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If it doesn’t work, check the automation trace logs and the Home Assistant logs (Settings -&amp;gt; System -&amp;gt; Logs) for errors related to automation, camera snapshot, Gemini service call or TTS service call. Check your Entity IDs, the snapshot filename path and your Gemini API key.&lt;/p&gt;
&lt;p&gt;You can also play around with the Gemini prompt to get different types of descriptions or different languages. The grumpy security officer in German is just a fun idea - try writing a prompt in English for an English response.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/making-your-reolink-camera-talk/#conclusion&quot; aria-labelledby=&quot;conclusion&quot;&gt;#&lt;/a&gt;&lt;p&gt;So there you have it! We’ve taken a basic camera motion alert and elevated it into a more intelligent system. Instead of just knowing that there’s motion, Home Assistant now takes a peek, asks an AI what it sees, and tells you the relevant details.&lt;/p&gt;
&lt;p&gt;This setup, using a snapshot and an AI conversation service, isn’t limited to Reolink or even just Gemini. The concept works with any camera that can take snapshots via Home Assistant and with other AI conversation integrations you might have configured.&lt;/p&gt;
&lt;p&gt;And honestly, integrating an AI conversation model like Gemini opens up a ton of possibilities beyond just camera analysis. You can use it to make other notifications smarter, get summaries of events, or even potentially use it as part of voice control flows. This little project just scratches the surface.&lt;/p&gt;
&lt;p&gt;It’s always satisfying when you can make your smart home a little bit smarter and more proactive. Getting a spoken description of what’s happening outside, without having to check my phone, feels like a genuine upgrade.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://markus-haack.com/#contact&quot;&gt;Let me know&lt;/a&gt; if you build this or if you’ve found other cool ways to leverage AI in your Home Assistant setup!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Weather Cards in Home Assistant: My Top Picks</title>
    <link href="https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/"/>
    <updated>2025-04-22T00:00:00Z</updated>
    <id>https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/</id>
    <content type="html">&lt;p&gt;Whether you want to see if you need an umbrella, trigger garden automation, or just want a nice weather forecast, it’s easy to integrate weather data into your &lt;a href=&quot;https://www.home-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt;. I don’t think I need to explain why having weather information on your Home Assistant dashboard is helpful. Almost every Home Assistant user has a weather card on the dashboard.&lt;/p&gt;
&lt;p&gt;But there’s a bit more to it than just connecting a weather integration - you also need a suitable weather card. Many people have one on their home dashboard. It is one of the first cards you see when you open Home Assistant in your app or browser. So you want a nice, clean weather card that shows you all the information you need.&lt;/p&gt;
&lt;p&gt;Over the past few weeks, I’ve been experimenting with different weather cards for my own dashboard. In this article, I’ll take you through the options I’ve tested, how to set them up, and the differences I’ve noticed in everyday use. By the end, you’ll know which approach works best for you - without having to install and remove five different cards yourself.&lt;/p&gt;
&lt;h2 id=&quot;why-upgrade-from-the-default%3F&quot;&gt;Why Upgrade From the Default?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#why-upgrade-from-the-default%3F&quot; aria-labelledby=&quot;why-upgrade-from-the-default%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;During my search for a better solution, I tested a handful of community cards that promise more features or a fancier look. Below are the four I’d recommend checking out, in order of increasing complexity and customization.&lt;/p&gt;
&lt;h2 id=&quot;the-setup&quot;&gt;The setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#the-setup&quot; aria-labelledby=&quot;the-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;You don’t need much to get started with a simple weather card. In fact, all you need is a configured weather integration. I use the default &lt;a href=&quot;https://www.home-assistant.io/integrations/open_meteo&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Open-Meteo&lt;/a&gt; integration which provides all the weather details and forecasts I need. Other weather data provides will of course work as well.&lt;/p&gt;
&lt;p&gt;For more advanced uses, additional integrations such as UV data or a local temperature and pressure sensors will be helpful.&lt;/p&gt;
&lt;p&gt;Almost all of the custom weather charts listed below offer powerful configuration options. In this article I can only summarise the highlights. A detailed list of all available options can be found in the linked GitHub repositories.&lt;/p&gt;
&lt;h2 id=&quot;1.-official-home-assistant-weather-forecast-card&quot;&gt;1. Official Home Assistant Weather Forecast Card&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#1.-official-home-assistant-weather-forecast-card&quot; aria-labelledby=&quot;1.-official-home-assistant-weather-forecast-card&quot;&gt;#&lt;/a&gt;&lt;p&gt;Home Assistant includes a simple built-in weather forecast card. Adding it to your dashboard is quick and works with most integrations out-of-the-box.&lt;/p&gt;
&lt;p&gt;This is the default option under &lt;em&gt;Add Card&lt;/em&gt; &amp;gt; &lt;em&gt;Weather Forecast&lt;/em&gt; in the dashboard editor. Setup is as simple as picking your &lt;code&gt;weather&lt;/code&gt; entity.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/weather_card_ha.png&quot; alt=&quot;Screenshot Home Assistant Weather Card&quot; title=&quot;Screenshot 1: Home Assistant Weather Card&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 1: Home Assistant Weather Card&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It shows current conditions and a five-day forecast in a compact design that fits anywhere. You can switch between hourly and daily forecasts. You can select the number of forecast entries. You can choose an extra value to display below the main temperature - humidity, rainfall or wind. For many users, this may be enough.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;br&gt;
Just add it from the Lovelace UI. No YAML or HACS install needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;br&gt;
If you want something reliable and straightforward without any extra dependencies.&lt;/p&gt;
&lt;h2 id=&quot;2.-clock-weather-card&quot;&gt;2. Clock Weather Card&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#2.-clock-weather-card&quot; aria-labelledby=&quot;2.-clock-weather-card&quot;&gt;#&lt;/a&gt;&lt;p&gt;While testing different weather cards, I also came across the &lt;a href=&quot;https://github.com/pkissling/clock-weather-card&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Clock Weather Card&lt;/a&gt;. This option combines a digital or analogue clock with weather information, making it particularly useful for dashboards on wall tablets or displays where you want to see both the time and current conditions at a glance. Ideal for your home screen dashboard.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/weather_card_clock.png&quot; alt=&quot;Screenshot Clock Weather Card&quot; title=&quot;Screenshot 2: Clock Weather Card&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 2: Clock Weather Card&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt;&lt;br&gt;
Like most custom cards, the Clock Weather Card can be installed via HACS. Just search for “Clock Weather Card” in the HACS Frontend section and install it. After that, use the Lovelace UI to add it as a custom card.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;br&gt;
You get a clear display of the current time alongside the weather icon, temperature and optional short forecast. The card is very powerful and already adds some complexity. There are several style options, including analogue and digital clocks, time zone and format, different animated icons, and you can customise which weather unit it uses. Various elements (current conditions, time &amp;amp; date, forecast) can be hidden for a very personal style. The number of forecast days is also configurable. The card also supports additional sensors for local temperature, humidity, apparent temperature and air quality. It also supports full localisation for a large list of languages.&lt;br&gt;
With a wide range of compatibility with different Lovelace themes, making it easy to fit into your overall dashboard look.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration:&lt;/strong&gt;&lt;br&gt;
The Clock Weater Card currently only supports YAML configuration. A UI configuration mode is not yet available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My impression:&lt;/strong&gt;&lt;br&gt;
The card is perfect if you want a simple, nice to look at info panel that shows both the time and weather. I find it works best in the mobile app dashboard and on always-on displays in the kitchen or hallway, as guests instantly see both the weather and what time it is. It doesn’t have as many advanced options or data points as the Platinum Weather Card, but it handles the basics very elegantly.&lt;/p&gt;
&lt;h2 id=&quot;3.-platinum-weather-card&quot;&gt;3. Platinum Weather Card&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#3.-platinum-weather-card&quot; aria-labelledby=&quot;3.-platinum-weather-card&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you like to tweak every pixel or combine weather data from multiple integrations, &lt;a href=&quot;https://github.com/Makin-Things/platinum-weather-card&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Platinum Weather Card&lt;/a&gt; is the tool for you. This is your power horse for weather data. It’s designed as a flexible, fully GUI configurable weather card - no YAML needed if you don’t want to. Like the other cards before it shows the current weather conditions and the forecast. But it does not stop there, it can display various details such as&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sunrise and sunset&lt;/li&gt;
&lt;li&gt;wind conditions, speed and direction&lt;/li&gt;
&lt;li&gt;recorded rainfall&lt;/li&gt;
&lt;li&gt;visibility&lt;/li&gt;
&lt;li&gt;rain or snowfall forecast&lt;/li&gt;
&lt;li&gt;UV forecast&lt;/li&gt;
&lt;li&gt;fire danger&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the details section you can freely configure up to 16 attributes (2 columns of 8 each).&lt;/p&gt;
&lt;p&gt;The forecast section of the cards supports two different layouts: horizontal and vertical. While the horizontal view displays icons and values in a row similar to the other cards, the vertical view is very verbose and gives you a detailed view of the coming days. This includes weather conditions, forecast temperature and rain, and a written weather forecast.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt;&lt;br&gt;
Install via HACS under &lt;em&gt;Frontend&lt;/em&gt;. Search for “Platinum Weather Card” and install. Then, add a new card of type &lt;em&gt;Custom: Platinum Weather Card&lt;/em&gt; to your dashboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration:&lt;/strong&gt;&lt;br&gt;
The card is fully configurable via the UI. It opens a full GUI editor with tons of settings. You can choose which data sources to use for each field, change the icon set, customise the forecast layout and much more.&lt;br&gt;
To take advantage of the full feature set of this card, you will need multiple sensors. The default weather sensor may not be sufficient for this card. You will also need UV (such as from &lt;a href=&quot;https://www.home-assistant.io/integrations/openuv/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenUV&lt;/a&gt; or &lt;a href=&quot;https://www.home-assistant.io/integrations/tomorrowio/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;tomorrow.io&lt;/a&gt;) and fire danger forecast. Local temperature sensors can also be used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My impression:&lt;/strong&gt;&lt;br&gt;
This Weather Card is perfect for anyone who wants to get and display all the data they can. The card allows extensive configuration and can be flexibly customised. However, this card is too much for a simple daily weather display that you look at on a tablet on the wall as you pass by. It is almost better suited for a seprated weather dashboard with a lot of details.&lt;/p&gt;
&lt;h2 id=&quot;4.-simple-weather-card&quot;&gt;4. Simple Weather Card&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#4.-simple-weather-card&quot; aria-labelledby=&quot;4.-simple-weather-card&quot;&gt;#&lt;/a&gt;&lt;p&gt;This is the opposite of the previous weather card. If you prefer a clean look and just the essentials, the &lt;a href=&quot;https://github.com/kalkih/simple-weather-card&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Simple Weather Card&lt;/a&gt; is worth a try. This card is designed to minimise clutter while still providing the most important weather data. It’s great for smaller dashboards, side panels or mobile views where space is at a premium.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/weather_card_simple.png&quot; alt=&quot;Screenshot Simple Weather Card&quot; title=&quot;Screenshot 3: Simple Weather Card&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 3: Simple Weather Card&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt;&lt;br&gt;
Same like before, you’ll find the Simple Weather Card in HACS under Frontend. After installing, just add it as a custom card through the Lovelace dashboard editor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;br&gt;
The minimalist layout of this weather card is straightforward - current weather icon and temperature, with options for additional details such as humidity, wind or precipitation. You can also customise which attributes are shown if you want to keep things extra minimal.&lt;/p&gt;
&lt;p&gt;The card has a nice day and night view and you can customise the background color of the card.&lt;/p&gt;
&lt;p&gt;It works with standard &lt;code&gt;weather&lt;/code&gt; entities, so it’s compatible with the usual Home Assistant weather integrations. A local temperature sensor is also supported.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration:&lt;/strong&gt;&lt;br&gt;
The Simple Weater Card currently only supports YAML configuration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My impression:&lt;/strong&gt;&lt;br&gt;
I use the Simple Weather Card on my phone dashboard because it loads quickly and doesn’t overwhelm the screen. It’s also a good choice for secondary dashboard panels where I don’t need a detailed forecast, just a quick overview. If you have family members who get confused by too much detail, this card keeps things simple and usable.&lt;/p&gt;
&lt;h2 id=&quot;other-options%3A&quot;&gt;Other options:&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#other-options%3A&quot; aria-labelledby=&quot;other-options%3A&quot;&gt;#&lt;/a&gt;&lt;p&gt;• &lt;a href=&quot;https://github.com/decompil3d/lovelace-hourly-weather&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hourly Weather Card&lt;/a&gt;: A simple card to visualise upcoming weather conditions as a coloured horizontal bar. This card focuses on one thing and does it perfectly.&lt;/p&gt;
&lt;p&gt;• &lt;a href=&quot;https://github.com/mlamberts78/weather-chart-card&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Weather Chart Card&lt;/a&gt;: If you prefer graphical trends, this card visualises forecast data such as temperature and precipitation over time. Similar to the Platinum Weather card this card, with all the details, deserves more space on the dashbaord.&lt;/p&gt;
&lt;h2 id=&quot;which-card-to-choose%3F&quot;&gt;Which Card to Choose?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#which-card-to-choose%3F&quot; aria-labelledby=&quot;which-card-to-choose%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you’re happy with a basic weather summary:&lt;br&gt;
Stick with the built-in card. It’s low-maintenance, fast, and works everywhere.&lt;/p&gt;
&lt;p&gt;For a visually appealing dashboard, especially on a wall tablet:&lt;br&gt;
Try the Clock Weather Card, he animations are subtle but make a big difference. Or, if you prefer a more minimalist design, choose the Simple Weather Card.&lt;/p&gt;
&lt;p&gt;If you want maximum control and like to experiment:&lt;br&gt;
Platinum Weather Card is the most powerful option, letting you mix and match data sources and customize the look.&lt;/p&gt;
&lt;h2 id=&quot;my-setup&quot;&gt;My Setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#my-setup&quot; aria-labelledby=&quot;my-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;At the moment I use the Clock Weather card in my main dashboard in combination with the forecast from the then standard built-in weather card. Using the custom `vertical-stack-in-card’ card, these can be nicely stitched together to give them a “one card” look and feel. Here is the YAML of the combination:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; custom&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;vertical&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;stack&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;in&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;card
&lt;span class=&quot;token key atrule&quot;&gt;cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; custom&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;clock&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;weather&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;card
   &lt;span class=&quot;token key atrule&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; weather.jama_villa
   &lt;span class=&quot;token key atrule&quot;&gt;temperature_sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sensor.garden_temperature
   &lt;span class=&quot;token key atrule&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; de
   &lt;span class=&quot;token key atrule&quot;&gt;weather_icon_type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; fill
   &lt;span class=&quot;token key atrule&quot;&gt;hide_clock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;hide_date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;forecast_rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;show_decimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;hide_forecast_section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;show_current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;show_forecast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; weather&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;forecast
   &lt;span class=&quot;token key atrule&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; weather.jama_villa
   &lt;span class=&quot;token key atrule&quot;&gt;forecast_type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hourly
   &lt;span class=&quot;token key atrule&quot;&gt;forecast_slots&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; custom&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;clock&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;weather&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;card
   &lt;span class=&quot;token key atrule&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; weather.jama_villa
   &lt;span class=&quot;token key atrule&quot;&gt;temperature_sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sensor.garden_temperature
   &lt;span class=&quot;token key atrule&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; de
   &lt;span class=&quot;token key atrule&quot;&gt;weather_icon_type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; fill
   &lt;span class=&quot;token key atrule&quot;&gt;hide_clock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;hide_date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;forecast_rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;show_decimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;hide_today_section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/weather_card_my_combo.png&quot; alt=&quot;Screenshot My Weather Card Combo&quot; title=&quot;Screenshot 4: My Weather Card Combo&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 4: My Weather Card Combo&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/weather-cards-in-home-assistant-my-top-picks/#conclusion&quot; aria-labelledby=&quot;conclusion&quot;&gt;#&lt;/a&gt;&lt;p&gt;There’s no one-size-fits-all answer. Home Assistant’s default forecast card covers the basics well, but the community has provided excellent alternatives for anyone wanting more features or a nicer look.&lt;/p&gt;
&lt;p&gt;If you haven’t tried a new card in a while, I recommend experimenting—weather is one of those bits of information you glance at every day, so it’s worth making it just right.&lt;/p&gt;
&lt;p&gt;Happy automating!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Home Assistant Backup in 2025</title>
    <link href="https://markus-haack.com/home-assistant-backup-2025/"/>
    <updated>2025-02-23T00:00:00Z</updated>
    <id>https://markus-haack.com/home-assistant-backup-2025/</id>
    <content type="html">&lt;p&gt;Two years ago, I wrote about &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/&quot;&gt;backing up Home Assistant to a Synology NAS&lt;/a&gt; using NFS shares. While that method still works, the Home Assistant team has gone all-in on backups and massively improved Home Assistant’s native backup capabilities with the &lt;a href=&quot;https://www.home-assistant.io/blog/2025/01/03/release-20251/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;2025.1&lt;/a&gt; and &lt;a href=&quot;https://www.home-assistant.io/blog/2025/02/05/release-20252/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;2025.2&lt;/a&gt; releases. I have already adjusted my backup configuration. Let’s explore what’s new and why you should update your approach.&lt;/p&gt;
&lt;p&gt;The Home Assistant team calls the now backup strategy: &lt;a href=&quot;https://www.home-assistant.io/blog/2025/01/03/3-2-1-backup/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;3…2…1… Backup&lt;/a&gt;. This means a solid backup strategy follows the 3-2-1 rule:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 copies of your data&lt;/li&gt;
&lt;li&gt;2 stored on different media&lt;/li&gt;
&lt;li&gt;1 kept off-site&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The recommendation is to backup regular and frequently. IMHO once a week is a good rule of a thumb. Keep backups at different locations. If you house burns down or a lightning strike you local and NAS backup could be extinguished. To be prepared for this, I synchronise important data from our NAS to the cloud (AWS S3 in our case). With the new cloud backup destinations, this can now be done directly from Home Assistant.&lt;/p&gt;
&lt;h2 id=&quot;upgrade-your-backup-strategy-with-home-assistant%E2%80%99s-2025-features.&quot;&gt;Upgrade your backup strategy with Home Assistant’s 2025 features.&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#upgrade-your-backup-strategy-with-home-assistant%E2%80%99s-2025-features.&quot; aria-labelledby=&quot;upgrade-your-backup-strategy-with-home-assistant%E2%80%99s-2025-features.&quot;&gt;#&lt;/a&gt;&lt;p&gt;Let’s have a quick look at them together, and then I’ll give you step-by-step instructions on how to configure a backup from Home Assistant 2025 onwards.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Easy Setup&lt;/strong&gt;&lt;br&gt;
The Home Assistant team has spent a lot of time making the experience as simple as possible. A new automatic backup configuration can be created with just 3 clicks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cloud Storage&lt;/strong&gt;&lt;br&gt;
Automatic backups can be saved locally or off-machine. For Home Assistant subscribers, these can be stored directly in Home Assistant Cloud. Network shares will of course continue to work. Other cloud backup options include &lt;a href=&quot;https://www.home-assistant.io/integrations/google_drive/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google Drive&lt;/a&gt; and &lt;a href=&quot;https://www.home-assistant.io/integrations/onedrive/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Microsoft OneDrive&lt;/a&gt; and there will be more (cloud) backup locations in the future.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Encryption&lt;/strong&gt;&lt;br&gt;
Backups to the Home Assistant Cloud are now secure and encrypted by default. For local backups to your NAS, you can choose to store them encrypted or unencrypted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scheduling and Retention&lt;/strong&gt;&lt;br&gt;
The new automatic backup also makes it easier to keep an overview. You can flexibly set when and how often the backup should run and how many versions should be kept.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;native-backups-to-the-place-of-your-choice&quot;&gt;Native backups to the place of your choice&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#native-backups-to-the-place-of-your-choice&quot; aria-labelledby=&quot;native-backups-to-the-place-of-your-choice&quot;&gt;#&lt;/a&gt;&lt;p&gt;Home Assistant 2025.2 eliminates the need for plugins such as Samba Backup or Google Drive add-ons. The update introduced native integrations for&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Synology NAS via DSM&lt;/li&gt;
&lt;li&gt;Google Drive&lt;/li&gt;
&lt;li&gt;Microsoft OneDrive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The integrations for these have been updated and are ready for the new automatic backups. This gives Home Assistant users who are not subscribed to Home Assistant Cloud many alternative cloud storage or local storage options.&lt;/p&gt;
&lt;p&gt;You can also combine locations for 3-2-1 protection – I store weekly backups on my Synology NAS &lt;em&gt;and&lt;/em&gt; Home Assistant Cloud simultaneously. Here I keep the last 3 backups. Additionally I create a backup on every Home Assistant update, just in case.&lt;/p&gt;
&lt;h2 id=&quot;from-0-to-data-protection-in-90-seconds&quot;&gt;From 0 to data protection in 90 seconds&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#from-0-to-data-protection-in-90-seconds&quot; aria-labelledby=&quot;from-0-to-data-protection-in-90-seconds&quot;&gt;#&lt;/a&gt;&lt;p&gt;Setting up the new automatic backup does not take much time.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Settings → System → Backups&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Set Up Backups&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;new encryption key&lt;/strong&gt; will be created the first time, please make a note of it. Store it in a password manager!&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Recommended Settings&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Done - Home Assistant will create your first backup for you.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2025-1.png&quot; alt=&quot;screenshot 1&quot; title=&quot;Screenshot 1: Home Assistant Backup&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 1: Home Assistant Backup&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;To save a backup of our system in the cloud, just a few clicks are necessary. In the &lt;strong&gt;Backup settings&lt;/strong&gt; area, click on the last menu item for the backup locations.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2025-2.png&quot; alt=&quot;screenshot 2&quot; title=&quot;Screenshot 2: Home Assistant Backup Locations&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 2: Home Assistant Backup Locations&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The local backup should already be displayed here. In my case, I have already moved this to the NAS as storage space. Cloud storage locations can now also be selected here for the backup.&lt;/p&gt;
&lt;p&gt;Depending on your configuration, several backups will accumulate over time. Click ‘Show all backups’ to view all backups.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2025-3.png&quot; alt=&quot;screenshot 3&quot; title=&quot;Screenshot 3: Home Assistant - My Backups&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 3: Home Assistant - My Backups&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Which locations are displayed here depends on the installed integration &lt;a href=&quot;https://www.home-assistant.io/integrations/google_drive/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google Drive&lt;/a&gt;,  &lt;a href=&quot;https://www.home-assistant.io/integrations/onedrive/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Microsoft OneDrive&lt;/a&gt; and &lt;a href=&quot;https://www.home-assistant.io/integrations/synology_dsm/#backup-location&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Synology DSM&lt;/a&gt;. And whether you have a Nabu Casa subscription or not. Only with Nabu Casa subscription you will have the “Home Assistant Cloud” option.&lt;/p&gt;
&lt;h2 id=&quot;backup-to-synology-in-2025&quot;&gt;Backup to Synology in 2025&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#backup-to-synology-in-2025&quot; aria-labelledby=&quot;backup-to-synology-in-2025&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you want to store your backup on a Synology NAS, please have a look at &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/&quot;&gt;my first article&lt;/a&gt;. The configuration steps on the NAS are exactly the same and still apply.&lt;/p&gt;
&lt;p&gt;In order to select Synology as a backup target for Home Assistant, an extra configuration step is required:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to Settings &amp;gt; Devices&lt;/li&gt;
&lt;li&gt;Select the “Synology DSM” integration&lt;/li&gt;
&lt;li&gt;Click on “Configure”&lt;/li&gt;
&lt;li&gt;In the dialog select one of the shared folders and enter an folder name.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The shared folders are configured on the Synology NAS. If this list is empty or the desired folder for the backups does not appear here, this must be set on Synology. See &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/&quot;&gt;my first article&lt;/a&gt; on how to achive this.&lt;/p&gt;
&lt;p&gt;The dialog should look similar to:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2025-4.png&quot; alt=&quot;screenshot 4&quot; title=&quot;Screenshot 4: Synology Backup Config&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 4: Synology Backup Config&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After the Synology backup directories have been configured, Synology DSM is made available as a backup location.&lt;/p&gt;
&lt;p&gt;Go back to the backup settings and click configure again. Synology DSM is now available as backup location and can be enabled. You can select whether the backups on the NAS should be encrypted, see next chapter. I have switched this off in my case.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2025-5.png&quot; alt=&quot;screenshot 5&quot; title=&quot;Screenshot 5: Synology Backup Location&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 5: Synology Backup Location&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The generic NAS backup localtion can still be used, but is not requiered any more.&lt;/p&gt;
&lt;p&gt;Other integrations are not automatically configured as a backup target and must be set up separately. See the integration documentation for more information.&lt;/p&gt;
&lt;h2 id=&quot;flexible-encryption&quot;&gt;Flexible Encryption&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#flexible-encryption&quot; aria-labelledby=&quot;flexible-encryption&quot;&gt;#&lt;/a&gt;&lt;p&gt;Home Assistant 2025.1 introduced automatic encryption of all backups. While encryption is still the default, you can now disable it on a per location basis.&lt;/p&gt;
&lt;p&gt;Why disable? Unencrypted local or NAS backups allow direct file recovery without Home Assistant. This can be useful in some cases. However, cloud backups will always remain encrypted for security.&lt;/p&gt;
&lt;h2 id=&quot;precision-scheduling-%26-smart-automation&quot;&gt;Precision Scheduling &amp;amp; Smart Automation&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#precision-scheduling-%26-smart-automation&quot; aria-labelledby=&quot;precision-scheduling-%26-smart-automation&quot;&gt;#&lt;/a&gt;&lt;p&gt;Automatic backups allow a very flexible setting of when - day &amp;amp; time - a backup should be created. The retention period can also be set individually.&lt;/p&gt;
&lt;p&gt;In my case, I have a backup created at the weekend, every Saturday at 4.45am. The days, frequency and even the backup time can be set to suit your needs. Retention can be configured based on the number of backups you want to keep or the number of days you want to keep them.&lt;/p&gt;
&lt;p&gt;If the recommended settings to not fit go to: &lt;strong&gt;Settings → System → Backups&lt;/strong&gt; and select the first option in the &lt;strong&gt;Backup settings&lt;/strong&gt; area. This will bring you to the automatic backups options which can be flexibly adjusted here.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2025-6.png&quot; alt=&quot;screenshot 6&quot; title=&quot;Screenshot 6: Home Assistant Automatic Backup Options&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 6: Home Assistant Automatic Backup Options&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;conditional-backups-via-automation&quot;&gt;Conditional Backups via Automation&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#conditional-backups-via-automation&quot; aria-labelledby=&quot;conditional-backups-via-automation&quot;&gt;#&lt;/a&gt;&lt;p&gt;In addition to all the automatic backup settings, you also have the option of creating backups manually or using automation.&lt;/p&gt;
&lt;p&gt;This makes sense, for example, if a fixed schedule cannot be used because, for example, the NAS server is switched off at night. Home Assistant provides the &lt;code&gt;backup.create_automatic&lt;/code&gt; action for automations.&lt;/p&gt;
&lt;p&gt;The following sample automation trigger backups when your NAS is awake:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;automation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Backup Home Assistant 5 min after NAS is online&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;triggers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
      &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.nas_online
      &lt;span class=&quot;token key atrule&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;on&#39;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Create backup now&#39;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; backup.create_automatic&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the help of a simple automation above, you can start the creation of a backup for a specific backup destination.&lt;/p&gt;
&lt;h2 id=&quot;disaster-recovery-protocol&quot;&gt;Disaster Recovery Protocol&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#disaster-recovery-protocol&quot; aria-labelledby=&quot;disaster-recovery-protocol&quot;&gt;#&lt;/a&gt;&lt;p&gt;Just as important as the regular creation of backups is the restoration. This should also be tested regularly.&lt;/p&gt;
&lt;p&gt;This is somewhat more time-consuming and annoying to accomplish. Nobody wants to mess around with their production system. That’s why you need a second piece of hardware to test the restore procedure. I use a Raspberry Pi that I still have lying around. Here I test the restore flow using my backups stored on our NAS. Unfortunately, the whole thing is quite time-consuming and I admit I should actually test it more often. Fingers crossed the Home Assistant backups are ok and not defective.&lt;/p&gt;
&lt;h2 id=&quot;final-thoughts%3A-backups-are-boring-until-they%E2%80%99re-critical&quot;&gt;Final Thoughts: Backups Are Boring Until They’re Critical&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-2025/#final-thoughts%3A-backups-are-boring-until-they%E2%80%99re-critical&quot; aria-labelledby=&quot;final-thoughts%3A-backups-are-boring-until-they%E2%80%99re-critical&quot;&gt;#&lt;/a&gt;&lt;p&gt;Let me summarise what has changed and improved compared to &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/&quot;&gt;my first Home Assistant backup article&lt;/a&gt; in the following table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;2023 Approach&lt;/th&gt;
&lt;th&gt;2025 Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backup Locations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local or NAS&lt;br&gt;Additional only via Add-ons&lt;/td&gt;
&lt;td&gt;Local, NAS &amp;amp; Cloud Backup built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Per-Location Toggle, Mandatory for Cloud locations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trigger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Via Automation&lt;/td&gt;
&lt;td&gt;Auto-Triggered, Via UI, Via Automation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Home Assistant’s 2025 backup tools have matured. With all the new features and configuration options, there is no excuse for not backing up your system. It’s easier than ever before.&lt;/p&gt;
&lt;p&gt;Define your backup strategy today – your future self will thank you when the SD card fails at 2 AM.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Our 2024 Solar Power Performance</title>
    <link href="https://markus-haack.com/our-2024-solar-power-performance/"/>
    <updated>2025-02-01T00:00:00Z</updated>
    <id>https://markus-haack.com/our-2024-solar-power-performance/</id>
    <content type="html">&lt;p&gt;Our home’s solar energy system continued its upward trajectory in 2024. In fact, compared to previous years, it provided a slight increase in energy production. This post looks at our solar performance in 2024, highlighting key trends and comparing them with the results from 2021, 2022 and 2023.&lt;/p&gt;
&lt;h2 id=&quot;2024%3A-a-bountiful-harvest-of-solar-energy&quot;&gt;2024: A Bountiful Harvest of Solar Energy&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2024-solar-power-performance/#2024%3A-a-bountiful-harvest-of-solar-energy&quot; aria-labelledby=&quot;2024%3A-a-bountiful-harvest-of-solar-energy&quot;&gt;#&lt;/a&gt;&lt;p&gt;In 2024, our solar panels generated a total of 8571 kWh, an improvement on 2023 but slightly lower than 2022. This represents a step towards greater energy independence and, of course, a lower energy bill. As expected, the data clearly shows a seasonal pattern:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/solar-2025-1.png&quot; alt=&quot;2024 production and consumption &quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Peak Production (June &amp;amp; July):&lt;/strong&gt; June and July were our most productive months with 1246 kWh and 1279 kWh respectively. This highlights the effectiveness of our system during peak sunlight hours. July &amp;amp; August 2024 had the highest energy yield compared to July &amp;amp; August of previous years. May was still good with a production of 1,140 kWh, but it looks like we had much less sun in May in 2024 compared to previous years.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lowest Production (December &amp;amp; January):&lt;/strong&gt; As expected, December (132 kWh) and January (181 kWh) had the lowest production due to shorter daylight hours and less intense solar radiation. However, both of these months were the best since our records began. In previous years, we did not even reach &amp;gt; 100 kWh in these winter months.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;last-4-years-of-our-energy-production&quot;&gt;Last 4 Years of our Energy Production&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2024-solar-power-performance/#last-4-years-of-our-energy-production&quot; aria-labelledby=&quot;last-4-years-of-our-energy-production&quot;&gt;#&lt;/a&gt;&lt;p&gt;The table below provides a comparison of our energy production and consumption across the years 2021-2024:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Solar Energy Production&lt;/th&gt;
&lt;th&gt;Electricity Consumption&lt;/th&gt;
&lt;th&gt;Grid Electricity Used&lt;/th&gt;
&lt;th&gt;Self-Consumption&lt;/th&gt;
&lt;th&gt;Self-Consumption Quota&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;7780 kWh&lt;/td&gt;
&lt;td&gt;9721 kWh&lt;/td&gt;
&lt;td&gt;4677 kWh&lt;/td&gt;
&lt;td&gt;5044 kWh&lt;/td&gt;
&lt;td&gt;52 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;9104 kWh&lt;/td&gt;
&lt;td&gt;10192 kWh&lt;/td&gt;
&lt;td&gt;4552 kWh&lt;/td&gt;
&lt;td&gt;5640 kWh&lt;/td&gt;
&lt;td&gt;55 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;8292 kWh&lt;/td&gt;
&lt;td&gt;10361 kWh&lt;/td&gt;
&lt;td&gt;5181 kWh&lt;/td&gt;
&lt;td&gt;5180 kWh&lt;/td&gt;
&lt;td&gt;50 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;8571 kWh&lt;/td&gt;
&lt;td&gt;10297 kWh&lt;/td&gt;
&lt;td&gt;4994 kWh&lt;/td&gt;
&lt;td&gt;5303 kWh&lt;/td&gt;
&lt;td&gt;52 %&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;energy-consumption%3A-a-relatively-stable-baseline&quot;&gt;Energy Consumption: A Relatively Stable Baseline&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2024-solar-power-performance/#energy-consumption%3A-a-relatively-stable-baseline&quot; aria-labelledby=&quot;energy-consumption%3A-a-relatively-stable-baseline&quot;&gt;#&lt;/a&gt;&lt;p&gt;Our total electricity consumption for 2024 was 10297 kWh, a relatively stable figure compared to recent years. The increase in solar energy production in 2024 compared to 2023 allowed us to self-consume 5303 kWh, reducing our reliance on the grid to just 4894 kWh. This reduced our grid dependency by ~100 kWh.&lt;br&gt;
Unfortunately, due to rising electricity prices in Germany, this is not reflected in the electricity costs.&lt;/p&gt;
&lt;h2 id=&quot;outlook%3A-changes-in-sight---or-not&quot;&gt;Outlook: Changes in sight - or not&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-2024-solar-power-performance/#outlook%3A-changes-in-sight---or-not&quot; aria-labelledby=&quot;outlook%3A-changes-in-sight---or-not&quot;&gt;#&lt;/a&gt;&lt;p&gt;The year 2024 was similar to previous years, both in terms of solar energy production and our consumption. There has been no major change. However, we have noticed a slight increase in electricity production compared to previous years, especially in the winter months, as we have less snow and frost. We can also observe this in January 2025.&lt;/p&gt;
&lt;p&gt;Overall, we do not expect any fundamental changes in 2025. By changing the electricity provider, we will probably be able to further reduce the electricity costs for grid purchases. We may also switch to a dynamic electricity tariff later in the year.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Implement large-scale projects on AEM Edge Delivery Services</title>
    <link href="https://markus-haack.com/implement-large-scale-projects-on-aem-edge-delivery-services/"/>
    <updated>2024-11-02T00:00:00Z</updated>
    <id>https://markus-haack.com/implement-large-scale-projects-on-aem-edge-delivery-services/</id>
    <content type="html">&lt;p&gt;We recently had the opportunity to present at &lt;a href=&quot;https://adapt.to/2024&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;adaptTo()&lt;/a&gt; in Berlin, one of the most anticipated tech conferences in the Adobe Experience Manager community. Together with my colleague &lt;a href=&quot;https://www.linkedin.com/in/anianweber/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Anian Weber &lt;/a&gt;we delivered an in-depth session on AEM Edge Delivery Services, focusing on how its capabilities have evolved well beyond small blog websites and basic corporate pages. Our talk aimed to answer a critical question: &lt;em&gt;Is it feasible to implement complex, multilingual, and multisite projects using AEM Edge Delivery Services while preserving the performance, flexibility, and ease of use it promises?&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;key-takeaways-from-our-talk&quot;&gt;Key Takeaways from Our Talk&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/implement-large-scale-projects-on-aem-edge-delivery-services/#key-takeaways-from-our-talk&quot; aria-labelledby=&quot;key-takeaways-from-our-talk&quot;&gt;#&lt;/a&gt;&lt;p&gt;Our presentation explored strategic approaches to designing and managing global, multilanguage projects within the AEM Edge Delivery framework. Based on real-world projects and challenges we’ve encountered, we walked attendees through essential steps in setting up large-scale projects, from effective developer configurations and content organization strategies to optimized translation workflows.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/adaptto-2024-2.jpeg&quot; alt=&quot;Presenting on adaptto() stage&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;For those interested in diving deeper into these topics, our &lt;a href=&quot;https://adapt.to/2024/schedule/scaling-up-implement-large-scale-projects-on-aem-edge-delivery-services&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;slide deck is available on the adaptTo() conference website&lt;/a&gt;. And stay tuned—the full recording of our talk will be available soon!&lt;/p&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/implement-large-scale-projects-on-aem-edge-delivery-services/#final-thoughts&quot; aria-labelledby=&quot;final-thoughts&quot;&gt;#&lt;/a&gt;&lt;p&gt;In addition to our presentation, I also had the pleasure of participating in an expert panel discussion on Adobe Edge Delivery Services. This session was a great chance to connect with AEM developers and learn about their thoughts &amp;amp; questions about the potential and challenges of Edge Delivery.&lt;/p&gt;
&lt;p&gt;Presenting at adaptTo() Berlin was a fantastic experience, and I’m excited to see how AEM Edge Delivery Services continues to transform as a robust solution for complex, multilingual projects. Thank you to everyone who attended our session and engaged with us during the panel discussion!&lt;/p&gt;
&lt;p&gt;For anyone interested in implementing AEM Edge Delivery for large-scale, global projects, feel free to reach out—we’re always excited to discuss insights and share knowledge on this evolving platform.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Automate Reolink camera notifications with Home Assistant</title>
    <link href="https://markus-haack.com/automate-reolink-camera-notifications/"/>
    <updated>2024-09-19T00:00:00Z</updated>
    <id>https://markus-haack.com/automate-reolink-camera-notifications/</id>
    <content type="html">&lt;p&gt;As I wrote in &lt;a href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/&quot;&gt;my previous post&lt;/a&gt;, I recently switched from Arlo cameras to Reolink cameras. The Reolink cameras have excellent hardware quality, an aluminium housing and no cloud subscription obligation.&lt;/p&gt;
&lt;p&gt;However, there are some gaps in the software and functions that have been standard with Arlo and other providers for years are missing here. The camera alarms cannot be automated and there is also no geo-fencing in the app so that the cameras can be activated automatically when everyone has left the house.&lt;/p&gt;
&lt;p&gt;This is where Home Assistant comes into play, as it can close these gaps.&lt;/p&gt;
&lt;h2 id=&quot;what-is-actually-missing-in-the-reolink-software%3F&quot;&gt;What is actually missing in the Reolink Software?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/automate-reolink-camera-notifications/#what-is-actually-missing-in-the-reolink-software%3F&quot; aria-labelledby=&quot;what-is-actually-missing-in-the-reolink-software%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;The only out-of-the-box way to quickly change the recording or push notification settings of multiple cameras at once is to use shortcuts within the Reolink app:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/reolink-app.png&quot; alt=&quot;Screenshot Reolink iOS App&quot; title=&quot;Scenes in the Reolink iOS App&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Scenes in the Reolink iOS App&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;At least in the Reolink iOS app, this feature is somewhat hidden and not immediately obvious. In the camera view, you normally only see the cameras. However, if you drag the whole view down a bit, you can see 3 badges. These are assigned shortcuts that can also be customised. You can toggle recording on and off, and enable or disable push or email alerts for each camera. You can also turn on the alarm sound.&lt;/p&gt;
&lt;p&gt;You can create different scenes. What you cannot do is control these scenes automatically. You always have to open the app to activate them, and they cannot be triggered at a certain time or by another event.&lt;/p&gt;
&lt;p&gt;So how do we solve this problem? To fill the gaps and add the missing functionality, Home Assistant comes in as a powerful smart home platform.&lt;/p&gt;
&lt;h2 id=&quot;automate-the-push-notifications&quot;&gt;Automate the push notifications&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/automate-reolink-camera-notifications/#automate-the-push-notifications&quot; aria-labelledby=&quot;automate-the-push-notifications&quot;&gt;#&lt;/a&gt;&lt;p&gt;Just like us, almost all camera users only want to receive push notifications at certain times. We have different notification profiles depending on the time of day or day of the week.&lt;/p&gt;
&lt;p&gt;When we’re at home in the garden, we don’t need notifications from the cameras in the garden or by the pool. It’s only us who would trigger them anyway. However, if someone is at the entrance and rings the doorbell, we don’t notice this in the garden, so notifications from the entrance camera are important.&lt;/p&gt;
&lt;p&gt;In our case the notifications will follow this patten:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;Camera&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;Week - Day&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;Weekend - Day&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;Nights&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;Frontdoor&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;on&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;on&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;Carport&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;on&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;off&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;Garden&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;off&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;off&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;To enable / disable the notifications as needed I use two automations in Home Assistant. The first on is triggered at sunset to enable the push notification settings of all the cameras:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-activate-reolink-notifications-sunset.png&quot; alt=&quot;Screenshot Home Assistant Automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;In YAML this looks like (simplified version):&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Camera] Activate notifications on sunset&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sun
   &lt;span class=&quot;token key atrule&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sunset
   &lt;span class=&quot;token key atrule&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second time-based automation is triggered at sunrise in the morning to switch the notifications back on. This only runs when we are at home, as we do not want the push notifications to be turned off when we are away. The carport camera notifications are only disabled at weekends.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-de-activate-reolink-notifications-sunrise.png&quot; alt=&quot;Screenshot Home Assistant Automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;In YAML this looks like:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[Camera] De-activate notifications on sunrise&quot;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sun
    &lt;span class=&quot;token key atrule&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sunrise
    &lt;span class=&quot;token key atrule&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; group.jama
    &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; home
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_off
    &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
    &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_off
    &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
    &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
        &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.workday_sensor
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;off&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_off
	    &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 3 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
	    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 3 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
        &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;add-the-missing-geofencing&quot;&gt;Add the missing geofencing&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/automate-reolink-camera-notifications/#add-the-missing-geofencing&quot; aria-labelledby=&quot;add-the-missing-geofencing&quot;&gt;#&lt;/a&gt;&lt;p&gt;When we are out and about and nobody is at home, we naturally also want to be notified by the cameras if something happens. Why else would we have surveillance cameras?&lt;/p&gt;
&lt;p&gt;As it is not possible to control these automatically via the Reolink app, and manually activating the scenes in the app is not a solution, we have also automated this using Home Assistant. We also set up two automations to make this work.&lt;/p&gt;
&lt;p&gt;One is triggered when we have all left the house and the other is triggered when at least one member of the family has returned home. The trigger can be either a mobile phone location change, a person location change or, as in our case, a group of people. &lt;a href=&quot;https://www.home-assistant.io/integrations/group/#old-style-groups&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Groups of people&lt;/a&gt; are still supported in Home Assistant, but can only be defined in YAML.&lt;/p&gt;
&lt;p&gt;Activating the camera notifications when nobody is at home:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-activate-reolink-notifications-geofence.png&quot; alt=&quot;Screenshot Home Assistant Automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The YAML version:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Camera] Activate notifications on leaving&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; group.jama
   &lt;span class=&quot;token key atrule&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; home
   &lt;span class=&quot;token key atrule&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; not_home
&lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Disabling push notifications follows a similar pattern. There’s an extra check because when we come home late at night, we want the cameras to stay on and we don’t want the notification to be disabled. So this automation only runs before sunset and after sunrise to be in sync with the time-based rules described above.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-de-activate-reolink-notifications-geofence.png&quot; alt=&quot;Screenshot Home Assistant Automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The script version of this automation looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Camera] De-activate notifications on coming home&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; group.jama
   &lt;span class=&quot;token key atrule&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; not_home
   &lt;span class=&quot;token key atrule&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; home
&lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sun
   &lt;span class=&quot;token key atrule&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sunset
   &lt;span class=&quot;token key atrule&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sunrise
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_off
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 1 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_off
   &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.&amp;lt;&amp;lt;&amp;lt; camera 2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;_push_notifications
   &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/automate-reolink-camera-notifications/#conclusion&quot; aria-labelledby=&quot;conclusion&quot;&gt;#&lt;/a&gt;&lt;p&gt;Take control of your push notifications with just four simple automations in Home Assistant. You decide when you want to be notified and when you don’t.&lt;br&gt;
This lets you fill a gap in the Reolink app and add the missing functions yourself.&lt;br&gt;
You can also use Home Assistant to create other useful workflows around the cameras. I’ll explain more in a later article.&lt;/p&gt;
&lt;p&gt;I am certain you will find this guide helpful. Please do not hesitate to ask if you have any questions.&lt;/p&gt;
&lt;p&gt;Hero image: AI generated with ChatGPT.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to Integrate Reolink Cameras into Home Assistant</title>
    <link href="https://markus-haack.com/reolink-cameras-in-home-assistant/"/>
    <updated>2024-09-13T00:00:00Z</updated>
    <id>https://markus-haack.com/reolink-cameras-in-home-assistant/</id>
    <content type="html">&lt;p&gt;I recently replaced all our security cameras around the house with new &lt;a href=&quot;https://reolink.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Reolink&lt;/a&gt; network cameras with either Wifi or PoE (Power of Ethernet). In this post, we will walk through the process of integrating Reolink Network Cameras into Home Assistant. With this integration, you can stream live footage, set up motion detection automations, and even record clips based on events. Here is why, and more importantly, how to set up the new cameras in &lt;a href=&quot;https://home-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-i-switched-from-arlo-to-reolink&quot;&gt;Why I Switched from Arlo to Reolink&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#why-i-switched-from-arlo-to-reolink&quot; aria-labelledby=&quot;why-i-switched-from-arlo-to-reolink&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you’ve been following my blog for a while, you know I previously wrote about my experience integrating &lt;a href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/&quot;&gt;Arlo cameras into Home Assistant&lt;/a&gt;. At the time, Arlo’s cameras seemed like a great option due to their robust features and seamless cloud integration. I was a happy customer for many years. However, things changed with Arlo forcing customers into a &lt;a href=&quot;https://www.arlo.com/serviceplans&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;cloud subscription and service plan&lt;/a&gt;. Without that the already expensive cameras are super limited - IMHO they are useless. Many basic features, like accessing recordings, activity zones and certain smart alerts, are locked behind their premium tiers.&lt;/p&gt;
&lt;h2 id=&quot;the-new-camera-setup&quot;&gt;The new camera setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#the-new-camera-setup&quot; aria-labelledby=&quot;the-new-camera-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;This made me start exploring more flexible, budget-friendly options that would allow local control over my cameras without being dependent on a cloud subscription. My requirements for the new setup were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;local only, without the need for a monthly subscription plan&lt;/li&gt;
&lt;li&gt;enough storage for 24/7 recording (in future) or SD Card&lt;/li&gt;
&lt;li&gt;can be powered via power over ethernet (PoE)&lt;/li&gt;
&lt;li&gt;Wifi option available&lt;/li&gt;
&lt;li&gt;Home Assistant integration possible&lt;/li&gt;
&lt;li&gt;bonus points for smart object detection (person, vehicle, animals, parcels)&lt;/li&gt;
&lt;li&gt;bonus points for rich push notification&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After checking our various options and spending hours on Reddit forums I ended up with Reolink network cameras.&lt;/p&gt;
&lt;p&gt;Our setup now consists of 6 cameras:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://reolink.com/us/product/rlc-540a/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;5MP RLC-540A PoE dome camera&lt;/a&gt; at the front door&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reolink.com/us/product/rlc-520a/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;5MP RLC-520A PoE camera&lt;/a&gt; in the carport&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reolink.com/us/product/cx410/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;2K 4MP CX410 camera&lt;/a&gt;with color night vision&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reolink.com/us/product/rlc-81ma/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;4K Smart Dual-Lens PoE Camera&lt;/a&gt;with super large diagonal via for the garden&lt;/li&gt;
&lt;li&gt;2 &lt;a href=&quot;https://reolink.com/us/product/rlc-810wa/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;4K Camera RLC-810WA&lt;/a&gt; with Wifi 6 for the garden and pool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reolink also offers battery powered cameras, dual view cameras or video door bells. Most of them &lt;a href=&quot;https://www.home-assistant.io/integrations/reolink/#tested-models&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;should also work with Home Assistant&lt;/a&gt;, however I only could test the cameras listed above.&lt;/p&gt;
&lt;p&gt;IMHO Reolink cameras offer excellent hardware at a reasonable price, with features like RTSP, ONVIF and even native home assistant integration, allowing me to maintain complete local control. The camera body is made of aluminium and there is a huge selection of PoE camera options. Best of all, Reolink doesn’t force you into a paid subscription to access key features, and they offer easy integration with Home Assistant for real-time monitoring, motion detection and video recording - no monthly fees.&lt;/p&gt;
&lt;p&gt;However, not everything is perfect, and even Reolink’s cameras have a few minor flaws.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most models, including the one I got, are only available with a white casing. Sometimes (like the RLC-520A) the different colour models have different specifications, such as different lenses.&lt;/li&gt;
&lt;li&gt;There is not much room for the antenna mounts on the wifi cameras, such as the RCL-810WA models. If the bracket is very tilted, the antennas cannot be mounted due to lack of space. The solution is a short extension cable &lt;a href=&quot;https://www.amazon.de/dp/B07MT3VZXZ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;such as this one&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Push notification in mixed languages, some cameras send notifications in German like the newer CX410 models, others only in English.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The biggest missing features are camera automation and geo-fencing, as we want to automatically activate the cameras when nobody is at home and after sunset. Arlo was much better at this. The good news is that this problem can be solved by using some automation in the Home Assistant. Finally, we only use the iOS application to view recordings when we receive notifications.&lt;/p&gt;
&lt;h2 id=&quot;integrate-reolink-network-cameras-into-home-assistant&quot;&gt;Integrate Reolink Network Cameras into Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#integrate-reolink-network-cameras-into-home-assistant&quot; aria-labelledby=&quot;integrate-reolink-network-cameras-into-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;In the following step-by-step guide I will walk you through how to add your Reolink cameras to Home Assistant with the &lt;a href=&quot;https://www.home-assistant.io/integrations/reolink/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;native Reolink integration&lt;/a&gt;. There are alternative integration options, for example using the &lt;a href=&quot;https://www.home-assistant.io/integrations/onvif/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ONVIF integration&lt;/a&gt; or manual RTSP setup as well. However in the guide below I will focus on the Reolink integration only.&lt;/p&gt;
&lt;h3 id=&quot;what-you-will-need&quot;&gt;What You Will Need&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#what-you-will-need&quot; aria-labelledby=&quot;what-you-will-need&quot;&gt;#&lt;/a&gt;&lt;ol&gt;
&lt;li&gt;Reolink Network Camera (with firmware that supports the Home Assistant Reolink integration)&lt;/li&gt;
&lt;li&gt;Home Assistant&lt;/li&gt;
&lt;li&gt;Reolink App credentials (admin user and password)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;step-1%3A-prepare-your-reolink-camera&quot;&gt;Step 1: Prepare Your Reolink Camera&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#step-1%3A-prepare-your-reolink-camera&quot; aria-labelledby=&quot;step-1%3A-prepare-your-reolink-camera&quot;&gt;#&lt;/a&gt;&lt;p&gt;Before integrating the camera into Home Assistant, make sure you can access your Reolink camera via the Reolink app or web portal, and it is connected to the same network as your Home Assistant instance.&lt;/p&gt;
&lt;p&gt;Optional: Enable the optional camera protocols&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open the &lt;strong&gt;Reolink App&lt;/strong&gt; or web interface.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Network Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Advanced&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Ensure that features like RTSP and ONVIF are enabled just in case they are needed for advanced use cases later on (although not required for the integration).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;step-2%3A-add-reolink-integration-to-home-assistant&quot;&gt;Step 2: Add Reolink Integration to Home Assistant&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#step-2%3A-add-reolink-integration-to-home-assistant&quot; aria-labelledby=&quot;step-2%3A-add-reolink-integration-to-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;At first we need to enabled the Reolink integration in Home Assistant.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Log in to your &lt;strong&gt;Home Assistant&lt;/strong&gt; instance.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Devices &amp;amp; Services&lt;/strong&gt; &amp;gt; &lt;strong&gt;+ Add Integration&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the search bar, type “Reolink” and select the &lt;strong&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/reolink/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Reolink integration&lt;/a&gt;&lt;/strong&gt; from the list.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;step-3%3A-add-your-cameras&quot;&gt;Step 3: Add your cameras&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#step-3%3A-add-your-cameras&quot; aria-labelledby=&quot;step-3%3A-add-your-cameras&quot;&gt;#&lt;/a&gt;&lt;p&gt;Reolink IP cameras - cable network or WiFi connected - can be auto-discovered by Home Assistant. If an device was found, it will be shown as &lt;em&gt;discovered&lt;/em&gt;. You can then set it up right away.&lt;/p&gt;
&lt;p&gt;If the camera is not auto-discovered it can be manually added by clicking on &lt;strong&gt;Add Entry&lt;/strong&gt;. In the following dialog enter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Username&lt;/strong&gt;: Admin or another user with admin privileges set up for the camera.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password&lt;/strong&gt;: Camera password.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IP Address&lt;/strong&gt;: The local IP address of the Reolink camera on your network.&lt;/li&gt;
&lt;li&gt;Once entered, click &lt;strong&gt;Submit&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/reolink-setup-1.png&quot; alt=&quot;Set up a Reolink camera in Home Assistant&quot; title=&quot;Set up a Reolink camera in Home Assistant&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Set up a Reolink camera in Home Assistant&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Once configured you can change the camera protocol used by Home Assistant to communicated with the camera. You can choose between RTSP, RTMP, or FLV streaming protocol. If there are no streaming issues, lagging video etc. I recommend to leave this setting at RTSP as this should give you the best video results and is the only protocol which can stream 4K camera streams.&lt;/p&gt;
&lt;h3 id=&quot;step-4%3A-confirm-the-camera-is-added-to-home-assistant&quot;&gt;Step 4: Confirm the Camera is added to Home Assistant&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#step-4%3A-confirm-the-camera-is-added-to-home-assistant&quot; aria-labelledby=&quot;step-4%3A-confirm-the-camera-is-added-to-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;After submitting your credentials, Home Assistant will automatically communicate with the Reolink camera and set up the connection. If the integration is successful, you will see a confirmation message, and the camera will appear in your list of devices.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/reolink-setup-2.png&quot; alt=&quot;Reolink camera integration in Home Assistant&quot; title=&quot;Reolink camera integration in Home Assistant&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Reolink camera integration in Home Assistant&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-5%3A-view-the-camera-in-devices&quot;&gt;Step 5: View the Camera in Devices&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#step-5%3A-view-the-camera-in-devices&quot; aria-labelledby=&quot;step-5%3A-view-the-camera-in-devices&quot;&gt;#&lt;/a&gt;&lt;p&gt;If the Reolink device view is not already open:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Devices &amp;amp; Services&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Devices&lt;/strong&gt;, you should now see your Reolink camera listed as a device. Click on it to view more information and entities that have been created for the camera (e.g., video feed, motion sensor, etc.).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depending on the features and capabilities of the camera the Reolink integration creates 40 or more entities for each camera device. It is very verbose and detailed. All the configuration setting you have in the Reolink app are exposed as well in Home Assistant. I personally disable most of the entires in the &lt;em&gt;Configuration&lt;/em&gt; group as I do not plan to change these from within Home Assistant. Like for other devices in Home Assistant associated automations and events are shown on the detail view as well.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/reolink-setup-3.jpeg&quot; alt=&quot;Camera detail view in Home Assistant&quot; title=&quot;Camera detail view in Home Assistant&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Camera detail view in Home Assistant&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I usually only keep the important switches, the camera stream(s), the motion detection sensors and a small number of configuration settings enabled.&lt;/p&gt;
&lt;p&gt;By clicking on the round image, you should be able to access the camera’s video stream. Typically, you will first see a snapshot while the camera stream is loading in the background. Once available, the snapshot image will be replaced by the playing video.&lt;/p&gt;
&lt;h3 id=&quot;step-5%3A-viewing-your-reolink-camera-in-lovelace-dashboard&quot;&gt;Step 5: Viewing Your Reolink Camera in Lovelace Dashboard&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#step-5%3A-viewing-your-reolink-camera-in-lovelace-dashboard&quot; aria-labelledby=&quot;step-5%3A-viewing-your-reolink-camera-in-lovelace-dashboard&quot;&gt;#&lt;/a&gt;&lt;p&gt;Once the Reolink camera is added to Home Assistant and you have checked the sensors and the camera stream in the device detail view, you can easily view the live video feed from your dashboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Go to your &lt;strong&gt;Lovelace dashboard&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on the three dots in the upper-right corner and choose &lt;strong&gt;Edit Dashboard&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select &lt;strong&gt;Add Card&lt;/strong&gt; and then choose the &lt;strong&gt;&lt;a href=&quot;https://www.home-assistant.io/dashboards/picture-entity/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Picture Entity&lt;/a&gt;&lt;/strong&gt; card.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Entity&lt;/strong&gt;: Select the newly added Reolink camera (e.g., &lt;code&gt;camera.reolink_front_door&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show Stream&lt;/strong&gt;: Toggle this option to display the live stream from the camera.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/reolink-setup-4.png&quot; alt=&quot;Add camera entity to your Lovelace dashboard&quot; title=&quot;Add camera entity to your Lovelace dashboard&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Add camera entity to your Lovelace dashboard&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you manage your dashboards in YAML files the picture entity card can be added via:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; picture&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;entity
&lt;span class=&quot;token key atrule&quot;&gt;show_state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;show_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;camera_view&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto
&lt;span class=&quot;token key atrule&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; camera.carport_fluent&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once added, you should now see the live feed from your Reolink camera directly on your dashboard.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/reolink-cameras-in-home-assistant/#conclusion&quot; aria-labelledby=&quot;conclusion&quot;&gt;#&lt;/a&gt;&lt;p&gt;Integrating Reolink cameras with Home Assistant using the official Reolink integration is powerful and quite simple. With live streaming, motion detection automation and the ability to record clips, you can easily enhance the security of your smart home. Overall I’m super happy with the new setup and I don’t regret switching from Arlo to Reolink.&lt;/p&gt;
&lt;p&gt;This step-by-step guide covers everything from setting up the camera to viewing the camera stream in the Home Assistant. In the &lt;a href=&quot;https://markus-haack.com/automate-reolink-camera-notifications/&quot;&gt;next post&lt;/a&gt;, I’ll share some of my automations and show you how to add the missing geo-fence functionality.&lt;/p&gt;
&lt;p&gt;Happy home automation!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>ZigBee Temperature and Humidity Sensors: A Comparison</title>
    <link href="https://markus-haack.com/zigbee-temperature-sensors/"/>
    <updated>2024-08-28T00:00:00Z</updated>
    <id>https://markus-haack.com/zigbee-temperature-sensors/</id>
    <content type="html">&lt;p&gt;Smart homes are becoming increasingly popular, and temperature and humidity sensors play a crucial role in automating home environments. Over the last years I have added &amp;gt; 10 in and around the house. Every room got one, the attic as well and one was added into the fridge. Of course there is a sensor outside in the garden and a second for to measure the pool water temp.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/temperature-sensors.jpeg&quot; alt=&quot;ZigBee temperature and humidity sensors&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;ZigBee sensors are great for this use case. They are known for their low power consumption and reliable communication. They can run on battery power for several months, even years.&lt;/p&gt;
&lt;p&gt;Most of the sensors we have installed are Aqara Temperature and Humidity sensors of the first generation. So far, these have been very reliable and most of them still are. But there are also a few, 3 so far, that have had failures recently and have repeatedly lost the connection. Only a re-paring helped, which is quite annoying. Different batteries, different position, nothing really brings any improvement. That’s why I’ve been looking around for alternatives.&lt;/p&gt;
&lt;p&gt;In this blog post, we’ll compare five popular ZigBee temperature and humidity sensors to help you make an informed choice. We’ll evaluate each sensor based on accuracy, battery life, size, ease of integration with Home Assistant, and more.&lt;/p&gt;
&lt;h2 id=&quot;overview-of-the-test-sensors&quot;&gt;Overview of the Test Sensors&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#overview-of-the-test-sensors&quot; aria-labelledby=&quot;overview-of-the-test-sensors&quot;&gt;#&lt;/a&gt;&lt;p&gt;Before diving into the comparison, let’s briefly introduce the five ZigBee sensors that we will be reviewing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://sonoff.tech/product/gateway-and-sensors/snzb-02p/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SONOFF Zigbee Temperature and Humidity Sensor&lt;/a&gt;&lt;/strong&gt;: A budget-friendly option known for its compact design and easy installation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.aqara.com/en/product/temperature-humidity-sensor/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Aqara Temperature and Humidity Sensor&lt;/a&gt; (Old Version)&lt;/strong&gt;: An established sensor that has been a favorite in the smart home community for its reliability and ease of use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.aqara.com/en/temperature-and-humidity-sensor-t1&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Aqara Temperature and Humidity Sensor T1&lt;/a&gt; (New Version)&lt;/strong&gt;: The upgraded version of the Aqara sensor, offering improved features and compatibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://nous.technology/product/smart-humidity-temperature-sensor-nous-e5-zigbee.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NOUS E5 ZigBee Smart Temperature and Humidity Sensor&lt;/a&gt;&lt;/strong&gt;: A lesser-known brand that promises high accuracy and seamless integration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.domadoo.fr/en/devices/5998-owon-zigbee-connected-outdoor-temperature-sensor-with-probe.html?domid=14&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OWON Zigbee with Remote Temperature Probe on Cable&lt;/a&gt;&lt;/strong&gt;: A unique sensor with a remote probe, designed for more specialized applications where precise placement is necessary.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I have selected sensors that are relatively easy to buy in Europe. They should also be easy to get in America and elsewhere. Therefore I avoided any Tuya sensor and clone. They are often only available via direct import from China and the sensors specs are often not clear.&lt;/p&gt;
&lt;h2 id=&quot;comparison-of-zigbee-temperature-and-humidity-sensors&quot;&gt;Comparison of ZigBee Temperature and Humidity Sensors&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#comparison-of-zigbee-temperature-and-humidity-sensors&quot; aria-labelledby=&quot;comparison-of-zigbee-temperature-and-humidity-sensors&quot;&gt;#&lt;/a&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;SONOFF Zigbee&lt;/th&gt;
&lt;th&gt;Aqara&lt;br&gt;(Old Version)&lt;/th&gt;
&lt;th&gt;Aqara T1&lt;br&gt;(New Version)&lt;/th&gt;
&lt;th&gt;NOUS E5&lt;/th&gt;
&lt;th&gt;OWON with Remote Probe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SNZB-02P&lt;/td&gt;
&lt;td&gt;WSDCGQ11LM&lt;/td&gt;
&lt;td&gt;TH-S02D&lt;/td&gt;
&lt;td&gt;TS0201&lt;/td&gt;
&lt;td&gt;THS-317-ET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Temperature Range&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-10℃ ~ +60°C&lt;/td&gt;
&lt;td&gt;-20℃ ~ +50°C&lt;/td&gt;
&lt;td&gt;-20℃ ~ +50°C&lt;/td&gt;
&lt;td&gt;-20℃ ~ +60℃&lt;/td&gt;
&lt;td&gt;-40°C ~ +200°C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Temperature Accuracy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;±0.2°C&lt;/td&gt;
&lt;td&gt;±0.3°C&lt;/td&gt;
&lt;td&gt;±0.3°C&lt;/td&gt;
&lt;td&gt;±0.3°C,&lt;/td&gt;
&lt;td&gt;±0.5°C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Humidity Range&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5%-95%RH&lt;/td&gt;
&lt;td&gt;0 – 100% RH&lt;/td&gt;
&lt;td&gt;0 – 100% RH&lt;/td&gt;
&lt;td&gt;0 – 100% RH&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Humidity Accuracy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;±2% RH&lt;/td&gt;
&lt;td&gt;±3% RH&lt;/td&gt;
&lt;td&gt;±3% RH&lt;/td&gt;
&lt;td&gt;±5% RH&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Atmospheric Pressure Range&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;30 kPa – 110 kPa&lt;/td&gt;
&lt;td&gt;30 kPa – 110 kPa&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Atmospheric Pressure Accuracy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;±0.12 kPa&lt;/td&gt;
&lt;td&gt;±0.12 kPa&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Battery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CR2477&lt;/td&gt;
&lt;td&gt;CR2032&lt;/td&gt;
&lt;td&gt;CR2032&lt;/td&gt;
&lt;td&gt;CR2*1&lt;/td&gt;
&lt;td&gt;2x AAA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Battery Life&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 2 years&lt;/td&gt;
&lt;td&gt;Up to 2 years&lt;/td&gt;
&lt;td&gt;Up to 2 years&lt;/td&gt;
&lt;td&gt;Up to 5 years&lt;/td&gt;
&lt;td&gt;Up to 1.5 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;45 x 45 x 17.7 mm&lt;/td&gt;
&lt;td&gt;36 x 36 x 9 mm&lt;/td&gt;
&lt;td&gt;36 x 36 x 9 mm&lt;/td&gt;
&lt;td&gt;40 x 40 x 23 mm&lt;/td&gt;
&lt;td&gt;62 x 52 x 15 mm (sensor case)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Special Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Compact design, magnetic mounting&lt;/td&gt;
&lt;td&gt;Compact design, high reliability&lt;/td&gt;
&lt;td&gt;Improved range and battery life&lt;/td&gt;
&lt;td&gt;High accuracy claims&lt;/td&gt;
&lt;td&gt;Remote probe capability, wide temperature rand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$15-$20&lt;/td&gt;
&lt;td&gt;$15-$20&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;$15-$20&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;comparison-of-temperature-%26-humidity-readings&quot;&gt;Comparison of Temperature &amp;amp; Humidity Readings&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#comparison-of-temperature-%26-humidity-readings&quot; aria-labelledby=&quot;comparison-of-temperature-%26-humidity-readings&quot;&gt;#&lt;/a&gt;&lt;p&gt;To understand how each sensor performs in real-world scenarios, I tested the sensors under similar conditions and recorded their readings. All the sensors were on my desk right next to each other for a week.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/temp-compare-diagram.png&quot; alt=&quot;Compare temperature measurements&quot; title=&quot;Compare temperature measurements of the 5 sensors&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Compare temperature measurements of the 5 sensors&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/humidity-compare-diagram.png&quot; alt=&quot;Compare humidity measurements&quot; title=&quot;Compare humidity sensors readings&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Compare humidity sensors readings&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;From the data recorded in the last 24 hours:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;SONOFF Zigbee&lt;/strong&gt; sensor shows slight deviations but remains close to the average readings, indicating good accuracy. It reacts more quickly to temperature changes then the Aqara sensors.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Aqara (Old Version)&lt;/strong&gt; and new &lt;strong&gt;Aqara T1&lt;/strong&gt; getting almost identical measurements for temperature, while the humidity values of the old version are minimal higher than the T1 and average.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;NOUS E5&lt;/strong&gt; seams to be calibrated very good, the temperature and humidity readings are always in the middle.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;OWON Remote Probe&lt;/strong&gt; sensor provides readings slightly higher then the other sensors and it reacts more quickly to temperature changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;integrating-with-home-assistant&quot;&gt;Integrating with Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#integrating-with-home-assistant&quot; aria-labelledby=&quot;integrating-with-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;The sensors can be used with many ZigBee bridges and hubs, including Philips Hue, Amazon Echo and other ZigBee 3.0 compatible hubs. However, the most common usage is together with a smart home system like Home Assistant. Here’s how you can integrate these sensors into Home Assistant using &lt;a href=&quot;https://www.home-assistant.io/integrations/zha/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zigbee Home Automation&lt;/a&gt; (ZHA), the native integration for ZigBee devices into HA.&lt;/p&gt;
&lt;p&gt;I can confirm that all the tested sensors work with ZHA without any issue. I am certain that other Home Assistant ZigBee integrations like &lt;a href=&quot;https://www.zigbee2mqtt.io/guide/usage/integrations/home_assistant.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ZigBee2MQTT&lt;/a&gt; and &lt;a href=&quot;https://www.home-assistant.io/integrations/deconz/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;deCONZ&lt;/a&gt; will work just as well. Ensure the sensor works with the particular integration by checking the &lt;a href=&quot;https://zigbee.blakadder.com/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ZigBee Device Compatibility Repository&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-zha-(zigbee-home-automation)&quot;&gt;Using ZHA (Zigbee Home Automation)&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#using-zha-(zigbee-home-automation)&quot; aria-labelledby=&quot;using-zha-(zigbee-home-automation)&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/zha/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ZHA&lt;/a&gt; is a native integration for ZigBee devices within Home Assistant, providing a straightforward way to connect and manage your sensors. It works with a variety of Zigbee coordinator radios and can easily be configured via the Home Assistant UI.&lt;/p&gt;
&lt;p&gt;Here’s a quick guide to get started:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hardware Requirements&lt;/strong&gt;: You’ll need a ZigBee coordinator, such as the &lt;a href=&quot;https://www.home-assistant.io/connectzbt1/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Connect ZBT-1&lt;/a&gt;, &lt;a href=&quot;https://itead.cc/product/zigbee-3-0-usb-dongle/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ITead SONOFF Zigbee 3.0 USB Dongle)&lt;/a&gt; or &lt;a href=&quot;https://phoscon.de/conbee2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ConBee II USB adapter&lt;/a&gt;, to act as a bridge between your ZigBee devices and Home Assistant.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setting Up ZHA&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;Integrations&lt;/strong&gt; section in Home Assistant.&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Add Integration&lt;/strong&gt; and search for &lt;strong&gt;Zigbee Home Automation (ZHA)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Follow the prompts to select your ZigBee coordinator and configure the integration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pairing Sensors&lt;/strong&gt;: Once ZHA is set up, you can pair your sensors by putting them into pairing mode (usually by pressing a button on the sensor). The sensors should automatically appear in Home Assistant under ZHA devices.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configuring Entities&lt;/strong&gt;: After pairing, each sensor will be listed as an entity in Home Assistant. You can rename, group, and set automations for these sensors to fit your specific needs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;alternative-integration-options&quot;&gt;Alternative Integration Options&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#alternative-integration-options&quot; aria-labelledby=&quot;alternative-integration-options&quot;&gt;#&lt;/a&gt;&lt;p&gt;ZigBee2MQTT &amp;amp; deCONZ are other popular and powerful options to integrate ZigBee devices and sensors into Home Assistant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ZigBee2MQTT&lt;/strong&gt; allows for a broader range of devices and more advanced configuration options. It works by bridging ZigBee devices to MQTT, a lightweight messaging protocol used by Home Assistant. A full setup requires an MQTT broker like Mosquitto running standalone or as &lt;a href=&quot;https://github.com/home-assistant/addons/tree/master/mosquitto&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Add-on&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another alternative to ZHA is &lt;strong&gt;deCONZ&lt;/strong&gt;, powerful integration for ZigBee devices, particularly popular for its detailed device visualization and management. Is has specially requirements on the supported ZigBee gateways and only works with selected radios like the &lt;a href=&quot;https://phoscon.de/en/raspbee2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;RaspBee II&lt;/a&gt;, &lt;a href=&quot;https://phoscon.de/en/conbee2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ConBee II&lt;/a&gt;, or &lt;a href=&quot;https://phoscon.de/en/conbee3&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ConBee III&lt;/a&gt; . I used this before I switched to ZHA and it worked super reliable. The setup requires a few more components. The &lt;a href=&quot;https://github.com/home-assistant/addons/tree/master/deconz&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;deCONZ&lt;/a&gt; can also be easily installed as a home assistant add-on via the Add-on store. New devices and sensors are usually paired in the deCONZ software, which then exposes them to the Home Assistant.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/zigbee-temperature-sensors/#summary&quot; aria-labelledby=&quot;summary&quot;&gt;#&lt;/a&gt;&lt;p&gt;When choosing a ZigBee temperature and humidity sensor, consider what features are most important for your specific needs. For indoor usage all for sensors are good choices.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;For General Home Use&lt;/strong&gt;: The SONOFF Zigbee Temperature and Humidity Sensor offers a good balance between price, accuracy, making it an excellent choice for most users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For “I want an established Brand”&lt;/strong&gt;: Both Aqara sensors are reliable choices, go with the newer T1 version.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For Specialized Applications&lt;/strong&gt;: The OWON Zigbee Remote Temperature Probe is ideal for applications needing precise placement and monitoring of specific areas, such as greenhouses or attics.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No matter your choice, integrating these sensors with Home Assistant will allow you to automate and monitor your home environment efficiently, making your smart home smarter and more comfortable.&lt;/p&gt;
&lt;p&gt;Happy automating!&lt;/p&gt;
&lt;p&gt;Hero image: AI generated with Microsoft Copilot.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The digital notepad box - a DIY e-ink project</title>
    <link href="https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/"/>
    <updated>2024-05-19T00:00:00Z</updated>
    <id>https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/</id>
    <content type="html">&lt;p&gt;E-Ink displays are known for their low power consumption and crisp visibility. They have gained popularity in various DIY projects. After seeing the first threads on the Home Assistant community forum, I got interested in building an e-paper project with ESPHome. I wanted to build a project where I always have the display in view and it shows me all kinds of useful information. I also wanted it to fit on my desk. That’s how the idea of the digital notepad was born.&lt;/p&gt;
&lt;p&gt;And as is often the case with DIY projects, I ordered the electronic components without knowing exactly what I wanted to do. I ordered 2 different sizes of e-ink displays. The 2.9&amp;quot; used in this project and a 10.3&amp;quot; version from Waveshare. I had a suitable ESP32 chip board lying around.&lt;/p&gt;
&lt;p&gt;After that it took another six months until I had an idea and could start working on it.&lt;/p&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use Cases&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#use-cases&quot; aria-labelledby=&quot;use-cases&quot;&gt;#&lt;/a&gt;&lt;p&gt;There are a huge number of use cases for e-ink displays in hobby projects. Here are a few examples that are easy to implement.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Home Automation Dashboard:&lt;/strong&gt;.&lt;br&gt;
Turn your home into a smart haven by creating a centralised dashboard that displays real-time data from your smart home devices. Monitor temperature, humidity and other sensor readings at a glance. This often uses old tablets or iPads, which are mounted on the wall. If you have one to spare and can find a good place for it in the house, this is a great idea.&lt;br&gt;
But you can also go a size smaller, which is less conspicuous, but also less interactive, with an e-ink display.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weather station&lt;/strong&gt;&lt;br&gt;
Build a sleek weather station that retrieves and displays weather information. With ESPHome you can easily integrate APIs for weather updates and provide a convenient visual representation on the e-paper display.&lt;br&gt;
There are some very cool examples of this in the Home Assistant community, such as the &lt;a href=&quot;https://community.home-assistant.io/t/use-esphome-with-e-ink-displays-to-blend-in-with-your-home-decor/435428&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Weatherman Dashboard&lt;/a&gt; project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Task scheduler:&lt;/strong&gt;.&lt;br&gt;
Using the e-paper display as a task scheduler to display your daily agenda, reminders or to-do lists is another idea. With ESPHome’s flexibility, you can customise the display to suit your specific scheduling needs.&lt;br&gt;
Originally I wanted to build something like this. But I couldn’t connect ESPHome to my work account &amp;amp; calendar.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;my-home-automation-dashboard&quot;&gt;My Home Automation Dashboard&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#my-home-automation-dashboard&quot; aria-labelledby=&quot;my-home-automation-dashboard&quot;&gt;#&lt;/a&gt;&lt;p&gt;In this guide we’ll explore how to build an e-ink based display using ESPHome for a Home Assistant home automation dashboard. The information shown on the display can be chosen freely. It can be customised to suit your home. In my case, it’s - quite classically - the temperature inside and outside the house, &lt;a href=&quot;https://markus-haack.com/solar-update-2023/&quot;&gt;power consumption and generation of our solar system&lt;/a&gt;, key data from the car and the water temperature and status of the pool.&lt;/p&gt;
&lt;p&gt;The full source code of the project can be found in my &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/esphome/home-display.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant config repo&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#hardware&quot; aria-labelledby=&quot;hardware&quot;&gt;#&lt;/a&gt;&lt;p&gt;You only need 3 electronic components for the project.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.waveshare.com/2.9inch-e-ink.htm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Waveshare 2.9inch e-ink panel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ESP32 based microcontroller - &lt;a href=&quot;https://www.aliexpress.com/w/wholesale-esp32.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;generic&lt;/a&gt; or &lt;a href=&quot;https://www.waveshare.com/product/displays/e-paper/driver-boards/e-paper-esp32-driver-board.htm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Waveshare Universal e-Paper Raw Panel Driver Board&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;USB power supply&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depending on which board you choose, you may be able to do without any soldering at all.&lt;/p&gt;
&lt;p&gt;But for a nice display you also need a case. Depending on the size of the display, you can use a picture frame or something smaller. It all depends on the application. With a 3D printer you have almost endless possibilities to print an attractive case or holder. Since I wanted to use a small 2.9-inch display for my project and I don’t have a 3D printer, I had to find another solution.&lt;/p&gt;
&lt;p&gt;For my notepad box display I built a wooden case. The display should always be visible. Due to its size it could not be too far away. It took me 2 tries to find the right design. The final version is made of plywood with the display at the bottom. The ESP32 microcontroller is located behind the display. The USB port is on the back.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/digital-notepad-box-1.jpeg&quot; alt=&quot;Photo of my digital notepad box&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you get the Waveshare Universal e-Paper Driver Board, no soldering is required. The controller board can be connected directly to the e-paper display. Waveshare and others also sell pre-assembled plug and play solutions. Connect the controller board with power via USB and you are ready to go.&lt;/p&gt;
&lt;h2 id=&quot;software&quot;&gt;Software&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#software&quot; aria-labelledby=&quot;software&quot;&gt;#&lt;/a&gt;&lt;p&gt;The software stack is quite simple. All you need is &lt;a href=&quot;https://esphome.io/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome&lt;/a&gt; and &lt;a href=&quot;https://www.home-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt;. The ESPHome code runs on the microcontroller that drives the display. Home Assistant is responsible for providing all the data you want to display. ESPHome can integrate a number of different sensors. However, I prefer to get the data from the Home Assistant as it is already available and integrated.&lt;/p&gt;
&lt;p&gt;The full configuration for my display is available on &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/esphome/home-display.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt;. To use the ESPHome configuration, simply copy it to the ESHome Config folder. You can then customise it for your own display and sensors. Change the display layout, data sources and update intervals according to the requirements of your project.&lt;/p&gt;
&lt;p&gt;The ESPHome configuration for my e-ink display project consists of 4 sections. Let me explain the most important parts.&lt;/p&gt;
&lt;h3 id=&quot;1.-setup-the-hardware&quot;&gt;1. Setup the hardware&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#1.-setup-the-hardware&quot; aria-labelledby=&quot;1.-setup-the-hardware&quot;&gt;#&lt;/a&gt;&lt;p&gt;First you have to tell ESPHome which board you are using, how the Wifi connection is and to which pins the display is connected.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;substitutions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;gpio_spi_clk_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO25
 &lt;span class=&quot;token key atrule&quot;&gt;gpio_spi_mosi_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO26
 &lt;span class=&quot;token key atrule&quot;&gt;gpio_cs_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO32
 &lt;span class=&quot;token key atrule&quot;&gt;gpio_busy_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO33
 &lt;span class=&quot;token key atrule&quot;&gt;gpio_reset_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO27
 &lt;span class=&quot;token key atrule&quot;&gt;gpio_dc_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO0

&lt;span class=&quot;token key atrule&quot;&gt;esphome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; homedisplay
 &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ESP32
 &lt;span class=&quot;token key atrule&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; lolin_d32_pro

&lt;span class=&quot;token key atrule&quot;&gt;spi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;clk_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $gpio_spi_clk_pin
 &lt;span class=&quot;token key atrule&quot;&gt;mosi_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $gpio_spi_mosi_pin
 &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; epaper_display

&lt;span class=&quot;token key atrule&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; waveshare_epaper
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; epaper
   &lt;span class=&quot;token key atrule&quot;&gt;cs_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $gpio_cs_pin
   &lt;span class=&quot;token key atrule&quot;&gt;busy_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $gpio_busy_pin
   &lt;span class=&quot;token key atrule&quot;&gt;reset_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $gpio_reset_pin
   &lt;span class=&quot;token key atrule&quot;&gt;dc_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $gpio_dc_pin
   &lt;span class=&quot;token key atrule&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2.90in
   &lt;span class=&quot;token key atrule&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 90°
   &lt;span class=&quot;token comment&quot;&gt;# 296x128 pixels&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;update_interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3600s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two components are needed to configure the display. The &lt;code&gt;display&lt;/code&gt; &lt;a href=&quot;https://esphome.io/components/display/#display-rendering-engine&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;component&lt;/a&gt; is a kind of container component for all ESPHome display integrations. It must be used for any type of display such as &lt;a href=&quot;https://esphome.io/components/display/ili9xxx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;TFT displays&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/display/ssd1306&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OLED displays&lt;/a&gt; or e-paper displays. It can also be used to drive pixel-based and &lt;a href=&quot;https://esphome.io/components/display/max7219&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;7-segment displays&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For an e-ink display such as the Waveshare E-Paper modules, the platform type &lt;code&gt;waveshare_epaper&lt;/code&gt; must be specified and the &lt;code&gt;spi&lt;/code&gt; component is also required to specify the pins to which the display is connected. The &lt;code&gt;model&lt;/code&gt; parameter specifies the display type used &lt;a href=&quot;https://esphome.io/components/display/waveshare_epaper&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome documentation&lt;/a&gt; has a full guide to the list of display variants.&lt;/p&gt;
&lt;p&gt;If you connect additional sensors such as a temperature sensor or an ambient light sensor, additional ping and sensor setup is required.&lt;/p&gt;
&lt;h3 id=&quot;2.-get-the-data&quot;&gt;2. Get the data&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#2.-get-the-data&quot; aria-labelledby=&quot;2.-get-the-data&quot;&gt;#&lt;/a&gt;&lt;p&gt;In my case I get all the data shown on the display from Home Assistant. Hence this is pretty much the only sensor I configured. I also use the &lt;code&gt;time&lt;/code&gt; integration to get the current time and to update the display.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; homeassistant
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sensor.garden_temperature
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_temp
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;binary_sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; homeassistant
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.pool_pump_state
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pool_pump_state
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;text_sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; homeassistant
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sensor.car_mercedes_l_jm227e_range_electric
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; car_charging_endtime
   &lt;span class=&quot;token key atrule&quot;&gt;attribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; endofchargetime&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3.-display-helpers&quot;&gt;3. Display helpers&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#3.-display-helpers&quot; aria-labelledby=&quot;3.-display-helpers&quot;&gt;#&lt;/a&gt;&lt;p&gt;To display icons and diagrams as well as text, we need a few helpers. Each icon that is used &lt;a href=&quot;https://esphome.io/components/display/#images&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;must be defined once&lt;/a&gt;. You can use your own images or pictograms or icons of the &lt;a href=&quot;https://pictogrammers.com/library/mdi/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Material Design Icon library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I also use the &lt;a href=&quot;https://esphome.io/components/display/#graph-component&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;graph component&lt;/a&gt; to display sensor values as a line graph for example for the indoor and outdoor temperature.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mdi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;thermometer
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; icon_thermometer
   &lt;span class=&quot;token key atrule&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 30x30
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mdi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;thermometer
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; icon_thermometer_small
   &lt;span class=&quot;token key atrule&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 22x22
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mdi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;car
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; car
   &lt;span class=&quot;token key atrule&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 22x22
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_temp_graph
   &lt;span class=&quot;token key atrule&quot;&gt;sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_temp
   &lt;span class=&quot;token key atrule&quot;&gt;line_thickness&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 12h
   &lt;span class=&quot;token key atrule&quot;&gt;x_grid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10min
   &lt;span class=&quot;token key atrule&quot;&gt;y_grid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20.0&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;120&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;max_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;min_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;-10&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;fonts/GoogleSans-Bold.ttf&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clock_font
   &lt;span class=&quot;token key atrule&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;glyphs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;fonts/GoogleSans-Bold.ttf&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; font_regular_16
   &lt;span class=&quot;token key atrule&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;glyphs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;&amp;amp;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;@&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;%&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;+&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;-&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;_&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;°&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;0&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;4&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;5&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;6&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;7&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;9&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;A&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;B&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;C&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;D&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;E&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;F&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;G&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;H&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;I&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;J&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;K&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;L&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;M&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;N&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;O&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;P&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;Q&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;R&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;S&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;T&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;U&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;V&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;W&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;X&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;Y&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;Z&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;b&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;c&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;d&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;e&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;f&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;g&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;h&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;i&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;j&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;k&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;l&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;m&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;o&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;p&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;q&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;r&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;s&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;t&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;u&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;v&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;w&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;x&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;y&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;z&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;ß&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token string&quot;&gt;&#39;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://esphome.io/components/display/fonts.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Font files&lt;/a&gt; must be saved in a folder next to the config file. ESPHome will load and bundle the configured glyphs during the build process of the config. Any OpenType or TrueType font should work. As the glyphs are rendered as bitmaps, you will need to define multiple fonts, one for each font &amp;amp; size combination. To keep the memory footprint small, it is recommended to list only the characters that are actually used.&lt;/p&gt;
&lt;h3 id=&quot;4.-main-display-logic&quot;&gt;4. Main display logic&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#4.-main-display-logic&quot; aria-labelledby=&quot;4.-main-display-logic&quot;&gt;#&lt;/a&gt;&lt;p&gt;The main rendering and data display logic is also configured via the &lt;code&gt;display&lt;/code&gt; component. All rendering is done through a large &lt;code&gt;lambda&lt;/code&gt; configuration option. This allows you to draw on the display, write text, render images, QR codes or diagrams.&lt;/p&gt;
&lt;p&gt;It is possible to draw directly on the display or to use so-called &lt;a href=&quot;https://esphome.io/components/display/#display-pages&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Display Pages&lt;/a&gt;. These allow you to configure multiple virtual screens that you can switch between. I’m using display pages to group and separate the different values I want to show on the e-pager display. I currently use 4 display pages. Every minute I switch to a new display page and update the display. Lets have a look at one of them:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;pages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; page1
   &lt;span class=&quot;token key atrule&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
    int x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y;
    ESP_LOGI(&quot;display&quot;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &quot;Updating Page 1&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; energy&quot;);

    // block headline
    it.image(2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(icon_flash));
    it.print(24&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_20)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &quot;Energie&quot;);
    it.line(102&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;184&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 20);

    // Time &amp;amp; Temp box
    it.strftime(242&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(clock_font)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_CENTER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%H:%M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(sntp_time).now());
    it.strftime(242&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;70&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_20)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_CENTER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%d.%m.%y&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(sntp_time).now());
    if (id(garden_temp).has_state()) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      it.image(195&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(icon_thermometer));
      it.printf(230&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_20)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%2.1f°C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(garden_temp).state);
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    it.line(188&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;188&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 126);

    if (id(energy_today).has_state()) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      it.image(6&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(icon_sunny));
      it.printf(32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;49&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_16)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%.1fkWh&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(energy_today).state);
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    if (id(storage_level).has_state()) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      x = 115&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y = 34;
      if (id(storage_level).state &amp;lt;= 33) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        it.image(x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(battery_low));
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; else if (id(storage_level).state &amp;lt;= 66) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        it.image(x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(battery_medium));
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; else &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        it.image(x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(battery_high));
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      it.printf(x+20&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y+15&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_16)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%2.0f%%&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(storage_level).state);
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    if (id(consumption_energy).has_state()) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      it.image(6&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;62&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(home_lightning_bolt_outline));
      it.printf(32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;79&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_16)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%.1fkWh&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(consumption_energy).state);
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    if (id(exported_energy).has_state()) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      it.image(6&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;106&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(transmission_tower_export));
      it.printf(32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_16)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%.1fkWh&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(exported_energy).state);
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    if (id(imported_energy).has_state()) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      it.image(100&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;106&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(transmission_tower_import));
      it.printf(123&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(font_regular_16)&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TextAlign&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;BASELINE_LEFT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%.1fkWh&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(imported_energy).state);
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wanted my display to always show the current time and the outside temperature. To ensure a consistent display and smooth transitions, all display pages have a heading and a line that visually separates the information. You will find these lines of code on all four virtual screens. The rest is individual for each screen, depending on the information displayed.&lt;/p&gt;
&lt;p&gt;To render on the display you essentially need three variables. The x &amp;amp; y coordinates of the display’s coordinate system and the information - text, images, graphics - to be displayed. The top left corner of the display is always the origin of the pixel coordinate system. It has the coordinates x=0, y=0.&lt;/p&gt;
&lt;p&gt;In the example above, I am rendering 3 lines of text and icons. They show the combined data of &lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/&quot;&gt;our solar system&lt;/a&gt; and the electricity produced &amp;amp; consumed. The other display pages work in a similar way.&lt;/p&gt;
&lt;h2 id=&quot;adapting-to-your-needs&quot;&gt;Adapting to your needs&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#adapting-to-your-needs&quot; aria-labelledby=&quot;adapting-to-your-needs&quot;&gt;#&lt;/a&gt;&lt;p&gt;Before you start tweaking the rendering, I suggest you familiarise yourself with the ESPHome &lt;a href=&quot;https://esphome.io/components/display/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;display component documentation&lt;/a&gt;. It contains all the basic information explaining how to draw and render on the display.&lt;/p&gt;
&lt;p&gt;Configuring ESPHome for your specific e-paper display model may require some trial and error. Especially positioning all the data elements &amp;amp; icons can take some time. I started by drawing some sketches on paper to find out how I wanted the different data points to be displayed. Play with different font and icon sizes depending on the resolution of your display. Depending on the type of data, you can use icons or graphs. Weather conditions, for example, work well with icons. For a long-term history of a sensor, such as temperature or network traffic, line graphs work well.&lt;/p&gt;
&lt;p&gt;When you are finished, use the ESPHome add-on in Home Assistant to flash the configured firmware to your ESP32 driver card.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#summary&quot; aria-labelledby=&quot;summary&quot;&gt;#&lt;/a&gt;&lt;p&gt;Building my e-ink display with ESPHome has been a fun and rewarding experience. Whether it’s for real-time weather updates, monitoring home energy consumption or display traffic information, I love how versatile the combo ESPHome &amp;amp; Home Assistant is for such kind of projects. Seeing the notepad box with the display on my desk every day brings me a sense of satisfaction and keeps me connected to my home automation system. I often think about what else might be useful to display. And, of course, what I could build with the second e-ink display that is still on the shelf.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-digital-notepad-box-a-diy-e-ink-project/#references&quot; aria-labelledby=&quot;references&quot;&gt;#&lt;/a&gt;&lt;p&gt;Here are some other repos that I referenced from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Madelena/esphome-weatherman-dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://github.com/Madelena/esphome-weatherman-dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/DeastinY/esphome-waveshare-e-paper-dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://github.com/DeastinY/esphome-waveshare-e-paper-dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fredrike/esphome-nodes&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://github.com/fredrike/esphome-nodes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Harnessing the Power of the Sun: A Year in Review</title>
    <link href="https://markus-haack.com/solar-update-2023/"/>
    <updated>2024-03-26T00:00:00Z</updated>
    <id>https://markus-haack.com/solar-update-2023/</id>
    <content type="html">&lt;p&gt;In this annual update I give an update on the 2023 performance of our photovoltaic system and comparing it with previous years’ data. This is a follow up to last years post series about the installation and first energy yield numbers (&lt;a href=&quot;https://markus-haack.com/our-own-electricity-1/&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/&quot;&gt;3&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;2023-solar-energy-production-overview&quot;&gt;2023 Solar Energy Production Overview&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/solar-update-2023/#2023-solar-energy-production-overview&quot; aria-labelledby=&quot;2023-solar-energy-production-overview&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Total solar energy produced in 2023: 8.292 kWh&lt;/li&gt;
&lt;li&gt;Average monthly solar energy production: 691 kWh&lt;/li&gt;
&lt;li&gt;Month with highest production: May with 1.330 kWh&lt;/li&gt;
&lt;li&gt;Lowest monthly production: 93 kWh in December&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-energy-2023.png&quot; alt=&quot;screenshot monthly energy production 2023&quot; title=&quot;Diagram 1: monthly energy production 2023&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Diagram 1: monthly energy production 2023&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;5.180 kWh of the produced energy was consumed by ourselves which is a ration of 62%. The surplus of 3.112 kWh was fed back into the grid.&lt;/p&gt;
&lt;p&gt;On the consumption side we used a total of 10.312 kWh of electricity. Most of this was for the heat pump (2.865 kWh), second highest consumer is our car which we charged with 2.095 kWh. 50% (5.180 kWh) of the consumed electricity produced by our selfs and the second 50% we got it from the power grid.&lt;/p&gt;
&lt;h2 id=&quot;comparing-with-previous-years&quot;&gt;Comparing with Previous Years&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/solar-update-2023/#comparing-with-previous-years&quot; aria-labelledby=&quot;comparing-with-previous-years&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2023 vs. 2022:&lt;/strong&gt; Total energy production in 2023 was significantly lower than the year before. Overall solar energy production decreased 9% from 9.098 kWh to 8.292 kWh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While the summer months (May, June, July and August) were about the same, we produced significantly more electricity in spring 2022, than in the same period in 2023. March and April were very rainy months in our region and the sky was often very cloudy.&lt;/p&gt;
&lt;p&gt;November 2023 we got already some snow very early, for the area we live. As a result, next to nothing was produced for two weeks.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-energy-2020-2024-year.png&quot; alt=&quot;year to year comparison of energy production&quot; title=&quot;Diagram 2: year to year comparison of energy production&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Diagram 2: year to year comparison of energy production&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Overall, 2023 was still the 2nd best year for our solar system.&lt;/p&gt;
&lt;p&gt;By harnessing the power of the sun we have reduced our carbon footprint and already saved more then 12 tones of CO2 emissions. Especially in the summer month were are mostly energy independent and don’t consume many kWh from the power grid.&lt;/p&gt;
&lt;p&gt;I’m curious to see what the numbers will look like at the end of the year for 2024. So far the first 3 months are looking very good. January was actually the best January so far.&lt;/p&gt;
&lt;p&gt;Hero image &lt;a href=&quot;https://unsplash.com/de/@tanerardali&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;taner ardalı&lt;/a&gt; from &lt;a href=&quot;https://unsplash.com/de/fotos/blaues-kabelgebundenes-elektronisches-gerat-auf-weiss-gestrichener-wand-montiert-vc7e5M6HXzA&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Home Assistant 2024</title>
    <link href="https://markus-haack.com/jama-villa-2024/"/>
    <updated>2024-01-24T00:00:00Z</updated>
    <id>https://markus-haack.com/jama-villa-2024/</id>
    <content type="html">&lt;p&gt;Since sharing our initial insights into the Home Assistant setup at &lt;a href=&quot;https://markus-haack.com/jama-villa/&quot;&gt;my first post about our Home Assistant setup&lt;/a&gt;, a lot has transformed. It’s time for an update. This article will walk you through the changes, replacements of devices and integrations, additions of new elements, and the tried-and-true components that have proven to be reliable.&lt;/p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#architecture&quot; aria-labelledby=&quot;architecture&quot;&gt;#&lt;/a&gt;&lt;p&gt;Since I’m an IT guy I have to draw an architecture diagram 😃 Ok I hope this is not only for me and also helps you to understand the entire setup better.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/jama-villa-2024.jpg&quot; alt=&quot;JaMa Villa 2024&quot; title=&quot;JaMa Villa 2024 setup&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;JaMa Villa 2024 setup&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-foundation&quot;&gt;The foundation&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#the-foundation&quot; aria-labelledby=&quot;the-foundation&quot;&gt;#&lt;/a&gt;&lt;p&gt;The &lt;a href=&quot;https://www.hardkernel.com/shop/odroid-n2-with-4gbyte-ram/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Odroid N2&lt;/a&gt; system has proven to be an extremely reliable and stable system. It is still in use today as it was 4 years ago. The second Raspberry Pi is gone as I consolidated the ZigBee router to the Odroid N2 as well.&lt;br&gt;
While the overall network setup hasn’t undergone significant changes, our home remains an Ubiquiti stronghold. The Unifi USG has been swapped out for the &lt;a href=&quot;https://ui.com/eu/en/cloud-gateways/dream-machine&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unifi UDM Pro&lt;/a&gt;, a powerhouse that may be deemed a bit oversized for a standard household. Today I my preferable choice would be the more streamlined &lt;a href=&quot;https://ui.com/eu/en/cloud-gateways/express&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unifi Express&lt;/a&gt; box.&lt;/p&gt;
&lt;p&gt;The main gear and integrations driving our home are:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device / Solution&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://sonoff.tech/product/gateway-and-sensors/sonoff-zigbee-3-0-usb-dongle-plus-p/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ZHA using SonOff ZigBee 3.0 USB dongle&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;This is the main ZigBee Hub with over 40 devices connected. All Ikea &amp;amp; Hue light bulbs and LED stripes are connected to the ZHA network. All the window &amp;amp; door contact sensors, plus all indoor and outdoor temperature sensors are on ZigBee as well.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.eq-3.com/start.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic CCU3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Used to control all Homematic devices, mainly security devices like motion sensors or sirens. Plus a few switch relays for DIN rail mounting.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.rademacher.de/en/smart-home/smart-home-systeme&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Rademacher DuoFern&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Wireless controller for our electric roller shutters. In fact, the roller shutters were the first smart devices in our house, long before Home Assistant took over the control.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://unifi-network.ui.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Ubiquiti UniFi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Our home network is operated by UniFi wired and wireless devices. Router, Switches, Wireless Access Points, … all UniFi. Only the DSL Modem is from DrayTek.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.tapo.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tapo&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://www.hikvision.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hikvision&lt;/a&gt; camera’s&lt;/td&gt;
&lt;td&gt;The new camera setup uses 100% local cameras without any cloud subscription. These replace the Arlo cameras.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://tasmota.github.io/docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://www.shelly.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shelly&lt;/a&gt; devices&lt;/td&gt;
&lt;td&gt;A bunch of Wifi switches &amp;amp; sockets. The Shelly devices are permanently installed, whereas the SonOff devices, primarily WiFi sockets, find extensive use for powering various Christmas lights both inside and outside the house during the holiday season.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The major changes, compared to our setup &lt;a href=&quot;https://markus-haack.com/jama-villa/&quot;&gt;from 2020&lt;/a&gt;, are:&lt;/p&gt;
&lt;h3 id=&quot;cameras&quot;&gt;Cameras&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#cameras&quot; aria-labelledby=&quot;cameras&quot;&gt;#&lt;/a&gt;&lt;p&gt;The Arlo cameras go replaced with local network cameras. While &lt;a href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/&quot;&gt;Arlo cameras work well with Home Assistant&lt;/a&gt; I decided to ditch them for two main reasons: a) Arlo’s shift to a subscription-based model for both new and existing customers, and b) the frequent release of new models without adequate support for older ones.&lt;/p&gt;
&lt;p&gt;Our new setup uses network cameras that operate entirely locally and record to either on device SD cards, our NAS storage or a combination of both. At the front door, we’ve installed a high-resolution 4K &lt;a href=&quot;https://www.hikvision.com/en/products/IP-Products/Network-Cameras/Pro-Series-EasyIP-/ds-2cd2086g2-i-u/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hikvision DS-2CD2086G2-IU&lt;/a&gt; connected and powered via Ethernet. Around the house, we’ve deployed &lt;a href=&quot;https://www.tapo.com/en/product/smart-camera/tapo-c320ws/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;4 Tapo C320WS&lt;/a&gt; cameras connected via WiFi, recording in 2K. Despite their affordable price point of approximately 50 Euros, the Tapo cameras deliver impressive image quality, especially in low-light conditions.&lt;/p&gt;
&lt;p&gt;For recording all camera streams, I’m currently experimenting with various solutions. Initially, I tried &lt;a href=&quot;https://frigate.video/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Frigate&lt;/a&gt;, an open-source and powerful option that requires extensive configuration for optimal performance. However, I encountered challenges with object detection, experiencing numerous false positives and missed animal detections. Currently, I’m testing &lt;a href=&quot;https://www.scrypted.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Scrypted&lt;/a&gt; as a home video integration platform in conjunction with HomeKit Secure Video. So far, it has proven to work quite effectively.&lt;/p&gt;
&lt;h3 id=&quot;wireless-devices&quot;&gt;Wireless devices&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#wireless-devices&quot; aria-labelledby=&quot;wireless-devices&quot;&gt;#&lt;/a&gt;&lt;p&gt;The major change in out smart home setup in the last 4 years was the switch of the ZigBee network. I transitioned from using Deconz with the Conbee II stick to ZHA, utilizing the SonOff ZigBee 3.0 USB dongle. This switch was motivated by the desire to eliminate the Raspberry Pi sidecar, prompting the relocation of two wireless integrations to the main Home Assistant device.&lt;/p&gt;
&lt;p&gt;The migration included moving the Rademacher DuoFern stick and custom integration seamlessly. However, for ZigBee, I decided to explore ZHA based on a friend’s recommendation. Building a new ZigBee network and re-pairing around 25 devices took approximately 4 hours.&lt;/p&gt;
&lt;p&gt;Over time, the smart home ecosystem expanded with the addition of various sensors, sockets, and devices. Notable additions include the &lt;a href=&quot;https://zigbee.blakadder.com/Lidl_HG06338.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SilverCrest Power Strip&lt;/a&gt; with 3 AC sockets and 4 USB outlets, strategically placed on my home office desk.&lt;/p&gt;
&lt;p&gt;One noticeable shift was the decline in reliability of Homematic devices, particularly the contact sensors on windows and doors. known for their .&lt;/p&gt;
&lt;p&gt;The biggest loser on the wireless device side is Homematic. For some reason out of sudden we had many issues with the contact sensors on the windows and doors. These all got replaced with &lt;a href=&quot;https://www.aqara.com/eu/product/door-and-window-sensor/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Aqara Door and Window Sensors&lt;/a&gt;. These little beasts are great have a discreet design. They can be hidden in almost any (German) window or door. In 2 years I only had to replace a battery from time to time.&lt;/p&gt;
&lt;p&gt;The wireless device landscape also saw the integration of more Shelly switches, such as the &lt;a href=&quot;https://www.shelly.com/en-de/products/product-overview/shelly-plus-2-pm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shelly Plus 2PM&lt;/a&gt; with a custom 3D printed DIN rail mount, replacing Homematic DIN rail switching actuators.&lt;/p&gt;
&lt;p&gt;Next to the Shelly switches we got a bunch of additional &lt;a href=&quot;https://tasmota.github.io/docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt; devices as well. Since the SonOff S20 are not really state of the art any more I switched to &lt;a href=&quot;https://nous.technology/product/nous-smart-wi-fi-socket-a1.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Nous A1&lt;/a&gt; which have a nice and compact design and are available pre-flashed with Tasmota firmware.&lt;/p&gt;
&lt;h3 id=&quot;other-hardware-changes&quot;&gt;Other hardware changes&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#other-hardware-changes&quot; aria-labelledby=&quot;other-hardware-changes&quot;&gt;#&lt;/a&gt;&lt;p&gt;In addition to the main changes mentioned earlier, here are a few other noteworthy hardware updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Replaced the old QNAP NAS (T-219P) with a more powerful Synology DS220+ NAS featuring an Intel CPU. This upgrade enables running Docker containers on the NAS like Frigate NVP or Scrypted (see above).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Upgraded our lawn mower robot to a Gardena Sileno life 750, replacing the old Landroid. The new robot can be seamlessly connected to Home Assistant and operates with significantly reduced noise levels during mowing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Added a fun project to the mix – the &lt;a href=&quot;https://markus-haack.com/mario-bros-clock/&quot;&gt;Mario Clock&lt;/a&gt; has found a place in our house, bringing a touch of whimsy to our smart home setup.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;home-assistant&quot;&gt;Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#home-assistant&quot; aria-labelledby=&quot;home-assistant&quot;&gt;#&lt;/a&gt;&lt;h3 id=&quot;add-ons&quot;&gt;Add-ons&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#add-ons&quot; aria-labelledby=&quot;add-ons&quot;&gt;#&lt;/a&gt;&lt;p&gt;The add-on list remains largely unchanged from &lt;a href=&quot;https://markus-haack.com/jama-villa/#hass.io-add-ons&quot;&gt;2020&lt;/a&gt;. Similar to many others, the Configurator add-on has been finally substituted with the &lt;a href=&quot;https://github.com/hassio-addons/addon-vscode&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Visual Studio Code add-on&lt;/a&gt;. Additionally, the Grafana and Influx DB add-ons have been disabled and removed since they were not frequently used any more. While Grafana dashboards are aesthetically pleasing, no one looked at them, hence there is little value in maintaining them.&lt;/p&gt;
&lt;h3 id=&quot;integrations-%26-custom-components&quot;&gt;Integrations &amp;amp; Custom Components&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#integrations-%26-custom-components&quot; aria-labelledby=&quot;integrations-%26-custom-components&quot;&gt;#&lt;/a&gt;&lt;p&gt;Like any other Home Assistant setup, we have many integrations. And with every update or new toys I get the list gets longer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/adguard/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AdGuard Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gluap/pyduofern-hacs&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Duofern control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/esphome&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/forecast_solar&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Forecast.Solar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/generic&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Generic Camera&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hacs.xyz/docs/configuration/basic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HACS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/hassio&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Supervisor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/ios&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/homekit&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HomeKit Bridge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/components/homematic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/hydrawise&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hunter Hydrawise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/components/mqtt/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MQTT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ReneNulschDE/mbapi2020&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MercedesME 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/HomeAssistant-Mods/home-assistant-miele&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Miele&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/mobile_app/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mobile App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/neato&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Neato Botvac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/open_meteo&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Open-Meteo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/season&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Season&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/shelly&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shelly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://community.home-assistant.io/t/add-on-scrypted-homekit-secure-video/398487&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Skrypted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/binsentsu/home-assistant-solaredge-modbus&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge Modbus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/solaredge&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/sonos&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Sonos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/speedtestdotnet&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Speedtest.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/sun&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Sun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/synology_dsm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Synology DSM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/systemmonitor&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;System Monitor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/tasmota&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/components/unifi/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;UniFi Network&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/version&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/wled&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;WLED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mampfes/hacs_waste_collection_schedule&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Waste Collection Schedule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/workday&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Workday&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/zha/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Zigbee Home Automation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;dashboards&quot;&gt;Dashboards&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#dashboards&quot; aria-labelledby=&quot;dashboards&quot;&gt;#&lt;/a&gt;&lt;p&gt;We primarily still configure Lovelace UI in YAML mode for our Home Assistant configuration. You can find our main Lovelace config file &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/ui-lovelace.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;here&lt;/a&gt;, and the folder defining the views is &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/tree/master/config/lovelace&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve recently cleaned up the configuration, reducing items on the main dashboards and moving more technical entities to an admin dashboard. I’m particularly excited about the new title card, which has replaced many of the basic entity cards. However, I’ve noticed that standard UI cards are not as powerful as Mushroom cards, for example. I’m hoping for some improvements in the entire Home Assistant user interface this year. This can be the final trigger to maybe start rethinking the dashboards and build new using the UI editor instead of YAML files.&lt;/p&gt;
&lt;h3 id=&quot;backup&quot;&gt;Backup&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#backup&quot; aria-labelledby=&quot;backup&quot;&gt;#&lt;/a&gt;&lt;p&gt;With the introduction of native support for mounted network storage in Home Assistant version 2023.6, I have reconfigured the backup flow. Now, the weekly backups of the entire Home Assistant setup are stored on our Synology NAS. I have detailed the setup in an &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/&quot;&gt;entire post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summary-%26-outlook&quot;&gt;Summary &amp;amp; Outlook&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa-2024/#summary-%26-outlook&quot; aria-labelledby=&quot;summary-%26-outlook&quot;&gt;#&lt;/a&gt;&lt;p&gt;This blog post provides an updated overview of our current 2024 Home Assistant setup, showcasing shifts to ZHA for ZigBee, and integration of Shelly and Tasmota devices. Changes in hardware include a Synology NAS upgrade and a new lawn mower robot.&lt;/p&gt;
&lt;p&gt;For this year I plan to move more and more configuration to the UI and get right of the YAML files. I’m looking forward to UI improvements and potential dashboard changes in the future to migrate all my dashboards.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Build your first website with Edge Delivery and document based authoring</title>
    <link href="https://markus-haack.com/build-your-first-website-with-edge-delivery-and-document-based-authoring/"/>
    <updated>2023-11-14T00:00:00Z</updated>
    <id>https://markus-haack.com/build-your-first-website-with-edge-delivery-and-document-based-authoring/</id>
    <content type="html">&lt;p&gt;For zero to go-live of your first website in 30 min. Is that possible? In this developer step-by-step walkthrough I show you how to build and launch your first size using Adobe’s new Edge Delivery Service.&lt;/p&gt;
&lt;p&gt;Here’s what you will learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up the GitHub Repo from our boilerplate project&lt;/li&gt;
&lt;li&gt;Setting up a document library and connecting it to the project&lt;/li&gt;
&lt;li&gt;Publish the first content changes&lt;/li&gt;
&lt;li&gt;Run a local development environment &amp;amp; CLI&lt;/li&gt;
&lt;li&gt;Change the site styling&lt;/li&gt;
&lt;li&gt;Build a first simple custom block&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YpLctMRmJdA&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=YpLctMRmJdA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Interested in trying it out on your own? Here is our &lt;a href=&quot;https://www.aem.live/developer/tutorial&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The talk was given on November 6, 2023 at Adobe Developers Live: Content and Commerce conference.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>AdaptTo 2023: Unveiling the Future of Adobe AEM Sites</title>
    <link href="https://markus-haack.com/adaptto-2023-franklin/"/>
    <updated>2023-10-05T00:00:00Z</updated>
    <id>https://markus-haack.com/adaptto-2023-franklin/</id>
    <content type="html">&lt;p&gt;This year’s AdaptTo 2023 conference in Berlin brought an exciting twist to my speaking journey. Unlike previous years, where AdaptTo conference was only virtually, I had the incredible opportunity to hold a keynote presentation in person.&lt;/p&gt;
&lt;p&gt;During this &lt;a href=&quot;https://adapt.to/2023/schedule/edge-delivery-services-getting-started-with-document-based-authoring&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;keynote&lt;/a&gt;, I gave an introduction into the innovation of Adobe AEM Sites – Document-based Authoring combined with Edge Delivery Services, also known as Project Franklin. This next evolution of AEM Sites introduces a fresh authoring and developer experience, promising to create blazingly fast websites.&lt;/p&gt;
&lt;p&gt;The presentation covered the architecture of the Edge Delivery Services stack and the core concepts of document-based authoring. It’s packed with practical details to help developers kickstart their projects and quickly launch their own websites.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Hlqowj7WrmM&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=Hlqowj7WrmM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you missed the event or want to revisit the presentation, you can &lt;a href=&quot;https://adapt.to/2023/presentations/adaptto-2023-edge-delivery-services-getting-started-with-document-based-authoring-markus-haack.pdf&quot;&gt;download it now&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Home Assistant backup to Synology NAS</title>
    <link href="https://markus-haack.com/home-assistant-backup-to-synology-nas/"/>
    <updated>2023-07-17T00:00:00Z</updated>
    <id>https://markus-haack.com/home-assistant-backup-to-synology-nas/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: With the first two 2025 releases, there were some new features for Home Assistant backups. I have summarised these in &lt;a href=&quot;https://markus-haack.com/home-assistant-backup-2025/&quot;&gt;a new article&lt;/a&gt;. However, the NAS backup steps in this article are of course still valid.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Okay, I don’t think I need to go into detail about why having a solid backup strategy for your &lt;a href=&quot;https://www.home-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt; solution is important. So I’ll write about how to set it up. I’ve wanted to set up the backup of my Home Assistant installation properly for months. Now that I’ve finally tackled this task, I thought I’d summarize the steps I took.&lt;/p&gt;
&lt;p&gt;I’m &lt;a href=&quot;https://markus-haack.com/jama-villa/&quot;&gt;running Home Assistant on an Odroid N2&lt;/a&gt;, and I’m well aware that frequent writes can shorten the lifespan of memory cards. In general a higher quality SD card typically will last longer and can hold multiple years. We also have to consider the entire system, not only Home Assistant itself, but also all add-on like MQTT broker etc. Although this concern primarily applies to SD cards, I wanted to be cautious with the Odroid N2 and its MMC memory.&lt;/p&gt;
&lt;p&gt;Until now, I’ve been creating weekly backups directly on the local disk of my Home Assistant server. Later, I manually transferred these backups to our NAS system at more or less regular intervals. Unfortunately, the memory card has filled up multiple times, forcing me to delete older backups.&lt;/p&gt;
&lt;p&gt;I previously experimented with syncing backups on Dropbox and Google Drive, but wasn’t really happy with these options either.&lt;/p&gt;
&lt;p&gt;However, with the release of Home Assistant 2023.6, native support for mounted network storage was introduced. This feature allows connecting Home Assistant to Windows/Samba (CIFS) or Network File Share (NFS) network shares within the local network. These network shares can serve as media folders or external backup storage.&lt;/p&gt;
&lt;p&gt;Now, it’s time for me to give it a try and establish a robust backup strategy.&lt;/p&gt;
&lt;h2 id=&quot;home-assistant-backup-to-network-storage&quot;&gt;Home Assistant backup to network storage&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#home-assistant-backup-to-network-storage&quot; aria-labelledby=&quot;home-assistant-backup-to-network-storage&quot;&gt;#&lt;/a&gt;&lt;p&gt;In my case I connected Home Assistant to our &lt;a href=&quot;https://www.synology.com/en-us/dsm/solution/what-is-nas/for-home&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Synology NAS&lt;/a&gt;. The setup steps are pretty well &lt;a href=&quot;https://www.home-assistant.io/common-tasks/os/#network-storage&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;documented&lt;/a&gt; for the Home Assistant part, however the NAS or file server part is always a little more tricky and different. I’ll explain how to configure a network share hosted on the Synology NAS as the main backup location for Home Assistant. This will work with other NAS systems (like QNAP) or file servers as well, but might require some different configuration steps to enable the file share.&lt;/p&gt;
&lt;h2 id=&quot;setup-step-by-step&quot;&gt;Setup step by step&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#setup-step-by-step&quot; aria-labelledby=&quot;setup-step-by-step&quot;&gt;#&lt;/a&gt;&lt;p&gt;With the following step by step you should have no problem to set up your own Home Assistant backup to a network share.&lt;/p&gt;
&lt;h3 id=&quot;1.-create-a-shared-folder&quot;&gt;1. Create a Shared Folder&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#1.-create-a-shared-folder&quot; aria-labelledby=&quot;1.-create-a-shared-folder&quot;&gt;#&lt;/a&gt;&lt;p&gt;In order to get started, you must create a shared network folder on your NAS. Go to &lt;em&gt;Control Panel&lt;/em&gt; &amp;gt; &lt;em&gt;Shared Folder&lt;/em&gt; and click &lt;em&gt;Create&lt;/em&gt;. Enter a name for the shared folder (such as “Home Assistant Backup”) and select a location. The location options depend on the NAS setup. I only have &lt;em&gt;Volume 1&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-1.png&quot; alt=&quot;screenshot 1&quot; title=&quot;Screenshot 1: configuration of Synology Shared Folder&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 1: configuration of Synology Shared Folder&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Do not enable the recycle bin feature. Click &lt;em&gt;Next&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;On the next screen leave the option at &lt;em&gt;skip&lt;/em&gt;. Don’t configure any encryption for the backup folder. You can choose to secure you backup with a password later in Home Assistant.&lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Next&lt;/em&gt;. Don’t change anything on the advanced setups and click &lt;em&gt;Next&lt;/em&gt; again.&lt;/p&gt;
&lt;p&gt;Review the settings and click &lt;em&gt;Next&lt;/em&gt; to create the shared folder.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-2.png&quot; alt=&quot;screenshot 2&quot; title=&quot;Screenshot 2: configuration of Synology Shared Folder&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 2: configuration of Synology Shared Folder&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Review the access permissions and click &lt;em&gt;Apply&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2.-enable-nfs-access&quot;&gt;2. Enable NFS access&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#2.-enable-nfs-access&quot; aria-labelledby=&quot;2.-enable-nfs-access&quot;&gt;#&lt;/a&gt;&lt;p&gt;In this step we will enable NFS file services on the Synology NAS. This step is only needed if not done before during the initial NAS system setup.&lt;/p&gt;
&lt;p&gt;In your Synology UI go to &lt;em&gt;Control Panel&lt;/em&gt; &amp;gt; &lt;em&gt;File Services&lt;/em&gt; and select the &lt;em&gt;NFS&lt;/em&gt; tab. If not already checked select the &lt;em&gt;Enable NFS Service&lt;/em&gt; checkbox. The screen should look like this:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-5.png&quot; alt=&quot;screenshot 3&quot; title=&quot;Screenshot 3: enable NFS services on Synology NAS&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 3: enable NFS services on Synology NAS&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3 id=&quot;3.-make-the-shared-folder-accessible-via-nfs&quot;&gt;3. Make the shared folder accessible via NFS&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#3.-make-the-shared-folder-accessible-via-nfs&quot; aria-labelledby=&quot;3.-make-the-shared-folder-accessible-via-nfs&quot;&gt;#&lt;/a&gt;&lt;p&gt;In the next step we need to enable NFS access and allow Home Assistant to use the newly created network share. I decided to proceed with NFS. CIFS shares are supported by Home Assistant as well, however I could not get it working with my Synology setup.&lt;/p&gt;
&lt;p&gt;Select the newly created shared folder from the &lt;em&gt;Shared Folder&lt;/em&gt; list in the Control Panel and click &lt;em&gt;Edit&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In the dialog navigate to the &lt;em&gt;NFS Permissions&lt;/em&gt; tab and click &lt;em&gt;Create&lt;/em&gt;. In the dialog enter the hostname or IP address of your Home Assistant machine.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-3.png&quot; alt=&quot;screenshot 4&quot; title=&quot;Screenshot 4: set up NFS Permissions for shared folder&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 4: set up NFS Permissions for shared folder&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Save&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Copy and note down the mount path at the bottom of the &lt;em&gt;NFS Permissions&lt;/em&gt; tab.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-4.png&quot; alt=&quot;screenshot 5&quot; title=&quot;Screenshot 5: set up NFS Permissions for shared folder&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 5: set up NFS Permissions for shared folder&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Save&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;4.-connect-the-shared-folder-in-home-assistant&quot;&gt;4. Connect the shared folder in Home Assistant&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#4.-connect-the-shared-folder-in-home-assistant&quot; aria-labelledby=&quot;4.-connect-the-shared-folder-in-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;Let’s switch to Home Assistant and connect to the recently created shared folder on your Synology NAS.&lt;/p&gt;
&lt;p&gt;Go to &lt;em&gt;Settings&lt;/em&gt; &amp;gt; &lt;em&gt;System&lt;/em&gt; &amp;gt; &lt;em&gt;Storage&lt;/em&gt; in Home Assistant. In the Network storage section you can see all connected network shares. This list might be empty if you have never connected to network storage before.&lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Add Network Storage&lt;/em&gt; button.&lt;/p&gt;
&lt;p&gt;In the dialog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;enter a name, like “HomeAssistantBackup”&lt;/li&gt;
&lt;li&gt;select &lt;em&gt;Backup&lt;/em&gt; from the &lt;em&gt;Usage&lt;/em&gt; category&lt;/li&gt;
&lt;li&gt;enter the NAS server hostname or IP address&lt;/li&gt;
&lt;li&gt;select &lt;em&gt;Network File Share (NFS)&lt;/em&gt; as the protocol&lt;/li&gt;
&lt;li&gt;in the remote share field enter the NFS share mount path you copied in step 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-6.png&quot; alt=&quot;screenshot 6&quot; title=&quot;Screenshot 6: Home Assistant Network Storage configuration&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 6: Home Assistant Network Storage configuration&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Click &lt;em&gt;Connect&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Home Assistant will not bind the network share and if everything was correct you should see the new network storage in the list of the &lt;em&gt;Network storage&lt;/em&gt; section.&lt;/p&gt;
&lt;p&gt;If you try to use the CIFS protocol you need to provide a username &amp;amp; password plus the CIFS share name to connect.&lt;/p&gt;
&lt;h3 id=&quot;5.-change-the-default-backup-location&quot;&gt;5. Change the default backup location&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#5.-change-the-default-backup-location&quot; aria-labelledby=&quot;5.-change-the-default-backup-location&quot;&gt;#&lt;/a&gt;&lt;p&gt;Once the network share is set up, we only need to change the backup location where Home Assistant stores backups.&lt;/p&gt;
&lt;p&gt;Go to &lt;em&gt;Settings&lt;/em&gt; &amp;gt; &lt;em&gt;System&lt;/em&gt; &amp;gt; &lt;em&gt;Backups&lt;/em&gt; in the Home Assistant UI. In the right top corner menu select &lt;em&gt;Change default backup location&lt;/em&gt;. In the pop-up dialog select the new backup location and click &lt;em&gt;Save&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ha-backup-screenshot-7.png&quot; alt=&quot;screenshot 7&quot; title=&quot;Screenshot 7: Home Assistant Network change default backup location&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot 7: Home Assistant Network change default backup location&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;That’s it, the next time a backup is created it will be stored on the NAS network share.&lt;/p&gt;
&lt;h3 id=&quot;6.-list-the-backups&quot;&gt;6. List the backups&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#6.-list-the-backups&quot; aria-labelledby=&quot;6.-list-the-backups&quot;&gt;#&lt;/a&gt;&lt;p&gt;There are three options to list the backups stored on our NAS:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In Home Assistant, navigate to &lt;em&gt;Settings&lt;/em&gt; &amp;gt; &lt;em&gt;System&lt;/em&gt; &amp;gt; &lt;em&gt;Backups&lt;/em&gt;. You will get a list of all backups. In the &lt;em&gt;Location&lt;/em&gt; column you can see where these are stored.&lt;/li&gt;
&lt;li&gt;Via Home Assistant CLI run &lt;code&gt;ha backup list&lt;/code&gt; to see all the backups. The result also contains a &lt;em&gt;location&lt;/em&gt; attribute for each backup. Also note the &lt;em&gt;slug&lt;/em&gt; attribute. This maps to the NAS file share filename.&lt;/li&gt;
&lt;li&gt;On our NAS we can simply check the shared folder contents. Each backup is stored as one .tar file. The filename maps to the &lt;em&gt;slug&lt;/em&gt; attribute in Home Assistant.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;backups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;compressed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;addons&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; a0d7b954_ssh
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; core_mosquitto
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; a0d7b954_adguard
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; core_samba
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; a0d7b954_vscode
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 15ef4d2f_esphome
    &lt;span class=&quot;token key atrule&quot;&gt;folders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; share
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; addons/local
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ssl
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; media
    &lt;span class=&quot;token key atrule&quot;&gt;homeassistant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;2023-07-16T11:23:21.072157+00:00&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; BackupShareNAS
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Backup_16&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;07&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;216.67&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; c528818e
   &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; full
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;compressed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;addons&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; a0d7b954_ssh
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; core_mosquitto
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; a0d7b954_adguard
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; core_samba
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; a0d7b954_vscode
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 15ef4d2f_esphome
    &lt;span class=&quot;token key atrule&quot;&gt;folders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; share
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; addons/local
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ssl
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; media
    &lt;span class=&quot;token key atrule&quot;&gt;homeassistant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;2023-07-08T18:00:00.304439+00:00&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null important&quot;&gt;null&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Backup_08&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;07&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;224.17&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 39b2baaf
   &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; full
&lt;span class=&quot;token key atrule&quot;&gt;days_until_stale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-backup-to-synology-nas/#conclusion&quot; aria-labelledby=&quot;conclusion&quot;&gt;#&lt;/a&gt;&lt;p&gt;Regularly backing up your Home Assistant configuration is crucial to protect your smart home deployment. While Home Assistant has offered that capability for years to backup to a local disk/memory card then transfer it to external storage afterwards - it is not very reliable. By utilizing a network share as backup storage you add an extra layer of security to your backup strategy. With these steps in place, you can rest assured that your Home Assistant configuration is safe and easily recoverable in case of unforeseen events.&lt;/p&gt;
&lt;p&gt;Happy automating!&lt;/p&gt;
&lt;p&gt;Hero image from &lt;a href=&quot;https://unsplash.com/@filmlav?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText&quot;&gt;Fernando Lavin&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/de/fotos/RxHCRDO0psE?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>New Talk: Developing a good editor experience with Microsoft 365/Google Workspace</title>
    <link href="https://markus-haack.com/aem-document-based-authoring/"/>
    <updated>2023-06-08T00:00:00Z</updated>
    <id>https://markus-haack.com/aem-document-based-authoring/</id>
    <content type="html">&lt;p&gt;In May Adobe hosted the Adobe Developers Live virtual conference for Adobe Experience Manager. The conference focused on building next generation composable services, universal editor, edge delivery and generative AI.&lt;/p&gt;
&lt;p&gt;I gave a presentation about the new AEM document-based authoring and how to build an effective editor experience with Microsoft 365/Google Workspace.&lt;/p&gt;
&lt;video controls=&quot;&quot; width=&quot;100%&quot; poster=&quot;https://images-tv.adobe.com/mpcv3/71a43592-0569-4d31-b735-0bf279223ba3/86fa4476-3518-40fb-8323-c06bff92652d/664e969baf6e435a8ea7755e00ad6047_1685156700-1920x1080.jpg&quot;&gt;
  &lt;source src=&quot;https://images-tv.adobe.com/mpcv3/7469/8ee3fb7a-4086-4f06-9898-0799c7aeea69_1685140943.854x480at800_h264.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;/video&gt;
&lt;p&gt;Abstract:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A crucial aspect of every project is the structure of the content documents. An author should be able to navigate through the documents intuitively without any problems. We will provide guidelines and tips and tricks on how to structure your content documents. When structuring a document for Experience Manager, it is essential for authors who will contribute content to make it simple and intuitive. This session will explain how to structure content documents in a content first approach letting authors drive the content structure. We will explain best practices, how and when to use sections and blocks and show common project pitfalls to avoid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you want to follow up, feel free to reach out or continue the conversation at the &lt;a href=&quot;https://adobe.ly/40YBTnO&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adobe Experience League Forum&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Need for Speed: Why Website Performance Matters</title>
    <link href="https://markus-haack.com/need-for-speed-why-website-performance-matters/"/>
    <updated>2023-05-09T00:00:00Z</updated>
    <id>https://markus-haack.com/need-for-speed-why-website-performance-matters/</id>
    <content type="html">&lt;p&gt;As I have run this website for a few years now and have been doing &lt;a href=&quot;https://markus-haack.com/website-history/&quot;&gt;some re-designs and new stack changes&lt;/a&gt;, I have always thought about how the website performs. Over time, I became more and more interested in topics related to performance optimization. Core Web Vitals and that website performance are important for site users, especially people who come here via mobile. Incidentally, this is also a topic I deal with intensively at &lt;a href=&quot;https://www.hlx.live/home&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;work&lt;/a&gt; 😃&lt;/p&gt;
&lt;p&gt;This page now regularly scores &lt;a href=&quot;https://pagespeed.web.dev/analysis/https-markus-haack-com/qdsgvo539g?hl=EN&amp;amp;form_factor=mobile&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;4x 100 in Google Lighthouse&lt;/a&gt; tests and is in the &lt;a href=&quot;https://www.11ty.dev/speedlify/markus-haack-com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;top 100&lt;/a&gt; of the &lt;a href=&quot;https://www.11ty.dev/speedlify/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eleventy Leaderboards&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;flex&quot;&gt;
&lt;is-land on:visible=&quot;&quot; class=&quot;mx-auto&quot;&gt;&lt;a href=&quot;https://www.11ty.dev/speedlify/markus-haack-com/&quot; aria-label=&quot;Speedlify lighthous score&quot; class=&quot;mx-auto no-underline text-mountain-300 hover:text-mountain-600&quot;&gt;&lt;speedlify-score speedlify-url=&quot;https://www.11ty.dev/speedlify&quot; hash=&quot;39ea9d4a&quot; score=&quot;&quot; weight=&quot;&quot;&gt;&lt;/speedlify-score&gt;&lt;/a&gt;&lt;template data-island=&quot;once&quot;&gt;&lt;script src=&quot;https://markus-haack.com/assets/js/speedlify-score.js&quot;&gt;&lt;/script&gt;&lt;/template&gt;&lt;/is-land&gt;
&lt;/div&gt;
&lt;p&gt;So, what is &lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/overview/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Google Lighthouse&lt;/a&gt; and why are Core Web Vitals important?&lt;/p&gt;
&lt;p&gt;Google Lighthouse is a tool that helps website owners and developers to improve the performance, accessibility, best practices, and search engine optimization (SEO) of their web pages. It measures several aspects of a website’s performance, such as page load speed, interactivity, accessibility, and more. Lighthouse generates a report based on these measurements and highlights areas of improvement and suggesting optimizations. The report provides a score out of 100 for each of the categories mentioned above - 4x 100 is the top score.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/vitals/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Core Web Vitals&lt;/a&gt; are a set of metrics also introduced by Google to measure and quantify the user experience of web pages based on real-world performance data. The data is collected by users of Google Chrome browser. There are three key metrics that make up the Core Web Vitals:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Largest Contentful Paint (LCP): This metric measures the time it takes for the largest content element of a web page to become visible in the viewport. A good LCP score means that users can see the main content of the page quickly.&lt;/li&gt;
&lt;li&gt;First Input Delay (FID): This measures the time it takes for a user to interact with a web page, such as clicking a link or button. A good FID score means that users can interact with the page without delay.&lt;/li&gt;
&lt;li&gt;Cumulative Layout Shift (CLS): Means the amount of unexpected layout shifts that occur during the loading process. A low CLS score means that the page layout remains stable while the page loads. Layout shifts are considered as distracting for the users.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Google considers these Core Web Vitals to be critical indicators of a web page’s user experience and uses them as a ranking factor in search results. Good Core Web Vitals therefore also lead to more users on your site from Google.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-goolge-pagespeed.png&quot; alt=&quot;Google PageSpeed Insights Report&quot; title=&quot;Google PageSpeed Insights Report for markus-haack.com tested on May 9th 2023&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Google PageSpeed Insights Report for markus-haack.com tested on May 9th 2023&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So how can websites be optimized for speed and a good Lighthouse? Here are some things you can do to improve website performance:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Optimize images: Images are often the largest files on a website and can slow down the page load time. Using modern image formats like WEBP or AVIF compress images significantly better than JPEG, reduce their file size and improve page speed.&lt;/li&gt;
&lt;li&gt;Optimize page size: Only load resources which are required and remove unnecessary JavaScript and CSS. If possible, load stuff incrementally to not block the browser from initial page rendering.&lt;/li&gt;
&lt;li&gt;Minimize HTTP requests: Each request made to the server to fetch a file, such as CSS or JavaScript, adds to page load time. Minimizing the number of requests can help reduce load time.&lt;/li&gt;
&lt;li&gt;Use HTTP/2: this can significantly improve the website’s page speed because it allows browsers to simultaneously process multiple requests over the same connection&lt;/li&gt;
&lt;li&gt;Use a Content Delivery Network (CDN): A CDN stores website files on servers located around the world, which allows users to access the website from the nearest server, reducing the load time. It works great with static site generators and web site builders like &lt;a href=&quot;https://www.11ty.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eleventy&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use browser caching: Browser caching allows website files to be stored on the user’s device, which can significantly reduce load time for returning visitors.&lt;/li&gt;
&lt;li&gt;Optimize code: Clean and efficient code can reduce load time and improve website performance.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once you test your own site’s Lighthouse you will get detailed recommendations on how to improve the site’s performance.&lt;/p&gt;
&lt;p&gt;As a result, websites that load quickly, provide a seamless user experience, and achieve high Lighthouse scores are not only beneficial for the user but also for the environment. Fast and size optimized websites are good for the environment because they consume less energy, which reduces their carbon footprint.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href=&quot;https://www.websitecarbon.com/website/markus-haack-com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Website Carbon Calculator&lt;/a&gt; only 0.03g of CO2 is produced every time someone visits my site. This is cleaner than 96% of web pages tested. (Tested on May 9th 2023).&lt;/p&gt;
&lt;is-land on:visible=&quot;&quot;&gt;
&lt;div id=&quot;wcb&quot; class=&quot;carbonbadge&quot;&gt;&lt;/div&gt;
&lt;template data-island=&quot;once&quot;&gt;&lt;script src=&quot;https://unpkg.com/website-carbon-badges@1.1.3/b.min.js&quot; defer=&quot;&quot;&gt;&lt;/script&gt;&lt;/template&gt;&lt;/is-land&gt;
&lt;p&gt;Why is that: when a website takes longer to load, it requires more data to be transferred, which in turn requires more energy from data centers and servers. This increased energy consumption contributes to carbon emissions and harms the environment.&lt;/p&gt;
&lt;p&gt;I have optimized this site to be as small as possible and haven’t sent unnecessary bytes to my users. I recently joined the &lt;a href=&quot;https://250kb.club/markus-haack-com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;250kb Club&lt;/a&gt;, &lt;a href=&quot;https://512kb.club&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;512KB Club&lt;/a&gt; and the &lt;a href=&quot;https://1mb.club&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;1mb.club&lt;/a&gt; to show how meaningful this topic is to me. In the future I will try to keep the site footprint under 250kB of data.&lt;/p&gt;
&lt;p&gt;Source hero image: &lt;a href=&quot;https://unsplash.com/de/fotos/-Vqn2WrfxTQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Marc Sendra Martorell&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building a Mario Bros. Clock</title>
    <link href="https://markus-haack.com/mario-bros-clock/"/>
    <updated>2023-04-15T00:00:00Z</updated>
    <id>https://markus-haack.com/mario-bros-clock/</id>
    <content type="html">&lt;p&gt;I’m a big fan of Nintendo and Super Mario since I was a teenager. One of my most played games in my life was probably Super Mario Land on the Gameboy. I still own it and an original Gameboy as well. I recently found a &lt;a href=&quot;https://www.hackster.io/jnthas/mario-bros-clock-4a0436&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;cool DIY project&lt;/a&gt; - &lt;a href=&quot;https://clockwise.page/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Clockwise&lt;/a&gt; Mario Bros. Clock by Jonathas Barbosa. I absolutely had to rebuild it. With this project you can create your own animated Mario clock. With a nice frame it can be a retro decorative object for any environment.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/mario-bros-1.jpg&quot; alt=&quot;Display backside with Trinity board&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mario-bros-clock/#hardware&quot; aria-labelledby=&quot;hardware&quot;&gt;#&lt;/a&gt;&lt;p&gt;After some research it turned out the project is relative easy to build. All you need is an HUB75 LED matrix display, an ESP32 based micro controller, some jumper wires and a 5V power supply. In addition, you need the Clockwise firmware.&lt;/p&gt;
&lt;p&gt;If you already have an ESP32 micro controller board at hand you can use that. For an easy-to-use and integrated solution check out &lt;a href=&quot;https://github.com/witnessmenow/ESP32-Trinity&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESP32 Trinity&lt;/a&gt;. If you want to build your own PCD &lt;a href=&quot;https://github.com/Alexvanheu/Mario-Clock-PCB-ESP32&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this project from @Alexvanheu&lt;/a&gt; can help you get started.&lt;/p&gt;
&lt;p&gt;As a starting point, I experimented with a breadboard and an ESP32-based microcontroller. Wiring instructions for the display can be found on &lt;a href=&quot;https://github.com/jnthas/clockwise#driving-the-led-matrix&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt;. However, I did not like all the wires and wanted them hidden behind the display. In the end I switched to the Trinity board. It can be directly plugged into the LED matrix display HUB75 connector - no wires, no soldering needed. The Trinity comes with touch sensitive buttons, an LDR to control the display brightness, display power control, 5V input and USB-C. It also makes some of the ESP32 pins available for other custom projects.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/mario-bros-2.jpg&quot; alt=&quot;Display backside with Trinity board&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The typical &lt;a href=&quot;https://www.aliexpress.com/item/1005001958513042.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;64x64 LED matrix displays you get on Aliexpress&lt;/a&gt; are available in different sizes. I opted for a 192mm x 192mm version. For the frame I bought a simple &lt;a href=&quot;https://www.amazon.de/dp/B09W47J295?&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;gray picture frame on Amazon&lt;/a&gt;. If you own a 3D printer you can &lt;a href=&quot;https://www.thingiverse.com/search?q=64x64+LED+matrix+case&amp;amp;page=1&amp;amp;type=things&amp;amp;sort=relevant&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;build a custom frame or case&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To supply the clock with enough power you need a 5V power supply with enough ampere. Minimum 2A, better 3A or higher is recommended. The power needed depends on the display itself and the brightness of the pixels you select.&lt;/p&gt;
&lt;p&gt;I use a USB-C power supply with a 2A current for powering my display. When using the Trinity board you can choose between a USB-C or a 2.1mm barrel jack power supply. Be sure to set the &lt;a href=&quot;https://github.com/witnessmenow/ESP32-Trinity/blob/master/setup.md#powering-the-matrix-panel-using-usb-c&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;correct jumper on the board for USB-C power&lt;/a&gt; and remove it while flashing.&lt;/p&gt;
&lt;h2 id=&quot;firmware&quot;&gt;Firmware&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mario-bros-clock/#firmware&quot; aria-labelledby=&quot;firmware&quot;&gt;#&lt;/a&gt;&lt;p&gt;The Clockwise project page has all the clock skins available to be directly flashed from the website. There are actually five of them: of course Mario Bros. but also a text-based clock, a world clock, a Castlevania skin and a Pac Mac skin.&lt;/p&gt;
&lt;p&gt;On the Clockwise website select the clock face you like and directly flash the firmware from within the browser. Make sure you use a browser supporting WebSerial API. Chrome on desktop works fine, Safari on Mac does not. Mobile browsers also don’t work.&lt;/p&gt;
&lt;p&gt;To flash the firmware follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://clockwise.page/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://clockwise.page/&lt;/a&gt; and select the clockface you like&lt;/li&gt;
&lt;li&gt;Connect the ESP32 device to your computer’s USB port (make sure it is not powered separately yet).&lt;/li&gt;
&lt;li&gt;Click on the Flash button.&lt;/li&gt;
&lt;li&gt;Select the correct USB port the device is connected to and click on “Connect” - this depends on the operating system and browser you use.&lt;/li&gt;
&lt;li&gt;The installer will ask you to install Clockwise firmware - click “INSTALL” and “INSTALL” on the next screen.&lt;/li&gt;
&lt;li&gt;Flashing the board will take ~ 2 minutes, then you should see the installation complete message. Click “NEXT”.&lt;/li&gt;
&lt;li&gt;The installer will look for WiFi networks to connect to.&lt;/li&gt;
&lt;li&gt;Select your local network and enter your password and click “CONNECT”.&lt;/li&gt;
&lt;li&gt;Once connected successfully, a message with the button “VISIT DEVICE” will pop up and you can visit the clock settings page.&lt;/li&gt;
&lt;li&gt;On the clock settings page make sure you set the right time zone to display the correct time. The default time zone is UTC.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;: the time zone lookup is based on ezTime which uses &lt;a href=&quot;http://timezoned.rop.nl&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;timezoned.rop.nl&lt;/a&gt; on port 2342. If you have a looked down network, you need to unblock UDP connections on port 2342 next to the NTP protocol.&lt;/p&gt;
&lt;p&gt;That’s it, your Mario Bros. clock is ready. If not already done, the next step could be to put the display in a stylish case or frame.&lt;/p&gt;
&lt;p&gt;With the current firmware version 1.1.0 some additional settings can be adjusted from the device settings page: time zone, swap Blue/Green pins (depending on the display type you use), 24h time format and display brightness.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update Dec. 01 2023&lt;/strong&gt;&lt;br&gt;
The Clockwise firmware has got a bunch of new releases since the first post. You are now able configure automatic brightness, connect a photoresistor (LDR sensor), customize the NTP server.&lt;br&gt;
You can now also configure the time zone using &lt;a href=&quot;https://github.com/ropg/ezTime#timezones-1&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Posix Timezone string&lt;/a&gt; in case the automatic time zone selection (which requires extra network ports) does not work.&lt;/p&gt;
&lt;h2 id=&quot;the-final-result&quot;&gt;The final result&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mario-bros-clock/#the-final-result&quot; aria-labelledby=&quot;the-final-result&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/mario-bros-3.gif&quot; alt=&quot;Mario Animation&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The project is great, thanks to &lt;a href=&quot;https://github.com/jnthas&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;@jnthas&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Going Green: SolarEdge &amp; Home Assistant</title>
    <link href="https://markus-haack.com/our-own-electricity-3/"/>
    <updated>2023-03-18T00:00:00Z</updated>
    <id>https://markus-haack.com/our-own-electricity-3/</id>
    <content type="html">&lt;p&gt;Home Assistant is an open-source home automation platform that allows you to connect and control all the devices in your home. It supports a &lt;a href=&quot;https://www.home-assistant.io/integrations/#energy&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;wide range of solar inverters&lt;/a&gt; like Fronius, SMA Solar, Solar-Log, GoodWe or SolarEdge. And while SolarEdge already provides an extensive monitoring portal for end users, there are still some reasons to integrate with Home Assistant. Home Assistant lets you design cross-system dashboards or automations that leave the proprietary islands of manufacturers. For example, we can start charging our electric car when we have enough solar power left. This is &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/#making-the-maths&quot;&gt;more cost effective than sending it back to the grid&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this blog post, we will take a look at how to integrate a SolarEdge inverter with Home Assistant. We will use the out of the box SolarEdge integration and the SolarEdge Modbus integration. It ties directly to the first two posts about our &lt;a href=&quot;https://markus-haack.com/our-own-electricity-1/&quot;&gt;solar installation&lt;/a&gt; and our &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/&quot;&gt;own green energy production&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;two-integration-options&quot;&gt;Two Integration Options&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#two-integration-options&quot; aria-labelledby=&quot;two-integration-options&quot;&gt;#&lt;/a&gt;&lt;p&gt;We have two options to get the data from our SolarEdge system into Home Assistant.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using the built-in, out of the box SolarEdge integration&lt;/li&gt;
&lt;li&gt;Via the SolarEdge Modbus custom integration&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Installation of 1) is way simpler and pretty straightforward. The inverter data is loaded from the SolarEdge monitoring portal, not via the inverter directly. This will only provide you with the data SolarEdge provides via its cloud APIs and it will also be delayed.&lt;/p&gt;
&lt;p&gt;With the custom integration - option 2) - you’ll get more data and technical details, maybe more than you even need. As the data is retrieved directly from the inverter, it is almost as real-time as possible. However the setup of the custom component code requires some inverter config changes (in most cases) and the installation is a little more effort.&lt;/p&gt;
&lt;p&gt;If you plan to use the Home Assistant energy dashboard I recommend option 2.&lt;/p&gt;
&lt;h2 id=&quot;integrating-solaredge-via-the-cloud-integration&quot;&gt;Integrating SolarEdge via the cloud integration&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#integrating-solaredge-via-the-cloud-integration&quot; aria-labelledby=&quot;integrating-solaredge-via-the-cloud-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;Integrating your &lt;a href=&quot;https://www.home-assistant.io/integrations/solaredge/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge inverter&lt;/a&gt; with Home Assistant is a straightforward process. This chapter describes how this can be achieved using the out of the box SolarEdge cloud integration which gets the data from the SolarEdge portal. The integration will update the site overview every 15 minutes. This is due to API request limits of the SolarEdge cloud API.&lt;/p&gt;
&lt;p&gt;Here are the steps:&lt;/p&gt;
&lt;h3 id=&quot;step-1%3A-obtain-your-solaredge-api-key&quot;&gt;Step 1: Obtain your SolarEdge API Key&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-1%3A-obtain-your-solaredge-api-key&quot; aria-labelledby=&quot;step-1%3A-obtain-your-solaredge-api-key&quot;&gt;#&lt;/a&gt;&lt;p&gt;The first thing you need to do is obtain your SolarEdge API key. To do this, go to the &lt;a href=&quot;https://monitoring.solaredge.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge monitoring website&lt;/a&gt; and log in to your account. Then navigate to “Admin” &amp;gt; “API Access” page, where you will find your Site ID and the API key. You will need to accept the terms and conditions if this is the first time.&lt;/p&gt;
&lt;h3 id=&quot;step-2%3A-install-the-solaredge-integration&quot;&gt;Step 2: Install the SolarEdge Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-2%3A-install-the-solaredge-integration&quot; aria-labelledby=&quot;step-2%3A-install-the-solaredge-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The next step is to install the SolarEdge integration in Home Assistant. This can be done via the “Settings” page in Home Assistant. From there select “Devices &amp;amp; Services” and then click on the “+ Add Integration” button in the bottom right corner. In the dialog search for “SolarEdge”. You will see two options. Select “SolarEdge” with the cloud symbol.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-solaredge-config-1.png&quot; alt=&quot;SolarEdge Config Step 2&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-3%3A-configure-the-integration&quot;&gt;Step 3: Configure the Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-3%3A-configure-the-integration&quot; aria-labelledby=&quot;step-3%3A-configure-the-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-solaredge-config-2.png&quot; alt=&quot;SolarEdge Config Step 3&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;On the SolarEdge integration configuration screen, enter your SolarEdge Site ID and API key from Step 1. Once done click on “Submit.” Home Assistant will then automatically discover your SolarEdge inverter via the SolarEdge monitoring portal, add it to your Home Assistant dashboard and configure the sensors.&lt;/p&gt;
&lt;p&gt;You are now ready to display the data in your custom dashboards or use them for the &lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/#home-assistent-energy-dashboard&quot;&gt;energy dashboard&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;integrating-solaredge-inverter-using-modbus&quot;&gt;Integrating SolarEdge Inverter using Modbus&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#integrating-solaredge-inverter-using-modbus&quot; aria-labelledby=&quot;integrating-solaredge-inverter-using-modbus&quot;&gt;#&lt;/a&gt;&lt;p&gt;The &lt;a href=&quot;https://github.com/binsentsu/home-assistant-solaredge-modbus&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge Modbus&lt;/a&gt; integration is an alternative way to integrate your SolarEdge inverter with Home Assistant. It can be used as a replacement for the default SolarEdge cloud-based integration or in combination. Instead of retrieving aggregated data from the SolarEdge monitoring portal this method uses the Modbus TCP protocol to communicate directly with the inverter.&lt;/p&gt;
&lt;p&gt;Here’s what you need to do:&lt;/p&gt;
&lt;h3 id=&quot;step-1%3A-enable-modbus-tcp-on-your-solaredge-inverter&quot;&gt;Step 1: Enable Modbus TCP on Your SolarEdge Inverter&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-1%3A-enable-modbus-tcp-on-your-solaredge-inverter&quot; aria-labelledby=&quot;step-1%3A-enable-modbus-tcp-on-your-solaredge-inverter&quot;&gt;#&lt;/a&gt;&lt;p&gt;Your inverter must have Modbus TCP enabled. For some inverters you can do it yourself, for others you need an electrician. This depends on the inverter model.&lt;/p&gt;
&lt;p&gt;In my case (using SE7K-RWS inverter) is was necessary to set the inverter into installation mode and connect directly to the inverter WiFi. Modbus TCP can be enabled in the “Site Communication” menu. This can be done via the SolarEdge SetApp or via a browser. These steps should be similar for most SolarEdge inverters of the current generation. If you are unsure ask your local solar installer or electrician.&lt;/p&gt;
&lt;h3 id=&quot;step-2%3A-configure-the-solaredge-modbus-integration&quot;&gt;Step 2: Configure the SolarEdge Modbus Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-2%3A-configure-the-solaredge-modbus-integration&quot; aria-labelledby=&quot;step-2%3A-configure-the-solaredge-modbus-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The SolarEdge Modbus integration is available as a customer integration. You can installed it via &lt;a href=&quot;https://hacs.xyz&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HACS&lt;/a&gt; - search for “SolarEdge” - or manually. See instructions on the &lt;a href=&quot;https://github.com/binsentsu/home-assistant-solaredge-modbus&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;projects Git repository&lt;/a&gt;.&lt;br&gt;
After installation make sure you reboot your Home-Assistant system.&lt;/p&gt;
&lt;h3 id=&quot;step-3%3A-connect-the-modbus-integration-with-the-inverter&quot;&gt;Step 3: Connect the Modbus Integration with the Inverter&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-3%3A-connect-the-modbus-integration-with-the-inverter&quot; aria-labelledby=&quot;step-3%3A-connect-the-modbus-integration-with-the-inverter&quot;&gt;#&lt;/a&gt;&lt;p&gt;On the SolarEdge Modbus integration configuration screen, enter the IP address and port number of your SolarEdge inverter, and click on “Submit.” Home Assistant will then automatically discover your SolarEdge inverter and add it to your Home Assistant dashboard.&lt;/p&gt;
&lt;p&gt;Like many other integrations the SolarEdge Modbus integration is installed via the Home Assistant UI. Then navigate to the “Settings” page in Home Assistant. From there select “Devices &amp;amp; Services” and then click on the “+ Add Integration” button in the bottom right corner. In the dialog search for “SolarEdge” and choose “SolarEdge Modbus”. The open box icon indicates that the SolarEdge Modbus integration is a custom integration.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-solaredge-config-3.png&quot; alt=&quot;SolarEdge Config Step 3&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-4%3A-configure-the-integration&quot;&gt;Step 4: Configure the Integration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#step-4%3A-configure-the-integration&quot; aria-labelledby=&quot;step-4%3A-configure-the-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-solaredge-config-4.png&quot; alt=&quot;SolarEdge Config Step 3&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the configuration dialog enter the local IP address of your inverter. The TCP port should stay at 1502 and in most cases the Modbus address must stay at 1 as well. This depends a little bit on your setup, if multiple inverters are used etc. Select the “Read …” checkboxes for the meters (up to 3) and batteries (up to 2) you would like to get data for. The integration automatically creates all sensor entities for the meters and batteries.&lt;/p&gt;
&lt;p&gt;The SolarEdge Modbus integration can provide very detailed data from the inverter. The integration created 107 sensors for our installation. Not all of them are needed by us. For example, since we have a 3 phase system, I disabled most of the sensors with separate details data for a single phase as I’m only interested in combined data.&lt;/p&gt;
&lt;h2 id=&quot;home-assistent-energy-dashboard&quot;&gt;Home Assistent Energy Dashboard&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#home-assistent-energy-dashboard&quot; aria-labelledby=&quot;home-assistent-energy-dashboard&quot;&gt;#&lt;/a&gt;&lt;p&gt;While SolarEdge offers a very comprehensive &lt;a href=&quot;https://monitoring.solaredge.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;energy monitoring portal&lt;/a&gt; it is still a smart idea to set up the &lt;a href=&quot;https://www.home-assistant.io/home-energy-management&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Energy Dashboard&lt;/a&gt;. The Home Assistant Energy Dashboard provides a more detailed overview of the energy usage of individual consumers. It also provides access to historical data, allowing users to track trends and make informed decisions about their energy usage. Furthermore, it helps you identify your home’s energy-hogging appliances and devices. Once you know which devices are using the most energy, you can take steps to reduce their usage or replace them with more energy-efficient alternatives.&lt;/p&gt;
&lt;p&gt;To get the most out of it I highly recommend configuring the &lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/#integrating-solaredge-inverter-using-modbus&quot;&gt;SolarEdge Modbus integration&lt;/a&gt; as this provides more data points, especially if your inverter has battery storage connected as well.&lt;/p&gt;
&lt;p&gt;To setup the Home Assistant Energy Dashboard three sensors are needed - the energy values for solar production, grid consumption and exported energy. If you have battery storage installed you have the option to configure battery in and out aka. charge and discharge energy sensors.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-ha-daschboard-1.png&quot; alt=&quot;Home Assistant Screenshot&quot; title=&quot;Screenshot Home Assistant Energy Dashboard Configuration&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot Home Assistant Energy Dashboard Configuration&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the “Individual devices” section you can add all devices which provide energy consumption data like washing machines, fridges, wallboxes, lamps etc. If your devices don’t provide energy consumption sensors a smart plug can be used.&lt;/p&gt;
&lt;p&gt;Make sure the energy sensors are not excluded if you have a customized recorder configuration in Home Assistant. Only sensors with history recording can be used in the energy dashboard.&lt;/p&gt;
&lt;p&gt;If you live in Europe I recommend setting up the &lt;a href=&quot;https://www.home-assistant.io/integrations/forecast_solar/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Forecast.Solar&lt;/a&gt; integration as well, in addition to the inverter and device energy sensors. Based on historical averages and weather forecasts, it can forecast solar power production for your solar panel system. Currently Forecast.Solar only works in Europe. I’m not sure if there is an equivalent service for other regions.&lt;/p&gt;
&lt;p&gt;Once configured Home Assistant requires some time to collect enough data until the Home Assistant Energy Dashboard is fully working.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-ha-daschboard-2.png&quot; alt=&quot;Home Assistant Screenshot&quot; title=&quot;Screenshot Home Assistant Energy Dashboard - 18th March 2023&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot Home Assistant Energy Dashboard - 18th March 2023&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Let it run for 2-3 days and then come back. Over time, with enough data collected, you will get a very clean and informative dashboard. With the help of the “Monitor individual devices” view it is now easier to find energy hungry devices using individual monitored devices.&lt;/p&gt;
&lt;p&gt;For an even more fine tuned configuration of the Home Assistant Energy Dashboard in combination with SolarEgde I recommend checking this thread on the &lt;a href=&quot;https://community.home-assistant.io/t/updated-solaredge-modbus-full-setup-guide-with-energy-dashboard-integration-for-installations-with-battery-connected/340956&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant Community&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-3/#conclusion&quot; aria-labelledby=&quot;conclusion&quot;&gt;#&lt;/a&gt;&lt;p&gt;Integrating a SolarEdge inverter with Home Assistant helps with real-time monitoring and managing of our solar power system. The integration can be achieved using either the SolarEdge API or the SolarEdge Modbus integration. With live data, especially from the SolarEdge Modbus integration we can optimize your energy usage, control electricity consumers and ultimately reduce your electricity bills.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>HC-SR04 &amp; JSN-SR04T ultrasonic distance sensors in ESPHome</title>
    <link href="https://markus-haack.com/ultrasonic-distance-sensors-esphome/"/>
    <updated>2023-03-04T00:00:00Z</updated>
    <id>https://markus-haack.com/ultrasonic-distance-sensors-esphome/</id>
    <content type="html">&lt;p&gt;In relation to my &lt;a href=&quot;https://markus-haack.com/watertank-esphome/&quot;&gt;ESPHome water tank project&lt;/a&gt; I got a lot of inquiries about how to use an ultrasonic distance sensor with ESPHome. That’s why I created this short guide.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://esphome.io/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome&lt;/a&gt; is an open-source framework for building Internet of Things (IoT) devices using the ESP8266 and ESP32 microcontrollers. ESPHome provides an YAML-based configuration language for creating custom firmware that runs on these devices. There is no need to learn and code C++ to program the microcontrollers.&lt;/p&gt;
&lt;h2 id=&quot;the-sensors&quot;&gt;The sensors&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/ultrasonic-distance-sensors-esphome/#the-sensors&quot; aria-labelledby=&quot;the-sensors&quot;&gt;#&lt;/a&gt;&lt;p&gt;Depending on the characteristics of your project you have two options of ultrasonic distance sensors to choose from: the HC-SR04 or the JSN-SR04T.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/ultrasonic-sensors.jpg&quot; alt=&quot;JSN-SR04T and HC-SR04&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;Both sensors are capable of accurately measuring distances between 2cm and ~400cm using ultrasonic pulses and are suitable for a wide range of projects. They both use the same principle of measuring the time it takes for an ultrasonic pulse to travel from the sensor to an object and back.&lt;/p&gt;
&lt;p&gt;Here are a few key differences between the two sensors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Physical size: The JSN-SR04T sensor is larger than the HC-SR04 sensor, which may make it more difficult to fit into small projects.&lt;/li&gt;
&lt;li&gt;Waterproofing: The JSN-SR04T sensor is designed to be waterproof, which makes it a better choice for outdoor projects or projects that may be exposed to moisture like a &lt;a href=&quot;https://markus-haack.com/watertank-esphome/&quot;&gt;water tank sensor&lt;/a&gt; installation.&lt;/li&gt;
&lt;li&gt;Cables: The JSN-SR04T typically consists of two parts: the sensor itself and a logic board. Only the sensor itself is waterproof, the logic board is not. The HC-SR04 sensor consists of only one module.&lt;/li&gt;
&lt;li&gt;Power consumption: The JSN-SR04T sensor has a higher power consumption than the HC-SR04 sensor. This can be a concern if you are building battery powered projects.&lt;/li&gt;
&lt;li&gt;Cost: A HC-SR04 sensor (~1€) is definitely the cheaper option and the JSN-SR04T (~4€) sensor is generally more expensive.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The choice between them will depend on your specific requirements, such as size, waterproofing, power consumption, and cost. While the HC-SR04 sensor can be used universally, the JSN-SR04T sensor is often the better choice for outdoor projects.&lt;/p&gt;
&lt;h2 id=&quot;esphome-ultrasonic-distance-sensor&quot;&gt;ESPHome Ultrasonic Distance Sensor&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/ultrasonic-distance-sensors-esphome/#esphome-ultrasonic-distance-sensor&quot; aria-labelledby=&quot;esphome-ultrasonic-distance-sensor&quot;&gt;#&lt;/a&gt;&lt;p&gt;For the following instructions, I assume that you already know ESPHome. If not, see here for &lt;a href=&quot;https://esphome.io/guides/getting_started_hassio.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;an introduction to the ESPHome&lt;/a&gt;. It is recommended that you integrate Home Assistant with ESPHome and use the Dashboard for ESPHome. As an alternative, for non Home Assistant users, there is also the option to use the &lt;a href=&quot;https://esphome.io/guides/getting_started_command_line.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome Command Line tool&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/hc-sr04-sensor-project.jpg&quot; alt=&quot;HC-SR04 &amp; Wemos D1 mini&quot; title=&quot;HC-SR04 &amp; Wemos D1 mini on the breadboard&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;HC-SR04 &amp; Wemos D1 mini on the breadboard&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here are the steps to use the HC-SR04 or JSN-SR04T sensor with ESPHome:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Connect the sensor to your microcontroller. I’m using a Wemos D1 mini to illustrate the steps. Both ultrasonic distance sensors have four pins: VCC, GND, TRIG, and ECHO. Connect the VCC pin to a 5V power supply, GND to ground, TRIG to a GPIO pin (I’m using D1) on the microcontroller board, and ECHO to another GPIO pin (I’m using D2).&lt;/li&gt;
&lt;li&gt;Create a new ESPHome configuration file for your device. Using the Home Assistant integration you can use the ESPHome wizard. Otherwise create a new YAML file manually.&lt;/li&gt;
&lt;li&gt;Add the following code to the configuration file to define the HC-SR04 sensor:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ultrasonic
   &lt;span class=&quot;token key atrule&quot;&gt;trigger_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D1
   &lt;span class=&quot;token key atrule&quot;&gt;echo_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D2
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;My Ultrasonic Sensor&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Replace &lt;code&gt;D1&lt;/code&gt; and &lt;code&gt;D2&lt;/code&gt; with the GPIO pins you connected to the TRIG and ECHO pins of your sensor.&lt;/li&gt;
&lt;li&gt;Save and upload the ESPHome firmware to your microcontroller using the ESPHome web interface or the command-line tool.&lt;/li&gt;
&lt;li&gt;Once the firmware is uploaded and the device is connected to your Wi-Fi network, you should be able to see the distance measurement from the ultrasonic sensor in the microcontroller logs within the ESPHome dashboard or using.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/watertank_steckplatine.png&quot; alt=&quot;fritzing diagram of water tank sensor setup&quot; title=&quot;Wiring diagram of JSN-SR04T on the breadboard&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Wiring diagram of JSN-SR04T on the breadboard&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;That’s it! You now have a working HC-SR04 or JSN-SR04T ultrasonic distance sensor connected to your microcontroller and integrated with ESPHome.&lt;/p&gt;
&lt;p&gt;The basic project code looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;esphome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ultrasonic&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;sensor
 &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ESP8266
 &lt;span class=&quot;token key atrule&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; d1_mini_pro

&lt;span class=&quot;token key atrule&quot;&gt;wifi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;ssid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;YOUR_SSID&#39;&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;YOUR_PASSWORD&#39;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Enable logging&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Enable Home Assistant API&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Enable over-the-air updates&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;ota&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ultrasonic
   &lt;span class=&quot;token key atrule&quot;&gt;trigger_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D1
   &lt;span class=&quot;token key atrule&quot;&gt;echo_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D2
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;My Ultrasonic Sensor&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;update_interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1s
   &lt;span class=&quot;token key atrule&quot;&gt;accuracy_decimals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;unit_of_measurement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cm&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this code, replace &lt;code&gt;YOUR_SSID&lt;/code&gt; and &lt;code&gt;YOUR_PASSWORD&lt;/code&gt; with your Wi-Fi network’s name and password, respectively. The &lt;code&gt;platform&lt;/code&gt; and &lt;code&gt;board&lt;/code&gt; options will depend on the type of microcontroller you are using. For a generic ESP8266 board use &lt;code&gt;board: nodemcuv2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Fortunately, HC-SR04 and JSN-SR04T use the same data interface. The code works for both ultrasonic distance sensors in the same way. Once running the log from ESPHome will look like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;I&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;102&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ESPHome version 2023.2.4 compiled on Mar 4 2023&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;14:48:45&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;504&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;WiFi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;362&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Local MAC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2C&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;3A&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;E8&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;1F&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;60:26&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;363&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;SSID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;redacted&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;364&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;IP Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.30.72
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;365&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;BSSID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;redacted&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;367&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;distance-sensor&#39;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;369&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Signal strength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;61 dB ▂▄▆█
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;373&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;374&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Subnet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 255.255.255.0
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;375&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Gateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.30.1
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;376&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;DNS1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.1.3
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wifi&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;377&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;DNS2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 192.168.30.1
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;293&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;294&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Level&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; DEBUG
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;295&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Log Baud Rate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;115200&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;296&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Hardware UART&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; UART0
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;045&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ultrasonic Sensor &#39;Ultrasonic Sensor&#39;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;045&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;State Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;measurement&#39;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;045&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Unit of Measurement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;m&#39;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;045&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Accuracy Decimals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;045&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Icon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mdi:arrow-expand-vertical&#39;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;046&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Echo Pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO4
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;047&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Trigger Pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GPIO5
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;048&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Pulse time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10 µs
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;049&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 11661 µs
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;050&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Update Interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10.0s
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;captive_portal&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;088&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Captive Portal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mdns&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;108&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;mDNS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mdns&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;109&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; distance&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;sensor
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ota&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;093&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Over-The-Air Updates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ota&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;094&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; distance&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;sensor.lan&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8266&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ota&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;097&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Using Password.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;138&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;API Server&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;139&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; distance&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;sensor.lan&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6053&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;141&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Using noise encryption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; YES
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:46&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;040&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &#39;Ultrasonic Sensor&#39; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Got distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.52 m
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:46&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;&#39;Ultrasonic Sensor&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Sending state 1.52258 m with 2 decimals of accuracy
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:56&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;040&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &#39;Ultrasonic Sensor&#39; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Got distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.76 m
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:49:56&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;&#39;Ultrasonic Sensor&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Sending state 0.75717 m with 2 decimals of accuracy
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:50:06&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;040&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &#39;Ultrasonic Sensor&#39; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Got distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.99 m
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:50:06&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;&#39;Ultrasonic Sensor&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Sending state 0.98938 m with 2 decimals of accuracy
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:50:16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;040&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &#39;Ultrasonic Sensor&#39; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Got distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.52 m
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:50:16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;&#39;Ultrasonic Sensor&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Sending state 1.51777 m with 2 decimals of accuracy
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:50:26&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultrasonic.sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;040&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &#39;Ultrasonic Sensor&#39; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Got distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.27 m
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token datetime number&quot;&gt;14:50:26&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;D&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sensor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;&#39;Ultrasonic Sensor&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Sending state 0.27440 m with 2 decimals of accuracy&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;advanced-esphome-configuration&quot;&gt;Advanced ESPHome configuration&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/ultrasonic-distance-sensors-esphome/#advanced-esphome-configuration&quot; aria-labelledby=&quot;advanced-esphome-configuration&quot;&gt;#&lt;/a&gt;&lt;p&gt;ESPHome has some powerful features that allow you to manipulate sensor values as well as automate the process of sending data before sending it to Home Assistant.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/index.html#sensor-filters&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;filters&lt;/a&gt; allow you to pre-process sensor values like adding offset or multipliers, calibrate the output or calculate median, moving average, min, max and more&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/index.html#sensor-automation&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;state change events&lt;/a&gt; help building automations and run a lambda function on sensor state changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;using-filters&quot;&gt;Using filters&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/ultrasonic-distance-sensors-esphome/#using-filters&quot; aria-labelledby=&quot;using-filters&quot;&gt;#&lt;/a&gt;&lt;p&gt;Some handy filters that can be used in combination with ultrasonic distance sensors are:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;filter_out&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;filter_out&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nan&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;filter_out&lt;/code&gt; can be used to filter out specific sensor readings. For some projects the ultrasonic distance sensors can sometimes give undefined data which I would like to ignore, for example if the distance gets too large for the sensor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;median&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;median&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;window_size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This filter is useful to filter outliers from the received sensor data. Using the &lt;code&gt;window_size&lt;/code&gt; option you can control the number of values over which to calculate a &lt;a href=&quot;https://esphome.io/components/sensor/index.html#median&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;moving median&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;min &amp;amp; max&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Similar to the &lt;code&gt;median&lt;/code&gt; filter these help to calculate a min or max value based on a defined number of sensor value readings.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; min

or

&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; max&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;offset &amp;amp; multiply&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;multiply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;offset&lt;/code&gt; you can add a constant factor to the sensor value. With the help of &lt;code&gt;multiply&lt;/code&gt; you can multiply each sensor value by a constant value. For the distance sensor this can be helpful for converting the units of the measurements. In order to adjust the value of ultrasonic distance sensors to centimeters and inches, they need to be filtered with a multiply filter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;calibrate_linear&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;calibrate_linear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 0.0 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; 0.0
	  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 10.0 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; 12.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the &lt;code&gt;calibrate_linear&lt;/code&gt; filter you get a powerful mapping tool for the sensor values allowing you to transform the measured values with an accurate “truth” source. You need to provide two ranges and a linear equation function is applied. This filter becomes handy if the sensor does not return accurate values or if you need to map the sensor values into another range.&lt;/p&gt;
&lt;h3 id=&quot;sensor-automation&quot;&gt;Sensor automation&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/ultrasonic-distance-sensors-esphome/#sensor-automation&quot; aria-labelledby=&quot;sensor-automation&quot;&gt;#&lt;/a&gt;&lt;p&gt;Sensor events provide the possibility of running automations directly on the micro controller board. No Home Assistant or server is needed. The available sensor events are:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;on_value&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;on_value&lt;/code&gt; sensor event an automation can be triggered to run a lambda function. The function can access the sensor trigger value by using the &lt;code&gt;x&lt;/code&gt; variable. Sensor automations are triggered after sensor filters have been applied. If filters are configured for a sensor &lt;code&gt;x&lt;/code&gt; has already the pre-processed value.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;on_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;sensor.template.publish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_liter
     &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return x * 3.1415926;&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As shown in the example, a second template sensor is updated with a new value. You can also use it to toggle a light or switch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;on_raw_value&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;on_raw_value&lt;/code&gt; works similar like the &lt;code&gt;on_value&lt;/code&gt; event, but as the name implies you have access to the direct sensor value that hasn’t passed through any filters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;on_value_range&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With the &lt;code&gt;on_value_range&lt;/code&gt; even you can run automations if a sensor value passes from outside a defined range of values to inside a range. By combining this with a distance sensor, a notification can be triggered when the sensor value exceeds or falls.&lt;/p&gt;
&lt;p&gt;Find more about ESPHome sensor automations on the &lt;a href=&quot;https://esphome.io/guides/automations.html#automation&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome web page&lt;/a&gt;. In my &lt;a href=&quot;https://markus-haack.com/watertank-esphome/&quot;&gt;water tank sensor project&lt;/a&gt; I use some of these filters and a simple automation to update linked template sensors. The water tank sensor project utilizes a JSN-SR04T ultrasonic distance sensor to monitor the water level in our water tank. The data collected by these sensor is send to Home Assistant.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Going Green: Our Own Electricity</title>
    <link href="https://markus-haack.com/our-own-electricity-2/"/>
    <updated>2023-02-27T00:00:00Z</updated>
    <id>https://markus-haack.com/our-own-electricity-2/</id>
    <content type="html">&lt;p&gt;In part 2 of my “Our Own Electricity” series I give an insight into our electricity production and consumption. After I explained our &lt;a href=&quot;https://markus-haack.com/our-own-electricity-1/&quot;&gt;setup&lt;/a&gt; I will share details on the installation costs, our break even calculation.&lt;/p&gt;
&lt;p&gt;Disclaimer: the numbers below are actual numbers from our installation. There will be differences in numbers based on the place where you live, the local regulations and the hours of sun you get.&lt;/p&gt;
&lt;h2 id=&quot;energy-production&quot;&gt;Energy Production&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#energy-production&quot; aria-labelledby=&quot;energy-production&quot;&gt;#&lt;/a&gt;&lt;p&gt;The initial estimates of electricity yield from the sales offers were all around 9 MWh per year. Of course, I knew that they were all overestimated, people wanted to sell us a photovoltaic system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-angebot.png&quot; alt=&quot;Screenshot offer&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;I now have real data from 2.5 years. First overall I am very satisfied with the energy production of our installation.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-energy-2020-2023-year.png&quot; alt=&quot;Screenshot SolarEdge panel monitoring&quot; title=&quot;Energy production 2020 - 2023 - yearly summery&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Energy production 2020 - 2023 - yearly summery&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In 2021, the first full year, our photovoltaic system produced 7,78 MWh. I’m very happy especially with the electricity production in 2022. Last year we had very sunny spring and summer and could produce 9,1 MWh. This is even a tiny bit higher than the initial estimates.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-energy-2020-2023-month.png&quot; alt=&quot;Screenshot SolarEdge panel monitoring&quot; title=&quot;Energy production 2020 - 2023 - per month&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Energy production 2020 - 2023 - per month&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In 2022 the electricity yield was higher than in 2021 in all months except December. See light blue bars in the diagram above. Only 60 kWh were produced throughout December 2022. We can produce almost the same on a summer day in July or August. We produce approximately 90% of the electricity between March and October. Darker winter months - November till February are usually very low in electricity yield. Living in central Europe 51° N there is not much sun during these month. And when the sun shines, it only shines for a few hours and at a flat angle.&lt;/p&gt;
&lt;p&gt;Last years we didn’t had much snow at the place we live. But if we had some it usually stayed for a while. During that time no electricity is produced even on sunny days if the panels are covered with snow. In December 2022 we had exactly such a case. It snowed for two days and then one week of super sunny winter days but the snow didn’t melt.&lt;/p&gt;
&lt;p&gt;Overall we get 50% of the electricity yield in 1/3 of the time. During the summer months May till August we produce &amp;gt; 1MWh each month. April 2022 was also close to 1MWh. The rest of the year the electricity yield is lower, especially during the winter months.&lt;/p&gt;
&lt;h3 id=&quot;effect-of-the-battery-storage&quot;&gt;Effect of the battery storage&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#effect-of-the-battery-storage&quot; aria-labelledby=&quot;effect-of-the-battery-storage&quot;&gt;#&lt;/a&gt;&lt;p&gt;In retrospect it was a good decision to install a battery. I was initially skeptical as to whether it would be worth it, especially because of the extra acquisition and installation costs &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/#making-the-maths&quot;&gt;calculation below&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In 2022 we consumed 38% (2.145 kWh) of our self produced electricity from the battery. Like any battery, a solar battery storage also has a low energy loss. The manufacturer claims it has over 90% efficiency. So we loaded ~ 2.383 kWh into the battery to get 2.145 kWh out. Without battery this would be send to the grid during the day and consumed from the grid during the evening our. This saved us over 400 Euro, &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/#making-the-maths&quot;&gt;see calculation below&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A typical battery charging and dis-charging curve on a summer day looks like this:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-energy-2020-2023-month.png&quot; alt=&quot;battery charging and dis-charging curve&quot; title=&quot;Sample battery charging and dis-charging curve&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Sample battery charging and dis-charging curve&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;making-the-maths&quot;&gt;Making the maths&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#making-the-maths&quot; aria-labelledby=&quot;making-the-maths&quot;&gt;#&lt;/a&gt;&lt;p&gt;Ok how profitable is the whole thing now really. The numbers below are from the initial calculation I made during our planing phase end of 2019. With the current energy crisis 2022 here in Europe and especially in Germany, the savings for every kilowatt hour that we produce ourselves are even higher. While paying lot more for electricity consumed from the grid we also save more money for every kilowatt we produce ourselves and don’t consume from the public grid.&lt;/p&gt;
&lt;h3 id=&quot;acquisition-costs&quot;&gt;Acquisition costs&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#acquisition-costs&quot; aria-labelledby=&quot;acquisition-costs&quot;&gt;#&lt;/a&gt;&lt;p&gt;When reading this part please keep in mind that we installed the solar panels early 2020, more than two years ago. Prices cannot be compared one-to-one with today’s price ranges for photovoltaic hardware, batteries and installation service costs. The cost of photovoltaic hardware, batteries and installation services have increased significantly since the installation of our system two years ago.&lt;/p&gt;
&lt;p&gt;Our installation costs are made up as follows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Photovoltaic system&lt;/td&gt;
&lt;td&gt;11.407,46 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYD battery storage&lt;/td&gt;
&lt;td&gt;5.765,07 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Electric assembly DC &amp;amp; AC&lt;/td&gt;
&lt;td&gt;3.811,00 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery&lt;/td&gt;
&lt;td&gt;328,00 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total (pre tax)&lt;/td&gt;
&lt;td&gt;21.311,53 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VAT 19%&lt;/td&gt;
&lt;td&gt;4.049,19 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total (incl. tax)&lt;/td&gt;
&lt;td&gt;25.360,72 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Battery storage funding&lt;/td&gt;
&lt;td&gt;-3.200 €&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Final installation cost&lt;/td&gt;
&lt;td&gt;22.160,72 €&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The first row of the table includes the 27 Qcells solar panels, the &lt;a href=&quot;https://www.solaredge.com/en/products/residential/pv-inverters&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge inverter&lt;/a&gt;, 27 &lt;a href=&quot;https://www.solaredge.com/en/products/residential/power-optimizers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SolarEdge optimizers&lt;/a&gt;, substructure, cables, and assembly on the roof. The electric assembly package contains the DC cable installation, connecting everything to the inverter, connecting the converter with the AC election installation in our house, installing overvoltage protection, all the cabels and configuring the SolarEdge inverter with the right parameters.&lt;/p&gt;
&lt;p&gt;As part of the Sächsische Aufbaubank funding program, we received 3.200 € for the installation of a photovoltaic battery system. Most likely, we wouldn’t have installed a battery storage system without the funding. By the end of 2019, electricity costs would not have made the purchase worthwhile. Luckily we did. However since electricity costs a lot in 2019, the calculation would be different now and today I would recommend to install a photovoltaic battery for most set ups.&lt;/p&gt;
&lt;h3 id=&quot;impact-of-the-battery-storage&quot;&gt;Impact of the battery storage&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#impact-of-the-battery-storage&quot; aria-labelledby=&quot;impact-of-the-battery-storage&quot;&gt;#&lt;/a&gt;&lt;p&gt;As written above in 2022 we consumed 2.145 kWh out of the photovoltaic battery. The photovoltaic battery, like every other battery, has some loss of charge. The energy amount loaded into the storage system was ~ 2.383 kWh.&lt;/p&gt;
&lt;p&gt;Would these 2.383 kWh have been sent back into the grid we would get some compensation for it.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;2.383 kWh * 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;0967 € = 230 € of theoretical compensation&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same time we would have drawn the 2.145 kWh from the grid instead from the battery. The price for that, with rates of 2022, would be:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;2.145 kWh *  0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;2996 € = 643 € of theoretical electricity cost&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The battery saved us approximately 413€ in one year. Giving the installation cost of the battery system (3200€) the investment is recovered after 8 years.&lt;/p&gt;
&lt;h3 id=&quot;savings-%26-break-even&quot;&gt;Savings &amp;amp; break even&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#savings-%26-break-even&quot; aria-labelledby=&quot;savings-%26-break-even&quot;&gt;#&lt;/a&gt;&lt;p&gt;Our self-produced electricity saves us a few hundred euros on our electricity bill. Based on the final &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/#acquisition-costs&quot;&gt;installation costs&lt;/a&gt; of 22.160,72 € for the entire system, we calculated that the break even point would be after 18 years. How is it today?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-energy-2022.png&quot; alt=&quot;Production and Consumption overview for 2022&quot; title=&quot;Production and Consumption overview for 2022&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Production and Consumption overview for 2022&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We reached 62% self-consumption on the production side in 2022. 3.460 kWh (= 38%) have been feed into the grid. For each kWh we don’t use ourselves and feed into the grid we receive 0,0967 € feed-in tariff. This amount is guaranteed for 20 years by the&lt;br&gt;
Erneuerbare-Energien-Gesetz (EEG = Renewable Energy Sources Act in Germany).&lt;/p&gt;
&lt;p&gt;For 2022 this means:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;3.460 kWh*  0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;0967 € = 334&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;97 €&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the consumption side we ended up with 56% self-consumption out of 10.150 kWh consumed energy. This means 5.640 kWh we did not consume from the grid.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;5.640 kWh *  0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;2996 € = 1689&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;74 €

with 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;2996 € = our price per kWh in 2022&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the end, we gained the equivalent of 1.689,74 € of free electricity. A lot of money was saved on the electricity bill. Due to the difference between the consumption tariff and the feed-in tariff, optimizing for self-consumption makes the most sense. We save more money on every kWh of self-produced electricity than we receive for grid excess energy.&lt;/p&gt;
&lt;p&gt;In total, savings on self-consumption plus money from electricity feed-in, we “earned” 2.024 €. Based on that projection, the break even point should be reached within 12 years. With the updated, increased consumption rates we already got for 2023 of 0,52 € per kWh this we should hit it even earlier.&lt;/p&gt;
&lt;p&gt;My original plan was to write an extra section about taxes as well. But I would only be able to explain the rules for Germany and even here I’m not a tax expert. Other countries have different laws and tax rules and even here in Germany things are constantly changing. So I will skip that part as it would likely be outdated at the time of writing.&lt;/p&gt;
&lt;h3 id=&quot;grand-total&quot;&gt;Grand total&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-2/#grand-total&quot; aria-labelledby=&quot;grand-total&quot;&gt;#&lt;/a&gt;&lt;p&gt;So far we are pretty happy with our installation. By installing a photovoltaic system, we have been able to save money on our electricity bills, as well as earn some money from the sale of our excess electricity. We earned a value of 2.024 € in 2022 (1.631€ in 2021). Installing the photovoltaic system was definitely the right choice if this continues in the coming years.&lt;/p&gt;
&lt;p&gt;We save money on and do something good for the environment at the same time.&lt;/p&gt;
&lt;p&gt;In the next &lt;a href=&quot;https://markus-haack.com/our-own-electricity-3/&quot;&gt;post&lt;/a&gt; I will explain how I integrated our photovoltaic system with Home Assistant to get more detailed data and electricity monitoring for our entire house.&lt;/p&gt;
&lt;p&gt;Hero image photo by &lt;a href=&quot;https://unsplash.com/@pf91_photography&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Daniel van den Berg&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/de/fotos/v-S6fyZOWKg&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Going Green: Installing a Solar System</title>
    <link href="https://markus-haack.com/our-own-electricity-1/"/>
    <updated>2023-01-08T00:00:00Z</updated>
    <id>https://markus-haack.com/our-own-electricity-1/</id>
    <content type="html">&lt;p&gt;This one has been in my draft folder for a few weeks. Our photovoltaic system was installed in spring 2020 and I wanted to report on it earlier. I finally had some time to finish the article over the holidays. Small side effect of the fact that it took a bit longer: by the end of 2022 I will have two full years of electricity yield data to show and compare.&lt;/p&gt;
&lt;p&gt;This article will consist of 3 blog posts because there are too many topics I would like to cover. This first article describes our journey, the motivation behind why we installed it in the first place and the technical setup. In part two, I will cover the numbers, the hard facts, about the electricity yield, our savings on the energy bill. I will also share our financial summary of when we expect to break even. In a third post I will explain how the solar system is integrated into our Home Assistant setup.&lt;/p&gt;
&lt;h2 id=&quot;why-solar&quot;&gt;Why Solar&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-1/#why-solar&quot; aria-labelledby=&quot;why-solar&quot;&gt;#&lt;/a&gt;&lt;p&gt;We had already thought about installing a photovoltaic system and put solar panels on our roof a few times before.&lt;/p&gt;
&lt;p&gt;Summer 2019 was the time to finally implement the project. Next to the obvious reasons to save money on our energy bills and having some protection against rising electricity costs there was another driver for this project: the pool we built in spring 2017 in our backyard. Due to this we have increased power consumption in summer - exactly when the sun is shining. The pool pump, which runs for at least 12 hours a day, depending on the temperature, consumes a lot of electricity. The warmer it is, the longer the pool pump has to run and the higher the power consumption.&lt;/p&gt;
&lt;p&gt;Based on our estimates from 2019 - with am electricity rate of 0,28 € per kWh and an investment of ~ 22k € - break even was projected for about 12-14 years. I will go into more detail in part 2 about our investment calculation.&lt;/p&gt;
&lt;p&gt;Germany has the highest electricity prices in Europe:&lt;/p&gt;
&lt;p class=&quot;small&quot;&gt;![European electricity prices 2021](/assets/images/pricelist-2021.png ‘European electricity prices 2021, Source: &lt;a href=&quot;https://ec.europa.eu/eurostat/databrowser/bookmark/f1f42d1e-4766-4f49-9612-b11bae203fe8?lang=en&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eurostat: electricity prices by type of user&lt;/a&gt;’)&lt;/p&gt;
&lt;p&gt;We have already calculated that electricity prices will increase anyway. But we could not foresee that increase now with the energy crisis we have in Europe. Current rates for kilowatt-hour in German are ~ 0,43 € per kWh. With that break even should be already a few years earlier.&lt;/p&gt;
&lt;p&gt;We also bought a hybrid car in 2021 and try to drive as much as possible on electricity. Another big electricity consumer and confirmation that producing our own electricity was a smart idea.&lt;/p&gt;
&lt;h2 id=&quot;our-setup&quot;&gt;Our setup&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-1/#our-setup&quot; aria-labelledby=&quot;our-setup&quot;&gt;#&lt;/a&gt;&lt;p&gt;Tech specs …&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;27 Hanwha / &lt;a href=&quot;https://qcells.com/ane/get-started/complete-energy-solution/solar-panel-detail?slrPnlId=SRPL211201065907002&amp;amp;look=002&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Q.Cells DUO-G8 panels&lt;/a&gt; with 350 Watts peak power each&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.solaredge.com/en/products/residential/power-optimizers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Solaredge optimizers&lt;/a&gt; P370&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.solaredge.com/en/products/residential/pv-inverters&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Solaredge inverter SE7K-RWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.bydbatterybox.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;BYD L10.5 battery storage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We installed 27 solar panels on the roof. Each can produce a peak of 350 Watts. Our house has a hip roof. We installed solar panels on the east, south and west side of the roof with a total of 9,45 kilowatts peak output.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-solar-system.png&quot; alt=&quot;Simulated panel installation&quot; title=&quot;Simulated solar panel placement on our roof&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Simulated solar panel placement on our roof&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We didn’t install solar panels on the north side because there was a 10 kilowatt peak output limit in Germany in 2019. If you exceed this, you have to install an extra switch-off device from the electricity network operator. With this, the grid operator can disconnect the system from the grid or turn down the power at any time. For example, too much electricity is available on the grid. Extra installation costs - that were not worth it at the time. This limit was raised to 25 kilowatts peak output in 2021. So today we would probably also install panels on the north side.&lt;/p&gt;
&lt;p&gt;We decided to go with a StorEdge 3 phase inverter system (SE7K-RWS) from SolarEdge with special optimizers. It can operate at a maximum of 7 kilowatts. Given the 3 roof sides have no full sun at the same time this should be more than enough. In the morning, the east side gets the most sunlight while the west side has shadows. In the evening, it’s the opposite. Panels installed on the west side produce electricity while panels on the east get almost no output. We also have a chimney on the west roof that casts shadows on the solar modules.&lt;/p&gt;
&lt;p&gt;With the installed optimizer, we will be able to produce more energy, especially if not all of the panels receive the same amount of sunlight. The optimizer can help to maximize the energy output of each solar panel, leading to increased overall energy production from the entire photovoltaic system. Additionally the Solaredge optimizers come with built-in monitoring capabilities. Each solar panel can be monitored individually. This is mostly a tech nerd argument, but it can help diagnose and troubleshoot problems with the photovoltaic system.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-panel-monitoring.png&quot; alt=&quot;Screenshot SolarEdge panel monitoring&quot; title=&quot;SolarEdge individual panel monitoring&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;SolarEdge individual panel monitoring&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The two biggest disadvantages of this setup are cost and compatibility. Each optimizer adds 80€, ~2k € to our installation. Also they are only compatible with Solaredge inverters, so we have to stay with one vendor and cannot install another inverter.&lt;/p&gt;
&lt;p&gt;The StorEdge inverter can also connect 48V low voltage batteries directly. Our battery storage solution consists of a BYD Battery-Box LV with a capacity of 10,5 kilowatts. The battery is charged and discharged with max. 5 kilowatts.&lt;/p&gt;
&lt;p&gt;SolarEdge’s mobile app and portal let you monitor the StorEdge inverter as well as the BYD Battery Box.&lt;/p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-1/#installation&quot; aria-labelledby=&quot;installation&quot;&gt;#&lt;/a&gt;&lt;p&gt;As soon as the contract with the solar installation company was signed, the installation of our solar system was scheduled for early 2020. At the beginning of 2020, COVID really got started in Europe. Lockdown, schools closed, everyone sent to the home office, people began hoarding toilet paper - ideal conditions for installing a solar system.&lt;/p&gt;
&lt;h3 id=&quot;up-on-the-roof&quot;&gt;Up on the roof&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-1/#up-on-the-roof&quot; aria-labelledby=&quot;up-on-the-roof&quot;&gt;#&lt;/a&gt;&lt;p&gt;We were lucky with the weather in February 2020. It was cold but dry, so the roofers were able to install the solar panels at the end of February. Delivering panels, setting up scaffolding and assembly of the substructure and solar panels on the roof - everything was done in 3 days.&lt;/p&gt;
&lt;p&gt;From then on it got complicated. Nothing happened in the next few weeks. Germany went into lockdown. The delivery of the inverter was delayed only by two weeks - that was nothing. We got the message that delivery of the battery system from China was delayed indefinitely. The electrician had to wait for the electricity network operator’s employees. They were all working from home, not allowed to work on the side. It took us over a month to get an appointment with a service technician.&lt;/p&gt;
&lt;p&gt;After the network operator’s technician replaced the energy meter, the electrician could finish the installation. Still took 2 weeks as the electrician had kids at home. Remember we were still in lockdown, the schools were also closed. All the setup was done in mid-April. Apart from annoying calls to the electricity network operator’s hotline to get an appointment, nothing happened for the next month and a half. Finally we could get an appointment with a service technician scheduled for May 28th for the final inspection. Everything was fine and connected properly. Finally, more than 3 months later than planned, at 2:30pm we could flip the circuit switch and start producing our own electricity.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-solaredge-day1.png&quot; alt=&quot;Screenshot SolarEdge Portal from day 1&quot; title=&quot;Electricity production of our photovoltaic system on day 1&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Electricity production of our photovoltaic system on day 1&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The entire setup was completed 2 months later with the battery storage installed in July 2020.&lt;/p&gt;
&lt;h3 id=&quot;all-the-paperwork&quot;&gt;All the paperwork&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-1/#all-the-paperwork&quot; aria-labelledby=&quot;all-the-paperwork&quot;&gt;#&lt;/a&gt;&lt;p&gt;Commissioning a solar system in Germany requires a lot of paperwork, phone calls, and yes even in 2019, sending a fax.&lt;/p&gt;
&lt;p&gt;The photovoltaic system has to be registered at with many organisations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the local electricity network operator&lt;/li&gt;
&lt;li&gt;the electricity provider company (because our electricity meter go replaced)&lt;/li&gt;
&lt;li&gt;the German “Bundesnetzagentur” (Federal Network Agency for Electricity, Gas, Telecommunications, Post and Railway)&lt;/li&gt;
&lt;li&gt;and finally the tax office&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solar installation company took care of most of those, at least the complex and time-consuming communication with the electricity company. They had countless forms, some with identical information, about our installation, electrical parameters, etc. that had to be filled out. Only after approval by the local electricity network operator we are allowed to operate the solar system and connect it to the grid.&lt;/p&gt;
&lt;p&gt;Registering the solar system and later the installed battery in the German Marktstammdatenregister (MaStR) is a legal obligation. At least this part can be done online. Why is this needed? I’m not an expert here but I feel mostly for data collection and statistics by the government. So my small home solar system and myself, as an electricity provider, are now registered in a database - next to the big power plants and energy provider companies.&lt;/p&gt;
&lt;p&gt;Last but not least, in Germany you have to notify the tax office that a solar system has been installed. With that I’m now running a business as an electricity provider that requires me to pay sales tax for the energy I produce. More on tax for solar systems see below.&lt;/p&gt;
&lt;h2 id=&quot;our-own-clean-energy&quot;&gt;Our own clean energy&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/our-own-electricity-1/#our-own-clean-energy&quot; aria-labelledby=&quot;our-own-clean-energy&quot;&gt;#&lt;/a&gt;&lt;p&gt;With the installation done we are now finally producing our own clean, carbon free electricity. This feels good.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-saved-trees.png&quot; alt=&quot;Screenshot SolarEdge Portal saved trees&quot; title=&quot;CO2 emission saved by us&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;CO2 emission saved by us&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://markus-haack.com/our-own-electricity-2/&quot;&gt;part 2&lt;/a&gt; I will show the details of the energy we produce and the financial calculation of our installation.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>New Talk: How to Build Content and Commerce Experiences Using App Builder and API Mesh</title>
    <link href="https://markus-haack.com/content-and-commerce-experiences-using-app-builder-and-api-mesh/"/>
    <updated>2022-12-07T00:00:00Z</updated>
    <id>https://markus-haack.com/content-and-commerce-experiences-using-app-builder-and-api-mesh/</id>
    <content type="html">&lt;p&gt;Last November, Adobe hosted the Adobe Developers Live Headless. The event focused on building modern experiences with AEM Sites headless.&lt;/p&gt;
&lt;p&gt;Together with my colleagues Mark &amp;amp; James I gave a presentation about how to build a Content and Commerce Experiences with AEM Sites &amp;amp; Adobe Commerce.&lt;/p&gt;
&lt;p&gt;The talk discussed the use of the App Builder and API Mesh to create content and commerce experiences. We guided developers through the end-to-end flow of building a headless experience driven commerce storefront.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starting with AppBuilder API Mesh to aggregate different content sources from Adobe Experience Manager &amp;amp; Commerce&lt;/li&gt;
&lt;li&gt;Learn how to build headless experience displaying products enriched with Adobe Experience Manager Content Fragments&lt;/li&gt;
&lt;li&gt;Use Micro Frontends for to integrate a shopping cart into your application&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enjoy the recording of our presentation.&lt;/p&gt;
&lt;div id=&quot;25cTzVV2jfQ&quot; class=&quot;eleventy-plugin-youtube-embed&quot; style=&quot;position:relative; width:100%; padding-top: 56.25%&quot;&gt;&lt;iframe allowfullscreen=&quot;&quot; embedded-video=&quot;&quot; src=&quot;https://video.tv.adobe.com/v/3411440/?quality=12&amp;amp;learn=on&quot; style=&quot;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&quot;&gt;&lt;source src=&quot;https://video.tv.adobe.com/v/3411440/?quality=12&amp;learn=on&quot; type=&quot;&quot;&gt;&lt;p&gt;Your browser does not support the iframe element.&lt;/p&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;The source code of the project built during the presentation can be found on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;https://github.com/herzog31/aem-nextjs-template&quot; label=&quot;AEM NextJS Template App&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;F﻿ind all recordings of the Adobe Developers Live Headless at &lt;a href=&quot;https://experienceleague.adobe.com/docs/adobe-developers-live-events/events/2022/nov2022/api-mesh.html?lang=en&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adobe Experience League&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The Moving Spiders</title>
    <link href="https://markus-haack.com/the-moving-spiders/"/>
    <updated>2022-11-15T00:00:00Z</updated>
    <id>https://markus-haack.com/the-moving-spiders/</id>
    <content type="html">&lt;h2 id=&quot;little-spiders-on-your-shoulder&quot;&gt;Little spiders on your shoulder&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-moving-spiders/#little-spiders-on-your-shoulder&quot; aria-labelledby=&quot;little-spiders-on-your-shoulder&quot;&gt;#&lt;/a&gt;&lt;p&gt;For this year’s Halloween project I built something without pumpkins. The small moving spiders are to scare our guests. During the party, we placed it over the buffet table. A second one was placed in such a way that it reached down to the kids’ shoulders when they were standing at the buffet and didn’t suspect anything. Using small motors, the spiders moved up and down on their own.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wgdrPl0-C9E&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=wgdrPl0-C9E&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;parts-%26-tools&quot;&gt;Parts &amp;amp; Tools&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-moving-spiders/#parts-%26-tools&quot; aria-labelledby=&quot;parts-%26-tools&quot;&gt;#&lt;/a&gt;&lt;p&gt;The following components &amp;amp; tools are needed to assemble the project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ESP8266 (&lt;a href=&quot;https://markus-haack.com/the-world-of-wemos-d1-mini-boards/&quot;&gt;Wemos D1 mini&lt;/a&gt;, Nodemcu) or ESP32&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aliexpress.com/item/1005004428326464.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;L298 dual motor bridge board&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;two slow motors with ~100-200rpm, I went with &lt;a href=&quot;https://www.aliexpress.com/item/32910513701.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;micro gear motors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;prototyping board&lt;/li&gt;
&lt;li&gt;male &amp;amp; female pin headers&lt;/li&gt;
&lt;li&gt;material for a small roller to wind up the thread&lt;/li&gt;
&lt;li&gt;two spiders or scary items&lt;/li&gt;
&lt;li&gt;USB cable and power supply&lt;/li&gt;
&lt;li&gt;soldering iron&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;hardware-assembly&quot;&gt;Hardware assembly&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-moving-spiders/#hardware-assembly&quot; aria-labelledby=&quot;hardware-assembly&quot;&gt;#&lt;/a&gt;&lt;p&gt;The wiring of electronic parts is straightforward. For the small motors, usually no extra power source is required. The L298 dual motor board can be directly connected to the 5V and GND of the ESP board. Additionally, 4 wires are needed to control the motors. A forward and reverse signal is needed for each motor. These must be connected to the digital pins of the ESP board.&lt;/p&gt;
&lt;p&gt;The motors are also powered by the L298 dual motor board directly.&lt;/p&gt;
&lt;p&gt;Here is my prototype and wiring diagram:&lt;br&gt;
&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/halloween-spiders2.jpg&quot; alt=&quot;the first prototype&quot; title=&quot;First prototype on a breadboard&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;First prototype on a breadboard&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/halloween-spiders_steckplatine.png&quot; alt=&quot;wiring diagram&quot; title=&quot;Wiring diagram&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Wiring diagram&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;For the final assembly soldered the cables and some headers to a &lt;a href=&quot;https://www.wemos.cc/en/latest/d1_mini_shield/protoboard.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Wemos protoboard&lt;/a&gt;. The Wemos D1 Mini is mounted on top. For the motor controller I chose with an L298 dual motor board. No extra soldering is needed here.&lt;/p&gt;
&lt;p&gt;The assembly of the motor part and the cylinder for winding the thread requires some trial and error. As for the construction, I chose wood. 3D printing a bracket would maybe be a better option, but I don’t have a 3D printer 😃&lt;/p&gt;
&lt;p&gt;The most tricky part is the cylinder. It took me three tries to get the drilling to mount the motor into the cylinder correctly. The small micro gear motors do not produce much torque. Even the slightest tilt blocks the motor.&lt;/p&gt;
&lt;p&gt;My final construction looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/halloween-spiders1.jpg&quot; alt=&quot;the final prototype&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;This got directly mounted to the ceiling.&lt;/p&gt;
&lt;h2 id=&quot;software&quot;&gt;Software&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-moving-spiders/#software&quot; aria-labelledby=&quot;software&quot;&gt;#&lt;/a&gt;&lt;p&gt;This time I created the software using &lt;a href=&quot;https://esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome&lt;/a&gt;. Controlling two motors is easy and can be done with a simple ESPHome sketch. No complex Arduino C development is needed.&lt;br&gt;
ESPHome has support for the L298 motor controller via the &lt;a href=&quot;https://esphome.io/components/fan/hbridge.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;fan integration&lt;/a&gt;. That’s why you will see &lt;code&gt;fan&lt;/code&gt; commands in the code.&lt;/p&gt;
&lt;p&gt;The forward and reverse pins for each motor are defined in the &lt;code&gt;output&lt;/code&gt; block. These are connected to a (fan) motor by the &lt;code&gt;fan&lt;/code&gt; block, which we can use later to control the motor direction and speed.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; esp8266_pwm
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor1_forward_pin
   &lt;span class=&quot;token key atrule&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D2
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; esp8266_pwm
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor1_reverse_pin
   &lt;span class=&quot;token key atrule&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D1
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; esp8266_pwm
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor2_forward_pin
   &lt;span class=&quot;token key atrule&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D5
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; esp8266_pwm
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor2_reverse_pin
   &lt;span class=&quot;token key atrule&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D6

&lt;span class=&quot;token key atrule&quot;&gt;fan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hbridge
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_1
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Motor 1&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mdi:spider-thread&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;pin_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor1_forward_pin
   &lt;span class=&quot;token key atrule&quot;&gt;pin_b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor1_reverse_pin
   &lt;span class=&quot;token key atrule&quot;&gt;decay_mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; slow
   &lt;span class=&quot;token key atrule&quot;&gt;on_turn_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;logger.log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Motor 1: on - duration = %d ms, direction = %d&#39;&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;id(motor_1_duration)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(motor_1).direction&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;on_turn_off&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;logger.log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Motor 1: off&#39;&lt;/span&gt;

 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hbridge
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_2
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Motor 2&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mdi:spider-thread&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;pin_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor2_forward_pin
   &lt;span class=&quot;token key atrule&quot;&gt;pin_b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor2_reverse_pin
   &lt;span class=&quot;token key atrule&quot;&gt;decay_mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; slow
   &lt;span class=&quot;token key atrule&quot;&gt;on_turn_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;logger.log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Motor 2: on - duration = %d ms, direction = %d&#39;&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;id(motor_2_duration)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id(motor_2).direction&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;on_turn_off&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;logger.log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Motor 2: off&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the program I defined two virtual switches to enable/disable the motor automation remotely for example via Home Assistant. The automation itself is an &lt;code&gt;interval&lt;/code&gt; based script with some random variable to add some variance in the up &amp;amp; down movement.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1min
   &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;globals.set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_1_duration
       &lt;span class=&quot;token key atrule&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return (rand() % 8) * 1000 + 3000;&#39;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;switch.is_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; program_1
       &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# forward&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;fan.turn_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
           &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_1
           &lt;span class=&quot;token key atrule&quot;&gt;direction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; forward
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return id(motor_1_duration);&#39;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;fan.turn_off&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_1
        &lt;span class=&quot;token comment&quot;&gt;# pause&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return id(motor_1_duration);&#39;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# reverse&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
           id(motor_1_duration) += 3000;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;fan.turn_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
           &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_1
           &lt;span class=&quot;token key atrule&quot;&gt;direction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; reverse
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return (id(motor_1_duration));&#39;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;fan.turn_off&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; motor_1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both motor automations follow the same pattern:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set the duration variable with a random number&lt;/li&gt;
&lt;li&gt;Turn motor on&lt;/li&gt;
&lt;li&gt;Wait for duration time&lt;/li&gt;
&lt;li&gt;Turn motor off&lt;/li&gt;
&lt;li&gt;Wait for duration time&lt;/li&gt;
&lt;li&gt;Turn motor on in reverse direction&lt;/li&gt;
&lt;li&gt;Wait for duration time&lt;/li&gt;
&lt;li&gt;Turn motor off&lt;/li&gt;
&lt;li&gt;Start with 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It even integrates with Home Assistant automatically with ESPHome. This is not really necessary as the motor control part runs automatically, but it is also fun to manually move the spiders up &amp;amp; down. It took some time to get the right values and ranges for &lt;code&gt;motor_1_duration&lt;/code&gt; and &lt;code&gt;motor_2_duration&lt;/code&gt;. They depend on the rotation speed of the motors, the weight of the spiders on the thread, and the height of the ceiling. Some trial and adjustment is needed.&lt;/p&gt;
&lt;p&gt;In Home Assistant I can turn on/off the automations using the virtual switches and control the motors directly. I can also set the motor speed and change the direction.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot-homeassistant.png&quot; alt=&quot;Home Assistant Screenshot&quot; title=&quot;Screenshot Home Assistant&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot Home Assistant&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As usual the &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/esphome/halloween-spiders.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;source&lt;/a&gt; can be found in my GitHub repository:&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/home-assistant-config&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-final-result&quot;&gt;The final result&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-moving-spiders/#the-final-result&quot; aria-labelledby=&quot;the-final-result&quot;&gt;#&lt;/a&gt;&lt;p&gt;The kids at the party had a lot of fun with the spiders. At first, they hadn’t seen them coming down from the ceiling and were absolutely scared. Next year, to level it up, I will try to get some spiders with blinking LED eyes.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/halloween-spiders.jpg&quot; alt=&quot;the final spider in action&quot; title=&quot;The spider in action&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;The spider in action&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The world of Wemos D1 Mini Boards</title>
    <link href="https://markus-haack.com/the-world-of-wemos-d1-mini-boards/"/>
    <updated>2022-09-26T00:00:00Z</updated>
    <id>https://markus-haack.com/the-world-of-wemos-d1-mini-boards/</id>
    <content type="html">&lt;p&gt;Some readers recently asked me about the Wemos D1 mini usage in my projects and how this board can be used with ESPHome.&lt;/p&gt;
&lt;p&gt;For most of my &lt;a href=&quot;https://markus-haack.com/tags/arduino/&quot;&gt;Arduino&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://markus-haack.com/tags/esphome/&quot;&gt;ESPHome&lt;/a&gt; projects I use a &lt;a href=&quot;https://www.wemos.cc/en/latest/d1/d1_mini_3.1.0.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Wemos D1 mini (v3.1.0)&lt;/a&gt; or &lt;a href=&quot;https://www.wemos.cc/en/latest/d1/d1_mini_pro.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Wemos D1 mini Pro (v1.1.0)&lt;/a&gt; and recently the &lt;a href=&quot;https://www.wemos.cc/en/latest/d1/d1_mini.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Wemos D1 mini v4.0&lt;/a&gt;. The fourth board of the family is the is the &lt;a href=&quot;https://www.wemos.cc/en/latest/d1/d1_mini_lite.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;D1 mini light&lt;/a&gt;. I never used one of the light versions, most of the time you can get the D1 mini &amp;amp; D1 mini pro for almost identical prices at &lt;a href=&quot;http://alipexpress.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;alipexpress.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The boards are equipped with a ESP-8266EX chip running at 80 or 160MHz, like many other Node MCU boards. They provide 12 I/O pins - &lt;a href=&quot;https://markus-haack.com/the-world-of-wemos-d1-mini-boards/#pinout&quot;&gt;11 digital and 1 analog input pin&lt;/a&gt; - enough for the most projects.&lt;/p&gt;
&lt;p&gt;I also like the board because it is little smaller than a classic Node MCU board. The dimensions are 34.2 mm x 25.6mm. It is so small; it even fits into a small &lt;a href=&quot;https://markus-haack.com/mini-tv/&quot;&gt;dollhouse Mini TV&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wemos recently upgraded both boards. The Wemos D1 mini is now on version 4.0.0 and the Wemos D1 mini Pro on v2.0.0. Both boards got USB type C connectors instead of micro USB. The pro version also got a lithium battery interface charging interface and a LOLIN I2C Port. To fit everything on the board D1 mini Pro has grown a bit.&lt;/p&gt;
&lt;h2 id=&quot;pinout&quot;&gt;Pinout&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-world-of-wemos-d1-mini-boards/#pinout&quot; aria-labelledby=&quot;pinout&quot;&gt;#&lt;/a&gt;&lt;p&gt;The pinouts of the D1 mini and the D1 mini Pro are identical, also the D1 mini shares the same pin layout. And with the latest board versions of the D1 mini (v4.0.0) vs. D1 mini Pro (v2.0.0) Wemos keeps the pin layout compatible.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/d1-mini-pro-pinout.jpeg&quot; alt=&quot;D1 mini Pro Pinout&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Pin&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Function&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;ESP-8266 Pin&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TX&lt;/td&gt;
&lt;td&gt;TXD&lt;/td&gt;
&lt;td&gt;TXD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RX&lt;/td&gt;
&lt;td&gt;RXD&lt;/td&gt;
&lt;td&gt;RXD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A0&lt;/td&gt;
&lt;td&gt;Analog input, max 3.2V&lt;/td&gt;
&lt;td&gt;A0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D0&lt;/td&gt;
&lt;td&gt;IO&lt;/td&gt;
&lt;td&gt;GPIO16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D1&lt;/td&gt;
&lt;td&gt;IO, SCL&lt;/td&gt;
&lt;td&gt;GPIO5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D2&lt;/td&gt;
&lt;td&gt;IO, SDA&lt;/td&gt;
&lt;td&gt;GPIO4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D3&lt;/td&gt;
&lt;td&gt;IO, 10k Pull-up&lt;/td&gt;
&lt;td&gt;GPIO0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D4&lt;/td&gt;
&lt;td&gt;IO, 10k Pull-up, BUILTIN_LED&lt;/td&gt;
&lt;td&gt;GPIO2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D5&lt;/td&gt;
&lt;td&gt;IO, SCK&lt;/td&gt;
&lt;td&gt;GPIO14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D6&lt;/td&gt;
&lt;td&gt;IO, MISO&lt;/td&gt;
&lt;td&gt;GPIO12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D7&lt;/td&gt;
&lt;td&gt;IO, MOSI&lt;/td&gt;
&lt;td&gt;GPIO13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D8&lt;/td&gt;
&lt;td&gt;IO, 10k Pull-down, SS&lt;/td&gt;
&lt;td&gt;GPIO15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G&lt;/td&gt;
&lt;td&gt;Ground&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5V&lt;/td&gt;
&lt;td&gt;5V&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3V3&lt;/td&gt;
&lt;td&gt;3.3V&lt;/td&gt;
&lt;td&gt;3.3V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RST&lt;/td&gt;
&lt;td&gt;Reset&lt;/td&gt;
&lt;td&gt;RST&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Important: all of the IO pins run at 3.3V.&lt;/p&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://www.wemos.cc/en/latest/d1/d1_mini.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.wemos.cc&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;d1-mini-vs.-d1-mini-pro&quot;&gt;D1 mini vs. D1 mini Pro&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-world-of-wemos-d1-mini-boards/#d1-mini-vs.-d1-mini-pro&quot; aria-labelledby=&quot;d1-mini-vs.-d1-mini-pro&quot;&gt;#&lt;/a&gt;&lt;p&gt;The most obvious visible difference between the two boards is the color. In previous versions all boards used a blue PCB, but with the latest release the Pro version got a green PCB.&lt;/p&gt;
&lt;p&gt;While the board shares the same pinout, USB-C connector and the LOLIN I2C Port they have a few technical differences. One is the ceramic antenna and the external antenna connector on the board. With the ceramic antenna the D1 mini Pro should have better WiFi reception than its little brother. The Pro board also comes with an external antenna connector to connect a U.FL connector compatible with 2.4GHz Wi-Fi antennas. Projects using the Pro board can also be powered with lithium batteries. The board includes a charging interface with 500mA Max charging current. Another difference is the flash memory size. In comparison, the D1 mini Pro has 16 MBytes of flash memory whereas the D1 mini only has 4 MBytes.&lt;/p&gt;
&lt;p&gt;Depending on the projects you build these differences matter for now. It was perfectly fine to use the D1 mini for most of the projects I built.&lt;/p&gt;
&lt;h2 id=&quot;d1-mini-compatible-shields&quot;&gt;D1 mini compatible shields&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-world-of-wemos-d1-mini-boards/#d1-mini-compatible-shields&quot; aria-labelledby=&quot;d1-mini-compatible-shields&quot;&gt;#&lt;/a&gt;&lt;p&gt;Wemos provides a wide range of pre-build extension shields for the D1 minis. There is a wide range of LED, OLED, TFT and ePager &lt;a href=&quot;https://www.wemos.cc/en/latest/d1_mini_shield/index.html#display-interactive-shields&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;display boards&lt;/a&gt; for interactive projects.&lt;/p&gt;
&lt;p&gt;Various types of &lt;a href=&quot;https://www.wemos.cc/en/latest/d1_mini_shield/index.html#environment-shields&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;environmental sensors&lt;/a&gt; are available. You can choose from simple temperature &amp;amp; humidity sensors, air quality sensors or a standard PIR sensor. Next to the sensor shields Wemos also has a selection of motor driver shields for different areas of applications.&lt;/p&gt;
&lt;p&gt;If you can’t find a suitable shield for your project, Wemos offers so-called base shields. These are &lt;a href=&quot;https://www.wemos.cc/en/latest/d1_mini_shield/index.html#others&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;empty prototyping boards&lt;/a&gt; for your DIY projects. They are available in different form factors (1x, 2x &amp;amp; 3x) and can also be used to stack other shields.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/wemosd1shields.jpg&quot; alt=&quot;D1 mini compatible shields&quot; class=&quot;large&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;All shield boards typically come with male and female pins are already included in the package. A full list of official shields can be found on the &lt;a href=&quot;https://www.wemos.cc/en/latest/d1_mini_shield/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Wemos Wiki&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;esphome-%26-the-d1-mini-boards&quot;&gt;ESPHome &amp;amp; the D1 mini boards&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/the-world-of-wemos-d1-mini-boards/#esphome-%26-the-d1-mini-boards&quot; aria-labelledby=&quot;esphome-%26-the-d1-mini-boards&quot;&gt;#&lt;/a&gt;&lt;p&gt;ESPHome works on top of PlatformIO which has support for a wide range of ESP8266, ESP32 and various other development boards. Wemos D1 boars are supported as well, to use them in your ESPHome projects use:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;esphome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ESP8266
  &lt;span class=&quot;token key atrule&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; d1_mini

&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; or &lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;esphome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ESP8266
  &lt;span class=&quot;token key atrule&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; d1_mini_pro&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or use the short form:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;esp8266&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; d1_mini_pro&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I recommend to always use the Wemos specific board name instead of a generic esp board or &lt;code&gt;board: nodemcuv2&lt;/code&gt;. While these might work as well the pin mapping might be mixed up and you will get unexpected behaviour.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Green grass with Home Assistant</title>
    <link href="https://markus-haack.com/green-grass-with-home-assistant/"/>
    <updated>2022-06-01T00:00:00Z</updated>
    <id>https://markus-haack.com/green-grass-with-home-assistant/</id>
    <content type="html">&lt;p&gt;Home Assistant controlled garden watering part 2 - are you ready?&lt;/p&gt;
&lt;p&gt;In my &lt;a href=&quot;https://markus-haack.com/watertank-esphome/&quot;&gt;previous post&lt;/a&gt;, I explained how I measured the level of water in our garden cistern using ESPHome. In this post, I will describe how the garden watering system works. I will explain how we get our water from the tank, distribute it in our garden, and control the main pump. In addition, I will give an example of how I use the measurements to automatically refill the water tank when the weather is dry.&lt;/p&gt;
&lt;h2 id=&quot;garden-watering&quot;&gt;Garden watering&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/green-grass-with-home-assistant/#garden-watering&quot; aria-labelledby=&quot;garden-watering&quot;&gt;#&lt;/a&gt;&lt;p&gt;The only water supply for the entire irrigation system is our water tank. The pipes are not connected to our domestic water connection. There are two reasons for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the outside water tap does not have enough pressure and the flow rate is too low&lt;/li&gt;
&lt;li&gt;it is cumbersome to connect two water sources - domestic water connection and rainwater tank into one cycle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In our region, connecting domestic water and rainwater can be tricky and may require the installation of expensive extra equipment. A special pump and a backflow stop valve are needed to make sure rainwater for the water tank does not flow back into the public water pipes.&lt;/p&gt;
&lt;p&gt;The low flow rate of domestic water connection is a smaller problem and can be worked around by separating the sprinklers into more independent zones. They can be activated sequentially one after each other - will work but extend the overall watering time.&lt;/p&gt;
&lt;h2 id=&quot;reliable%2C-robust-and-without-drama&quot;&gt;Reliable, robust and without drama&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/green-grass-with-home-assistant/#reliable%2C-robust-and-without-drama&quot; aria-labelledby=&quot;reliable%2C-robust-and-without-drama&quot;&gt;#&lt;/a&gt;&lt;p&gt;After some market research, we decided to proceed with a commercial product and installed a &lt;a href=&quot;https://www.hunterindustries.com/irrigation-product/controllers/pro-hc&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hunter Hydrawise Pro-HC 6&lt;/a&gt; in 2020. We have the outdoor version, installed at the back of our carport and currently use 4 watering zones:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;complete lawn sprinklers&lt;/li&gt;
&lt;li&gt;plants back yard&lt;/li&gt;
&lt;li&gt;plants front yard&lt;/li&gt;
&lt;li&gt;cypress hedge&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To distribute water to the sprinklers and for watering plants, 3/4-inch pipes are used. For the plants we already had a &lt;a href=&quot;https://www.gardena.com/int/products/watering/micro-drip/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Gardena drip system&lt;/a&gt; installed. But we had to control this manually and always connect a garden hose. That is now a thing of the past. The drip system could be connected without any problems to the solenoid valves. The hedge is easily hydrated via some drip hose, which is connected to its own solenoid valve as well.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/hunterhydrawise.jpg&quot; alt=&quot;Hunter Hydrawise&quot; title=&quot;Hunter Hydrawise controller in our garden house&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Hunter Hydrawise controller in our garden house&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The Hydrawise Pro-HC 6 can handle 6 independent zones, so there is some reserve capacity for later. The same controller is also available with 12 or 24 valve stations. We also connected a rain sensor to automatically suspend the irrigation as soon as the moisture limit is reached.&lt;/p&gt;
&lt;p&gt;I know there are other commercial or open source based solutions and &lt;a href=&quot;https://community.home-assistant.io/search?expanded=true&amp;amp;q=irrigation%20%23projects&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DIY irrigation controller projects&lt;/a&gt; but I’m pretty happy with our choice. The Hydrawise Pro-HC in combination with the Hunter solenoid valves is super solid. So far I have had no issues with the Hydrawise controller at all. It simply does the job. Once the zones and schedules are programmed there is no need to touch the system anymore. All this setup can be done with the Hydrawise App. The device also has a small touch display which I really don’t use much. Only during the initial setup and 2-3 times a year if I manually switch a zone but don’t have my mobile around.&lt;/p&gt;
&lt;p&gt;The Hunter valves work without any problems. They survived two frosty winters without suffering any damage from the long days with minus degrees.&lt;/p&gt;
&lt;h2 id=&quot;hydrawise-%26-home-assistant&quot;&gt;Hydrawise &amp;amp; Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/green-grass-with-home-assistant/#hydrawise-%26-home-assistant&quot; aria-labelledby=&quot;hydrawise-%26-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;To start the irrigation we need water from our water tank and this is where &lt;a href=&quot;https://www.home-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt; comes into the picture.&lt;/p&gt;
&lt;p&gt;As mentioned above, our water tank supplies the entire garden with water. To get water into all the pipes we have a normal pump. This pump must be manually turned on/off when the scheduled irrigation programs start or end. The Hydrawise Pro-HC 6 actually has 7 valve controls, one additional for the main valve. This one is automatically switched with every zone value switched on or off. But since our 10-year-old pump has no automatic on/off control, it must be operated manually. The main valve will not work here.&lt;/p&gt;
&lt;p&gt;However, there is a super simple alternative … we already have a smart home automation system, right? Can we use Home Assistant for that? Yes, we can.&lt;/p&gt;
&lt;p&gt;Home Assistant has an &lt;a href=&quot;https://www.home-assistant.io/integrations/hydrawise/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;integration for Hunter Hydrawise&lt;/a&gt; and we can make use of that. It provides sensors &amp;amp; binary sensors for each zone, valve states, current watering time and schedule programs.&lt;/p&gt;
&lt;p&gt;With a simple automation triggered by every valve change we can control our main pump:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Switch on/of water tank pump on when Hydrawise irrigation programs trigger.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 493a7766&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;2d4f&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4f11&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;a80d&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;413d02f2498e
&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Watertank] Pump operation controller&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; binary_sensor.rasen_watering
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; binary_sensor.vorgarten_watering
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; binary_sensor.beete_watering
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; binary_sensor.hecke_watering
&lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; parallel
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;choose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
         &lt;span class=&quot;token key atrule&quot;&gt;value_template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;false&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;sequence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_on
         &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_pump
       &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notify.mobile_app_iphone
         &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 🚰
          &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Bewässerung wurde eingeschaltet.
          &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
           &lt;span class=&quot;token key atrule&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notification&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;irrigation
   &lt;span class=&quot;token key atrule&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_off
      &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_pump
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notify.mobile_app_iphone
      &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 🚰
       &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Bewässerung wurde ausgeschaltet.
       &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notification&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;irrigation&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also created a handy dashboard in Home Assistant which shows me the running irrigation program and the next scheduled watering times. Additionally, it shows how much water we have in our tank and how the pump is performing.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/watering-dashboard.png&quot; alt=&quot;Watering Dashboard Home Assistant&quot; title=&quot;Garden watering dashboard in Home Assistant&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Garden watering dashboard in Home Assistant&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;(free)-re-fill&quot;&gt;(free) re-fill&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/green-grass-with-home-assistant/#(free)-re-fill&quot; aria-labelledby=&quot;(free)-re-fill&quot;&gt;#&lt;/a&gt;&lt;p&gt;As explained earlier, we get all the irrigation water from the water tank. Our cistern isn’t super large only 5.500 litres. Depending on how often we water and which zones we water, this can run out in 2-3 weeks already.&lt;/p&gt;
&lt;p&gt;So … what happens if we haven’t had any rain for several weeks and the tank is empty?&lt;/p&gt;
&lt;p&gt;To solve that problem I built a simple but robust DIY re-fill system. First challenge: how to get fresh water into the tank? Our cistern is connected to the gutters of the house and the carport. Rainwater is collected and guided into the tank already. This is the free re-fill we get. So a pipe was already there let’s use that. I connected the outside water faucet to the gutter with a garden hose via a solenoid valve. When the valve is opened, water flows directly into the cistern. That is it, as simple as that.&lt;/p&gt;
&lt;p&gt;The solenoid valve is connected via some Sonoff socket which can be controlled via Home Assistant. With a simple automation and the water level data from our &lt;a href=&quot;https://markus-haack.com/watertank-esphome/&quot;&gt;ESPHome sensor from part 1&lt;/a&gt; we can start a refill if we are running out of water.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Controll the refill mechanism for the watertank.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# If the water tank is below 2500 liter it will be refilled&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# via the mains water supply for one hour. This should add ~ 1.400 liter.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# To not irritate the leak detection the refill is paused every 20 min.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 86e7306b&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;00ae&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4773&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;9af8&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;595a1a748858
&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Watertank] Automatic Refill&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; numeric_state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sensor.garden_watertank_liter
   &lt;span class=&quot;token key atrule&quot;&gt;below&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2500&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;# first run&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_refill
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;20:00&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_off
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_refill

 &lt;span class=&quot;token comment&quot;&gt;# second run&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;1:00&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_refill
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;20:00&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_off
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_refill

 &lt;span class=&quot;token comment&quot;&gt;# third run&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;1:00&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_refill
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;20:00&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.turn_off
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.garden_watertank_refill&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Automation appears to be more complicated than it actually is. If we run below 2.500 litres, it starts the refill. It runs for one hour but at 20-minute intervals. This is in our case needed because our domestic water connection has a leak detection system. If an excessive flow or too long water consumption is detected the main tap is blocked. This has to be unblocked manually. To avoid this we simply add some pauses to the automation.&lt;/p&gt;
&lt;p&gt;My automation does not consider weather or rain forecasts. With the low flow rate of our outside faucet we get ~1.400 litre of water filled into the tank within one hour. There is enough capacity left if it starts raining a little later.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/sprinkler.jpg&quot; alt=&quot;Some sprinkler&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/green-grass-with-home-assistant/#summary&quot; aria-labelledby=&quot;summary&quot;&gt;#&lt;/a&gt;&lt;p&gt;Overall I’m very happy with my setup. I finally got the water tank sensor to work with ESPHome after tinkering around with it. The watering controller does a solid job and Home Assistant controlled refill works smooth.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Water tank monitoring with ESPHome</title>
    <link href="https://markus-haack.com/watertank-esphome/"/>
    <updated>2022-04-02T00:00:00Z</updated>
    <id>https://markus-haack.com/watertank-esphome/</id>
    <content type="html">&lt;p&gt;Watering your lawn and plants around the house wasn’t one of my favourite things to do. Especially when we bought a robot lawnmower, watering the lawn became quite a hassle since we had to always put away the sprinklers and hoses after each irrigation.&lt;/p&gt;
&lt;p&gt;An automatic irrigation system was needed. Inspired by &lt;a href=&quot;https://community.home-assistant.io/t/garden-irrigation/1950&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this thread&lt;/a&gt; on the HA Community I started looking into building a DIY solution. Which includes controlling the individual irrigation zones, monitoring the water level of the cistern and, if necessary, automatically filling the cistern. We end up with a mixed setup using a Hunter Hydrawise as the irrigation controller and a custom-made solution to monitor and refill the water tank.&lt;/p&gt;
&lt;p&gt;I’m splitting this into two posts. Part 1 is about the &lt;a href=&quot;https://esphome.io/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome&lt;/a&gt; solution to monitor the water level of our garden cistern. &lt;a href=&quot;https://markus-haack.com/green-grass-with-home-assistant/&quot;&gt;Part 2&lt;/a&gt; will cover the Home Assistant integration of Hydrawise, valves, the ESPHome water tank sensor and automations for the entire garden irrigation setup.&lt;/p&gt;
&lt;p&gt;The cistern plays a central role in our garden irrigation. Since the pump can deliver a higher pressure than the house water connection, the entire system is connected to it. For us, no water in the cistern means no watering of the plants or the lawn.&lt;/p&gt;
&lt;h2 id=&quot;a-few-tries-to-get-it-right&quot;&gt;A few tries to get it right&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/watertank-esphome/#a-few-tries-to-get-it-right&quot; aria-labelledby=&quot;a-few-tries-to-get-it-right&quot;&gt;#&lt;/a&gt;&lt;p&gt;I’ve been working for quite a while on a simple &amp;amp; reliable monitoring solution for our garden cistern. Today’s ESPHome base solution is the 3rd and most stable iteration.&lt;/p&gt;
&lt;p&gt;The way the sensor works is very simple. The ultrasonic sensor is mounted inside the cistern above the water. It measures the distance to the water surface. The higher the water level, the smaller the distance between the water and the sensor. When we consume water, the water surface sinks and the distance increases. If it rains or we manually refill the cistern, the distance decreases again. I measured the full and empty levels of our cistern and can interpolate the intermediates. Using a volume formula, I can convert the distance (in cm) to litres.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/cistern.jpg&quot; alt=&quot;schematic drawing cistern&quot; title=&quot;Schematic drawing of our cistern with pump and sensor placement&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Schematic drawing of our cistern with pump and sensor placement&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This concept is still used for the current version of the water level sensor.&lt;/p&gt;
&lt;p&gt;The first version of my cistern water level sensor consisted of a &lt;a href=&quot;https://store.particle.io/collections/gen-2/products/photon&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;particle.io Photon&lt;/a&gt; microcontroller chip, a HC-SR04 ultrasonic sensor, a rechargeable battery incl. charging controller, all together in a waterproof enclosure. I was already familiar with Arduino microcontrollers, so programming the Photon chip was not a problem. The initial version of the source code is available &lt;a href=&quot;https://github.com/mhaack/Photon-WaterTank-Monitor/blob/master/src/Photon-WaterTank-Monitor.ino&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt;. Looks super complicated because of the extra logic for average measurement calculation, deep sleep mode and sending the values to MQTT and the &lt;a href=&quot;http://particle.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;particle.io&lt;/a&gt; cloud in parallel.&lt;/p&gt;
&lt;p&gt;The two main problems of this setup were the Wifi connectivity and the battery management. Since the cistern is completely underground and made of reinforced concrete there is no good wifi coverage inside. Getting a wifi connection required usually 3-5 retries. This drained the battery a lot. To get a long battery life I put the Photon chip into sleep mode most of the time. It took a distance reading every 15 minutes, compared it with the previous measurement and only connected to wifi to send and update if there are any changes. This could mean I did not get an updated measurement for some days and could not be sure that the battery was still charged.&lt;/p&gt;
&lt;p&gt;The second iteration was also based on the Photon microcontroller chip. But this time I split the hardware into two units. The sensor box was still inside the water tank. In fact, the microcontroller was now outside, connected to a sensor via cables, and powered by a USB adapter permanently. This setup had way better reliability and no wifi connection problems.&lt;/p&gt;
&lt;p&gt;Unfortunately, the HC-SR04 ultrasonic sensor still caused problems. It is simply not made to be placed in a cistern with permanent moisture around.&lt;/p&gt;
&lt;h2 id=&quot;all-good-things-come-in-three&quot;&gt;All good things come in three&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/watertank-esphome/#all-good-things-come-in-three&quot; aria-labelledby=&quot;all-good-things-come-in-three&quot;&gt;#&lt;/a&gt;&lt;p&gt;After two HC-SR04 ultrasonic sensors died because of corrosion, I began looking for an alternative. For the third and hopefully the final version of the water tank sensor two changes has been implemented:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the sensor device got a waterproof upgrade to a JSN SR04T ultrasonic sensor&lt;/li&gt;
&lt;li&gt;the microcontroller was changed to an ESP8266 based Wemos D1 mini pro running ESPHome&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So far the JSN SR04T ultrasonic sensor is pretty reliable. The setup has been running super stable for more than a year now.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/microcontroller-watertank.jpg&quot; alt=&quot;microcontroller watertank sensor&quot; title=&quot;Photo of Wemo D1 microcontroller&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Photo of Wemo D1 microcontroller&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The hardware setup for the water tank sensor is simple. JSN SR04T is connected via the helper module to the Wemos D1 mini microcontroller. Only 4 pins are required: 5V, GND, Trigger pin and echo pin.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/watertank_steckplatine.png&quot; alt=&quot;fritzing diagram of water tank sensor setup&quot; title=&quot;Wiring  diagram of water tank sensor setup&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Wiring  diagram of water tank sensor setup&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;No further electronic components are required. The setup is powered by a USB power adapter.&lt;/p&gt;
&lt;h2 id=&quot;watertank-sensor.yaml&quot;&gt;watertank-sensor.yaml&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/watertank-esphome/#watertank-sensor.yaml&quot; aria-labelledby=&quot;watertank-sensor.yaml&quot;&gt;#&lt;/a&gt;&lt;p&gt;If you are not familiar with ESPHome getting started is not complicated, especially if you already use Home Assistant and the &lt;a href=&quot;https://esphome.io/guides/getting_started_hassio.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;step-by-step install guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The ESPHome configuration for the water tank sensor is relatively simple. Only 80 lines of YAML config … and these already include the setup boilerplate and some comments.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;esphome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; watertank
 &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ESP8266
 &lt;span class=&quot;token key atrule&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; d1_mini_pro

&lt;span class=&quot;token key atrule&quot;&gt;wifi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;ssid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!secret&lt;/span&gt; esphome_wifi_ssid
 &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!secret&lt;/span&gt; esphome_wifi_password

 &lt;span class=&quot;token key atrule&quot;&gt;ap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;ssid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; esp01

&lt;span class=&quot;token key atrule&quot;&gt;captive_portal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!secret&lt;/span&gt; esphome_api_password

&lt;span class=&quot;token key atrule&quot;&gt;ota&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!secret&lt;/span&gt; esphome_ota_password

&lt;span class=&quot;token key atrule&quot;&gt;sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;# Wifi signal sensor.&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; wifi_signal
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_wifi
   &lt;span class=&quot;token key atrule&quot;&gt;update_interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 600s
   &lt;span class=&quot;token key atrule&quot;&gt;unit_of_measurement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;%&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;
       if (x &amp;lt;= &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;100) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         return 0;
       &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; else &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         if (x &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;= &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;50) &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
           return 100;
         &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; else &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
           return 2 * (x + 100);
         &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
       &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;token comment&quot;&gt;# Templates for calculated liter &amp;amp; percent&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_liter
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_liter
   &lt;span class=&quot;token key atrule&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mdi:water&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;unit_of_measurement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;l&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;accuracy_decimals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; template
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_percent
   &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_percent
   &lt;span class=&quot;token key atrule&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mdi:water-percent&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;unit_of_measurement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;%&#39;&lt;/span&gt;

 &lt;span class=&quot;token comment&quot;&gt;# The actual distance sensor&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ultrasonic
   &lt;span class=&quot;token key atrule&quot;&gt;trigger_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D1
   &lt;span class=&quot;token key atrule&quot;&gt;echo_pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; D2
   &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_distance
   &lt;span class=&quot;token key atrule&quot;&gt;update_interval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 600s
   &lt;span class=&quot;token key atrule&quot;&gt;pulse_time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50us
   &lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;filter_out&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nan
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;median&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;window_size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;send_every&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;send_first_at&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;calibrate_linear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 0.23 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; 1.86
       &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 2.41 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; 0.0
   &lt;span class=&quot;token key atrule&quot;&gt;on_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;sensor.template.publish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_liter
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return x * 3141.592653589793238;&#39;&lt;/span&gt;

     &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;sensor.template.publish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; garden_watertank_percent
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!lambda&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;return x * 53.979255216319471;&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The most crucial parts of the code config start in line 56 with the setup of the &lt;a href=&quot;https://esphome.io/components/sensor/ultrasonic.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ultrasonic sensor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I decided to send updated measurements every 10 minutes only. The water level does not vary that much during most of the year, so there are few updates. But if we consume water quickly and there is heavy rain filling the cistern the 10 minutes interval still results in a smooth graph.&lt;/p&gt;
&lt;p&gt;All sensor readings returned by &lt;code&gt;platform: ultrasonic&lt;/code&gt; are in meter. This is important for the formulas. Values you put in the formula must be in meters too.&lt;/p&gt;
&lt;p&gt;The measuring and calculation of litre and percent happens in two steps. In a first step some filters are applied to the measured distance values to filter out invalid readings and get a smooth median value. All sensor values are in meters, conversion to inches require some extra conversion step.&lt;/p&gt;
&lt;p&gt;Since the sensor measures the distance between sensor and water surface it must be transformed into the actual height of the water within our cistern. This happens via &lt;code&gt;calibrate_linear&lt;/code&gt; filter. It is used to adjusted and map the sensor values. This filter must be adjusted for your water tank. You need the sensor readings for a full and empty water tank. In my case the sensor is placed 0,23 meter above the water level which translates to 1,86 meter high water level from the ground of the tank. For an empty tank I get 2,41 meter as reading from the sensor. Have in mind that the filter, as the name &lt;code&gt;calibrate_linear&lt;/code&gt; says does a linear value mapping, see &lt;a href=&quot;https://esphome.io/components/sensor/index.html?highlight=calibrate_linear#calibrate-linear&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;docs for details&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The values for litre and percent are calculated based on the water height using two lambda functions. The magic factors in the formulas are multiplied out factors for volume of our cistern.&lt;/p&gt;
&lt;p&gt;In our case the cistern is a round cylinder, the volume formula for that is:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;V &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; π * radius² * height&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;code&gt;height = x&lt;/code&gt; in the lambda function. The diameter of the cistern is exactly 2 meters, hence a radius of 1 meter. To formula for me is &lt;code&gt;π * 1² * x&lt;/code&gt; which will return the volume in square meters. That multiplied by 1000 results in the returned value in litres.&lt;/p&gt;
&lt;p&gt;The percentage calculation is similar. It is based on the max volume of your cistern, 5.500 litre in our case.&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; π * radius² * height * &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; / max litre * &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;is-it-accurate%3F&quot;&gt;Is it accurate?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/watertank-esphome/#is-it-accurate%3F&quot; aria-labelledby=&quot;is-it-accurate%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;The way the sensor works it cannot be super accurate and it is not really important for our use case but let’s check. I’m comparing the measurements with an older flow meter I had lying around:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/bildschirmfoto-2022-06-02-um-11.32.png&quot; alt=&quot;Compare ESPHome sensor &amp; flow meter&quot; title=&quot;Compare watering sensor data with flow meter&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Compare watering sensor data with flow meter&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The readings from the distance sensor are in centimetres. The minimum change it recognizes is 1cm. If we put that into our formula (in meters) &lt;code&gt;π * 1² * 0,01&lt;/code&gt; we get 0,03141m³ which is ~ 31 litre. That is the minimum accuracy we can get.&lt;/p&gt;
&lt;h2 id=&quot;into-home-assistant&quot;&gt;Into Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/watertank-esphome/#into-home-assistant&quot; aria-labelledby=&quot;into-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;To use the water tank sensor in Home Assistant I use the &lt;a href=&quot;https://www.home-assistant.io/integrations/esphome/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESPHome integration&lt;/a&gt;. Setup is super easy via the UI and all exposed sensor data from the ESPHome sketch is automatically available in Home Assistant.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/screenshot_esphome_integration.png&quot; alt=&quot;Screenshot ESPHome integration&quot; title=&quot;Screenshot of ESPHome sensor in Home Assistant&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;figcaption&gt;Screenshot of ESPHome sensor in Home Assistant&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://markus-haack.com/green-grass-with-home-assistant/&quot;&gt;next post&lt;/a&gt; I will explain how the water tank data of the ESPHome sensor is used in Home Assistant. The automations I have set up to control the water tank pump &amp;amp; Hydrawise irrigation controller for the garden and lawn watering.&lt;/p&gt;
&lt;p&gt;Hero image photo by &lt;a href=&quot;https://unsplash.com/@danielvandenberg&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Daniel van den Berg&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/watertank&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Arlo Cameras in Home Assistant</title>
    <link href="https://markus-haack.com/arlo-cameras-in-home-assistant/"/>
    <updated>2022-03-14T00:00:00Z</updated>
    <id>https://markus-haack.com/arlo-cameras-in-home-assistant/</id>
    <content type="html">&lt;p&gt;Home Assistant &amp;amp; Arlo cameras go better together than I initially expected. I’m using it since our entire setup got migrated from OpenHab to Home Assistant and I’m happy with the setup.&lt;/p&gt;
&lt;p&gt;But let’s start from the beginning …&lt;/p&gt;
&lt;h2 id=&quot;how-it-started&quot;&gt;How it started&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#how-it-started&quot; aria-labelledby=&quot;how-it-started&quot;&gt;#&lt;/a&gt;&lt;p&gt;In 2016 I tough about the topic of home surveillance for the first time. I was looking for a camera system that could operate on batteries. I have identified two places at our house where I would like to mount a camera but where there is no electricity or wired network available.&lt;/p&gt;
&lt;p&gt;The first time I became aware of Arlo was mid 2016. Back then it was a brand of Netgear, later in 2018 it became its own company Arlo Technologies.&lt;/p&gt;
&lt;p&gt;After some quick market research it turned out I didn’t have many options. At that time there was not a wide range of waterproof outdoor cameras available. Unlike today Ring, Reolink, Wyze or Nest cameras didn’t even exist at the time, at least not in Europe.&lt;/p&gt;
&lt;p&gt;So Arlo cameras became my first choice and still are today. The initial setup for our home consists of the hub and 2 Arlo cameras - the original version. Later I added a third one.&lt;/p&gt;
&lt;p&gt;Arlo cameras, at least if operated solely on batteries, are mostly passive. They only record if someone or something moves. The built-in motion sensor recognises movement and triggers the recording. This helps to optimise for a longer battery life. The initial camera version used replaceable batteries only. These used to last for ~3 months, depending how often the camera got activated.&lt;/p&gt;
&lt;p&gt;Later versions of the camera came with a rechargeable battery and could be charged without having to remove the battery. They also can get permanent power from a USB power adapter or charged by a solar panel.&lt;/p&gt;
&lt;p&gt;Today our setup consists of two Arlo Pro 2 and three Arlo Pro 3 cameras. When upgrading to the Pro 3 I also replaced the original hub with a new one. Most likely it will remain the same. We don’t need indoor cameras and other devices like a doorbell. Also the service plan I’m currently on, called “Arlo Smart Premier Multi Camera” only allows for up to 5 cameras. One of the cameras is operated with a permanent power connection and two got a solar panel installed. I only have to charge the battery regularly with two of the cameras which still run on battery power only.&lt;/p&gt;
&lt;h2 id=&quot;subscription-or-not&quot;&gt;Subscription or not&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#subscription-or-not&quot; aria-labelledby=&quot;subscription-or-not&quot;&gt;#&lt;/a&gt;&lt;p&gt;In my view an Arlo system can only be operated properly with a subscription plan - a paid subscription plan. The recordings and video history are stored in the cloud, which will result in storage and streaming costs.&lt;/p&gt;
&lt;p&gt;At the very beginning the initial subscription plans still included 7 day recording history stored in the cloud in the free plan. As of 2021, subscription plans changed, so one can only gain access to all features and store recording history on a paid subscription plan.&lt;/p&gt;
&lt;p&gt;It is possible to operate an Arlo setup with a “no plan” option. With this you only get live video streaming directly from the camera and basic notifications. It is also possible to store the recordings on a USB stick connected to the Arlo Hub. Overall the free no plan option is very limited. Many of the new features recently added require a paid subscription. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;person, vehicle, package and animal detection&lt;/li&gt;
&lt;li&gt;advanced push notifications&lt;/li&gt;
&lt;li&gt;activity zones and blind zones&lt;/li&gt;
&lt;li&gt;theft protection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For me, detecting people, animals, and cars works well. However, I can only really use it for the front door camera. We usually don’t have cars or buses in our garden. With advanced or rich push notifications you get a preview image embedded in the notification and you can directly start the video stream.&lt;br&gt;
Activity zones and blind zones are working ok but not perfect for our setup. They definitely require some tuning. I have defined a few blind spots but still, get alerts for motions in these zones from time to time.&lt;/p&gt;
&lt;p&gt;Arlo cameras have a decent price tag. A $249 camera plus pay for a subscription is a bold call. Arlo’s subscription plans are its biggest disadvantage. If you don’t want to pay monthly fees, Arlo isn’t for you and other vendors might be a better fit.&lt;/p&gt;
&lt;h2 id=&quot;arlo-%26-home-assistant&quot;&gt;Arlo &amp;amp; Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#arlo-%26-home-assistant&quot; aria-labelledby=&quot;arlo-%26-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;One reason, among others, to switch from &lt;a href=&quot;https://markus-haack.com/home-assistant/&quot;&gt;OpenHab to Home Assistant&lt;/a&gt; for me was the missing integration with the Arlo system. And looking back on it, the Arlo &amp;amp; Home Assistant integration was a little challenge at the beginning. Home Assistant comes with an &lt;a href=&quot;https://www.home-assistant.io/integrations/arlo/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Arlo integration&lt;/a&gt; out of the box. Unfortunately, it looks like it does not get much attention and love. It has had only a few updates lately, mostly catching up with changes in Home Assistant.&lt;/p&gt;
&lt;p&gt;Luckily for us, there is an alternative: &lt;a href=&quot;https://github.com/twrecked/hass-aarlo&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;aarlo&lt;/a&gt; - Asynchronous Arlo. It can be used as a replacement original Arlo component and is actively maintained. I work with all Arlo devices, including cameras, base stations, sirens, doorbells, and lights.&lt;/p&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#installation&quot; aria-labelledby=&quot;installation&quot;&gt;#&lt;/a&gt;&lt;p&gt;Since AArlo is a custom component it must be installed separately. The easiest way to do this is using HACS. AArlo is part of the default HACS store.&lt;/p&gt;
&lt;p&gt;Once downloaded the config is like:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;aarlo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token key atrule&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!secret&lt;/span&gt; arlo_username
 &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;!secret&lt;/span&gt; arlo_password&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to play with the lasted, unreleased code a manual deployment, directly from GitHub is possible as well.&lt;/p&gt;
&lt;h3 id=&quot;creating-a-login&quot;&gt;Creating a Login&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#creating-a-login&quot; aria-labelledby=&quot;creating-a-login&quot;&gt;#&lt;/a&gt;&lt;p&gt;The setup in Home Assistant is pretty simple. For the default setup you provided an Arlo username and password. It is highly recommended to create a dedicated Arlo user account for Home Assistant. Don’t use your main login you use on your phone. Otherwise, you will constantly get logged out, looks like Arlo does only accept one login for a user at a time.&lt;/p&gt;
&lt;p&gt;If you have &lt;a href=&quot;https://github.com/twrecked/hass-aarlo#2fa&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Arlo 2FA enabled&lt;/a&gt; enabled - which should be standard nowadays, some extra config steps are needed. Make sure you configure with the correct 2FA method - IMAP or PUSH - for your Arlo account.&lt;/p&gt;
&lt;h3 id=&quot;component-configuration&quot;&gt;Component Configuration&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#component-configuration&quot; aria-labelledby=&quot;component-configuration&quot;&gt;#&lt;/a&gt;&lt;p&gt;After creating the Arlo login you can continue to set up the components. We get many different components and sensors with the AArlo integration. Some of them depend on the devices you own and also on the subscription plan.&lt;/p&gt;
&lt;p&gt;In my setup, I use the camera component as an obvious part of a camera surveillance solution, along with the alarm component and some sensors. The configuration and how it is used in my setup is described below.&lt;/p&gt;
&lt;p&gt;Additionally, AArlo provides a comprehensive collection of sensors, binary sensors, switches and lights and media_player for your Arlo devices. For these check the documentation on Github:&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;twrecked/hass-aarlo&quot; label=&quot;hass-aarlo project on GitHub&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;First and most important the camera:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;camera&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; aarlo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is all you need, AArlo will create a &lt;code&gt;camera.aarlo_xyz&lt;/code&gt; entity for each Arlo camera in your account. The naming pattern for all entities created by AArlo is &lt;code&gt;component-type.aarlo lowercase name with underscores&lt;/code&gt;. Sensors will use the same naming convention as well.&lt;/p&gt;
&lt;p&gt;AArlo is very verbose cameras and sensors have a lot of detailed information and attributes. All camera &amp;amp; device details, configuration information, battery &amp;amp; charging details, environment sensors and last recordings and image snapshots are available.&lt;/p&gt;
&lt;p&gt;The following Home Assistant &lt;a href=&quot;https://github.com/twrecked/hass-aarlo#sensor-configuration&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;sensors&lt;/a&gt; are available:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;sensor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; aarlo
   &lt;span class=&quot;token key atrule&quot;&gt;monitored_conditions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; total_cameras
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; last_capture
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; recent_activity
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; captured_today
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; battery_level
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; signal_strength
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; temperature
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; humidity
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; air_quality&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While &lt;code&gt;total_cameras&lt;/code&gt; is a global sensor showing the number of configured devices all other sensors are created for each device. Not all sensors will be available for all devices, for example, my cameras (Pro 2 &amp;amp; 3) don’t provide temperature, humidity or air quality information.&lt;/p&gt;
&lt;p&gt;Especially &lt;code&gt;last_capture&lt;/code&gt; is interesting here, it provides many details on the last recording. The sensor includes &lt;code&gt;thumbnail_url&lt;/code&gt; &amp;amp; &lt;code&gt;video_url&lt;/code&gt; containing the secure URL to directly to the thumbnail and video recording on the cloud servers. This is very handy if you want to use that for some automations. If smart object detection is set up this sensor has two additional attributes. &lt;code&gt;object_type&lt;/code&gt; contains the detected object like “person” or “vehicle” and &lt;code&gt;object_region&lt;/code&gt; has the rectangle coordinates of the detected object within the image.&lt;/p&gt;
&lt;h3 id=&quot;camera-services&quot;&gt;Camera Services&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#camera-services&quot; aria-labelledby=&quot;camera-services&quot;&gt;#&lt;/a&gt;&lt;p&gt;The AArlo component provides a set of Home Assistant &lt;a href=&quot;https://github.com/twrecked/hass-aarlo#services&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;services&lt;/a&gt; to control the cameras, set the alarm modes or trigger alarms.&lt;/p&gt;
&lt;p&gt;I mainly use them to start a recording (&lt;code&gt;aarlo.camera_start_recording&lt;/code&gt;) or request an image snapshot (&lt;code&gt;aarlo.camera_request_snapshot&lt;/code&gt;) within automations.&lt;/p&gt;
&lt;h3 id=&quot;custom-lovelace-card&quot;&gt;Custom Lovelace Card&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#custom-lovelace-card&quot; aria-labelledby=&quot;custom-lovelace-card&quot;&gt;#&lt;/a&gt;&lt;p&gt;Additionally, AArlo also comes with a nice custom lovelace card. The card is optional, the standard &lt;code&gt;picture-glance&lt;/code&gt; or other cards can be used as well. I like that card very much because it has a bunch of extra functions tightly integrated with AArlo.&lt;/p&gt;
&lt;p&gt;It has very powerful options for individual setups, can be configured for one or multiple cameras and allows direct access to the camera library recordings. Users can directly interact with the cameras to start recording, stream live video, or take a snapshot.&lt;/p&gt;
&lt;p&gt;My usage of the cart is pretty standard:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;custom:aarlo-glance&#39;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; camera.aarlo_pool
  &lt;span class=&quot;token key atrule&quot;&gt;image_top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; name
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; date
  &lt;span class=&quot;token key atrule&quot;&gt;image_bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; motion
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; library
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; stream
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; snapshot
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; battery&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/arlo_ha_camera.png&quot; alt=&quot;Arlo camera view&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The library view looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/arlo_ha_library.png&quot; alt=&quot;Arlo library view&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;Notice the rectangles for the detected persons or animals.&lt;/p&gt;
&lt;p&gt;Additional details on motion and sound notification sensors can be displayed as well. For doorbells, the card provides extra functionality like door opening notifications.&lt;/p&gt;
&lt;h2 id=&quot;a-good-combination&quot;&gt;A good combination&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/arlo-cameras-in-home-assistant/#a-good-combination&quot; aria-labelledby=&quot;a-good-combination&quot;&gt;#&lt;/a&gt;&lt;p&gt;For my situation the Arlo &amp;amp; Home Assistant combination is a good fit. Using them together gives me a solid security camera solution that I can use with the automation power of Home Assistant.&lt;/p&gt;
&lt;p&gt;Yes, they are expensive, especially when we consider the subscription plan as well. I’ve been looking for alternatives time and time again in the past. I even ordered some Reolink and Blink, but all were returned back. Still, in 2022 there are not many reliable alternatives for battery-powered camera systems. I still recommend Arlo if battery power is a requirement.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Mia&#39;s Dino Facts</title>
    <link href="https://markus-haack.com/mias-dino-facts/"/>
    <updated>2022-02-06T00:00:00Z</updated>
    <id>https://markus-haack.com/mias-dino-facts/</id>
    <content type="html">&lt;p&gt;My daughter Mia is a huge dinosaur fan, almost a little dinosaur nerd. We are overwhelmed with information about dinosaurs every day. It starts during breakfast and doesn’t stop before she falls asleep 😉.&lt;/p&gt;
&lt;p&gt;She is super happy when she can share her dinosaur knowledge with someone. Then, between the Christmas holidays last year, we had the idea: how about sharing the Dino knowledge not only with family and friends but with the whole world.&lt;/p&gt;
&lt;p&gt;This was the birth of &lt;a href=&quot;https://dino-fakten.de/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;dino-fakten.de&lt;/a&gt; - her very first website.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dino-fakten.de/karte/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/dino-fakten-map.png&quot; alt=&quot;map with the localities of the different dinosaurs around the world&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;one-more-dinosaur-website&quot;&gt;One more dinosaur website&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mias-dino-facts/#one-more-dinosaur-website&quot; aria-labelledby=&quot;one-more-dinosaur-website&quot;&gt;#&lt;/a&gt;&lt;p&gt;Yes, there are plenty of sources of information about dinosaurs and some good websites about them, but why another?&lt;/p&gt;
&lt;p&gt;With her own website, Mia can present her personal dinosaur knowledge to the whole world. Formulated and processed as she imagines, her little 🦖 corner on the internet. The Dino Facts on her website are organized with what she calls “card”. Each dinosaur gets its own page with all the facts and details.&lt;/p&gt;
&lt;p&gt;Visitors can look at &lt;a href=&quot;https://dino-fakten.de/tags/lieblingsdino/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mia’s favourite dinosaurs&lt;/a&gt;, search for dinosaurs directly and recently I added a &lt;a href=&quot;https://dino-fakten.de/karte/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;map with the localities&lt;/a&gt; of the different dinosaurs around the world.&lt;/p&gt;
&lt;h2 id=&quot;some-technical-details&quot;&gt;Some technical details&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mias-dino-facts/#some-technical-details&quot; aria-labelledby=&quot;some-technical-details&quot;&gt;#&lt;/a&gt;&lt;p&gt;The website was built with &lt;a href=&quot;https://www.11ty.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eleventy&lt;/a&gt;, just like my own blog here. Since I’m not a web design professional, I just looked through the list of &lt;a href=&quot;https://www.11ty.dev/docs/starter/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eleventy starters&lt;/a&gt; with Mia. There we found &lt;a href=&quot;https://myonlinecookbook.xyz/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;My Online Cookbook&lt;/a&gt;, created by &lt;a href=&quot;https://www.maelbrunet.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Maël Brunet&lt;/a&gt;. Actually, as the name suggests, it is made for online cookbooks and recipes. Mia liked it and so we repurposed it a bit.&lt;/p&gt;
&lt;p&gt;The starter template was already prepared to work with &lt;a href=&quot;https://www.netlifycms.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Netlify CMS&lt;/a&gt; - a simple CMS UI built on top of markdown files in a Git repository. This was super helpful for us. I didn’t want my daughter learning and playing around with Markdown files. A mini CMS is exactly the right thing here. She was able to start and enter dino content while I was still working on the website. Meanwhile, after getting used to the editor, markdown is no longer a problem either. I’ve observed her every now and then she switches from rich text editor to markdown to type in her dinosaur descriptions.&lt;/p&gt;
&lt;p&gt;On the technical side of things, the template was built around &lt;a href=&quot;https://sass-lang.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SASS&lt;/a&gt; for CSS processing and &lt;a href=&quot;https://alpinejs.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Alpine.JS&lt;/a&gt; for interactions, such as search, on the website. This was a good foundation for the world map I added using the &lt;a href=&quot;http://datamaps.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DataMaps&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;The site itself is now hosted on &lt;a href=&quot;https://www.netlify.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Netlify&lt;/a&gt;, with the domain managed by &lt;a href=&quot;https://all-inkl.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;all-inkl.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The source code of the site is available on GitHub:&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/mias-dino-facts&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-next%3F&quot;&gt;What is next?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mias-dino-facts/#what-is-next%3F&quot; aria-labelledby=&quot;what-is-next%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;With the site online and the CMS setup, the main technical work is done. I leave the responsibility for the website more and more to Mia. She created fact sheets for 25 dinosaurs and is constantly adding more every week.&lt;br&gt;
She also already has some other content ideas: dinosaurs in Minecraft (her other hobby) or report about our trips to dino parks.&lt;/p&gt;
&lt;p&gt;And my favourite dinosaur … that is the &lt;a href=&quot;https://dino-fakten.de/dinos/triceratops/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Triceratops&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Website History</title>
    <link href="https://markus-haack.com/website-history/"/>
    <updated>2022-01-20T00:00:00Z</updated>
    <id>https://markus-haack.com/website-history/</id>
    <content type="html">&lt;p&gt;In this post I will briefly describe my personal website’s history. It started in 1998. At this point, I have already gone through six iterations. I had already completely forgotten two of them.&lt;/p&gt;
&lt;p&gt;My personal blog is built around simple HTML and CSS. There’s no need for much javascript on the site - something I got sorted out over time. The site also become a bit of a playground.&lt;/p&gt;
&lt;p&gt;Described here is a brief explanation of the evolution steps and the tools and technologies behind each version.&lt;/p&gt;
&lt;h2 id=&quot;v1---geocities&quot;&gt;V1 - Geocities&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/website-history/#v1---geocities&quot; aria-labelledby=&quot;v1---geocities&quot;&gt;#&lt;/a&gt;&lt;p&gt;On May 1st, 1998 the first version of my personal website was put online on &lt;a href=&quot;https://en.wikipedia.org/wiki/Yahoo!_GeoCities&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Geocities&lt;/a&gt;. Geocities does not exist anymore nor does my own website, the old URL is not available anymore.&lt;/p&gt;
&lt;p&gt;I don’t even remember exactly what the site was about and what content I put there.&lt;/p&gt;
&lt;h2 id=&quot;v2---www.markus-haack.de&quot;&gt;V2 - &lt;a href=&quot;http://www.markus-haack.de&quot;&gt;www.markus-haack.de&lt;/a&gt;&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/website-history/#v2---www.markus-haack.de&quot; aria-labelledby=&quot;v2---www.markus-haack.de&quot;&gt;#&lt;/a&gt;&lt;p&gt;On December 12th, 1999 I registered my first domain &lt;a href=&quot;http://markus-haack.de&quot;&gt;markus-haack.de&lt;/a&gt; at &lt;a href=&quot;http://www.netbeat.de/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NetBeat&lt;/a&gt;. Initially, it was just a HTML &lt;a href=&quot;https://www.w3schools.com/tags/tag_frameset.asp&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;frameset&lt;/a&gt; embedding the Geocities site. “frameset” is not used anymore these days, it was only available till HTML 4.&lt;/p&gt;
&lt;p&gt;A few weeks later I rebuild the site with &lt;a href=&quot;https://www.adobe.com/products/dreamweaver.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Dreamweaver&lt;/a&gt;, all static HTML with some basic CSS and Javascript. It was the first time I dipped my toe in the cold water of web development.&lt;/p&gt;
&lt;h2 id=&quot;v3---blogger.com&quot;&gt;V3 - &lt;a href=&quot;http://blogger.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;blogger.com&lt;/a&gt;&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/website-history/#v3---blogger.com&quot; aria-labelledby=&quot;v3---blogger.com&quot;&gt;#&lt;/a&gt;&lt;p&gt;In October 2004, after the site was in deep sleep for a while, the first blog “Klasse Kaffee” was launched on &lt;a href=&quot;http://blogger.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;blogger.com&lt;/a&gt; platform. And I started posting more frequently.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/website-1.jpeg&quot; alt=&quot;Screenshot of Klasse Kaffee from 2005&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;v4---wordpress&quot;&gt;V4 - Wordpress&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/website-history/#v4---wordpress&quot; aria-labelledby=&quot;v4---wordpress&quot;&gt;#&lt;/a&gt;&lt;p&gt;On 19. December 2005 I announced the move of “Klasse Kaffee” to my own hosted space. This was the time at which I gained my first experience with Wordpress 1. The initial theme of the site was called MX4. In 2006 the site was upgraded to Wordpress 2.0. Also, this version is available in the &lt;a href=&quot;https://web.archive.org/web/20120416105640/http://haagi.de/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Internet Archive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I blogged regularly until 2010, after which I lost interest a little.&lt;/p&gt;
&lt;h2 id=&quot;v5---gatsby&quot;&gt;V5 - Gatsby&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/website-history/#v5---gatsby&quot; aria-labelledby=&quot;v5---gatsby&quot;&gt;#&lt;/a&gt;&lt;p&gt;How the time flies … In 2019, 9 years later, I reactivated the domain and started blocking again. It was a fresh start. The entire site was rebuilt with &lt;a href=&quot;https://reactjs.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;React&lt;/a&gt; from scratch using &lt;a href=&quot;https://www.gatsbyjs.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Gatsby&lt;/a&gt; using the &lt;a href=&quot;https://github.com/codebushi/gatsby-starter-stellar&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Stellar&lt;/a&gt; theme. A snapshot is still available in the &lt;a href=&quot;https://web.archive.org/web/20190108060741/https://www.markus-haack.com/&quot;&gt;Internet Archive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/website-2.jpeg&quot; alt=&quot;Screenshot of my website from 2019&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The redesigned blog also got a new &lt;a href=&quot;https://markus-haack.com&quot;&gt;markus-haack.com&lt;/a&gt; domain. The .de domain &lt;a href=&quot;http://www.markus-haack.de&quot;&gt;markus-haack.de&lt;/a&gt; still exists, it redirects to the .com domain.&lt;/p&gt;
&lt;p&gt;I started writing in English, which was something I had never done on my blog before. I mostly write about smart home and IoT (Internet of Things) projects I have built. I also post professional news occasionally.&lt;/p&gt;
&lt;p&gt;Later in 2019, I switched the theme to &lt;a href=&quot;https://novela.narative.co/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Novela&lt;/a&gt; which was, back then, actively maintained and updated.&lt;/p&gt;
&lt;h2 id=&quot;v6---eleventy&quot;&gt;V6 - Eleventy&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/website-history/#v6---eleventy&quot; aria-labelledby=&quot;v6---eleventy&quot;&gt;#&lt;/a&gt;&lt;p&gt;The most recent framework I have adopted is &lt;a href=&quot;https://11ty.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eleventy&lt;/a&gt;. Eleventy fulfils a similar task as Gatsby and is also implemented in Javascript.&lt;/p&gt;
&lt;p&gt;There is one big difference between the two tools: even a site without any JS, or that is entirely server-side rendered, will still ship a bunch amount of client-side JS to make it feel “lightning fast”. It seems logical to only send JS to the client when it’s actually needed, so for a simple static site, like this blog it’s unnecessary. That’s why Eleventy seems like the better choice.&lt;/p&gt;
&lt;p&gt;Getting started with Eleventy was pretty easy. The &lt;a href=&quot;https://www.11ty.dev/docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;documentation&lt;/a&gt; is excellent and there are plenty of how-to guides like &lt;a href=&quot;https://css-irl.info/from-gatsby-to-eleventy/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The initial template I used was the &lt;a href=&quot;https://github.com/yinkakun/eleventy-duo&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Eleventy Duo&lt;/a&gt; theme. While it helped me get the site up and running, I added quite a few extensions and customizations. As the site got more and more complex, I re-wrote the entire CSS to &lt;a href=&quot;https://tailwindcss.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tailwind CSS&lt;/a&gt; and little remains of the original template.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/mh-site&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;Source hero image: &lt;a href=&quot;https://unsplash.com/photos/tZc3vjPCk-Q&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;unsplash.com&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>CIF on Adobe Tech Blog</title>
    <link href="https://markus-haack.com/cif-on-adobe-tech-blog/"/>
    <updated>2021-12-11T00:00:00Z</updated>
    <id>https://markus-haack.com/cif-on-adobe-tech-blog/</id>
    <content type="html">&lt;p&gt;In the last few weeks and months, my colleagues and I have written several articles for the &lt;a href=&quot;https://medium.com/adobetech&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adobe Tech Blog&lt;/a&gt;. Since I am also presenting some of my professional projects here, I wanted to take the opportunity and briefly introduce them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/adobetech/taking-a-deep-dive-into-adobe-experience-managers-commerce-integration-framework-631947b0a9a7&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Taking a Deep Dive into Adobe Experience Manager’s Commerce Integration Framework&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the first article in a series that we wrote about the Commerce Integration Framework (CIF) - the project I’m current working on most of my time at Adobe.&lt;br&gt;
CIF is a powerful Adobe Experience Manager extension for building integrated and seamless content and e-commerce experiences.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/adobetech/architecting-a-better-ecommerce-experience-with-adobe-experience-managers-commerce-integration-712feef5de8&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Architecting a Better Ecommerce Experience with Commerce Integration Framework&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The second post on CIF explains the high level architecture, cloud-native integration concepts and explains the core elements of the Commerce Integration Framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/content-and-commerce/home.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Commerce Add-on&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/adobe/aem-core-cif-components&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Commerce Core Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/adobe/aem-cif-guides-venia&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AEM Venia Reference store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/adobetech/how-cif-integrates-with-adobe-commerce-and-third-party-commerce-solutions-5a5efb8da2a0&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;How CIF Integrates with Adobe Commerce and Third-Party Commerce Solutions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The most extensive blog post on CIF so far goes deep and explains the architecture details on how AEM &amp;amp; CIF integration works. It explains the different integration scenarios and options projects can apply to integrate Adobe Experience Manager with Adobe Commerce or third-party commerce solutions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/adobetech/building-rich-content-and-commerce-experiences-with-cif-754685dc2927&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Building Rich Content and Commerce Experiences with CIF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The 4th blog post is a little context switch. While the first three posts have been all about architecture, infrastructure and integration options, this article is for the business user. We give an overview of the functionality of CIF and explain the individual functions that an AEM author has to create engaging commerce experiences.&lt;/p&gt;
&lt;p&gt;Have fun while reading the posts.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>New Talk: Extend AEM Content &amp; Commerce</title>
    <link href="https://markus-haack.com/extend-aem-commerce/"/>
    <updated>2021-10-18T00:00:00Z</updated>
    <id>https://markus-haack.com/extend-aem-commerce/</id>
    <content type="html">&lt;p&gt;At the last Adobe Developers Live conference I gave a talk about how to extend AEM Content &amp;amp; Commerce with new Adobe Developer App Builder.&lt;/p&gt;
&lt;p&gt;In this talk I discuss AEM Commerce integration &amp;amp; extensibility patterns using App Builder. I explain how you can integrate your eCommerce solution, either in house home grown services or an off the shelf commercial solution, with Adobe Experience Manager. The talk covers the overall integration architecture, how we use GraphQL in the Commerce Integration Framework (CIF) and how you can easily build your own integration.&lt;/p&gt;
&lt;p&gt;Interested? The recording for my talk is now available on YouTube.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=25cTzVV2jfQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=25cTzVV2jfQ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Projects build by our team mentioned in the talk:&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;adobe/aem-core-cif-components&quot; label=&quot;AEM CIF Core Components&quot;&gt;&lt;/github-badge&gt;&lt;github-badge repo=&quot;adobe/commerce-cif-graphql-integration-reference&quot; label=&quot;CIF GraphQL integration reference project&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Mini plant watering project</title>
    <link href="https://markus-haack.com/mini-plant-watering/"/>
    <updated>2021-08-17T00:00:00Z</updated>
    <id>https://markus-haack.com/mini-plant-watering/</id>
    <content type="html">&lt;p&gt;I would like to show you my new half 30 minutes no coding holiday &lt;a href=&quot;https://www.home-assistant.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt; project. My daughter’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Mimosa_pudica&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mimosa&lt;/a&gt; plants need some water while we were on vacation, so I built this super simple automated watering system. The project goal is to keep the plants alive for two weeks while we are away. Nothing permanently only a temporary project.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0LImGXfNvG4&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=0LImGXfNvG4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It was built very quick shortly before we went out to our summer vacation place. I only used parts that I already had lying around. It took ~ 30min to build the project.&lt;/p&gt;
&lt;h2 id=&quot;parts&quot;&gt;Parts&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-plant-watering/#parts&quot; aria-labelledby=&quot;parts&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;The plants 🪴&lt;/li&gt;
&lt;li&gt;Water hose&lt;/li&gt;
&lt;li&gt;Water bottle, a bucket, or some container&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://www.aliexpress.com/item/33006096807.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;mini pump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A 5V power supply&lt;/li&gt;
&lt;li&gt;A smart socket outlet which can be controlled by Home Assistant&lt;/li&gt;
&lt;li&gt;Some wires&lt;/li&gt;
&lt;li&gt;Cable ties&lt;/li&gt;
&lt;li&gt;Tape&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;assembly&quot;&gt;Assembly&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-plant-watering/#assembly&quot; aria-labelledby=&quot;assembly&quot;&gt;#&lt;/a&gt;&lt;p&gt;Ok there is not much assembly needed for this project, no soldering, no screws, no glue. You can do a lot with cable ties and tape 😀&lt;/p&gt;
&lt;p&gt;The little bench for the plants was already there before I only had to mount the little bridge holding water hose. It is fixed with cable ties and locked with two cable ties at the end to prevent the water from leaking. Above the plants I made a tiny hole in it with a small screwdriver. Be careful it should be super small so that the water can slowly drip out.&lt;/p&gt;
&lt;p&gt;The aquarium pump can be mounted anywhere. It fixes it directly to the water bottle with cable tiers. Depending how long and how often the irrigation should run you might need a bigger water container. Then connect the water hose to the pump. Almost done.&lt;/p&gt;
&lt;p&gt;The pump, in my case, requires 6 volts. I had this old power supply that can deliver 5 volts, enough to run the pump for a few seconds. The wires from the pump are connected to the plug at the end of the power supply cable and fixed with some tape. Pay attention to the correct polarity. Ok not very professional but it works, and it is low voltage only so it will not burn down our house.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2021-08-17-mini-plant-watering-project/8bce2361-f2e5-4962-b38e-b13568460be3.jpeg&quot; alt=&quot;Sonoff S20&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The last step is to connect the power supply with some smart socket which can be controlled by Home Assistant. I use a &lt;a href=&quot;https://sonoff.tech/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Sonoff S20&lt;/a&gt; which I have left from another project. It is already flashed with &lt;a href=&quot;https://tasmota.github.io/docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt; firmware which works perfectly with Home Assistant. I just had to rename the device. Other controllable socket outlets like a Shelly Plug S will work as well. The socket should be connected to you Wifi network, if not already done before.&lt;/p&gt;
&lt;p&gt;Place the plants directly under the holes in the hose and put some water into the bottle. Maybe also have a towel at hand in case something goes next to the flowerpot.&lt;/p&gt;
&lt;p&gt;And now - it is time for the first “dry-run”.&lt;/p&gt;
&lt;h2 id=&quot;home-assistant&quot;&gt;Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-plant-watering/#home-assistant&quot; aria-labelledby=&quot;home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;First why do you need Home Assistant here? The answer is you don’t. But it makes the project so much easier. Even the job for Home Assistant for this project is only on simple task: switch on/off the pump at a scheduled time. This can all be done by having a timer on the smart outlet directly (both Tasmota &amp;amp; Shelly firmware can do this) or by using a micro controller with a relay.&lt;/p&gt;
&lt;p&gt;Doing this with Home Assistant is simple and fun, plus you get the user interface and app to control the socket manually for free. You get logs and events when and how often the pump runs. And with Home Assistant &amp;amp; Nabu Casa you get access to your plant watering from everywhere in the world - that’s cool.&lt;/p&gt;
&lt;p&gt;The first step in HA is to add the controllable socket via the Home Assistant integration page. Depending on the device it might be already automatically discovered by Home Assistant. Since I reuse a Sonoff S20 I had used before I just did some double check.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2021-08-17-mini-plant-watering-project/screenshot_2021-08-17_at_16.27.05.png&quot; alt=&quot;Sonoff Tasmota integration&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is the Sonoff device for other integrations this should look similar.&lt;/p&gt;
&lt;p&gt;In a second step I created a simple automatic rule to switch on and off the pump. The automation was created entirely in Home Assistant UI.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2021-08-17-mini-plant-watering-project/screenshot_2021-08-17_at_17.02.45.png&quot; alt=&quot;Pump automation&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;It is super simple: it runs a a fixed time, not every day, switch on the Sonoff socket to enable the pump, wait 5 seconds and switch off the pump again. The wait time must be adjusted to the amount of water needed by your plants.&lt;/p&gt;
&lt;p&gt;Here is the full YAML for reference (id and device_id’s will be different) :&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1394083d&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;7c2f&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4a3f&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;8690&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;59a691148bcx
  &lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Childsroom] Mimosen gießen&#39;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; single
  &lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; time
     &lt;span class=&quot;token key atrule&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;07:00&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; time
     &lt;span class=&quot;token key atrule&quot;&gt;weekday&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; mon
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; wed
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; sat
  &lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_on
     &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 6788c5632346427ca0e4b7aa21e271dc
     &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.sonoff_nursery_watering
     &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; turn_off
     &lt;span class=&quot;token key atrule&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 6788c5632346427ca0e4b7aa21e271dc
     &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch.sonoff_nursery_watering
     &lt;span class=&quot;token key atrule&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; switch&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that you are good to go on holiday a little longer without hesitation and the plants will survive.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>AEM&#39;s Headless Extension for Adobe Commerce PWA Studio</title>
    <link href="https://markus-haack.com/medium-aem-headless/"/>
    <updated>2021-06-30T00:00:00Z</updated>
    <id>https://markus-haack.com/medium-aem-headless/</id>
    <content type="html">&lt;p&gt;Together with my colleague &lt;a href=&quot;https://www.linkedin.com/in/marbec/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mark J. Becker&lt;/a&gt; I wrote an introduction and instructions on how to use AEM Content Fragments together with the Adobe Commerce (aka. Magento) PWA.&lt;/p&gt;
&lt;p&gt;We provide step-by-step instructions that explain the individual tasks in detail, using a blog example - starting with setting up the PWA with the help of PWA Studio, via setting up the GraphQL endpoint in Adobe Experience Manager, managemnet of the content fragment models and content fragments itself and up to deployment.&lt;/p&gt;
&lt;p&gt;Check out the full post on the &lt;a href=&quot;https://medium.com/adobetech/introducing-adobe-experience-managers-new-headless-extension-for-adobe-commerce-pwa-studio-12a0d6c5a4e9&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adobe Tech Blog&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Content and Commerce with Adobe Experience Manager as a Cloud Service</title>
    <link href="https://markus-haack.com/content-and-commerce/"/>
    <updated>2021-03-04T00:00:00Z</updated>
    <id>https://markus-haack.com/content-and-commerce/</id>
    <content type="html">&lt;p&gt;I held a session on “Content and Commerce with Adobe Experience Manager” at the recent Adobe Developers Live | Content conference.&lt;/p&gt;
&lt;p&gt;The recording for my talk is now up. If you couldn’t join the session, please watch and learn about how to get started with Commerce on Adobe Experience Manager as a Cloud Service.&lt;/p&gt;
&lt;iframe width=&quot;680&quot; height=&quot;400&quot; allowfullscreen=&quot;&quot; src=&quot;https://video.tv.adobe.com/v/331851/?quality=12&amp;amp;learn=on&amp;amp;hidetitle=true&amp;amp;captions=eng&quot; style=&quot;width: 800px; height: 600px;&quot;&gt;&lt;source src=&quot;https://video.tv.adobe.com/v/331851/?quality=12&amp;learn=on&amp;hidetitle=true&quot; type=&quot;&quot;&gt;&lt;p&gt;Your browser does not support the iframe element.&lt;/p&gt;&lt;/iframe&gt;
&lt;p&gt;The &lt;a href=&quot;https://experienceleague.adobe.com/docs/adobe-developers-live-events/assets/content-commerce.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;slide deck&lt;/a&gt; is available as well.&lt;/p&gt;
&lt;p&gt;An overview of all sessions and recordings of this two-day conference are available on &lt;a href=&quot;https://experienceleague.adobe.com/docs/adobe-developers-live-events/events/content/feb2021/overview.html?lang=en#content&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adobe Experience League&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Arduino Dollhouse Mini TV</title>
    <link href="https://markus-haack.com/mini-tv/"/>
    <updated>2020-12-13T00:00:00Z</updated>
    <id>https://markus-haack.com/mini-tv/</id>
    <content type="html">&lt;h2 id=&quot;a-mini-tv-for-my-daughter%E2%80%99s-dollhouse&quot;&gt;A mini TV for my daughter’s dollhouse&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-tv/#a-mini-tv-for-my-daughter%E2%80%99s-dollhouse&quot; aria-labelledby=&quot;a-mini-tv-for-my-daughter%E2%80%99s-dollhouse&quot;&gt;#&lt;/a&gt;&lt;p&gt;This project and the blog post about it were originally created in February 2019. A few weeks ago I updated the Mini TV software so it was time to update the blog post as well.&lt;/p&gt;
&lt;p&gt;The dollhouse Mini TV is a small Arduino project using an ESP8266 chip on a Wemos D1 board and an SSD1306 OLED display to build a small working TV for my daughter’s birthday. She already had this older plastic TV showing some yellowed picture and the project brings that TV to life.&lt;/p&gt;
&lt;p&gt;The TV displays an endless loop of different TV “channels” showing animations, a clock, and a weather forecast. With a small button at the side, one could stop the loop and watch the current channel. Another button press continues the loop.&lt;/p&gt;
&lt;h3 id=&quot;from-prototype-to-working-mini-tv&quot;&gt;From prototype to working mini TV&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-tv/#from-prototype-to-working-mini-tv&quot; aria-labelledby=&quot;from-prototype-to-working-mini-tv&quot;&gt;#&lt;/a&gt;&lt;p&gt;The display size for this project was predefined by the frame size of the old dollhouse TV. There were only a few options and I had an SSD1306 OLED display laying around. A normal NodeMCU or Adafruit feather was too big for the small frame, so I decided on a Wemos D1 which fitted nicely into the old TV.&lt;/p&gt;
&lt;p&gt;The TV is powered via dollhouse cabling. All rooms have mini sockets installed providing 4.5 volts, enough to power the mini TV. Only the DC polarity is a small problem for the TV, it needs to be plugged in the correct way.&lt;/p&gt;
&lt;p&gt;The display shows 5 screens (can be extended) in a carousel mode. Most of them are little cat or dinosaur animations but it has a real weather forecast and a nice clock as well. Additionally, I added some real black &amp;amp; white pictures of our cats with the last update.&lt;/p&gt;
&lt;h3 id=&quot;hardware-components-%26-tools&quot;&gt;Hardware components &amp;amp; tools&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-tv/#hardware-components-%26-tools&quot; aria-labelledby=&quot;hardware-components-%26-tools&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Wemos D1 mini&lt;/li&gt;
&lt;li&gt;SSD1306 OLED Display&lt;/li&gt;
&lt;li&gt;Tactile Button Switch&lt;/li&gt;
&lt;li&gt;Dollhouse plug (fitting into the sockets the dollhouse already has)&lt;/li&gt;
&lt;li&gt;USB cable (for programming only)&lt;/li&gt;
&lt;li&gt;Some wires&lt;/li&gt;
&lt;li&gt;Soldering iron&lt;/li&gt;
&lt;li&gt;Hot glue&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The wiring is pretty simple the display connects via I2C bus to the Wemos board and the button just needs two wires.&lt;/p&gt;
&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mini-tv/#software&quot; aria-labelledby=&quot;software&quot;&gt;#&lt;/a&gt;&lt;p&gt;Like some of my other Arduino projects, I used &lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie&lt;/a&gt; as a base library for this project. This is actually not really necessary for the Mini TV as it has no special requirements and does not need MQTT. But since it uses the same SSD1306 OLED display I could reuse some of the Homie node classes from the &lt;a href=&quot;https://markus-haack.com/mqtt-bme280-homie/&quot;&gt;mqtt-bme280-homie project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, with Homie one gets OTA update as well, which is important here because I hot glued the board to the rear wall of the TV and could not access the USB connector anymore.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/arduino-dollhouse-tv&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;The following software libraries are used for this project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/homieiot/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie V3 for ESP8266&lt;/a&gt; including dependencies&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/squix78/esp8266-oled-ssd1306&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SSD1306 driver for ESP8266 platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arduino-libraries/NTPClient&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NTPClient to connect to a time server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ThingPulse/esp8266-weather-station&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ESP8266 Weather Station&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://platformio.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;PlatformIO&lt;/a&gt; environment for building the code&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Code structure&lt;/h4&gt;
&lt;p&gt;As usual, the source code and configuration details can be found on GitHub: &lt;a href=&quot;https://github.com/mhaack/arduino-dollhouse-tv&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://github.com/mhaack/arduino-dollhouse-tv&lt;/a&gt;&lt;br&gt;
It is organized into 4 main modules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dollhouse-tv.cpp&lt;/code&gt; - the main program drawing all the TV screens and assembling them all together&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DisplayNode.h / .cpp&lt;/code&gt; - generic class to control the SSD1306 display&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ButtonNode.h / .cpp&lt;/code&gt; - simple and generic class to capture the button press (this is from &lt;a href=&quot;http://github.com/luebbe&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;http://github.com/luebbe&lt;/a&gt; Homie node collection)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherStationNode.h / .cpp&lt;/code&gt; - Homie wrapper class around the OpenWeatherMap client of the ESP8266 Weather Station project&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, we have &lt;code&gt;WeatherStationFonts.h&lt;/code&gt; to store the weather icons like sun, clouds, etc. for the weather display. And &lt;code&gt;images.h&lt;/code&gt; which has a list of array constants storing the images &amp;amp; bitmaps.&lt;/p&gt;
&lt;p&gt;The TV logic itself is very simple. For each screen aka. channel there is a “draw” method defined in &lt;code&gt;dollhouse-tv.cpp&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawCat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawStars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawClock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawWeather&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawDino&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawPictures&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each method is used to draw the channel-specific information or images on the screen. They contain mostly painting method calls and have access to the entire display. For transitions between the different screens the draw method gets virtual x &amp;amp; y coordinate. This is used to have a smooth animation while the current screen is transition in and out.&lt;/p&gt;
&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drawDino&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;OLEDDisplay &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;display&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OLEDDisplayUiState &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int16_t&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    display&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WHITE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    display&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;drawXbm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; dinoPosX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dino_width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dino_height&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dinoPointers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dinoState&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    dinoState&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dinoState &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        dinoState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    dinoPosX&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dinoPosX &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        dinoPosX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above example shows a dinosaur animation build-out of different sprites. It sets the color (there are only white and black on an SSD1306 OLED display) and draws the bitmap image. Then it moves to the next sprite and one pixel to the right on the x coordinates until the dinosaur reaches the edge of the screen.&lt;/p&gt;
&lt;h4&gt;Configuration&lt;/h4&gt;
&lt;p&gt;Like all Homie-based projects, this project needs a configuration file as well. To configure the device, you have to create and manually flash the configuration file to the device SPIFFS at the &lt;code&gt;/homie/config.json&lt;/code&gt;. The following sample configuration file can be used for upload. This file is in the GitHub repository as well.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dollhous TV&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;device_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mqtt-dollhouse-tv&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;wifi&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;ssid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;wifi ssid&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;wifi password&gt;&quot;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;mqtt&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;mqtt server hostname or ip&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1883&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;auth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// if MQTT server requieres authentication&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;mqtt username&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;mqtt password&gt;&quot;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;ota&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;settings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;flipScreen&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;WeatherApiKey&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;your open weather map api key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;WeatherLanguage&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;WeatherLocation&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2950159&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;WeatherUpdate&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The important configuration settings here are the wifi username &amp;amp; password, the MQTT settings, and the parameters for the OpenWeatherMap client.&lt;/p&gt;
&lt;p&gt;For MQTT you need to provide the server’s hostname or IP address. If authentication is used username and password are required here as well. If not you don’t need to include these in your config.&lt;/p&gt;
&lt;p&gt;To retrieve OpenWeatherMap weather three configuration parameters are needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WeatherApiKey&lt;/code&gt; - To load weather data from OpenWeatherMap you need an API key, &lt;a href=&quot;https://openweathermap.org/appid&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;follow the instructions&lt;/a&gt; create one for your needs.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherLanguage&lt;/code&gt; - set this to get the output in your language, check &lt;a href=&quot;https://openweathermap.org/current#multi&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;here&lt;/a&gt; for available languages&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherLocation&lt;/code&gt;- this is the identifier of the location you want to load the weather data for. To get it open the weather details for the place you are interested in and copy the number of the location from the URL. For example the &lt;a href=&quot;https://openweathermap.org/city/2950159&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Berlin OpenWeatherMap&lt;/a&gt; page, you take &lt;code&gt;2950159&lt;/code&gt; from the URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an alternative to the file upload configuration, Homie ESP8266 also allows configuration via &lt;a href=&quot;https://homieiot.github.io/homie-esp8266/docs/stable/configuration/http-json-api/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HTTP JSON API&lt;/a&gt;. Once the device is running and connected individual configuration settings can be changed via MQTT as well.&lt;/p&gt;
&lt;h4&gt;Your own screens and animations&lt;/h4&gt;
&lt;p&gt;You can add as many screens as you want and add them to &lt;code&gt;dollhouse-tv.cpp&lt;/code&gt; via the &lt;code&gt;setup&lt;/code&gt; method. Each screen animation goes into its own “drawXYZ” method, for an animation example see &lt;code&gt;drawCat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to build animations out of a sequence of XBM bitmaps you can follow the procedure below.&lt;/p&gt;
&lt;p&gt;The workflow to add a new image animation is simple. First get the image either as an animated gif or independent image files, ideally in black and white format. The size of the image should match the screen size of the display. For the SSD1306 OLED display it must have a width of 128 pixels and a height of 64 pixels. Gif animations have to be split into individual image files.&lt;/p&gt;
&lt;p&gt;These can be converted to an XBM bitmap file using some image tool or an online service like &lt;a href=&quot;https://convertio.co/gif-xbm/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://convertio.co/gif-xbm/&lt;/a&gt;. Put the XBM files into the project src folder or merge them into &lt;code&gt;images.h&lt;/code&gt;. After that, they can be loaded into the code by using &lt;code&gt;drawXbm&lt;/code&gt;. Make sure you add the &lt;code&gt;x&lt;/code&gt; &amp;amp; &lt;code&gt;y&lt;/code&gt; coordinates from the method parameters when drawing on the screen to have smooth transitions if the screen is changed to the next one.&lt;/p&gt;
&lt;p&gt;That’s it have fun with the Mini TV.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Home Assistant: You have got mail</title>
    <link href="https://markus-haack.com/you-have-got-mail/"/>
    <updated>2020-09-05T00:00:00Z</updated>
    <id>https://markus-haack.com/you-have-got-mail/</id>
    <content type="html">&lt;p&gt;Today I want to share a little holiday project I build this week: a mailbox sensor to make a dumb mailbox smart and notifying us if we got new mail. I’m talking about real physical mail here - letters, postcards, newspapers etc. dropped into our mailbox.&lt;/p&gt;
&lt;h2 id=&quot;how-does-it-work%3F&quot;&gt;How does it work?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/you-have-got-mail/#how-does-it-work%3F&quot; aria-labelledby=&quot;how-does-it-work%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;The project is build using two Xiaomi ZigBee contact sensors I had leftover. You can get these from Gearbest, AliExpress, or Amazon. Our &lt;a href=&quot;https://markus-haack.com/jama-villa/&quot;&gt;smart home setup&lt;/a&gt; already has a ZigBee network running using a &lt;a href=&quot;https://phoscon.de/en/conbee2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Conbee II stick&lt;/a&gt;. Of course, it is integrated with &lt;a href=&quot;https://www.home-assistant.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt; already.&lt;/p&gt;
&lt;p&gt;This is how the setup looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-09-01-home-assistant-you-have-got-mail/mailbox-sensor-diagram.png&quot; alt=&quot;Overview&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-hard(ware)-part&quot;&gt;The hard(ware) part&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/you-have-got-mail/#the-hard(ware)-part&quot; aria-labelledby=&quot;the-hard(ware)-part&quot;&gt;#&lt;/a&gt;&lt;p&gt;Not much is needed for this project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 ZigBee contact sensors (e.g. Xiaomi…)&lt;/li&gt;
&lt;li&gt;ZigBee network (for example via Deconz)&lt;/li&gt;
&lt;li&gt;Home Assistant&lt;/li&gt;
&lt;li&gt;Duck tape, hot glue, etc. to fix the sensors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The setup depends a little on the construction of the actual mailbox. Ours has a flap on the front side where the mail is thrown in and a door on the backside to empty it. So I needed two sensors, one to detect if the mail was inserted and a second one to detect when we cleared the mailbox. For a mailbox with just one door or flap, only one sensor would be needed. Our mailbox is made of metal, like most mailboxes here, built into a concrete column. I first thought having a metal frame like this might be problematic with the ZigBee signal but that is not the case.&lt;/p&gt;
&lt;p&gt;For a first prototype, I just duck taped the sensor inside the mailbox. On the door sensor the original magnet was too small so I replaced it with a bigger one.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-09-01-home-assistant-you-have-got-mail/img_0758.jpg&quot; alt=&quot;Mailbox flap with magnet&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-09-01-home-assistant-you-have-got-mail/img_0755.jpg&quot; alt=&quot;First prototype&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is it for the hardware assembly, actually not really hard.&lt;/p&gt;
&lt;h2 id=&quot;the-fun-part&quot;&gt;The fun part&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/you-have-got-mail/#the-fun-part&quot; aria-labelledby=&quot;the-fun-part&quot;&gt;#&lt;/a&gt;&lt;p&gt;With the hardware part done we can now have a look at the software part. Since our ZigBee network was already running it was easy to connect the two new sensors via the Deconz UI.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-09-01-home-assistant-you-have-got-mail/deconz-sensor.jpg&quot; alt=&quot;Mailbox sensor in deCONZ&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;With Deconz integrated into Home Assistant the new sensors are immediately available in Home Assistant as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-09-01-home-assistant-you-have-got-mail/mailbox-deconz.jpg&quot; alt=&quot;Mailbox sensors in Home Assistant&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;No extra configuration is needed here. Just name the sensors are you prefer. Adding some ZigBee sensors to Home Assistant - pretty easy. Additionally to the two deCONZ sensors I use one boolean input helper plus a corresponding template sensor to keep the state of there is mail or not. deCONZ also creates battery level sensors for each battery-powered device. These are not really used here, but there are other automations that notify us of batteries running low. For convenience one more boolean input helper is used to enable/disable the mailbox notifications. In total there are 5 sensors and 2 inputs used for this project.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-09-01-home-assistant-you-have-got-mail/mailbox-sensors.jpg&quot; alt=&quot;Mailbox sensors in Home Assistant&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The last step is to build out the automations. I’m still having all automations in YAML, so the mailbox automations are added here as well. For the mailbox sensor three automations are needed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;set the mailbox state if the mail was inserted&lt;/li&gt;
&lt;li&gt;Reset the mailbox state once we have cleared the mailbox&lt;/li&gt;
&lt;li&gt;Reminder in case we forgot to empty the mailbox in the evening&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All of them are relatively simple and short.&lt;/p&gt;
&lt;p&gt;The mail detection automation is executed when the flap of the mailbox has been opened the sensor triggered. It sets the mail state to on and sends a notification. Notifications are only sent if the second condition is also met.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Mailbox] Mail detection&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.garden_mailbox_flap
   &lt;span class=&quot;token key atrule&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;off&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;on&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.turn_on
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.garden_mailbox
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.garden_mailbox_notification
   &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;on&#39;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notify.mobile_app_xyz
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 📬
    &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Trari&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; trara&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; die Post ✉️ ist da&lt;span class=&quot;token tag&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token key atrule&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;thread-id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ha-mailbox-notification-group&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The mailbox door automation is even simpler. It just resets the mail status to off if the mailbox door got open which is the indication that the mailbox has been emptied.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Mailbox] Reset&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; binary_sensor.garden_mailbox_door
   &lt;span class=&quot;token key atrule&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;off&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;on&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.turn_off
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.garden_mailbox&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The reminder automation is also very simple. At a certain time it checks the mailbox state and sends us a reminder in case there is still mail in the mailbox. We decided to have two reminders: first at 6 pm, second at 8 pm.&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[Mailbox] Notification&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; time
   &lt;span class=&quot;token key atrule&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;18:00:00&#39;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;20:00:00&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.garden_mailbox_notification
   &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;on&#39;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; state
   &lt;span class=&quot;token key atrule&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; input_boolean.garden_mailbox
   &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;on&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; notify.mobile_app_xzy
   &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; JaMa Villa &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 📬
    &lt;span class=&quot;token key atrule&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Der Briefkasten wurde noch nicht geleert&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; da ist noch ✉️ drin.
    &lt;span class=&quot;token key atrule&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
     &lt;span class=&quot;token key atrule&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;thread-id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ha-mailbox-notification-group&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/home-assistant-config&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;That is, not much needed for this little fun project.&lt;/p&gt;
&lt;p&gt;Source hero image: &lt;a href=&quot;https://www.flickr.com/photos/8058853@N06/2685196800&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Flickr - Helgi Halldórsson&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building Experiences - AEM &amp; Magento Commerce Integration</title>
    <link href="https://markus-haack.com/building-experiences-with-aem-and-magento/"/>
    <updated>2020-07-31T00:00:00Z</updated>
    <id>https://markus-haack.com/building-experiences-with-aem-and-magento/</id>
    <content type="html">&lt;p&gt;I want to share some professional projects I’m working on: Commerce Integration Framework and the &lt;a href=&quot;https://github.com/adobe/aem-core-cif-components&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AEM CIF Core Components&lt;/a&gt; are built by the team I’m working for at Adobe.&lt;/p&gt;
&lt;p&gt;On July 28th I was a guest on Mark Szulc’s &lt;a href=&quot;https://www.youtube.com/channel/UC8zeS_5A2HxNA5-vKtIrtqg&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Building Experiences using Adobe Experience Cloud show&lt;/a&gt;. We discussed how Adobe Experience Manager works together with Magento, using the latest release of the Commerce Integration Framework. I explained how projects can use the power of CIF and how we support AEM as a Cloud Services.&lt;/p&gt;
&lt;p&gt;Check out the recording of the live stream:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6LUHYCEx4GU&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=6LUHYCEx4GU&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;All our projects are open-source, public on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;adobe/aem-core-cif-components&quot; label=&quot;AEM CIF Core Components&quot;&gt;&lt;/github-badge&gt;&lt;github-badge repo=&quot;adobe/aem-cif-guides-venia&quot; label=&quot;AEM Venia Reference Store&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;Mark &lt;a href=&quot;https://www.markszulc.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;does regular live streams&lt;/a&gt; on different interesting topics around Adobe Experience Cloud and Adobe Experience Manager.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Our home sweet smart home</title>
    <link href="https://markus-haack.com/jama-villa/"/>
    <updated>2020-01-14T00:00:00Z</updated>
    <id>https://markus-haack.com/jama-villa/</id>
    <content type="html">&lt;p&gt;I try to gather and describe our Home Assistant setup here, along with the configuration in GitHub. Maybe there is something useful to copy and adapt 😃 I already documented our &lt;a href=&quot;https://markus-haack.com/home-assistant/&quot;&gt;migration journey&lt;/a&gt; from OpenHab to Home Assistant and some details about how to better integrate &lt;a href=&quot;https://markus-haack.com/home-assistant-display/&quot;&gt;Homematic devices&lt;/a&gt; into HA.&lt;/p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa/#overview&quot; aria-labelledby=&quot;overview&quot;&gt;#&lt;/a&gt;&lt;p&gt;Our Home Assistant setup is simple - everything currently runs on a single board &lt;a href=&quot;https://www.hardkernel.com/shop/odroid-n2-with-4gbyte-ram/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Odroid N2&lt;/a&gt;. The N2 has only recently replaced the Raspberry Pi 3B. Like may Home Assistant beginners we started with Raspberry Pi (it was used for &lt;a href=&quot;https://markus-haack.com/home-assistant/&quot;&gt;OpenHab&lt;/a&gt; before as well) and were pretty ok with it. Until the SD Card broke, that was a good opportunity to move the entire system to the Odroid N2.&lt;/p&gt;
&lt;p&gt;Other main gear we use:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device / Solution&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.eq-3.com/start.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic CCU3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Used to control all Homematic devices, mainly security devices like window/door sensors, motion sensors or sirene. Plus a few switch relays for DIN rail mounting.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://phoscon.de/de/conbee2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Phoscon Conbee II&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The main ZigBee Hub and second wireless device network. All Ikea &amp;amp; Hue light bulbs und LED stripes are connected to the Conbee ZigBee network. In addition temperature sensors in every room and a few contact sensors, we installed lately.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.arlo.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Arlo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Arlo camera system integration, currently we have 5 outdoor cameras connected. We are early day Arlo users, started with the 1st generation cameras, later we added Arlo Pro 2 devices.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.rademacher.de/en/smart-home/smart-home-systeme&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Rademacher DuoFern&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Wireless controller for our electric roller shutters. In fact, the roller shutters were the first smart devices in our house installed 5 years ago, long before Home Assistant took over the control.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://unifi-network.ui.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Ubiquiti UniFi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Our home network is operated by UniFi wired and wireless devices. Router, Switches, Wireless Access Points, … all UniFi. Only the DSL Modem is from DrayTek.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The entire system looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-01-14-jama-villa/setup.png&quot; alt=&quot;The setup&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;dashboards&quot;&gt;Dashboards&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa/#dashboards&quot; aria-labelledby=&quot;dashboards&quot;&gt;#&lt;/a&gt;&lt;p&gt;A small selection of Lovelace views. We use Lovelace in Yaml mode, the main Lovelace config file is found &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/ui-lovelace.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;here&lt;/a&gt;, and the folder defining the views &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/tree/master/config/lovelace&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Main info view&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-01-14-jama-villa/dashboard-main.png&quot; alt=&quot;Main Lovelace Dashboard&quot; class=&quot;large&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h4&gt;House view&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-01-14-jama-villa/dashboard-house.png&quot; alt=&quot;House Dashboard&quot; class=&quot;large&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Garden view&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-01-14-jama-villa/dashboard-garden.png&quot; alt=&quot;Garden Dashboard&quot; class=&quot;large&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h4&gt;System view&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2020-01-14-jama-villa/dashboard-system.png&quot; alt=&quot;System Dashboard&quot; class=&quot;large&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;integrations&quot;&gt;Integrations&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa/#integrations&quot; aria-labelledby=&quot;integrations&quot;&gt;#&lt;/a&gt;&lt;p&gt;Like any other Home Assistant setup, we have many integrations. And with every update or new toys I get the list gets longer. The five most important integrates our setup relies on are:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Integration&lt;/th&gt;
&lt;th&gt;Config&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/components/homematic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/homematic.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/components/deconz/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;deCONZ&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/components/unifi/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Unifi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/components/mqtt/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MQTT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/mqtt.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/adguard/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AdGuard Home&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/mobile_app/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mobile App&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://www.home-assistant.io/integrations/sonos&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Sonos&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/home-assistant-config/tree/master/config/integrations&quot; label=&quot;The full list is available on Github&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;h3 id=&quot;custom-integrations&quot;&gt;Custom Integrations&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa/#custom-integrations&quot; aria-labelledby=&quot;custom-integrations&quot;&gt;#&lt;/a&gt;&lt;p&gt;While Home Assistant already includes more than 1.500 integrations there are still some devices or services which are not integrated yet. Additionally, there is a large ecosystem of so-called custom integrations. They are not natively integrated into Home Assistant and must be loaded sideways via some special folder. Luckily there is HACS (Home Assistant Community Store) which helps to manage custom integration and Lovelace UI plug-ins, and which is a custom integration on its own.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Custom Integration&lt;/th&gt;
&lt;th&gt;Config&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/twrecked/hass-aarlo&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;aarlo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/aarlo.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/gluap/pyduofern&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Rademacher DuoFern&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/duofern.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/custom-components/hacs&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;hacs&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/hacs.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/thomasloven/hass-browser_mod&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;browser_mod&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/browser_mod.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/HomeAssistant-Mods/home-assistant-miele&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Miele&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mampfes/hacs_waste_collection_schedule&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Waste Collection Schedule&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/integrations/waste.yaml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;custom-lovelace-cards&quot;&gt;Custom Lovelace cards&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa/#custom-lovelace-cards&quot; aria-labelledby=&quot;custom-lovelace-cards&quot;&gt;#&lt;/a&gt;&lt;p&gt;To pimp the Lovelace dashboard, we use a bunch of custom lovelace cards. The three most used are:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Custom Card&lt;/th&gt;
&lt;th&gt;Documentation / GitHub&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mini Media Player&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://community.home-assistant.io/t/lovelace-mini-media-player/68459&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Docs&lt;/a&gt;, &lt;a href=&quot;https://github.com/kalkih/mini-media-player&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layout Card&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://community.home-assistant.io/t/layout-card-take-control-of-where-your-cards-end-up/147805&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Docs&lt;/a&gt;, &lt;a href=&quot;https://github.com/thomasloven/lovelace-layout-card&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A full list of all custom cards currently used is in &lt;a href=&quot;https://github.com/mhaack/home-assistant-config/tree/master/config/lovelace/resources&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Git&lt;/a&gt;. Just like the custom integrations, the custom Lovelace cards are managed via hacs.&lt;/p&gt;
&lt;h3 id=&quot;hass.io-add-ons&quot;&gt;&lt;a href=&quot;http://Hass.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hass.io&lt;/a&gt; add-ons&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/jama-villa/#hass.io-add-ons&quot; aria-labelledby=&quot;hass.io-add-ons&quot;&gt;#&lt;/a&gt;&lt;p&gt;The entire JaMa Villa Home Assistant setup is running and managed by &lt;a href=&quot;http://hass.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;hass.io&lt;/a&gt;. With the following add-ons currently used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hassio-addons/addon-adguard-home&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AdGuard Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hassio-addons/addon-vscode&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hassio-addons/addon-grafana&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hassio-addons/addon-influxdb&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;InfluxDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hassio-addons/addon-log-viewer&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Log Viewer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://home-assistant.io/addons/mosquitto/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mosquitto MQTT broker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hassio-addons/addon-ssh&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SSH &amp;amp; Web Terminal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://home-assistant.io/addons/samba/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Samba share&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s it on our Home Assistant setup. Feel free to reach out if you have questions.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Home Assistant - Homematic HM-Dis-EP-WM55 e-paper display</title>
    <link href="https://markus-haack.com/home-assistant-display/"/>
    <updated>2019-07-08T00:00:00Z</updated>
    <id>https://markus-haack.com/home-assistant-display/</id>
    <content type="html">&lt;h2 id=&quot;home-assistant&quot;&gt;Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-display/#home-assistant&quot; aria-labelledby=&quot;home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;I recently &lt;a href=&quot;https://markus-haack.com/home-assistant/&quot;&gt;switched from OpenHab to Home Assistant&lt;/a&gt;. While this transition was smooth for most of the devices and integrations the &lt;a href=&quot;https://www.homematic.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic&lt;/a&gt; part was a little more challenging.&lt;/p&gt;
&lt;p&gt;Homematic is a proprietary Smart Home solution mainly marketed in Germany. It is actually an entire Smart Home ecosystem similar to SmartThings. It can be used as a standalone solution and has a wide variety of devices. OpenHab has extremely good support from Homematic, I think mainly because OpenHab has a big German community and user group.&lt;/p&gt;
&lt;p&gt;The HomeMatic integration of Home Assistant has decent support for many Homematic devices as well, but some have special features like remote control or displays that require more work to integrate. Luckily the Home Assistant integration supports communication with a device on the low-level protocol to send any kind of data to any device.&lt;/p&gt;
&lt;h2 id=&quot;the-display&quot;&gt;The display&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-display/#the-display&quot; aria-labelledby=&quot;the-display&quot;&gt;#&lt;/a&gt;&lt;p&gt;The device I needed to get working with Home Assistant is the wireless e-paper display (&lt;a href=&quot;https://www.amazon.de/dp/B01KPM3MRU/ref=cm_sw_em_r_mt_dp_U_mm6iDb1716TD1&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HM-Dis-EP-WM55&lt;/a&gt;). It is installed on a central place in our house, displaying the status of open/closed windows &amp;amp; doors and our two alarms for the house and garden house.&lt;/p&gt;
&lt;p&gt;The display has 5 lines of text and icons, a three-color LED and a beeper. One can configure the text of the first and last line via the Homematic CCU as fixed device parameters. The 3 middle lines can be controlled and updated via some command. The display itself is always on but consumes very little energy since the e-paper display does not need power all the time, only if changed. It also acts as a switch with two buttons which both can trigger a long or short press event.&lt;/p&gt;
&lt;h2 id=&quot;home-assistant-integration&quot;&gt;Home Assistant integration&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant-display/#home-assistant-integration&quot; aria-labelledby=&quot;home-assistant-integration&quot;&gt;#&lt;/a&gt;&lt;p&gt;The HM-Dis-EP-WM55 display can be controlled via a dedicated channel (#3) where you have to send the data in order to update the display content. A special encoded string must be sent to the device to update the text, icons, LED color and beeper, all in one. It is not possible to send partial updates; the string must always contain all information one would like to show on the display.&lt;/p&gt;
&lt;p&gt;Since there is no Home Assistant device type for a display the only way to communicate with the HM-Dis-EP-WM55 display is via &lt;code&gt;homematic.set_device_value&lt;/code&gt;. This command can be used to send any kind of data to any HomeMatic device integrated with Home Assistant. It is basically a low-level interface to a device. To use it one must know the device-specific behavior and data formats the device understands.&lt;/p&gt;
&lt;p&gt;I created some python scripts to concatenate all the text lines, icons, LED color and encode the string and push that to the device.&lt;/p&gt;
&lt;p&gt;The scripts are split into two parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A generic &lt;em&gt;&lt;a href=&quot;https://github.com/mhaack/home-assistant-config/blob/master/config/python_scripts/update_display.py&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;update_display.py&lt;/a&gt;&lt;/em&gt; script which does all the encoding and construction of the proprietary string format – this one can be reused directly&lt;/li&gt;
&lt;li&gt;A second, custom to my/your setup script to extract the data from my devices, collecting all and sending it to the first script&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;em&gt;update_display.py&lt;/em&gt; script constructs the string beginning with the three text lines and icons, encoding special characters, followed by the beeper code and LED color. This is sent to the device &lt;code&gt;homematic.set_device_value&lt;/code&gt;.&lt;br&gt;
The second script is included in my automation’s, once called it collects all the device variables and merges all data into a JSON object. Some values like the device id or display text which does not change are hardcoded. This JSON is sent to the first python script.&lt;/p&gt;
&lt;p&gt;The button press events (&lt;code&gt;homematic.keypress&lt;/code&gt;) can be captured by a simple automation. See &lt;a href=&quot;https://www.home-assistant.io/components/homematic/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic Home Assistant integration&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/home-assistant-config&quot; label=&quot;Home Assistant config&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;The full scripts are available in &lt;a href=&quot;https://github.com/mhaack/home-assistant-config&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;my Home Assistant config repo&lt;/a&gt; in the &lt;em&gt;python_scripts&lt;/em&gt; folder on GitHub. These are my first python baby steps, feedback and improvements are always welcome.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Home Assistant - The big move</title>
    <link href="https://markus-haack.com/home-assistant/"/>
    <updated>2019-05-21T00:00:00Z</updated>
    <id>https://markus-haack.com/home-assistant/</id>
    <content type="html">&lt;h2 id=&quot;from-openhab-to-home-assistant&quot;&gt;From OpenHab to Home Assistant&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant/#from-openhab-to-home-assistant&quot; aria-labelledby=&quot;from-openhab-to-home-assistant&quot;&gt;#&lt;/a&gt;&lt;p&gt;This “project” is about the change I did from &lt;a href=&quot;https://www.openhab.org&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenHab&lt;/a&gt; to &lt;a href=&quot;https://www.home-assistant.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt; for our smart home automation system. Ok maybe the headline sounds a bit too sensational but change our entire home automation setup from one system we used for 2+ years now to a completely new one requires quite some heavy lifting.&lt;/p&gt;
&lt;p&gt;Let’s start from the beginning. I’m running a smart home system for our house for almost 3 years now. I started with OpenHab 1 and quickly moved to OpenHab 2. I always wanted a system with local control and not cloud connection required, at least not by default. I also wanted to be vendor in-depended and don’t install a ton of apps on my smartphone. So OpenHab was a pretty good choice and already stable solution, they also have a quite large community in Germany and support a few more local system like &lt;a href=&quot;https://www.homematic.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homematic&lt;/a&gt; which are not known elsewhere. The initial reason why I decided to go with OpenHab was the very good support for the Homematic ecosystem, maybe the best you can get at the moment.&lt;/p&gt;
&lt;h2 id=&quot;so-why-change-a-running-system%3F&quot;&gt;So why change a running system?&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant/#so-why-change-a-running-system%3F&quot; aria-labelledby=&quot;so-why-change-a-running-system%3F&quot;&gt;#&lt;/a&gt;&lt;p&gt;Maybe 6 months ago I decided to move the smart home controller from OpenHab to Home Assistant. So why looking for an alternative? I was dissatisfied with the overall situation of OpenHab. This is not bashing on OpenHab, this is only about my personal opinion and view on it - which changed over time. Both systems are very powerful home automatic systems with a ton of integrations and both fulfill my requirement of being local and cloud independent.&lt;/p&gt;
&lt;p&gt;This was actually the 3rd time I looked into Home Assistant, two times I put it away and decided to stay with OpenHab. I finally decided now is the time for something new because I’m not happy with OpenHab process anymore. OpenHab moves slowly with yearly major releases (I know there are milestones now as well) and the core team spends very much time to keep the platform stable while continue to improve it. But there is not so much improvement on the integration side. While I was happy with how Homematic, Hue, Sonos, etc. are integrated other devices we have like Rademacher, Roomba or Ubiquiti took a very long time or are not available.&lt;br&gt;
Home Assistant, on the other hand, moves very quickly, they have a release every 2-3 weeks, adding new integrations with every minor release while fixing bugs and improving the core - pretty impressive pace. All except one (Landroid) integrations I was looking for are available for Home Assistant and also the Homematic integration has improved a lot (compared to when I looked at HA the first time).&lt;/p&gt;
&lt;h2 id=&quot;a-new-smart-home-automation-system&quot;&gt;A new smart home automation system&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant/#a-new-smart-home-automation-system&quot; aria-labelledby=&quot;a-new-smart-home-automation-system&quot;&gt;#&lt;/a&gt;&lt;p&gt;The old system was running on a RaspberryPI and for Home Assistant I keep it like that. The &lt;a href=&quot;http://hass.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;hass.io&lt;/a&gt; installer is a great help, the new system was up and running in minutes. &lt;a href=&quot;http://Hass.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hass.io&lt;/a&gt; also has a large collection of add-ons. Installing other core services in I need like Mosquitto, InfluxDB or Grafana was just a few clicks.&lt;br&gt;
Many of Home Assistant users run the system and bigger machines like Intel NUC maybe I will upgrade sometime later for now I’m fine with the RaspberryPI.&lt;/p&gt;
&lt;p&gt;My current setup looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2019-05-21-home-assistant/setup.png&quot; alt=&quot;This is our setup&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;Moving over my environment from OpenHab to Home Assistant did not take that long, maybe 7 or 8 evenings and most of the integrations, devices and automations/rules were working. I decided to configure everything file based, also did that in the past. That allows me to keep the entire config in Git, track changes easily and restore the entire system in case something breaks. Following the Home Assistant community best practices I also share my config on GitHub.&lt;/p&gt;
&lt;p&gt;The biggest difference in configuration from my point of view is the rules aka. automatons. OpenHab has a powerful rule programming language and with the new next-gen rule engine any programming language can be used. Creating some rule here is like programming something. In Home Assistant by default one defines the automations in YAML. This is much more descriptive than programming something. At the beginning, I was little skeptical if that fulfills all my needs, but it did expect from some small exceptions where I create Python scripts to do the job. As an alternative one can plugin AppDeamon or NodeRed as well.&lt;/p&gt;
&lt;p&gt;The Lovelace UI of Home Assistant is much more powerful than OpenHab’s sitemap approach for the Basic UI. I know OpenHab has HABPanel as well but I never got really used to it.&lt;/p&gt;
&lt;h2 id=&quot;integrations&quot;&gt;Integrations&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant/#integrations&quot; aria-labelledby=&quot;integrations&quot;&gt;#&lt;/a&gt;&lt;p&gt;Over time we collected a long list of devices from different vendors. These are the platforms, integrations, and devices we use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Homematic&lt;/li&gt;
&lt;li&gt;Philips Hue&lt;/li&gt;
&lt;li&gt;Xaiomi ZigBee sensors&lt;/li&gt;
&lt;li&gt;Apple HomeKit&lt;/li&gt;
&lt;li&gt;Rademacher Duofern&lt;/li&gt;
&lt;li&gt;Amazon Echo&lt;/li&gt;
&lt;li&gt;Sonos Players&lt;/li&gt;
&lt;li&gt;Roomba E5&lt;/li&gt;
&lt;li&gt;Worx Landorid lawnmower robot&lt;/li&gt;
&lt;li&gt;SonOff devices (using &lt;a href=&quot;https://github.com/arendst/Sonoff-Tasmota&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tasmota&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;DIY Arduino devices connected via MQTT&lt;/li&gt;
&lt;li&gt;Uquiti Unifi network equipment&lt;/li&gt;
&lt;li&gt;Qnap NAS&lt;/li&gt;
&lt;li&gt;Fritzbox&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Home Assistant support has integrations for 1000+ systems and devices and also OpenHab’s add-on list is at the same length. Add details list of all hubs, devices, sensors etc. I used is available on my &lt;a href=&quot;https://github.com/mhaack/home-assistant-config&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant config&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/home-assistant-config&quot; label=&quot;Home Assistant config&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;h2 id=&quot;community-support&quot;&gt;Community support&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant/#community-support&quot; aria-labelledby=&quot;community-support&quot;&gt;#&lt;/a&gt;&lt;p&gt;I think both platforms have a great community, always will support and help. But to me, it feels that &lt;a href=&quot;https://www.home-assistant.io/help/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;HA community&lt;/a&gt; is much more active and bigger. OpenHab community has a few very knowledgeable members. They are very active and supportive but at the end of the day, it very often comes back to a small group which answers the majority of questions.&lt;/p&gt;
&lt;p&gt;Home Assistant community, in contrast, is much bigger, it is not only the active forum, they also have a Discord server to get in touch with community and core developers, many people share their configs public on GitHub (which was a huge boost for me when I started to migrate) or running very active YouTube channels. And there is a regular podcast as well.&lt;br&gt;
So far I only asked a handful of questions on the community forum and always got help.&lt;/p&gt;
&lt;h2 id=&quot;some-final-thoughts&quot;&gt;Some final thoughts&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/home-assistant/#some-final-thoughts&quot; aria-labelledby=&quot;some-final-thoughts&quot;&gt;#&lt;/a&gt;&lt;p&gt;While I would consider my switch to Home Assistant as done and already have archived my OpenHab installation I know it will never be really finished. There is always some stuff to tinker and improve. I already have a to-do list of 15 items 😉&lt;/p&gt;
&lt;p&gt;I am sure, for me, moving to Home Assistant was the right choice. And I definitely recommend to everybody who is willing to invest some time into building a local and flexible smart home solution to have a look at Home Assistant. Is Home Assistant a perfect solution? No, no smart home hub is, all have strengths and weaknesses. Also as written above OpenHab is a mature piece of software. But among these both - Home Assistant and OpenHab - Home Assistant is now the perfect fit for me.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>IoT enabled Jack-O-Lantern Flamethrower</title>
    <link href="https://markus-haack.com/halloween-fire-pumpkin/"/>
    <updated>2018-11-03T00:00:00Z</updated>
    <id>https://markus-haack.com/halloween-fire-pumpkin/</id>
    <content type="html">&lt;h2 id=&quot;jack-o-lantern-flamethrower&quot;&gt;Jack-O-Lantern Flamethrower&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#jack-o-lantern-flamethrower&quot; aria-labelledby=&quot;jack-o-lantern-flamethrower&quot;&gt;#&lt;/a&gt;&lt;p&gt;A flame-throwing jack-o’-lantern is a real Halloween highlight and definitely something to impress the trick-or-treaters and your neighbors. An internet controlled IoT flame throwing jack-o’-lantern is even better.&lt;/p&gt;
&lt;p&gt;This Jack-O-Lantern is internet connected and can be controlled via MQTT protocol. That way the project can be integrated into a home automation solution like &lt;a href=&quot;https://www.openhab.org&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenHab&lt;/a&gt; or &lt;a href=&quot;https://www.home-assistant.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Home Assistant&lt;/a&gt; to control the flamethrower from there or via Alexa or Google Home.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jMbAKtgw04k&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=jMbAKtgw04k&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You are “not so much” interested in Halloween? This is for you as well, a little fire will make even the most bold of people think twice about approaching your door.&lt;/p&gt;
&lt;p&gt;This is actually my second version of the flame-throwing jack-o’-lantern 😀 I already build one last year using a modified room spray (like &lt;a href=&quot;https://www.hackster.io/Dlbates/iot-flaming-and-talking-pumpkin-using-aws-and-esp8266-49934f&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this project&lt;/a&gt;). But these do not allow to control the flame directly so I decided I need to build a more pro version which allows controlling the duration of the flame.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: This pumpkin and playing with fire is extremely dangerous and you definitely should not make one of these. I do not endorse the manufacture or use of flamethrowers jack-o’-lanterns. The following project description is posted here are for research and entertainment purposes only.&lt;/p&gt;
&lt;p&gt;If you are going to rebuild this project you do it at your own risks. Read the warning above - twice! Also, make sure the place the pumpkin at a safe location to not harm anybody or burn down your own house!&lt;/p&gt;
&lt;h3 id=&quot;hardware&quot;&gt;Hardware&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#hardware&quot; aria-labelledby=&quot;hardware&quot;&gt;#&lt;/a&gt;&lt;p&gt;The following components are needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A big pumpkin&lt;/li&gt;
&lt;li&gt;Penetrating fluid like WD-40 or cheaper replacement, it’s just going to be burned anyway&lt;/li&gt;
&lt;li&gt;A tea candle&lt;/li&gt;
&lt;li&gt;Material for the flamethrower construction to hold the spray can&lt;/li&gt;
&lt;li&gt;ESP8266 (Wemos D1 mini, Nodemcu) or ESP32&lt;/li&gt;
&lt;li&gt;1-3 PIR motion sensors&lt;/li&gt;
&lt;li&gt;Strong servo motor&lt;/li&gt;
&lt;li&gt;SSD1306 display (optional)&lt;/li&gt;
&lt;li&gt;Prototyping board&lt;/li&gt;
&lt;li&gt;male &amp;amp; female pin headers&lt;/li&gt;
&lt;li&gt;USB cable and power supply&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The display is not really needed for this project, it is just used for fun to display some little animation and information which of the motion sensors triggered the fire.&lt;/p&gt;
&lt;p&gt;As usual, I got the most parts from &lt;a href=&quot;https://www.aliexpress.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Aliexpress&lt;/a&gt; but all the parts should be available via other sources like ebay or &lt;a href=&quot;http://amazon.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;amazon.com&lt;/a&gt; as well.&lt;/p&gt;
&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#tools&quot; aria-labelledby=&quot;tools&quot;&gt;#&lt;/a&gt;&lt;p&gt;These are the tools needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A cutting knife&lt;/li&gt;
&lt;li&gt;A marker&lt;/li&gt;
&lt;li&gt;Soldering iron with solder&lt;/li&gt;
&lt;li&gt;Tools to construct the flame-throwing mechanism&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-flamethrower&quot;&gt;The flamethrower&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#the-flamethrower&quot; aria-labelledby=&quot;the-flamethrower&quot;&gt;#&lt;/a&gt;&lt;p&gt;Ok, again: only build this if you have read the warning and are sure what you are doing!&lt;/p&gt;
&lt;p&gt;The key element of this project is burning penetrating fluid which if sprayed directly into a candle burns like a small flamethrower.&lt;/p&gt;
&lt;p&gt;There are multiple ways to build the flamethrower. I used old wood pieces covered with aluminum foil to mount the spray can and candle. Maybe not the optimal solution but working, using metal parts would be a slightly better way.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/fire-1.jpg&quot; alt=&quot;flamethrower mechanism&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;Bend the thick wire like on the picture above. It should be a big lever as possible to make the most of the power of the servo motor. Hot glue or screw down the servo at the side of the construction and mount it with the wire. The lever will press down the spray nozzle when the servo is activated.&lt;/p&gt;
&lt;h2 id=&quot;the-pumpkin&quot;&gt;The pumpkin&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#the-pumpkin&quot; aria-labelledby=&quot;the-pumpkin&quot;&gt;#&lt;/a&gt;&lt;p&gt;The pumpkin is, of course, the most important part for a project like this 😉&lt;/p&gt;
&lt;p&gt;First cut around the stem of the pumpkin at an angle. The top cover should be big enough, so you can later easily mount the flame thrower construction. After done cutting all the way around, remove the stem and the guts from the pumpkin. Depending on the size of the project you also need to cut out the bottom to fit in the flamethrower construction. If you have a very large pumpkin this might not be needed.&lt;/p&gt;
&lt;p&gt;Use the marker to mark jack-o’-lanterns face. The mouth should be at the position of the spray nozzle, so that the flame can flow out well. Make sure it is big enough so that there is no setback of the flame. I the pumpkin is not big enough the flame can also be fired through a bigger nose hole. Cut the face as marked.&lt;/p&gt;
&lt;p&gt;Place the flamethrower construction inside the pumpkin. Fix it with hot glue to stabilize it. Connect the electronics with the servo motor wires. If enough space the electronics can be placed inside the pumpkin and the PIR sensors can be inside jack-o’-lanterns eyes. Make sure you have a sufficient distance between the electronic parts and the flame.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/fire-2.jpg&quot; alt=&quot;pumpkin&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you have a smaller pumpkin, with not enough space inside the electronics can also be placed outside. I prefer this setup because it makes you more flexible when placing the PIR motion sensors.&lt;/p&gt;
&lt;p&gt;The PIR motions sensors got some protection cover and habe been places to recognize the movement of approaching trick-or-treaters.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/fire-4.jpg&quot; alt=&quot;pumpkin&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-electronics&quot;&gt;The electronics&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#the-electronics&quot; aria-labelledby=&quot;the-electronics&quot;&gt;#&lt;/a&gt;&lt;p&gt;The PIR motion sensors and the servo must be connected to the Wemos / ESP8266 board, you can use any of the Dx pins, expect D0 &amp;amp; D1. These two will be used by the OLED display. Connect power via USB adapter or battery pack.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/fritzing.png&quot; alt=&quot;Fritzing Diagram&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-software&quot;&gt;The software&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#the-software&quot; aria-labelledby=&quot;the-software&quot;&gt;#&lt;/a&gt;&lt;p&gt;The software project for the ESP8288 board can be found in my &lt;a href=&quot;https://github.com/mhaack/halloween-pumpkin-fire&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt; repository.&lt;/p&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/halloween-pumpkin-fire&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;p&gt;After uploading the software to the board it has to be configured to connect to WiFi and MQTT. Homie provides multiple ways to do this, I prefer to create and upload a config file. Alternatively, the configuration UI can be used.&lt;/p&gt;
&lt;p&gt;My test setup looked like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/fire-3.jpg&quot; alt=&quot;pumpkin&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The code is written in C++, &lt;code&gt;halloween.cpp&lt;/code&gt; is the main class.&lt;/p&gt;
&lt;p&gt;The following software libraries are used. If using PlatformIO all dependencies are resolved automatically.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie V2&lt;/a&gt; including dependencies&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/squix78/esp8266-oled-ssd1306&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SSD1306 driver for ESP8266 platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arduino-libraries/NTPClient&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NTPClient to connect to a time server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optionally PlatformIO environment for building the code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-iot-part&quot;&gt;The IoT part&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#the-iot-part&quot; aria-labelledby=&quot;the-iot-part&quot;&gt;#&lt;/a&gt;&lt;p&gt;I used &lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie&lt;/a&gt; to better modularize the software parts into dedicated “nodes” to control the servo, the display and get the PIR motion sensor inputs. Homie provides the MQTT protocol support, see &lt;a href=&quot;https://git.io/homieiot&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie specification&lt;/a&gt; for details.&lt;/p&gt;
&lt;h3 id=&quot;mqtt-commands-and-config&quot;&gt;MQTT commands and config&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#mqtt-commands-and-config&quot; aria-labelledby=&quot;mqtt-commands-and-config&quot;&gt;#&lt;/a&gt;&lt;p&gt;The flamethrower supports one import command: switch on the fire 😀. It can be triggered via MQTT with &lt;code&gt;homie/&amp;lt;device id&amp;gt;/fire/on/set&lt;/code&gt; with the value &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Command line example:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mosquitto_pub &lt;span class=&quot;token parameter variable&quot;&gt;-h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;mqtt broker host&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-t&lt;/span&gt; homie/&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;device id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;/fire/on/set &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where &amp;lt;devie id&amp;gt; is the name of the device assigned during configuration and &amp;lt;mqtt broker host&amp;gt; the hostname or ip address of your MQTT broker. This should make it easy to integrate it into home automation solution. I run OpenHab and integrated it there, just for the fun of controlling the fire via my mobile.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/openhab.jpg&quot; alt=&quot;Openhab&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The following config parameters are available via config file or MQTT message (see Homie documentation how to use):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;fireInterval&lt;/td&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;min. interval in sec between flame activations (if motion was detected) to avoid permanent fire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fireDuration&lt;/td&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;duration of one flame shot in ms aka. time until servo moves back to initial position&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flipScreen&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;flip the display screen vertically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;the-final-result&quot;&gt;The final result&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/halloween-fire-pumpkin/#the-final-result&quot; aria-labelledby=&quot;the-final-result&quot;&gt;#&lt;/a&gt;&lt;p&gt;This is the Jack-O-Lantern on fire.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-11-03-halloween-fire-pumpkin/pumpkin-fire.jpg&quot; alt=&quot;Jack-O-Lantern&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Creepy Halloween Eyes</title>
    <link href="https://markus-haack.com/creepy-halloween-eyes/"/>
    <updated>2018-10-30T00:00:00Z</updated>
    <id>https://markus-haack.com/creepy-halloween-eyes/</id>
    <content type="html">&lt;h2 id=&quot;story&quot;&gt;Story&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#story&quot; aria-labelledby=&quot;story&quot;&gt;#&lt;/a&gt;&lt;p&gt;Halloween is coming in a few days and here is the first of my Halloween projects this year. I wanted to rebuild an cool Arduino project I found on &lt;a href=&quot;https://youtu.be/ryUNHPJ3leY&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;YouTube&lt;/a&gt; - the pumpkin with moving eyes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8-jia1-PfCQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.youtube.com/watch?v=8-jia1-PfCQ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The project is not complicated and easy to rebuild. Now we see how to do that.&lt;/p&gt;
&lt;h3 id=&quot;parts&quot;&gt;Parts&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#parts&quot; aria-labelledby=&quot;parts&quot;&gt;#&lt;/a&gt;&lt;p&gt;The following components are used for this project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A pumpkin&lt;/li&gt;
&lt;li&gt;10 creepy plastic eyes&lt;/li&gt;
&lt;li&gt;10 mini servos, for example SG90&lt;/li&gt;
&lt;li&gt;Thin wire&lt;/li&gt;
&lt;li&gt;Thin nails&lt;/li&gt;
&lt;li&gt;Plastic tube (inner diameter a little bit bigger than the eyes)&lt;/li&gt;
&lt;li&gt;Wooden or plastic stick with ~ 8mm diameter&lt;/li&gt;
&lt;li&gt;Wemos / Lolin D1 (or equivalent NodeMCU board)&lt;/li&gt;
&lt;li&gt;Wemos ProtoBoard (or any other protoboard will do as well)&lt;/li&gt;
&lt;li&gt;PCB male and female pin header&lt;/li&gt;
&lt;li&gt;AA Battery box holding 4 batteries&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#tools&quot; aria-labelledby=&quot;tools&quot;&gt;#&lt;/a&gt;&lt;p&gt;These are the tools needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A cutting knife&lt;/li&gt;
&lt;li&gt;A small drill&lt;/li&gt;
&lt;li&gt;A marker&lt;/li&gt;
&lt;li&gt;Some pliers&lt;/li&gt;
&lt;li&gt;Hot glue&lt;/li&gt;
&lt;li&gt;Soldering iron with solder&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;eyes&quot;&gt;Eyes&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#eyes&quot; aria-labelledby=&quot;eyes&quot;&gt;#&lt;/a&gt;&lt;p&gt;The trickiest part of this project are the eyes. Tricky because they should be assembled all in the same way, especially the length of the wooden stick and position of the servo should be equally to use the same servo swing parameters for all eyes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Instructions:&lt;/em&gt;&lt;br&gt;
Cut the tube and the wooden stick to the same length ~ 40mm. Hot glue the wooden stick to the back of the eye. Drill a hole at the end of the wooden stick. Also drill a hole into the side of the eye and one on the opposite side (see photo). Put the nail through the holes, place the eye inside the tube and hot glue both ends onto the tube edge. Move the stick at the back side of the tube should now be moving the eye.&lt;/p&gt;
&lt;p&gt;To mount the servo hot glue it in a 90-degree angle to the wooden stick on the back side of the plastic tube. Use the wire to connect servo with the end of the wooden stick. The wire must be strong enough not to bend and move the eye.&lt;/p&gt;
&lt;h2 id=&quot;electronics&quot;&gt;Electronics&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#electronics&quot; aria-labelledby=&quot;electronics&quot;&gt;#&lt;/a&gt;&lt;p&gt;To move 10 servos with a small Wemos board we need some extra power. These small ESP8266 boards can only handle a current of ~500 mA in total max, enough to control two or three servo motors. To solve this, I use AA batteries as an additional power source to run all 10 servos. 2 boxes of 4 AA batteries in parallel provide 6 volts and enough juice to run the servos.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-10-30-halloween-creepy-eyes/fritzing.png&quot; alt=&quot;Fritzing Diagram&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Instructions:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Solder the pin header to the Wemos D1 and solder female pin header to the prototype board to hold the D1. On the opposite side, in the middle of the prototype board solder 3 rows of male pin header with 10 pins each. These are used to connect the 10 servos. 2 rows can be connected with solder for the ground and positive lines. The pins of the third row are connected to the digital pins of the Wemos D1. I used D0 to D8 and TX pin. The ground row is connected with the ground pin of the Wemos board as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-10-30-halloween-creepy-eyes/electronics-3.jpg&quot; alt=&quot;Electronics&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The battery box(es) are connected with ground row (black wire) and positive row (red wire). If more than one battery box is used to provide more power they must be connected in parallel.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-10-30-halloween-creepy-eyes/electronics-1.jpg&quot; alt=&quot;Electronics&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;software&quot;&gt;Software&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#software&quot; aria-labelledby=&quot;software&quot;&gt;#&lt;/a&gt;&lt;p&gt;Compared to the hardware assembly the software is relatively simple. The small program controls an array of 10 servos and changes them randomly between an min and max position value. A short delay makes the overall eye movements more random. The full code is on &lt;a href=&quot;https://github.com/mhaack/halloween-pumpkin-eyes&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-pumpkin&quot;&gt;The pumpkin&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#the-pumpkin&quot; aria-labelledby=&quot;the-pumpkin&quot;&gt;#&lt;/a&gt;&lt;p&gt;The pumpkin is, of course, the most important part of this project 😉&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Instructions:&lt;/em&gt;&lt;br&gt;
Use the marker to mark 10 circles with the size of the plastic tube used for the eyes. These should not be too close to each other to still have enough space inside.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-10-30-halloween-creepy-eyes/pumpkin-1.jpg&quot; alt=&quot;Pumkpin&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;Cut around the stem of the pumpkin at an angle. Make it big enough, this will make connecting the eyes later much easier. After done cutting, all the way around, remove the stem and the guts from the pumpkin.&lt;/p&gt;
&lt;p&gt;Next cut the 10 circle holes for the eyes. Make sure to cut with an angle to get a little bigger hole inside.&lt;/p&gt;
&lt;p&gt;Place the eyes in the holes and fix them from the inside with hot glue. The challenge is hot glue does not stick so well on pumpkin pulp. I turned screws into the pulp to help to fix it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-10-30-halloween-creepy-eyes/pumpkin-2.jpg&quot; alt=&quot;Pumkpin&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;When placing the eyes make sure the servo will not be blocked.&lt;/p&gt;
&lt;p&gt;Connect all servos to the headers on the board. Pay attention to the right connection and polarity of the connectors. Place the batteries into the boxes and put the whole electronics into a plastic bag or some box to protect it.&lt;/p&gt;
&lt;h2 id=&quot;the-final-result&quot;&gt;The final result&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/creepy-halloween-eyes/#the-final-result&quot; aria-labelledby=&quot;the-final-result&quot;&gt;#&lt;/a&gt;&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2018-10-30-halloween-creepy-eyes/pumpkin-3.jpg&quot; alt=&quot;Pumkpin&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;I placed some Bluetooth speaker next to the pumpkin playing some Halloween tunes from YouTube to have nice spooky sound effects.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>433Mhz &lt;-&gt; MQTT gateway with some extras</title>
    <link href="https://markus-haack.com/mqtt-433mhz-gateway-homie/"/>
    <updated>2017-01-22T00:00:00Z</updated>
    <id>https://markus-haack.com/mqtt-433mhz-gateway-homie/</id>
    <content type="html">&lt;h2 id=&quot;smart-home-433mhz-rf-%3C-%3E-mqtt-gateway-with-some-extras&quot;&gt;Smart Home 433Mhz RF &amp;lt;-&amp;gt; MQTT Gateway with Some Extras&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#smart-home-433mhz-rf-%3C-%3E-mqtt-gateway-with-some-extras&quot; aria-labelledby=&quot;smart-home-433mhz-rf-%3C-%3E-mqtt-gateway-with-some-extras&quot;&gt;#&lt;/a&gt;&lt;p&gt;The MQTT-433mhz-gateway-homie project is a simple bidirectional gateway to transmit and receive 433Mhz RF signals connected to MQTT. The gateway is built with a cost-effective ESP8266 WiFi chip (I used a Wemos D1 mini, NodeMCU will do as well), simple 433Mhz RF modules and an additional BMP085 sensor.&lt;/p&gt;
&lt;p&gt;It enables you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;receive MQTT data from a topic and send the 433Mhz signal.&lt;/li&gt;
&lt;li&gt;receive 433Mhz signal from a traditional remote, optional map it to a channel and publish the data to a MQTT topic.&lt;/li&gt;
&lt;li&gt;additionally, a simple temperature sensor can record the room temperature of the room where the gateway is installed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The software is based on &lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie&lt;/a&gt; to enable easy integration with home automation systems like &lt;a href=&quot;http://www.openhab.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenHab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The final assembly looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2017-01-22-mqtt-433mhz-gateway-homie/electronics-1.jpg&quot; alt=&quot;final assembly&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;hardware&quot;&gt;Hardware&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#hardware&quot; aria-labelledby=&quot;hardware&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ESP8266 (Wemos D1 mini, Nodemcu)&lt;/li&gt;
&lt;li&gt;RF Receiver 433Mhz&lt;/li&gt;
&lt;li&gt;RF Transmitter 433MHz&lt;/li&gt;
&lt;li&gt;BMP085 or BMP180 sensor breakout&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I got the RF modules from &lt;a href=&quot;https://www.sparkfun.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.sparkfun.com&lt;/a&gt;, others will do as well. Additional I got some &lt;a href=&quot;https://www.wemos.cc/product/protoboard.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Wemos Protoboards&lt;/a&gt;, a USB power supply with a very short cable&lt;br&gt;
and an &lt;a href=&quot;https://www.amazon.de/gp/product/B00PZYMLJ4&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;enclosure&lt;/a&gt; to keep all together.&lt;/p&gt;
&lt;p&gt;The circuit inside the enclosure box:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2017-01-22-mqtt-433mhz-gateway-homie/electronics-2.jpg&quot; alt=&quot;final assembly in box&quot; class=&quot;small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;building-the-circuit&quot;&gt;Building the circuit&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#building-the-circuit&quot; aria-labelledby=&quot;building-the-circuit&quot;&gt;#&lt;/a&gt;&lt;p&gt;The wireing of the gateway project is very easy. The sensor, the transmitter and the receiver must be connected to VIN &amp;amp; GND and the GPIO pins of the ESP8266 board as shown in the table below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2017-01-22-mqtt-433mhz-gateway-homie/fritzing.jpg&quot; alt=&quot;Fritzing Diagram&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Wemos D1 mini&lt;/th&gt;
&lt;th&gt;BMP085&lt;/th&gt;
&lt;th&gt;RF Receiver&lt;/th&gt;
&lt;th&gt;RF Transmitter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5V&lt;/td&gt;
&lt;td&gt;VIN&lt;/td&gt;
&lt;td&gt;VIN&lt;/td&gt;
&lt;td&gt;VIN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;DATA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D1&lt;/td&gt;
&lt;td&gt;SCL&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D2&lt;/td&gt;
&lt;td&gt;SDA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D5&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;DATA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#software&quot; aria-labelledby=&quot;software&quot;&gt;#&lt;/a&gt;&lt;p&gt;The following software libraries are used. When using PlatformIO all dependencies are resolved automatically.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie V2&lt;/a&gt; (dev) including dependencies&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sui77/rc-switch&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;RCSwitch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/adafruit/Adafruit_BMP085_Unified&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adafruit BMP085 Unified&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/adafruit/Adafruit_Sensor&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adafruit Unified Sensor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optionally PlatformIO environment for building the code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/mqtt-433mhz-gateway-homie&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;h3 id=&quot;mqtt&quot;&gt;MQTT&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#mqtt&quot; aria-labelledby=&quot;mqtt&quot;&gt;#&lt;/a&gt;&lt;p&gt;For detailed documentation of the MQTT topics and commands used see &lt;a href=&quot;https://homie-esp8266.readme.io/docs&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sample gateway messages:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# sensor temperature reading&lt;/span&gt;
homie/mqtt-gateway-livingroom/temperature/degrees &lt;span class=&quot;token number&quot;&gt;23.70&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Temperature value send from device.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# send RF command via MQTT &amp;amp; response&lt;/span&gt;
homie/mqtt-gateway-livingroom/MQTTto433/on/set &lt;span class=&quot;token number&quot;&gt;1394001&lt;/span&gt;
homie/mqtt-gateway-livingroom/MQTTto433/on &lt;span class=&quot;token number&quot;&gt;1394001&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First line: MQTT command send from MQTT client or smart home solution. Translates into the code send by the RF transmitter.&lt;br&gt;
Second line: Response from a device after the RF signal was transmitted.&lt;/p&gt;
&lt;h2 id=&quot;config&quot;&gt;Config&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#config&quot; aria-labelledby=&quot;config&quot;&gt;#&lt;/a&gt;&lt;p&gt;The following config parameters are available via MQTT message (see Homie documentation how to use):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;temperatureInterval&lt;/td&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;temperature reading interval in seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;temperatureOffset&lt;/td&gt;
&lt;td&gt;double&lt;/td&gt;
&lt;td&gt;temperature offset (-/+) to correct the sensor reading, for example if used in enclosure box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;channels&lt;/td&gt;
&lt;td&gt;const char*&lt;/td&gt;
&lt;td&gt;mapping of 433MHz signals to mqtt channels, useful if used with OpenHab&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All configs can be set during the init procedure of the module or via MQTT messages (see Homie specification).&lt;/p&gt;
&lt;p&gt;Sample config:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;settings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &quot;o&lt;span class=&quot;token number&quot;&gt;-1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;139400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;o&lt;span class=&quot;token number&quot;&gt;-2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;139707&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;o&lt;span class=&quot;token number&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1398097&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1398100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;o&lt;span class=&quot;token number&quot;&gt;-4&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;139803&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;i&lt;span class=&quot;token number&quot;&gt;-1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;44618&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;i&lt;span class=&quot;token number&quot;&gt;-2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;44620&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;i&lt;span class=&quot;token number&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;44623&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;i&lt;span class=&quot;token number&quot;&gt;-4&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;44638&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;i&lt;span class=&quot;token number&quot;&gt;-5&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;44700&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;;“&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &quot;temperatureOffset“&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;-2.4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;temperatureInterval&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;credits&quot;&gt;Credits&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-433mhz-gateway-homie/#credits&quot; aria-labelledby=&quot;credits&quot;&gt;#&lt;/a&gt;&lt;p&gt;This project is was inspired by 1 Technophile’s &lt;a href=&quot;https://1technophile.blogspot.de/2016/09/433tomqttto433-bidirectional-esp8266.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;433toMQTTto433&lt;/a&gt; solution.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Homie Sensor project with BME280</title>
    <link href="https://markus-haack.com/mqtt-bme280-homie/"/>
    <updated>2017-01-11T00:00:00Z</updated>
    <id>https://markus-haack.com/mqtt-bme280-homie/</id>
    <content type="html">&lt;h2 id=&quot;homie-bme280---the-sensor&quot;&gt;Homie BME280 - The Sensor&lt;/h2&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-bme280-homie/#homie-bme280---the-sensor&quot; aria-labelledby=&quot;homie-bme280---the-sensor&quot;&gt;#&lt;/a&gt;&lt;p&gt;The mqtt-bme280-homie sensor project is a small and easy to integrate temperature, air pressure and humidity monitoring solution with an extra SSD1306 OLED display. Sensor data is send via MQTT and displayed on the small screen. Local time is loaded via NTP. The project is built with a cost-effective ESP8266 WiFi chip.&lt;/p&gt;
&lt;p&gt;The software is based on &lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie&lt;/a&gt; to enable an easy integration with home automation systems like &lt;a href=&quot;http://www.openhab.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenHab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://markus-haack.com/assets/images/2017-01-11-mqtt-bme280-homie/box.jpg&quot; alt=&quot;fully assembled&quot; class=&quot;x-small&quot; eleventy:widths=&quot;650,960,1400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The display shows 4 screens (can be extended) in a carousel mode. temperature, humidity, air pressure and some status like IP address.&lt;/p&gt;
&lt;h3 id=&quot;hardware-components&quot;&gt;Hardware components&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-bme280-homie/#hardware-components&quot; aria-labelledby=&quot;hardware-components&quot;&gt;#&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;ESP8266 (Wemos D1 mini, Nodemcu)&lt;/li&gt;
&lt;li&gt;BME280 sensor breakout&lt;/li&gt;
&lt;li&gt;SSD1306 OLED display&lt;/li&gt;
&lt;li&gt;USB power supply and cable&lt;/li&gt;
&lt;li&gt;Enclosure&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I got the BME280 breakout form &lt;a href=&quot;https://www.adafruit.com/product/2652&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adafruit&lt;/a&gt;, others will do as well. The SSD1306 OLED displays I ordered at Aliexpress. This &lt;a href=&quot;https://www.amazon.de/gp/product/B00PZYMLJ4&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;enclosure&lt;/a&gt; keeps everything together. Wiring is pretty simple since both sensor and display connect via I2C bus with the ESP.&lt;/p&gt;
&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-bme280-homie/#software&quot; aria-labelledby=&quot;software&quot;&gt;#&lt;/a&gt;&lt;p&gt;The following software libraries are used. If using PlatformIO all dependencies are resolved automatically.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/marvinroger/homie-esp8266&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Homie V2&lt;/a&gt; (dev) including dependencies&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/adafruit/Adafruit_BME280_Library&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adafruit BME280 Driver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/adafruit/Adafruit_Sensor&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Adafruit Unified Sensor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/squix78/esp8266-oled-ssd1306&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;SSD1306 driver for ESP8266 platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arduino-libraries/NTPClient&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NTPClient to connect to a time server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optionally PlatformIO environment for building the code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;github-badge repo=&quot;mhaack/mqtt-bme280-homie&quot;&gt;&lt;/github-badge&gt;&lt;/p&gt;
&lt;h3 id=&quot;reading-sensor-data&quot;&gt;Reading sensor data&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-bme280-homie/#reading-sensor-data&quot; aria-labelledby=&quot;reading-sensor-data&quot;&gt;#&lt;/a&gt;&lt;p&gt;The senoor data is published via MQTT according to the Homie spec. It can be read with any MQTT client:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;homie/mqtt-sensor-livingroom/sensor/temperature &lt;span class=&quot;token number&quot;&gt;24.58&lt;/span&gt;
homie/mqtt-sensor-livingroom/sensor/humidity &lt;span class=&quot;token number&quot;&gt;32.67&lt;/span&gt;
homie/mqtt-sensor-livingroom/&lt;span class=&quot;token variable&quot;&gt;$stats&lt;/span&gt;/signal &lt;span class=&quot;token number&quot;&gt;94&lt;/span&gt;
homie/mqtt-sensor-livingroom/&lt;span class=&quot;token variable&quot;&gt;$stats&lt;/span&gt;/uptime &lt;span class=&quot;token number&quot;&gt;17126998&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;config&quot;&gt;Config&lt;/h3&gt;
&lt;a class=&quot;heading-anchor&quot; href=&quot;https://markus-haack.com/mqtt-bme280-homie/#config&quot; aria-labelledby=&quot;config&quot;&gt;#&lt;/a&gt;&lt;p&gt;The software can be configured via MQTT (or Homie config file), also while running. You can set &lt;code&gt;sensorInterval&lt;/code&gt; to control the reading intervals and how often data will be published via MQTT. Additionally a &lt;code&gt;temperatureOffset&lt;/code&gt; can be set, especially if installed within some box the BME280 sensor will give some slightly of temperate values because of the heat the  ESP chip emits. Rotating the display is also possible by set the &lt;code&gt;flipScreen&lt;/code&gt; parameter to true.&lt;/p&gt;
</content>
  </entry>
</feed>