Skip to main content

Command Palette

Search for a command to run...

Silent by Design: Blinds Automation That Disappears

The Digital Homestead · Home Automation

Published
7 min read
Silent by Design: Blinds Automation That Disappears

The Digital Homestead · Home Automation

In my last post I went deep on the firewall that keeps my network segmented and secure. Today I'm shifting to principle 03: Simplicity; using my blinds automation as the case study.

Blinds are one of those things that seem too simple to automate intelligently, and too trivial to bother building properly. That assumption is wrong on both counts. Done right, a blinds automation disappears entirely. Nobody in the house thinks about the blinds. They open when they should. They close when they should. When you come downstairs on a Saturday morning the light is already right. That's the goal.

Getting there took more iteration than I expected.

The Hardware

The blinds run on eWand Zigbee motors — one per blind, installed inside the standard wand mechanism. They pair directly into ZHA (Zigbee Home Automation) in Home Assistant and appear as switch entities. No hub, no cloud, no app.

The Zigbee integration was deliberate. These motors run locally. If the internet is down, the blinds still work. If eWand's servers go down (or the company disappears), nothing changes. I control the device; I don't rent access to it.

The one trade-off with eWand is that they expose as switches rather than proper cover entities — on or off, not a position percentage. For most blinds, that's fine. You want them open or closed, not 47% open.

Before buying any smart home hardware I check one thing: does it work locally with Home Assistant without needing the manufacturer's cloud? eWand does. That's the whole criteria.


The Architecture: One Script to Rule All Zones

Most automations I see hardcode device entity IDs directly into their logic. It works until you add a device, rename something, or reorganize a room — then you're hunting through YAML to patch five different automations.

I took a different approach. Every blind in the house carries two Home Assistant labels: Blinds and its zone — Living Room, Breakfast Room, Dining Room, Primary Bathroom, or Sun Room. The central script.blinds doesn't know which entities exist. It discovers them at runtime.

devices: >
  {%- set data = namespace(deviceList=[]) -%}
  {% set blinds = label_entities('Blinds') %}
  {% set room = label_entities(zone) %}
  {%- for x in blinds -%}
    {%- if x in room -%}
      {%- set data.deviceList = data.deviceList + [x] -%}
    {%- endif -%}
  {% endfor %}
  {{data.deviceList}}

The script takes two arguments: order (open or close) and zone. It resolves the right devices dynamically, runs the command, and retries anything that didn't respond. Adding a new blind to the living room means applying two labels in Home Assistant. The automation picks it up automatically on the next run.

That's the kind of design that survives years of hardware changes without accumulating technical debt.


The Safety Guard

Not every room should open on the same schedule. The primary bathroom has different morning timing from the living room. Some zones; such as the living room and sunroom benefit from early light regardless of the day. Others should stay closed on weekdays until people are actually moving around.

The script enforces this with a single template condition that gates all open commands. Three cases allow the script to proceed:

Close commands always execute. Privacy and heat control are non-negotiable. If the order is to close, it runs immediately, no conditions checked.

Special zones have restricted schedules. The Breakfast Room and Dining Room are flagged as specialScheduleZones. These zones are restricted to a workday check where they only open on Weekends and Holidays

Weekends and holidays are unblocked. When the Workday sensor is off, all zones open on their normal schedules. The system knows it's Saturday.

One template condition, three cases, clean logic. No per-zone automation files, no duplicate guards scattered across the system.


The Reliability Loop

Zigbee devices occasionally miss a command. It's rare, but a blind that doesn't respond means one blind closed out of three in the living room — which is worse than none at all.

The script handles this with a built-in retry loop. After sending a command, it waits ten seconds, checks whether each device is in the expected state, and re-sends to any that aren't. It keeps doing this until every device in the zone matches the target state.

repeat:
  while:
    - condition: template
      value_template: |
        {% set data = namespace(status = false) %}
        {% for device in devices %}
          {% if states(device) != order %}
            {% set data.status = true %}
          {% endif %}
        {% endfor %}
        {{data.status}}
  sequence:
    - action: switch.turn_{{order}}
      target:
        entity_id: "{{ devices }}"
    - delay:
        seconds: 10

The automation doesn't require a perfect mesh. It requires an eventually consistent one. That's a more honest target.


The Three Triggers

Three things change the state of the blinds in this house:

Sundown State Change is the primary driver. A SunDown input boolean toggles at sunrise and sunset, automatically calculated by Home Assistant based on location. At sunset, all zones close in parallel — seven simultaneous script calls, one per zone. At sunrise, the first-floor zones open. The primary bedroom is intentionally excluded from the sunrise open; that one has its own logic.

Primary Bathroom Morning Schedule runs independently. On workdays, it opens at 8 AM. On weekends and holidays, it waits until 9 AM. The workday condition is checked at the trigger level here, since the timing difference is meaningful and zone-specific.

Temperature Override is the one that bypasses everything else. When the outside temperature sensor crosses 78°F, all zones close. Immediately. No schedule check, no zone exceptions. Heat gain is a physical problem and it doesn't care what day of the week it is.

The temperature close was the automation I resisted building longest. It felt unnecessary. Then I had a week in August where the AC was running hard while the blinds were open and I couldn't figure out why the house wasn't cooling. It was not unnecessary.


Voice Control Without Confusion

eWand motors appear as switch entities in Home Assistant — which means a voice assistant would say "turn on" and "turn off" instead of "open" and "close." That's a small thing that makes voice control feel broken.

The fix is an abstraction layer. Each zone gets a Cover helper built from its switch group. The Cover entity exposes "open" and "close" semantics, hides the on/off language, and maps to the underlying physical switches. Only the cover entities are exposed to voice assistants. The physical switches stay hidden.

Zone Exposed Entity
Breakfast Room cover.breakfast_room_blinds
Dining Room cover.blinds_dining_room
Living Room cover.living_room_blinds
Primary Bathroom cover.blinds_primary_bathroom
Sun Room cover.sunroom_blinds

"Hey Google, close the living room blinds" works the way you'd expect, because the entity it's talking to is modeled as a blind, not a light switch.


The Result

The blinds in this house have been running without manual intervention for over three years. Nobody in the family thinks about them. They open in the morning, close at sunset, and close themselves when it's hot outside. Physical switches still work — walk up to any blind and twist the wand and it responds immediately, same as before automation.

That's what principle 03 actually looks like in practice. Not a clever system with fifteen configuration options. A system that handles the routine cases automatically, stays out of the way when someone wants manual control, and has exactly one interface for each use case: time, sun position, temperature, and voice.

When I evaluate whether an automation is worth keeping, I ask one question: has anyone complained about it? The blinds have never come up. That's the benchmark.


The Blueprint

Part 1 of 3

This is the Blueprint. A professional-grade smart home isn't bought; it's engineered. This series documents the transition from consumer gadgets to a hardened, local-first infrastructure. From UDM SE network segmentation and Alpine Linux bastions to automated CI/CD pipelines, these are the architectural standards of the Digital Homestead.

Up next

Zone Defense: How I Built a Zone‑Based Firewall That Actually Secures a Smart Home

In my last post I introduced five principles I consider non-negotiable for a well-run smart home. Today I'm going deep on principle 02: Security. Most home network security advice stops at "use a stro